summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 08:06:26 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 08:06:26 +0000
commit1660d4b7a65d9ad2ce0deaa19d35579ca4084ac5 (patch)
tree6cf8220b628ebd2ccfc1375dd6516c6996e9abcc
parentInitial commit. (diff)
downloadcryptsetup-1660d4b7a65d9ad2ce0deaa19d35579ca4084ac5.tar.xz
cryptsetup-1660d4b7a65d9ad2ce0deaa19d35579ca4084ac5.zip
Adding upstream version 2:2.6.1.upstream/2%2.6.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rwxr-xr-x.github/workflows/cibuild-setup-ubuntu.sh29
-rwxr-xr-x.github/workflows/cibuild.sh38
-rw-r--r--.github/workflows/cibuild.yml30
-rw-r--r--.github/workflows/coverity.yml48
-rw-r--r--.gitignore61
-rw-r--r--.gitlab-ci.yml23
-rw-r--r--.gitlab/ci/alpinelinux.yml55
-rw-r--r--.gitlab/ci/annocheck.yml19
-rw-r--r--.gitlab/ci/centos.yml59
-rwxr-xr-x.gitlab/ci/cibuild-setup-ubuntu.sh50
-rw-r--r--.gitlab/ci/cifuzz.yml46
-rwxr-xr-x.gitlab/ci/clang-Wall49
-rw-r--r--.gitlab/ci/compilation-clang.gitlab-ci.yml27
-rw-r--r--.gitlab/ci/compilation-gcc.gitlab-ci.yml27
-rw-r--r--.gitlab/ci/compilation-various-disables.yml21
-rw-r--r--.gitlab/ci/csmock.yml17
-rw-r--r--.gitlab/ci/debian.yml56
-rw-r--r--.gitlab/ci/fedora.yml60
-rwxr-xr-x.gitlab/ci/gcc-Wall57
-rw-r--r--.gitlab/ci/gitlab-shared-docker.yml31
-rw-r--r--.gitlab/ci/rhel.yml106
-rw-r--r--.gitlab/ci/ubuntu-32bit.yml41
-rw-r--r--.gitlab/issue_templates/Bug.md15
-rw-r--r--.gitlab/issue_templates/Documentation.md5
-rw-r--r--.gitlab/issue_templates/Feature.md5
-rw-r--r--.lgtm.yml11
-rw-r--r--AUTHORS4
-rw-r--r--COPYING354
-rw-r--r--COPYING.LGPL517
-rw-r--r--FAQ.md3159
-rw-r--r--Makefile.am77
-rw-r--r--README.md148
-rw-r--r--SECURITY.md10
-rwxr-xr-xautogen.sh82
-rw-r--r--configure.ac773
-rw-r--r--docs/ChangeLog.old887
-rw-r--r--docs/Keyring.txt56
-rw-r--r--docs/LUKS2-locking.txt61
-rw-r--r--docs/doxyfile335
-rw-r--r--docs/doxygen_index.h110
-rw-r--r--docs/examples/Makefile17
-rw-r--r--docs/examples/crypt_log_usage.c94
-rw-r--r--docs/examples/crypt_luks_usage.c250
-rw-r--r--docs/on-disk-format-luks2.pdfbin0 -> 382277 bytes
-rw-r--r--docs/on-disk-format.pdfbin0 -> 119729 bytes
-rw-r--r--docs/v1.0.7-ReleaseNotes92
-rw-r--r--docs/v1.1.0-ReleaseNotes110
-rw-r--r--docs/v1.1.1-ReleaseNotes47
-rw-r--r--docs/v1.1.2-ReleaseNotes33
-rw-r--r--docs/v1.1.3-ReleaseNotes13
-rw-r--r--docs/v1.2.0-ReleaseNotes126
-rw-r--r--docs/v1.3.0-ReleaseNotes101
-rw-r--r--docs/v1.3.1-ReleaseNotes14
-rw-r--r--docs/v1.4.0-ReleaseNotes131
-rw-r--r--docs/v1.4.1-ReleaseNotes25
-rw-r--r--docs/v1.4.2-ReleaseNotes44
-rw-r--r--docs/v1.4.3-ReleaseNotes62
-rw-r--r--docs/v1.5.0-ReleaseNotes241
-rw-r--r--docs/v1.5.1-ReleaseNotes32
-rw-r--r--docs/v1.6.0-ReleaseNotes261
-rw-r--r--docs/v1.6.1-ReleaseNotes32
-rw-r--r--docs/v1.6.2-ReleaseNotes25
-rw-r--r--docs/v1.6.3-ReleaseNotes50
-rw-r--r--docs/v1.6.4-ReleaseNotes57
-rw-r--r--docs/v1.6.5-ReleaseNotes54
-rw-r--r--docs/v1.6.6-ReleaseNotes29
-rw-r--r--docs/v1.6.7-ReleaseNotes84
-rw-r--r--docs/v1.6.8-ReleaseNotes47
-rw-r--r--docs/v1.7.0-ReleaseNotes81
-rw-r--r--docs/v1.7.1-ReleaseNotes36
-rw-r--r--docs/v1.7.2-ReleaseNotes37
-rw-r--r--docs/v1.7.3-ReleaseNotes20
-rw-r--r--docs/v1.7.4-ReleaseNotes22
-rw-r--r--docs/v1.7.5-ReleaseNotes22
-rw-r--r--docs/v2.0.0-ReleaseNotes605
-rw-r--r--docs/v2.0.1-ReleaseNotes109
-rw-r--r--docs/v2.0.2-ReleaseNotes93
-rw-r--r--docs/v2.0.3-ReleaseNotes121
-rw-r--r--docs/v2.0.4-ReleaseNotes119
-rw-r--r--docs/v2.0.5-ReleaseNotes102
-rw-r--r--docs/v2.0.6-ReleaseNotes97
-rw-r--r--docs/v2.1.0-ReleaseNotes210
-rw-r--r--docs/v2.2.0-ReleaseNotes279
-rw-r--r--docs/v2.2.1-ReleaseNotes36
-rw-r--r--docs/v2.2.2-ReleaseNotes56
-rw-r--r--docs/v2.3.0-ReleaseNotes209
-rw-r--r--docs/v2.3.1-ReleaseNotes45
-rw-r--r--docs/v2.3.2-ReleaseNotes42
-rw-r--r--docs/v2.3.3-ReleaseNotes42
-rw-r--r--docs/v2.3.4-ReleaseNotes112
-rw-r--r--docs/v2.3.5-ReleaseNotes181
-rw-r--r--docs/v2.3.6-ReleaseNotes56
-rw-r--r--docs/v2.4.0-ReleaseNotes302
-rw-r--r--docs/v2.4.1-ReleaseNotes47
-rw-r--r--docs/v2.4.2-ReleaseNotes37
-rw-r--r--docs/v2.4.3-ReleaseNotes101
-rw-r--r--docs/v2.5.0-ReleaseNotes291
-rw-r--r--docs/v2.6.0-ReleaseNotes236
-rw-r--r--docs/v2.6.1-ReleaseNotes50
-rw-r--r--lib/Makemodule.am111
-rw-r--r--lib/bitlk/bitlk.c1460
-rw-r--r--lib/bitlk/bitlk.h148
-rw-r--r--lib/bitops.h123
-rw-r--r--lib/crypt_plain.c117
-rw-r--r--lib/crypto_backend/Makemodule.am41
-rw-r--r--lib/crypto_backend/argon2/LICENSE30
-rw-r--r--lib/crypto_backend/argon2/Makemodule.am30
-rw-r--r--lib/crypto_backend/argon2/README5
-rw-r--r--lib/crypto_backend/argon2/argon2.c458
-rw-r--r--lib/crypto_backend/argon2/argon2.h437
-rw-r--r--lib/crypto_backend/argon2/blake2/blake2-impl.h154
-rw-r--r--lib/crypto_backend/argon2/blake2/blake2.h89
-rw-r--r--lib/crypto_backend/argon2/blake2/blake2b.c392
-rw-r--r--lib/crypto_backend/argon2/blake2/blamka-round-opt.h471
-rw-r--r--lib/crypto_backend/argon2/blake2/blamka-round-ref.h56
-rw-r--r--lib/crypto_backend/argon2/core.c646
-rw-r--r--lib/crypto_backend/argon2/core.h228
-rw-r--r--lib/crypto_backend/argon2/encoding.c462
-rw-r--r--lib/crypto_backend/argon2/encoding.h57
-rw-r--r--lib/crypto_backend/argon2/opt.c283
-rw-r--r--lib/crypto_backend/argon2/ref.c194
-rw-r--r--lib/crypto_backend/argon2/thread.c49
-rw-r--r--lib/crypto_backend/argon2/thread.h62
-rw-r--r--lib/crypto_backend/argon2_generic.c79
-rw-r--r--lib/crypto_backend/base64.c276
-rw-r--r--lib/crypto_backend/cipher_check.c161
-rw-r--r--lib/crypto_backend/cipher_generic.c89
-rw-r--r--lib/crypto_backend/crc32.c183
-rw-r--r--lib/crypto_backend/crypto_backend.h161
-rw-r--r--lib/crypto_backend/crypto_backend_internal.h75
-rw-r--r--lib/crypto_backend/crypto_cipher_kernel.c351
-rw-r--r--lib/crypto_backend/crypto_gcrypt.c573
-rw-r--r--lib/crypto_backend/crypto_kernel.c428
-rw-r--r--lib/crypto_backend/crypto_nettle.c460
-rw-r--r--lib/crypto_backend/crypto_nss.c407
-rw-r--r--lib/crypto_backend/crypto_openssl.c849
-rw-r--r--lib/crypto_backend/crypto_storage.c347
-rw-r--r--lib/crypto_backend/pbkdf2_generic.c232
-rw-r--r--lib/crypto_backend/pbkdf_check.c443
-rw-r--r--lib/crypto_backend/utf8.c288
-rw-r--r--lib/fvault2/fvault2.c1057
-rw-r--r--lib/fvault2/fvault2.h80
-rw-r--r--lib/integrity/integrity.c402
-rw-r--r--lib/integrity/integrity.h101
-rw-r--r--lib/internal.h253
-rw-r--r--lib/keyslot_context.c488
-rw-r--r--lib/keyslot_context.h111
-rw-r--r--lib/libcryptsetup.h2881
-rw-r--r--lib/libcryptsetup.pc.in11
-rw-r--r--lib/libcryptsetup.sym167
-rw-r--r--lib/libcryptsetup_macros.h70
-rw-r--r--lib/libcryptsetup_symver.h103
-rw-r--r--lib/libdevmapper.c3181
-rw-r--r--lib/loopaes/loopaes.c253
-rw-r--r--lib/loopaes/loopaes.h46
-rw-r--r--lib/luks1/af.c170
-rw-r--r--lib/luks1/af.h67
-rw-r--r--lib/luks1/keyencryption.c268
-rw-r--r--lib/luks1/keymanage.c1300
-rw-r--r--lib/luks1/luks.h194
-rw-r--r--lib/luks2/luks2.h497
-rw-r--r--lib/luks2/luks2_digest.c455
-rw-r--r--lib/luks2/luks2_digest_pbkdf2.c210
-rw-r--r--lib/luks2/luks2_disk_metadata.c811
-rw-r--r--lib/luks2/luks2_internal.h388
-rw-r--r--lib/luks2/luks2_json_format.c411
-rw-r--r--lib/luks2/luks2_json_metadata.c2874
-rw-r--r--lib/luks2/luks2_keyslot.c977
-rw-r--r--lib/luks2/luks2_keyslot_luks2.c821
-rw-r--r--lib/luks2/luks2_keyslot_reenc.c752
-rw-r--r--lib/luks2/luks2_luks1_convert.c945
-rw-r--r--lib/luks2/luks2_reencrypt.c4375
-rw-r--r--lib/luks2/luks2_reencrypt_digest.c410
-rw-r--r--lib/luks2/luks2_segment.c426
-rw-r--r--lib/luks2/luks2_token.c1043
-rw-r--r--lib/luks2/luks2_token_keyring.c144
-rw-r--r--lib/nls.h34
-rw-r--r--lib/random.c244
-rw-r--r--lib/setup.c6564
-rw-r--r--lib/tcrypt/tcrypt.c1136
-rw-r--r--lib/tcrypt/tcrypt.h120
-rw-r--r--lib/utils.c334
-rw-r--r--lib/utils_benchmark.c218
-rw-r--r--lib/utils_blkid.c347
-rw-r--r--lib/utils_blkid.h69
-rw-r--r--lib/utils_crypt.c347
-rw-r--r--lib/utils_crypt.h54
-rw-r--r--lib/utils_device.c1089
-rw-r--r--lib/utils_device_locking.c520
-rw-r--r--lib/utils_device_locking.h49
-rw-r--r--lib/utils_devpath.c459
-rw-r--r--lib/utils_dm.h246
-rw-r--r--lib/utils_io.c299
-rw-r--r--lib/utils_io.h43
-rw-r--r--lib/utils_keyring.c237
-rw-r--r--lib/utils_keyring.h55
-rw-r--r--lib/utils_loop.c331
-rw-r--r--lib/utils_loop.h34
-rw-r--r--lib/utils_pbkdf.c333
-rw-r--r--lib/utils_safe_memory.c122
-rw-r--r--lib/utils_storage_wrappers.c394
-rw-r--r--lib/utils_storage_wrappers.h75
-rw-r--r--lib/utils_wipe.c311
-rw-r--r--lib/verity/rs.h63
-rw-r--r--lib/verity/rs_decode_char.c201
-rw-r--r--lib/verity/rs_encode_char.c173
-rw-r--r--lib/verity/verity.c416
-rw-r--r--lib/verity/verity.h87
-rw-r--r--lib/verity/verity_fec.c336
-rw-r--r--lib/verity/verity_hash.c444
-rw-r--r--lib/volumekey.c147
-rw-r--r--m4/ax_check_compile_flag.m453
-rw-r--r--man/Makemodule.am145
-rw-r--r--man/common_footer.adoc17
-rw-r--r--man/common_options.adoc1195
-rw-r--r--man/cryptsetup-benchmark.8.adoc41
-rw-r--r--man/cryptsetup-bitlkDump.8.adoc34
-rw-r--r--man/cryptsetup-close.8.adoc30
-rw-r--r--man/cryptsetup-config.8.adoc30
-rw-r--r--man/cryptsetup-convert.8.adoc37
-rw-r--r--man/cryptsetup-erase.8.adoc28
-rw-r--r--man/cryptsetup-fvault2Dump.8.adoc34
-rw-r--r--man/cryptsetup-isLuks.8.adoc29
-rw-r--r--man/cryptsetup-luksAddKey.8.adoc71
-rw-r--r--man/cryptsetup-luksChangeKey.8.adoc46
-rw-r--r--man/cryptsetup-luksConvertKey.8.adoc41
-rw-r--r--man/cryptsetup-luksDump.8.adoc50
-rw-r--r--man/cryptsetup-luksFormat.8.adoc51
-rw-r--r--man/cryptsetup-luksHeaderBackup.8.adoc35
-rw-r--r--man/cryptsetup-luksHeaderRestore.8.adoc34
-rw-r--r--man/cryptsetup-luksKillSlot.8.adoc40
-rw-r--r--man/cryptsetup-luksRemoveKey.8.adoc33
-rw-r--r--man/cryptsetup-luksResume.8.adoc29
-rw-r--r--man/cryptsetup-luksSuspend.8.adoc33
-rw-r--r--man/cryptsetup-luksUUID.8.adoc25
-rw-r--r--man/cryptsetup-open.8.adoc165
-rw-r--r--man/cryptsetup-reencrypt.8.adoc175
-rw-r--r--man/cryptsetup-refresh.8.adoc53
-rw-r--r--man/cryptsetup-repair.8.adoc43
-rw-r--r--man/cryptsetup-resize.8.adoc42
-rw-r--r--man/cryptsetup-ssh.8.adoc80
-rw-r--r--man/cryptsetup-status.8.adoc24
-rw-r--r--man/cryptsetup-tcryptDump.8.adoc37
-rw-r--r--man/cryptsetup-token.8.adoc55
-rw-r--r--man/cryptsetup.8.adoc729
-rw-r--r--man/integritysetup.8.adoc334
-rw-r--r--man/veritysetup.8.adoc311
-rw-r--r--misc/11-dm-crypt.rules17
-rw-r--r--misc/dict_search/Makefile17
-rw-r--r--misc/dict_search/README22
-rw-r--r--misc/dict_search/crypt_dict.c158
-rw-r--r--misc/fedora/cryptsetup.spec121
-rw-r--r--misc/keyslot_checker/Makefile14
-rw-r--r--misc/keyslot_checker/README120
-rw-r--r--misc/keyslot_checker/chk_luks_keyslots.c371
-rwxr-xr-xmisc/luks-header-from-active59
-rw-r--r--po/LINGUAS20
-rw-r--r--po/Makevars44
-rw-r--r--po/POTFILES.in56
-rw-r--r--po/cryptsetup.pot3895
-rw-r--r--po/cs.po4782
-rw-r--r--po/da.po3893
-rw-r--r--po/de.po4644
-rw-r--r--po/es.po4373
-rw-r--r--po/fi.po1933
-rw-r--r--po/fr.po4764
-rw-r--r--po/id.po815
-rw-r--r--po/it.po3193
-rw-r--r--po/ja.po3850
-rw-r--r--po/ka.po3756
-rw-r--r--po/nl.po4099
-rw-r--r--po/pl.po3851
-rw-r--r--po/pt_BR.po3217
-rw-r--r--po/ro.po3874
-rw-r--r--po/ru.po4964
-rw-r--r--po/sr.po4435
-rw-r--r--po/sv.po4527
-rw-r--r--po/uk.po4480
-rw-r--r--po/vi.po1958
-rw-r--r--po/zh_CN.po3075
-rw-r--r--scripts/Makemodule.am5
-rw-r--r--scripts/cryptsetup.conf.in1
-rw-r--r--src/Makemodule.am118
-rw-r--r--src/cryptsetup.c3603
-rw-r--r--src/cryptsetup.h177
-rw-r--r--src/cryptsetup_arg_list.h232
-rw-r--r--src/cryptsetup_args.h113
-rw-r--r--src/integritysetup.c767
-rw-r--r--src/integritysetup_arg_list.h100
-rw-r--r--src/integritysetup_args.h61
-rw-r--r--src/utils_arg_macros.h103
-rw-r--r--src/utils_arg_names.h173
-rw-r--r--src/utils_args.c131
-rw-r--r--src/utils_blockdev.c382
-rw-r--r--src/utils_luks.c274
-rw-r--r--src/utils_luks.h52
-rw-r--r--src/utils_password.c331
-rw-r--r--src/utils_progress.c301
-rw-r--r--src/utils_reencrypt.c1560
-rw-r--r--src/utils_reencrypt_luks1.c1354
-rw-r--r--src/utils_tools.c468
-rw-r--r--src/veritysetup.c680
-rw-r--r--src/veritysetup_arg_list.h70
-rw-r--r--src/veritysetup_args.h57
-rwxr-xr-xtests/00modules-test49
-rw-r--r--tests/Makefile.am206
-rw-r--r--tests/Makefile.localtest66
-rwxr-xr-xtests/align-test341
-rwxr-xr-xtests/align-test2449
-rw-r--r--tests/all-symbols-test.c177
-rw-r--r--tests/api-test-2.c5139
-rw-r--r--tests/api-test.c2411
-rw-r--r--tests/api_test.h165
-rwxr-xr-xtests/bitlk-compat-test200
-rw-r--r--tests/bitlk-images.tar.xzbin0 -> 293068 bytes
-rw-r--r--tests/blkid-luks2-pv.img.xzbin0 -> 5236 bytes
-rwxr-xr-xtests/blockwise-compat-test379
-rwxr-xr-xtests/compat-args-test299
-rwxr-xr-xtests/compat-test1137
-rwxr-xr-xtests/compat-test21204
-rw-r--r--tests/compatimage.img.xzbin0 -> 66716 bytes
-rw-r--r--tests/compatimage2.img.xzbin0 -> 66356 bytes
-rw-r--r--tests/compatv10image.img.xzbin0 -> 66688 bytes
-rw-r--r--tests/conversion_imgs.tar.xzbin0 -> 8135164 bytes
-rw-r--r--tests/crypto-vectors.c1559
-rw-r--r--tests/cryptsetup-valg-supps14
-rwxr-xr-xtests/device-test363
-rw-r--r--tests/differ.c166
-rwxr-xr-xtests/discards-test113
-rw-r--r--tests/evil_hdr-keyslot_overlap.xzbin0 -> 676 bytes
-rw-r--r--tests/evil_hdr-luks_hdr_damage.xzbin0 -> 612 bytes
-rw-r--r--tests/evil_hdr-payload_overwrite.xzbin0 -> 612 bytes
-rw-r--r--tests/evil_hdr-small_luks_device.xzbin0 -> 452 bytes
-rw-r--r--tests/evil_hdr-stripes_payload_dmg.xzbin0 -> 616 bytes
-rw-r--r--tests/fake_systemd_tpm_path.c17
-rw-r--r--tests/fake_token_path.c6
-rw-r--r--tests/fuzz/FuzzerInterface.h81
-rw-r--r--tests/fuzz/LUKS2.proto379
-rw-r--r--tests/fuzz/LUKS2_plain_JSON.proto190
-rw-r--r--tests/fuzz/Makefile.am122
-rw-r--r--tests/fuzz/README.md66
-rw-r--r--tests/fuzz/crypt2_load_fuzz.cc112
-rw-r--r--tests/fuzz/crypt2_load_fuzz.dict130
-rw-r--r--tests/fuzz/crypt2_load_ondisk_fuzz.cc64
-rw-r--r--tests/fuzz/crypt2_load_ondisk_fuzz.dict9
-rw-r--r--tests/fuzz/crypt2_load_proto_fuzz.cc51
-rw-r--r--tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc51
-rw-r--r--tests/fuzz/crypt2_load_proto_plain_json_fuzz.dict72
-rw-r--r--tests/fuzz/json_proto_converter.cc87
-rw-r--r--tests/fuzz/json_proto_converter.h43
-rwxr-xr-xtests/fuzz/oss-fuzz-build.sh152
-rw-r--r--tests/fuzz/plain_json_proto_to_luks2.cc75
-rw-r--r--tests/fuzz/plain_json_proto_to_luks2_converter.cc153
-rw-r--r--tests/fuzz/plain_json_proto_to_luks2_converter.h58
-rw-r--r--tests/fuzz/proto_to_luks2.cc75
-rw-r--r--tests/fuzz/proto_to_luks2_converter.cc604
-rw-r--r--tests/fuzz/proto_to_luks2_converter.h91
-rw-r--r--tests/fuzz/unpoison-mutated-buffers-from-libfuzzer.patch29
-rwxr-xr-xtests/fvault2-compat-test134
-rw-r--r--tests/fvault2-images.tar.xzbin0 -> 34200 bytes
-rwxr-xr-xtests/generate-symbols-list35
-rwxr-xr-xtests/generators/generate-luks2-area-in-json-hdr-space-json0.img.sh44
-rwxr-xr-xtests/generators/generate-luks2-argon2-leftover-params.img.sh42
-rwxr-xr-xtests/generators/generate-luks2-correct-full-json0.img.sh58
-rwxr-xr-xtests/generators/generate-luks2-corrupted-hdr0-with-correct-chks.img.sh42
-rwxr-xr-xtests/generators/generate-luks2-corrupted-hdr1-with-correct-chks.img.sh42
-rwxr-xr-xtests/generators/generate-luks2-invalid-checksum-both-hdrs.img.sh32
-rwxr-xr-xtests/generators/generate-luks2-invalid-checksum-hdr0.img.sh28
-rwxr-xr-xtests/generators/generate-luks2-invalid-checksum-hdr1.img.sh29
-rwxr-xr-xtests/generators/generate-luks2-invalid-json-size-c0.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-invalid-json-size-c1.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-invalid-json-size-c2.img.sh55
-rwxr-xr-xtests/generators/generate-luks2-invalid-keyslots-size-c0.img.sh43
-rwxr-xr-xtests/generators/generate-luks2-invalid-keyslots-size-c1.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-invalid-keyslots-size-c2.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-invalid-object-type-json0.img.sh41
-rwxr-xr-xtests/generators/generate-luks2-invalid-opening-char-json0.img.sh41
-rwxr-xr-xtests/generators/generate-luks2-invalid-tokens.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-invalid-top-objects.img.sh43
-rwxr-xr-xtests/generators/generate-luks2-keyslot-invalid-af.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-keyslot-invalid-area-size.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-keyslot-invalid-area.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-keyslot-invalid-objects.img.sh41
-rwxr-xr-xtests/generators/generate-luks2-keyslot-missing-digest.img.sh43
-rwxr-xr-xtests/generators/generate-luks2-keyslot-too-many-digests.img.sh41
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-128k-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-128k.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-16k-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-1m-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-1m.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-256k-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-256k.img.sh62
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-2m-secondary.img.sh63
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-2m.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-32k-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-32k.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-4m-secondary.img.sh63
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-4m.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-512k-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-512k.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-64k-inv-area-c0.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-64k-inv-area-c1.img.sh63
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-64k-inv-keyslots-size-c0.img.sh63
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-64k-secondary.img.sh64
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-64k.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh63
-rwxr-xr-xtests/generators/generate-luks2-metadata-size-invalid.img.sh61
-rwxr-xr-xtests/generators/generate-luks2-missing-keyslot-referenced-in-digest.img.sh45
-rwxr-xr-xtests/generators/generate-luks2-missing-keyslot-referenced-in-token.img.sh43
-rwxr-xr-xtests/generators/generate-luks2-missing-segment-referenced-in-digest.img.sh45
-rwxr-xr-xtests/generators/generate-luks2-missing-trailing-null-byte-json0.img.sh60
-rwxr-xr-xtests/generators/generate-luks2-non-null-byte-beyond-json0.img.sh43
-rwxr-xr-xtests/generators/generate-luks2-non-null-bytes-beyond-json0.img.sh47
-rwxr-xr-xtests/generators/generate-luks2-overlapping-areas-c0-json0.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-overlapping-areas-c1-json0.img.sh42
-rwxr-xr-xtests/generators/generate-luks2-overlapping-areas-c2-json0.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-pbkdf2-leftover-params-0.img.sh42
-rwxr-xr-xtests/generators/generate-luks2-pbkdf2-leftover-params-1.img.sh42
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-empty-encryption.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-missing-encryption.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-missing-ivoffset.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-missing-sectorsize.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-wrong-encryption.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-wrong-ivoffset.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-wrong-sectorsize-0.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-wrong-sectorsize-1.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-crypt-wrong-sectorsize-2.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-missing-offset.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-missing-size.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-missing-type.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-two.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-unknown-type.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-flags-element.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-flags.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-offset.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-size-0.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-size-1.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-size-2.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-segment-wrong-type.img.sh39
-rwxr-xr-xtests/generators/generate-luks2-uint64-max-segment-size.img.sh40
-rwxr-xr-xtests/generators/generate-luks2-uint64-overflow-segment-size.img.sh38
-rwxr-xr-xtests/generators/generate-luks2-uint64-signed-segment-size.img.sh39
-rw-r--r--tests/generators/lib.sh283
-rw-r--r--tests/img_fs_ext4.img.xzbin0 -> 5680 bytes
-rw-r--r--tests/img_fs_vfat.img.xzbin0 -> 6124 bytes
-rw-r--r--tests/img_fs_xfs.img.xzbin0 -> 7676 bytes
-rwxr-xr-xtests/integrity-compat-test651
-rwxr-xr-xtests/keyring-compat-test234
-rwxr-xr-xtests/keyring-test238
-rwxr-xr-xtests/loopaes-test192
-rwxr-xr-xtests/luks1-compat-test124
-rw-r--r--tests/luks1-images.tar.xzbin0 -> 67192 bytes
-rwxr-xr-xtests/luks2-integrity-test203
-rwxr-xr-xtests/luks2-reencryption-mangle-test548
-rwxr-xr-xtests/luks2-reencryption-test2207
-rwxr-xr-xtests/luks2-validation-test249
-rw-r--r--tests/luks2_header_requirements.tar.xzbin0 -> 134412 bytes
-rw-r--r--tests/luks2_keyslot_unassigned.img.xzbin0 -> 270548 bytes
-rw-r--r--tests/luks2_mda_images.tar.xzbin0 -> 156028 bytes
-rw-r--r--tests/luks2_valid_hdr.img.xzbin0 -> 3684 bytes
-rwxr-xr-xtests/mode-test187
-rwxr-xr-xtests/password-hash-test213
-rwxr-xr-xtests/reencryption-compat-test489
-rwxr-xr-xtests/run-all-symbols21
-rwxr-xr-xtests/ssh-test-plugin204
-rwxr-xr-xtests/systemd-test-plugin150
-rwxr-xr-xtests/tcrypt-compat-test223
-rw-r--r--tests/tcrypt-images.tar.xzbin0 -> 308700 bytes
-rw-r--r--tests/test_utils.c950
-rw-r--r--tests/unit-utils-crypt.c259
-rw-r--r--tests/unit-utils-io.c352
-rwxr-xr-xtests/unit-wipe-test170
-rw-r--r--tests/unit-wipe.c138
-rwxr-xr-xtests/valg-api.sh11
-rwxr-xr-xtests/valg.sh11
-rw-r--r--tests/valid_header_file.xzbin0 -> 608 bytes
-rwxr-xr-xtests/verity-compat-test559
-rw-r--r--tests/xfs_512_block_size.img.xzbin0 -> 6284 bytes
-rw-r--r--tokens/Makemodule.am29
-rw-r--r--tokens/libcryptsetup-token.sym9
-rw-r--r--tokens/ssh/cryptsetup-ssh.c420
-rw-r--r--tokens/ssh/libcryptsetup-token-ssh.c193
-rw-r--r--tokens/ssh/ssh-utils.c177
-rw-r--r--tokens/ssh/ssh-utils.h29
486 files changed, 193230 insertions, 0 deletions
diff --git a/.github/workflows/cibuild-setup-ubuntu.sh b/.github/workflows/cibuild-setup-ubuntu.sh
new file mode 100755
index 0000000..2c0adb2
--- /dev/null
+++ b/.github/workflows/cibuild-setup-ubuntu.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -ex
+
+PACKAGES=(
+ git make autoconf automake autopoint pkg-config libtool libtool-bin
+ gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol-dev
+ libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev libpwquality-dev
+ sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass
+ asciidoctor
+)
+
+COMPILER="${COMPILER:?}"
+COMPILER_VERSION="${COMPILER_VERSION:?}"
+RELEASE="$(lsb_release -cs)"
+
+bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list"
+
+# Latest gcc stack deb packages provided by
+# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
+add-apt-repository -y ppa:ubuntu-toolchain-r/test
+PACKAGES+=(gcc-$COMPILER_VERSION)
+
+# scsi_debug, gost crypto
+PACKAGES+=(dkms linux-headers-$(uname -r) linux-modules-extra-$(uname -r) gost-crypto-dkms)
+
+apt-get -y update --fix-missing
+apt-get -y install "${PACKAGES[@]}"
+apt-get -y build-dep cryptsetup
diff --git a/.github/workflows/cibuild.sh b/.github/workflows/cibuild.sh
new file mode 100755
index 0000000..55ddd17
--- /dev/null
+++ b/.github/workflows/cibuild.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+PHASES=(${@:-CONFIGURE MAKE CHECK})
+COMPILER="${COMPILER:?}"
+COMPILER_VERSION="${COMPILER_VERSION}"
+CFLAGS=(-O1 -g)
+CXXFLAGS=(-O1 -g)
+
+CC="gcc${COMPILER_VERSION:+-$COMPILER_VERSION}"
+CXX="g++${COMPILER_VERSION:+-$COMPILER_VERSION}"
+
+set -ex
+
+for phase in "${PHASES[@]}"; do
+ case $phase in
+ CONFIGURE)
+ opts=(
+ --enable-libargon2
+ )
+
+ sudo -E git clean -xdf
+
+ ./autogen.sh
+ CC="$CC" CXX="$CXX" CFLAGS="${CFLAGS[@]}" CXXFLAGS="${CXXFLAGS[@]}" ./configure "${opts[@]}"
+ ;;
+ MAKE)
+ make -j
+ make -j -C tests check-programs
+ ;;
+ CHECK)
+ make check
+ ;;
+
+ *)
+ echo >&2 "Unknown phase '$phase'"
+ exit 1
+ esac
+done
diff --git a/.github/workflows/cibuild.yml b/.github/workflows/cibuild.yml
new file mode 100644
index 0000000..2698389
--- /dev/null
+++ b/.github/workflows/cibuild.yml
@@ -0,0 +1,30 @@
+name: Build test
+on:
+ push:
+ branches:
+ - 'main'
+ - 'wip-luks2'
+ - 'v2.3.x'
+ - 'v2.4.x'
+ paths-ignore:
+ - 'docs/**'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ if: github.repository == 'mbroz/cryptsetup'
+ strategy:
+ fail-fast: false
+ matrix:
+ env:
+ - { COMPILER: "gcc", COMPILER_VERSION: "11", RUN_SSH_PLUGIN_TEST: "1" }
+ env: ${{ matrix.env }}
+ steps:
+ - name: Repository checkout
+ uses: actions/checkout@v1
+ - name: Ubuntu setup
+ run: sudo -E .github/workflows/cibuild-setup-ubuntu.sh
+ - name: Configure & Make
+ run: .github/workflows/cibuild.sh CONFIGURE MAKE
+ - name: Check
+ run: sudo -E .github/workflows/cibuild.sh CHECK
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
new file mode 100644
index 0000000..edc88e8
--- /dev/null
+++ b/.github/workflows/coverity.yml
@@ -0,0 +1,48 @@
+name: Coverity test
+on:
+ push:
+ branches:
+ - 'coverity_scan'
+ paths-ignore:
+ - 'docs/**'
+
+jobs:
+ latest:
+ runs-on: ubuntu-latest
+ if: github.repository == 'mbroz/cryptsetup'
+ steps:
+ - name: Repository checkout
+ uses: actions/checkout@v1
+ - name: Ubuntu setup
+ run: sudo -E .github/workflows/cibuild-setup-ubuntu.sh
+ env:
+ COMPILER: "gcc"
+ COMPILER_VERSION: "11"
+ - name: Install Coverity
+ run: |
+ wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=mbroz/cryptsetup" -O cov-analysis-linux64.tar.gz
+ mkdir cov-analysis-linux64
+ tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
+ env:
+ TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
+ - name: Run autoconf & configure
+ run: |
+ ./autogen.sh
+ ./configure
+ - name: Run cov-build
+ run: |
+ export PATH=`pwd`/cov-analysis-linux64/bin:$PATH
+ cov-build --dir cov-int make
+ - name: Submit to Coverity Scan
+ run: |
+ tar czvf cryptsetup.tgz cov-int
+ curl \
+ --form project=mbroz/cryptsetup \
+ --form token=$TOKEN \
+ --form email=gmazyland@gmail.com \
+ --form file=@cryptsetup.tgz \
+ --form version=trunk \
+ --form description="`./cryptsetup --version`" \
+ https://scan.coverity.com/builds?project=mbroz/cryptsetup
+ env:
+ TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..41715d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,61 @@
+po/*gmo
+*~
+Makefile
+Makefile.in
+Makefile.in.in
+*.lo
+*.la
+*.o
+*.so
+*.8
+**/*.dirstamp
+.deps/
+.libs/
+src/cryptsetup
+src/veritysetup
+ABOUT-NLS
+aclocal.m4
+autom4te.cache/
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.rpath
+config.status
+config.sub
+configure
+cryptsetup
+cryptsetup-reencrypt
+cryptsetup-ssh
+depcomp
+install-sh
+integritysetup
+lib/libcryptsetup.pc
+libtool
+ltmain.sh
+m4/
+missing
+po/Makevars.template
+po/POTFILES
+po/Rules-quot
+po/*.header
+po/*.sed
+po/*.sin
+po/stamp-po
+scripts/cryptsetup.conf
+stamp-h1
+veritysetup
+tests/valglog.*
+*/*.dirstamp
+*-debug-luks2-backup*
+tests/api-test
+tests/api-test-2
+tests/differ
+tests/luks1-images
+tests/tcrypt-images
+tests/unit-utils-io
+tests/vectors-test
+tests/test-symbols-list.h
+tests/all-symbols-test
+tests/fuzz/LUKS2.pb*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..3153145
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,23 @@
+stages:
+ - test
+
+.dump_kernel_log:
+ after_script:
+ - sudo dmesg > /mnt/artifacts/dmesg.log
+ - sudo journalctl > /mnt/artifacts/journalctl.log
+ - '[ "$(ls -A /var/coredumps)" ] && exit 1 || true'
+
+include:
+ - local: .gitlab/ci/debian.yml
+ - local: .gitlab/ci/fedora.yml
+ - local: .gitlab/ci/rhel.yml
+ - local: .gitlab/ci/centos.yml
+ - local: .gitlab/ci/annocheck.yml
+ - local: .gitlab/ci/csmock.yml
+ - local: .gitlab/ci/gitlab-shared-docker.yml
+ - local: .gitlab/ci/compilation-various-disables.yml
+ - local: .gitlab/ci/compilation-gcc.gitlab-ci.yml
+ - local: .gitlab/ci/compilation-clang.gitlab-ci.yml
+ - local: .gitlab/ci/alpinelinux.yml
+ - local: .gitlab/ci/ubuntu-32bit.yml
+ - local: .gitlab/ci/cifuzz.yml
diff --git a/.gitlab/ci/alpinelinux.yml b/.gitlab/ci/alpinelinux.yml
new file mode 100644
index 0000000..81bd6cb
--- /dev/null
+++ b/.gitlab/ci/alpinelinux.yml
@@ -0,0 +1,55 @@
+.alpinelinux-dependencies:
+ after_script:
+ - sudo dmesg > /mnt/artifacts/dmesg.log
+ - sudo cp /var/log/messages /mnt/artifacts/
+ - '[ "$(ls -A /var/coredumps)" ] && exit 1 || true'
+ before_script:
+ - >
+ sudo apk add
+ lvm2-dev openssl1.1-compat-dev popt-dev util-linux-dev json-c-dev
+ argon2-dev device-mapper which sharutils gettext gettext-dev automake
+ autoconf libtool build-base keyutils tar jq expect git asciidoctor
+ - ./autogen.sh
+ - ./configure --prefix=/usr --libdir=/lib --sbindir=/sbin --disable-static --enable-libargon2 --with-crypto_backend=openssl --disable-external-tokens --disable-ssh-token --enable-asciidoc
+
+test-main-commit-job-alpinelinux:
+ extends:
+ - .alpinelinux-dependencies
+ tags:
+ - libvirt
+ - alpinelinux
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "0"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-mergerq-job-alpinelinux:
+ extends:
+ - .alpinelinux-dependencies
+ tags:
+ - libvirt
+ - alpinelinux
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "0"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
diff --git a/.gitlab/ci/annocheck.yml b/.gitlab/ci/annocheck.yml
new file mode 100644
index 0000000..5b3a715
--- /dev/null
+++ b/.gitlab/ci/annocheck.yml
@@ -0,0 +1,19 @@
+test-main-commit-job-annocheck:
+ extends:
+ - .dump_kernel_log
+ tags:
+ - libvirt
+ - rhel9-annocheck
+ stage: test
+ interruptible: true
+ allow_failure: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - /opt/build-rpm-script.sh > /dev/null 2>&1
+ - annocheck /var/lib/mock/rhel-9.0.0-candidate-x86_64/result/*.rpm --profile=el9
+ - annocheck /var/lib/mock/rhel-9.0.0-candidate-x86_64/result/*.rpm --profile=el8
diff --git a/.gitlab/ci/centos.yml b/.gitlab/ci/centos.yml
new file mode 100644
index 0000000..6f5559c
--- /dev/null
+++ b/.gitlab/ci/centos.yml
@@ -0,0 +1,59 @@
+.centos-openssl-backend:
+ extends:
+ - .dump_kernel_log
+ before_script:
+ - >
+ sudo dnf -y -q install
+ autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
+ libblkid-devel libpwquality-devel libselinux-devel libssh-devel libtool
+ libuuid-devel make popt-devel libsepol-devel nc openssh-clients passwd
+ pkgconfig sharutils sshpass tar uuid-devel vim-common device-mapper
+ expect gettext git jq keyutils openssl-devel openssl gem
+ - sudo gem install asciidoctor
+ - sudo -E git clean -xdf
+ - ./autogen.sh
+ - ./configure --enable-fips --enable-pwquality --with-crypto_backend=openssl --enable-asciidoc
+
+# non-FIPS jobs
+
+test-main-commit-centos-stream9:
+ extends:
+ - .centos-openssl-backend
+ tags:
+ - libvirt
+ - centos-stream9
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-mergerq-centos-stream9:
+ extends:
+ - .centos-openssl-backend
+ tags:
+ - libvirt
+ - centos-stream9
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
diff --git a/.gitlab/ci/cibuild-setup-ubuntu.sh b/.gitlab/ci/cibuild-setup-ubuntu.sh
new file mode 100755
index 0000000..07b0990
--- /dev/null
+++ b/.gitlab/ci/cibuild-setup-ubuntu.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+set -ex
+
+PACKAGES=(
+ git make autoconf automake autopoint pkg-config libtool libtool-bin
+ gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol-dev
+ libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev libpwquality-dev
+ sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass
+ asciidoctor
+)
+
+COMPILER="${COMPILER:?}"
+COMPILER_VERSION="${COMPILER_VERSION:?}"
+
+grep -E '^deb' /etc/apt/sources.list > /etc/apt/sources.list~
+sed -Ei 's/^deb /deb-src /' /etc/apt/sources.list~
+cat /etc/apt/sources.list~ >> /etc/apt/sources.list
+
+apt-get -y update --fix-missing
+DEBIAN_FRONTEND=noninteractive apt-get -yq install software-properties-common wget lsb-release
+RELEASE="$(lsb_release -cs)"
+
+if [[ $COMPILER == "gcc" ]]; then
+ # Latest gcc stack deb packages provided by
+ # https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
+ add-apt-repository -y ppa:ubuntu-toolchain-r/test
+ PACKAGES+=(gcc-$COMPILER_VERSION)
+elif [[ $COMPILER == "clang" ]]; then
+ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+ add-apt-repository "deb http://apt.llvm.org/${RELEASE}/ llvm-toolchain-${RELEASE}-${COMPILER_VERSION} main"
+
+ # scan-build
+ PACKAGES+=(clang-tools-$COMPILER_VERSION clang-$COMPILER_VERSION lldb-$COMPILER_VERSION lld-$COMPILER_VERSION clangd-$COMPILER_VERSION)
+ PACKAGES+=(perl)
+else
+ exit 1
+fi
+
+apt-get -y update --fix-missing
+DEBIAN_FRONTEND=noninteractive apt-get -yq install "${PACKAGES[@]}"
+apt-get -y build-dep cryptsetup
+
+echo "====================== VERSIONS ==================="
+if [[ $COMPILER == "clang" ]]; then
+ echo "Using scan-build${COMPILER_VERSION:+-$COMPILER_VERSION}"
+fi
+
+${COMPILER}-$COMPILER_VERSION -v
+echo "====================== END VERSIONS ==================="
diff --git a/.gitlab/ci/cifuzz.yml b/.gitlab/ci/cifuzz.yml
new file mode 100644
index 0000000..063b912
--- /dev/null
+++ b/.gitlab/ci/cifuzz.yml
@@ -0,0 +1,46 @@
+cifuzz:
+ variables:
+ OSS_FUZZ_PROJECT_NAME: cryptsetup
+ CFL_PLATFORM: gitlab
+ CIFUZZ_DEBUG: "True"
+ FUZZ_SECONDS: 300 # 5 minutes per fuzzer
+ ARCHITECTURE: "x86_64"
+ DRY_RUN: "False"
+ LOW_DISK_SPACE: "True"
+ BAD_BUILD_CHECK: "True"
+ LANGUAGE: "c"
+ DOCKER_HOST: "tcp://docker:2375"
+ DOCKER_IN_DOCKER: "true"
+ DOCKER_DRIVER: overlay2
+ DOCKER_TLS_CERTDIR: ""
+ image:
+ name: gcr.io/oss-fuzz-base/cifuzz-base
+ entrypoint: [""]
+ services:
+ - docker:dind
+
+ stage: test
+ parallel:
+ matrix:
+ - SANITIZER: [address, undefined, memory]
+ rules:
+ # Default code change.
+ # - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ # variables:
+ # MODE: "code-change"
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $BUILD_AND_RUN_FUZZERS != null
+ before_script:
+ # Get gitlab's container id.
+ - export CFL_CONTAINER_ID=`cut -c9- < /proc/1/cpuset`
+ script:
+ # Will build and run the fuzzers.
+ # We use a hack to override CI_JOB_ID, because otherwise a bad path is used
+ # in GitLab CI environment
+ - CI_JOB_ID="$CI_PROJECT_NAMESPACE/$CI_PROJECT_TITLE" python3 "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py"
+ artifacts:
+ # Upload artifacts when a crash makes the job fail.
+ when: always
+ paths:
+ - artifacts/
diff --git a/.gitlab/ci/clang-Wall b/.gitlab/ci/clang-Wall
new file mode 100755
index 0000000..d09e154
--- /dev/null
+++ b/.gitlab/ci/clang-Wall
@@ -0,0 +1,49 @@
+#!/bin/bash
+# clang -Wall plus other important warnings not included in -Wall
+
+for arg in "$@"
+do
+ case $arg in
+ -O*) Wuninitialized=-Wuninitialized;; # only makes sense with `-O'
+ esac
+done
+
+CLANG="clang${COMPILER_VERSION:+-$COMPILER_VERSION}"
+
+#PEDANTIC="-std=gnu99"
+#PEDANTIC="-pedantic -std=gnu99"
+#PEDANTIC="-pedantic -std=gnu99 -Wno-variadic-macros"
+#CONVERSION="-Wconversion"
+
+EXTRA="\
+ -Wextra \
+ -Wsign-compare \
+ -Wcast-align
+ -Werror-implicit-function-declaration \
+ -Wpointer-arith \
+ -Wwrite-strings \
+ -Wswitch \
+ -Wmissing-format-attribute \
+ -Winit-self \
+ -Wdeclaration-after-statement \
+ -Wold-style-definition \
+ -Wno-missing-field-initializers \
+ -Wno-unused-parameter \
+ -Wno-long-long"
+
+exec $CLANG $PEDANTIC $CONVERSION \
+ -Wall $Wuninitialized \
+ -Wno-switch \
+ -Wdisabled-optimization \
+ -Wwrite-strings \
+ -Wpointer-arith \
+ -Wbad-function-cast \
+ -Wmissing-prototypes \
+ -Wmissing-declarations \
+ -Wstrict-prototypes \
+ -Wnested-externs \
+ -Wcomment \
+ -Winline \
+ -Wcast-qual \
+ -Wredundant-decls $EXTRA \
+ "$@"
diff --git a/.gitlab/ci/compilation-clang.gitlab-ci.yml b/.gitlab/ci/compilation-clang.gitlab-ci.yml
new file mode 100644
index 0000000..6f5cd42
--- /dev/null
+++ b/.gitlab/ci/compilation-clang.gitlab-ci.yml
@@ -0,0 +1,27 @@
+test-clang-compilation:
+ extends:
+ - .gitlab-shared-clang
+ script:
+ - export CFLAGS="-Wall -Werror"
+ - ./configure
+ - make -j
+ - make -j check-programs
+
+test-clang-Wall-script:
+ extends:
+ - .gitlab-shared-clang
+ script:
+ - export CFLAGS="-g -O0"
+ - export CC="$CI_PROJECT_DIR/.gitlab/ci/clang-Wall"
+ - ./configure
+ - make -j CFLAGS="-g -O0 -Werror"
+ - make -j CFLAGS="-g -O0 -Werror" check-programs
+
+test-scan-build:
+ extends:
+ - .gitlab-shared-clang
+ script:
+ - scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} -V ./configure CFLAGS="-g -O0"
+ - make clean
+ - scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} --status-bugs -maxloop 10 make -j
+ - scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} --status-bugs -maxloop 10 make -j check-programs
diff --git a/.gitlab/ci/compilation-gcc.gitlab-ci.yml b/.gitlab/ci/compilation-gcc.gitlab-ci.yml
new file mode 100644
index 0000000..00fae36
--- /dev/null
+++ b/.gitlab/ci/compilation-gcc.gitlab-ci.yml
@@ -0,0 +1,27 @@
+test-gcc-compilation:
+ extends:
+ - .gitlab-shared-gcc
+ script:
+ - export CFLAGS="-Wall -Werror"
+ - ./configure
+ - make -j
+ - make -j check-programs
+
+test-gcc-Wall-script:
+ extends:
+ - .gitlab-shared-gcc
+ script:
+ - export CFLAGS="-g -O0"
+ - export CC="$CI_PROJECT_DIR/.gitlab/ci/gcc-Wall"
+ - ./configure
+ - make -j CFLAGS="-g -O0 -Werror"
+ - make -j CFLAGS="-g -O0 -Werror" check-programs
+
+test-gcc-fanalyzer:
+ extends:
+ - .gitlab-shared-gcc
+ script:
+ - export CFLAGS="-Wall -Werror -g -O0 -fanalyzer -fdiagnostics-path-format=separate-events"
+ - ./configure
+ - make -j
+ - make -j check-programs
diff --git a/.gitlab/ci/compilation-various-disables.yml b/.gitlab/ci/compilation-various-disables.yml
new file mode 100644
index 0000000..1414f9e
--- /dev/null
+++ b/.gitlab/ci/compilation-various-disables.yml
@@ -0,0 +1,21 @@
+test-gcc-disable-compiles:
+ extends:
+ - .gitlab-shared-gcc
+ parallel:
+ matrix:
+ - DISABLE_FLAGS: [
+ "--disable-keyring",
+ "--disable-external-tokens --disable-ssh-token",
+ "--disable-luks2-reencryption",
+ "--disable-cryptsetup --disable-veritysetup --disable-integritysetup",
+ "--disable-kernel_crypto",
+ "--disable-selinux",
+ "--disable-udev",
+ "--disable-internal-argon2",
+ "--disable-blkid"
+ ]
+ script:
+ - export CFLAGS="-Wall -Werror"
+ - ./configure $DISABLE_FLAGS
+ - make -j
+ - make -j check-programs
diff --git a/.gitlab/ci/csmock.yml b/.gitlab/ci/csmock.yml
new file mode 100644
index 0000000..72b53ed
--- /dev/null
+++ b/.gitlab/ci/csmock.yml
@@ -0,0 +1,17 @@
+test-commit-job-csmock:
+ extends:
+ - .dump_kernel_log
+ tags:
+ - libvirt
+ - rhel7-csmock
+ stage: test
+ interruptible: true
+ allow_failure: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/ || $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - /opt/csmock-run-script.sh
diff --git a/.gitlab/ci/debian.yml b/.gitlab/ci/debian.yml
new file mode 100644
index 0000000..fad9d97
--- /dev/null
+++ b/.gitlab/ci/debian.yml
@@ -0,0 +1,56 @@
+.debian-prep:
+ extends:
+ - .dump_kernel_log
+ before_script:
+ - >
+ [ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] ||
+ sudo apt-get -y install -y -qq swtpm meson ninja-build python3-jinja2
+ gperf libcap-dev tpm2-tss-engine-dev libmount-dev swtpm-tools
+ - >
+ sudo apt-get -y install -y -qq git gcc make autoconf automake autopoint
+ pkgconf libtool libtool-bin gettext libssl-dev libdevmapper-dev
+ libpopt-dev uuid-dev libsepol-dev libjson-c-dev libssh-dev libblkid-dev
+ tar libargon2-0-dev libpwquality-dev sharutils dmsetup jq xxd expect
+ keyutils netcat passwd openssh-client sshpass asciidoctor
+ - sudo apt-get -y build-dep cryptsetup
+ - sudo -E git clean -xdf
+ - ./autogen.sh
+ - ./configure --enable-libargon2 --enable-asciidoc
+
+test-mergerq-job-debian:
+ extends:
+ - .debian-prep
+ tags:
+ - libvirt
+ - debian11
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-main-commit-job-debian:
+ extends:
+ - .debian-prep
+ tags:
+ - libvirt
+ - debian11
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
diff --git a/.gitlab/ci/fedora.yml b/.gitlab/ci/fedora.yml
new file mode 100644
index 0000000..7fd9c7e
--- /dev/null
+++ b/.gitlab/ci/fedora.yml
@@ -0,0 +1,60 @@
+.dnf-openssl-backend:
+ extends:
+ - .dump_kernel_log
+ before_script:
+ - >
+ [ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] ||
+ sudo dnf -y -q install
+ swtpm meson ninja-build python3-jinja2 gperf libcap-devel tpm2-tss-devel
+ libmount-devel swtpm-tools
+ - >
+ sudo dnf -y -q install
+ autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
+ libargon2-devel libblkid-devel libpwquality-devel libselinux-devel
+ libssh-devel libtool libuuid-devel make popt-devel
+ libsepol-devel.x86_64 netcat openssh-clients passwd pkgconfig sharutils
+ sshpass tar uuid-devel vim-common device-mapper expect gettext git jq
+ keyutils openssl-devel openssl asciidoctor
+ - sudo -E git clean -xdf
+ - ./autogen.sh
+ - ./configure --enable-fips --enable-pwquality --enable-libargon2 --with-crypto_backend=openssl --enable-asciidoc
+
+test-main-commit-job-rawhide:
+ extends:
+ - .dnf-openssl-backend
+ tags:
+ - libvirt
+ - fedora-rawhide
+ stage: test
+ interruptible: true
+ allow_failure: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-mergerq-job-rawhide:
+ extends:
+ - .dnf-openssl-backend
+ tags:
+ - libvirt
+ - fedora-rawhide
+ stage: test
+ interruptible: true
+ allow_failure: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
diff --git a/.gitlab/ci/gcc-Wall b/.gitlab/ci/gcc-Wall
new file mode 100755
index 0000000..6669504
--- /dev/null
+++ b/.gitlab/ci/gcc-Wall
@@ -0,0 +1,57 @@
+#!/bin/bash
+# gcc -Wall plus other important warnings not included in -Wall
+
+for arg in "$@"
+do
+ case $arg in
+ -O*) Wuninitialized=-Wuninitialized;; # only makes sense with `-O'
+ esac
+done
+
+GCC="gcc${COMPILER_VERSION:+-$COMPILER_VERSION}"
+
+#PEDANTIC="-std=gnu99"
+#PEDANTIC="-pedantic -std=gnu99"
+#PEDANTIC="-pedantic -std=gnu99 -Wno-variadic-macros"
+#CONVERSION="-Wconversion"
+# -Wpacked \
+
+# This does more than expected for gcc (mixed code with declarations)
+# -Wdeclaration-after-statement \
+
+EXTRA="-Wextra \
+ -Wsign-compare \
+ -Werror-implicit-function-declaration \
+ -Wpointer-arith \
+ -Wwrite-strings \
+ -Wswitch \
+ -Wmissing-format-attribute \
+ -Wstrict-aliasing=3 \
+ -Winit-self \
+ -Wunsafe-loop-optimizations \
+ -Wold-style-definition \
+ -Wno-missing-field-initializers \
+ -Wno-unused-parameter \
+ -Wno-long-long \
+ -Wmaybe-uninitialized \
+ -Wvla \
+ -Wformat-overflow \
+ -Wformat-truncation"
+
+exec $GCC $PEDANTIC $CONVERSION \
+ -Wall $Wuninitialized \
+ -Wno-switch \
+ -Wdisabled-optimization \
+ -Wwrite-strings \
+ -Wpointer-arith \
+ -Wbad-function-cast \
+ -Wmissing-prototypes \
+ -Wmissing-declarations \
+ -Wstrict-prototypes \
+ -Wnested-externs \
+ -Wcomment \
+ -Winline \
+ -Wcast-align=strict \
+ -Wcast-qual \
+ -Wredundant-decls $EXTRA \
+ "$@"
diff --git a/.gitlab/ci/gitlab-shared-docker.yml b/.gitlab/ci/gitlab-shared-docker.yml
new file mode 100644
index 0000000..1edacc8
--- /dev/null
+++ b/.gitlab/ci/gitlab-shared-docker.yml
@@ -0,0 +1,31 @@
+.gitlab-shared-docker:
+ image: ubuntu:focal
+ tags:
+ - gitlab-org-docker
+ stage: test
+ interruptible: true
+ rules:
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ before_script:
+ - .gitlab/ci/cibuild-setup-ubuntu.sh
+ - export CC="${COMPILER}${COMPILER_VERSION:+-$COMPILER_VERSION}"
+ - export CXX="${COMPILER}++${COMPILER_VERSION:+-$COMPILER_VERSION}"
+ - ./autogen.sh
+
+.gitlab-shared-gcc:
+ extends:
+ - .gitlab-shared-docker
+ variables:
+ COMPILER: "gcc"
+ COMPILER_VERSION: "11"
+ RUN_SSH_PLUGIN_TEST: "1"
+
+.gitlab-shared-clang:
+ extends:
+ - .gitlab-shared-docker
+ variables:
+ COMPILER: "clang"
+ COMPILER_VERSION: "13"
+ RUN_SSH_PLUGIN_TEST: "1"
diff --git a/.gitlab/ci/rhel.yml b/.gitlab/ci/rhel.yml
new file mode 100644
index 0000000..f71533c
--- /dev/null
+++ b/.gitlab/ci/rhel.yml
@@ -0,0 +1,106 @@
+.rhel-openssl-backend:
+ extends:
+ - .dump_kernel_log
+ before_script:
+ - >
+ sudo yum -y -q install
+ autoconf automake device-mapper-devel gcc gettext-devel json-c-devel
+ libblkid-devel libpwquality-devel libselinux-devel libssh-devel libtool
+ libuuid-devel make popt-devel libsepol-devel nc openssh-clients passwd
+ pkgconfig sharutils sshpass tar uuid-devel vim-common device-mapper
+ expect gettext git jq keyutils openssl-devel openssl gem > /dev/null 2>&1
+ - sudo gem install asciidoctor
+ - sudo -E git clean -xdf
+ - ./autogen.sh
+ - ./configure --enable-fips --enable-pwquality --with-crypto_backend=openssl --enable-asciidoc
+
+# non-FIPS jobs
+
+test-main-commit-rhel8:
+ extends:
+ - .rhel-openssl-backend
+ tags:
+ - libvirt
+ - rhel8
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-main-commit-rhel9:
+ extends:
+ - .rhel-openssl-backend
+ tags:
+ - libvirt
+ - rhel9
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+# FIPS jobs
+
+test-main-commit-rhel8-fips:
+ extends:
+ - .rhel-openssl-backend
+ tags:
+ - libvirt
+ - rhel8-fips
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - fips-mode-setup --check || exit 1
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-main-commit-rhel9-fips:
+ extends:
+ - .rhel-openssl-backend
+ tags:
+ - libvirt
+ - rhel9-fips
+ stage: test
+ interruptible: true
+ allow_failure: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - fips-mode-setup --check || exit 1
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
diff --git a/.gitlab/ci/ubuntu-32bit.yml b/.gitlab/ci/ubuntu-32bit.yml
new file mode 100644
index 0000000..f51c059
--- /dev/null
+++ b/.gitlab/ci/ubuntu-32bit.yml
@@ -0,0 +1,41 @@
+test-mergerq-job-ubuntu-32bit:
+ extends:
+ - .debian-prep
+ tags:
+ - libvirt
+ - ubuntu-bionic-32bit
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
+
+test-main-commit-job-ubuntu-32bit:
+ extends:
+ - .debian-prep
+ tags:
+ - libvirt
+ - ubuntu-bionic-32bit
+ stage: test
+ interruptible: true
+ variables:
+ RUN_SSH_PLUGIN_TEST: "1"
+ rules:
+ - if: $RUN_SYSTEMD_PLUGIN_TEST != null
+ when: never
+ - if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
+ when: never
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
+ script:
+ - make -j
+ - make -j -C tests check-programs
+ - sudo -E make check
diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md
new file mode 100644
index 0000000..f8837aa
--- /dev/null
+++ b/.gitlab/issue_templates/Bug.md
@@ -0,0 +1,15 @@
+### Issue description
+<!-- Please, shortly describe the issue here. -->
+
+### Steps for reproducing the issue
+<!-- How it can be reproduced? Include all important steps. -->
+
+### Additional info
+<!-- Please mention what distribution you are using. -->
+
+### Debug log
+<!-- Paste a debug log of the failing command (add --debug option) between the markers below (to keep raw debug format).-->
+```
+Output with --debug option:
+
+```
diff --git a/.gitlab/issue_templates/Documentation.md b/.gitlab/issue_templates/Documentation.md
new file mode 100644
index 0000000..b4e47e2
--- /dev/null
+++ b/.gitlab/issue_templates/Documentation.md
@@ -0,0 +1,5 @@
+### Documentation issue
+<!-- Please, shortly describe the issue in documentation here. -->
+
+### Additional info
+<!-- Please mention what cryptsetup version you are using. -->
diff --git a/.gitlab/issue_templates/Feature.md b/.gitlab/issue_templates/Feature.md
new file mode 100644
index 0000000..fa94c8a
--- /dev/null
+++ b/.gitlab/issue_templates/Feature.md
@@ -0,0 +1,5 @@
+### New feature description
+<!-- Please, shortly describe the requested feature here. -->
+
+### Additional info
+<!-- Please mention what distribution and cryptsetup version you are using. -->
diff --git a/.lgtm.yml b/.lgtm.yml
new file mode 100644
index 0000000..64d9cc8
--- /dev/null
+++ b/.lgtm.yml
@@ -0,0 +1,11 @@
+queries:
+ - exclude: cpp/fixme-comment
+ - exclude: cpp/empty-block
+# symver attribute detection cannot be used, disable it for lgtm
+extraction:
+ cpp:
+ configure:
+ command:
+ - "./autogen.sh"
+ - "./configure --enable-external-tokens --enable-ssh-token"
+ - "echo \"#undef HAVE_ATTRIBUTE_SYMVER\" >> config.h"
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..f4e5175
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,4 @@
+Jana Saout <jana@saout.de>
+Clemens Fruhwirth <clemens@endorphin.org>
+Milan Broz <gmazyland@gmail.com>
+Ondrej Kozina <okozina@redhat.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..86289a1
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,354 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+
+-----
+In addition, as a special exception, the copyright holders give
+permission to link the code of portions of this program with the
+OpenSSL library under certain conditions as described in each
+individual source file, and distribute linked combinations
+including the two.
+
+You must obey the GNU General Public License in all respects
+for all of the code used other than OpenSSL. If you modify
+file(s) with this exception, you may extend this exception to your
+version of the file(s), but you are not obligated to do so. If you
+do not wish to do so, delete this exception statement from your
+version. If you delete this exception statement from all source
+files in the program, then also delete it here.
diff --git a/COPYING.LGPL b/COPYING.LGPL
new file mode 100644
index 0000000..7e354d5
--- /dev/null
+++ b/COPYING.LGPL
@@ -0,0 +1,517 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+-----
+In addition, as a special exception, the copyright holders give
+permission to link the code of portions of this program with the
+OpenSSL library under certain conditions as described in each
+individual source file, and distribute linked combinations
+including the two.
+
+You must obey the GNU Lesser General Public License in all respects
+for all of the code used other than OpenSSL. If you modify
+file(s) with this exception, you may extend this exception to your
+version of the file(s), but you are not obligated to do so. If you
+do not wish to do so, delete this exception statement from your
+version. If you delete this exception statement from all source
+files in the program, then also delete it here.
diff --git a/FAQ.md b/FAQ.md
new file mode 100644
index 0000000..74ad955
--- /dev/null
+++ b/FAQ.md
@@ -0,0 +1,3159 @@
+# Frequently Asked Questions Cryptsetup/LUKS
+
+# Sections
+[1. General Questions](#1-general-questions)
+[2. Setup](#2-setup)
+[3. Common Problems](#3-common-problems)
+[4. Troubleshooting](#4-troubleshooting)
+[5. Security Aspects](#5-security-aspects)
+[6. Backup and Data Recovery](#6-backup-and-data-recovery)
+[7. Interoperability with other Disk Encryption Tools](#7-interoperability-with-other-disk-encryption-tools)
+[8. Issues with Specific Versions of cryptsetup](#8-issues-with-specific-versions-of-cryptsetup)
+[9. The Initrd question](#9-the-initrd-question)
+[10. LUKS2 Questions](#10-luks2-questions)
+[11. References and Further Reading](#11-references-and-further-reading)
+[A. Contributors](#a-contributors)
+
+# 1. General Questions
+
+
+ * **1.1 What is this?**
+
+ This is the FAQ (Frequently Asked Questions) for cryptsetup. It covers
+ Linux disk encryption with plain dm-crypt (one passphrase, no
+ management, no metadata on disk) and LUKS (multiple user keys with one
+ volume key, anti-forensic features, metadata block at start of device,
+ ...). The latest version of this FAQ should usually be available at
+ https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
+
+
+ * **1.2 WARNINGS**
+
+ LUKS2 COMPATIBILITY: This FAQ was originally written for LUKS1, not
+ LUKS2. Hence regarding LUKS2, some of the answers found here may not
+ apply. Updates for LUKS2 have been done and anything not applying to
+ LUKS2 should clearly say LUKS1. However, this is a Frequently Asked
+ Questions, and questions for LUKS2 are limited at this time or at least
+ those that have reached me are. In the following, "LUKS" refers to both
+ LUKS1 and LUKS2.
+
+ The LUKS1 on-disk format specification is at
+ https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf
+ The LUKS2 on-disk format specification is at
+ https://gitlab.com/cryptsetup/LUKS2-docs
+
+ ATTENTION: If you are going to read just one thing, make it the section
+ on Backup and Data Recovery. By far the most questions on the
+ cryptsetup mailing list are from people that managed to damage the start
+ of their LUKS partitions, i.e. the LUKS header. In most cases, there
+ is nothing that can be done to help these poor souls recover their data.
+ Make sure you understand the problem and limitations imposed by the LUKS
+ security model BEFORE you face such a disaster! In particular, make
+ sure you have a current header backup before doing any potentially
+ dangerous operations. The LUKS2 header should be a bit more resilient
+ as critical data starts later and is stored twice, but you can decidedly
+ still destroy it or a keyslot permanently by accident.
+
+ DEBUG COMMANDS: While the --debug and --debug-json options should not
+ leak secret data, "strace" and the like can leak your full passphrase.
+ Do not post an strace output with the correct passphrase to a
+ mailing-list or online! See Item 4.5 for more explanation.
+
+ SSDs/FLASH DRIVES: SSDs and Flash are different. Currently it is
+ unclear how to get LUKS or plain dm-crypt to run on them with the full
+ set of security assurances intact. This may or may not be a problem,
+ depending on the attacker model. See Section 5.19.
+
+ BACKUP: Yes, encrypted disks die, just as normal ones do. A full backup
+ is mandatory, see Section "6. Backup and Data Recovery" on options for
+ doing encrypted backup.
+
+ CLONING/IMAGING: If you clone or image a LUKS container, you make a copy
+ of the LUKS header and the volume key will stay the same! That means
+ that if you distribute an image to several machines, the same volume key
+ will be used on all of them, regardless of whether you change the
+ passphrases. Do NOT do this! If you do, a root-user on any of the
+ machines with a mapped (decrypted) container or a passphrase on that
+ machine can decrypt all other copies, breaking security. See also Item
+ 6.15.
+
+ DISTRIBUTION INSTALLERS: Some distribution installers offer to create
+ LUKS containers in a way that can be mistaken as activation of an
+ existing container. Creating a new LUKS container on top of an existing
+ one leads to permanent, complete and irreversible data loss. It is
+ strongly recommended to only use distribution installers after a
+ complete backup of all LUKS containers has been made.
+
+ UBUNTU INSTALLER: In particular the Ubuntu installer seems to be quite
+ willing to kill LUKS containers in several different ways. Those
+ responsible at Ubuntu seem not to care very much (it is very easy to
+ recognize a LUKS container), so treat the process of installing Ubuntu
+ as a severe hazard to any LUKS container you may have.
+
+ NO WARNING ON NON-INTERACTIVE FORMAT: If you feed cryptsetup from STDIN
+ (e.g. via GnuPG) on LUKS format, it does not give you the warning that
+ you are about to format (and e.g. will lose any pre-existing LUKS
+ container on the target), as it assumes it is used from a script. In
+ this scenario, the responsibility for warning the user and possibly
+ checking for an existing LUKS header is shifted to the script. This is
+ a more general form of the previous item.
+
+ LUKS PASSPHRASE IS NOT THE VOLUME KEY: The LUKS passphrase is not used
+ in deriving the volume key. It is used in decrypting a volume key that
+ is randomly selected on header creation. This means that if you create
+ a new LUKS header on top of an old one with exactly the same parameters
+ and exactly the same passphrase as the old one, it will still have a
+ different volume key and your data will be permanently lost.
+
+ PASSPHRASE CHARACTER SET: Some people have had difficulties with this
+ when upgrading distributions. It is highly advisable to only use the 95
+ printable characters from the first 128 characters of the ASCII table,
+ as they will always have the same binary representation. Other
+ characters may have different encoding depending on system configuration
+ and your passphrase will not work with a different encoding. A table of
+ the standardized first 128 ASCII characters can, e.g. be found on
+ https://en.wikipedia.org/wiki/ASCII
+
+ KEYBOARD NUM-PAD: Apparently some pre-boot authentication environments
+ (these are done by the distro, not by cryptsetup, so complain there)
+ treat digits entered on the num-pad and ones entered regularly
+ different. This may be because the BIOS USB keyboard driver is used and
+ that one may have bugs on some computers. If you cannot open your
+ device in pre-boot, try entering the digits over the regular digit keys.
+
+
+ * **1.3 System specific warnings**
+
+ - The Ubuntu Natty uinstaller has a "won't fix" defect that may destroy
+ LUKS containers. This is quite old an not relevant for most people.
+ Reference:
+ https://bugs.launchpad.net/ubuntu/+source/partman-crypto/+bug/420080
+
+
+ * **1.4 My LUKS-device is broken! Help!**
+
+ First: Do not panic! In many cases the data is still recoverable.
+ Do not do anything hasty! Steps:
+
+ - Take some deep breaths. Maybe add some relaxing music. This may
+ sound funny, but I am completely serious. Often, critical damage is
+ done only after the initial problem.
+
+ - Do not reboot. The keys may still be in the kernel if the device is
+ mapped.
+
+ - Make sure others do not reboot the system.
+
+ - Do not write to your disk without a clear understanding why this will
+ not make matters worse. Do a sector-level backup before any writes.
+ Often you do not need to write at all to get enough access to make a
+ backup of the data.
+
+ - Relax some more.
+
+ - Read section 6 of this FAQ.
+
+ - Ask on the mailing-list if you need more help.
+
+
+ * **1.5 Who wrote this?**
+
+ Current FAQ maintainer is Arno Wagner <arno@wagner.name>. If you want
+ to send me encrypted email, my current PGP key is DSA key CB5D9718,
+ fingerprint 12D6 C03B 1B30 33BB 13CF B774 E35C 5FA1 CB5D 9718.
+
+ Other contributors are listed at the end. If you want to contribute,
+ send your article, including a descriptive headline, to the maintainer,
+ or the dm-crypt mailing list with something like "FAQ ..."
+ in the subject. You can also send more raw information and have
+ me write the section. Please note that by contributing to this FAQ,
+ you accept the license described below.
+
+ This work is under the "Attribution-Share Alike 3.0 Unported" license,
+ which means distribution is unlimited, you may create derived works, but
+ attributions to original authors and this license statement must be
+ retained and the derived work must be under the same license. See
+ https://creativecommons.org/licenses/by-sa/3.0/ for more details of the
+ license.
+
+ Side note: I did text license research some time ago and I think this
+ license is best suited for the purpose at hand and creates the least
+ problems.
+
+
+ * **1.6 Where is the project website?**
+
+ There is the project website at
+ https://gitlab.com/cryptsetup/cryptsetup/ Please do not post
+ questions there, nobody will read them. Use the mailing-list
+ instead.
+
+
+ * **1.7 Is there a mailing-list?**
+
+ Instructions on how to subscribe to the mailing-list are on the
+ project website. People are generally helpful and friendly on the
+ list.
+
+ The question of how to unsubscribe from the list does crop up sometimes.
+ For this you need your list management URL
+ https://subspace.kernel.org/lists.linux.dev.html. Go to the URL mentioned
+ in the email and select "unsubscribe".
+
+ Alternatively, you can send an empty Email to cryptsetup+help@lists.linux.dev.
+ Make sure to send it from your list address.
+
+ The mailing list archive is here:
+ https://lore.kernel.org/cryptsetup/
+
+ The legacy dm-crypt mailing list archive is here:
+ https://lore.kernel.org/dm-crypt/
+
+
+ * **1.8 Unsubscribe from the mailing-list**
+
+ Send mail to cryptsetup+unsubscribe@lists.linux.dev from the subscribed account.
+ You will get an email with instructions.
+
+ Basically, you just have to respond to it unmodified to get
+ unsubscribed. The listserver admin functions are not very fast. It can
+ take 15 minutes or longer for a reply to arrive (I suspect greylisting
+ is in use), so be patient.
+
+ Also note that nobody on the list can unsubscribe you, sending demands
+ to be unsubscribed to the list just annoys people that are entirely
+ blameless for you being subscribed.
+
+ If you are subscribed, a subscription confirmation email was sent to
+ your email account and it had to be answered before the subscription
+ went active. The confirmation emails from the listserver have subjects
+ like these (with other numbers):
+```
+ Subject: Confirm subscription to cryptsetup@lists.linux.dev
+```
+ and are sent from cryptsetup+help@lists.linux.dev. You should check whether
+ you have anything like it in your sent email folder. If you find
+ nothing and are sure you did not confirm, then you should look into a
+ possible compromise of your email account.
+
+ * **1.9 What can I do if cryptsetup is running out of memory?**
+
+ Memory issues are generally related to the key derivation function. You may
+ be able to tune usage with the options --pbkdf-memory or --pbkdf pbkdf2.
+
+
+ * **1.10 Can cryptsetup be run without root access?**
+
+ Elevated privileges are required to use cryptsetup and LUKS. Some operations
+ require root access. There are a few features which will work without root
+ access with the right switches but there are caveats.
+
+
+ * **1.11 What are the problems with running as non root?**
+
+ The first issue is one of permissions to devices. Generally, root or a group
+ such as disk has ownership of the storage devices. The non root user will
+ need write access to the block device used for LUKS.
+
+ Next, file locking is managed in /run/cryptsetup. You may use
+ --disable-locks but cryptsetup will no longer protect you from race
+ conditions and problems with concurrent access to the same devices.
+
+ Also, device mapper requires root access. cryptsetup uses device mapper to
+ manage the decrypted container.
+
+ * **1.12 How can I report an issue in the cryptsetup project?**
+
+ Before reporting any issue, please be sure you are using the latest
+ upstream version and that you read the documentation (and this FAQ).
+
+ If you think you have discovered an issue, please report it through
+ the project issue tracker [New issue](https://gitlab.com/cryptsetup/cryptsetup/issues).
+ For a possible security issue, please use the confidential checkbox.
+
+ Please fill in all information requested in the report template
+ (specifically add debug output with all run environment data).
+ Do not trim the output; debug output does not include private data.
+
+
+# 2. Setup
+
+ * **2.1 LUKS Container Setup mini-HOWTO**
+
+ This item tries to give you a very brief list of all the steps you
+ should go through when creating a new LUKS encrypted container, i.e.
+ encrypted disk, partition or loop-file.
+
+ 01) All data will be lost, if there is data on the target, make a
+ backup.
+
+ 02) Make very sure you use the right target disk, partition or
+ loop-file.
+
+ 03) If the target was in use previously, it is a good idea to wipe it
+ before creating the LUKS container in order to remove any trace of old
+ file systems and data. For example, some users have managed to run
+ e2fsck on a partition containing a LUKS container, possibly because of
+ residual ext2 superblocks from an earlier use. This can do arbitrary
+ damage up to complete and permanent loss of all data in the LUKS
+ container.
+
+ To just quickly wipe file systems (old data may remain), use
+```
+ wipefs -a <target device>
+```
+ To wipe file system and data, use something like
+```
+ cat /dev/zero > <target device>
+```
+ This can take a while. To get a progress indicator, you can use the
+ tool dd_rescue (->google) instead or use my stream meter "wcs" (source
+ here: https://www.tansi.org/tools/index.html) in the following fashion:
+```
+ cat /dev/zero | wcs > <target device>
+```
+ Plain "dd" also gives you the progress on a SIGUSR1, see its man-page.
+ The GNU "dd" command supports the "status=progress" operand that gives you
+ the progress without having to send it any signal.
+
+ Be very sure you have the right target, all data will be lost!
+
+ Note that automatic wiping is on the TODO list for cryptsetup, so at
+ some time in the future this will become unnecessary.
+
+ Alternatively, plain dm-crypt can be used for a very fast wipe with
+ crypto-grade randomness, see Item 2.19
+
+ 04) Create the LUKS container.
+
+ LUKS1:
+```
+ cryptsetup luksFormat --type luks1 <target device>
+```
+ LUKS2:
+```
+ cryptsetup luksFormat --type luks2 <target device>
+```
+
+ Just follow the on-screen instructions.
+
+ Note: Passphrase iteration count is based on time and hence security
+ level depends on CPU power of the system the LUKS container is created
+ on. For example on a Raspberry Pi and LUKS1, I found some time ago that
+ the iteration count is 15 times lower than for a regular PC (well, for
+ my old one). Depending on security requirements, this may need
+ adjustment. For LUKS1, you can just look at the iteration count on
+ different systems and select one you like. You can also change the
+ benchmark time with the -i parameter to create a header for a slower
+ system.
+
+ For LUKS2, the parameters are more complex. ARGON2 has iteration,
+ parallelism and memory parameter. cryptsetup actually may adjust the
+ memory parameter for time scaling. Hence to use -i is the easiest way
+ to get slower or faster opening (default: 2000 = 2sec). Just make sure
+ to not drop this too low or you may get a memory parameter that is to
+ small to be secure. The luksDump command lists the memory parameter of
+ a created LUKS2 keyslot in kB. That parameter should probably be not
+ much lower than 100000, i.e. 100MB, but don't take my word for it.
+
+ 05) Map the container. Here it will be mapped to /dev/mapper/c1:
+```
+ cryptsetup luksOpen <target device> c1
+```
+ 06) (Optionally) wipe the container (make sure you have the right
+ target!):
+```
+ cat /dev/zero > /dev/mapper/c1
+```
+ This will take a while. Note that this creates a small information
+ leak, as an attacker can determine whether a 512 byte block is zero if
+ the attacker has access to the encrypted container multiple times.
+ Typically a competent attacker that has access multiple times can
+ install a passphrase sniffer anyways, so this leakage is not very
+ significant. For getting a progress indicator, see step 03.
+
+ 07) Create a file system in the mapped container, for example an
+ ext3 file system (any other file system is possible):
+```
+ mke2fs -j /dev/mapper/c1
+```
+ 08) Mount your encrypted file system, here on /mnt:
+```
+ mount /dev/mapper/c1 /mnt
+```
+ 09) Make a LUKS header backup and plan for a container backup.
+ See Section 6 for details.
+
+ Done. You can now use the encrypted file system to store data. Be sure
+ to read through the rest of the FAQ, these are just the very basics. In
+ particular, there are a number of mistakes that are easy to make, but
+ will compromise your security.
+
+
+ * **2.2 LUKS on partitions or raw disks? What about RAID?**
+
+ Also see Item 2.8.
+ This is a complicated question, and made more so by the availability of
+ RAID and LVM. I will try to give some scenarios and discuss advantages
+ and disadvantages. Note that I say LUKS for simplicity, but you can do
+ all the things described with plain dm-crypt as well. Also note that
+ your specific scenario may be so special that most or even all things I
+ say below do not apply.
+
+ Be aware that if you add LVM into the mix, things can get very
+ complicated. Same with RAID but less so. In particular, data recovery
+ can get exceedingly difficult. Only add LVM if you have a really good
+ reason and always remember KISS is what separates an engineer from an
+ amateur. Of course, if you really need the added complexity, KISS is
+ satisfied. But be very sure as there is a price to pay for it. In
+ engineering, complexity is always the enemy and needs to be fought
+ without mercy when encountered.
+
+ Also consider using RAID instead of LVM, as at least with the old
+ superblock format 0.90, the RAID superblock is in the place (end of
+ disk) where the risk of it damaging the LUKS header is smallest and you
+ can have your array assembled by the RAID controller (i.e. the kernel),
+ as it should be. Use partition type 0xfd for that. I recommend staying
+ away from superblock formats 1.0, 1.1 and 1.2 unless you really need
+ them.
+
+ Scenarios:
+
+ (1) Encrypted partition: Just make a partition to your liking, and put
+ LUKS on top of it and a filesystem into the LUKS container. This gives
+ you isolation of differently-tasked data areas, just as ordinary
+ partitioning does. You can have confidential data, non-confidential
+ data, data for some specific applications, user-homes, root, etc.
+ Advantages are simplicity as there is a 1:1 mapping between partitions
+ and filesystems, clear security functionality and the ability to
+ separate data into different, independent (!) containers.
+
+ Note that you cannot do this for encrypted root, that requires an
+ initrd. On the other hand, an initrd is about as vulnerable to a
+ competent attacker as a non-encrypted root, so there really is no
+ security advantage to doing it that way. An attacker that wants to
+ compromise your system will just compromise the initrd or the kernel
+ itself. The better way to deal with this is to make sure the root
+ partition does not store any critical data and to move that to
+ additional encrypted partitions. If you really are concerned your root
+ partition may be sabotaged by somebody with physical access (who would
+ however strangely not, say, sabotage your BIOS, keyboard, etc.), protect
+ it in some other way. The PC is just not set-up for a really secure
+ boot-chain (whatever some people may claim).
+
+ That said, if you want an encrypted root partition, you have to store
+ an initrd with cryptsetup somewhere else. The traditional approach is
+ to have a separate partition under /boot for that. You can also put that
+ initrd on a bootable memory stick, bootable CD or bootable external
+ drive as well. The kernel and Grub typically go to the same location
+ as that initrd. A minimal example what such an initrd can look like is
+ given in Section 9.
+
+ (2) Fully encrypted raw block device: For this, put LUKS on the raw
+ device (e.g. /dev/sdb) and put a filesystem into the LUKS container, no
+ partitioning whatsoever involved. This is very suitable for things like
+ external USB disks used for backups or offline data-storage.
+
+ (3) Encrypted RAID: Create your RAID from partitions and/or full
+ devices. Put LUKS on top of the RAID device, just if it were an
+ ordinary block device. Applications are just the same as above, but you
+ get redundancy. (Side note as many people seem to be unaware of it: You
+ can do RAID1 with an arbitrary number of components in Linux.) See also
+ Item 2.8.
+
+ (4) Now, some people advocate doing the encryption below the RAID layer.
+ That has several serious problems. One is that suddenly debugging RAID
+ issues becomes much harder. You cannot do automatic RAID assembly
+ anymore. You need to keep the encryption keys for the different RAID
+ components in sync or manage them somehow. The only possible advantage
+ is that things may run a little faster as more CPUs do the encryption,
+ but if speed is a priority over security and simplicity, you are doing
+ this wrong anyways. A good way to mitigate a speed issue is to get a
+ CPU that does hardware AES as most do today.
+
+
+ * **2.3 How do I set up encrypted swap?**
+
+ As things that are confidential can end up in swap (keys, passphrases,
+ etc. are usually protected against being swapped to disk, but other
+ things may not be), it may be advisable to do something about the issue.
+ One option is to run without swap, which generally works well in a
+ desktop-context. It may cause problems in a server-setting or under
+ special circumstances. The solution to that is to encrypt swap with a
+ random key at boot-time.
+
+ NOTE: This is for Debian, and should work for Debian-derived
+ distributions. For others you may have to write your own startup script
+ or use other mechanisms.
+
+ 01) Add the swap partition to /etc/crypttab. A line like the
+ following should do it:
+```
+ swap /dev/<partition> /dev/urandom swap,noearly
+```
+ Warning: While Debian refuses to overwrite partitions with a filesystem
+ or RAID signature on it, as your disk IDs may change (adding or removing
+ disks, failure of disk during boot, etc.), you may want to take
+ additional precautions. Yes, this means that your kernel device names
+ like sda, sdb, ... can change between reboots! This is not a concern
+ if you have only one disk. One possibility is to make sure the
+ partition number is not present on additional disks or also swap there.
+ Another is to encapsulate the swap partition (by making it a 1-partition
+ RAID1 or by using LVM), as that gets a persistent identifier.
+ Specifying it directly by UUID does not work, unfortunately, as the UUID
+ is part of the swap signature and that is not visible from the outside
+ due to the encryption and in addition changes on each reboot with this
+ setup.
+
+ Note: Use /dev/random if you are paranoid or in a potential low-entropy
+ situation (embedded system, etc.). This may cause the operation to take
+ a long time during boot however. If you are in a "no entropy"
+ situation, you cannot encrypt swap securely. In this situation you
+ should find some entropy, also because nothing else using crypto will be
+ secure, like ssh, ssl or GnuPG.
+
+ Note: The "noearly" option makes sure things like LVM, RAID, etc. are
+ running. As swap is non-critical for boot, it is fine to start it late.
+
+ 02) Add the swap partition to /etc/fstab. A line like the following
+ should do it:
+```
+ /dev/mapper/swap none swap sw 0 0
+```
+ That is it. Reboot or start it manually to activate encrypted swap.
+ Manual start would look like this:
+```
+ /etc/init.d/cryptdisks start
+ swapon /dev/mapper/swap
+```
+
+ * **2.4 What is the difference between "plain" and LUKS format?**
+
+ First, unless you happen to understand the cryptographic background
+ well, you should use LUKS. It does protect the user from a lot of
+ common mistakes. Plain dm-crypt is for experts.
+
+ Plain format is just that: It has no metadata on disk, reads all
+ parameters from the commandline (or the defaults), derives a volume-key
+ from the passphrase and then uses that to de-/encrypt the sectors of the
+ device, with a direct 1:1 mapping between encrypted and decrypted
+ sectors.
+
+ Primary advantage is high resilience to damage, as one damaged encrypted
+ sector results in exactly one damaged decrypted sector. Also, it is not
+ readily apparent that there even is encrypted data on the device, as an
+ overwrite with crypto-grade randomness (e.g. from
+ /dev/urandom) looks exactly the same on disk.
+
+ Side-note: That has limited value against the authorities. In civilized
+ countries, they cannot force you to give up a crypto-key anyways. In
+ quite a few countries around the world, they can force you to give up
+ the keys (using imprisonment or worse to pressure you, sometimes without
+ due process), and in the worst case, they only need a nebulous
+ "suspicion" about the presence of encrypted data. Sometimes this
+ applies to everybody, sometimes only when you are suspected of having
+ "illicit data" (definition subject to change) and sometimes specifically
+ when crossing a border. Note that this is going on in countries like
+ the US and the UK to different degrees and sometimes with courts
+ restricting what the authorities can actually demand.
+
+ My advice is to either be ready to give up the keys or to not have
+ encrypted data when traveling to those countries, especially when
+ crossing the borders. The latter also means not having any high-entropy
+ (random) data areas on your disk, unless you can explain them and
+ demonstrate that explanation. Hence doing a zero-wipe of all free
+ space, including unused space, may be a good idea.
+
+ Disadvantages are that you do not have all the nice features that the
+ LUKS metadata offers, like multiple passphrases that can be changed, the
+ cipher being stored in the metadata, anti-forensic properties like
+ key-slot diffusion and salts, etc..
+
+ LUKS format uses a metadata header and 8 key-slot areas that are being
+ placed at the beginning of the disk, see below under "What does the LUKS
+ on-disk format looks like?". The passphrases are used to decrypt a
+ single volume key that is stored in the anti-forensic stripes. LUKS2
+ adds some more flexibility.
+
+ Advantages are a higher usability, automatic configuration of
+ non-default crypto parameters, defenses against low-entropy passphrases
+ like salting and iterated PBKDF2 or ARGON 2 passphrase hashing, the
+ ability to change passphrases, and others.
+
+ Disadvantages are that it is readily obvious there is encrypted data on
+ disk (but see side note above) and that damage to the header or
+ key-slots usually results in permanent data-loss. See below under "6.
+ Backup and Data Recovery" on how to reduce that risk. Also the sector
+ numbers get shifted by the length of the header and key-slots and there
+ is a loss of that size in capacity. Unless you have a specific need,
+ use LUKS2.
+
+
+ * **2.5 Can I encrypt an existing, non-empty partition to use LUKS?**
+
+ There is no converter, and it is not really needed. The way to do this
+ is to make a backup of the device in question, securely wipe the device
+ (as LUKS device initialization does not clear away old data), do a
+ luksFormat, optionally overwrite the encrypted device, create a new
+ filesystem and restore your backup on the now encrypted device. Also
+ refer to sections "Security Aspects" and "Backup and Data Recovery".
+
+ For backup, plain GNU tar works well and backs up anything likely to be
+ in a filesystem.
+
+
+ * **2.6 How do I use LUKS with a loop-device?**
+
+ This can be very handy for experiments. Setup is just the same as with
+ any block device. If you want, for example, to use a 100MiB file as
+ LUKS container, do something like this:
+```
+ head -c 100M /dev/zero > luksfile # create empty file
+ losetup /dev/loop0 luksfile # map file to /dev/loop0
+ cryptsetup luksFormat --type luks2 /dev/loop0 # create LUKS2 container
+```
+ Afterwards just use /dev/loop0 as a you would use a LUKS partition.
+ To unmap the file when done, use "losetup -d /dev/loop0".
+
+
+ * **2.7 When I add a new key-slot to LUKS, it asks for a passphrase but then complains about there not being a key-slot with that passphrase?**
+
+ That is as intended. You are asked a passphrase of an existing key-slot
+ first, before you can enter the passphrase for the new key-slot.
+ Otherwise you could break the encryption by just adding a new key-slot.
+ This way, you have to know the passphrase of one of the already
+ configured key-slots in order to be able to configure a new key-slot.
+
+
+ * **2.8 Encryption on top of RAID or the other way round?**
+
+ Also see Item 2.2.
+ Unless you have special needs, place encryption between RAID and
+ filesystem, i.e. encryption on top of RAID. You can do it the other
+ way round, but you have to be aware that you then need to give the
+ passphrase for each individual disk and RAID auto-detection will not
+ work anymore. Therefore it is better to encrypt the RAID device, e.g.
+ /dev/dm0 .
+
+ This means that the typical layering looks like this:
+```
+ Filesystem <- top
+ |
+ Encryption (LUKS)
+ |
+ RAID
+ |
+ Raw partitions (optional)
+ |
+ Raw disks <- bottom
+```
+ The big advantage of this is that you can manage the RAID container just
+ like any other regular RAID container, it does not care that its content
+ is encrypted. This strongly cuts down on complexity, something very
+ valuable with storage encryption.
+
+ Try to avoid so-called fake RAID (RAID configured from BIOS but handled
+ by proprietary drivers). Note that some fake RAID firmware automatically
+ writes signature on disks if enabled. This causes corruption of LUKS
+ metadata. Be sure to switch the RAID option off in BIOS if you do not
+ use it.
+
+ Another data corruption can happen if you resize (enlarge) the underlying
+ device and some remnant metadata appear near the end of the resized device
+ (like a secondary copy of the GPT table). You can use wipefs command to
+ detect and wipe such signatures.
+
+
+ * **2.9 How do I read a dm-crypt key from file?**
+
+ Use the --key-file option, like this:
+```
+ cryptsetup create --key-file keyfile e1 /dev/loop0
+```
+ This will read the binary key from file, i.e. no hashing or
+ transformation will be applied to the keyfile before its bits are used
+ as key. Extra bits (beyond the length of the key) at the end are
+ ignored. Note that if you read from STDIN, the data will be hashed,
+ just as a key read interactively from the terminal. See the man-page
+ sections "NOTES ON PASSPHRASE PROCESSING..." for more detail.
+
+
+ * **2.10 How do I read a LUKS slot key from file?**
+
+ What you really do here is to read a passphrase from file, just as you
+ would with manual entry of a passphrase for a key-slot. You can add a
+ new passphrase to a free key-slot, set the passphrase of an specific
+ key-slot or put an already configured passphrase into a file. Make sure
+ no trailing newline (0x0a) is contained in the input key file, or the
+ passphrase will not work because the whole file is used as input.
+
+ To add a new passphrase to a free key slot from file, use something
+ like this:
+```
+ cryptsetup luksAddKey /dev/loop0 keyfile
+```
+ To add a new passphrase to a specific key-slot, use something
+ like this:
+```
+ cryptsetup luksAddKey --key-slot 7 /dev/loop0 keyfile
+```
+ To supply a key from file to any LUKS command, use the --key-file
+ option, e.g. like this:
+```
+ cryptsetup luksOpen --key-file keyfile /dev/loop0 e1
+```
+
+
+ * **2.11 How do I read the LUKS volume key from file?**
+
+ The question you should ask yourself first is why you would want to do
+ this. The only legitimate reason I can think of is if you want to have
+ two LUKS devices with the same volume key. Even then, I think it would
+ be preferable to just use key-slots with the same passphrase, or to use
+ plain dm-crypt instead. If you really have a good reason, please tell
+ me. If I am convinced, I will add how to do this here.
+
+
+ * **2.12 What are the security requirements for a key read from file?**
+
+ A file-stored key or passphrase has the same security requirements as
+ one entered interactively, however you can use random bytes and thereby
+ use bytes you cannot type on the keyboard. You can use any file you
+ like as key file, for example a plain text file with a human readable
+ passphrase. To generate a file with random bytes, use something like
+ this:
+```
+ head -c 256 /dev/random > keyfile
+```
+
+
+ * **2.13 If I map a journaled file system using dm-crypt/LUKS, does it still provide its usual transactional guarantees?**
+
+ Yes, it does, unless a very old kernel is used. The required flags come
+ from the filesystem layer and are processed and passed onward by
+ dm-crypt (regardless of direct key management or LUKS key management).
+ A bit more information on the process by which transactional guarantees
+ are implemented can be found here:
+
+ https://lwn.net/Articles/400541/
+
+ Please note that these "guarantees" are weaker than they appear to be.
+ One problem is that quite a few disks lie to the OS about having flushed
+ their buffers. This is likely still true with SSDs. Some other things
+ can go wrong as well. The filesystem developers are aware of these
+ problems and typically can make it work anyways. That said,
+ dm-crypt/LUKS will not make things worse.
+
+ One specific problem you can run into is that you can get short freezes
+ and other slowdowns due to the encryption layer. Encryption takes time
+ and forced flushes will block for that time. For example, I did run
+ into frequent small freezes (1-2 sec) when putting a vmware image on
+ ext3 over dm-crypt. When I went back to ext2, the problem went away.
+ This seems to have gotten better with kernel 2.6.36 and the reworking of
+ filesystem flush locking mechanism (less blocking of CPU activity during
+ flushes). This should improve further and eventually the problem should
+ go away.
+
+
+ * **2.14 Can I use LUKS or cryptsetup with a more secure (external) medium for key storage, e.g. TPM or a smartcard?**
+
+ Yes, see the answers on using a file-supplied key. You do have to write
+ the glue-logic yourself though. Basically you can have cryptsetup read
+ the key from STDIN and write it there with your own tool that in turn
+ gets the key from the more secure key storage.
+
+
+ * **2.15 Can I resize a dm-crypt or LUKS container?**
+
+ Yes, you can, as neither dm-crypt nor LUKS1 stores partition size and
+ LUKS2 uses a generic "whole device" size as default. Note that LUKS2
+ can use specified data-area sizes as a non-standard case and that these
+ may cause issues when resizing a LUKS2 container if set to a specific
+ value.
+
+ Whether you should do this is a different question. Personally I
+ recommend backup, recreation of the dm-crypt or LUKS container with new
+ size, recreation of the filesystem and restore. This gets around the
+ tricky business of resizing the filesystem. Resizing a dm-crypt or LUKS
+ container does not resize the filesystem in it. A backup is really
+ non-optional here, as a lot can go wrong, resulting in partial or
+ complete data loss. But if you have that backup, you can also just
+ recreate everything.
+
+ You also need to be aware of size-based limitations. The one currently
+ relevant is that aes-xts-plain should not be used for encrypted
+ container sizes larger than 2TiB. Use aes-xts-plain64 for that.
+
+
+ * **2.16 How do I Benchmark the Ciphers, Hashes and Modes?**
+
+ Since version 1.60 cryptsetup supports the "benchmark" command.
+ Simply run as root:
+```
+ cryptsetup benchmark
+```
+ You can get more than the default benchmarks, see the man-page for the
+ relevant parameters. Note that XTS mode takes two keys, hence the
+ listed key sizes are double that for other modes and half of it is the
+ cipher key, the other half is the XTS key.
+
+
+ * **2.17 How do I Verify I have an Authentic cryptsetup Source Package?**
+
+ Current maintainer is Milan Broz and he signs the release packages with
+ his PGP key. The key he currently uses is the "RSA key ID D93E98FC",
+ fingerprint 2A29 1824 3FDE 4664 8D06 86F9 D9B0 577B D93E 98FC. While I
+ have every confidence this really is his key and that he is who he
+ claims to be, don't depend on it if your life is at stake. For that
+ matter, if your life is at stake, don't depend on me being who I claim
+ to be either.
+
+ That said, as cryptsetup is under good version control and a malicious
+ change should be noticed sooner or later, but it may take a while.
+ Also, the attacker model makes compromising the sources in a non-obvious
+ way pretty hard. Sure, you could put the volume-key somewhere on disk,
+ but that is rather obvious as soon as somebody looks as there would be
+ data in an empty LUKS container in a place it should not be. Doing this
+ in a more nefarious way, for example hiding the volume-key in the salts,
+ would need a look at the sources to be discovered, but I think that
+ somebody would find that sooner or later as well.
+
+ That said, this discussion is really a lot more complicated and longer
+ as an FAQ can sustain. If in doubt, ask on the mailing list.
+
+
+ * **2.18 Is there a concern with 4k Sectors?**
+
+ Not from dm-crypt itself. Encryption will be done in 512B blocks, but
+ if the partition and filesystem are aligned correctly and the filesystem
+ uses multiples of 4kiB as block size, the dm-crypt layer will just
+ process 8 x 512B = 4096B at a time with negligible overhead. LUKS does
+ place data at an offset, which is 2MiB per default and will not break
+ alignment. See also Item 6.12 of this FAQ for more details. Note that
+ if your partition or filesystem is misaligned, dm-crypt can make the
+ effect worse though. Also note that SSDs typically have much larger
+ blocks internally (e.g. 128kB or even larger).
+
+
+ * **2.19 How can I wipe a device with crypto-grade randomness?**
+
+ The conventional recommendation if you want to do more than just a
+ zero-wipe is to use something like
+```
+ cat /dev/urandom > <target-device>
+```
+ That used to very slow and painful at 10-20MB/s on a fast computer, but
+ newer kernels can give you > 200MB/s (depending on hardware). An
+ alternative is using cryptsetup and a plain dm-crypt device with a
+ random key, which is fast and on the same level of security. The
+ defaults are quite enough.
+
+ For device set-up, do the following:
+```
+ cryptsetup open --type plain -d /dev/urandom /dev/<device> target
+```
+ This maps the container as plain under /dev/mapper/target with a random
+ password. For the actual wipe you have several options. Basically, you
+ pipe zeroes into the opened container that then get encrypted. Simple
+ wipe without progress-indicator:
+```
+ cat /dev/zero > /dev/mapper/to_be_wiped
+```
+ Progress-indicator by dd_rescue:
+```
+ dd_rescue -w /dev/zero /dev/mapper/to_be_wiped
+```
+ Progress-indicator by my "wcs" stream meter (available from
+ https://www.tansi.org/tools/index.html ):
+```
+ cat /dev/zero | wcs > /dev/mapper/to_be_wiped
+```
+ Or use plain "dd", which gives you the progress when sent a SIGUSR1, see
+ the dd man page. The GNU "dd" command supports the "status=progress"
+ operand that gives you the progress without having to send it any signal.
+
+ Remove the mapping at the end and you are done.
+
+
+ * **2.20 How do I wipe only the LUKS header?**
+
+ This does _not_ describe an emergency wipe procedure, see Item 5.4 for
+ that. This procedure here is intended to be used when the data should
+ stay intact, e.g. when you change your LUKS container to use a detached
+ header and want to remove the old one. Please only do this if you have
+ a current backup.
+
+ LUKS1:
+ 01) Determine header size in 512 Byte sectors with luksDump:
+```
+ cryptsetup luksDump <device with LUKS container>
+
+-> ...
+ Payload offset: <number> [of 512 byte sectors]
+ ...
+```
+ 02) Take the result number, multiply by 512 zeros and write to
+ the start of the device, e.g. using one of the following alternatives:
+```
+ dd bs=512 count=<number> if=/dev/zero of=<device>
+```
+```
+ head -c <number * 512> /dev/zero > /dev/<device>
+```
+
+ LUKS2:
+ (warning, untested! Remember that backup?) This assumes the
+ LUKS2 container uses the defaults, in particular there is only one data
+ segment.
+ 01) Determine the data-segment offset using luksDump, same
+ as above for LUKS1:
+```
+ cryptsetup luksDump <device with LUKS container>
+-> ...
+ Data segments:
+ 0: crypt
+ offset: <number> [bytes]
+ ...
+```
+ 02) Overwrite the stated number of bytes from the start of the device.
+ Just to give yet another way to get a defined number of zeros:
+```
+ head -c <number> /dev/zero > /dev/<device>
+```
+
+# 3. Common Problems
+
+
+ * **3.1 My dm-crypt/LUKS mapping does not work! What general steps are there to investigate the problem?**
+
+ If you get a specific error message, investigate what it claims first.
+ If not, you may want to check the following things.
+
+ - Check that "/dev", including "/dev/mapper/control" is there. If it is
+ missing, you may have a problem with the "/dev" tree itself or you may
+ have broken udev rules.
+
+ - Check that you have the device mapper and the crypt target in your
+ kernel. The output of "dmsetup targets" should list a "crypt" target.
+ If it is not there or the command fails, add device mapper and
+ crypt-target to the kernel.
+
+ - Check that the hash-functions and ciphers you want to use are in the
+ kernel. The output of "cat /proc/crypto" needs to list them.
+
+
+ * **3.2 My dm-crypt mapping suddenly stopped when upgrading cryptsetup.**
+
+ The default cipher, hash or mode may have changed (the mode changed from
+ 1.0.x to 1.1.x). See under "Issues With Specific Versions of
+ cryptsetup".
+
+
+ * **3.3 When I call cryptsetup from cron/CGI, I get errors about unknown features?**
+
+ If you get errors about unknown parameters or the like that are not
+ present when cryptsetup is called from the shell, make sure you have no
+ older version of cryptsetup on your system that then gets called by
+ cron/CGI. For example some distributions install cryptsetup into
+ /usr/sbin, while a manual install could go to /usr/local/sbin. As a
+ debugging aid, call "cryptsetup --version" from cron/CGI or the
+ non-shell mechanism to be sure the right version gets called.
+
+
+ * **3.4 Unlocking a LUKS device takes very long. Why?**
+
+ The unlock time for a key-slot (see Section 5 for an explanation what
+ iteration does) is calculated when setting a passphrase. By default it
+ is 1 second (2 seconds for LUKS2). If you set a passphrase on a fast
+ machine and then unlock it on a slow machine, the unlocking time can be
+ much longer. Also take into account that up to 8 key-slots (LUKS2: up
+ to 32 key-slots) have to be tried in order to find the right one.
+
+ If this is the problem, you can add another key-slot using the slow
+ machine with the same passphrase and then remove the old key-slot. The
+ new key-slot will have the unlock time adjusted to the slow machine.
+ Use luksKeyAdd and then luksKillSlot or luksRemoveKey. You can also use
+ the -i option to reduce iteration time (and security level) when setting
+ a passphrase. Default is 1000 (1 sec) for LUKS1 and 2000 (2sec) for
+ LUKS2.
+
+ However, this operation will not change volume key iteration count ("MK
+ iterations" for LUKS1, "Iterations" under "Digests" for LUKS2). In
+ order to change that, you will have to backup the data in the LUKS
+ container (i.e. your encrypted data), luksFormat on the slow machine
+ and restore the data. Note that MK iterations are not very security
+ relevant.
+
+
+ * **3.5 "blkid" sees a LUKS UUID and an ext2/swap UUID on the same device. What is wrong?**
+
+ Some old versions of cryptsetup have a bug where the header does not get
+ completely wiped during LUKS format and an older ext2/swap signature
+ remains on the device. This confuses blkid.
+
+ Fix: Wipe the unused header areas by doing a backup and restore of
+ the header with cryptsetup 1.1.x or later:
+```
+ cryptsetup luksHeaderBackup --header-backup-file <file> <device>
+ cryptsetup luksHeaderRestore --header-backup-file <file> <device>
+```
+
+ * **3.6 I see a data corruption with the Intel QAT kernel driver; why?**
+
+ Intel QAT crypto API drivers have severe bugs that are not fixed for years.
+
+ If you see data corruption, please disable the QAT in the BIOS or avoid loading
+ kernel Intel QAT drivers (switch to software crypto implementation or AES-NI).
+
+ For more info, see posts in dm-devel list https://lore.kernel.org/dm-devel/?q=intel+qat
+
+
+# 4. Troubleshooting
+
+
+ * **4.1 I get the error "LUKS keyslot x is invalid." What does that mean?**
+
+ For LUKS1, this means that the given keyslot has an offset that points
+ outside the valid keyslot area. Typically, the reason is a corrupted
+ LUKS1 header because something was written to the start of the device
+ the LUKS1 container is on. For LUKS2, I do not know when this error can
+ happen, but I expect it will be something similar. Refer to Section
+ "Backup and Data Recovery" and ask on the mailing list if you have
+ trouble diagnosing and (if still possible) repairing this.
+
+
+ * **4.2 I cannot unlock my LUKS container! What could be the problem?**
+
+ First, make sure you have a correct passphrase. Then make sure you have
+ the correct key-map and correct keyboard. And then make sure you have
+ the correct character set and encoding, see also "PASSPHRASE CHARACTER
+ SET" under Section 1.2.
+
+ If you are sure you are entering the passphrase right, there is the
+ possibility that the respective key-slot has been damaged. There is no
+ way to recover a damaged key-slot, except from a header backup (see
+ Section 6). For security reasons, there is also no checksum in the
+ key-slots that could tell you whether a key-slot has been damaged. The
+ only checksum present allows recognition of a correct passphrase, but
+ that only works with that correct passphrase and a respective key-slot
+ that is intact.
+
+ In order to find out whether a key-slot is damaged one has to look for
+ "non-random looking" data in it. There is a tool that automates this
+ for LUKS1 in the cryptsetup distribution from version 1.6.0 onwards. It
+ is located in misc/keyslot_checker/. Instructions how to use and how to
+ interpret results are in the README file. Note that this tool requires
+ a libcryptsetup from cryptsetup 1.6.0 or later (which means
+ libcryptsetup.so.4.5.0 or later). If the tool complains about missing
+ functions in libcryptsetup, you likely have an earlier version from your
+ distribution still installed. You can either point the symbolic link(s)
+ from libcryptsetup.so.4 to the new version manually, or you can
+ uninstall the distribution version of cryptsetup and re-install that
+ from cryptsetup >= 1.6.0 again to fix this.
+
+
+ * **4.3 Can a bad RAM module cause problems?**
+
+ LUKS and dm-crypt can give the RAM quite a workout, especially when
+ combined with software RAID. In particular the combination RAID5 +
+ LUKS1 + XFS seems to uncover RAM problems that do not cause obvious
+ problems otherwise. Symptoms vary, but often the problem manifests
+ itself when copying large amounts of data, typically several times
+ larger than your main memory.
+
+ Note: One thing you should always do on large data copying or movements
+ is to run a verify, for example with the "-d" option of "tar" or by
+ doing a set of MD5 checksums on the source or target with
+```
+ find . -type f -exec md5sum \{\} \; > checksum-file
+```
+ and then a "md5sum -c checksum-file" on the other side. If you get
+ mismatches here, RAM is the primary suspect. A lesser suspect is an
+ overclocked CPU. I have found countless hardware problems in verify
+ runs after copying data or making backups. Bit errors are much more
+ common than most people think.
+
+ Some RAM issues are even worse and corrupt structures in one of the
+ layers. This typically results in lockups, CPU state dumps in the
+ system logs, kernel panic or other things. It is quite possible to have
+ a problem with an encrypted device, but not with an otherwise the same
+ unencrypted device. The reason for that is that encryption has an error
+ amplification property: If you flip one bit in an encrypted data block,
+ the decrypted version has half of its bits flipped. This is actually an
+ important security property for modern ciphers. With the usual modes in
+ cryptsetup (CBC, ESSIV, XTS), you can get a completely changed 512 byte
+ block for a bit error. A corrupt block causes a lot more havoc than the
+ occasionally flipped single bit and can result in various obscure
+ errors.
+
+ Note that a verify run on copying between encrypted or unencrypted
+ devices will reliably detect corruption, even when the copying itself
+ did not report any problems. If you find defect RAM, assume all backups
+ and copied data to be suspect, unless you did a verify.
+
+
+ * **4.4 How do I test RAM?**
+
+ First you should know that overclocking often makes memory problems
+ worse. So if you overclock (which I strongly recommend against in a
+ system holding data that has any worth), run the tests with the
+ overclocking active.
+
+ There are two good options. One is Memtest86+ and the other is
+ "memtester" by Charles Cazabon. Memtest86+ requires a reboot and then
+ takes over the machine, while memtester runs from a root-shell. Both
+ use different testing methods and I have found problems fast with either
+ one that the other needed long to find. I recommend running the
+ following procedure until the first error is found:
+
+ - Run Memtest86+ for one cycle
+
+ - Run memtester for one cycle (shut down as many other applications
+ as possible and use the largest memory area you can get)
+
+ - Run Memtest86+ for 24h or more
+
+ - Run memtester for 24h or more
+
+ If all that does not produce error messages, your RAM may be sound,
+ but I have had one weak bit in the past that Memtest86+ needed around
+ 60 hours to find. If you can reproduce the original problem reliably,
+ a good additional test may be to remove half of the RAM (if you have
+ more than one module) and try whether the problem is still there and if
+ so, try with the other half. If you just have one module, get a
+ different one and try with that. If you do overclocking, reduce the
+ settings to the most conservative ones available and try with that.
+
+
+ * **4.5 Is there a risk using debugging tools like strace?**
+
+ There most definitely is. A dump from strace and friends can contain
+ all data entered, including the full passphrase. Example with strace
+ and passphrase "test":
+```
+ > strace cryptsetup luksOpen /dev/sda10 c1
+ ...
+ read(6, "test\n", 512) = 5
+ ...
+```
+ Depending on different factors and the tool used, the passphrase may
+ also be encoded and not plainly visible. Hence it is never a good idea
+ to give such a trace from a live container to anybody. Recreate the
+ problem with a test container or set a temporary passphrase like "test"
+ and use that for the trace generation. Item 2.6 explains how to create
+ a loop-file backed LUKS container that may come in handy for this
+ purpose.
+
+ See also Item 6.10 for another set of data you should not give to
+ others.
+
+
+# 5. Security Aspects
+
+
+ * **5.1 How long is a secure passphrase?**
+
+ This is just the short answer. For more info and explanation of some of
+ the terms used in this item, read the rest of Section 5. The actual
+ recommendation is at the end of this item.
+
+ First, passphrase length is not really the right measure, passphrase
+ entropy is. If your passphrase is 200 times the letter "a", it is long
+ but has very low entropy and is pretty insecure.
+
+ For example, a random lowercase letter (a-z) gives you 4.7 bit of
+ entropy, one element of a-z0-9 gives you 5.2 bits of entropy, an element
+ of a-zA-Z0-9 gives you 5.9 bits and a-zA-Z0-9!@#$%\^&:-+ gives you 6.2
+ bits. On the other hand, a random English word only gives you 0.6...1.3
+ bits of entropy per character. Using sentences that make sense gives
+ lower entropy, series of random words gives higher entropy. Do not use
+ sentences that can be tied to you or found on your computer. This type
+ of attack is done routinely today.
+
+ That said, it does not matter too much what scheme you use, but it does
+ matter how much entropy your passphrase contains, because an attacker
+ has to try on average
+```
+ 1/2 * 2^(bits of entropy in passphrase)
+```
+ different passphrases to guess correctly.
+
+ Historically, estimations tended to use computing time estimates, but
+ more modern approaches try to estimate cost of guessing a passphrase.
+
+ As an example, I will try to get an estimate from the numbers in
+ https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a270c40 This
+ thing costs 23kUSD and does 68Ghashes/sec for SHA1. This is in 2017.
+
+ Incidentally, my older calculation for a machine around 1000 times
+ slower was off by a factor of about 1000, but in the right direction,
+ i.e. I estimated the attack to be too easy. Nobody noticed ;-) On the
+ plus side, the tables are now (2017) pretty much accurate.
+
+ More references can be found at the end of this document. Note that
+ these are estimates from the defender side, so assuming something is
+ easier than it actually is fine. An attacker may still have
+ significantly higher cost than estimated here.
+
+ LUKS1 used SHA1 (since version 1.7.0 it uses SHA256) for hashing per
+ default. We will leave aside the check whether a try actually decrypts
+ a key-slot. I will assume a useful lifetime of the hardware of 2 years.
+ (This is on the low side.) Disregarding downtime, the machine can then
+ break
+```
+ N = 68*10^9 * 3600 * 24 * 365 * 2 ~ 4*10^18
+```
+ passphrases for EUR/USD 23k. That is one 62 bit passphrase hashed once
+ with SHA1 for EUR/USD 23k. This can be parallelized, it can be done
+ faster than 2 years with several of these machines.
+
+ For LUKS2, things look a bit better, as the advantage of using graphics
+ cards is massively reduced. Using the recommendations below should
+ hence be fine for LUKS2 as well and give a better security margin.
+
+ For plain dm-crypt (no hash iteration) this is it. This gives (with
+ SHA1, plain dm-crypt default is ripemd160 which seems to be slightly
+ slower than SHA1):
+```
+ Passphrase entropy Cost to break
+ 60 bit EUR/USD 6k
+ 65 bit EUR/USD 200K
+ 70 bit EUR/USD 6M
+ 75 bit EUR/USD 200M
+ 80 bit EUR/USD 6B
+ 85 bit EUR/USD 200B
+ ... ...
+```
+
+ For LUKS1, you have to take into account hash iteration in PBKDF2.
+ For a current CPU, there are about 100k iterations (as can be queried
+ with ''cryptsetup luksDump''.
+
+ The table above then becomes:
+```
+ Passphrase entropy Cost to break
+ 50 bit EUR/USD 600k
+ 55 bit EUR/USD 20M
+ 60 bit EUR/USD 600M
+ 65 bit EUR/USD 20B
+ 70 bit EUR/USD 600B
+ 75 bit EUR/USD 20T
+ ... ...
+```
+
+ Recommendation:
+
+ To get reasonable security for the next 10 years, it is a good idea
+ to overestimate by a factor of at least 1000.
+
+ Then there is the question of how much the attacker is willing to spend.
+ That is up to your own security evaluation. For general use, I will
+ assume the attacker is willing to spend up to 1 million EUR/USD. Then
+ we get the following recommendations:
+
+ Plain dm-crypt: Use > 80 bit. That is e.g. 17 random chars from a-z
+ or a random English sentence of > 135 characters length.
+
+ LUKS1 and LUKS2: Use > 65 bit. That is e.g. 14 random chars from a-z
+ or a random English sentence of > 108 characters length.
+
+ If paranoid, add at least 20 bit. That is roughly four additional
+ characters for random passphrases and roughly 32 characters for a
+ random English sentence.
+
+
+ * **5.2 Is LUKS insecure? Everybody can see I have encrypted data!**
+
+ In practice it does not really matter. In most civilized countries you
+ can just refuse to hand over the keys, no harm done. In some countries
+ they can force you to hand over the keys if they suspect encryption.
+ The suspicion is enough, they do not have to prove anything. This is
+ for practical reasons, as even the presence of a header (like the LUKS
+ header) is not enough to prove that you have any keys. It might have
+ been an experiment, for example. Or it was used as encrypted swap with
+ a key from /dev/random. So they make you prove you do not have
+ encrypted data. Of course, if true, that is impossible and hence the
+ whole idea is not compatible with fair laws. Note that in this context,
+ countries like the US or the UK are not civilized and do not have fair
+ laws.
+
+ As a side-note, standards for biometrics (fingerprint, retina,
+ vein-pattern, etc.) are often different and much lower. If you put
+ your LUKS passphrase into a device that can be unlocked using biometrics,
+ they may force a biometric sample in many countries where they could not
+ force you to give them a passphrase you solely have in your memory and
+ can claim to have forgotten if needed (it happens). If you need protection
+ on this level, make sure you know what the respective legal situation is,
+ also while traveling, and make sure you decide beforehand what you
+ will do if push comes to shove as they will definitely put you under
+ as much pressure as they can legally apply.
+
+ This means that if you have a large set of random-looking data, they can
+ already lock you up. Hidden containers (encryption hidden within
+ encryption), as possible with Truecrypt, do not help either. They will
+ just assume the hidden container is there and unless you hand over the
+ key, you will stay locked up. Don't have a hidden container? Tough
+ luck. Anybody could claim that.
+
+ Still, if you are concerned about the LUKS header, use plain dm-crypt
+ with a good passphrase. See also Section 2, "What is the difference
+ between "plain" and LUKS format?"
+
+
+ * **5.3 Should I initialize (overwrite) a new LUKS/dm-crypt partition?**
+
+ If you just create a filesystem on it, most of the old data will still
+ be there. If the old data is sensitive, you should overwrite it before
+ encrypting. In any case, not initializing will leave the old data there
+ until the specific sector gets written. That may enable an attacker to
+ determine how much and where on the partition data was written. If you
+ think this is a risk, you can prevent this by overwriting the encrypted
+ device (here assumed to be named "e1") with zeros like this:
+```
+ dd_rescue -w /dev/zero /dev/mapper/e1
+```
+ or alternatively with one of the following more standard commands:
+```
+ cat /dev/zero > /dev/mapper/e1
+ dd if=/dev/zero of=/dev/mapper/e1
+```
+
+
+ * **5.4 How do I securely erase a LUKS container?**
+
+ For LUKS, if you are in a desperate hurry, overwrite the LUKS header and
+ key-slot area. For LUKS1 and LUKS2, just be generous and overwrite the
+ first 100MB. A single overwrite with zeros should be enough. If you
+ anticipate being in a desperate hurry, prepare the command beforehand.
+ Example with /dev/sde1 as the LUKS partition and default parameters:
+```
+ head -c 100000000 /dev/zero > /dev/sde1; sync
+```
+ A LUKS header backup or full backup will still grant access to most or
+ all data, so make sure that an attacker does not have access to backups
+ or destroy them as well.
+
+ Also note that SSDs and also some HDDs (SMR and hybrid HDDs, for
+ example) may not actually overwrite the header and only do that an
+ unspecified and possibly very long time later. The only way to be sure
+ there is physical destruction. If the situation permits, do both
+ overwrite and physical destruction.
+
+ If you have time, overwrite the whole drive with a single pass of random
+ data. This is enough for most HDDs. For SSDs or FLASH (USB sticks) or
+ SMR or hybrid drives, you may want to overwrite the whole drive several
+ times to be sure data is not retained. This is possibly still insecure
+ as the respective technologies are not fully understood in this regard.
+ Still, due to the anti-forensic properties of the LUKS key-slots, a
+ single overwrite could be enough. If in doubt, use physical destruction
+ in addition. Here is a link to some current research results on erasing
+ SSDs and FLASH drives:
+ https://www.usenix.org/events/fast11/tech/full_papers/Wei.pdf
+
+ Keep in mind to also erase all backups.
+
+ Example for a random-overwrite erase of partition sde1 done with
+ dd_rescue:
+```
+ dd_rescue -w /dev/urandom /dev/sde1
+```
+
+
+ * **5.5 How do I securely erase a backup of a LUKS partition or header?**
+
+ That depends on the medium it is stored on. For HDD and SSD, use
+ overwrite with random data. For an SSD, FLASH drive (USB stick) hybrid
+ HDD or SMR HDD, you may want to overwrite the complete drive several
+ times and use physical destruction in addition, see last item. For
+ re-writable CD/DVD, a single overwrite should be enough, due to the
+ anti-forensic properties of the LUKS keyslots. For write-once media,
+ use physical destruction. For low security requirements, just cut the
+ CD/DVD into several parts. For high security needs, shred or burn the
+ medium.
+
+ If your backup is on magnetic tape, I advise physical destruction by
+ shredding or burning, after (!) overwriting. The problem with magnetic
+ tape is that it has a higher dynamic range than HDDs and older data may
+ well be recoverable after overwrites. Also write-head alignment issues
+ can lead to data not actually being deleted during overwrites.
+
+ The best option is to actually encrypt the backup, for example with
+ PGP/GnuPG and then just destroy all copies of the encryption key if
+ needed. Best keep them on paper, as that has excellent durability and
+ secure destruction is easy, for example by burning and then crushing the
+ ashes to a fine powder. A blender and water also works nicely.
+
+
+ * **5.6 What about backup? Does it compromise security?**
+
+ That depends. See item 6.7.
+
+
+ * **5.7 Why is all my data permanently gone if I overwrite the LUKS header?**
+
+ Overwriting the LUKS header in part or in full is the most common reason
+ why access to LUKS containers is lost permanently. Overwriting can be
+ done in a number of fashions, like creating a new filesystem on the raw
+ LUKS partition, making the raw partition part of a RAID array and just
+ writing to the raw partition.
+
+ The LUKS1 header contains a 256 bit "salt" per key-slot and without that
+ no decryption is possible. While the salts are not secret, they are
+ key-grade material and cannot be reconstructed. This is a
+ cryptographically strong "cannot". From observations on the cryptsetup
+ mailing-list, people typically go though the usual stages of grief
+ (Denial, Anger, Bargaining, Depression, Acceptance) when this happens to
+ them. Observed times vary between 1 day and 2 weeks to complete the
+ cycle. Seeking help on the mailing-list is fine. Even if we usually
+ cannot help with getting back your data, most people found the feedback
+ comforting.
+
+ If your header does not contain an intact key-slot salt, best go
+ directly to the last stage ("Acceptance") and think about what to do
+ now. There is one exception that I know of: If your LUKS1 container is
+ still open, then it may be possible to extract the volume key from the
+ running system. See Item "How do I recover the volume key from a mapped
+ LUKS1 container?" in Section "Backup and Data Recovery".
+
+ For LUKS2, things are both better and worse. First, the salts are in a
+ less vulnerable position now. But, on the other hand, the keys of a
+ mapped (open) container are now stored in the kernel key-store, and
+ while there probably is some way to get them out of there, I am not sure
+ how much effort that needs.
+
+
+ * **5.8 What is a "salt"?**
+
+ A salt is a random key-grade value added to the passphrase before it is
+ processed. It is not kept secret. The reason for using salts is as
+ follows: If an attacker wants to crack the password for a single LUKS
+ container, then every possible passphrase has to be tried. Typically an
+ attacker will not try every binary value, but will try words and
+ sentences from a dictionary.
+
+ If an attacker wants to attack several LUKS containers with the same
+ dictionary, then a different approach makes sense: Compute the resulting
+ slot-key for each dictionary element and store it on disk. Then the
+ test for each entry is just the slow unlocking with the slot key (say
+ 0.00001 sec) instead of calculating the slot-key first (1 sec). For a
+ single attack, this does not help. But if you have more than one
+ container to attack, this helps tremendously, also because you can
+ prepare your table before you even have the container to attack! The
+ calculation is also very simple to parallelize. You could, for example,
+ use the night-time unused CPU power of your desktop PCs for this.
+
+ This is where the salt comes in. If the salt is combined with the
+ passphrase (in the simplest form, just appended to it), you suddenly
+ need a separate table for each salt value. With a reasonably-sized salt
+ value (256 bit, e.g.) this is quite infeasible.
+
+
+ * **5.9 Is LUKS secure with a low-entropy (bad) passphrase?**
+
+ Short answer: yes. Do not use a low-entropy passphrase.
+
+ Note: For LUKS2, protection for bad passphrases is a bit better
+ due to the use of Argon2, but that is only a gradual improvement.
+
+ Longer answer:
+ This needs a bit of theory. The quality of your passphrase is directly
+ related to its entropy (information theoretic, not thermodynamic). The
+ entropy says how many bits of "uncertainty" or "randomness" are in you
+ passphrase. In other words, that is how difficult guessing the
+ passphrase is.
+
+ Example: A random English sentence has about 1 bit of entropy per
+ character. A random lowercase (or uppercase) character has about 4.7
+ bit of entropy.
+
+ Now, if n is the number of bits of entropy in your passphrase and t
+ is the time it takes to process a passphrase in order to open the
+ LUKS container, then an attacker has to spend at maximum
+```
+ attack_time_max = 2^n * t
+```
+ time for a successful attack and on average half that. There is no way
+ getting around that relationship. However, there is one thing that does
+ help, namely increasing t, the time it takes to use a passphrase, see
+ next FAQ item.
+
+ Still, if you want good security, a high-entropy passphrase is the only
+ option. For example, a low-entropy passphrase can never be considered
+ secure against a TLA-level (Three Letter Agency level, i.e.
+ government-level) attacker, no matter what tricks are used in the
+ key-derivation function. Use at least 64 bits for secret stuff. That
+ is 64 characters of English text (but only if randomly chosen) or a
+ combination of 12 truly random letters and digits.
+
+ For passphrase generation, do not use lines from very well-known texts
+ (religious texts, Harry Potter, etc.) as they are too easy to guess.
+ For example, the total Harry Potter has about 1'500'000 words (my
+ estimation). Trying every 64 character sequence starting and ending at
+ a word boundary would take only something like 20 days on a single CPU
+ and is entirely feasible. To put that into perspective, using a number
+ of Amazon EC2 High-CPU Extra Large instances (each gives about 8 real
+ cores), this test costs currently about 50USD/EUR, but can be made to
+ run arbitrarily fast.
+
+ On the other hand, choosing 1.5 lines from, say, the Wheel of Time, is
+ in itself not more secure, but the book selection adds quite a bit of
+ entropy. (Now that I have mentioned it here, don't use tWoT either!) If
+ you add 2 or 3 typos and switch some words around, then this is good
+ passphrase material.
+
+
+ * **5.10 What is "iteration count" and why is decreasing it a bad idea?**
+
+ LUKS1:
+ Iteration count is the number of PBKDF2 iterations a passphrase is put
+ through before it is used to unlock a key-slot. Iterations are done
+ with the explicit purpose to increase the time that it takes to unlock a
+ key-slot. This provides some protection against use of low-entropy
+ passphrases.
+
+ The idea is that an attacker has to try all possible passphrases. Even
+ if the attacker knows the passphrase is low-entropy (see last item), it
+ is possible to make each individual try take longer. The way to do this
+ is to repeatedly hash the passphrase for a certain time. The attacker
+ then has to spend the same time (given the same computing power) as the
+ user per try. With LUKS1, the default is 1 second of PBKDF2 hashing.
+
+ Example 1: Lets assume we have a really bad passphrase (e.g. a
+ girlfriends name) with 10 bits of entropy. With the same CPU, an
+ attacker would need to spend around 500 seconds on average to break that
+ passphrase. Without iteration, it would be more like 0.0001 seconds on
+ a modern CPU.
+
+ Example 2: The user did a bit better and has 32 chars of English text.
+ That would be about 32 bits of entropy. With 1 second iteration, that
+ means an attacker on the same CPU needs around 136 years. That is
+ pretty impressive for such a weak passphrase. Without the iterations,
+ it would be more like 50 days on a modern CPU, and possibly far less.
+
+ In addition, the attacker can both parallelize and use special hardware
+ like GPUs or FPGAs to speed up the attack. The attack can also happen
+ quite some time after the luksFormat operation and CPUs can have become
+ faster and cheaper. For that reason you want a bit of extra security.
+ Anyways, in Example 1 your are screwed. In example 2, not necessarily.
+ Even if the attack is faster, it still has a certain cost associated
+ with it, say 10000 EUR/USD with iteration and 1 EUR/USD without
+ iteration. The first can be prohibitively expensive, while the second
+ is something you try even without solid proof that the decryption will
+ yield something useful.
+
+ The numbers above are mostly made up, but show the idea. Of course the
+ best thing is to have a high-entropy passphrase.
+
+ Would a 100 sec iteration time be even better? Yes and no.
+ Cryptographically it would be a lot better, namely 100 times better.
+ However, usability is a very important factor for security technology
+ and one that gets overlooked surprisingly often. For LUKS, if you have
+ to wait 2 minutes to unlock the LUKS container, most people will not
+ bother and use less secure storage instead. It is better to have less
+ protection against low-entropy passphrases and people actually use LUKS,
+ than having them do without encryption altogether.
+
+ Now, what about decreasing the iteration time? This is generally a very
+ bad idea, unless you know and can enforce that the users only use
+ high-entropy passphrases. If you decrease the iteration time without
+ ensuring that, then you put your users at increased risk, and
+ considering how rarely LUKS containers are unlocked in a typical
+ work-flow, you do so without a good reason. Don't do it. The iteration
+ time is already low enough that users with low entropy passphrases are
+ vulnerable. Lowering it even further increases this danger
+ significantly.
+
+ LUKS2: Pretty much the same reasoning applies. The advantages of using
+ GPUs or FPGAs in an attack have been significantly reduced, but that
+ is the only main difference.
+
+
+ * **5.11 Some people say PBKDF2 is insecure?**
+
+ There is some discussion that a hash-function should have a "large
+ memory" property, i.e. that it should require a lot of memory to be
+ computed. This serves to prevent attacks using special programmable
+ circuits, like FPGAs, and attacks using graphics cards. PBKDF2 does not
+ need a lot of memory and is vulnerable to these attacks. However, the
+ publication usually referred in these discussions is not very convincing
+ in proving that the presented hash really is "large memory" (that may
+ change, email the FAQ maintainer when it does) and it is of limited
+ usefulness anyways. Attackers that use clusters of normal PCs will not
+ be affected at all by a "large memory" property. For example the US
+ Secret Service is known to use the off-hour time of all the office PCs
+ of the Treasury for password breaking. The Treasury has about 110'000
+ employees. Assuming every one has an office PC, that is significant
+ computing power, all of it with plenty of memory for computing "large
+ memory" hashes. Bot-net operators also have all the memory they want.
+ The only protection against a resourceful attacker is a high-entropy
+ passphrase, see items 5.9 and 5.10.
+
+ That said, LUKS2 defaults to Argon2, which has a large-memory property
+ and massively reduces the advantages of GPUs and FPGAs.
+
+
+ * **5.12 What about iteration count with plain dm-crypt?**
+
+ Simple: There is none. There is also no salting. If you use plain
+ dm-crypt, the only way to be secure is to use a high entropy passphrase.
+ If in doubt, use LUKS instead.
+
+
+ * **5.13 Is LUKS with default parameters less secure on a slow CPU?**
+
+ Unfortunately, yes. However the only aspect affected is the protection
+ for low-entropy passphrase or volume-key. All other security aspects
+ are independent of CPU speed.
+
+ The volume key is less critical, as you really have to work at it to
+ give it low entropy. One possibility to mess this up is to supply the
+ volume key yourself. If that key is low-entropy, then you get what you
+ deserve. The other known possibility to create a LUKS container with a
+ bad volume key is to use /dev/urandom for key generation in an
+ entropy-starved situation (e.g. automatic installation on an embedded
+ device without network and other entropy sources or installation in a VM
+ under certain circumstances).
+
+ For the passphrase, don't use a low-entropy passphrase. If your
+ passphrase is good, then a slow CPU will not matter. If you insist on a
+ low-entropy passphrase on a slow CPU, use something like
+ "--iter-time=10000" or higher and wait a long time on each LUKS unlock
+ and pray that the attacker does not find out in which way exactly your
+ passphrase is low entropy. This also applies to low-entropy passphrases
+ on fast CPUs. Technology can do only so much to compensate for problems
+ in front of the keyboard.
+
+ Also note that power-saving modes will make your CPU slower. This will
+ reduce iteration count on LUKS container creation. It will keep unlock
+ times at the expected values though at this CPU speed.
+
+
+ * **5.14 Why was the default aes-cbc-plain replaced with aes-cbc-essiv?**
+
+ Note: This item applies both to plain dm-crypt and to LUKS
+
+ The problem is that cbc-plain has a fingerprint vulnerability, where a
+ specially crafted file placed into the crypto-container can be
+ recognized from the outside. The issue here is that for cbc-plain the
+ initialization vector (IV) is the sector number. The IV gets XORed to
+ the first data chunk of the sector to be encrypted. If you make sure
+ that the first data block to be stored in a sector contains the sector
+ number as well, the first data block to be encrypted is all zeros and
+ always encrypted to the same ciphertext. This also works if the first
+ data chunk just has a constant XOR with the sector number. By having
+ several shifted patterns you can take care of the case of a
+ non-power-of-two start sector number of the file.
+
+ This mechanism allows you to create a pattern of sectors that have the
+ same first ciphertext block and signal one bit per sector to the
+ outside, allowing you to e.g. mark media files that way for recognition
+ without decryption. For large files this is a practical attack. For
+ small ones, you do not have enough blocks to signal and take care of
+ different file starting offsets.
+
+ In order to prevent this attack, the default was changed to cbc-essiv.
+ ESSIV uses a keyed hash of the sector number, with the encryption key as
+ key. This makes the IV unpredictable without knowing the encryption key
+ and the watermarking attack fails.
+
+
+ * **5.15 Are there any problems with "plain" IV? What is "plain64"?**
+
+ First, "plain" and "plain64" are both not secure to use with CBC, see
+ previous FAQ item.
+
+ However there are modes, like XTS, that are secure with "plain" IV. The
+ next limit is that "plain" is 64 bit, with the upper 32 bit set to zero.
+ This means that on volumes larger than 2TiB, the IV repeats, creating a
+ vulnerability that potentially leaks some data. To avoid this, use
+ "plain64", which uses the full sector number up to 64 bit. Note that
+ "plain64" requires a kernel 2.6.33 or more recent. Also note that
+ "plain64" is backwards compatible for volume sizes of maximum size 2TiB,
+ but not for those > 2TiB. Finally, "plain64" does not cause any
+ performance penalty compared to "plain".
+
+
+ * **5.16 What about XTS mode?**
+
+ XTS mode is potentially even more secure than cbc-essiv (but only if
+ cbc-essiv is insecure in your scenario). It is a NIST standard and
+ used, e.g. in Truecrypt. From version 1.6.0 of cryptsetup onwards,
+ aes-xts-plain64 is the default for LUKS. If you want to use it with a
+ cryptsetup before version 1.6.0 or with plain dm-crypt, you have to
+ specify it manually as "aes-xts-plain", i.e.
+```
+ cryptsetup -c aes-xts-plain luksFormat <device>
+```
+ For volumes >2TiB and kernels >= 2.6.33 use "plain64" (see FAQ item
+ on "plain" and "plain64"):
+```
+ cryptsetup -c aes-xts-plain64 luksFormat <device>
+```
+ There is a potential security issue with XTS mode and large blocks.
+ LUKS and dm-crypt always use 512B blocks and the issue does not apply.
+
+
+ * **5.17 Is LUKS FIPS-140-2 certified?**
+
+ No. But that is more a problem of FIPS-140-2 than of LUKS. From a
+ technical point-of-view, LUKS with the right parameters would be
+ FIPS-140-2 compliant, but in order to make it certified, somebody has to
+ pay real money for that. And then, whenever cryptsetup is changed or
+ extended, the certification lapses and has to be obtained again.
+
+ From the aspect of actual security, LUKS with default parameters should
+ be as good as most things that are FIPS-140-2 certified, although you
+ may want to make sure to use /dev/random (by specifying --use-random on
+ luksFormat) as randomness source for the volume key to avoid being
+ potentially insecure in an entropy-starved situation.
+
+
+ * **5.18 What about Plausible Deniability?**
+
+ First let me attempt a definition for the case of encrypted filesystems:
+ Plausible deniability is when you store data inside an encrypted
+ container and it is not possible to prove it is there without having a
+ special passphrase. And at the same time it must be "plausible" that
+ there actually is no hidden data there.
+
+ As a simple entropy-analysis will show that here may be data there, the
+ second part is what makes it tricky.
+
+ There seem to be a lot of misunderstandings about this idea, so let me
+ make it clear that this refers to the situation where the attackers can
+ prove that there is data that either may be random or may be part of a
+ plausible-deniability scheme, they just cannot prove which one it is.
+ Hence a plausible-deniability scheme must hold up when the attackers
+ know there is something potentially fishy. If you just hide data and
+ rely on it not being found, that is just simple deniability, not
+ "plausible" deniability and I am not talking about that in the
+ following. Simple deniability against a low-competence attacker may be
+ as simple as renaming a file or putting data into an unused part of a
+ disk. Simple deniability against a high-skill attacker with time to
+ invest is usually pointless unless you go for advanced steganographic
+ techniques, which have their own drawbacks, such as low data capacity.
+
+ Now, the idea of plausible deniability is compelling and on a first
+ glance it seems possible to do it. And from a cryptographic point of
+ view, it actually is possible.
+
+ So, does the idea work in practice? No, unfortunately. The reasoning
+ used by its proponents is fundamentally flawed in several ways and the
+ cryptographic properties fail fatally when colliding with the real
+ world.
+
+ First, why should "I do not have a hidden partition" be any more
+ plausible than "I forgot my crypto key" or "I wiped that partition with
+ random data, nothing in there"? I do not see any reason.
+
+ Second, there are two types of situations: Either they cannot force you
+ to give them the key (then you simply do not) or they can. In the
+ second case, they can always do bad things to you, because they cannot
+ prove that you have the key in the first place! This means they do not
+ have to prove you have the key, or that this random looking data on your
+ disk is actually encrypted data. So the situation will allow them to
+ waterboard/lock-up/deport you anyways, regardless of how "plausible"
+ your deniability is. Do not have a hidden partition you could show to
+ them, but there are indications you may? Too bad for you.
+ Unfortunately "plausible deniability" also means you cannot prove there
+ is no hidden data.
+
+ Third, hidden partitions are not that hidden. There are basically just
+ two possibilities: a) Make a large crypto container, but put a smaller
+ filesystem in there and put the hidden partition into the free space.
+ Unfortunately this is glaringly obvious and can be detected in an
+ automated fashion. This means that the initial suspicion to put you
+ under duress in order to make you reveal your hidden data is given. b)
+ Make a filesystem that spans the whole encrypted partition, and put the
+ hidden partition into space not currently used by that filesystem.
+ Unfortunately that is also glaringly obvious, as you then cannot write
+ to the filesystem without a high risk of destroying data in the hidden
+ container. Have not written anything to the encrypted filesystem in a
+ while? Too bad, they have the suspicion they need to do unpleasant
+ things to you.
+
+ To be fair, if you prepare option b) carefully and directly before going
+ into danger, it may work. But then, the mere presence of encrypted data
+ may already be enough to get you into trouble in those places were they
+ can demand encryption keys.
+
+ Here is an additional reference for some problems with plausible
+ deniability:
+ https://www.schneier.com/academic/paperfiles/paper-truecrypt-dfs.pdf
+ I strongly suggest you read it.
+
+ So, no, I will not provide any instructions on how to do it with plain
+ dm-crypt or LUKS. If you insist on shooting yourself in the foot, you
+ can figure out how to do it yourself.
+
+
+ * **5.19 What about SSDs, Flash, Hybrid and SMR Drives?**
+
+ The problem is that you cannot reliably erase parts of these devices,
+ mainly due to wear-leveling and possibly defect management and delayed
+ writes to the main data area.
+
+ For example for SSDs, when overwriting a sector, what the device does is
+ to move an internal sector (may be 128kB or even larger) to some pool of
+ discarded, not-yet erased unused sectors, take a fresh empty sector from
+ the empty-sector pool and copy the old sector over with the changes to
+ the small part you wrote. This is done in some fashion so that larger
+ writes do not cause a lot of small internal updates.
+
+ The thing is that the mappings between outside-addressable sectors and
+ inside sectors is arbitrary (and the vendors are not talking). Also the
+ discarded sectors are not necessarily erased immediately. They may
+ linger a long time.
+
+ For plain dm-crypt, the consequences are that older encrypted data may
+ be lying around in some internal pools of the device. Thus may or may
+ not be a problem and depends on the application. Remember the same can
+ happen with a filesystem if consecutive writes to the same area of a
+ file can go to different sectors.
+
+ However, for LUKS, the worst case is that key-slots and LUKS header may
+ end up in these internal pools. This means that password management
+ functionality is compromised (the old passwords may still be around,
+ potentially for a very long time) and that fast erase by overwriting the
+ header and key-slot area is insecure.
+
+ Also keep in mind that the discarded/used pool may be large. For
+ example, a 240GB SSD has about 16GB of spare area in the chips that it
+ is free to do with as it likes. You would need to make each individual
+ key-slot larger than that to allow reliable overwriting. And that
+ assumes the disk thinks all other space is in use. Reading the internal
+ pools using forensic tools is not that hard, but may involve some
+ soldering.
+
+ What to do?
+
+ If you trust the device vendor (you probably should not...) you can try
+ an ATA "secure erase" command. That is not present in USB keys though
+ and may or may not be secure for a hybrid drive.
+
+ If you can do without password management and are fine with doing
+ physical destruction for permanently deleting data (always after one or
+ several full overwrites!), you can use plain dm-crypt.
+
+ If you want or need all the original LUKS security features to work, you
+ can use a detached LUKS header and put that on a conventional, magnetic
+ disk. That leaves potentially old encrypted data in the pools on the
+ main disk, but otherwise you get LUKS with the same security as on a
+ traditional magnetic disk. Note however that storage vendors are prone
+ to lying to their customers. For example, it recently came out that
+ HDDs sold without any warning or mentioning in the data-sheets were
+ actually using SMR and that will write data first to a faster area and
+ only overwrite the original data area some time later when things are
+ quiet.
+
+ If you are concerned about your laptop being stolen, you are likely fine
+ using LUKS on an SSD or hybrid drive. An attacker would need to have
+ access to an old passphrase (and the key-slot for this old passphrase
+ would actually need to still be somewhere in the SSD) for your data to
+ be at risk. So unless you pasted your old passphrase all over the
+ Internet or the attacker has knowledge of it from some other source and
+ does a targeted laptop theft to get at your data, you should be fine.
+
+
+ * **5.20 LUKS1 is broken! It uses SHA-1!**
+
+ No, it is not. SHA-1 is (academically) broken for finding collisions,
+ but not for using it in a key-derivation function. And that collision
+ vulnerability is for non-iterated use only. And you need the hash-value
+ in verbatim.
+
+ This basically means that if you already have a slot-key, and you have
+ set the PBKDF2 iteration count to 1 (it is > 10'000 normally), you could
+ (maybe) derive a different passphrase that gives you the same slot-key.
+ But if you have the slot-key, you can already unlock the key-slot and
+ get the volume key, breaking everything. So basically, this SHA-1
+ vulnerability allows you to open a LUKS1 container with high effort when
+ you already have it open.
+
+ The real problem here is people that do not understand crypto and claim
+ things are broken just because some mechanism is used that has been
+ broken for a specific different use. The way the mechanism is used
+ matters very much. A hash that is broken for one use can be completely
+ secure for other uses and here it is.
+
+ Since version 1.7.0, cryptsetup uses SHA-256 as default to ensure that
+ it will be compatible in the future. There are already some systems
+ where SHA-1 is completely phased out or disabled by a security policy.
+
+
+ * **5.21 Why is there no "Nuke-Option"?**
+
+ A "Nuke-Option" or "Kill-switch" is a password that when entered upon
+ unlocking instead wipes the header and all passwords. So when somebody
+ forces you to enter your password, you can destroy the data instead.
+
+ While this sounds attractive at first glance, it does not make sense
+ once a real security analysis is done. One problem is that you have to
+ have some kind of HSM (Hardware Security Module) in order to implement
+ it securely. In the movies, a HSM starts to smoke and melt once the
+ Nuke-Option has been activated. In actual reality, it just wipes some
+ battery-backed RAM cells. A proper HSM costs something like
+ 20'000...100'000 EUR/USD and there a Nuke-Option may make some sense.
+ BTW, a chipcard or a TPM is not a HSM, although some vendors are
+ promoting that myth.
+
+ Now, a proper HSMs will have a wipe option but not a Nuke-Option, i.e.
+ you can explicitly wipe the HSM, but by a different process than
+ unlocking it takes. Why is that? Simple: If somebody can force you to
+ reveal passwords, then they can also do bad things to you if you do not
+ or if you enter a nuke password instead. Think locking you up for a few
+ years for "destroying evidence" or for far longer and without trial for
+ being a "terrorist suspect". No HSM maker will want to expose its
+ customers to that risk.
+
+ Now think of the typical LUKS application scenario, i.e. disk
+ encryption. Usually the ones forcing you to hand over your password
+ will have access to the disk as well, and, if they have any real
+ suspicion, they will mirror your disk before entering anything supplied
+ by you. This neatly negates any Nuke-Option. If they have no suspicion
+ (just harassing people that cross some border for example), the
+ Nuke-Option would work, but see above about likely negative consequences
+ and remember that a Nuke-Option may not work reliably on SSD and hybrid
+ drives anyways.
+
+ Hence my advice is to never take data that you do not want to reveal
+ into any such situation in the first place. There is no need to
+ transfer data on physical carriers today. The Internet makes it quite
+ possible to transfer data between arbitrary places and modern encryption
+ makes it secure. If you do it right, nobody will even be able to
+ identify source or destination. (How to do that is out of scope of this
+ document. It does require advanced skills in this age of pervasive
+ surveillance.)
+
+ Hence, LUKS has no kill option because it would do much more harm than
+ good.
+
+ Still, if you have a good use-case (i.e. non-abstract real-world
+ situation) where a Nuke-Option would actually be beneficial, please let
+ me know.
+
+
+ * **5.22 Does cryptsetup open network connections to websites, etc. ?**
+
+ This question seems not to make much sense at first glance, but here is
+ an example form the real world: The TrueCrypt GUI has a "Donation"
+ button. Press it, and a web-connection to the TrueCrypt website is
+ opened via the default browser, telling everybody that listens that you
+ use TrueCrypt. In the worst case, things like this can get people
+ tortured or killed.
+
+ So: Cryptsetup will never open any network connections except the
+ local netlink socket it needs to talk to the kernel crypto API.
+
+ In addition, the installation package should contain all documentation,
+ including this FAQ, so that you do not have to go to a web-site to read
+ it. (If your distro cuts the docu, please complain to them.) In
+ security software, any connection initiated to anywhere outside your
+ machine should always be the result of an explicit request for such a
+ connection by the user and cryptsetup will stay true to that principle.
+
+
+ * **5.23 What is cryptsetup CVE-2021-4122?**
+
+ CVE-2021-4122 describes a possible attack against data confidentiality
+ through LUKS2 online reencryption extension crash recovery.
+
+ An attacker can modify on-disk metadata to simulate decryption in
+ progress with crashed (unfinished) reencryption step and persistently
+ decrypt part of the LUKS device.
+
+ This attack requires repeated physical access to the LUKS device but
+ no knowledge of user passphrases.
+
+ The decryption step is performed after a valid user activates
+ the device with a correct passphrase and modified metadata.
+ There are no visible warnings for the user that such recovery happened
+ (except using the luksDump command). The attack can also be reversed
+ afterward (simulating crashed encryption from a plaintext) with
+ possible modification of revealed plaintext.
+
+ The problem was fixed in cryptsetup version 2.4.3 and 2.3.7.
+
+ For more info, please see the report here:
+ https://seclists.org/oss-sec/2022/q1/34
+
+
+# 6. Backup and Data Recovery
+
+
+ * **6.1 Why do I need Backup?**
+
+ First, disks die. The rate for well-treated (!) disk is about 5% per
+ year, which is high enough to worry about. There is some indication
+ that this may be even worse for some SSDs. This applies both to LUKS
+ and plain dm-crypt partitions.
+
+ Second, for LUKS, if anything damages the LUKS header or the key-stripe
+ area then decrypting the LUKS device can become impossible. This is a
+ frequent occurrence. For example an accidental format as FAT or some
+ software overwriting the first sector where it suspects a partition boot
+ sector typically makes a LUKS1 partition permanently inaccessible. See
+ more below on LUKS header damage.
+
+ So, data-backup in some form is non-optional. For LUKS, you may also
+ want to store a header backup in some secure location. This only needs
+ an update if you change passphrases.
+
+
+ * **6.2 How do I backup a LUKS header?**
+
+ While you could just copy the appropriate number of bytes from the start
+ of the LUKS partition, the best way is to use command option
+ "luksHeaderBackup" of cryptsetup. This protects also against errors
+ when non-standard parameters have been used in LUKS partition creation.
+ Example:
+```
+ cryptsetup luksHeaderBackup --header-backup-file <file> <device>
+```
+ To restore, use the inverse command, i.e.
+```
+ cryptsetup luksHeaderRestore --header-backup-file <file> <device>
+```
+ If you are unsure about a header to be restored, make a backup of the
+ current one first! You can also test the header-file without restoring
+ it by using the --header option for a detached header like this:
+```
+ cryptsetup --header <file> luksOpen <device> </dev/mapper/name>
+```
+ If that unlocks your key-slot, you are good. Do not forget to close
+ the device again.
+
+ Under some circumstances (damaged header), this fails. Then use the
+ following steps in case it is LUKS1:
+
+ First determine the volume (volume) key size:
+```
+ cryptsetup luksDump <device>
+```
+ gives a line of the form
+```
+ MK bits: <bits>
+```
+ with bits equal to 256 for the old defaults and 512 for the new
+ defaults. 256 bits equals a total header size of 1'052'672 Bytes and
+ 512 bits one of 2MiB. (See also Item 6.12) If luksDump fails, assume
+ 2MiB, but be aware that if you restore that, you may also restore the
+ first 1M or so of the filesystem. Do not change the filesystem if you
+ were unable to determine the header size! With that, restoring a
+ too-large header backup is still safe.
+
+ Second, dump the header to file. There are many ways to do it, I
+ prefer the following:
+```
+ head -c 1052672 <device> > header_backup.dmp
+```
+ or
+```
+ head -c 2M <device> > header_backup.dmp
+```
+ for a 2MiB header. Verify the size of the dump-file to be sure.
+
+ To restore such a backup, you can try luksHeaderRestore or do a more
+ basic
+```
+ cat header_backup.dmp > <device>
+```
+
+
+ * **6.3 How do I test for a LUKS header?**
+
+ Use
+```
+ cryptsetup -v isLuks <device>
+```
+ on the device. Without the "-v" it just signals its result via
+ exit-status. You can also use the more general test
+```
+ blkid -p <device>
+```
+ which will also detect other types and give some more info. Omit
+ "-p" for old versions of blkid that do not support it.
+
+
+ * **6.4 How do I backup a LUKS or dm-crypt partition?**
+
+ There are two options, a sector-image and a plain file or filesystem
+ backup of the contents of the partition. The sector image is already
+ encrypted, but cannot be compressed and contains all empty space. The
+ filesystem backup can be compressed, can contain only part of the
+ encrypted device, but needs to be encrypted separately if so desired.
+
+ A sector-image will contain the whole partition in encrypted form, for
+ LUKS the LUKS header, the keys-slots and the data area. It can be done
+ under Linux e.g. with dd_rescue (for a direct image copy) and with
+ "cat" or "dd". Examples:
+```
+ cat /dev/sda10 > sda10.img
+ dd_rescue /dev/sda10 sda10.img
+```
+ You can also use any other backup software that is capable of making a
+ sector image of a partition. Note that compression is ineffective for
+ encrypted data, hence it does not make sense to use it.
+
+ For a filesystem backup, you decrypt and mount the encrypted partition
+ and back it up as you would a normal filesystem. In this case the
+ backup is not encrypted, unless your encryption method does that. For
+ example you can encrypt a backup with "tar" as follows with GnuPG:
+```
+ tar cjf - <path> | gpg --cipher-algo AES -c - > backup.tbz2.gpg
+```
+ And verify the backup like this if you are at "path":
+```
+ cat backup.tbz2.gpg | gpg - | tar djf -
+```
+ Note: Always verify backups, especially encrypted ones!
+
+ There is one problem with verifying like this: The kernel may still have
+ some files cached and in fact verify them against RAM or may even verify
+ RAM against RAM, which defeats the purpose of the exercise. The
+ following command empties the kernel caches:
+```
+ echo 3 > /proc/sys/vm/drop_caches
+```
+ Run it after backup and before verify.
+
+ In both cases GnuPG will ask you interactively for your symmetric key.
+ The verify will only output errors. Use "tar dvjf -" to get all
+ comparison results. To make sure no data is written to disk
+ unencrypted, turn off swap if it is not encrypted before doing the
+ backup.
+
+ Restore works like certification with the 'd' ('difference') replaced
+ by 'x' ('eXtract'). Refer to the man-page of tar for more explanations
+ and instructions. Note that with default options tar will overwrite
+ already existing files without warning. If you are unsure about how
+ to use tar, experiment with it in a location where you cannot do damage.
+
+ You can of course use different or no compression and you can use an
+ asymmetric key if you have one and have a backup of the secret key that
+ belongs to it.
+
+ A second option for a filesystem-level backup that can be used when the
+ backup is also on local disk (e.g. an external USB drive) is to use a
+ LUKS container there and copy the files to be backed up between both
+ mounted containers. Also see next item.
+
+
+ * **6.5 Do I need a backup of the full partition? Would the header and key-slots not be enough?**
+
+ Backup protects you against two things: Disk loss or corruption and user
+ error. By far the most questions on the dm-crypt mailing list about how
+ to recover a damaged LUKS partition are related to user error. For
+ example, if you create a new filesystem on a non-mapped LUKS container,
+ chances are good that all data is lost permanently.
+
+ For this case, a header+key-slot backup would often be enough. But keep
+ in mind that a well-treated (!) HDD has roughly a failure risk of 5% per
+ year. It is highly advisable to have a complete backup to protect
+ against this case.
+
+
+ * **6.6 What do I need to backup if I use "decrypt_derived"?**
+
+ This is a script in Debian, intended for mounting /tmp or swap with a
+ key derived from the volume key of an already decrypted device. If you
+ use this for an device with data that should be persistent, you need to
+ make sure you either do not lose access to that volume key or have a
+ backup of the data. If you derive from a LUKS device, a header backup
+ of that device would cover backing up the volume key. Keep in mind that
+ this does not protect against disk loss.
+
+ Note: If you recreate the LUKS header of the device you derive from
+ (using luksFormat), the volume key changes even if you use the same
+ passphrase(s) and you will not be able to decrypt the derived device
+ with the new LUKS header.
+
+
+ * **6.7 Does a backup compromise security?**
+
+ Depends on how you do it. However if you do not have one, you are going
+ to eventually lose your encrypted data.
+
+ There are risks introduced by backups. For example if you
+ change/disable a key-slot in LUKS, a binary backup of the partition will
+ still have the old key-slot. To deal with this, you have to be able to
+ change the key-slot on the backup as well, securely erase the backup or
+ do a filesystem-level backup instead of a binary one.
+
+ If you use dm-crypt, backup is simpler: As there is no key management,
+ the main risk is that you cannot wipe the backup when wiping the
+ original. However wiping the original for dm-crypt should consist of
+ forgetting the passphrase and that you can do without actual access to
+ the backup.
+
+ In both cases, there is an additional (usually small) risk with binary
+ backups: An attacker can see how many sectors and which ones have been
+ changed since the backup. To prevent this, use a filesystem level
+ backup method that encrypts the whole backup in one go, e.g. as
+ described above with tar and GnuPG.
+
+ My personal advice is to use one USB disk (low value data) or three
+ disks (high value data) in rotating order for backups, and either use
+ independent LUKS partitions on them, or use encrypted backup with tar
+ and GnuPG.
+
+ If you do network-backup or tape-backup, I strongly recommend to go
+ the filesystem backup path with independent encryption, as you
+ typically cannot reliably delete data in these scenarios, especially
+ in a cloud setting. (Well, you can burn the tape if it is under your
+ control...)
+
+
+ * **6.8 What happens if I overwrite the start of a LUKS partition or damage the LUKS header or key-slots?**
+
+ There are two critical components for decryption: The salt values in the
+ key-slot descriptors of the header and the key-slots. For LUKS2 they
+ are a bit better protected. but for LUKS1, these are right in the first
+ sector. If the salt values are overwritten or changed, nothing (in the
+ cryptographically strong sense) can be done to access the data, unless
+ there is a backup of the LUKS header. If a key-slot is damaged, the
+ data can still be read with a different key-slot, if there is a
+ remaining undamaged and used key-slot. Note that in order to make a
+ key-slot completely unrecoverable, changing about 4-6 bits in random
+ locations of its 128kiB size is quite enough.
+
+
+ * **6.9 What happens if I (quick) format a LUKS partition?**
+
+ I have not tried the different ways to do this, but very likely you will
+ have written a new boot-sector, which in turn overwrites the LUKS
+ header, including the salts, making your data permanently irretrievable,
+ unless you have a LUKS header backup. For LUKS2 this may still be
+ recoverable without that header backup, for LUKS1 it is not. You may
+ also damage the key-slots in part or in full. See also last item.
+
+
+ * **6.10 How do I recover the volume key from a mapped LUKS1 container?**
+
+ Note: LUKS2 uses the kernel keyring to store keys and hence this
+ procedure does not work unless you have explicitly disabled the use of
+ the keyring with "--disable-keyring" on opening.
+
+ This is typically only needed if you managed to damage your LUKS1
+ header, but the container is still mapped, i.e. "luksOpen"ed. It also
+ helps if you have a mapped container that you forgot or do not know a
+ passphrase for (e.g. on a long running server.)
+
+ WARNING: Things go wrong, do a full backup before trying this!
+
+ WARNING: This exposes the volume key of the LUKS1 container. Note that
+ both ways to recreate a LUKS header with the old volume key described
+ below will write the volume key to disk. Unless you are sure you have
+ securely erased it afterwards, e.g. by writing it to an encrypted
+ partition, RAM disk or by erasing the filesystem you wrote it to by a
+ complete overwrite, you should change the volume key afterwards.
+ Changing the volume key requires a full data backup, luksFormat and then
+ restore of the backup. Alternatively the tool cryptsetup-reencrypt from
+ the cryptsetup package can be used to change the volume key (see its
+ man-page), but a full backup is still highly recommended.
+
+ First, there is a script by Milan that automates the whole process,
+ except generating a new LUKS1 header with the old volume key (it prints
+ the command for that though):
+
+ https://gitlab.com/cryptsetup/cryptsetup/blob/main/misc/luks-header-from-active
+
+ You can also do this manually. Here is how:
+
+ - Get the volume key from the device mapper. This is done by the
+ following command. Substitute c5 for whatever you mapped to:
+```
+ # dmsetup table --target crypt --showkey /dev/mapper/c5
+
+ Result:
+ 0 200704 crypt aes-cbc-essiv:sha256
+ a1704d9715f73a1bb4db581dcacadaf405e700d591e93e2eaade13ba653d0d09
+ 0 7:0 4096
+```
+ The result is actually one line, wrapped here for clarity. The long
+ hex string is the volume key.
+
+ - Convert the volume key to a binary file representation. You can do
+ this manually, e.g. with hexedit. You can also use the tool "xxd"
+ from vim like this:
+```
+ echo "a1704d9....53d0d09" | xxd -r -p > <volume-key-file>
+```
+
+ - Do a luksFormat to create a new LUKS1 header.
+
+ NOTE: If your header is intact and you just forgot the passphrase,
+ you can just set a new passphrase, see next sub-item.
+
+ Unmap the device before you do that (luksClose). Then do
+```
+ cryptsetup luksFormat --volume-key-file=<volume-key-file> <luks device>
+```
+ Note that if the container was created with other than the default
+ settings of the cryptsetup version you are using, you need to give
+ additional parameters specifying the deviations. If in doubt, try the
+ script by Milan. It does recover the other parameters as well.
+
+ Side note: This is the way the decrypt_derived script gets at the volume
+ key. It just omits the conversion and hashes the volume key string.
+
+ - If the header is intact and you just forgot the passphrase, just
+ set a new passphrase like this:
+```
+ cryptsetup luksAddKey --volume-key-file=<volume-key-file> <luks device>
+```
+ You may want to disable the old one afterwards.
+
+
+ * **6.11 What does the on-disk structure of dm-crypt look like?**
+
+ There is none. dm-crypt takes a block device and gives encrypted access
+ to each of its blocks with a key derived from the passphrase given. If
+ you use a cipher different than the default, you have to specify that as
+ a parameter to cryptsetup too. If you want to change the password, you
+ basically have to create a second encrypted device with the new
+ passphrase and copy your data over. On the plus side, if you
+ accidentally overwrite any part of a dm-crypt device, the damage will be
+ limited to the area you overwrote.
+
+
+ * **6.12 What does the on-disk structure of LUKS1 look like?**
+
+ Note: For LUKS2, refer to the LUKS2 document referenced in Item 1.2
+
+ A LUKS1 partition consists of a header, followed by 8 key-slot
+ descriptors, followed by 8 key slots, followed by the encrypted data
+ area.
+
+ Header and key-slot descriptors fill the first 592 bytes. The key-slot
+ size depends on the creation parameters, namely on the number of
+ anti-forensic stripes, key material offset and volume key size.
+
+ With the default parameters, each key-slot is a bit less than 128kiB in
+ size. Due to sector alignment of the key-slot start, that means the key
+ block 0 is at offset 0x1000-0x20400, key block 1 at offset
+ 0x21000-0x40400, and key block 7 at offset 0xc1000-0xe0400. The space
+ to the next full sector address is padded with zeros. Never used
+ key-slots are filled with what the disk originally contained there, a
+ key-slot removed with "luksRemoveKey" or "luksKillSlot" gets filled with
+ 0xff. Due to 2MiB default alignment, start of the data area for
+ cryptsetup 1.3 and later is at 2MiB, i.e. at 0x200000. For older
+ versions, it is at 0x101000, i.e. at 1'052'672 bytes, i.e. at 1MiB +
+ 4096 bytes from the start of the partition. Incidentally,
+ "luksHeaderBackup" for a LUKS container created with default parameters
+ dumps exactly the first 2MiB (or 1'052'672 bytes for headers created
+ with cryptsetup versions < 1.3) to file and "luksHeaderRestore" restores
+ them.
+
+ For non-default parameters, you have to figure out placement yourself.
+ "luksDump" helps. See also next item. For the most common non-default
+ settings, namely aes-xts-plain with 512 bit key, the offsets are: 1st
+ keyslot 0x1000-0x3f800, 2nd keyslot 0x40000-0x7e000, 3rd keyslot
+ 0x7e000-0xbd800, ..., and start of bulk data at 0x200000.
+
+ The exact specification of the format is here:
+ https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification
+
+ For your convenience, here is the LUKS1 header with hex offsets.
+ NOTE:
+ The spec counts key-slots from 1 to 8, but the cryptsetup tool counts
+ from 0 to 7. The numbers here refer to the cryptsetup numbers.
+
+```
+Refers to LUKS1 On-Disk Format Specification Version 1.2.3
+
+LUKS1 header:
+
+offset length name data type description
+-----------------------------------------------------------------------
+0x0000 0x06 magic byte[] 'L','U','K','S', 0xba, 0xbe
+ 0 6
+0x0006 0x02 version uint16_t LUKS version
+ 6 3
+0x0008 0x20 cipher-name char[] cipher name spec.
+ 8 32
+0x0028 0x20 cipher-mode char[] cipher mode spec.
+ 40 32
+0x0048 0x20 hash-spec char[] hash spec.
+ 72 32
+0x0068 0x04 payload-offset uint32_t bulk data offset in sectors
+ 104 4 (512 bytes per sector)
+0x006c 0x04 key-bytes uint32_t number of bytes in key
+ 108 4
+0x0070 0x14 mk-digest byte[] volume key checksum
+ 112 20 calculated with PBKDF2
+0x0084 0x20 mk-digest-salt byte[] salt for PBKDF2 when
+ 132 32 calculating mk-digest
+0x00a4 0x04 mk-digest-iter uint32_t iteration count for PBKDF2
+ 164 4 when calculating mk-digest
+0x00a8 0x28 uuid char[] partition UUID
+ 168 40
+0x00d0 0x30 key-slot-0 key slot key slot 0
+ 208 48
+0x0100 0x30 key-slot-1 key slot key slot 1
+ 256 48
+0x0130 0x30 key-slot-2 key slot key slot 2
+ 304 48
+0x0160 0x30 key-slot-3 key slot key slot 3
+ 352 48
+0x0190 0x30 key-slot-4 key slot key slot 4
+ 400 48
+0x01c0 0x30 key-slot-5 key slot key slot 5
+ 448 48
+0x01f0 0x30 key-slot-6 key slot key slot 6
+ 496 48
+0x0220 0x30 key-slot-7 key slot key slot 7
+ 544 48
+
+
+Key slot:
+
+offset length name data type description
+-------------------------------------------------------------------------
+0x0000 0x04 active uint32_t key slot enabled/disabled
+ 0 4
+0x0004 0x04 iterations uint32_t PBKDF2 iteration count
+ 4 4
+0x0008 0x20 salt byte[] PBKDF2 salt
+ 8 32
+0x0028 0x04 key-material-offset uint32_t key start sector
+ 40 4 (512 bytes/sector)
+0x002c 0x04 stripes uint32_t number of anti-forensic
+ 44 4 stripes
+```
+
+
+ * **6.13 What is the smallest possible LUKS1 container?**
+
+ Note: From cryptsetup 1.3 onwards, alignment is set to 1MB. With modern
+ Linux partitioning tools that also align to 1MB, this will result in
+ alignment to 2k sectors and typical Flash/SSD sectors, which is highly
+ desirable for a number of reasons. Changing the alignment is not
+ recommended.
+
+ That said, with default parameters, the data area starts at exactly 2MB
+ offset (at 0x101000 for cryptsetup versions before 1.3). The smallest
+ data area you can have is one sector of 512 bytes. Data areas of 0
+ bytes can be created, but fail on mapping.
+
+ While you cannot put a filesystem into something this small, it may
+ still be used to contain, for example, key. Note that with current
+ formatting tools, a partition for a container this size will be 3MiB
+ anyways. If you put the LUKS container into a file (via losetup and a
+ loopback device), the file needs to be 2097664 bytes in size, i.e. 2MiB
+ + 512B.
+
+ The two ways to influence the start of the data area are key-size and
+ alignment.
+
+ For alignment, you can go down to 1 on the parameter. This will still
+ leave you with a data-area starting at 0x101000, i.e. 1MiB+4096B
+ (default parameters) as alignment will be rounded up to the next
+ multiple of 8 (i.e. 4096 bytes) If in doubt, do a dry-run on a larger
+ file and dump the LUKS header to get actual information.
+
+ For key-size, you can use 128 bit (e.g. AES-128 with CBC), 256 bit
+ (e.g. AES-256 with CBC) or 512 bit (e.g. AES-256 with XTS mode). You
+ can do 64 bit (e.g. blowfish-64 with CBC), but anything below 128 bit
+ has to be considered insecure today.
+
+ Example 1 - AES 128 bit with CBC:
+```
+ cryptsetup luksFormat -s 128 --align-payload=8 <device>
+```
+ This results in a data offset of 0x81000, i.e. 516KiB or 528384
+ bytes. Add one 512 byte sector and the smallest LUKS container size
+ with these parameters is 516KiB + 512B or 528896 bytes.
+
+ Example 2 - Blowfish 64 bit with CBC (WARNING: insecure):
+```
+ cryptsetup luksFormat -c blowfish -s 64 --align-payload=8 /dev/loop0
+```
+ This results in a data offset of 0x41000, i.e. 260kiB or 266240
+ bytes, with a minimal LUKS1 container size of 260kiB + 512B or 266752
+ bytes.
+
+
+ * **6.14 I think this is overly complicated. Is there an alternative?**
+
+ Not really. Encryption comes at a price. You can use plain dm-crypt to
+ simplify things a bit. It does not allow multiple passphrases, but on
+ the plus side, it has zero on disk description and if you overwrite some
+ part of a plain dm-crypt partition, exactly the overwritten parts are
+ lost (rounded up to full sectors).
+
+ * **6.15 Can I clone a LUKS container?**
+
+ You can, but it breaks security, because the cloned container has the
+ same header and hence the same volume key. Even if you change the
+ passphrase(s), the volume key stays the same. That means whoever has
+ access to one of the clones can decrypt them all, completely bypassing
+ the passphrases.
+
+ While you can use cryptsetup-reencrypt to change the volume key,
+ this is probably more effort than to create separate LUKS containers
+ in the first place.
+
+ The right way to do this is to first luksFormat the target container,
+ then to clone the contents of the source container, with both containers
+ mapped, i.e. decrypted. You can clone the decrypted contents of a LUKS
+ container in binary mode, although you may run into secondary issues
+ with GUIDs in filesystems, partition tables, RAID-components and the
+ like. These are just the normal problems binary cloning causes.
+
+ Note that if you need to ship (e.g.) cloned LUKS containers with a
+ default passphrase, that is fine as long as each container was
+ individually created (and hence has its own volume key). In this case,
+ changing the default passphrase will make it secure again.
+
+ * **6.16 How to convert the printed volume key to a raw one?**
+ A volume key printed via something like:
+```
+ cryptsetup --dump-volume-key luksDump /dev/<device> >volume-key
+```
+(i.e. without using `--volume-key-file`), which gives something like:
+```
+LUKS header information for /dev/<device>
+Cipher name: aes
+Cipher mode: xts-plain64
+Payload offset: 32768
+UUID: 6e914442-e8b5-4eb5-98c4-5bf0cf17ecad
+MK bits: 512
+MK dump: e0 3f 15 c2 0f e5 80 ab 35 b4 10 03 ae 30 b9 5d
+ 4c 0d 28 9e 1b 0f e3 b0 50 57 ef d4 4d 53 a0 12
+ b7 4e 43 a1 20 7e c5 02 1f f1 f5 08 04 3c f5 20
+ a6 0b 23 f6 7b 53 55 aa 22 d8 aa 02 e0 2f d5 04
+```
+can be converted to the raw volume key for example via:
+```
+ sed -E -n '/^MK dump:\t/,/^[^\t]/{0,/^MK dump:\t/s/^MK dump://; /^([^\t].*)?$/q; s/\t+//p;};' volume-key | xxd -r -p
+```
+
+
+
+
+# 7. Interoperability with other Disk Encryption Tools
+
+
+ * **7.1 What is this section about?**
+
+ Cryptsetup for plain dm-crypt can be used to access a number of on-disk
+ formats created by tools like loop-aes patched into losetup. This
+ sometimes works and sometimes does not. This section collects insights
+ into what works, what does not and where more information is required.
+
+ Additional information may be found in the mailing-list archives,
+ mentioned at the start of this FAQ document. If you have a solution
+ working that is not yet documented here and think a wider audience may
+ be interested, please email the FAQ maintainer.
+
+
+ * **7.2 loop-aes: General observations.**
+
+ One problem is that there are different versions of losetup around.
+ loop-aes is a patch for losetup. Possible problems and deviations
+ from cryptsetup option syntax include:
+
+ - Offsets specified in bytes (cryptsetup: 512 byte sectors)
+
+ - The need to specify an IV offset
+
+ - Encryption mode needs specifying (e.g. "-c twofish-cbc-plain")
+
+ - Key size needs specifying (e.g. "-s 128" for 128 bit keys)
+
+ - Passphrase hash algorithm needs specifying
+
+ Also note that because plain dm-crypt and loop-aes format does not have
+ metadata, and while the loopAES extension for cryptsetup tries
+ autodetection (see command loopaesOpen), it may not always work. If you
+ still have the old set-up, using a verbosity option (-v) on mapping with
+ the old tool or having a look into the system logs after setup could
+ give you the information you need. Below, there are also some things
+ that worked for somebody.
+
+
+ * **7.3 loop-aes patched into losetup on Debian 5.x, kernel 2.6.32**
+
+ In this case, the main problem seems to be that this variant of
+ losetup takes the offset (-o option) in bytes, while cryptsetup takes
+ it in sectors of 512 bytes each.
+
+ Example: The losetup command
+```
+ losetup -e twofish -o 2560 /dev/loop0 /dev/sdb1
+ mount /dev/loop0 mount-point
+```
+ translates to
+```
+ cryptsetup create -c twofish -o 5 --skip 5 e1 /dev/sdb1
+ mount /dev/mapper/e1 mount-point
+```
+
+
+ * **7.4 loop-aes with 160 bit key**
+
+ This seems to be sometimes used with twofish and blowfish and represents
+ a 160 bit ripemed160 hash output padded to 196 bit key length. It seems
+ the corresponding options for cryptsetup are
+```
+ --cipher twofish-cbc-null -s 192 -h ripemd160:20
+```
+
+
+ * **7.5 loop-aes v1 format OpenSUSE**
+
+ Apparently this is done by older OpenSUSE distros and stopped working
+ from OpenSUSE 12.1 to 12.2. One user had success with the following:
+```
+ cryptsetup create <target> <device> -c aes -s 128 -h sha256
+```
+
+
+ * **7.6 Kernel encrypted loop device (cryptoloop)**
+
+ There are a number of different losetup implementations for using
+ encrypted loop devices so getting this to work may need a bit of
+ experimentation.
+
+ NOTE: Do NOT use this for new containers! Some of the existing
+ implementations are insecure and future support is uncertain.
+
+ Example for a compatible mapping:
+```
+ losetup -e twofish -N /dev/loop0 /image.img
+```
+ translates to
+```
+ cryptsetup create image_plain /image.img -c twofish-cbc-plain -H plain
+```
+ with the mapping being done to /dev/mapper/image_plain instead of
+ to /dev/loop0.
+
+ More details:
+
+ Cipher, mode and password hash (or no hash):
+```
+ -e cipher [-N] => -c cipher-cbc-plain -H plain [-s 256]
+ -e cipher => -c cipher-cbc-plain -H ripemd160 [-s 256]
+```
+
+ Key size and offsets (losetup: bytes, cryptsetuop: sectors of 512 bytes):
+```
+ -k 128 => -s 128
+ -o 2560 => -o 5 -p 5 # 2560/512 = 5
+```
+
+ There is no replacement for --pass-fd, it has to be emulated using
+ keyfiles, see the cryptsetup man-page.
+
+
+# 8. Issues with Specific Versions of cryptsetup
+
+
+ * **8.1 When using the create command for plain dm-crypt with cryptsetup 1.1.x, the mapping is incompatible and my data is not accessible anymore!**
+
+ With cryptsetup 1.1.x, the distro maintainer can define different
+ default encryption modes. You can check the compiled-in defaults using
+ "cryptsetup --help". Moreover, the plain device default changed because
+ the old IV mode was vulnerable to a watermarking attack.
+
+ If you are using a plain device and you need a compatible mode, just
+ specify cipher, key size and hash algorithm explicitly. For
+ compatibility with cryptsetup 1.0.x defaults, simple use the following:
+```
+ cryptsetup create -c aes-cbc-plain -s 256 -h ripemd160 <name> <dev>
+```
+ LUKS stores cipher and mode in the metadata on disk, avoiding this
+ problem.
+
+
+ * **8.2 cryptsetup on SLED 10 has problems...**
+
+ SLED 10 is missing an essential kernel patch for dm-crypt, which is
+ broken in its kernel as a result. There may be a very old version of
+ cryptsetup (1.0.x) provided by SLED, which should also not be used
+ anymore as well. My advice would be to drop SLED 10.
+
+
+ * **8.3 Gcrypt 1.6.x and later break Whirlpool**
+
+ It is the other way round: In gcrypt 1.5.x, Whirlpool is broken and it
+ was fixed in 1.6.0 and later. If you selected whirlpool as hash on
+ creation of a LUKS container, it does not work anymore with the fixed
+ library. This shows one serious risk of using rarely used settings.
+
+ Note that at the time this FAQ item was written, 1.5.4 was the latest
+ 1.5.x version and it has the flaw, i.e. works with the old Whirlpool
+ version. Possibly later 1.5.x versions will work as well. If not,
+ please let me know.
+
+ The only two ways to access older LUKS containers created with Whirlpool
+ are to either decrypt with an old gcrypt version that has the flaw or to
+ use a compatibility feature introduced in cryptsetup 1.6.4 and gcrypt
+ 1.6.1 or later. Version 1.6.0 cannot be used.
+
+ Steps:
+
+ - Make at least a header backup or better, refresh your full backup.
+ (You have a full backup, right? See Item 6.1 and following.)
+
+ - Make sure you have cryptsetup 1.6.4 or later and check the gcrypt
+ version:
+```
+ cryptsetup luksDump <your luks device> --debug | grep backend
+```
+ If gcrypt is at version 1.5.x or before:
+
+ - Reencrypt the LUKS header with a different hash. (Requires entering
+ all keyslot passphrases. If you do not have all, remove the ones you
+ do not have before.):
+```
+ cryptsetup-reencrypt --keep-key --hash sha256 <your luks device>
+```
+ If gcrypt is at version 1.6.1 or later:
+
+ - Patch the hash name in the LUKS header from "whirlpool" to
+ "whirlpool_gcryptbug". This activates the broken implementation.
+ The detailed header layout is in Item 6.12 of this FAQ and in the
+ LUKS on-disk format specification. One way to change the hash is
+ with the following command:
+```
+ echo -n -e 'whirlpool_gcryptbug\0' | dd of=<luks device> bs=1 seek=72 conv=notrunc
+```
+ - You can now open the device again. It is highly advisable to change
+ the hash now with cryptsetup-reencrypt as described above. While you
+ can reencrypt to use the fixed whirlpool, that may not be a good idea
+ as almost nobody seems to use it and hence the long time until the
+ bug was discovered.
+
+
+# 9. The Initrd question
+
+
+ * **9.1 My initrd is broken with cryptsetup**
+
+ That is not nice! However the initrd is supplied by your distribution,
+ not by the cryptsetup project and hence you should complain to them. We
+ cannot really do anything about it.
+
+
+ * **9.2 CVE-2016-4484 says cryptsetup is broken!**
+
+ Not really. It says the initrd in some Debian versions have a behavior
+ that under some very special and unusual conditions may be considered
+ a vulnerability.
+
+ What happens is that you can trick the initrd to go to a rescue-shell if
+ you enter the LUKS password wrongly in a specific way. But falling back
+ to a rescue shell on initrd errors is a sensible default behavior in the
+ first place. It gives you about as much access as booting a rescue
+ system from CD or USB-Stick or as removing the disk would give you. So
+ this only applies when an attacker has physical access, but cannot boot
+ anything else or remove the disk. These will be rare circumstances
+ indeed, and if you rely on the default distribution initrd to keep you
+ safe under these circumstances, then you have bigger problems than this
+ somewhat expected behavior.
+
+ The CVE was exaggerated and should not be assigned to upstream
+ cryptsetup in the first place (it is a distro specific initrd issue).
+ It was driven more by a try to make a splash for self-aggrandizement,
+ than by any actual security concerns. Ignore it.
+
+
+ * **9.3 How do I do my own initrd with cryptsetup?**
+
+ Note: The instructions here apply to an initrd in initramfs format, not
+ to an initrd in initrd format. The latter is a filesystem image, not a
+ cpio-archive, and seems to not be widely used anymore.
+
+ It depends on the distribution. Below, I give a very simple example and
+ step-by-step instructions for Debian. With a bit of work, it should be
+ possible to adapt this to other distributions. Note that the
+ description is pretty general, so if you want to do other things with an
+ initrd it provides a useful starting point for that too.
+
+ 01) Unpacking an existing initrd to use as template
+
+ A Linux initrd is in gzip'ed cpio format. To unpack it, use something
+ like this:
+```
+ mkdir tmp; cd tmp; cat ../initrd | gunzip | cpio -id
+```
+ After this, you have the full initrd content in tmp/
+
+ 02) Inspecting the init-script
+
+ The init-script is the only thing the kernel cares about. All activity
+ starts there. Its traditional location is /sbin/init on disk, but /init
+ in an initrd. In an initrd unpacked as above it is tmp/init.
+
+ While init can be a binary despite usually being called "init script",
+ in Debian the main init on the root partition is a binary, but the init
+ in the initrd (and only that one is called by the kernel) is a script
+ and starts like this:
+```
+ #!/bin/sh
+ ....
+```
+ The "sh" used here is in tmp/bin/sh as just unpacked, and in Debian it
+ currently is a busybox.
+
+ 03) Creating your own initrd
+
+ The two examples below should give you most of what is needed. This is
+ tested with LUKS1 and should work with LUKS2 as well. If not, please
+ let me know.
+
+ Here is a really minimal example. It does nothing but set up some
+ things and then drop to an interactive shell. It is perfect to try out
+ things that you want to go into the init-script.
+```
+ #!/bin/sh
+ export PATH=/sbin:/bin
+ [ -d /sys ] || mkdir /sys
+ [ -d /proc ] || mkdir /proc
+ [ -d /tmp ] || mkdir /tmp
+ mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
+ mount -t proc -o nodev,noexec,nosuid proc /proc
+ echo "initrd is running, starting BusyBox..."
+ exec /bin/sh --login
+```
+
+ Here is an example that opens the first LUKS-partition it finds with the
+ hard-coded password "test2" and then mounts it as root-filesystem. This
+ is intended to be used on an USB-stick that after boot goes into a safe,
+ as it contains the LUKS-passphrase in plain text and is not secure to be
+ left in the system. The script contains debug-output that should make it
+ easier to see what is going on. Note that the final hand-over to the init
+ on the encrypted root-partition is done by "exec switch_root /mnt/root
+ /sbin/init", after mounting the decrypted LUKS container with "mount
+ /dev/mapper/c1 /mnt/root". The second argument of switch_root is relative
+ to the first argument, i.e. the init started with this command is really
+ /mnt/sbin/init before switch_root runs.
+```
+ #!/bin/sh
+ export PATH=/sbin:/bin
+ [ -d /sys ] || mkdir /sys
+ [ -d /proc ] || mkdir /proc
+ [ -d /tmp ] || mkdir /tmp
+ mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
+ mount -t proc -o nodev,noexec,nosuid proc /proc
+ echo "detecting LUKS containers in sda1-10, sdb1-10"; sleep 1
+ for i in a b
+ do
+ for j in 1 2 3 4 5 6 7 8 9 10
+ do
+ sleep 0.5
+ d="/dev/sd"$i""$j
+ echo -n $d
+ cryptsetup isLuks $d >/dev/null 2>&1
+ r=$?
+ echo -n " result: "$r""
+ # 0 = is LUKS, 1 = is not LUKS, 4 = other error
+ if expr $r = 0 > /dev/null
+ then
+ echo " is LUKS, attempting unlock"
+ echo -n "test2" | cryptsetup luksOpen --key-file=- $d c1
+ r=$?
+ echo " result of unlock attempt: "$r""
+ sleep 2
+ if expr $r = 0 > /dev/null
+ then
+ echo "*** LUKS partition unlocked, switching root ***
+ echo " (waiting 30 seconds before doing that)"
+ mount /dev/mapper/c1 /mnt/root
+ sleep 30
+ exec switch_root /mnt/root /sbin/init
+ fi
+ else
+ echo " is not LUKS"
+ fi
+ done
+ done
+ echo "FAIL finding root on LUKS, loading BusyBox..."; sleep 5
+ exec /bin/sh --login
+```
+
+ 04) What if I want a binary in the initrd, but libraries are missing?
+
+ That is a bit tricky. One option is to compile statically, but that
+ does not work for everything. Debian puts some libraries into lib/ and
+ lib64/ which are usually enough. If you need more, you can add the
+ libraries you need there. That may or may not need a configuration
+ change for the dynamic linker "ld" as well. Refer to standard Linux
+ documentation on how to add a library to a Linux system. A running
+ initrd is just a running Linux system after all, it is not special in
+ any way.
+
+ 05) How do I repack the initrd?
+
+ Simply repack the changed directory. While in tmp/, do
+ the following:
+ ```
+ find . | cpio --create --format='newc' | gzip > ../new_initrd
+ ```
+ Rename "new_initrd" to however you want it called (the name of
+ the initrd is a kernel-parameter) and move to /boot. That is it.
+
+
+# 10. LUKS2 Questions
+
+
+ * **10.1 Is the cryptography of LUKS2 different?**
+
+ Mostly not. The header has changed in its structure, but the
+ cryptography is the same. The one exception is that PBKDF2 has been
+ replaced by Argon2 to give better resilience against attacks by
+ graphics cards and other hardware with lots of computing power but
+ limited local memory per computing element.
+
+
+ * **10.2 What new features does LUKS2 have?**
+
+ There are quite a few. I recommend reading the man-page and the on-disk
+ format specification, see Item 1.2.
+
+ To list just some:
+ - A lot of the metadata is JSON, allowing for easier extension
+ - Max 32 key-slots per default
+ - Better protection for bad passphrases now available with Argon2
+ - Authenticated encryption
+ - The LUKS2 header is less vulnerable to corruption and has a 2nd copy
+
+
+ * **10.3 Why does LUKS2 need so much memory?**
+
+ LUKS2 uses Argon2 instead of PBKDF2. That causes the increase in memory.
+ See next item.
+
+
+ * **10.4 Why use Argon2 in LUKS 2 instead of PBKDF2?**
+
+ LUKS tries to be secure with not-so-good passwords. Bad passwords need to
+ be protected in some way against an attacker that just tries all possible
+ combinations. (For good passwords, you can just wait for the attacker to
+ die of old age...) The situation with LUKS is not quite the same as with a
+ password stored in a database, but there are similarities.
+
+ LUKS does not store passwords on disk. Instead, the passwords are used to
+ decrypt the volume-key with it and that one is stored on disk in encrypted
+ form. If you have a good password, with, say, more than 80 bits of
+ entropy, you could just put the password through a single crypto-hash (to
+ turn it into something that can be used as a key) and that would be secure.
+ This is what plain dm-crypt does.
+
+ If the password has lower entropy, you want to make this process cost some
+ effort, so that each try takes time and resources and slows the attacker
+ down. LUKS1 uses PBKDF2 for that, adding an iteration count and a salt.
+ The iteration count is per default set to that it takes 1 second per try on
+ the CPU of the device where the respective passphrase was set. The salt is
+ there to prevent precomputation.
+
+ The problem with that is that if you use a graphics card, you can massively
+ speed up these computations as PBKDF2 needs very little memory to compute
+ it. A graphics card is (grossly simplified) a mass of small CPUs with some
+ small very fast local memory per CPU and a large slow memory (the 4/6/8 GB
+ a current card may have). If you can keep a computation in the small,
+ CPU-local memory, you can gain a speed factor of 1000 or more when trying
+ passwords with PBKDF2.
+
+ Argon2 was created to address this problem. It adds a "large memory
+ property" where computing the result with less memory than the memory
+ parameter requires is massively (exponentially) slowed down. That means,
+ if you set, for example, 4GB of memory, computing Argon2 on a graphics card
+ with around 100kB of memory per "CPU" makes no sense at all because it is
+ far too slow. An attacker has hence to use real CPUs and furthermore is
+ limited by main memory bandwidth.
+
+ Hence the large amount of memory used is a security feature and should not
+ be turned off or reduced. If you really (!) understand what you are doing
+ and can assure good passwords, you can either go back to PBKDF2 or set a
+ low amount of memory used for Argon2 when creating the header.
+
+
+ * **10.5 LUKS2 is insecure! It uses less memory than the Argon2 RFC say!**
+
+ Well, not really. The RFC recommends 6GiB of memory for use with disk
+ encryption. That is a bit insane and something clearly went wrong in the
+ standardization process here. First, that makes Argon2 unusable on any 32
+ bit Linux and that is clearly a bad thing. Second, there are many small
+ Linux devices around that do not have 6GiB of RAM in the first place. For
+ example, the current Raspberry Pi has 1GB, 2GB or 4GB of RAM, and with the
+ RFC recommendations, none of these could compute Argon2 hashes.
+
+ Hence LUKS2 uses a more real-world approach. Iteration is set to a
+ minimum of 4 because there are some theoretical attacks that work up to an
+ iteration count of 3. The thread parameter is set to 4. To achieve 2
+ second/slot unlock time, LUKS2 adjusts the memory parameter down if
+ needed. In the other direction, it will respect available memory and not
+ exceed it. On a current PC, the memory parameter will be somewhere around
+ 1GB, which should be quite generous. The minimum I was able to set in an
+ experiment with "-i 1" was 400kB of memory and that is too low to be
+ secure. A Raspberry Pi would probably end up somewhere around 50MB (have
+ not tried it) and that should still be plenty.
+
+ That said, if you have a good, high-entropy passphrase, LUKS2 is secure
+ with any memory parameter.
+
+
+ * **10.6 How does re-encryption store data while it is running?**
+
+ All metadata necessary to perform a recovery of said segment (in case of
+ crash) is stored in the LUKS2 metadata area. No matter if the LUKS2
+ reencryption was run in online or offline mode.
+
+
+ * **10.7 What do I do if re-encryption crashes?**
+
+ In case of a reencryption application crash, try to close the original
+ device via following command first:
+```
+ cryptsetup close <my_crypt_device>.
+```
+ Cryptsetup assesses if it's safe to teardown the reencryption device stack
+ or not. It will also cut off I/O (via dm-error mapping) to current
+ hotzone segment (to make later recovery possible). If it can't be torn
+ down, i.e. due to a mounted fs, you must unmount the filesystem first.
+ Never try to tear down reencryption dm devices manually using e.g.
+ dmsetup tool, at least not unless cryptsetup says it's safe to do so. It
+ could damage the data beyond repair.
+
+
+ * **10.8 Do I need to enter two passphrases to recover a crashed re-encryption?**
+
+ Cryptsetup (command line utility) expects the passphrases to be identical
+ for the keyslot containing old volume key and for the keyslot containing
+ new one. So the recovery happens during normal the "cryptsetup open"
+ operation or the equivalent during boot.
+
+ Re-encryption recovery can be also performed in offline mode by
+ the "cryptsetup repair" command.
+
+
+ * **10.9 What is an unbound keyslot and what is it used for?**
+
+ Quite simply, an 'unbound key' is an independent 'key' stored in a luks2
+ keyslot that cannot be used to unlock a LUKS2 data device. More specifically,
+ an 'unbound key' or 'unbound luks2 keyslot' contains a secret that is not
+ currently associated with any data/crypt segment (encrypted area) in the
+ LUKS2 'Segments' section (displayed by luksDump).
+
+ This is a bit of a more general idea. It basically allows one to use a
+ keyslot as a container for a key to be used in other things than decrypting
+ a data segment.
+
+ As of April 2020, the following uses are defined:
+
+ 1) LUKS2 re-encryption. The new volume key is stored in an unbound keyslot
+ which becomes a regular LUKS2 keyslot later when re-encryption is
+ finished.
+
+ 2) Somewhat similar is the use with a wrapped key scheme (e.g. with the
+ paes cipher). In this case, the VK (Volume Key) stored in a keyslot
+ is an encrypted binary binary blob. The KEK (Key Encryption Key) for
+ that blob may be refreshed (Note that this KEK is not managed by
+ cryptsetup!) and the binary blob gets changed. The KEK refresh process
+ uses an 'unbound keyslot'. First the future effective VK is placed
+ in the unbound keyslot and later it gets turned into the new real VK
+ (and bound to the respective crypt segment).
+
+
+ * **10.10 What about the size of the LUKS2 header**?
+
+ While the LUKS1 header has a fixed size that is determined by the cipher
+ spec (see Item 6.12), LUKS2 is more variable. The default size is 16MB,
+ but it can be adjusted on creation by using the --luks2-metadata-size
+ and --luks2-keyslots-size options. Refer to the man-page for details.
+ While adjusting the size in an existing LUKS2 container is possible,
+ it is somewhat complicated and risky. My advice is to do a backup,
+ recreate the container with changed parameters and restore that backup.
+
+
+ * **10.11 Does LUKS2 store metadata anywhere except in the header?**
+
+ It does not. But note that if you use the experimental integrity support,
+ there will be an integrity header as well at the start of the data area
+ and things get a bit more complicated. All metadata will still be at the
+ start of the device, nothing gets stored somewhere in the middle or at
+ the end.
+
+ * **10.12 What is a LUKS2 Token?**
+
+ A LUKS2 token is an object that describes "how to get a passphrase or
+ key" to unlock particular keyslot. A LUKS2 token is stored as json data
+ in the LUKS2 header. The token can be related to all keyslots or a
+ specific one. As the token is stored in JSON formay it is text by
+ default but binary data can be encoded into it according to the JSON
+ conventions.
+
+ Documentation on the last changes to LUKS2 tokens can be found in the
+ release notes. As of version 2.4 of cryptsetup, there are significant
+ features. The standard documentation for working with tokens is
+ in the luks2 reference available as PDF on the project page.
+
+
+# 11. References and Further Reading
+
+
+ * **Purpose of this Section**
+
+ The purpose of this section is to collect references to all materials
+ that do not fit the FAQ but are relevant in some fashion. This can be
+ core topics like the LUKS spec or disk encryption, but it can also be
+ more tangential, like secure storage management or cryptography used in
+ LUKS. It should still have relevance to cryptsetup and its
+ applications.
+
+ If you want to see something added here, send email to the maintainer
+ (or the cryptsetup mailing list) giving an URL, a description (1-3 lines
+ preferred) and a section to put it in. You can also propose new
+ sections.
+
+ At this time I would like to limit the references to things that are
+ available on the web.
+
+ * **Specifications**
+
+ - LUKS on-disk format spec: See Item 1.2
+
+ * **Other Documentation**
+
+ - Arch Linux on LUKS, LVM and full-disk encryption:
+ https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system
+
+ * **Code Examples**
+
+ - Some code examples are in the source package under docs/examples
+
+ - LUKS AF Splitter in Ruby by John Lane: https://rubygems.org/gems/afsplitter
+
+ * **Brute-forcing passphrases**
+
+ - http://news.electricalchemy.net/2009/10/password-cracking-in-cloud-part-5.html
+
+ - https://it.slashdot.org/story/12/12/05/0623215/new-25-gpu-monster-devours-strong-passwords-in-minutes
+
+ * **Tools**
+
+ * **SSD and Flash Disk Related**
+
+ * **Disk Encryption**
+
+ * **Attacks Against Disk Encryption**
+
+ * **Risk Management as Relevant for Disk Encryption**
+
+ * **Cryptography**
+
+ * **Secure Storage**
+
+
+# A. Contributors
+In no particular order:
+
+ - Arno Wagner
+
+ - Milan Broz
+
+___
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..fb7cb18
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,77 @@
+EXTRA_DIST = README.md COPYING.LGPL FAQ.md docs misc autogen.sh
+SUBDIRS = po tests tests/fuzz
+CLEANFILES =
+DISTCLEAN_TARGETS =
+
+AM_CPPFLAGS = \
+ -include config.h \
+ -I$(top_srcdir)/lib \
+ -DDATADIR=\""$(datadir)"\" \
+ -DLOCALEDIR=\""$(datadir)/locale"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DPREFIX=\""$(prefix)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DVERSION=\""$(VERSION)"\" \
+ -DEXTERNAL_LUKS2_TOKENS_PATH=\"${EXTERNAL_LUKS2_TOKENS_PATH}\"
+AM_CFLAGS = -Wall
+AM_CXXFLAGS = -Wall
+AM_LDFLAGS =
+
+if ENABLE_FUZZ_TARGETS
+AM_CFLAGS += -fsanitize=fuzzer-no-link
+AM_CXXFLAGS += -fsanitize=fuzzer-no-link
+endif
+
+LDADD = $(LTLIBINTL)
+
+tmpfilesddir = @DEFAULT_TMPFILESDIR@
+
+include_HEADERS =
+lib_LTLIBRARIES =
+noinst_LTLIBRARIES =
+sbin_PROGRAMS =
+man8_MANS =
+tmpfilesd_DATA =
+pkgconfig_DATA =
+dist_noinst_DATA =
+
+include man/Makemodule.am
+
+include scripts/Makemodule.am
+
+if CRYPTO_INTERNAL_ARGON2
+include lib/crypto_backend/argon2/Makemodule.am
+endif
+include lib/crypto_backend/Makemodule.am
+include lib/Makemodule.am
+
+include src/Makemodule.am
+include tokens/Makemodule.am
+
+ACLOCAL_AMFLAGS = -I m4
+
+DISTCHECK_CONFIGURE_FLAGS = \
+ --with-tmpfilesdir=$$dc_install_base/usr/lib/tmpfiles.d \
+ --enable-internal-argon2 --enable-internal-sse-argon2 \
+ --enable-external-tokens --enable-ssh-token --enable-asciidoc
+
+distclean-local:
+ -find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f
+ rm -rf autom4te.cache
+
+clean-local:
+ -rm -rf docs/doxygen_api_docs libargon2.la
+
+install-data-local:
+ $(MKDIR_P) -m 0755 $(DESTDIR)/${EXTERNAL_LUKS2_TOKENS_PATH}
+
+uninstall-local:
+ rmdir $(DESTDIR)/${EXTERNAL_LUKS2_TOKENS_PATH} 2>/dev/null || :
+
+check-programs: libcryptsetup.la
+ $(MAKE) -C tests $@
+
+if ENABLE_FUZZ_TARGETS
+fuzz-targets: libcryptsetup.la libcrypto_backend.la
+ $(MAKE) -C tests/fuzz $@
+endif
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..daec8f7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,148 @@
+![LUKS logo](https://gitlab.com/cryptsetup/cryptsetup/wikis/luks-logo.png)
+
+What the ...?
+=============
+**Cryptsetup** is an open-source utility used to conveniently set up disk encryption based
+on the [dm-crypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
+
+These formats are supported:
+ * **plain** volumes,
+ * **LUKS** volumes,
+ * **loop-AES**,
+ * **TrueCrypt** (including **VeraCrypt** extension),
+ * **BitLocker**, and
+ * **FileVault2**.
+
+The project also includes a **veritysetup** utility used to conveniently setup
+[dm-verity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity)
+block integrity checking kernel module and **integritysetup** to setup
+[dm-integrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity)
+block integrity kernel module.
+
+LUKS Design
+-----------
+**LUKS** is the standard for Linux disk encryption. By providing a standard on-disk format,
+it does not only facilitate compatibility among distributions, but also provides secure management
+of multiple user passwords. LUKS stores all necessary setup information in the partition header,
+enabling to transport or migrate data seamlessly.
+
+### Specification and documentation
+
+ * The latest version of the
+ [LUKS2 format specification](https://gitlab.com/cryptsetup/LUKS2-docs).
+ * The latest version of the
+ [LUKS1 format specification](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
+ * [Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
+ * [Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
+
+Download
+--------
+All release tarballs and release notes are hosted on
+[kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
+
+**The latest stable cryptsetup release version is 2.6.1**
+ * [cryptsetup-2.6.1.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.1.tar.xz)
+ * Signature [cryptsetup-2.6.1.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/cryptsetup-2.6.1.tar.sign)
+ _(You need to decompress file first to check signature.)_
+ * [Cryptsetup 2.6.1 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/v2.6.1-ReleaseNotes).
+
+Previous versions
+ * [Version 2.5.0](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/cryptsetup-2.5.0.tar.xz) -
+ [Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/cryptsetup-2.5.0.tar.sign) -
+ [Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/v2.5.0-ReleaseNotes).
+ * [Version 1.7.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz) -
+ [Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.sign) -
+ [Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.5-ReleaseNotes).
+
+Source and API documentation
+----------------------------
+For development version code, please refer to
+[source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page,
+mirror on [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) or
+[GitHub](https://github.com/mbroz/cryptsetup).
+
+For libcryptsetup documentation see
+[libcryptsetup API](https://mbroz.fedorapeople.org/libcryptsetup_API/) page.
+
+The libcryptsetup API/ABI changes are tracked in
+[compatibility report](https://abi-laboratory.pro/tracker/timeline/cryptsetup/).
+
+NLS PO files are maintained by
+[TranslationProject](https://translationproject.org/domain/cryptsetup.html).
+
+Required packages
+-----------------
+All distributions provide cryptsetup as distro package. If you need to compile cryptsetup yourself,
+some packages are required for compilation.
+Please always prefer distro specific build tools to manually configuring cryptsetup.
+
+Here is the list of packages needed for the compilation of project for particular distributions:
+
+**For Fedora**:
+```
+git gcc make autoconf automake gettext-devel pkgconfig openssl-devel popt-devel device-mapper-devel
+libuuid-devel json-c-devel libblkid-devel findutils libtool libssh-devel tar
+
+Optionally: libargon2-devel libpwquality-devel
+```
+To run the internal testsuite (make check) you also need to install
+```
+sharutils device-mapper jq vim-common expect keyutils netcat shadow-utils openssh-clients openssh sshpass
+```
+
+**For Debian and Ubuntu**:
+```
+git gcc make autoconf automake autopoint pkg-config libtool gettext libssl-dev libdevmapper-dev
+libpopt-dev uuid-dev libsepol1-dev libjson-c-dev libssh-dev libblkid-dev tar
+
+Optionally: libargon2-0-dev libpwquality-dev
+```
+To run the internal testsuite (make check) you also need to install
+```
+sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass
+```
+
+Note that the list could change as the distributions evolve.
+
+Compilation
+-----------
+The cryptsetup project uses **automake** and **autoconf** system to generate all needed files
+for compilation. If you check it from the git snapshot, use **./autogen.sh && ./configure && make**
+to compile the project. If you use downloaded released **tar.xz** archive, the configure script
+is already pre-generated (no need to run **autoconf.sh**).
+See **./configure --help** and use **--disable-[feature]** and **--enable-[feature]** options.
+
+For running the test suite that come with the project, type **make check**.
+Note that most tests will need root user privileges and run many dangerous storage fail simulations.
+Do **not** run tests with root privilege on production systems! Some tests will need scsi_debug
+kernel module to be available.
+
+For more details, please refer to [automake](https://www.gnu.org/software/automake/manual/automake.html)
+and [autoconf](https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf.html) manuals.
+
+Help!
+-----
+### Documentation
+Please read the following documentation before posting questions in the mailing list...
+You will be able to ask better questions and better understand the answers.
+
+* [Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions),
+* [LUKS Specifications](#specification-and-documentation), and
+* manuals (aka man page, man pages, man-page)
+
+The FAQ is online and in the source code for the project. The Specifications are referenced above
+in this document. The man pages are in source and should be available after installation using
+standard man commands, e.g. **man cryptsetup**.
+
+### Mailing List
+
+For cryptsetup and LUKS related questions, please use the cryptsetup mailing list
+[cryptsetup@lists.linux.dev](mailto:cryptsetup@lists.linux.dev),
+hosted at [kernel.org subspace](https://subspace.kernel.org/lists.linux.dev.html).
+To subscribe send an empty mail to
+[cryptsetup+subscribe@lists.linux.dev](mailto:cryptsetup+subscribe@lists.linux.dev).
+
+You can also browse and/or search the mailing [list archive](https://lore.kernel.org/cryptsetup/).
+News (NNTP), Atom feed and git access to public inbox is available through [lore.kernel.org](https://lore.kernel.org) service.
+
+The former dm-crypt [list archive](https://lore.kernel.org/dm-crypt/) is also available.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..3bca49f
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,10 @@
+# Reporting a Security Bug in cryptsetup project
+
+If you think you have discovered a security issue, please report it through
+the project issue tracker [New issue](https://gitlab.com/cryptsetup/cryptsetup/issues)
+as a confidential issue (select confidential checkbox).
+
+An alternative is to send PGP encrypted mail to the cryptsetup maintainer.
+Current maintainer is [Milan Broz](mailto:gmazyland@gmail.com), use PGP key
+with fingerprint 2A29 1824 3FDE 4664 8D06 86F9 D9B0 577B D93E 98FC.
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..c111f79
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+PKG_NAME="cryptsetup"
+
+DIE=0
+
+(autopoint --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have autopoint installed."
+ echo "Download the appropriate package for your distribution."
+ DIE=1
+}
+
+
+(msgfmt --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Warning**: You should have gettext installed."
+ echo "Download the appropriate package for your distribution."
+ echo "To disable translation, you can also use --disable-nls"
+ echo "configure option."
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have autoconf installed."
+ echo "Download the appropriate package for your distribution."
+ DIE=1
+}
+
+(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && {
+ (libtoolize --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have libtoolize installed."
+ echo "Download the appropriate package for your distribution."
+ DIE=1
+ }
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have automake installed."
+ echo "Download the appropriate package for your distribution."
+ DIE=1
+ NO_AUTOMAKE=yes
+}
+
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: Missing aclocal. The version of automake"
+ echo "installed doesn't appear recent enough."
+ DIE=1
+}
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+echo
+echo "Generate build-system by:"
+echo " autopoint: $(autopoint --version | head -1)"
+echo " aclocal: $(aclocal --version | head -1)"
+echo " autoconf: $(autoconf --version | head -1)"
+echo " automake: $(automake --version | head -1)"
+echo " libtoolize: $(libtoolize --version | head -1)"
+echo
+
+
+set -e
+autopoint --force $AP_OPTS
+libtoolize --force --copy
+aclocal -I m4 $AL_OPTS
+autoheader $AH_OPTS
+automake --force-missing --add-missing --copy --gnu $AM_OPTS
+autoconf $AC_OPTS
+
+echo
+echo "Now type '$srcdir/configure' and 'make' to compile."
+echo
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..ccf2112
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,773 @@
+AC_PREREQ([2.67])
+AC_INIT([cryptsetup],[2.6.1])
+
+dnl library version from <major>.<minor>.<release>[-<suffix>]
+LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
+LIBCRYPTSETUP_VERSION_INFO=21:0:9
+
+AM_SILENT_RULES([yes])
+AC_CONFIG_SRCDIR(src/cryptsetup.c)
+AC_CONFIG_MACRO_DIR([m4])
+
+AC_CONFIG_HEADERS([config.h:config.h.in])
+
+# We do not want to run test in parallel. Really.
+# http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html
+
+# For old automake use this
+#AM_INIT_AUTOMAKE(dist-xz subdir-objects)
+AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests subdir-objects foreign])
+
+if test "x$prefix" = "xNONE"; then
+ sysconfdir=/etc
+fi
+AC_PREFIX_DEFAULT(/usr)
+
+AC_CANONICAL_HOST
+AC_USE_SYSTEM_EXTENSIONS
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CPP
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_PROG_MKDIR_P
+AC_ENABLE_STATIC(no)
+LT_INIT
+PKG_PROG_PKG_CONFIG
+
+dnl ==========================================================================
+dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
+m4_ifndef([AS_VAR_COPY],
+[m4_define([AS_VAR_COPY],
+[AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])
+])
+m4_ifndef([PKG_CHECK_VAR], [
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])
+])
+])
+dnl ==========================================================================
+dnl AsciiDoc manual pages
+
+AC_ARG_ENABLE([asciidoc],
+ AS_HELP_STRING([--disable-asciidoc], [do not generate man pages from asciidoc]),
+ [], [enable_asciidoc=yes]
+)
+
+AC_PATH_PROG([ASCIIDOCTOR], [asciidoctor])
+if test "x$enable_asciidoc" = xyes -a "x$ASCIIDOCTOR" = x; then
+ AC_MSG_ERROR([Building man pages requires asciidoctor installed.])
+fi
+AM_CONDITIONAL([ENABLE_ASCIIDOC], [test "x$enable_asciidoc" = xyes])
+
+have_manpages=no
+AS_IF([test -f "$srcdir/man/cryptsetup-open.8"], [
+ AC_MSG_NOTICE([re-use already generated man-pages.])
+ have_manpages=yes]
+)
+AM_CONDITIONAL([HAVE_MANPAGES], [test "x$have_manpages" = xyes])
+
+dnl ==========================================================================
+
+AC_C_RESTRICT
+
+AC_HEADER_DIRENT
+AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h uchar.h sys/ioctl.h sys/mman.h \
+ sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h)
+AC_CHECK_DECLS([O_CLOEXEC],,[AC_DEFINE([O_CLOEXEC],[0], [Defined to 0 if not provided])],
+[[
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+]])
+
+AC_CHECK_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR([You need the uuid library.])])
+AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR([You need the device-mapper library.])])
+
+AC_ARG_ENABLE([keyring],
+ AS_HELP_STRING([--disable-keyring], [disable kernel keyring support and builtin kernel keyring token]),
+ [], [enable_keyring=yes])
+if test "x$enable_keyring" = "xyes"; then
+ AC_CHECK_HEADERS(linux/keyctl.h,,[AC_MSG_ERROR([You need Linux kernel headers with kernel keyring service compiled.])])
+
+ dnl ==========================================================================
+ dnl check whether kernel is compiled with kernel keyring service syscalls
+ AC_CHECK_DECL(__NR_add_key,,[AC_MSG_ERROR([The kernel is missing add_key syscall.])], [#include <syscall.h>])
+ AC_CHECK_DECL(__NR_keyctl,,[AC_MSG_ERROR([The kernel is missing keyctl syscall.])], [#include <syscall.h>])
+ AC_CHECK_DECL(__NR_request_key,,[AC_MSG_ERROR([The kernel is missing request_key syscall.])], [#include <syscall.h>])
+
+ dnl ==========================================================================
+ dnl check that key_serial_t hasn't been adopted yet in stdlib
+ AC_CHECK_TYPES([key_serial_t], [], [], [
+ AC_INCLUDES_DEFAULT
+ #ifdef HAVE_LINUX_KEYCTL_H
+ # include <linux/keyctl.h>
+ #endif
+ ])
+
+ AC_DEFINE(KERNEL_KEYRING, 1, [Enable kernel keyring service support])
+fi
+AM_CONDITIONAL(KERNEL_KEYRING, test "x$enable_keyring" = "xyes")
+
+saved_LIBS=$LIBS
+AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR([You need the uuid library.])])
+AC_SUBST(UUID_LIBS, $LIBS)
+LIBS=$saved_LIBS
+
+AC_SEARCH_LIBS([clock_gettime],[rt posix4])
+AC_CHECK_FUNCS([posix_memalign clock_gettime posix_fallocate explicit_bzero])
+
+if test "x$enable_largefile" = "xno"; then
+ AC_MSG_ERROR([Building with --disable-largefile is not supported, it can cause data corruption.])
+fi
+
+AC_C_CONST
+AC_C_BIGENDIAN
+AC_TYPE_OFF_T
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+AC_PROG_GCC_TRADITIONAL
+AC_FUNC_STRERROR_R
+
+dnl ==========================================================================
+dnl LUKS2 external tokens
+
+AC_ARG_ENABLE([external-tokens],
+ AS_HELP_STRING([--disable-external-tokens], [disable external LUKS2 tokens]),
+ [], [enable_external_tokens=yes])
+if test "x$enable_external_tokens" = "xyes"; then
+ AC_DEFINE(USE_EXTERNAL_TOKENS, 1, [Use external tokens])
+ dnl we need dynamic library loading here
+ saved_LIBS=$LIBS
+ AC_SEARCH_LIBS([dlsym],[dl])
+ AC_CHECK_FUNCS([dlvsym])
+ AC_SUBST(DL_LIBS, $LIBS)
+ LIBS=$saved_LIBS
+fi
+AM_CONDITIONAL(EXTERNAL_TOKENS, test "x$enable_external_tokens" = "xyes")
+
+AC_ARG_ENABLE([ssh-token],
+ AS_HELP_STRING([--disable-ssh-token], [disable LUKS2 ssh-token]),
+ [], [enable_ssh_token=yes])
+AM_CONDITIONAL(SSHPLUGIN_TOKEN, test "x$enable_ssh_token" = "xyes")
+
+if test "x$enable_ssh_token" = "xyes" -a "x$enable_external_tokens" = "xno"; then
+ AC_MSG_ERROR([Requested LUKS2 ssh-token build, but external tokens are disabled.])
+fi
+
+dnl LUKS2 online reencryption
+AC_ARG_ENABLE([luks2-reencryption],
+ AS_HELP_STRING([--disable-luks2-reencryption], [disable LUKS2 online reencryption extension]),
+ [], [enable_luks2_reencryption=yes])
+if test "x$enable_luks2_reencryption" = "xyes"; then
+ AC_DEFINE(USE_LUKS2_REENCRYPTION, 1, [Use LUKS2 online reencryption extension])
+fi
+
+dnl ==========================================================================
+
+AM_GNU_GETTEXT([external],[need-ngettext])
+AM_GNU_GETTEXT_VERSION([0.18.3])
+
+dnl ==========================================================================
+
+saved_LIBS=$LIBS
+AC_CHECK_LIB(popt, poptConfigFileToString,,
+ [AC_MSG_ERROR([You need popt 1.7 or newer to compile.])])
+AC_SUBST(POPT_LIBS, $LIBS)
+LIBS=$saved_LIBS
+
+dnl ==========================================================================
+dnl FIPS extensions
+AC_ARG_ENABLE([fips],
+ AS_HELP_STRING([--enable-fips], [enable FIPS mode restrictions]))
+if test "x$enable_fips" = "xyes"; then
+ AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions])
+
+ if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then
+ AC_MSG_ERROR([Static build is not compatible with FIPS.])
+ fi
+fi
+
+AC_DEFUN([NO_FIPS], [
+ if test "x$enable_fips" = "xyes"; then
+ AC_MSG_ERROR([This option is not compatible with FIPS.])
+ fi
+])
+
+dnl ==========================================================================
+dnl pwquality library (cryptsetup CLI only)
+AC_ARG_ENABLE([pwquality],
+ AS_HELP_STRING([--enable-pwquality], [enable password quality checking using pwquality library]))
+
+if test "x$enable_pwquality" = "xyes"; then
+ AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking using pwquality library])
+ PKG_CHECK_MODULES([PWQUALITY], [pwquality >= 1.0.0],,
+ AC_MSG_ERROR([You need pwquality library.]))
+
+ dnl FIXME: this is really hack for now
+ PWQUALITY_STATIC_LIBS="$PWQUALITY_LIBS -lcrack -lz"
+fi
+
+dnl ==========================================================================
+dnl fuzzers, it requires own static library compilation later
+AC_ARG_ENABLE([fuzz-targets],
+ AS_HELP_STRING([--enable-fuzz-targets], [enable building fuzz targets]))
+AM_CONDITIONAL(ENABLE_FUZZ_TARGETS, test "x$enable_fuzz_targets" = "xyes")
+
+if test "x$enable_fuzz_targets" = "xyes"; then
+ AX_CHECK_COMPILE_FLAG([-fsanitize=fuzzer-no-link],,
+ AC_MSG_ERROR([Required compiler options not supported; use clang.]), [-Werror])
+fi
+
+dnl ==========================================================================
+dnl passwdqc library (cryptsetup CLI only)
+AC_ARG_ENABLE([passwdqc],
+ AS_HELP_STRING([--enable-passwdqc@<:@=CONFIG_PATH@:>@],
+ [enable password quality checking using passwdqc library (optionally with CONFIG_PATH)]))
+
+case "$enable_passwdqc" in
+ ""|yes|no) use_passwdqc_config="" ;;
+ /*) use_passwdqc_config="$enable_passwdqc"; enable_passwdqc=yes ;;
+ *) AC_MSG_ERROR([Unrecognized --enable-passwdqc parameter.]) ;;
+esac
+AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc library config file])
+
+if test "x$enable_passwdqc" = "xyes"; then
+ AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library])
+
+ saved_LIBS="$LIBS"
+ AC_SEARCH_LIBS([passwdqc_check], [passwdqc])
+ case "$ac_cv_search_passwdqc_check" in
+ no) AC_MSG_ERROR([failed to find passwdqc_check]) ;;
+ -l*) PASSWDQC_LIBS="$ac_cv_search_passwdqc_check" ;;
+ *) PASSWDQC_LIBS= ;;
+ esac
+ AC_CHECK_FUNCS([passwdqc_params_free])
+ LIBS="$saved_LIBS"
+fi
+
+if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then
+ AC_MSG_ERROR([--enable-pwquality and --enable-passwdqc are mutually incompatible.])
+fi
+
+dnl ==========================================================================
+dnl Crypto backend functions
+
+AC_DEFUN([CONFIGURE_GCRYPT], [
+ if test "x$enable_fips" = "xyes"; then
+ GCRYPT_REQ_VERSION=1.4.5
+ else
+ GCRYPT_REQ_VERSION=1.1.42
+ fi
+
+ dnl libgcrypt rejects to use pkgconfig, use AM_PATH_LIBGCRYPT from gcrypt-devel here.
+ dnl Do not require gcrypt-devel if other crypto backend is used.
+ m4_ifdef([AM_PATH_LIBGCRYPT],[
+ AC_ARG_ENABLE([gcrypt-pbkdf2],
+ dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password)
+ AS_HELP_STRING([--enable-gcrypt-pbkdf2], [force enable internal gcrypt PBKDF2]),
+ if test "x$enableval" = "xyes"; then
+ [use_internal_pbkdf2=0]
+ else
+ [use_internal_pbkdf2=1]
+ fi,
+ [AM_PATH_LIBGCRYPT([1.6.1], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
+ AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])],
+ AC_MSG_ERROR([Missing support for gcrypt: install gcrypt and regenerate configure.]))
+
+ AC_MSG_CHECKING([if internal cryptsetup PBKDF2 is compiled-in])
+ if test $use_internal_pbkdf2 = 0; then
+ AC_MSG_RESULT([no])
+ else
+ AC_MSG_RESULT([yes])
+ NO_FIPS([])
+ fi
+
+ AC_CHECK_DECLS([GCRY_CIPHER_MODE_XTS], [], [], [#include <gcrypt.h>])
+
+ if test "x$enable_static_cryptsetup" = "xyes"; then
+ saved_LIBS=$LIBS
+ LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static"
+ AC_CHECK_LIB(gcrypt, gcry_check_version,,
+ AC_MSG_ERROR([Cannot find static gcrypt library.]),
+ [-lgpg-error])
+ LIBGCRYPT_STATIC_LIBS="$LIBGCRYPT_LIBS -lgpg-error"
+ LIBS=$saved_LIBS
+ fi
+
+ CRYPTO_CFLAGS=$LIBGCRYPT_CFLAGS
+ CRYPTO_LIBS=$LIBGCRYPT_LIBS
+ CRYPTO_STATIC_LIBS=$LIBGCRYPT_STATIC_LIBS
+
+ AC_DEFINE_UNQUOTED(GCRYPT_REQ_VERSION, ["$GCRYPT_REQ_VERSION"], [Requested gcrypt version])
+])
+
+AC_DEFUN([CONFIGURE_OPENSSL], [
+ PKG_CHECK_MODULES([OPENSSL], [openssl >= 0.9.8],,
+ AC_MSG_ERROR([You need openssl library.]))
+ CRYPTO_CFLAGS=$OPENSSL_CFLAGS
+ CRYPTO_LIBS=$OPENSSL_LIBS
+ use_internal_pbkdf2=0
+
+ if test "x$enable_static_cryptsetup" = "xyes"; then
+ saved_PKG_CONFIG=$PKG_CONFIG
+ PKG_CONFIG="$PKG_CONFIG --static"
+ PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl])
+ CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS
+ PKG_CONFIG=$saved_PKG_CONFIG
+ fi
+])
+
+AC_DEFUN([CONFIGURE_NSS], [
+ if test "x$enable_static_cryptsetup" = "xyes"; then
+ AC_MSG_ERROR([Static build of cryptsetup is not supported with NSS.])
+ fi
+
+ AC_MSG_WARN([NSS backend does NOT provide backward compatibility (missing ripemd160 hash).])
+
+ PKG_CHECK_MODULES([NSS], [nss],,
+ AC_MSG_ERROR([You need nss library.]))
+
+ saved_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $NSS_CFLAGS"
+ AC_CHECK_DECLS([NSS_GetVersion], [], [], [#include <nss.h>])
+ CFLAGS=$saved_CFLAGS
+
+ CRYPTO_CFLAGS=$NSS_CFLAGS
+ CRYPTO_LIBS=$NSS_LIBS
+ use_internal_pbkdf2=1
+ NO_FIPS([])
+])
+
+AC_DEFUN([CONFIGURE_KERNEL], [
+ AC_CHECK_HEADERS(linux/if_alg.h,,
+ [AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface.])])
+# AC_CHECK_DECLS([AF_ALG],,
+# [AC_MSG_ERROR([You need Linux kernel with userspace crypto interface.])],
+# [#include <sys/socket.h>])
+ use_internal_pbkdf2=1
+ NO_FIPS([])
+])
+
+AC_DEFUN([CONFIGURE_NETTLE], [
+ AC_CHECK_HEADERS(nettle/sha.h,,
+ [AC_MSG_ERROR([You need Nettle cryptographic library.])])
+ AC_CHECK_HEADERS(nettle/version.h)
+
+ saved_LIBS=$LIBS
+ AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,,
+ [AC_MSG_ERROR([You need Nettle library version 2.6 or more recent.])])
+ CRYPTO_LIBS=$LIBS
+ LIBS=$saved_LIBS
+
+ CRYPTO_STATIC_LIBS=$CRYPTO_LIBS
+ use_internal_pbkdf2=0
+ NO_FIPS([])
+])
+
+dnl ==========================================================================
+saved_LIBS=$LIBS
+
+AC_ARG_ENABLE([static-cryptsetup],
+ AS_HELP_STRING([--enable-static-cryptsetup], [enable build of static version of tools]))
+if test "x$enable_static_cryptsetup" = "xyes"; then
+ if test "x$enable_static" = "xno"; then
+ AC_MSG_WARN([Requested static cryptsetup build, enabling static library.])
+ enable_static=yes
+ fi
+fi
+AM_CONDITIONAL(STATIC_TOOLS, test "x$enable_static_cryptsetup" = "xyes")
+
+AC_ARG_ENABLE([cryptsetup],
+ AS_HELP_STRING([--disable-cryptsetup], [disable cryptsetup support]),
+ [], [enable_cryptsetup=yes])
+AM_CONDITIONAL(CRYPTSETUP, test "x$enable_cryptsetup" = "xyes")
+
+AC_ARG_ENABLE([veritysetup],
+ AS_HELP_STRING([--disable-veritysetup], [disable veritysetup support]),
+ [], [enable_veritysetup=yes])
+AM_CONDITIONAL(VERITYSETUP, test "x$enable_veritysetup" = "xyes")
+
+AC_ARG_ENABLE([integritysetup],
+ AS_HELP_STRING([--disable-integritysetup], [disable integritysetup support]),
+ [], [enable_integritysetup=yes])
+AM_CONDITIONAL(INTEGRITYSETUP, test "x$enable_integritysetup" = "xyes")
+
+AC_ARG_ENABLE([selinux],
+ AS_HELP_STRING([--disable-selinux], [disable selinux support [default=auto]]),
+ [], [enable_selinux=yes])
+
+AC_ARG_ENABLE([udev],
+ AS_HELP_STRING([--disable-udev], [disable udev support]),
+ [], [enable_udev=yes])
+
+dnl Try to use pkg-config for devmapper, but fallback to old detection
+PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03],, [
+ AC_CHECK_LIB(devmapper, dm_task_set_name,,
+ [AC_MSG_ERROR([You need the device-mapper library.])])
+ AC_CHECK_LIB(devmapper, dm_task_set_message,,
+ [AC_MSG_ERROR([The device-mapper library on your system is too old.])])
+ DEVMAPPER_LIBS=$LIBS
+])
+LIBS=$saved_LIBS
+
+LIBS="$LIBS $DEVMAPPER_LIBS"
+AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([dm_device_get_name], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([DM_DEVICE_GET_TARGET_VERSION], [], [], [#include <libdevmapper.h>])
+AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
+if test "x$enable_udev" = xyes; then
+ if test "x$have_cookie" = xno; then
+ AC_MSG_WARN([The device-mapper library on your system has no udev support, udev support disabled.])
+ else
+ AC_DEFINE(USE_UDEV, 1, [Try to use udev synchronisation?])
+ fi
+fi
+LIBS=$saved_LIBS
+
+dnl Check for JSON-C used in LUKS2
+PKG_CHECK_MODULES([JSON_C], [json-c])
+AC_CHECK_DECLS([json_object_object_add_ex], [], [], [#include <json-c/json.h>])
+AC_CHECK_DECLS([json_object_deep_copy], [], [], [#include <json-c/json.h>])
+
+dnl Check for libssh and argp for SSH plugin
+if test "x$enable_ssh_token" = "xyes"; then
+ PKG_CHECK_MODULES([LIBSSH], [libssh])
+ AC_CHECK_DECLS([ssh_session_is_known_server], [], [], [#include <libssh/libssh.h>])
+ AC_CHECK_HEADER([argp.h], [], AC_MSG_ERROR([You need argp library.]))
+ saved_LIBS=$LIBS
+ AC_SEARCH_LIBS([argp_parse],[argp])
+ AC_SUBST(ARGP_LIBS, $LIBS)
+ LIBS=$saved_LIBS
+fi
+
+dnl Crypto backend configuration.
+AC_ARG_WITH([crypto_backend],
+ AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]),
+ [], [with_crypto_backend=openssl])
+
+dnl Kernel crypto API backend needed for benchmark and tcrypt
+AC_ARG_ENABLE([kernel_crypto],
+ AS_HELP_STRING([--disable-kernel_crypto], [disable kernel userspace crypto (no benchmark and tcrypt)]),
+ [], [enable_kernel_crypto=yes])
+
+if test "x$enable_kernel_crypto" = "xyes"; then
+ AC_CHECK_HEADERS(linux/if_alg.h,,
+ [AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)])])
+ AC_DEFINE(ENABLE_AF_ALG, 1, [Enable using of kernel userspace crypto])
+fi
+
+case $with_crypto_backend in
+ gcrypt) CONFIGURE_GCRYPT([]) ;;
+ openssl) CONFIGURE_OPENSSL([]) ;;
+ nss) CONFIGURE_NSS([]) ;;
+ kernel) CONFIGURE_KERNEL([]) ;;
+ nettle) CONFIGURE_NETTLE([]) ;;
+ *) AC_MSG_ERROR([Unknown crypto backend.]) ;;
+esac
+AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test "$with_crypto_backend" = "gcrypt")
+AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test "$with_crypto_backend" = "openssl")
+AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test "$with_crypto_backend" = "nss")
+AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test "$with_crypto_backend" = "kernel")
+AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test "$with_crypto_backend" = "nettle")
+
+AM_CONDITIONAL(CRYPTO_INTERNAL_PBKDF2, test $use_internal_pbkdf2 = 1)
+AC_DEFINE_UNQUOTED(USE_INTERNAL_PBKDF2, [$use_internal_pbkdf2], [Use internal PBKDF2])
+
+dnl Argon2 implementation
+AC_ARG_ENABLE([internal-argon2],
+ AS_HELP_STRING([--disable-internal-argon2], [disable internal implementation of Argon2 PBKDF]),
+ [], [enable_internal_argon2=yes])
+
+AC_ARG_ENABLE([libargon2],
+ AS_HELP_STRING([--enable-libargon2], [enable external libargon2 (PHC) library (disables internal bundled version)]))
+
+if test "x$enable_libargon2" = "xyes" ; then
+ AC_CHECK_HEADERS(argon2.h,,
+ [AC_MSG_ERROR([You need libargon2 development library installed.])])
+ AC_CHECK_DECL(Argon2_id,,[AC_MSG_ERROR([You need more recent Argon2 library with support for Argon2id.])], [#include <argon2.h>])
+ PKG_CHECK_MODULES([LIBARGON2], [libargon2],,[LIBARGON2_LIBS="-largon2"])
+ enable_internal_argon2=no
+else
+ AC_MSG_WARN([Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2.])
+
+ AC_ARG_ENABLE([internal-sse-argon2],
+ AS_HELP_STRING([--enable-internal-sse-argon2], [enable internal SSE implementation of Argon2 PBKDF]))
+
+ if test "x$enable_internal_sse_argon2" = "xyes"; then
+ AC_MSG_CHECKING(if Argon2 SSE optimization can be used)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #include <emmintrin.h>
+ __m128i testfunc(__m128i *a, __m128i *b) {
+ return _mm_xor_si128(_mm_loadu_si128(a), _mm_loadu_si128(b));
+ }
+ ]])],,[enable_internal_sse_argon2=no])
+ AC_MSG_RESULT($enable_internal_sse_argon2)
+ fi
+fi
+
+if test "x$enable_internal_argon2" = "xyes"; then
+ AC_DEFINE(USE_INTERNAL_ARGON2, 1, [Use internal Argon2])
+fi
+AM_CONDITIONAL(CRYPTO_INTERNAL_ARGON2, test "x$enable_internal_argon2" = "xyes")
+AM_CONDITIONAL(CRYPTO_INTERNAL_SSE_ARGON2, test "x$enable_internal_sse_argon2" = "xyes")
+
+dnl Link with blkid to check for other device types
+AC_ARG_ENABLE([blkid],
+ AS_HELP_STRING([--disable-blkid], [disable use of blkid for device signature detection and wiping]),
+ [], [enable_blkid=yes])
+
+if test "x$enable_blkid" = "xyes"; then
+ PKG_CHECK_MODULES([BLKID], [blkid],[AC_DEFINE([HAVE_BLKID], 1, [Define to 1 to use blkid for detection of disk signatures.])],[LIBBLKID_LIBS="-lblkid"])
+
+ AC_CHECK_HEADERS(blkid/blkid.h,,[AC_MSG_ERROR([You need blkid development library installed.])])
+ AC_CHECK_DECL([blkid_do_wipe],
+ [ AC_DEFINE([HAVE_BLKID_WIPE], 1, [Define to 1 to use blkid_do_wipe.])
+ enable_blkid_wipe=yes
+ ],,
+ [#include <blkid/blkid.h>])
+ AC_CHECK_DECL([blkid_probe_step_back],
+ [ AC_DEFINE([HAVE_BLKID_STEP_BACK], 1, [Define to 1 to use blkid_probe_step_back.])
+ enable_blkid_step_back=yes
+ ],,
+ [#include <blkid/blkid.h>])
+ AC_CHECK_DECLS([ blkid_reset_probe,
+ blkid_probe_set_device,
+ blkid_probe_filter_superblocks_type,
+ blkid_do_safeprobe,
+ blkid_do_probe,
+ blkid_probe_lookup_value
+ ],,
+ [AC_MSG_ERROR([Can not compile with blkid support, disable it by --disable-blkid.])],
+ [#include <blkid/blkid.h>])
+fi
+AM_CONDITIONAL(HAVE_BLKID, test "x$enable_blkid" = "xyes")
+AM_CONDITIONAL(HAVE_BLKID_WIPE, test "x$enable_blkid_wipe" = "xyes")
+AM_CONDITIONAL(HAVE_BLKID_STEP_BACK, test "x$enable_blkid_step_back" = "xyes")
+
+dnl Magic for cryptsetup.static build.
+if test "x$enable_static_cryptsetup" = "xyes"; then
+ saved_PKG_CONFIG=$PKG_CONFIG
+ PKG_CONFIG="$PKG_CONFIG --static"
+
+ LIBS="$saved_LIBS -static"
+ AC_CHECK_LIB(popt, poptGetContext,,
+ AC_MSG_ERROR([Cannot find static popt library.]))
+
+ dnl Try to detect needed device-mapper static libraries, try pkg-config first.
+ LIBS="$saved_LIBS -static"
+ PKG_CHECK_MODULES([DEVMAPPER_STATIC], [devmapper >= 1.02.27],,[
+ DEVMAPPER_STATIC_LIBS=$DEVMAPPER_LIBS
+ if test "x$enable_selinux" = "xyes"; then
+ AC_CHECK_LIB(sepol, sepol_bool_set)
+ AC_CHECK_LIB(selinux, is_selinux_enabled)
+ DEVMAPPER_STATIC_LIBS="$DEVMAPPER_STATIC_LIBS $LIBS"
+ fi
+ ])
+ LIBS="$saved_LIBS $DEVMAPPER_STATIC_LIBS"
+ AC_CHECK_LIB(devmapper, dm_task_set_uuid,,
+ AC_MSG_ERROR([Cannot link with static device-mapper library.]))
+
+ dnl Try to detect uuid static library.
+ LIBS="$saved_LIBS -static"
+ AC_CHECK_LIB(uuid, uuid_generate,,
+ AC_MSG_ERROR([Cannot find static uuid library.]))
+
+ LIBS=$saved_LIBS
+ PKG_CONFIG=$saved_PKG_CONFIG
+fi
+
+dnl Check compiler support for symver function attribute
+AC_MSG_CHECKING([for symver attribute support])
+saved_CFLAGS=$CFLAGS
+CFLAGS="-O0 -Werror"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ void _test_sym(void);
+ __attribute__((__symver__("sym@VERSION_4.2"))) void _test_sym(void) {}
+]],
+[[ _test_sym() ]]
+)],[
+ AC_DEFINE([HAVE_ATTRIBUTE_SYMVER], 1, [Define to 1 to use __attribute__((symver))])
+ AC_MSG_RESULT([yes])
+], [
+ AC_MSG_RESULT([no])
+])
+CFLAGS=$saved_CFLAGS
+
+AC_MSG_CHECKING([for systemd tmpfiles config directory])
+PKG_CHECK_VAR([systemd_tmpfilesdir], [systemd], [tmpfilesdir], [], [systemd_tmpfilesdir=no])
+AC_MSG_RESULT([$systemd_tmpfilesdir])
+
+AC_SUBST([DEVMAPPER_LIBS])
+AC_SUBST([DEVMAPPER_STATIC_LIBS])
+
+AC_SUBST([PWQUALITY_LIBS])
+AC_SUBST([PWQUALITY_STATIC_LIBS])
+
+AC_SUBST([PASSWDQC_LIBS])
+
+AC_SUBST([CRYPTO_CFLAGS])
+AC_SUBST([CRYPTO_LIBS])
+AC_SUBST([CRYPTO_STATIC_LIBS])
+
+AC_SUBST([JSON_C_LIBS])
+AC_SUBST([LIBARGON2_LIBS])
+AC_SUBST([BLKID_LIBS])
+
+AC_SUBST([LIBSSH_LIBS])
+
+AC_SUBST([LIBCRYPTSETUP_VERSION])
+AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
+
+dnl Set Requires.private for libcryptsetup.pc
+dnl pwquality is used only by tools
+PKGMODULES="uuid devmapper json-c"
+case $with_crypto_backend in
+ gcrypt) PKGMODULES+=" libgcrypt" ;;
+ openssl) PKGMODULES+=" openssl" ;;
+ nss) PKGMODULES+=" nss" ;;
+ nettle) PKGMODULES+=" nettle" ;;
+esac
+if test "x$enable_libargon2" = "xyes"; then
+ PKGMODULES+=" libargon2"
+fi
+if test "x$enable_blkid" = "xyes"; then
+ PKGMODULES+=" blkid"
+fi
+AC_SUBST([PKGMODULES])
+dnl ==========================================================================
+AC_ARG_ENABLE([dev-random],
+ AS_HELP_STRING([--enable-dev-random], [use /dev/random by default for key generation (otherwise use /dev/urandom)]))
+if test "x$enable_dev_random" = "xyes"; then
+ default_rng=/dev/random
+else
+ default_rng=/dev/urandom
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_RNG, ["$default_rng"], [default RNG type for key generator])
+
+dnl ==========================================================================
+AC_DEFUN([CS_DEFINE],
+ [AC_DEFINE_UNQUOTED(DEFAULT_[]m4_translit([$1], [-a-z], [_A-Z]), [$2], [$3])
+])
+
+AC_DEFUN([CS_STR_WITH], [AC_ARG_WITH([$1],
+ [AS_HELP_STRING(--with-[$1], [default $2 [$3]])],
+ [CS_DEFINE([$1], ["$withval"], [$2])],
+ [CS_DEFINE([$1], ["$3"], [$2])]
+)])
+
+AC_DEFUN([CS_NUM_WITH], [AC_ARG_WITH([$1],
+ [AS_HELP_STRING(--with-[$1], [default $2 [$3]])],
+ [CS_DEFINE([$1], [$withval], [$2])],
+ [CS_DEFINE([$1], [$3], [$2])]
+)])
+
+AC_DEFUN([CS_ABSPATH], [
+ case "$1" in
+ /*) ;;
+ *) AC_MSG_ERROR([$2 argument must be an absolute path.]);;
+ esac
+])
+
+dnl ==========================================================================
+CS_STR_WITH([plain-hash], [password hashing function for plain mode], [ripemd160])
+CS_STR_WITH([plain-cipher], [cipher for plain mode], [aes])
+CS_STR_WITH([plain-mode], [cipher mode for plain mode], [cbc-essiv:sha256])
+CS_NUM_WITH([plain-keybits],[key length in bits for plain mode], [256])
+
+CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha256])
+CS_STR_WITH([luks1-cipher], [cipher for LUKS1], [aes])
+CS_STR_WITH([luks1-mode], [cipher mode for LUKS1], [xts-plain64])
+CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256])
+
+AC_ARG_ENABLE([luks_adjust_xts_keysize], AS_HELP_STRING([--disable-luks-adjust-xts-keysize],
+ [XTS mode requires two keys, double default LUKS keysize if needed]),
+ [], [enable_luks_adjust_xts_keysize=yes])
+if test "x$enable_luks_adjust_xts_keysize" = "xyes"; then
+ AC_DEFINE(ENABLE_LUKS_ADJUST_XTS_KEYSIZE, 1, [XTS mode - double default LUKS keysize if needed])
+fi
+
+CS_STR_WITH([luks2-pbkdf], [Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2], [argon2id])
+CS_NUM_WITH([luks1-iter-time], [PBKDF2 iteration time for LUKS1 (in ms)], [2000])
+CS_NUM_WITH([luks2-iter-time], [Argon2 PBKDF iteration time for LUKS2 (in ms)], [2000])
+CS_NUM_WITH([luks2-memory-kb], [Argon2 PBKDF memory cost for LUKS2 (in kB)], [1048576])
+CS_NUM_WITH([luks2-parallel-threads],[Argon2 PBKDF max parallel cost for LUKS2 (if CPUs available)], [4])
+
+CS_STR_WITH([luks2-keyslot-cipher], [fallback cipher for LUKS2 keyslot (if data encryption is incompatible)], [aes-xts-plain64])
+CS_NUM_WITH([luks2-keyslot-keybits],[fallback key size for LUKS2 keyslot (if data encryption is incompatible)], [512])
+
+CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
+CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
+
+CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
+CS_NUM_WITH([integrity-keyfile-size-maxkb],[maximum integritysetup keyfile size (in KiB)], [4])
+CS_NUM_WITH([passphrase-size-max],[maximum passphrase size (in characters)], [512])
+
+CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
+CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
+CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096])
+CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32])
+CS_NUM_WITH([verity-fec-roots], [parity bytes for verity FEC], [2])
+
+CS_STR_WITH([tmpfilesdir], [override default path to directory with systemd temporary files], [])
+test -z "$with_tmpfilesdir" && with_tmpfilesdir=$systemd_tmpfilesdir
+test "x$with_tmpfilesdir" = "xno" || {
+ CS_ABSPATH([${with_tmpfilesdir}],[with-tmpfilesdir])
+ DEFAULT_TMPFILESDIR=$with_tmpfilesdir
+ AC_SUBST(DEFAULT_TMPFILESDIR)
+}
+AM_CONDITIONAL(CRYPTSETUP_TMPFILE, test -n "$DEFAULT_TMPFILESDIR")
+
+CS_STR_WITH([luks2-lock-path], [path to directory for LUKSv2 locks], [/run/cryptsetup])
+test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/cryptsetup
+CS_ABSPATH([${with_luks2_lock_path}],[with-luks2-lock-path])
+DEFAULT_LUKS2_LOCK_PATH=$with_luks2_lock_path
+AC_SUBST(DEFAULT_LUKS2_LOCK_PATH)
+
+CS_NUM_WITH([luks2-lock-dir-perms], [default luks2 locking directory permissions], [0700])
+test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700
+DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms
+AC_SUBST(DEFAULT_LUKS2_LOCK_DIR_PERMS)
+
+CS_STR_WITH([luks2-external-tokens-path], [path to directory with LUKSv2 external token handlers (plugins)], [LIBDIR/cryptsetup])
+if test -n "$with_luks2_external_tokens_path"; then
+ CS_ABSPATH([${with_luks2_external_tokens_path}],[with-luks2-external-tokens-path])
+ EXTERNAL_LUKS2_TOKENS_PATH=$with_luks2_external_tokens_path
+else
+ EXTERNAL_LUKS2_TOKENS_PATH="\${libdir}/cryptsetup"
+fi
+AC_SUBST(EXTERNAL_LUKS2_TOKENS_PATH)
+
+dnl Override default LUKS format version (for cryptsetup or cryptsetup-reencrypt format actions only).
+AC_ARG_WITH([default_luks_format],
+ AS_HELP_STRING([--with-default-luks-format=FORMAT], [default LUKS format version (LUKS1/LUKS2) [LUKS2]]),
+ [], [with_default_luks_format=LUKS2])
+
+case $with_default_luks_format in
+ LUKS1) default_luks=CRYPT_LUKS1 ;;
+ LUKS2) default_luks=CRYPT_LUKS2 ;;
+ *) AC_MSG_ERROR([Unknown default LUKS format. Use LUKS1 or LUKS2 only.]) ;;
+esac
+AC_DEFINE_UNQUOTED([DEFAULT_LUKS_FORMAT], [$default_luks], [default LUKS format version])
+
+dnl ==========================================================================
+
+AC_CONFIG_FILES([ Makefile
+lib/libcryptsetup.pc
+po/Makefile.in
+scripts/cryptsetup.conf
+tests/Makefile
+tests/fuzz/Makefile
+])
+AC_OUTPUT
diff --git a/docs/ChangeLog.old b/docs/ChangeLog.old
new file mode 100644
index 0000000..516ea17
--- /dev/null
+++ b/docs/ChangeLog.old
@@ -0,0 +1,887 @@
+2012-12-21 Milan Broz <gmazyland@gmail.com>
+ * Since version 1.6 This file is no longer maintained.
+ * See version control log http://code.google.com/p/cryptsetup/source/list
+
+2012-10-11 Milan Broz <gmazyland@gmail.com>
+ * Added keyslot checker (by Arno Wagner).
+ * Version 1.5.1.
+
+2012-09-11 Milan Broz <gmazyland@gmail.com>
+ * Add crypt_keyslot_area() API call.
+
+2012-08-27 Milan Broz <gmazyland@gmail.com>
+ * Optimize seek to keyfile-offset (Issue #135, thx to dreisner).
+ * Fix luksHeaderBackup for very old v1.0 unaligned LUKS headers.
+
+2012-08-12 Milan Broz <gmazyland@gmail.com>
+ * Allocate loop device late (only when real block device needed).
+ * Rework underlying device/file access functions.
+ * Create hash image if doesn't exist in veritysetup format.
+ * Provide better error message if running as non-root user (device-mapper, loop).
+
+2012-07-10 Milan Broz <gmazyland@gmail.com>
+ * Version 1.5.0.
+
+2012-06-25 Milan Broz <gmazyland@gmail.com>
+ * Add --device-size option for reencryption tool.
+ * Switch to use unit suffix for --reduce-device-size option.
+ * Remove open device debugging feature (no longer needed).
+ * Fix library name for FIPS check.
+
+2012-06-20 Milan Broz <gmazyland@gmail.com>
+ * Version 1.5.0-rc2.
+
+2012-06-18 Milan Broz <gmazyland@gmail.com>
+ * Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool.
+ * Fix luks-header-from-active script (do not use LUKS header on-disk, add UUID).
+ * Add --test-passphrase option for luksOpen (check passphrase only).
+
+2012-06-11 Milan Broz <gmazyland@gmail.com>
+ * Introduce veritysetup for dm-verity target management.
+ * Version 1.5.0-rc1.
+
+2012-06-10 Milan Broz <gmazyland@gmail.com>
+ * Both data and header device can now be a file.
+ * Loop is automatically allocated in crypt_set_data_device().
+ * Require only up to last keyslot area for header device (ignore data offset).
+ * Fix header backup and restore to work on files with large data offset.
+
+2012-05-27 Milan Broz <gmazyland@gmail.com>
+ * Fix readonly activation if underlying device is readonly (1.4.0).
+ * Include stddef.h in libdevmapper.h (size_t definition).
+ * Version 1.4.3.
+
+2012-05-21 Milan Broz <gmazyland@gmail.com>
+ * Add --enable-fips for linking with fipscheck library.
+ * Initialize binary and library selfcheck if running in FIPS mode.
+ * Use FIPS RNG in FIPS mode for KEY and SALT (only gcrypt backend supported).
+
+2012-05-09 Milan Broz <gmazyland@gmail.com>
+ * Fix keyslot removal (wipe keyslot) for device with 4k hw block (1.4.0).
+ * Allow empty cipher (cipher_null) for testing.
+
+2012-05-02 Milan Broz <gmazyland@gmail.com>
+ * Fix loop mapping on readonly file.
+ * Relax --shared test, allow mapping even for overlapping segments.
+ * Support shared flag for LUKS devices (dangerous).
+ * Switch on retry on device remove for libdevmapper.
+ * Allow "private" activation (skip some udev global rules) flag.
+
+2012-04-09 Milan Broz <gmazyland@gmail.com>
+ * Fix header check to support old (cryptsetup 1.0.0) header alignment. (1.4.0)
+ * Version 1.4.2.
+
+2012-03-16 Milan Broz <gmazyland@gmail.com>
+ * Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
+ * Add repair command and crypt_repair() for known LUKS metadata problems repair.
+ * Allow one to specify --align-payload only for luksFormat.
+
+2012-03-16 Milan Broz <mbroz@redhat.com>
+ * Unify password verification option.
+ * Support password verification with quiet flag if possible. (1.2.0)
+ * Fix retry if entered passphrases (with verify option) do not match.
+ * Support UUID=<LUKS_UUID> format for device specification.
+
+2012-02-11 Milan Broz <mbroz@redhat.com>
+ * Add --master-key-file option to luksOpen (open using volume key).
+
+2012-01-12 Milan Broz <mbroz@redhat.com>
+ * Fix use of empty keyfile.
+
+2011-11-13 Milan Broz <mbroz@redhat.com>
+ * Fix error message for luksClose and detached LUKS header.
+ * Allow --header for status command to get full info with detached header.
+
+2011-11-09 Milan Broz <mbroz@redhat.com>
+ * Version 1.4.1.
+
+2011-11-05 Milan Broz <mbroz@redhat.com>
+ * Merge pycryptsetup (Python libcryptsetup bindings).
+ * Fix stupid typo in set_iteration_time API call.
+ * Fix cryptsetup status output if parameter is device path.
+
+2011-10-27 Milan Broz <mbroz@redhat.com>
+ * Fix crypt_get_volume_key_size() for plain device.
+ * Fix FSF address in license text.
+
+2011-10-25 Milan Broz <mbroz@redhat.com>
+ * Print informative message in isLuks only in verbose mode.
+ * Version 1.4.0.
+
+2011-10-10 Milan Broz <mbroz@redhat.com>
+ * Version 1.4.0-rc1.
+
+2011-10-05 Milan Broz <mbroz@redhat.com>
+ * Support Nettle 2.4 crypto backend (for ripemd160).
+ * If device is not rotational, do not use Gutmann wipe method.
+ * Add crypt_last_error() API call.
+ * Fix luksKillSLot exit code if slot is inactive or invalid.
+ * Fix exit code if passphrases do not match in luksAddKey.
+ * Add LUKS on-disk format description into package.
+
+2011-09-22 Milan Broz <mbroz@redhat.com>
+ * Support key-slot option for luksOpen (use only explicit keyslot).
+
+2011-08-22 Milan Broz <mbroz@redhat.com>
+ * Add more paranoid checks for LUKS header and keyslot attributes.
+ * Fix crypt_load to properly check device size.
+ * Use new /dev/loop-control (kernel 3.1) if possible.
+ * Enhance check of device size before writing LUKS header.
+ * Do not allow context format of already formatted device.
+
+2011-07-25 Milan Broz <mbroz@redhat.com>
+ * Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
+ * Improve check for invalid offset and size values.
+
+2011-07-19 Milan Broz <mbroz@redhat.com>
+ * Revert default initialisation of volume key in crypt_init_by_name().
+ * Do not allow key retrieval while suspended (key could be wiped).
+ * Do not allow suspend for non-LUKS devices.
+ * Support retries and timeout parameters for luksSuspend.
+ * Add --header option for detached metadata (on-disk LUKS header) device.
+ * Add crypt_init_by_name_and_header() and crypt_set_data_device() to API.
+ * Allow different data offset setting for detached header.
+
+2011-07-07 Milan Broz <mbroz@redhat.com>
+ * Remove old API functions (all functions using crypt_options).
+ * Add --enable-discards option to allow discards/TRIM requests.
+ * Add crypt_get_iv_offset() function to API.
+
+2011-07-01 Milan Broz <mbroz@redhat.com>
+ * Add --shared option for creating non-overlapping crypt segments.
+ * Add shared flag to libcryptsetup api.
+ * Fix plain crypt format parameters to include size option (API change).
+
+2011-06-08 Milan Broz <mbroz@redhat.com>
+ * Fix return code for status command when device doesn't exists.
+
+2011-05-24 Milan Broz <mbroz@redhat.com>
+ * Version 1.3.1.
+
+2011-05-17 Milan Broz <mbroz@redhat.com>
+ * Fix keyfile=- processing in create command (1.3.0).
+ * Simplify device path status check.
+
+2011-05-03 Milan Broz <mbroz@redhat.com>
+ * Do not ignore size argument for create command (1.2.0).
+
+2011-04-18 Milan Broz <mbroz@redhat.com>
+ * Fix error paths in blockwise code and lseek_write call.
+ * Add Nettle crypto backend support.
+
+2011-04-05 Milan Broz <mbroz@redhat.com>
+ * Version 1.3.0.
+
+2011-03-22 Milan Broz <mbroz@redhat.com>
+ * Also support --skip and --hash option for loopaesOpen.
+ * Fix return code when passphrase is read from pipe.
+ * Document cryptsetup exit codes.
+
+2011-03-18 Milan Broz <mbroz@redhat.com>
+ * Respect maximum keyfile size parameter.
+ * Introduce maximum default keyfile size, add configure option.
+ * Require the whole key read from keyfile in create command (broken in 1.2.0).
+ * Fix offset option for loopaesOpen.
+ * Lock memory also in luksDump command.
+ * Version 1.3.0-rc2.
+
+2011-03-14 Milan Broz <mbroz@redhat.com>
+ * Version 1.3.0-rc1.
+
+2011-03-11 Milan Broz <mbroz@redhat.com>
+ * Add loop manipulation code and support mapping of images in file.
+ * Add backing device loop info into status message.
+ * Add luksChangeKey command.
+
+2011-03-05 Milan Broz <mbroz@redhat.com>
+ * Add exception to COPYING for binary distribution linked with OpenSSL library.
+ * Set secure data flag (wipe all ioctl buffers) if devmapper library supports it.
+
+2011-01-29 Milan Broz <mbroz@redhat.com>
+ * Fix mapping removal if device disappeared but node still exists.
+ * Fix luksAddKey return code if master key is used.
+
+2011-01-25 Milan Broz <mbroz@redhat.com>
+ * Add loop-AES handling (loopaesOpen and loopaesClose commands).
+ (requires kernel 2.6.38 and above)
+
+2011-01-05 Milan Broz <mbroz@redhat.com>
+ * Fix static build (--disable-static-cryptsetup now works properly).
+
+2010-12-30 Milan Broz <mbroz@redhat.com>
+ * Add compile time crypto backends implementation
+ (gcrypt, OpenSSL, NSS and userspace Linux kernel crypto api).
+ * Currently NSS is lacking ripemd160, cannot provide full plain compatibility.
+ * Use --with-crypto_backend=[gcrypt|openssl|nss|kernel] to configure.
+
+2010-12-20 Milan Broz <mbroz@redhat.com>
+ * Version 1.2.0.
+
+2010-11-25 Milan Broz <mbroz@redhat.com>
+ * Fix crypt_activate_by_keyfile() to work with PLAIN devices.
+ * Fix create command to properly handle keyfile size.
+
+2010-11-16 Milan Broz <mbroz@redhat.com>
+ * Version 1.2.0-rc1.
+
+2010-11-13 Milan Broz <mbroz@redhat.com>
+ * Fix password callback call.
+ * Fix default plain password entry from terminal in activate_by_passphrase.
+ * Add --dump-master-key option for luksDump to allow volume key dump.
+ * Allow one to activate by internally cached volume key
+ (format/activate without keyslots active - used for temporary devices).
+ * Initialize volume key from active device in crypt_init_by_name()
+ * Fix cryptsetup binary exitcodes.
+ * Increase library version (still binary compatible with 1.1.x release).
+
+2010-11-01 Milan Broz <mbroz@redhat.com>
+ * No longer support luksDelKey, reload and --non-exclusive.
+ * Remove some obsolete info from man page.
+ * Add crypt_get_type(), crypt_resize(), crypt_keyslot_max()
+ and crypt_get_active_device() to API.
+ * Rewrite all implementations in cryptsetup to new API.
+ * Fix luksRemoveKey to behave as documented (do not ask
+ for remaining keyslot passphrase).
+ * Add more regression tests for commands.
+ * Disallow mapping of device which is already in use (mapped or mounted).
+ * Disallow luksFormat on device in use.
+
+2010-10-27 Milan Broz <mbroz@redhat.com>
+ * Rewrite cryptsetup luksFormat, luksOpen, luksAddKey to use new API
+ to allow adding new features.
+ * Implement --use-random and --use-urandom for luksFormat to allow
+ setting of RNG for volume key generator.
+ * Add crypt_set_rng_type() and crypt_get_rng_type() to API.
+ * Add crypt_set_uuid() to API.
+ * Allow UUID setting in luksFormat and luksUUID (--uuid parameter).
+ * Add --keyfile-size and --new-keyfile-size (in bytes) size and disallow overloading
+ of --key-size for limiting keyfile reads.
+ * Fix luksFormat to properly use key file with --master-key-file switch.
+ * Fix possible double free when handling master key file.
+
+2010-10-17 Milan Broz <mbroz@redhat.com>
+ * Add crypt_get_device_name() to API (get underlying device name).
+ * Change detection for static libraries.
+ * Fix pkg-config use in automake scripts.
+ * Remove --disable-shared-library switch and handle static library build
+ by common libtool logic (using --enable-static).
+ * Add --enable-static-cryptsetup option to build cryptsetup.static binary
+ together with shared build.
+
+2010-08-05 Milan Broz <mbroz@redhat.com>
+ * Wipe iteration and salt after KillSlot in LUKS header.
+ * Rewrite file differ test to C (and fix it to really work).
+ * Switch to 1MiB default alignment of data.
+ For more info see https://bugzilla.redhat.com/show_bug.cgi?id=621684
+ * Do not query non-existent device twice (cryptsetup status /dev/nonexistent).
+ * Check if requested hash is supported before writing LUKS header.
+
+2010-07-28 Arno Wagner <arno@wagner.name>
+ * Add FAQ (Frequently Asked Questions) file to distribution.
+
+2010-07-03 Milan Broz <mbroz@redhat.com>
+ * Fix udev support for old libdevmapper with not compatible definition.
+ * Version 1.1.3.
+
+2010-06-01 Milan Broz <mbroz@redhat.com>
+ * Fix device alignment ioctl calls parameters.
+ * Fix activate_by_* API calls to handle NULL device name as documented.
+
+2010-05-30 Milan Broz <mbroz@redhat.com>
+ * Version 1.1.2.
+
+2010-05-27 Milan Broz <mbroz@redhat.com>
+ * Fix luksFormat/luksOpen reading passphrase from stdin and "-" keyfile.
+ * Support --key-file/-d option for luksFormat.
+ * Fix description of --key-file and add --verbose and --debug options to man page.
+ * Add verbose log level and move unlocking message there.
+ * Remove device even if underlying device disappeared.
+ * Fix (deprecated) reload device command to accept new device argument.
+
+2010-05-23 Milan Broz <mbroz@redhat.com>
+ * Fix luksClose operation for stacked DM devices.
+ * Version 1.1.1.
+
+2010-05-03 Milan Broz <mbroz@redhat.com>
+ * Fix automatic dm-crypt module loading.
+ * Escape hyphens in man page.
+ * Version 1.1.1-rc2.
+
+2010-04-30 Milan Broz <mbroz@redhat.com>
+ * Try to use pkgconfig for device mapper library.
+ * Detect old dm-crypt module and disable LUKS suspend/resume.
+ * Fix apitest to work on older systems.
+ * Allow no hash specification in plain device constructor.
+ * Fix luksOpen reading of passphrase on stdin (if "-" keyfile specified).
+ * Fix isLuks to initialise crypto backend (blkid instead is suggested anyway).
+ * Version 1.1.1-rc1.
+
+2010-04-12 Milan Broz <mbroz@redhat.com>
+ * Fix package config to use proper package version.
+ * Avoid class C++ keyword in library header.
+ * Detect and use devmapper udev support if available (disable by --disable-udev).
+
+2010-04-06 Milan Broz <mbroz@redhat.com>
+ * Prefer some device paths in status display.
+ * Support device topology detectionfor data alignment.
+
+2010-02-25 Milan Broz <mbroz@redhat.com>
+ * Do not verify unlocking passphrase in luksAddKey command.
+ * Properly initialise crypto backend in header backup/restore commands.
+
+2010-01-17 Milan Broz <mbroz@redhat.com>
+ * If gcrypt compiled with capabilities, document workaround for cryptsetup (see lib/gcrypt.c).
+ * Version 1.1.0.
+
+2010-01-10 Milan Broz <mbroz@redhat.com>
+ * Fix initialisation of gcrypt during luksFormat.
+ * Convert hash name to lower case in header (fix sha1 backward compatible header)
+ * Check for minimum required gcrypt version.
+
+2009-12-30 Milan Broz <mbroz@redhat.com>
+ * Fix key slot iteration count calculation (small -i value was the same as default).
+ * The slot and key digest iteration minimum is now 1000.
+ * The key digest iteration # is calculated from iteration time (approx 1/8 of that).
+ * Version 1.1.0-rc4.
+
+2009-12-11 Milan Broz <mbroz@redhat.com>
+ * Fix error handling during reading passhrase.
+
+2009-12-01 Milan Broz <mbroz@redhat.com>
+ * Allow changes of default compiled-in cipher parameters through configure.
+ * Switch default key size for LUKS to 256bits.
+ * Switch default plain mode to aes-cbc-essiv:sha256 (default is backward incompatible!).
+
+2009-11-14 Milan Broz <mbroz@redhat.com>
+ * Add CRYPT_ prefix to enum defined in libcryptsetup.h.
+ * Fix status call to fail when running as non-root user.
+ * Check in configure if selinux libraries are required in static version.
+ * Add temporary debug code to find processes locking internal device.
+ * Simplify build system, use autopoint and clean gettext processing.
+ * Use proper NLS macros and detection (so the message translation works again).
+ * Version 1.1.0-rc3.
+
+2009-09-30 Milan Broz <mbroz@redhat.com>
+ * Fix exported symbols and versions in libcryptsetup.
+ * Do not use internal lib functions in cryptsetup.
+ * Add crypt_log to library.
+ * Fix crypt_remove_device (remove, luksClose) implementation.
+ * Move dm backend initialisation to library calls.
+ * Move duplicate Command failed message to verbose level (error is printed always).
+ * Add some password and used algorithms notes to man page.
+ * Version 1.1.0-rc2.
+
+2009-09-28 Milan Broz <mbroz@redhat.com>
+ * Add luksHeaderBackup and luksHeaderRestore commands.
+ * Fail passphrase read if piped input no longer exists.
+ * Version 1.1.0-rc1.
+
+2009-09-15 Milan Broz <mbroz@redhat.com>
+ * Initialize crypto library before LUKS header load.
+ * Fix manpage to not require --size which expands to device size by default.
+
+2009-09-10 Milan Broz <mbroz@redhat.com>
+ * Clean up Makefiles and configure script.
+ * Version 1.1.0-test0.
+
+2009-09-08 Milan Broz <mbroz@redhat.com>
+ * Use dm-uuid for all crypt devices, contains device type and name now.
+ * Try to read first sector from device to properly check that device is ready.
+
+2009-09-02 Milan Broz <mbroz@redhat.com>
+ * Add luksSuspend (freeze device and wipe key) and luksResume (with provided passphrase).
+
+2009-08-30 Milan Broz <mbroz@redhat.com>
+ * Require device device-mapper to build and do not use backend wrapper for dm calls.
+ * Move memory locking and dm initialization to command layer.
+ * Increase priority of process if memory is locked.
+ * Add log macros and make logging more consistent.
+ * Move command successful messages to verbose level.
+ * Introduce --debug parameter.
+ * Move device utils code and provide context parameter (for log).
+ * Keyfile now must be provided by path, only stdin file descriptor is used (api only).
+ * Do not call isatty() on closed keyfile descriptor.
+ * Run performance check for PBKDF2 from LUKS code, do not mix hash algorithms results.
+ * Add ability to provide pre-generated master key and UUID in LUKS header format.
+ * Add LUKS function to verify master key digest.
+ * Move key slot manipulation function into LUKS specific code.
+ * Replace global options struct with separate parameters in helper functions.
+ * Add new libcryptsetup API (documented in libcryptsetup.h).
+ * Implement old API calls using new functions.
+ * Remove old API code helper functions.
+ * Add --master-key-file option for luksFormat and luksAddKey.
+
+2009-08-17 Milan Broz <mbroz@redhat.com>
+ * Fix PBKDF2 speed calculation for large passphrases.
+ * Allow using passphrase provided in options struct for LuksOpen.
+ * Allow restrict keys size in LuksOpen.
+
+2009-07-30 Milan Broz <mbroz@redhat.com>
+ * Fix errors when compiled with LUKS_DEBUG.
+ * Print error when getline fails.
+ * Remove po/cryptsetup-luks.pot, it's autogenerated.
+ * Return ENOENT for empty keyslots, EINVAL will be used later for other type of error.
+ * Switch PBKDF2 from internal SHA1 to libgcrypt, make hash algorithm not hardcoded to SHA1 here.
+ * Add required parameters for changing hash used in LUKS key setup scheme.
+ * Do not export simple XOR helper now used only inside AF functions.
+ * Completely remove internal SHA1 implementation code, not needed anymore.
+ * Enable hash algorithm selection for LUKS through -h luksFormat option.
+
+2009-07-28 Milan Broz <mbroz@redhat.com>
+ * Pad luks header to 512 sector size.
+ * Rework read/write blockwise to not split operation to many pieces.
+ * Use posix_memalign if available.
+
+2009-07-22 Milan Broz <mbroz@redhat.com>
+ * Fix segfault if provided slot in luksKillslot is invalid.
+ * Remove unneeded timeout when remove of temporary device succeeded.
+
+2009-07-22 Milan Broz <mbroz@redhat.com>
+ * version 1.0.7
+
+2009-07-16 Milan Broz <mbroz@redhat.com>
+ * Allow removal of last slot in luksRemoveKey and luksKillSlot.
+
+2009-07-11 Milan Broz <mbroz@redhat.com>
+
+ * Add --disable-selinux option and fix static build if selinux is required.
+ * Reject unsupported --offset and --skip options for luksFormat and update man page.
+
+2009-06-22 Milan Broz <mbroz@redhat.com>
+
+ * Summary of changes in subversion for 1.0.7-rc1:
+ * Various man page fixes.
+ * Set UUID in device-mapper for LUKS devices.
+ * Retain readahead of underlying device.
+ * Display device name when asking for password.
+ * Check device size when loading LUKS header. Remove misleading error message later.
+ * Add error hint if dm-crypt mapping failed.
+ * Use better error messages if device doesn't exist or is already used by other mapping.
+ * Fix make distcheck.
+ * Check if all slots are full during luksAddKey.
+ * Fix segfault in set_error.
+ * Code cleanups, remove precompiled pot files, remove unnecessary files from po directory
+ * Fix uninitialized return value variable in setup.c.
+ * Code cleanups. (thanks to Ivan Stankovic)
+ * Fix wrong output for remaining key at key deletion.
+ * Allow deletion of key slot while other keys have the same key information.
+ * Add missing AM_PROG_CC_C_O to configure.in
+ * Remove duplicate sentence in man page.
+ * Wipe start of device (possible fs signature) before LUKS-formatting.
+ * Do not process configure.in in hidden directories.
+ * Return more descriptive error in case of IO or header format error.
+ * Use remapping to error target instead of calling udevsettle for temporary crypt device.
+ * Check device mapper communication and warn user if device-mapper support missing in kernel.
+ * Fix signal handler to properly close device.
+ * write_lseek_blockwise: declare innerCount outside the if block.
+ * add -Wall to the default CFLAGS. fix some signedness issues.
+ * Error handling improvement.
+ * Add non-exclusive override to interface definition.
+ * Refactor key slot selection into keyslot_from_option.
+
+2007-05-01 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/backends.c, man/cryptsetup.8: Apply patch from Ludwig Nussel
+ <ludwig.nussel@suse.de>, for old SuSE compat hashing.
+
+2007-04-16 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Summary of changes in subversion:
+ Fix segfault for key size > 32 bytes.
+ Kick ancient header version conversion.
+ Fix http://bugs.debian.org/403075
+ No passwort retrying for I/O errors.
+ Fix hang on "-i 0".
+ Fix parenthesization error that prevented --tries from working
+ correctly.
+
+2006-11-28 gettextize <bug-gnu-gettext@gnu.org>
+
+ * m4/gettext.m4: Upgrade to gettext-0.15.
+ * m4/glibc2.m4: New file, from gettext-0.15.
+ * m4/intmax.m4: New file, from gettext-0.15.
+ * m4/inttypes-h.m4: New file, from gettext-0.15.
+ * m4/inttypes-pri.m4: Upgrade to gettext-0.15.
+ * m4/lib-link.m4: Upgrade to gettext-0.15.
+ * m4/lib-prefix.m4: Upgrade to gettext-0.15.
+ * m4/lock.m4: New file, from gettext-0.15.
+ * m4/longdouble.m4: New file, from gettext-0.15.
+ * m4/longlong.m4: New file, from gettext-0.15.
+ * m4/nls.m4: Upgrade to gettext-0.15.
+ * m4/po.m4: Upgrade to gettext-0.15.
+ * m4/printf-posix.m4: New file, from gettext-0.15.
+ * m4/signed.m4: New file, from gettext-0.15.
+ * m4/size_max.m4: New file, from gettext-0.15.
+ * m4/visibility.m4: New file, from gettext-0.15.
+ * m4/wchar_t.m4: New file, from gettext-0.15.
+ * m4/wint_t.m4: New file, from gettext-0.15.
+ * m4/xsize.m4: New file, from gettext-0.15.
+ * m4/Makefile.am: New file.
+ * configure.in (AC_OUTPUT): Add m4/Makefile.
+ (AM_GNU_GETTEXT_VERSION): Bump to 0.15.
+
+2006-10-22 David Härdeman <david@hardeman.nu>
+
+ * Allow hashing of keys passed through stdin.
+
+2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: 1.0.4 release
+
+2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * man/cryptsetup.8: Document --tries switch; patch by Jonas
+ Meurer.
+
+2006-10-13 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c: Added terminal timeout rewrite as forwarded by
+ Jonas Meurer
+
+2006-10-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Merged patch from Marc Merlin <marc@merlins.org> to allow user
+ selection of key slot.
+
+2006-09-26 gettextize <bug-gnu-gettext@gnu.org>
+
+ * m4/codeset.m4: Upgrade to gettext-0.14.4.
+ * m4/gettext.m4: Upgrade to gettext-0.14.4.
+ * m4/glibc2.m4: New file, from gettext-0.14.4.
+ * m4/glibc21.m4: Upgrade to gettext-0.14.4.
+ * m4/iconv.m4: Upgrade to gettext-0.14.4.
+ * m4/intdiv0.m4: Upgrade to gettext-0.14.4.
+ * m4/intmax.m4: New file, from gettext-0.14.4.
+ * m4/inttypes.m4: Upgrade to gettext-0.14.4.
+ * m4/inttypes_h.m4: Upgrade to gettext-0.14.4.
+ * m4/inttypes-pri.m4: Upgrade to gettext-0.14.4.
+ * m4/isc-posix.m4: Upgrade to gettext-0.14.4.
+ * m4/lcmessage.m4: Upgrade to gettext-0.14.4.
+ * m4/lib-ld.m4: Upgrade to gettext-0.14.4.
+ * m4/lib-link.m4: Upgrade to gettext-0.14.4.
+ * m4/lib-prefix.m4: Upgrade to gettext-0.14.4.
+ * m4/longdouble.m4: New file, from gettext-0.14.4.
+ * m4/longlong.m4: New file, from gettext-0.14.4.
+ * m4/nls.m4: Upgrade to gettext-0.14.4.
+ * m4/po.m4: Upgrade to gettext-0.14.4.
+ * m4/printf-posix.m4: New file, from gettext-0.14.4.
+ * m4/progtest.m4: Upgrade to gettext-0.14.4.
+ * m4/signed.m4: New file, from gettext-0.14.4.
+ * m4/size_max.m4: New file, from gettext-0.14.4.
+ * m4/stdint_h.m4: Upgrade to gettext-0.14.4.
+ * m4/uintmax_t.m4: Upgrade to gettext-0.14.4.
+ * m4/ulonglong.m4: Upgrade to gettext-0.14.4.
+ * m4/wchar_t.m4: New file, from gettext-0.14.4.
+ * m4/wint_t.m4: New file, from gettext-0.14.4.
+ * m4/xsize.m4: New file, from gettext-0.14.4.
+ * Makefile.am (ACLOCAL_AMFLAGS): New variable.
+ * configure.in (AM_GNU_GETTEXT_VERSION): Bump to 0.14.4.
+
+2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: 1.0.4-rc2
+
+2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * luks/Makefile.am: Add a few regression tests
+
+2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (get_key): Applied patch from David Härdeman
+ <david@2gen.com> for reading binary keys from stdin using
+ the "-" as key file.
+
+2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (__crypt_luks_add_key): For checking options struct
+ (optionsCheck) filter out CRYPT_FLAG_VERIFY and
+ CRYPT_FLAG_VERIFY_IF_POSSIBLE, so that in no case password verification is done
+ for password retrieval.
+
+2006-08-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: Merge Patch from http://bugs.gentoo.org/show_bug.cgi?id=132126 for sepol
+
+2006-07-23 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Applied patches from David Härdeman <david@2gen.com> to fix 64
+ bit compiler warning issues.
+
+2006-05-19 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Applied patches from Jonas Meurer
+ - fix terminal status after timeout
+ - add remark for --tries to manpage
+ - allow more than 32 chars from standard input.
+ - exit status fix for cryptsetup status.
+
+2006-05-06 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c (yesDialog): Fix getline problem for 64-bit archs.
+
+2006-04-05 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: Release 1.0.3.
+
+ * Applied patch by Johannes Weißl for more meaningful exit codes
+ and password retries
+
+2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (__crypt_create_device): (char *) -> (const char *)
+
+2006-03-30 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Apply alignPayload patch from Peter Palfrader <weasel@debian.org>
+
+2006-03-15 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: 1.0.3-rc3. Most displease release ever.
+ * lib/setup.c (__crypt_create_device): More verbose error message.
+
+2006-02-26 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c: Revert to 1.0.1 key reading.
+
+2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * man/cryptsetup.8: merge patch from Jonas Meurer
+
+2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: 1.0.3-rc2
+
+2006-02-25 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/libdevmapper.c (dm_create_device): Remove dup check here.
+ * lib/setup.c (__crypt_luks_open): Adopt same dup check as regular
+ create command.
+
+2006-02-22 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: Spin 1.0.3-rc1
+
+2006-02-22 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c (action_create): Change defaulting.
+ (action_luksFormat): Change defaulting.
+
+ * lib/setup.c (parse_into_name_and_mode): Revert that default
+ change. This is FORBIDDEN here, as it will change cryptsetup
+ entire default. This is BAD in a non-LUKS world.
+
+2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * luks/keyencryption.c (setup_mapping): Add proper size restriction to mapping.
+ (LUKS_endec_template): Add more verbose error message.
+
+2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/libdevmapper.c (dm_query_device): Incorporate patch from
+ Bastian Blank
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=344313
+
+2006-02-21 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c: Rename show_error -> show_status.
+
+2006-02-20 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/libdevmapper.c (dm_create_device): Prevent existing mapping
+ from being removed when a mapping with the same name is added
+
+ * Add timeout patch from Jonas Meurer
+
+ * src/cryptsetup.c: Remove conditional error printing to enable
+ printing the no-error msg (Command successful). Verify passphrase
+ for LUKS volumes.
+ (main): Add no-verify-passphrase
+
+ * lib/setup.c (parse_into_name_and_mode): Change default mode complition to essiv:sha256.
+
+2006-01-04 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c (help): Merge patch from Gentoo: change gettext(..) to _(..).
+
+2005-12-06 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * man/cryptsetup.8: Correct "seconds" to "microseconds" in the explanation for -i.
+
+2005-11-09 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c (main): Add version string.
+
+2005-11-08 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/backends.c: compile fix.
+
+2005-09-11 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (get_key): Fixed another incompatibility from my
+ get_key rewrite with original cryptsetup.
+
+2005-09-11 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Merged changes from Florian Knauf's fk02 branch.
+
+2005-09-08 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (get_key): Fixed another incompatibility with
+ original cryptsetup.
+
+2005-08-20 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * Checked in a patch from Michael Gebetsroither <gebi@sbox.tugraz.at>
+ to silent all confirmation dialogs.
+
+2005-06-23 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c (help): print PACKAGE_STRING
+
+2005-06-20 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * luks/keymanage.c (LUKS_set_key): Security check against header manipulation
+
+ * src/cryptsetup.c (action_luksDelKey): Safety check in luksDelKey
+
+ * luks/keymanage.c: Changed disk layout generation to align key material to 4k boundaries.
+ (LUKS_is_last_keyslot): Added LUKS_is_last_keyslot function.
+
+ * Applied patch from Bill Nottingham fixing a lot of prototypes.
+
+ * src/cryptsetup.c (action_luksOpen): Add support for -r flag.
+
+ * configure.in: Version bump 1.0.1
+
+2005-06-16 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (__crypt_luks_open): Remove mem leaking of dmCipherSpec.
+ (get_key): Fix missing zero termination for read string.
+
+2005-06-12 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * luks/keyencryption.c (setup_mapping): Added CRYPT_FLAG_READONLY in case of O_RDONLY mode
+
+2005-06-11 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: Version bump 1.0.1-pre
+
+2005-06-09 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/utils.c: Added write_llseek_blocksize method to support sector wiping on sector_size != 512
+ media
+
+2005-05-23 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/setup.c (crypt_luksDelKey): Added missing return statement
+ (setup_leave): Added missing return statement
+
+ * luks/keyencryption.c (clear_mapping): Added missing return statement
+
+2005-05-19 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * lib/utils.c (write_blockwise, read_blockwise): Changed to soft bsize instead of SECTOR_SIZE
+
+ * luks/keymanage.c (wipe): Changed open mode to O_DIRECT | O_SYNC, and changed write
+ to use the blockwise write helper
+
+2005-04-21 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * man/cryptsetup.8: Corrected an error, thanks to Dick Middleton.
+
+2005-04-09 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * luks/sha/hmac.c: Add 64 bit bug fix courtesy to
+ Oliver Paukstadt <pstadt@sourcentral.org>.
+
+ * luks/pbkdf.c, luks/keyencryption.c, luks/keymanage.c, luks/af.c: Added a license
+ disclaimer and remove option for "any future GPL versions".
+
+2005-03-25 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * configure.in: man page Makefile. Version bump 1.0.
+
+ * man/cryptsetup.8: finalize man page and move to section 8.
+
+ * src/cryptsetup.c (action_luksFormat): Add "are you sure" for interactive sessions.
+
+ * lib/setup.c (crypt_luksDump), src/cryptsetup.c: add LUKS dump command
+
+2005-03-24 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * src/cryptsetup.c, luks/Makefile.am (test), lib/setup.c (setup_enter):
+ rename luksInit to luksFormat
+
+2005-03-12 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * man/cryptsetup.1: Add man page.
+
+ * lib/setup.c: Remove unnecessary LUKS_write_phdr call, so the
+ phdr is written after passphrase reading, so the user can change
+ his mind, and not have a partial written LUKS header on it's disk.
+
+2005-02-09 Clemens Fruhwirth <clemens@endorphin.org>
+
+ * luks/keymanage.c (LUKS_write_phdr): converted argument phdr to
+ pointer, and make a copy of phdr for conversion
+
+ * configure.in: Version dump.
+
+ * luks/keyencryption.c: Convert to read|write_blockwise.
+
+ * luks/keymanage.c: Convert to read|write_blockwise.
+
+ * lib/utils.c: Add read|write_blockwise functions, to use in
+ O_DIRECT file accesses.
+
+2004-03-11 Thursday 15:52 Jana Saout <jana@saout.de>
+
+ * lib/blockdev.h: BLKGETSIZE64 really uses size_t as third
+ argument, the rest is wrong.
+
+2004-03-10 Wednesday 17:50 Jana Saout <jana@saout.de>
+
+ * lib/: libcryptsetup.h, libdevmapper.c: Small fixes.
+
+2004-03-09 Tuesday 21:41 Jana Saout <jana@saout.de>
+
+ * lib/internal.h, lib/libcryptsetup.h, lib/libdevmapper.c,
+ lib/setup.c, po/de.po, src/cryptsetup.c: Added internal flags to
+ keep track of malloc'ed return values in struct crypt_options and
+ add a function to free the memory. Also add a readonly flag to
+ libcryptsetup.
+
+2004-03-09 Tuesday 16:03 Jana Saout <jana@saout.de>
+
+ * ChangeLog, configure.in, setup-gettext, lib/Makefile.am,
+ lib/backends.c, lib/blockdev.h, lib/gcrypt.c, lib/internal.h,
+ lib/libcryptsetup.h, lib/libdevmapper.c, lib/setup.c,
+ lib/utils.c, po/de.po, src/Makefile.am, src/cryptsetup.c: More
+ reorganization work.
+
+2004-03-08 Monday 01:38 Jana Saout <jana@saout.de>
+
+ * ChangeLog, Makefile.am, acinclude.m4, configure.in,
+ lib/Makefile.am, lib/backends.c, lib/blockdev.h, lib/gcrypt.c,
+ lib/libdevmapper.c, lib/setup.c, lib/utils.c, po/de.po,
+ src/Makefile.am: BLKGETSIZE64 fixes and started modularity
+ enhancements
+
+2004-03-04 Thursday 21:06 Jana Saout <jana@saout.de>
+
+ * Makefile.am, po/de.po, src/cryptsetup.c, src/cryptsetup.h: First
+ backward compatible working version.
+
+2004-03-04 Thursday 00:42 Jana Saout <jana@saout.de>
+
+ * NEWS, AUTHORS, ChangeLog, Makefile.am, README, autogen.sh,
+ configure.in, setup-gettext, po/ChangeLog, po/LINGUAS,
+ po/POTFILES.in, po/de.po, src/cryptsetup.c, src/cryptsetup.h,
+ src/Makefile.am (utags: initial): Initial checkin.
+
+2004-03-04 Thursday 00:42 Jana Saout <jana@saout.de>
+
+ * NEWS, AUTHORS, ChangeLog, Makefile.am, README, autogen.sh,
+ configure.in, setup-gettext, po/ChangeLog, po/LINGUAS,
+ po/POTFILES.in, po/de.po, src/cryptsetup.c, src/cryptsetup.h,
+ src/Makefile.am: Initial revision
diff --git a/docs/Keyring.txt b/docs/Keyring.txt
new file mode 100644
index 0000000..bdcc838
--- /dev/null
+++ b/docs/Keyring.txt
@@ -0,0 +1,56 @@
+Integration with kernel keyring service
+---------------------------------------
+
+We have two different use cases for kernel keyring service:
+
+I) Volume keys
+
+Since upstream kernel 4.10 dm-crypt device mapper target allows loading volume
+key (VK) in kernel keyring service. The key offloaded in kernel keyring service
+is only referenced (by key description) in dm-crypt target and the VK is therefore
+no longer stored directly in dm-crypt target. Starting with cryptsetup 2.0 we
+load VK in kernel keyring by default for LUKSv2 devices (when dm-crypt with the
+feature is available).
+
+Currently cryptsetup loads VK in 'logon' type kernel key so that VK is passed in
+the kernel and can't be read from userspace afterward. Also cryptsetup loads VK in
+thread keyring (before passing the reference to dm-crypt target) so that the key
+lifetime is directly bound to the process that performs the dm-crypt setup. When
+cryptsetup process exits (for whatever reason) the key gets unlinked in kernel
+automatically. In summary, the key description visible in dm-crypt table line is
+a reference to VK that usually no longer exists in kernel keyring service if you
+used cryptsetup to for device activation.
+
+Using this feature dm-crypt no longer maintains a direct key copy (but there's
+always at least one copy in kernel crypto layer).
+
+II) Keyslot passphrase
+The second use case for kernel keyring is to allow cryptsetup reading the keyslot
+passphrase stored in kernel keyring instead. The user may load passphrase in kernel
+keyring and notify cryptsetup to read it from there later. Currently, cryptsetup
+cli supports kernel keyring for passphrase only via LUKS2 internal token
+(luks2-keyring). Library also provides a general method for device activation by
+reading passphrase from keyring: crypt_activate_by_keyring(). The key type
+for use case II) must always be 'user' since we need to read the actual key
+data from userspace unlike with VK in I). Ability to read keyslot passphrase
+from kernel keyring also allows easily auto-activate LUKS2 devices.
+
+Simple example how to use kernel keyring for keyslot passphrase:
+
+1) create LUKS2 keyring token for keyslot 0 (in LUKS2 device/image)
+cryptsetup token add --key-description my:key -S 0 /dev/device
+
+2) Load keyslot passphrase in user keyring
+read -s -p "Keyslot passphrase: "; echo -n $REPLY | keyctl padd user my:key @u
+
+3) Activate device using passphrase stored in kernel keyring
+cryptsetup open /dev/device my_unlocked_device
+
+4a) unlink the key when no longer needed by
+keyctl unlink %user:my:key @u
+
+4b) or revoke it immediately by
+keyctl revoke %user:my:key
+
+If cryptsetup asks for passphrase in step 3) something went wrong with keyring
+activation. See --debug output then.
diff --git a/docs/LUKS2-locking.txt b/docs/LUKS2-locking.txt
new file mode 100644
index 0000000..e401b61
--- /dev/null
+++ b/docs/LUKS2-locking.txt
@@ -0,0 +1,61 @@
+LUKS2 device locking overview
+=============================
+
+Why
+~~~
+
+LUKS2 format keeps two identical copies of metadata stored consecutively
+at the head of metadata device (file or bdev). The metadata
+area (both copies) must be updated in a single atomic operation to avoid
+header corruption during concurrent write.
+
+While with LUKS1 users may have clear knowledge of when a LUKS header is
+being updated (written to) or when it's being read solely the need for
+locking with legacy format was not so obvious as it is with the LUKSv2 format.
+
+With LUKS2 the boundary between read-only and read-write is blurry and what
+used to be the exclusively read-only operation (i.e., cryptsetup open command) may
+easily become read-update operation silently without user's knowledge.
+Major feature of LUKS2 format is resilience against accidental
+corruption of metadata (i.e., partial header overwrite by parted or cfdisk
+while creating partition on mistaken block device).
+Such header corruption is detected early on header read and auto-recovery
+procedure takes place (the corrupted header with checksum mismatch is being
+replaced by the secondary one if that one is intact).
+On current Linux systems header load operation may be triggered without user
+direct intervention for example by udev rule or from systemd service.
+Such clash of header read and auto-recovery procedure could have severe
+consequences with the worst case of having LUKS2 device unaccessible or being
+broken beyond repair.
+
+The whole locking of LUKSv2 device headers split into two categories depending
+what backend the header is stored on:
+
+I) block device
+~~~~~~~~~~~~~~~
+
+We perform flock() on file descriptors of files stored in a private
+directory (by default /run/lock/cryptsetup). The file name is derived
+from major:minor couple of affected block device. Note we recommend
+that access to private locking directory is supposed to be limited
+to superuser only. For this method to work the distribution needs
+to install the locking directory with appropriate access rights.
+
+II) regular files
+~~~~~~~~~~~~~~~~~
+
+First notable difference between headers stored in a file
+vs. headers stored in a block device is that headers in a file may be
+manipulated by the regular user unlike headers on block devices. Therefore
+we perform flock() protection on file with the luks2 header directly.
+
+Limitations
+~~~~~~~~~~~
+
+a) In general, the locking model provides serialization of I/Os targeting
+the header only. It means the header is always written or read at once
+while locking is enabled.
+We do not suppress any other negative effect that two or more concurrent
+writers of the same header may cause.
+
+b) The locking is not cluster aware in any way.
diff --git a/docs/doxyfile b/docs/doxyfile
new file mode 100644
index 0000000..0943772
--- /dev/null
+++ b/docs/doxyfile
@@ -0,0 +1,335 @@
+# Doxyfile 1.9.1
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "cryptsetup API"
+PROJECT_NUMBER =
+PROJECT_BRIEF = "Public cryptsetup API"
+PROJECT_LOGO =
+OUTPUT_DIRECTORY = doxygen_api_docs
+CREATE_SUBDIRS = NO
+ALLOW_UNICODE_NAMES = NO
+OUTPUT_LANGUAGE = English
+OUTPUT_TEXT_DIRECTION = None
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+JAVADOC_BANNER = NO
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+PYTHON_DOCSTRING = YES
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+OPTIMIZE_OUTPUT_SLICE = NO
+EXTENSION_MAPPING =
+MARKDOWN_SUPPORT = YES
+TOC_INCLUDE_HEADINGS = 5
+AUTOLINK_SUPPORT = YES
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+GROUP_NESTED_COMPOUNDS = NO
+SUBGROUPING = YES
+INLINE_GROUPED_CLASSES = NO
+INLINE_SIMPLE_STRUCTS = NO
+TYPEDEF_HIDES_STRUCT = YES
+LOOKUP_CACHE_SIZE = 0
+NUM_PROC_THREADS = 1
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_PRIV_VIRTUAL = NO
+EXTRACT_PACKAGE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+RESOLVE_UNNAMED_PARAMS = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+HIDE_COMPOUND_REFERENCE= NO
+SHOW_INCLUDE_FILES = YES
+SHOW_GROUPED_MEMB_INC = NO
+FORCE_LOCAL_INCLUDES = NO
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_MEMBERS_CTORS_1ST = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+STRICT_PROTO_MATCHING = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+LAYOUT_FILE =
+CITE_BIB_FILES =
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_AS_ERROR = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = doxygen_index.h \
+ ../lib/libcryptsetup.h
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH = examples
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+FILTER_SOURCE_PATTERNS =
+USE_MDFILE_AS_MAINPAGE =
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+SOURCE_TOOLTIPS = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+CLANG_ASSISTED_PARSING = NO
+CLANG_ADD_INC_PATHS = YES
+CLANG_OPTIONS =
+CLANG_DATABASE_PATH =
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
+HTML_EXTRA_FILES =
+HTML_COLORSTYLE_HUE = 220
+HTML_COLORSTYLE_SAT = 100
+HTML_COLORSTYLE_GAMMA = 80
+HTML_TIMESTAMP = YES
+HTML_DYNAMIC_MENUS = YES
+HTML_DYNAMIC_SECTIONS = NO
+HTML_INDEX_NUM_ENTRIES = 100
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+DOCSET_PUBLISHER_NAME = Publisher
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+GENERATE_QHP = NO
+QCH_FILE =
+QHP_NAMESPACE = org.doxygen.Project
+QHP_VIRTUAL_FOLDER = doc
+QHP_CUST_FILTER_NAME =
+QHP_CUST_FILTER_ATTRS =
+QHP_SECT_FILTER_ATTRS =
+QHG_LOCATION =
+GENERATE_ECLIPSEHELP = NO
+ECLIPSE_DOC_ID = org.doxygen.Project
+DISABLE_INDEX = NO
+GENERATE_TREEVIEW = NO
+ENUM_VALUES_PER_LINE = 4
+TREEVIEW_WIDTH = 250
+EXT_LINKS_IN_WINDOW = NO
+HTML_FORMULA_FORMAT = png
+FORMULA_FONTSIZE = 10
+FORMULA_TRANSPARENT = YES
+FORMULA_MACROFILE =
+USE_MATHJAX = NO
+MATHJAX_FORMAT = HTML-CSS
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+MATHJAX_EXTENSIONS =
+MATHJAX_CODEFILE =
+SEARCHENGINE = YES
+SERVER_BASED_SEARCH = NO
+EXTERNAL_SEARCH = NO
+SEARCHENGINE_URL =
+SEARCHDATA_FILE = searchdata.xml
+EXTERNAL_SEARCH_ID =
+EXTRA_SEARCH_MAPPINGS =
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+LATEX_MAKEINDEX_CMD = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4
+EXTRA_PACKAGES =
+LATEX_HEADER =
+LATEX_FOOTER =
+LATEX_EXTRA_STYLESHEET =
+LATEX_EXTRA_FILES =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+LATEX_SOURCE_CODE = NO
+LATEX_BIB_STYLE = plain
+LATEX_TIMESTAMP = NO
+LATEX_EMOJI_DIRECTORY =
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+RTF_SOURCE_CODE = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_SUBDIR =
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_PROGRAMLISTING = YES
+XML_NS_MEMB_FILE_SCOPE = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+GENERATE_DOCBOOK = NO
+DOCBOOK_OUTPUT = docbook
+DOCBOOK_PROGRAMLISTING = NO
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+EXTERNAL_PAGES = YES
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+DIA_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+DOT_NUM_THREADS = 0
+DOT_FONTNAME = Helvetica
+DOT_FONTSIZE = 10
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+UML_LIMIT_NUM_FIELDS = 10
+DOT_UML_DETAILS = NO
+DOT_WRAP_THRESHOLD = 17
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+INTERACTIVE_SVG = NO
+DOT_PATH =
+DOTFILE_DIRS =
+MSCFILE_DIRS =
+DIAFILE_DIRS =
+PLANTUML_JAR_PATH =
+PLANTUML_CFG_FILE =
+PLANTUML_INCLUDE_PATH =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
diff --git a/docs/doxygen_index.h b/docs/doxygen_index.h
new file mode 100644
index 0000000..8bdf05f
--- /dev/null
+++ b/docs/doxygen_index.h
@@ -0,0 +1,110 @@
+/*! \mainpage Cryptsetup API
+ *
+ * <b>The</b> documentation covers public parts of cryptsetup API. In the following sections you'll find
+ * the examples that describe some features of cryptsetup API.
+ * For more info about libcryptsetup API versions see
+ * <a href="https://gitlab.com/cryptsetup/cryptsetup/wikis/ABI-tracker/timeline/libcryptsetup/index.html">API Tracker</a>.
+ *
+ * <OL type="A">
+ * <LI>@ref cexamples "Cryptsetup API examples"</LI>
+ * <OL type="1">
+ * <LI>@ref cluks "crypt_luks_usage" - cryptsetup LUKS device type usage examples</LI>
+ * <UL>
+ * <LI>@ref cinit "crypt_init()"</LI>
+ * <LI>@ref cformat "crypt_format()" - header and payload on mutual device</LI>
+ * <LI>@ref ckeys "Keyslot operations" </LI>
+ * <UL>
+ * <LI>@ref ckeyslot_vol "crypt_keyslot_add_by_volume_key()"</LI>
+ * <LI>@ref ckeyslot_pass "crypt_keyslot_add_by_passphrase()"</LI>
+ * </UL>
+ * <LI>@ref cload "crypt_load()"
+ * <LI>@ref cactivate "crypt_activate_by_passphrase()"</LI>
+ * <LI>@ref cactive_pars "crypt_get_active_device()"</LI>
+ * <LI>@ref cinit_by_name "crypt_init_by_name()"</LI>
+ * <LI>@ref cdeactivate "crypt_deactivate()"</LI>
+ * <LI>@ref cluks_ex "crypt_luks_usage.c"</LI>
+ * </UL>
+ * <LI>@ref clog "crypt_log_usage" - cryptsetup logging API examples</LI>
+ * </OL>
+ * </OL>
+ *
+ * @section cexamples Cryptsetup API examples
+ * @section cluks crypt_luks_usage - cryptsetup LUKS device type usage
+ * @subsection cinit crypt_init()
+ * Every time you need to do something with cryptsetup or dmcrypt device
+ * you need a valid context. The first step to start your work is
+ * @ref crypt_init call. You can call it either with path
+ * to the block device or path to the regular file. If you don't supply the path,
+ * empty context is initialized.
+ *
+ * @subsection cformat crypt_format() - header and payload on mutual device
+ * This section covers basic use cases for formatting LUKS devices. Format operation
+ * sets device type in context and in case of LUKS header is written at the beginning
+ * of block device. In the example below we use the scenario where LUKS header and data
+ * are both stored on the same device. There's also a possibility to store header and
+ * data separately.
+ *
+ * <B>Bear in mind</B> that @ref crypt_format() is destructive operation and it
+ * overwrites part of the backing block device.
+ *
+ * @subsection ckeys Keyslot operations examples
+ * After successful @ref crypt_format of LUKS device, volume key is not stored
+ * in a persistent way on the device. Keyslot area is an array beyond LUKS header, where
+ * volume key is stored in the encrypted form using user input passphrase. For more info about
+ * LUKS keyslots and how it's actually protected, please look at
+ * <A HREF="https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification">LUKS specification</A>.
+ * There are two basic methods to create a new keyslot:
+ *
+ * @subsection ckeyslot_vol crypt_keyslot_add_by_volume_key()
+ * Creates a new keyslot directly by encrypting volume_key stored in the device
+ * context. Passphrase should be supplied or user is prompted if passphrase param is
+ * NULL.
+ *
+ * @subsection ckeyslot_pass crypt_keyslot_add_by_passphrase()
+ * Creates a new keyslot for the volume key by opening existing active keyslot,
+ * extracting volume key from it and storing it into a new keyslot
+ * protected by a new passphrase
+ *
+ * @subsection cload crypt_load()
+ * Function loads header from backing block device into device context.
+ *
+ * @subsection cactivate crypt_activate_by_passphrase()
+ * Activates crypt device by user supplied password for keyslot containing the volume_key.
+ * If <I>keyslot</I> parameter is set to <I>CRYPT_ANY_SLOT</I> then all active keyslots
+ * are tried one by one until the volume key is found.
+ *
+ * @subsection cactive_pars crypt_get_active_device()
+ * This call returns structure containing runtime attributes of active device.
+ *
+ * @subsection cinit_by_name crypt_init_by_name()
+ * In case you need to do operations with active device (device which already
+ * has its corresponding mapping) and you miss valid device context stored in
+ * *crypt_device reference, you should use this call. Function tries to
+ * get path to backing device from DM, initializes context for it and loads LUKS
+ * header.
+ *
+ * @subsection cdeactivate crypt_deactivate()
+ * Deactivates crypt device (removes DM mapping and safely erases volume key from kernel).
+ *
+ * @subsection cluks_ex crypt_luks_usage.c - Complex example
+ * To compile and run use following commands in examples directory:
+ *
+ * @code
+ * make
+ * ./crypt_luks_usage _path_to_[block_device]_file
+ * @endcode
+ * Note that you need to have the cryptsetup library compiled. @include crypt_luks_usage.c
+ *
+ * @section clog crypt_log_usage - cryptsetup logging API example
+ * Example describes basic use case for cryptsetup logging. To compile and run
+ * use following commands in examples directory:
+ *
+ * @code
+ * make
+ * ./crypt_log_usage
+ * @endcode
+ * Note that you need to have the cryptsetup library compiled. @include crypt_log_usage.c
+ *
+ * @example crypt_luks_usage.c
+ * @example crypt_log_usage.c
+ */
diff --git a/docs/examples/Makefile b/docs/examples/Makefile
new file mode 100644
index 0000000..845b6cb
--- /dev/null
+++ b/docs/examples/Makefile
@@ -0,0 +1,17 @@
+TARGETS=crypt_log_usage crypt_luks_usage
+CFLAGS=-O0 -g -Wall -D_GNU_SOURCE
+LDLIBS=-lcryptsetup
+CC=gcc
+
+all: $(TARGETS)
+
+crypt_log_usage: crypt_log_usage.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+crypt_luks_usage: crypt_luks_usage.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+clean:
+ rm -f *.o *~ core $(TARGETS)
+
+.PHONY: clean
diff --git a/docs/examples/crypt_log_usage.c b/docs/examples/crypt_log_usage.c
new file mode 100644
index 0000000..3d08c34
--- /dev/null
+++ b/docs/examples/crypt_log_usage.c
@@ -0,0 +1,94 @@
+/*
+ * libcryptsetup API log example
+ *
+ * Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <libcryptsetup.h>
+
+/*
+ * This is an example of crypt_set_log_callback API callback.
+ *
+ */
+static void simple_syslog_wrapper(int level, const char *msg, void *usrptr)
+{
+ const char *prefix = (const char *)usrptr;
+ int priority;
+
+ switch(level) {
+ case CRYPT_LOG_NORMAL: priority = LOG_NOTICE; break;
+ case CRYPT_LOG_ERROR: priority = LOG_ERR; break;
+ case CRYPT_LOG_VERBOSE: priority = LOG_INFO; break;
+ case CRYPT_LOG_DEBUG: priority = LOG_DEBUG; break;
+ default:
+ fprintf(stderr, "Unsupported log level requested!\n");
+ return;
+ }
+
+ if (prefix)
+ syslog(priority, "%s:%s", prefix, msg);
+ else
+ syslog(priority, "%s", msg);
+}
+
+int main(void)
+{
+ struct crypt_device *cd;
+ char usrprefix[] = "cslog_example";
+ int r;
+
+ if (geteuid()) {
+ printf("Using of libcryptsetup requires super user privileges.\n");
+ return 1;
+ }
+
+ openlog("cryptsetup", LOG_CONS | LOG_PID, LOG_USER);
+
+ /* Initialize empty crypt device context */
+ r = crypt_init(&cd, NULL);
+ if (r < 0) {
+ printf("crypt_init() failed.\n");
+ return 2;
+ }
+
+ /* crypt_set_log_callback() - register a log callback for crypt context */
+ crypt_set_log_callback(cd, &simple_syslog_wrapper, (void *)usrprefix);
+
+ /* send messages ithrough the crypt_log() interface */
+ crypt_log(cd, CRYPT_LOG_NORMAL, "This is normal log message");
+ crypt_log(cd, CRYPT_LOG_ERROR, "This is error log message");
+ crypt_log(cd, CRYPT_LOG_VERBOSE, "This is verbose log message");
+ crypt_log(cd, CRYPT_LOG_DEBUG, "This is debug message");
+
+ /* release crypt context */
+ crypt_free(cd);
+
+ /* Initialize default (global) log callback */
+ crypt_set_log_callback(NULL, &simple_syslog_wrapper, NULL);
+
+ crypt_log(NULL, CRYPT_LOG_NORMAL, "This is normal log message");
+ crypt_log(NULL, CRYPT_LOG_ERROR, "This is error log message");
+ crypt_log(NULL, CRYPT_LOG_VERBOSE, "This is verbose log message");
+ crypt_log(NULL, CRYPT_LOG_DEBUG, "This is debug message");
+
+ closelog();
+ return 0;
+}
diff --git a/docs/examples/crypt_luks_usage.c b/docs/examples/crypt_luks_usage.c
new file mode 100644
index 0000000..d7779bd
--- /dev/null
+++ b/docs/examples/crypt_luks_usage.c
@@ -0,0 +1,250 @@
+/*
+ * libcryptsetup API - using LUKS device example
+ *
+ * Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <libcryptsetup.h>
+
+static int format_and_add_keyslots(const char *path)
+{
+ struct crypt_device *cd;
+ int r;
+
+ /*
+ * The crypt_init() call is used to initialize crypt_device context,
+ * The path parameter specifies a device path.
+ *
+ * For path, you can use either link to a file or block device.
+ * The loopback device will be detached automatically.
+ */
+
+ r = crypt_init(&cd, path);
+ if (r < 0) {
+ printf("crypt_init() failed for %s.\n", path);
+ return r;
+ }
+
+ printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
+
+ /*
+ * So far, no data were written to the device.
+ */
+ printf("Device %s will be formatted as a LUKS device after 5 seconds.\n"
+ "Press CTRL+C now if you want to cancel this operation.\n", path);
+ sleep(5);
+
+ /*
+ * NULLs for uuid and volume_key means that these attributes will be
+ * generated during crypt_format().
+ */
+ r = crypt_format(cd, /* crypt context */
+ CRYPT_LUKS2, /* LUKS2 is a new LUKS format; use CRYPT_LUKS1 for LUKS1 */
+ "aes", /* used cipher */
+ "xts-plain64", /* used block mode and IV */
+ NULL, /* generate UUID */
+ NULL, /* generate volume key from RNG */
+ 512 / 8, /* 512bit key - here AES-256 in XTS mode, size is in bytes */
+ NULL); /* default parameters */
+
+ if (r < 0) {
+ printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
+ crypt_free(cd);
+ return r;
+ }
+
+ /*
+ * The device now contains a LUKS header, but there is no active keyslot.
+ *
+ * crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot.
+ *
+ * After format, the volume key is stored internally.
+ */
+ r = crypt_keyslot_add_by_volume_key(cd, /* crypt context */
+ CRYPT_ANY_SLOT, /* just use first free slot */
+ NULL, /* use internal volume key */
+ 0, /* unused (size of volume key) */
+ "foo", /* passphrase - NULL means query*/
+ 3); /* size of passphrase */
+
+ if (r < 0) {
+ printf("Adding keyslot failed.\n");
+ crypt_free(cd);
+ return r;
+ }
+
+ printf("The first keyslot is initialized.\n");
+
+ /*
+ * Add another keyslot, now authenticating with the first keyslot.
+ * It decrypts the volume key from the first keyslot and creates a new one with the specified passphrase.
+ */
+ r = crypt_keyslot_add_by_passphrase(cd, /* crypt context */
+ CRYPT_ANY_SLOT, /* just use first free slot */
+ "foo", 3, /* passphrase for the old keyslot */
+ "bar", 3); /* passphrase for the new kesylot */
+ if (r < 0) {
+ printf("Adding keyslot failed.\n");
+ crypt_free(cd);
+ return r;
+ }
+
+ printf("The second keyslot is initialized.\n");
+
+ crypt_free(cd);
+ return 0;
+}
+
+static int activate_and_check_status(const char *path, const char *device_name)
+{
+ struct crypt_device *cd;
+ struct crypt_active_device cad;
+ int r;
+
+ /*
+ * LUKS device activation example.
+ */
+ r = crypt_init(&cd, path);
+ if (r < 0) {
+ printf("crypt_init() failed for %s.\n", path);
+ return r;
+ }
+
+ /*
+ * crypt_load() is used to load existing LUKS header from a block device
+ */
+ r = crypt_load(cd, /* crypt context */
+ CRYPT_LUKS, /* requested type - here LUKS of any type */
+ NULL); /* additional parameters (not used) */
+
+ if (r < 0) {
+ printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
+ crypt_free(cd);
+ return r;
+ }
+
+ /*
+ * Device activation creates a device-mapper device with the specified name.
+ */
+ r = crypt_activate_by_passphrase(cd, /* crypt context */
+ device_name, /* device name to activate */
+ CRYPT_ANY_SLOT,/* the keyslot use (try all here) */
+ "foo", 3, /* passphrase */
+ CRYPT_ACTIVATE_READONLY); /* flags */
+ if (r < 0) {
+ printf("Device %s activation failed.\n", device_name);
+ crypt_free(cd);
+ return r;
+ }
+
+ printf("%s device %s/%s is active.\n", crypt_get_type(cd), crypt_get_dir(), device_name);
+ printf("\tcipher used: %s\n", crypt_get_cipher(cd));
+ printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
+ printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
+
+ /*
+ * Get info about the active device.
+ */
+ r = crypt_get_active_device(cd, device_name, &cad);
+ if (r < 0) {
+ printf("Get info about active device %s failed.\n", device_name);
+ crypt_deactivate(cd, device_name);
+ crypt_free(cd);
+ return r;
+ }
+
+ printf("Active device parameters for %s:\n"
+ "\tDevice offset (in sectors): %" PRIu64 "\n"
+ "\tIV offset (in sectors) : %" PRIu64 "\n"
+ "\tdevice size (in sectors) : %" PRIu64 "\n"
+ "\tread-only flag : %s\n",
+ device_name, cad.offset, cad.iv_offset, cad.size,
+ cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");
+
+ crypt_free(cd);
+ return 0;
+}
+
+static int handle_active_device(const char *device_name)
+{
+ struct crypt_device *cd;
+ int r;
+
+ /*
+ * crypt_init_by_name() initializes context by an active device-mapper name
+ */
+ r = crypt_init_by_name(&cd, device_name);
+ if (r < 0) {
+ printf("crypt_init_by_name() failed for %s.\n", device_name);
+ return r;
+ }
+
+ if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
+ printf("Device %s is still active.\n", device_name);
+ else {
+ printf("Something failed perhaps, device %s is not active.\n", device_name);
+ crypt_free(cd);
+ return -1;
+ }
+
+ /*
+ * crypt_deactivate() is used to deactivate a device
+ */
+ r = crypt_deactivate(cd, device_name);
+ if (r < 0) {
+ printf("crypt_deactivate() failed.\n");
+ crypt_free(cd);
+ return r;
+ }
+
+ printf("Device %s is now deactivated.\n", device_name);
+
+ crypt_free(cd);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ if (geteuid()) {
+ printf("Using of libcryptsetup requires super user privileges.\n");
+ return 1;
+ }
+
+ if (argc != 2) {
+ printf("usage: ./crypt_luks_usage <path>\n"
+ "<path> refers to either a regular file or a block device.\n"
+ " WARNING: the file or device will be wiped.\n");
+ return 2;
+ }
+
+ if (format_and_add_keyslots(argv[1]))
+ return 3;
+
+ if (activate_and_check_status(argv[1], "example_device"))
+ return 4;
+
+ if (handle_active_device("example_device"))
+ return 5;
+
+ return 0;
+}
diff --git a/docs/on-disk-format-luks2.pdf b/docs/on-disk-format-luks2.pdf
new file mode 100644
index 0000000..d89bcef
--- /dev/null
+++ b/docs/on-disk-format-luks2.pdf
Binary files differ
diff --git a/docs/on-disk-format.pdf b/docs/on-disk-format.pdf
new file mode 100644
index 0000000..7f6e5e7
--- /dev/null
+++ b/docs/on-disk-format.pdf
Binary files differ
diff --git a/docs/v1.0.7-ReleaseNotes b/docs/v1.0.7-ReleaseNotes
new file mode 100644
index 0000000..9288c60
--- /dev/null
+++ b/docs/v1.0.7-ReleaseNotes
@@ -0,0 +1,92 @@
+cryptsetup 1.0.7 Release Notes (2009-07-22)
+===========================================
+
+Changes since 1.0.7-rc1
+------------------------
+[committer name]
+
+ * Allow removal of last slot in luksRemoveKey
+and luksKillSlot. [Milan Broz]
+
+ * Add --disable-selinux option and fix static build if selinux
+is required. [Milan Broz]
+
+ * Reject unsupported --offset and --skip options for luksFormat
+and update man page. [Milan Broz]
+
+
+Changes since 1.0.6
+--------------------
+[committer name]
+
+* Various man page fixes. Also merged some Debian/Ubuntu man page
+fixes. (thanks to Martin Pitt) [Milan Broz]
+
+* Set UUID in device-mapper for LUKS devices. [Milan Broz]
+
+* Retain readahead of underlying device. [Milan Broz]
+
+* Display device name when asking for password. (thanks to Till
+Maas) [Milan Broz]
+
+* Check device size when loading LUKS header. Remove misleading
+error message later. [Milan Broz]
+
+* Add error hint if dm-crypt mapping failed. (Key size and kernel
+version check for XTS and LRW mode for now.) [Milan Broz]
+
+* Use better error messages if device doesn't exist or is already
+used by other mapping. [Milan Broz]
+
+* Fix make distcheck. (thanks to Mike Kelly) [Milan Broz]
+
+* Check if all slots are full during luksAddKey. [Clemens Fruhwirth]
+
+* Fix segfault in set_error (thanks to Oliver Metz). [Clemens Fruhwirth]
+
+* Remove precompiled pot files. Fix uninitialized return value
+variable in setup.c. [Clemens Fruhwirth]
+
+* Code cleanups. (thanks to Ivan Stankovic) [Clemens Fruhwirth]
+
+* Remove unnecessary files from po directory. They will be
+regenerated by autogen.sh. [Clemens Fruhwirth]
+
+* Fix wrong output for remaining key at key deletion. Allow deletion
+of key slot while other keys have the same key information. [Clemens
+Fruhwirth]
+
+* Add missing AM_PROG_CC_C_O to configure.in [Milan Broz]
+
+* Remove duplicate sentence in man page (thanks to Till Maas).
+[Milan Broz]
+
+* Wipe start of device (possible fs signature) before
+LUKS-formatting. [Milan Broz]
+
+* Do not process configure.in in hidden directories. [Milan Broz]
+
+* Return more descriptive error in case of IO or header format
+error. [Milan Broz]
+
+* Use remapping to error target instead of calling udevsettle
+for temporary crypt device. [Milan Broz]
+
+* Check device mapper communication and warn user in case the
+communication fails. (thanks to Milan Broz) [Clemens Fruhwirth]
+
+* Fix signal handler to proper close device. (thanks to Milan Broz)
+[Clemens Fruhwirth]
+
+* write_lseek_blockwise: declare innerCount outside the if block,
+add -Wall to the default CFLAGS, * fix some signedness issues
+(thanks to Ivan Stankovic) [Clemens Fruhwirth]
+
+* Error handling improvement. (thanks to Erik Edin) [Clemens Fruhwirth]
+
+* Add non-exclusive override to interface definition. [Clemens
+Fruhwirth]
+
+* Refactor key slot selection into keyslot_from_option. Either
+autoselect next free keyslot or honor user choice (after checking).
+[Clemens Fruhwirth]
diff --git a/docs/v1.1.0-ReleaseNotes b/docs/v1.1.0-ReleaseNotes
new file mode 100644
index 0000000..7ee6dea
--- /dev/null
+++ b/docs/v1.1.0-ReleaseNotes
@@ -0,0 +1,110 @@
+Cryptsetup 1.1.0 Release Notes
+==============================
+
+Changes since version 1.0.7
+----------------------------
+
+Important changes:
+~~~~~~~~~~~~~~~~~~
+
+ * IMPORTANT: the default compiled-in cipher parameters changed
+ plain mode: aes-cbc-essiv:sha256 (default is backward incompatible!).
+ LUKS mode: aes-cbc-essiv:sha256 (only key size increased)
+ In both modes is now default key size 256bits.
+
+ * Default compiled-in parameters are now configurable through configure options:
+ --with-plain-* / --with-luks1-* (see configure --help)
+
+ * If you need backward compatible defaults for distribution use
+ configure --with-plain-mode=cbc-plain --with-luks1-keybits=128
+
+ Default compiled-in modes are printed in "cryptsetup --help" output.
+
+ * Change in iterations count (LUKS):
+ The slot and key digest iteration minimum count is now 1000.
+ The key digest iteration count is calculated from iteration time (approx 1/8 of req. time).
+ For more info about above items see discussion here: http://tinyurl.com/yaug97y
+
+ * New libcryptsetup API (documented in libcryptsetup.h).
+
+ The old API (using crypt_options struct) is still available but will remain
+ frozen and not used for new functions.
+ Soname of library changed to libcryptsetup.so.1.0.0.
+ (But only recompilation should be needed for old programs.)
+
+ The new API provides much more flexible operation over LUKS device for
+ applications, it is preferred that new applications will use libcryptsetup
+ and not wrapper around cryptsetup binary.
+
+ * New luksHeaderBackup and luksHeaderRestore commands.
+
+ These commands allows binary backup of LUKS header.
+ Please read man page about possible security issues with backup files.
+
+ * New luksSuspend (freeze device and wipe key) and luksResume (with provided passphrase).
+
+ luksSuspend wipe encryption key in kernel memory and set device to suspend
+ (blocking all IO) state. This option can be used for situations when you need
+ temporary wipe encryption key (like suspend to RAM etc.)
+ Please read man page for more information.
+
+ * New --master-key-file option for luksFormat and luksAddKey.
+
+ User can now specify pre-generated master key in file, which allows regenerating
+ LUKS header or add key with only master key knowledge.
+
+ * Uses libgcrypt and enables all gcrypt hash algorithms for LUKS through -h luksFormat option.
+
+ Please note that using different hash for LUKS header make device incompatible with
+ old cryptsetup releases.
+
+ * Introduces --debug parameter.
+
+ Use when reporting bugs (just run cryptsetup with --debug and attach output
+ to issue report.) Sensitive data are never printed to this log.
+
+ * Moves command successful messages to verbose level.
+
+ * Requires device-mapper library and libgcrypt to build.
+
+ * Uses dm-uuid for all crypt devices, contains device type and name now.
+
+ * Removes support for dangerous non-exclusive option
+ (it is ignored now, LUKS device must be always opened exclusive)
+
+Other changes:
+~~~~~~~~~~~~~~
+ * Fixed localization to work again. Also cryptsetup is now translated by translationproject.org.
+ * Fix some libcryptsetup problems, including
+ * exported symbols and versions in libcryptsetup (properly use versioned symbols)
+ * Add crypt_log library function.
+ * Add CRYPT_ prefix to enum defined in libcryptsetup.h.
+ * Move duplicate Command failed message to verbose level (error is printed always).
+ * Fix several problems in build system
+ * use autopoint and clean gettext processing.
+ * Check in configure if selinux libraries are required in static version.
+ * Fix build for non-standard location of gcrypt library.
+ * Add temporary debug code to find processes locking internal device.
+ * Fix error handling during reading passphrase.
+ * Fail passphrase read if piped input no longer exists.
+ * Fix man page to not require --size which expands to device size by default.
+ * Clean up Makefiles and configure script.
+ * Try to read first sector from device to properly check that device is ready.
+ * Move memory locking and dm initialization to command layer.
+ * Increase priority of process if memory is locked.
+ * Add log macros and make logging more consistent.
+ * Keyfile now must be provided by path, only stdin file descriptor is used (api only).
+ * Do not call isatty() on closed keyfile descriptor.
+ * Move key slot manipulation function into LUKS specific code.
+ * Replace global options struct with separate parameters in helper functions.
+ * Implement old API calls using new functions.
+ * Allow using passphrase provided in options struct for LuksOpen.
+ * Allow restrict keys size in LuksOpen.
+ * Fix errors when compiled with LUKS_DEBUG.
+ * Print error when getline fails.
+ * Completely remove internal SHA1 implementation code, not needed anymore.
+ * Pad luks header to 512 sector size.
+ * Rework read/write blockwise to not split operation to many pieces.
+ * Use posix_memalign if available.
+ * Fix segfault if provided slot in luksKillslot is invalid.
+ * Remove unneeded timeout when remove of temporary device succeeded.
diff --git a/docs/v1.1.1-ReleaseNotes b/docs/v1.1.1-ReleaseNotes
new file mode 100644
index 0000000..e85107c
--- /dev/null
+++ b/docs/v1.1.1-ReleaseNotes
@@ -0,0 +1,47 @@
+Cryptsetup 1.1.1 Release Notes
+==============================
+
+Changes since version 1.1.1-rc2
+* Fix luksClose error if underlying device is LVM logical volume.
+
+Changes since version 1.1.1-rc1
+* Fix automatic dm-crypt module loading.
+
+Changes since version 1.1.0
+
+Important changes:
+~~~~~~~~~~~~~~~~~~
+
+* Detects and use device-mapper udev support if available.
+
+ This should allow synchronisation with udev rules and avoid races with udev.
+
+ If package maintainer want to use old, direct libdevmapper device node creation,
+ use configure option --disable-udev.
+
+* Supports device topology detection for data alignment.
+
+ If kernel provides device topology ioctl calls, the LUKS data area
+ alignment is automatically set to optimal value.
+
+ This means that stacked devices (like LUKS over MD/LVM)
+ should use the most optimal data alignment.
+
+ (You can still overwrite this calculation using --align-payload option.)
+
+* Prefers some device paths in status display.
+ (So status command will try to find top level device name, like /dev/sdb.)
+
+* Fix package config file to use proper package version.
+
+Other changes:
+~~~~~~~~~~~~~~
+* Fix luksOpen reading of passphrase on stdin (if "-" keyfile specified).
+* Fix isLuks to initialise crypto backend (blkid instead is suggested anyway).
+* Properly initialise crypto backend in header backup/restore commands.
+* Do not verify unlocking passphrase in luksAddKey command.
+* Allow no hash specification in plain device constructor - user can provide volume key directly.
+* Try to use pkgconfig for device mapper library in configuration script.
+* Add some compatibility checks and disable LUKS suspend/resume if not supported.
+* Rearrange tests, "make check" now run all available test for package.
+* Avoid class C++ keyword in library header.
diff --git a/docs/v1.1.2-ReleaseNotes b/docs/v1.1.2-ReleaseNotes
new file mode 100644
index 0000000..9931f05
--- /dev/null
+++ b/docs/v1.1.2-ReleaseNotes
@@ -0,0 +1,33 @@
+== Cryptsetup 1.1.2 Release Notes ==
+
+This release fixes a regression (introduced in 1.1.1 version) in handling
+key files containing new line characters (affects only files read from
+standard input).
+
+Cryptsetup can accept passphrase on stdin (standard input).
+
+Handling of new line (\n) character is defined by input specification:
+
+ * if keyfile is specified as "-" (using --key-file=- of by "-" positional argument
+ in luksFormat and luksAddKey, like cat file | cryptsetup --key-file=- <action>),
+ input is processed as normal binary file and no new line is interpreted.
+
+ * if there is no key file specification (with default input from stdin pipe
+ like echo passphrase | cryptsetup <action>) input is processed as input from terminal,
+ reading will stop after new line is detected.
+
+Moreover, luksFormat now understands --key-file (in addition to positional key
+file argument).
+
+N.B. Using of standard input and pipes for passphrases should be avoided if possible,
+cryptsetup have no control of used pipe buffers between commands in scripts and cannot
+guarantee that all passphrase/key-file buffers are properly wiped after use.
+
+=== changes since version 1.1.1 ===
+
+ * Fix luksFormat/luksOpen reading passphrase from stdin and "-" keyfile.
+ * Support --key-file/-d option for luksFormat.
+ * Fix description of --key-file and add --verbose and --debug options to man page.
+ * Add verbose log level and move unlocking message there.
+ * Remove device even if underlying device disappeared (remove, luksClose).
+ * Fix (deprecated) reload device command to accept new device argument.
diff --git a/docs/v1.1.3-ReleaseNotes b/docs/v1.1.3-ReleaseNotes
new file mode 100644
index 0000000..94ee73e
--- /dev/null
+++ b/docs/v1.1.3-ReleaseNotes
@@ -0,0 +1,13 @@
+== Cryptsetup 1.1.3 Release Notes ==
+
+=== changes since version 1.1.2 ===
+
+* Fix device alignment ioctl calls parameters.
+ (Device alignment code was not working properly on some architectures like ppc64.)
+
+* Fix activate_by_* API calls to handle NULL device name as documented.
+ (To enable check of passphrase/keyfile using libcryptsetup without activating the device.)
+
+* Fix udev support for old libdevmapper with not compatible definition.
+
+* Added Polish translation file.
diff --git a/docs/v1.2.0-ReleaseNotes b/docs/v1.2.0-ReleaseNotes
new file mode 100644
index 0000000..77fbedf
--- /dev/null
+++ b/docs/v1.2.0-ReleaseNotes
@@ -0,0 +1,126 @@
+Cryptsetup 1.2.0 Release Notes
+==============================
+
+Changes since version 1.2.0-rc1
+
+ * Fix crypt_activate_by_keyfile() to work with PLAIN devices.
+ * Fix plain create command to properly handle keyfile size.
+ * Update translations.
+
+Changes since version 1.1.3
+
+Important changes
+~~~~~~~~~~~~~~~~~
+
+ * Add text version of *FAQ* (Frequently Asked Questions) to distribution.
+
+ * Add selection of random/urandom number generator for luksFormat
+ (option --use-random and --use-urandom).
+
+ (This affects only long term volume key in *luksFormat*,
+ not RNG used for salt and AF splitter).
+
+ You can also set the default to /dev/random during compilation with
+ --enable-dev-random. Compiled-in default is printed in --help output.
+
+ Be very careful before changing default to blocking /dev/random use here.
+
+ * Fix *luksRemoveKey* to not ask for remaining keyslot passphrase,
+ only for removed one.
+
+ * No longer support *luksDelKey* (replaced with luksKillSlot).
+ * if you want to remove particular passphrase, use *luksKeyRemove*
+ * if you want to remove particular keyslot, use *luksKillSlot*
+
+ Note that in batch mode *luksKillSlot* allows removing of any keyslot
+ without question, in normal mode requires passphrase or keyfile from
+ other keyslot.
+
+ * *Default alignment* for device (if not overridden by topology info)
+ is now (multiple of) *1MiB*.
+ This reflects trends in storage technologies and aligns to the same
+ defaults for partitions and volume management.
+
+ * Allow explicit UUID setting in *luksFormat* and allow change it later
+ in *luksUUID* (--uuid parameter).
+
+ * All commands using key file now allows limited read from keyfile using
+ --keyfile-size and --new-keyfile-size parameters (in bytes).
+
+ This change also disallows overloading of --key-size parameter which
+ is now exclusively used for key size specification (in bits.)
+
+ * *luksFormat* using pre-generated master key now properly allows
+ using key file (only passphrase was allowed prior to this update).
+
+ * Add --dump-master-key option for *luksDump* to perform volume (master)
+ key dump. Note that printed information allows accessing device without
+ passphrase so it must be stored encrypted.
+
+ This operation is useful for simple Key Escrow function (volume key and
+ encryption parameters printed on paper on safe place).
+
+ This operation requires passphrase or key file.
+
+ * The reload command is no longer supported.
+ (Use dmsetup reload instead if needed. There is no real use for this
+ function except explicit data corruption:-)
+
+ * Cryptsetup now properly checks if underlying device is in use and
+ disallows *luksFormat*, *luksOpen* and *create* commands on open
+ (e.g. already mapped or mounted) device.
+
+ * Option --non-exclusive (already deprecated) is removed.
+
+Libcryptsetup API additions:
+
+ * new functions
+ * crypt_get_type() - explicit query to crypt device context type
+ * crypt_resize() - new resize command using context
+ * crypt_keyslot_max() - helper to get number of supported keyslots
+ * crypt_get_active_device() - get active device info
+ * crypt_set/get_rng_type() - random/urandom RNG setting
+ * crypt_set_uuid() - explicit UUID change of existing device
+ * crypt_get_device_name() - get underlying device name
+
+ * Fix optional password callback handling.
+
+ * Allow one to activate by internally cached volume key immediately after
+ crypt_format() without active slot (for temporary devices with
+ on-disk metadata)
+
+ * libcryptsetup is binary compatible with 1.1.x release and still
+ supports legacy API calls
+
+ * cryptsetup binary now uses only new API calls.
+
+ * Static compilation of both library (--enable-static) and cryptsetup
+ binary (--enable-static-cryptsetup) is now properly implemented by common
+ libtool logic.
+
+ Prior to this it produced miscompiled dynamic cryptsetup binary with
+ statically linked libcryptsetup.
+
+ The static binary is compiled as src/cryptsetup.static in parallel
+ with dynamic build if requested.
+
+Other changes
+~~~~~~~~~~~~~
+ * Fix default plain password entry from terminal in activate_by_passphrase.
+ * Initialize volume key from active device in crypt_init_by_name()
+ * Fix cryptsetup binary exit codes.
+ 0 - success, otherwise fail
+ 1 - wrong parameters
+ 2 - no permission
+ 3 - out of memory
+ 4 - wrong device specified
+ 5 - device already exists or device is busy
+ * Remove some obsolete info from man page.
+ * Add more regression tests for commands.
+ * Fix possible double free when handling master key file.
+ * Fix pkg-config use in automake scripts.
+ * Wipe iteration and salt after luksKillSlot in LUKS header.
+ * Rewrite file differ test to C (and fix it to really work).
+ * Do not query non-existent device twice (cryptsetup status /dev/nonexistent).
+ * Check if requested hash is supported before writing LUKS header.
+ * Fix problems reported by clang scan-build.
diff --git a/docs/v1.3.0-ReleaseNotes b/docs/v1.3.0-ReleaseNotes
new file mode 100644
index 0000000..b7ae977
--- /dev/null
+++ b/docs/v1.3.0-ReleaseNotes
@@ -0,0 +1,101 @@
+Cryptsetup 1.3.0 Release Notes
+==============================
+
+Changes since version 1.2.0
+
+Important changes
+~~~~~~~~~~~~~~~~~
+ * Several userspace crypto backends support
+
+ cryptsetup now supports generic crypto backend interface which allows
+ compile package with various crypto libraries, these are already implemented:
+
+ * gcrypt (default, used in previous versions)
+ * OpenSSL
+ * NSS (because of missing ripemd160 it cannot provide full backward compatibility)
+ * kernel userspace API (provided by kernel 2.6.38 and above)
+ (Note that kernel userspace backend is very slow for this type of operation.
+ But it can be useful for embedded systems, because you can avoid userspace
+ crypto library completely.)
+
+ Backend is selected during configure time, using --with-crypto_backend option.
+
+ configure --with-crypto_backend=BACKEND (gcrypt/openssl/nss/kernel) [gcrypt]
+
+ Note that performance checked (iterations) in LUKS header will cause that
+ real iteration time will differ with different backends.
+ (There are huge differences in speed between libraries.)
+
+ * Cryptsetup now automatically allocates loopback device (/dev/loop) if device
+ argument is file and not plain device.
+
+ This require Linux kernel 2.6.25 and above (which implements loop autoclear flag).
+
+ You can see backing file in cryptsetup status output if underlying device is loopback.
+
+ * Introduce maximum default keyfile size, add configure option, visible in --help.
+
+ Cryptsetup now fails if read from keyfile exceeds internal limit.
+ You can always specify keyfile size (overrides limit) by using --keyfile-size option.
+
+ * Adds luksChangeKey command
+
+ cryptestup luksChangeKey --key-file <old keyfile> <new keyfile> [--key-slot X]
+ cryptestup luksChangeKey [--key-slot X] (for passphrase change)
+
+ This command allows passphrase/keyfile change in one step. If no key slot is
+ specified (and there is still free key slot on device) new slot is allocated before
+ the old is purged.
+
+ If --key-slot option is specified (or there is no free slot) command will overwrite
+ existing slot.
+ WARNING: Be sure you have another slot active or header backup when using explicit
+ key slot (so you can unlock the device even after possible media failure).
+
+ * Adds compatible support for loop-AES encryption type in loopaesOpen command.
+
+ Linux dm-crypt in 2.6.38 and above supports loop-AES compatible mapping
+ (including multi-key and special CBC mode, all three modes are supported).
+
+ If you have raw loop-AES keyfile (text file with uuencoded per-line keys), you can
+ access loop-AES volume using
+ cryptsetup loopaesOpen <device> <name> [--key-size 128] --key-file <key-file>
+
+ If you are using GPG encrypted keyfile
+ gpg --decrypt <key-file> | cryptsetup loopaesOpen --key-file=- <device> <name>
+
+ Do not forget to specify key size. Version and hash is automatically detected
+ according to number of lines in key file. For special configuration you can
+ override IV sector offset using --skip option, device offset with --offset
+ and hash algorithm using --hash, see man page for details.
+
+ Please note that loopAES dm-crypt mode is provided for compatibility reasons
+ (so you do not need to patch kernel and util-linux to map existing volumes)
+ but it is not, and never will be, optimized for speed.
+ It is experimental feature for now.
+
+ * Require the whole key read from keyfile in create command (regression in 1.2.0).
+
+ * WARNING: This is the last cryptsetup release which supports library with
+ old API (using struct crypt_options).
+ These calls are deprecated since 1.1.0 and AFAIK no application
+ is using it in recent distros. Removing compatible code will allow
+ new features to be implemented easily.
+
+Other changes
+~~~~~~~~~~~~~
+ * Lock memory also in luksDump command.
+ * Fix return code when passphrase is read from pipe.
+ * Increase libcryptsetup version (loopAES change), still fully backward compatible.
+ * Fixes static build (--disable-static-cryptsetup now works properly).
+ * Supports secure data flag for device-mapper ioctl (will be in 2.6.39,
+ forcing kernel to wipe all ioctl buffers with possible key data).
+ To enable this flag you need new device-mapper library, in LVM2 2.02.84.
+ * Add copyright texts into some files and adds GPL exception allowing
+ to distribute resulting binaries linked with OpenSSL.
+ * Update FAQ.
+ * Fix message when locking memory fails.
+ * Fix luksAddKey return code if master key is used.
+ * Update some text files in distributions.
+ * Add docs directory with Release Notes archive.
+ * Do not hardcode loopback device name in tests, use internal loopback library.
diff --git a/docs/v1.3.1-ReleaseNotes b/docs/v1.3.1-ReleaseNotes
new file mode 100644
index 0000000..8b2d1dd
--- /dev/null
+++ b/docs/v1.3.1-ReleaseNotes
@@ -0,0 +1,14 @@
+Cryptsetup 1.3.1 Release Notes
+==============================
+
+Changes since version 1.3.0
+
+ * Fix keyfile=- processing in create command (regression in 1.3.0).
+
+ * Simplify device path status check (use /sys and do not scan /dev).
+
+ * Do not ignore device size argument for create command (regression in 1.2.0).
+
+ * Fix error paths in blockwise code and lseek_write call.
+
+ * Add optional Nettle crypto backend support.
diff --git a/docs/v1.4.0-ReleaseNotes b/docs/v1.4.0-ReleaseNotes
new file mode 100644
index 0000000..bef4e74
--- /dev/null
+++ b/docs/v1.4.0-ReleaseNotes
@@ -0,0 +1,131 @@
+Cryptsetup 1.4.0 Release Notes
+==============================
+
+Changes since version 1.3.1
+
+Important changes
+~~~~~~~~~~~~~~~~~
+
+WARNING: This release removes old deprecated API from libcryptsetup
+ (all functions using struct crypt_options).
+
+ This require libcrypsetup version change and
+ rebuild of applications using cryptsetup library.
+ All new API symbols are backward compatible.
+
+* If device is not rotational disk, cryptsetup no longer tries
+ to wipe keyslot with Gutmann algorithm for magnetic media erase
+ but simply rewrites area once by random data.
+
+* The on-disk LUKS header can now be detached (e.g. placed on separate
+ device or in file) using new --header option.
+
+ This option is only relevant for LUKS devices and can be used in
+ luksFormat, luksOpen, luksSuspend, luksResume and resize commands.
+
+ If used with luksFormat the --align-payload option is taken
+ as absolute sector alignment on ciphertext device and can be zero.
+
+ Example:
+ Create LUKS device with ciphertext device on /dev/sdb and header
+ on device /dev/sdc. Use all space on /dev/sdb (no reserved area for header).
+
+ cryptsetup luksFormat /dev/sdb --header /dev/sdc --align-payload 0
+
+ Activate such device:
+ cryptsetup luksOpen /dev/sdb --header /dev/sdc test_disk
+
+ You can use file for LUKS header (loop device will be used while
+ manipulating with such detached header), just you have to create
+ large enough file in advance.
+
+ dd if=/dev/zero of=/mnt/luks_header bs=1M count=4
+ cryptsetup luksFormat /dev/sdb --header /mnt/luks_header --align-payload 0
+
+ Activation is the same as above.
+
+ cryptsetup luksOpen /dev/sdb --header /mnt/luks_header test_disk
+
+ All keyslot operations need to be run on _header_ not on ciphertext device,
+ an example:
+
+ cryptsetup luksAddKey /mnt/luks_header
+
+ If you do not use --align-payload 0, you can later restore LUKS header
+ on device itself (and use it as normal LUKS device without detached header).
+
+ WARNING: There is no possible check that specified ciphertext device
+ matches detached on-disk header. Use with care, it can destroy
+ your data in case of a mistake.
+
+ WARNING: Storing LUKS header in a file means that anti-forensic splitter
+ cannot properly work (there is filesystem allocation layer between
+ header and disk).
+
+* Support --allow-discards option to allow discards/TRIM requests.
+
+ Since kernel 3.1, dm-crypt devices optionally (not by default) support
+ block discards (TRIM) commands.
+ If you want to enable this operation, you have to enable it manually
+ on every activation using --allow-discards
+
+ cryptsetup luksOpen --allow-discards /dev/sdb test_disk
+
+ WARNING: There are several security consequences, please read at least
+ http://asalor.blogspot.com/2011/08/trim-dm-crypt-problems.html
+ before you enable it.
+
+* Add --shared option for creating non-overlapping crypt segments.
+
+ The --shared options checks that mapped segments are not overlapping
+ and allows non-exclusive access to underlying device.
+ Only plain crypt devices can be used in this mode.
+
+ Example - map 64M of device disk and following 32 M area as another disk.
+
+ cryptsetup create outer_disk /dev/sdb --offset 0 --size 65536
+ cryptsetup create inner_disk /dev/sdb --offset 65536 --size 32768 --shared
+
+ (It can be used to simulate trivial hidden disk concepts.)
+
+libcryptsetup API changes:
+ * Added options to support detached metadata device
+ crypt_init_by_name_and_header()
+ crypt_set_data_device()
+ * Add crypt_last_error() API call.
+ * Fix plain crypt format parameters to include size option.
+ * Add crypt_get_iv_offset() function.
+
+ * Remove old API functions (all functions using crypt_options).
+
+* Support key-slot option for luksOpen (use only explicit keyslot).
+
+ You can now specify key slot in luksOpen and limit checking
+ only to specified slot.
+
+* Support retries and timeout parameters for luksSuspend.
+ (The same way as in luksOpen.)
+
+* Add doxygen-like documentation (it will be available on project page later).
+ (To generate it manually run doxygen in docs directory.)
+
+Other changes
+~~~~~~~~~~~~~
+* Fix crypt_load to properly check device size.
+* Do not allow context format of already formatted device.
+* Do not allow key retrieval while suspended (key could be wiped).
+* Do not allow suspend for non-LUKS devices.
+* Fix luksKillSLot exit code if slot is inactive or invalid.
+* Fix exit code if passphrases do not match in luksAddKey.
+* Fix return code for status command when device doesn't exists.
+* Fix verbose messages in isLuks command.
+* Support Nettle 2.4 crypto backend (supports ripemd160).
+* Add LUKS on-disk format description into package.
+* Enhance check of device size before writing LUKS header.
+* Add more paranoid checks for LUKS header and keyslot attributes.
+* Use new /dev/loop-control (kernel 3.1) if possible.
+* Remove hash/hmac restart from crypto backend and make it part of hash/hmac final.
+* Improve check for invalid offset and size values.
+* Revert default initialisation of volume key in crypt_init_by_name().
+* Add more regression tests.
+* Add some libcryptsetup example files (see docs/examples).
diff --git a/docs/v1.4.1-ReleaseNotes b/docs/v1.4.1-ReleaseNotes
new file mode 100644
index 0000000..ea68cb8
--- /dev/null
+++ b/docs/v1.4.1-ReleaseNotes
@@ -0,0 +1,25 @@
+Cryptsetup 1.4.1 Release Notes
+==============================
+
+Changes since version 1.4.0
+
+* Merge experimental Python cryptsetup (pycryptsetup) binding.
+
+ This option is disabled by default, you can enable build of Python binding
+ with --enable--python configure switch.
+
+ Note that binding currently covers only partial libcryptsetup functions,
+ mainly LUKS device handling needed for Anaconda installer.
+ Until now provided separately as python-cryptsetup.
+ Thanks to Martin Sivak for the code.
+
+ See python subdirectory for more info.
+
+ Python binding code is experimental for now, no stable API guarantee.
+
+* Fix crypt_get_volume_key_size() for plain device.
+ (cryptsetup status reported zero key size for plain crypt devices).
+
+* Fix typo in set_iteration_time API call (old name remains for compatibility reasons).
+
+* Fix FSF address in license and add LGPL license text.
diff --git a/docs/v1.4.2-ReleaseNotes b/docs/v1.4.2-ReleaseNotes
new file mode 100644
index 0000000..a3c2912
--- /dev/null
+++ b/docs/v1.4.2-ReleaseNotes
@@ -0,0 +1,44 @@
+Cryptsetup 1.4.2 Release Notes
+==============================
+
+Changes since version 1.4.1
+
+* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
+ These options can be used to skip start of keyfile or device used as keyfile.
+
+* Add repair command and crypt_repair() for known LUKS metadata problems repair.
+
+ Some well-known LUKS metadata corruptions are easy to repair, this
+ command should provide a way to fix these problems.
+
+ Always create binary backup of header device before running repair,
+ (only 4kB - visible header) for example by using dd:
+ dd if=/dev/<LUKS header device> of=repair_bck.img bs=1k count=4
+
+ Then you can try to run repair:
+ cryptsetup repair <device>
+
+ Note, not all problems are possible to repair and if keyslot or some header
+ parameters are overwritten, device is lost permanently.
+
+* Fix header check to support old (cryptsetup 1.0.0) header alignment.
+ (Regression in 1.4.0)
+
+* Allow one to specify --align-payload only for luksFormat.
+
+* Add --master-key-file option to luksOpen (open using volume key).
+
+* Support UUID=<LUKS_UUID> format for device specification.
+ You can open device by UUID (only shortcut to /dev/disk/by-uuid/ symlinks).
+
+* Support password verification with quiet flag if possible. (1.2.0)
+ Password verification can be still possible if input is terminal.
+
+* Fix retry if entered passphrases (with verify option) do not match.
+ (It should retry if requested, not fail.)
+
+* Fix use of empty keyfile.
+
+* Fix error message for luksClose and detached LUKS header.
+
+* Allow --header for status command to get full info with detached header.
diff --git a/docs/v1.4.3-ReleaseNotes b/docs/v1.4.3-ReleaseNotes
new file mode 100644
index 0000000..16792a5
--- /dev/null
+++ b/docs/v1.4.3-ReleaseNotes
@@ -0,0 +1,62 @@
+Cryptsetup 1.4.3 Release Notes
+==============================
+
+Changes since version 1.4.2
+
+* Fix readonly activation if underlying device is readonly (1.4.0).
+
+* Fix loop mapping on readonly file.
+
+* Include stddef.h in libdevmapper.h (size_t definition).
+
+* Fix keyslot removal for device with 4k hw block (1.4.0).
+(Wipe keyslot failed in this case.)
+
+* Relax --shared flag to allow mapping even for overlapping segments.
+
+ The --shared flag (and API CRYPT_ACTIVATE_SHARED flag) is now able
+ to map arbitrary overlapping area. From API it is even usable
+ for LUKS devices.
+ It is user responsibility to not cause data corruption though.
+
+ This allows e.g. scubed to work again and also allows some
+ tricky extensions later.
+
+* Allow empty cipher (cipher_null) for testing.
+
+ You can now use "null" (or directly cipher_null-ecb) in cryptsetup.
+ This means no encryption, useful for performance tests
+ (measure dm-crypt layer overhead).
+
+* Switch on retry on device remove for libdevmapper.
+ Device-mapper now retry removal if device is busy.
+
+* Allow "private" activation (skip some udev global rules) flag.
+ Cryptsetup library API now allows one to specify CRYPT_ACTIVATE_PRIVATE,
+ which means that some udev rules are not processed.
+ (Used for temporary devices, like internal keyslot mappings where
+ it is not desirable to run any device scans.)
+
+* This release also includes some Red Hat/Fedora specific extensions
+related to FIPS140-2 compliance.
+
+In fact, all these patches are more formal changes and are just subset
+of building blocks for FIPS certification. See FAQ for more details
+about FIPS.
+
+FIPS extensions are enabled by using --enable-fips configure switch.
+
+In FIPS mode (kernel booted with fips=1 and gcrypt in FIPS mode)
+
+ - it provides library and binary integrity verification using
+ libfipscheck (requires pre-generated checksums)
+
+ - it uses FIPS approved RNG for encryption key and salt generation
+ (note that using /dev/random is not formally FIPS compliant RNG).
+
+ - only gcrypt crypto backend is currently supported in FIPS mode.
+
+The FIPS RNG requirement for salt comes from NIST SP 800-132 recommendation.
+(Recommendation for Password-Based Key Derivation. Part 1: Storage Applications.
+http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf)
+LUKS should be aligned to this recommendation otherwise.
diff --git a/docs/v1.5.0-ReleaseNotes b/docs/v1.5.0-ReleaseNotes
new file mode 100644
index 0000000..9f1e1d1
--- /dev/null
+++ b/docs/v1.5.0-ReleaseNotes
@@ -0,0 +1,241 @@
+Cryptsetup 1.5.0 Release Notes
+==============================
+
+This release covers mainly inclusion of:
+
+ * Veritysetup tool (and related libcryptsetup extensions for dm-verity).
+
+ * Experimental cryptsetup-reencrypt tool (LUKS offline reencryption).
+
+Changes since version 1.5.0-rc2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ * Add --device-size option for reencryption tool.
+
+ * Switch to use unit suffix for --reduce-device-size option.
+
+ * Remove open device debugging feature (no longer needed).
+
+ * Fix library name for FIPS check.
+
+ * Add example of using reencryption inside dracut (see misc/dracut).
+
+Changes since version 1.5.0-rc1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Introduce cryptsetup-reencrypt - experimental offline LUKS reencryption tool.
+
+! cryptsetup-reencrypt tool is EXPERIMENTAL
+! ALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS TOOL
+
+This tool tries to simplify situation when you need to re-encrypt the whole
+LUKS device in situ (without need to move data elsewhere).
+
+This can happen for example when you want to change volume (master) key,
+encryption algorithm, or other encryption parameter.
+
+Cryptsetup-reencrypt can even optionally shift data on device
+(reducing data device size - you need some free space at the end of device).
+
+In general, cryptsetup-reencrypt can be used to
+
+ - re-generate volume key
+ - change arbitrary encryption parameters
+ - add encryption to not yet encrypted drive
+
+Side effect of reencryption is that final device will contain
+only ciphertext (for all sectors) so even if device was not properly
+wiped by random data, after reencryption you cannot distinguish
+which sectors are used.
+(Reencryption is done always for the whole device.)
+
+There are for sure bugs, please TEST IT IN TEST ENVIRONMENT before
+use for your data.
+
+This tool is not resistant to HW and kernel failures - hw crash
+will cause serious data corruption.
+
+You can enable compilation of this tool with --enable-cryptsetup-reencrypt
+configure option (it is switched off by default).
+(Tool requires libcryptsetup 1.4.3 and later.)
+
+You have to provide all keyslot passphrases or use --keyslot-option
+(then all other keyslots will be disabled).
+
+EXAMPLES (from man page)
+
+Reencrypt /dev/sdb1 (change volume key)
+ # cryptsetup-reencrypt /dev/sdb1
+
+Reencrypt and also change cipher and cipher mode
+ # cryptsetup-reencrypt /dev/sdb1 -c aes-xts-plain64
+
+ Note: if you are changing key size, there must be enough space
+ for keyslots in header or you have to use --reduce-device size and
+ reduce fs in advance.
+
+Add LUKS encryption to not yet encrypted device
+ First, be sure you have space added to disk.
+ Or, alternatively, shrink filesystem in advance.
+
+ Here we need 4096 512-bytes sectors (enough for 2x128 bit key).
+
+ # fdisk -u /dev/sdb # move sdb1 partition end + 4096 sectors
+
+ # cryptsetup-reencrypt /dev/sdb1 --new --reduce-device-size 4096
+
+There are some options which can improve performance (depends on system),
+namely --use-directio (use direct IO for all operations) can be faster
+on some systems. See man page.
+
+Progress and estimated time is printed during reencryption.
+
+You can suspend reencryption (using ctrl+c or term signal).
+To continue reencryption you have to provide only
+the device parameter (offset is stored in temporary log file).
+
+Please note LUKS device is marked invalid during reencryption and
+you have to retain tool temporary files until reencryption finishes.
+
+Temporary files are LUKS-<uuid>.[log|org|new]
+
+Other changes
+~~~~~~~~~~~~~
+
+ * Fix luks-header-from-active script (do not use LUKS header on-disk, add UUID).
+
+ * Add --test-passphrase option for luksOpen (check passphrase only).
+
+ * Fix parsing of hexadecimal string (salt or root hash) in veritysetup.
+
+Changes since version 1.4.3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Introduce veritysetup tool for dm-verity target management.
+
+The dm-verity device-mapper target was added to Linux kernel 3.4 and
+provides transparent integrity checking of block devices using a cryptographic
+digest provided by the kernel crypto API. This target is read-only.
+
+It is meant to be setup as part of a verified boot path (it was originally
+developed by Chrome OS authors as part of verified boot infrastructure).
+
+For deeper description please see http://code.google.com/p/cryptsetup/wiki/DMVerity
+and kernel dm-verity documentation.
+
+The libcryptsetup library was extended to support manipulation
+with dm-verity kernel module and new veritysetup CLI tool is added.
+
+There are no additional library requirements (it uses the same crypto
+backend as cryptsetup).
+
+If you want compile cryptsetup without veritysetup tool,
+use --disable-veritysetup configure option.
+For other configuration option see configure --help and veritysetup --help
+(e.g. default parameters).
+
+Supported libcryptsetup functions new CRYPT_VERITY type:
+ crypt_init
+ crypt_init_by_name
+ crypt_set_data device
+ crypt_get_type
+ crypt_format
+ crypt_load
+ crypt_get_active_device
+ crypt_activate_by_volume_key (volume key == root hash here)
+ crypt_dump
+and new introduced function
+ crypt_get_verity_info
+
+Please see comments in libcryptsetup.h and veritysetup.c as an code example
+how to use CRYPT_VERITY API.
+
+The veritysetup tool supports these operations:
+
+ veritysetup format <data_device> <hash_device>
+ Formats <hash_device> (calculates all hash areas according to <data_device>).
+ This is initial command to prepare device <hash_device> for later verification.
+
+ veritysetup create <name> <data_device> <hash_device> <root_hash>
+ Creates (activates) a dm-verity mapping with <name> backed by device <data_device>
+ and using <hash_device> for in-kernel verification.
+
+ veritysetup verify <data_device> <hash_device> <root_hash>
+ Verifies data in userspace (no kernel device is activated).
+
+ veritysetup remove <name>
+ Removes activated device from kernel (similar to dmsetup remove).
+
+ veritysetup status <name>
+ Reports status for the active kernel dm-verity device.
+
+ veritysetup dump <hash_device>
+ Reports parameters of verity device from on-disk stored superblock.
+
+For more info see veritysetup --help and veritysetup man page.
+
+Other changes
+~~~~~~~~~~~~~
+
+ * Both data and header device can now be a file and
+ loop device is automatically allocated.
+
+ * Require only up to last keyslot area for header device, previously
+ backup (and activation) required device/file of size up to data start
+ offset (data payload).
+
+ * Fix header backup and restore to work on files with large data offset.
+ Backup and restore now works even if backup file is smaller than data offset.
+
+Appendix: Examples of veritysetup use
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Format device using default parameters, info and final root hash is printed:
+ # veritysetup format /dev/sdb /dev/sdc
+ VERITY header information for /dev/sdc
+ UUID: fad30431-0c59-4fa6-9b57-732a90501f75
+ Hash type: 1
+ Data blocks: 52224
+ Data block size: 4096
+ Hash block size: 4096
+ Hash algorithm: sha256
+ Salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
+ Root hash: 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
+
+ Activation of device in-kernel:
+ # veritysetup create vr /dev/sdb /dev/sdc 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
+ Note - if device is corrupted, kernel mapping is created but will report failure:
+ Verity device detected corruption after activation.
+
+ Userspace verification:
+ # veritysetup verify /dev/sdb /dev/sdc 7aefa4506f7af497ac491a27f862cf8005ea782a5d97f6426945a6896ab557a1
+ Verification failed at position 8192.
+ Verification of data area failed.
+
+ Active device status report:
+ # veritysetup status vr
+ /dev/mapper/vr is active.
+ type: VERITY
+ status: verified
+ hash type: 1
+ data block: 4096
+ hash block: 4096
+ hash name: sha256
+ salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
+ data device: /dev/sdb
+ size: 417792 sectors
+ mode: readonly
+ hash device: /dev/sdc
+ hash offset: 8 sectors
+
+ Dump of on-disk superblock information:
+ # veritysetup dump /dev/sdc
+ VERITY header information for /dev/sdc
+ UUID: fad30431-0c59-4fa6-9b57-732a90501f75
+ Hash type: 1
+ Data blocks: 52224
+ Data block size: 4096
+ Hash block size: 4096
+ Hash algorithm: sha256
+ Salt: 5cc52759af76a092e0c21829cd0ef6938f69831bf86926525106f92a7e9e3aa9
+
+ Remove mapping:
+ # veritysetup remove vr
diff --git a/docs/v1.5.1-ReleaseNotes b/docs/v1.5.1-ReleaseNotes
new file mode 100644
index 0000000..7202a8c
--- /dev/null
+++ b/docs/v1.5.1-ReleaseNotes
@@ -0,0 +1,32 @@
+Cryptsetup 1.5.1 Release Notes
+==============================
+
+Changes since version 1.5.0
+
+* The libcryptsetup library now tries to initialize device-mapper backend and
+ loop devices only if they are really needed (lazy initializations).
+ This allows some operations to be run by a non-root user.
+
+ (Unfortunately LUKS header keyslot operations still require temporary dm-crypt
+ device and device-mapper subsystem is available only to superuser.)
+
+ Also clear error messages are provided if running as non-root user and
+ operation requires privileged user.
+
+* Veritysetup can be now used by a normal user for creating hash image to file
+ and also it can create hash image if doesn't exist.
+ (Previously it required pre-allocated space.)
+
+* Added crypt_keyslot_area() API call which allows external tools
+ to get exact keyslot offsets and analyse content.
+
+ An example of a tool that searches the keyslot area of a LUKS container
+ for positions where entropy is low and hence there is a high probability
+ of damage is in misc/kesylot_checker.
+ (Thanks to Arno Wagner for the code.)
+
+* Optimized seek to keyfile-offset if key offset is large.
+
+* Fixed luksHeaderBackup for very old v1.0 unaligned LUKS headers.
+
+* Various fixes for problems found by a several static analysis tools.
diff --git a/docs/v1.6.0-ReleaseNotes b/docs/v1.6.0-ReleaseNotes
new file mode 100644
index 0000000..8ee64a0
--- /dev/null
+++ b/docs/v1.6.0-ReleaseNotes
@@ -0,0 +1,261 @@
+Cryptsetup 1.6.0 Release Notes
+==============================
+
+Changes since version 1.6.0-rc1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ * Change LUKS default cipher to use XTS encryption mode,
+ aes-xts-plain64 (i.e. using AES128-XTS).
+
+ XTS mode becomes standard in hard disk encryption.
+
+ You can still use any old mode:
+ - compile cryptsetup with old default:
+ configure --with-luks1-cipher=aes --with-luks1-mode=cbc-essiv:sha256 --with-luks1-keybits=256
+ - format LUKS device with old default:
+ cryptsetup luksFormat -c aes-cbc-essiv:sha256 -s 256 <device>
+
+
+ * Skip tests and fix error messages if running on old systems (or with old kernel).
+
+ * Rename configure.in to configure.ac and fix issues with new automake and pkgconfig
+ and --disable-kernel_crypto option to allow compilation with old kernel headers.
+
+ * Allow repair of 512 bits key header.
+
+ * Fix status of device if path argument is used and fix double path prefix
+ for non-existent device path.
+
+
+Changes since version 1.5.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Important changes
+~~~~~~~~~~~~~~~~~
+
+ * Cryptsetup and libcryptsetup is now released under GPLv2+
+ (GPL version 2 or any later).
+ Some internal code handling files (loopaes, verity, tcrypt
+ and crypto backend wrapper) are LGPLv2+.
+
+ Previously code was GPL version 2 only.
+
+
+ * Introducing new unified command open and close.
+
+ Example:
+ cryptsetup open --type plain|luks|loopaes|tcrypt <device> <name>
+ (type defaults to luks)
+
+ with backward-compatible aliases plainOpen, luksOpen, loopaesOpen,
+ tcryptOpen. Basically "open --type xyz" has alias "xyzOpen".
+
+ The "create" command (plain device create) is DEPRECATED but will
+ be still supported.
+ (This command is confusing because of switched arguments order.)
+
+ The close command is generic command to remove mapping and have
+ backward compatible aliases (remove, luksClose, ...) which behaves
+ exactly the same.
+
+ While all old syntax is still supported, I strongly suggest to use
+ new command syntax which is common for all device types (and possible
+ new formats added in future).
+
+
+ * cryptsetup now support directly TCRYPT (TrueCrypt and compatible tc-play)
+ on-disk format
+ (Code is independent implementation not related to original project).
+
+ Only dump (tcryptDump command) and activation (open --type tcrypt or tcryptOpen)
+ of TCRYPT device are supported. No header changes are supported.
+
+ It is intended to easily access containers shared with other operating systems
+ without need to install 3rd party software. For native Linux installations LUKS
+ is the preferred format.
+
+ WARNING: TCRYPT extension requires kernel userspace crypto API to be
+ available (introduced in Linux kernel 2.6.38).
+ If you are configuring kernel yourself, enable "User-space interface
+ for symmetric key cipher algorithms" in "Cryptographic API" section
+ (CRYPTO_USER_API_SKCIPHER .config option).
+
+ Because TCRYPT header is encrypted, you have to always provide valid
+ passphrase and keyfiles. Keyfiles are handled exactly the same as in original
+ format (basically, first 1MB of every keyfile is mixed using CRC32 into pool).
+
+ Cryptsetup should recognize all TCRYPT header variants ever released, except
+ legacy cipher chains using LRW encryption mode with 64 bits encryption block
+ (namely Blowfish in LRW mode is not recognized, this is limitation of kernel
+ crypto API).
+
+ Device activation is supported only for LRW/XTS modes (again, limitation
+ of kernel dmcrypt which do not implements TCRYPT extensions to CBC mode).
+ (So old containers cannot be activated, but you can use libcryptsetup
+ for lost password search, example of such code is included in misc directory.)
+
+ Hidden header are supported using --tcrypt-hidden option, system encryption
+ using --tcrypt-system option.
+
+ For detailed description see man page.
+
+ EXAMPLE:
+ * Dump device parameters of container in file:
+
+ # cryptsetup tcryptDump tst
+ Enter passphrase:
+
+ TCRYPT header information for tst
+ Version: 5
+ Driver req.: 7
+ Sector size: 512
+ MK offset: 131072
+ PBKDF2 hash: sha512
+ Cipher chain: serpent-twofish-aes
+ Cipher mode: xts-plain64
+ MK bits: 1536
+
+ You can also dump master key using --dump-master-key.
+ Dump does not require superuser privilege.
+
+ * Activation of this container
+
+ # cryptsetup tcryptOpen tst tcrypt_dev
+ Enter passphrase:
+ (Chain of dmcrypt devices is activated as /dev/mapper/tcrypt_dev.)
+
+ * See status of active TCRYPT device
+
+ # cryptsetup status tcrypt_dev
+
+ /dev/mapper/tcrypt_dev is active.
+ type: TCRYPT
+ cipher: serpent-twofish-aes-xts-plain64
+ keysize: 1536 bits
+ device: /dev/loop0
+ loop: /tmp/tst
+ offset: 256 sectors
+ size: 65024 sectors
+ skipped: 256 sectors
+ mode: read/write
+
+ * And plaintext filesystem now ready to mount
+
+ # blkid /dev/mapper/tcrypt_dev
+ /dev/mapper/tcrypt_dev: SEC_TYPE="msdos" UUID="9F33-2954" TYPE="vfat"
+
+
+ * Add (optional) support for lipwquality for new LUKS passwords.
+
+ If password is entered through terminal (no keyfile specified)
+ and cryptsetup is compiled with --enable-pwquality, default
+ system pwquality settings are used to check password quality.
+
+ You can always override this check by using new --force-password option.
+
+ For more info about pwquality project see http://libpwquality.fedorahosted.org/
+
+
+ * Proper handle interrupt signals (ctrl+c and TERM signal) in tools
+
+ Code should now handle interrupt properly, release and explicitly wipe
+ in-memory key materials on interrupt.
+ (Direct users of libcryptsetup should always call crypt_free() when
+ code is interrupted to wipe all resources. There is no signal handling
+ in library, it is up to the tool using it.)
+
+
+ * Add new benchmark command
+
+ The "benchmark" command now tries to benchmark PBKDF2 and some block
+ cipher variants. You can specify you own parameters (--cipher/--key-size
+ for block ciphers, --hash for PBKDF2).
+
+ See man page for detailed description.
+
+ WARNING: benchmark command requires kernel userspace crypto API to be
+ available (introduced in Linux kernel 2.6.38).
+ If you are configuring kernel yourself, enable "User-space interface
+ for symmetric key cipher algorithms" in "Cryptographic API" section
+ (CRYPTO_USER_API_SKCIPHER .config option).
+
+ EXAMPLE:
+ # cryptsetup benchmark
+ # Tests are approximate using memory only (no storage IO).
+ PBKDF2-sha1 111077 iterations per second
+ PBKDF2-sha256 53718 iterations per second
+ PBKDF2-sha512 18832 iterations per second
+ PBKDF2-ripemd160 89775 iterations per second
+ PBKDF2-whirlpool 23918 iterations per second
+ # Algorithm | Key | Encryption | Decryption
+ aes-cbc 128b 212.0 MiB/s 428.0 MiB/s
+ serpent-cbc 128b 23.1 MiB/s 66.0 MiB/s
+ twofish-cbc 128b 46.1 MiB/s 50.5 MiB/s
+ aes-cbc 256b 163.0 MiB/s 350.0 MiB/s
+ serpent-cbc 256b 23.1 MiB/s 66.0 MiB/s
+ twofish-cbc 256b 47.0 MiB/s 50.0 MiB/s
+ aes-xts 256b 190.0 MiB/s 190.0 MiB/s
+ serpent-xts 256b 58.4 MiB/s 58.0 MiB/s
+ twofish-xts 256b 49.0 MiB/s 49.5 MiB/s
+ aes-xts 512b 175.0 MiB/s 175.0 MiB/s
+ serpent-xts 512b 59.0 MiB/s 58.0 MiB/s
+ twofish-xts 512b 48.5 MiB/s 49.5 MiB/s
+
+ Or you can specify cipher yourself:
+ # cryptsetup benchmark --cipher cast5-cbc-essiv:sha256 -s 128
+ # Tests are approximate using memory only (no storage IO).
+ # Algorithm | Key | Encryption | Decryption
+ cast5-cbc 128b 32.4 MiB/s 35.0 MiB/s
+
+ WARNING: these tests do not use dmcrypt, only crypto API.
+ You have to benchmark the whole device stack and you can get completely
+ different results. But it is usable for basic comparison.
+ (Note for example AES-NI decryption optimization effect in example above.)
+
+Features
+~~~~~~~~
+
+ * Do not maintain ChangeLog file anymore, see git log for detailed changes,
+ e.g. here http://code.google.com/p/cryptsetup/source/list
+
+ * Move change key into library, add crypt_keyslot_change_by_passphrase().
+ This change is useful mainly in FIPS mode, where we cannot
+ extract volume key directly from libcryptsetup.
+
+ * Add verbose messages during reencryption.
+
+ * Default LUKS PBKDF2 iteration time is now configurable.
+
+ * Add simple cipher benchmarking API.
+
+ * Add kernel skcipher backend.
+
+ * Add CRC32 implementation (for TCRYPT).
+
+ * Move PBKDF2 into crypto backend wrapper.
+ This allows use it in other formats, use library implementations and
+ also possible use of different KDF function in future.
+
+ * New PBKDF2 benchmark using getrusage().
+
+Fixes
+~~~~~
+
+ * Avoid O_DIRECT open if underlying storage doesn't support it.
+
+ * Fix some non-translated messages.
+
+ * Fix regression in header backup (1.5.1) with container in file.
+
+ * Fix blockwise read/write for end writes near end of device.
+ (was not used in previous versions)
+
+ * Ignore setpriority failure.
+
+ * Code changes to fix/ignore problems found by Coverity static analysis, including
+ - Get page size should never fail.
+ - Fix time of check/use (TOCTOU test) in tools
+ - Fix time of check/use in loop/wipe utils.
+ - Fix time of check/use in device utils.
+
+ * Disallow header restore if context is non-LUKS device.
diff --git a/docs/v1.6.1-ReleaseNotes b/docs/v1.6.1-ReleaseNotes
new file mode 100644
index 0000000..8fdc7d0
--- /dev/null
+++ b/docs/v1.6.1-ReleaseNotes
@@ -0,0 +1,32 @@
+Cryptsetup 1.6.1 Release Notes
+==============================
+
+Changes since version 1.6.0
+
+* Fix loop-AES keyfile parsing.
+ Loop-AES keyfile should be text keyfile, reject keyfiles which
+ are not properly terminated.
+
+* Fix passphrase pool overflow for too long TCRYPT passphrase.
+ (Maximal TCRYPT passphrase length is 64 characters.)
+
+* Return EPERM (translated to exit code 2) for too long TCRYPT passphrase.
+
+* Fix deactivation of device when failed underlying node disappeared.
+
+* Fix API deactivate call for TCRYPT format and NULL context parameter.
+
+* Improve keyslot checker example documentation.
+
+* Report error message if deactivation fails and device is still busy.
+
+* Make passphrase prompts more consistent (and remove "LUKS" form prompt).
+
+* Fix some missing headers (compilation failed with alternative libc).
+
+* Remove not functional API UUID support for plain & loopaes devices.
+ (not persistent activation UUID).
+
+* Properly cleanup devices on interrupt in api-test.
+
+* Support all tests run if kernel is in FIPS mode.
diff --git a/docs/v1.6.2-ReleaseNotes b/docs/v1.6.2-ReleaseNotes
new file mode 100644
index 0000000..fba3990
--- /dev/null
+++ b/docs/v1.6.2-ReleaseNotes
@@ -0,0 +1,25 @@
+Cryptsetup 1.6.2 Release Notes
+==============================
+
+Changes since version 1.6.1
+
+* Print error and fail if more device arguments are present for isLuks command.
+
+* Fix cipher specification string parsing (found by gcc -fsanitize=address option).
+
+* Try to map TCRYPT system encryption through partition
+ (allows one to activate mapping when other partition on the same device is mounted).
+
+* Print a warning if system encryption is used and device is a partition.
+ (TCRYPT system encryption uses whole device argument.)
+
+* Disallow explicit small payload offset for LUKS detached header.
+ LUKS detached header only allows data payload 0 (whole data device is used)
+ or explicit offset larger than header + keyslots size.
+
+* Fix boundary condition for verity device that caused failure for certain device sizes.
+
+* Various fixes to documentation, including update FAQ, default modes
+ and TCRYPT description.
+
+* Workaround for some recent changes in automake (serial-tests).
diff --git a/docs/v1.6.3-ReleaseNotes b/docs/v1.6.3-ReleaseNotes
new file mode 100644
index 0000000..24254b8
--- /dev/null
+++ b/docs/v1.6.3-ReleaseNotes
@@ -0,0 +1,50 @@
+Cryptsetup 1.6.3 Release Notes
+==============================
+
+Changes since version 1.6.2
+
+* Fix cryptsetup reencryption tool to work properly
+ with devices using 4kB sectors.
+
+* Always use page size if running through loop device,
+ this fixes failures for external LUKS header and
+ filesystem requiring 4kB block size.
+
+* Fix TCRYPT system encryption mapping for multiple partitions.
+ Since this commit, one can use partition directly as device parameter.
+ If you need to activate such partition from image in file,
+ please first use map partitioned loop device (losetup -P)
+ on image.
+ (Cryptsetup require partition offsets visible in kernel sysfs
+ in this mode.)
+
+* Support activation of old TrueCrypt containers using CBC mode
+ and whitening (created in TrueCrypt version < 4.1).
+ This requires Linux kernel 3.13 or later.
+ (Containers with cascade CBC ciphers are not supported.)
+
+* Properly display keys in dump --dump-master-key command
+ for TrueCrypt CBC containers.
+
+* Rewrite cipher benchmark loop which was unreliable
+ on very fast machines.
+
+* Add warning if LUKS device was activated using non-cryptsetup
+ library which did not set UUID properly (e.g. cryptmount).
+ (Some commands, like luksSuspend, are not available then.)
+
+* Support length limitation also for plain (no hash) length.
+ This can be used for mapping problematic cryptosystems which
+ wipes some key (losetup sometimes set last 32 byte to zero,
+ which can be now configured as --hash plain:31 parameter).
+
+* Fix hash limit if parameter is not a number.
+ (The whole key was set to zero instead of command failure.)
+
+* Unify --key-slot behavior in cryptsetup_reencrypt tool.
+
+* Update dracut example scripts for system reencryption on first boot.
+
+* Add command line option --tcrypt-backup to access TCRYPT backup header.
+
+* Fix static compilation with OpenSSL.
diff --git a/docs/v1.6.4-ReleaseNotes b/docs/v1.6.4-ReleaseNotes
new file mode 100644
index 0000000..010ba5f
--- /dev/null
+++ b/docs/v1.6.4-ReleaseNotes
@@ -0,0 +1,57 @@
+Cryptsetup 1.6.4 Release Notes
+==============================
+
+Changes since version 1.6.3
+
+* Implement new erase (with alias luksErase) command.
+
+ The erase cryptsetup command can be used to permanently erase
+ all keyslots and make the LUKS container inaccessible.
+ (The only way to unlock such device is to use LUKS header backup
+ created before erase command was used.)
+
+ You do not need to provide any password for this operation.
+
+ This operation is irreversible.
+
+* Add internal "whirlpool_gcryptbug hash" for accessing flawed
+ Whirlpool hash in gcrypt (requires gcrypt 1.6.1 or above).
+
+ The gcrypt version of Whirlpool hash algorithm was flawed in some
+ situations.
+
+ This means that if you used Whirlpool in LUKS header and upgraded
+ to new gcrypt library your LUKS container become inaccessible.
+
+ Please refer to cryptsetup FAQ for detail how to fix this situation.
+
+* Allow one to use --disable-gcrypt-pbkdf2 during configuration
+ to force use internal PBKDF2 code.
+
+* Require gcrypt 1.6.1 for imported implementation of PBKDF2
+ (PBKDF2 in gcrypt 1.6.0 is too slow).
+
+* Add --keep-key to cryptsetup-reencrypt.
+
+ This allows change of LUKS header hash (and iteration count) without
+ the need to reencrypt the whole data area.
+ (Reencryption of LUKS header only without master key change.)
+
+* By default verify new passphrase in luksChangeKey and luksAddKey
+ commands (if input is from terminal).
+
+* Fix memory leak in Nettle crypto backend.
+
+* Support --tries option even for TCRYPT devices in cryptsetup.
+
+* Support --allow-discards option even for TCRYPT devices.
+ (Note that this could destroy hidden volume and it is not suggested
+ by original TrueCrypt security model.)
+
+* Link against -lrt for clock_gettime to fix undefined reference
+ to clock_gettime error (introduced in 1.6.2).
+
+* Fix misleading error message when some algorithms are not available.
+
+* Count system time in PBKDF2 benchmark if kernel returns no self usage info.
+ (Workaround to broken getrusage() syscall with some hypervisors.)
diff --git a/docs/v1.6.5-ReleaseNotes b/docs/v1.6.5-ReleaseNotes
new file mode 100644
index 0000000..0f46964
--- /dev/null
+++ b/docs/v1.6.5-ReleaseNotes
@@ -0,0 +1,54 @@
+Cryptsetup 1.6.5 Release Notes
+==============================
+
+Changes since version 1.6.4
+
+* Allow LUKS header operation handling without requiring root privilege.
+ It means that you can manipulate with keyslots as a regular user, only
+ write access to device (or image) is required.
+
+ This requires kernel crypto wrapper (similar to TrueCrypt device handling)
+ to be available (CRYPTO_USER_API_SKCIPHER kernel option).
+ If this kernel interface is not available, code fallbacks to old temporary
+ keyslot device creation (where root privilege is required).
+
+ Note that activation, deactivation, resize and suspend operations still
+ need root privilege (limitation of kernel device-mapper backend).
+
+* Fix internal PBKDF2 key derivation function implementation for alternative
+ crypto backends (kernel, NSS) which do not support PBKDF2 directly and have
+ issues with longer HMAC keys.
+
+ This fixes the problem for long keyfiles where either calculation is too slow
+ (because of internal rehashing in every iteration) or there is a limit
+ (kernel backend seems to not support HMAC key longer than 20480 bytes).
+
+ (Note that for recent version of gcrypt, nettle or openssl the internal
+ PBKDF2 code is not compiled in and crypto library internal functions are
+ used instead.)
+
+* Support for Python3 for simple Python binding.
+ Python >= 2.6 is now required. You can set Python compiled version by setting
+ --with-python_version configure option (together with --enable-python).
+
+* Use internal PBKDF2 in Nettle library for Nettle crypto backend.
+ Cryptsetup compilation requires Nettle >= 2.6 (if using Nettle crypto backend).
+
+* Allow simple status of crypt device without providing metadata header.
+ The command "cryptsetup status" will print basic info, even if you
+ do not provide detached header argument.
+
+* Allow one to specify ECB mode in cryptsetup benchmark.
+
+* Add some LUKS images for regression testing.
+ Note that if image with Whirlpool fails, the most probable cause is that
+ you have old gcrypt library with flawed whirlpool hash.
+ Read FAQ section 8.3 for more info.
+
+Cryptsetup API NOTE:
+The direct terminal handling for passphrase entry will be removed from
+libcryptsetup in next major version (application should handle it itself).
+
+It means that you have to always either provide password in buffer or set
+your own password callback function trhough crypt_set_password_callback().
+See API documentation (or libcryptsetup.h) for more info.
diff --git a/docs/v1.6.6-ReleaseNotes b/docs/v1.6.6-ReleaseNotes
new file mode 100644
index 0000000..9d1fbee
--- /dev/null
+++ b/docs/v1.6.6-ReleaseNotes
@@ -0,0 +1,29 @@
+Cryptsetup 1.6.6 Release Notes
+==============================
+
+Changes since version 1.6.5
+
+* LUKS: Fix keyslot device access for devices which
+ do not support direct IO operations. (Regression in 1.6.5.)
+
+* LUKS: Fallback to old temporary keyslot device mapping method
+ if hash (for ESSIV) is not supported by userspace crypto
+ library. (Regression in 1.6.5.)
+
+* Properly activate device with discard (TRIM for SSDs)
+ if requested even if dm_crypt module is not yet loaded.
+ Only if discard is not supported by the old kernel then
+ the discard option is ignored.
+
+* Fix some static analysis build warnings (scan-build).
+
+* Report crypto lib version only once (and always add kernel
+ version) in debug output.
+
+Cryptsetup API NOTE:
+The direct terminal handling for passphrase entry will be removed from
+libcryptsetup in next major version (application should handle it itself).
+
+It means that you have to always either provide password in buffer or set
+your own password callback function through crypt_set_password_callback().
+See API documentation (or libcryptsetup.h) for more info.
diff --git a/docs/v1.6.7-ReleaseNotes b/docs/v1.6.7-ReleaseNotes
new file mode 100644
index 0000000..bb7c671
--- /dev/null
+++ b/docs/v1.6.7-ReleaseNotes
@@ -0,0 +1,84 @@
+Cryptsetup 1.6.7 Release Notes
+==============================
+
+Changes since version 1.6.6
+
+* Cryptsetup git and wiki are now hosted on GitLab.
+ https://gitlab.com/cryptsetup/cryptsetup
+
+ Repository of stable releases remains on kernel.org site
+ https://www.kernel.org/pub/linux/utils/cryptsetup/
+
+ For more info please see README file.
+
+* Cryptsetup TCRYPT mode now supports VeraCrypt devices (TrueCrypt extension).
+
+ The VeraCrypt extension only increases iteration count for the key
+ derivation function (on-disk format is the same as TrueCrypt format).
+
+ Note that unlocking of a VeraCrypt device can take very long time if used
+ on slow machines.
+
+ To use this extension, add --veracrypt option, for example
+ cryptsetup open --type tcrypt --veracrypt <container> <name>
+
+ For use through libcryptsetup, just add CRYPT_TCRYPT_VERA_MODES flag.
+
+* Support keyfile-offset and keyfile-size options even for plain volumes.
+
+* Support keyfile option for luksAddKey if the master key is specified.
+
+* For historic reasons, hashing in the plain mode is not used
+ if keyfile is specified (with exception of --key-file=-).
+ Print a warning if these parameters are ignored.
+
+* Support permanent device decryption for cryptsetup-reencrypt.
+ To remove LUKS encryption from a device, you can now use --decrypt option.
+
+* Allow one to use --header option in all LUKS commands.
+ The --header always takes precedence over positional device argument.
+
+* Allow luksSuspend without need to specify a detached header.
+
+* Detect if O_DIRECT is usable on a device allocation.
+ There are some strange storage stack configurations which wrongly allows
+ one to open devices with direct-io but fails on all IO operations later.
+
+ Cryptsetup now tries to read the device first sector to ensure it can use
+ direct-io.
+
+* Add low-level performance options tuning for dmcrypt (for Linux 4.0 and later).
+
+ Linux kernel 4.0 contains rewritten dmcrypt code which tries to better utilize
+ encryption on parallel CPU cores.
+
+ While tests show that this change increases performance on most configurations,
+ dmcrypt now provides some switches to change its new behavior.
+
+ You can use them (per-device) with these cryptsetup switches:
+ --perf-same_cpu_crypt
+ --perf-submit_from_crypt_cpus
+
+ Please use these only in the case of serious performance problems.
+ Refer to the cryptsetup man page and dm-crypt documentation
+ (for same_cpu_crypt and submit_from_crypt_cpus options).
+ https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
+
+* Get rid of libfipscheck library.
+ (Note that this option was used only for Red Hat and derived distributions.)
+ With recent FIPS changes we do not need to link to this FIPS monster anymore.
+ Also drop some no longer needed FIPS mode checks.
+
+* Many fixes and clarifications to man pages.
+
+* Prevent compiler to optimize-out zeroing of buffers for on-stack variables.
+
+* Fix a crash if non-GNU strerror_r is used.
+
+Cryptsetup API NOTE:
+The direct terminal handling for passphrase entry will be removed from
+libcryptsetup in next major version (application should handle it itself).
+
+It means that you have to always either provide password in buffer or set
+your own password callback function through crypt_set_password_callback().
+See API documentation (or libcryptsetup.h) for more info.
diff --git a/docs/v1.6.8-ReleaseNotes b/docs/v1.6.8-ReleaseNotes
new file mode 100644
index 0000000..8ae0da9
--- /dev/null
+++ b/docs/v1.6.8-ReleaseNotes
@@ -0,0 +1,47 @@
+Cryptsetup 1.6.8 Release Notes
+==============================
+
+Changes since version 1.6.7
+
+* If the null cipher (no encryption) is used, allow only empty password for LUKS.
+ (Previously cryptsetup accepted any password in this case.)
+
+ The null cipher can be used only for testing and it is used temporarily during
+ offline encrypting not yet encrypted device (cryptsetup-reencrypt tool).
+
+ Accepting only empty password prevents situation when someone adds another
+ LUKS device using the same UUID (UUID of existing LUKS device) with faked
+ header containing null cipher.
+ This could force user to use different LUKS device (with no encryption)
+ without noticing.
+ (IOW it prevents situation when attacker intentionally forces
+ user to boot into different system just by LUKS header manipulation.)
+
+ Properly configured systems should have an additional integrity protection
+ in place here (LUKS here provides only confidentiality) but it is better
+ to not allow this situation in the first place.
+
+ (For more info see QubesOS Security Bulletin QSB-019-2015.)
+
+* Properly support stdin "-" handling for luksAddKey for both new and old
+ keyfile parameters.
+
+* If encrypted device is file-backed (it uses underlying loop device),
+ cryptsetup resize will try to resize underlying loop device as well.
+ (It can be used to grow up file-backed device in one step.)
+
+* Cryptsetup now allows one to use empty password through stdin pipe.
+ (Intended only for testing in scripts.)
+
+Cryptsetup API NOTE:
+
+Direct terminal handling and password calling callback for passphrase
+entry will be removed from libcryptsetup in next major (2.x) version
+(application should handle it itself).
+It means that application have to always provide password in API calls.
+
+Functions returning last error will be removed in next major version (2.x).
+These functions did not work properly for early initialization errors
+and application can implement better function easily using own error callback.
+
+See comments in libcryptsetup.h for more info about deprecated functions.
diff --git a/docs/v1.7.0-ReleaseNotes b/docs/v1.7.0-ReleaseNotes
new file mode 100644
index 0000000..cd568c1
--- /dev/null
+++ b/docs/v1.7.0-ReleaseNotes
@@ -0,0 +1,81 @@
+Cryptsetup 1.7.0 Release Notes
+==============================
+
+The cryptsetup 1.7 release changes defaults for LUKS,
+there are no API changes.
+
+Changes since version 1.6.8
+
+* Default hash function is now SHA256 (used in key derivation function
+ and anti-forensic splitter).
+
+ Note that replacing SHA1 with SHA256 is not for security reasons.
+ (LUKS does not have problems even if collisions are found for SHA1,
+ for details see FAQ item 5.20).
+
+ Using SHA256 as default is mainly to prevent compatibility problems
+ on hardened systems where SHA1 is already be phased out.
+
+ Note that all checks (kernel crypto API availability check) now uses
+ SHA256 as well.
+
+* Default iteration time for PBKDF2 is now 2 seconds.
+
+ Increasing iteration time is in combination with PBKDF2 benchmark
+ fixes a try to keep PBKDF2 iteration count still high enough and
+ also still acceptable for users.
+
+ N.B. Long term is to replace PBKDF2 algorithm with Password Hashing
+ Competition winner - Argon2.
+
+ Distributions can still change these defaults in compilation time.
+
+ You can change iteration time and used hash function in existing LUKS
+ header with cryptsetup-reencrypt utility even without full reencryption
+ of device (see --keep-key option).
+
+* Fix PBKDF2 iteration benchmark for longer key sizes.
+
+ The previous PBKDF2 benchmark code did not take into account
+ output key length properly.
+
+ For SHA1 (with 160-bits output) and 256-bit keys (and longer)
+ it means that the final iteration value was higher than it should be.
+
+ For other hash algorithms (like SHA256 or SHA512) it caused
+ that iteration count was lower (in comparison to SHA1) than
+ expected for the requested time period.
+
+ The PBKDF2 benchmark code is now fixed to use the key size for
+ the formatted device (or default LUKS key size if running in informational
+ benchmark mode).
+
+ Thanks to A.Visconti, S.Bossi, A.Calo and H.Ragab
+ (http://www.club.di.unimi.it/) for point this out.
+ (Based on "What users should know about Full Disk Encryption
+ based on LUKS" paper to be presented on CANS2015).
+
+* Remove experimental warning for reencrypt tool.
+ The strong request for full backup before using reencryption utility
+ still applies :)
+
+* Add optional libpasswdqc support for new LUKS passwords.
+
+ If password is entered through terminal (no keyfile specified) and
+ cryptsetup is compiled with --enable-passwdqc[=/etc/passwdqc.conf],
+ configured system passwdqc settings are used to check password quality.
+
+* Update FAQ document.
+
+Cryptsetup API NOTE:
+
+Direct terminal handling and password calling callback for passphrase
+entry will be removed from libcryptsetup in next major (2.x) version
+(application should handle it itself).
+It means that application have to always provide password in API calls.
+
+Functions returning last error will be removed in next major version (2.x).
+These functions did not work properly for early initialization errors
+and application can implement better function easily using own error callback.
+
+See comments in libcryptsetup.h for more info about deprecated functions.
diff --git a/docs/v1.7.1-ReleaseNotes b/docs/v1.7.1-ReleaseNotes
new file mode 100644
index 0000000..057c135
--- /dev/null
+++ b/docs/v1.7.1-ReleaseNotes
@@ -0,0 +1,36 @@
+Cryptsetup 1.7.1 Release Notes
+==============================
+
+Changes since version 1.7.0
+
+* Code now uses kernel crypto API backend according to new
+ changes introduced in mainline kernel
+
+ While mainline kernel should contain backward compatible
+ changes, some stable series kernels do not contain fully
+ backported compatibility patches.
+ Without these patches most of cryptsetup operations
+ (like unlocking device) fail.
+
+ This change in cryptsetup ensures that all operations using
+ kernel crypto API works even on these kernels.
+
+* The cryptsetup-reencrypt utility now properly detects removal
+ of underlying link to block device and does not remove
+ ongoing re-encryption log.
+ This allows proper recovery (resume) of reencrypt operation later.
+
+ NOTE: Never use /dev/disk/by-uuid/ path for reencryption utility,
+ this link disappears once the device metadata is temporarily
+ removed from device.
+
+* Cryptsetup now allows special "-" (standard input) keyfile handling
+ even for TCRYPT (TrueCrypt and VeraCrypt compatible) devices.
+
+* Cryptsetup now fails if there are more keyfiles specified
+ for non-TCRYPT device.
+
+* The luksKillSlot command now does not suppress provided password
+ in batch mode (if password is wrong slot is not destroyed).
+ Note that not providing password in batch mode means that keyslot
+ is destroyed unconditionally.
diff --git a/docs/v1.7.2-ReleaseNotes b/docs/v1.7.2-ReleaseNotes
new file mode 100644
index 0000000..6323430
--- /dev/null
+++ b/docs/v1.7.2-ReleaseNotes
@@ -0,0 +1,37 @@
+Cryptsetup 1.7.2 Release Notes
+==============================
+
+Changes since version 1.7.1
+
+* Update LUKS documentation format.
+ Clarify fixed sector size and keyslots alignment.
+
+* Support activation options for error handling modes in Linux kernel
+ dm-verity module:
+
+ --ignore-corruption - dm-verity just logs detected corruption
+
+ --restart-on-corruption - dm-verity restarts the kernel if corruption is detected
+
+ If the options above are not specified, default behavior for dm-verity remains.
+ Default is that I/O operation fails with I/O error if corrupted block is detected.
+
+ --ignore-zero-blocks - Instructs dm-verity to not verify blocks that are expected
+ to contain zeroes and always return zeroes directly instead.
+
+ NOTE that these options could have security or functional impacts,
+ do not use them without assessing the risks!
+
+* Fix help text for cipher benchmark specification (mention --cipher option).
+
+* Fix off-by-one error in maximum keyfile size.
+ Allow keyfiles up to compiled-in default and not that value minus one.
+
+* Support resume of interrupted decryption in cryptsetup-reencrypt utility.
+ To resume decryption, LUKS device UUID (--uuid option) option must be used.
+
+* Do not use direct-io for LUKS header with unaligned keyslots.
+ Such headers were used only by the first cryptsetup-luks-1.0.0 release (2005).
+
+* Fix device block size detection to properly work on particular file-based
+ containers over underlying devices with 4k sectors.
diff --git a/docs/v1.7.3-ReleaseNotes b/docs/v1.7.3-ReleaseNotes
new file mode 100644
index 0000000..4a2757c
--- /dev/null
+++ b/docs/v1.7.3-ReleaseNotes
@@ -0,0 +1,20 @@
+Cryptsetup 1.7.3 Release Notes
+==============================
+
+Changes since version 1.7.2
+
+* Fix device access to hash offsets located beyond the 2GB device boundary in veritysetup.
+
+* Set configured (compile-time) default iteration time for devices created directly through
+ libcryptsetup (default was hardcoded 1 second, the configured value applied only
+ for cryptsetup application).
+
+* Fix PBKDF2 benchmark to not double iteration count for specific corner case.
+ If the measurement function returns exactly 500 ms, the iteration calculation loop
+ doubled iteration count but instead of repeating measurement it used this value directly.
+
+* OpenSSL backend: fix memory leak if hash context was repeatedly reused.
+
+* OpenSSL backend: add support for OpenSSL 1.1.0.
+
+* Fix several minor spelling errors.
diff --git a/docs/v1.7.4-ReleaseNotes b/docs/v1.7.4-ReleaseNotes
new file mode 100644
index 0000000..2b24754
--- /dev/null
+++ b/docs/v1.7.4-ReleaseNotes
@@ -0,0 +1,22 @@
+Cryptsetup 1.7.4 Release Notes
+==============================
+
+Changes since version 1.7.3
+
+* Allow one to specify LUKS1 hash algorithm in Python luksFormat wrapper.
+
+* Use LUKS1 compiled-in defaults also in Python wrapper.
+
+* OpenSSL backend: Fix OpenSSL 1.1.0 support without backward compatible API.
+
+* OpenSSL backend: Fix LibreSSL compatibility.
+
+* Check for data device and hash device area overlap in veritysetup.
+
+* Fix a possible race while allocating a free loop device.
+
+* Fix possible file descriptor leaks if libcryptsetup is run from a forked process.
+
+* Fix missing same_cpu_crypt flag in status command.
+
+* Various updates to FAQ and man pages.
diff --git a/docs/v1.7.5-ReleaseNotes b/docs/v1.7.5-ReleaseNotes
new file mode 100644
index 0000000..eec4315
--- /dev/null
+++ b/docs/v1.7.5-ReleaseNotes
@@ -0,0 +1,22 @@
+Cryptsetup 1.7.5 Release Notes
+==============================
+
+Changes since version 1.7.4
+
+* Fixes to luksFormat to properly support recent kernel running in FIPS mode.
+
+ Cryptsetup must never use a weak key even if it is just used for testing
+ of algorithm availability. In FIPS mode, weak keys are always rejected.
+
+ A weak key is for example detected if the XTS encryption mode use
+ the same key for the tweak and the encryption part.
+
+* Fixes accesses to unaligned hidden legacy TrueCrypt header.
+
+ On a native 4k-sector device the old hidden TrueCrypt header is not
+ aligned with the hw sector size (this problem was fixed in later TrueCrypt
+ on-disk format versions).
+
+ Cryptsetup now properly aligns the read so it does not fail.
+
+* Fixes to optional dracut ramdisk scripts for offline re-encryption on initial boot.
diff --git a/docs/v2.0.0-ReleaseNotes b/docs/v2.0.0-ReleaseNotes
new file mode 100644
index 0000000..401484d
--- /dev/null
+++ b/docs/v2.0.0-ReleaseNotes
@@ -0,0 +1,605 @@
+Cryptsetup 2.0.0 Release Notes
+==============================
+Stable release with experimental features.
+
+This version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+NOTE: This version changes soname of libcryptsetup library and increases
+major version for all public symbols.
+Most of the old functions are fully backward compatible, so only
+recompilation of programs should be needed.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+To provide all security features of authenticated encryption we need
+better nonce-reuse resistant algorithm in kernel (see note below).
+For now, please use authenticated encryption as experimental feature.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.0-RC1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Limit KDF requested (for format) memory by available physical memory.
+ On some systems too high requested amount of memory causes OOM killer
+ to kill the process (instead of returning ENOMEM).
+ We never try to use more than half of available physical memory.
+
+* Ignore device alignment if it is not multiple of minimal-io.
+ Some USB enclosures seems to report bogus topology info that
+ prevents to use LUKS detached header.
+
+Changes since version 2.0.0-RC0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Enable to use system libargon2 instead of bundled version.
+ Renames --disable-argon2 to --disable-internal-argon2 option
+ and adds --enable-libargon2 flag to allow system libargon2.
+
+* Changes in build system (Automake)
+ - The build system now uses non-recursive automake (except for tests).
+ (Tools binaries are now located in buildroot directory.)
+ - New --disable-cryptsetup option to disable build of cryptsetup tool.
+ - Enable build of cryptsetup-reencrypt by default.
+
+* Install tmpfiles.d configuration for LUKS2 locking directory.
+ You can overwrite this using --with-tmpfilesdir configure option.
+ If your distro does not support tmpfiles.d directory, you have
+ to create locking directory (/run/lock/cryptsetup) in cryptsetup
+ package (or init scripts).
+
+* Adds limited support for offline reencryption of LUKS2 format.
+
+* Decrease size of testing images (and the whole release archive).
+
+* Fixes for several memory leaks found by Valgrind and Coverity tools.
+
+* Fixes for several typos in man pages and error messages.
+
+* LUKS header file in luksFormat is now automatically created
+ if it does not exist.
+
+* Do not allow resize if device size is not aligned to sector size.
+
+Cryptsetup 2.0.0 RC0 Release Notes
+==================================
+
+Important features
+~~~~~~~~~~~~~~~~~~
+
+* New command integritysetup: support for the new dm-integrity kernel target.
+
+ The dm-integrity is a new kernel device-mapper target that introduces
+ software emulation of per-sector integrity fields on the disk sector level.
+ It is available since Linux kernel version 4.12.
+
+ The provided per-sector metadata fields can be used for storing a data
+ integrity checksum (for example CRC32).
+ The dm-integrity implements data journal that enforces atomic update
+ of a sector and its integrity metadata.
+
+ Integritysetup is a CLI utility that can setup standalone dm-integrity
+ devices (that internally check integrity of data).
+
+ Integritysetup is intended to be used for settings that require
+ non-cryptographic data integrity protection with no data encryption.
+ For setting integrity protected encrypted devices, see disk authenticated
+ encryption below.
+
+ Note that after formatting the checksums need to be initialized;
+ otherwise device reads will fail because of integrity errors.
+ Integritysetup by default tries to wipe the device with zero blocks
+ to avoid this problem. Device wipe can be time-consuming, you can skip
+ this step by specifying --no-wipe option.
+ (But note that not wiping device can cause some operations to fail
+ if a write is not multiple of page size and kernel page cache tries
+ to read sectors with not yet initialized checksums.)
+
+ The default setting is tag size 4 bytes per-sector and CRC32C protection.
+ To format device with these defaults:
+ $ integritysetup format <device>
+ $ integritysetup open <device> <name>
+
+ Note that used algorithm (unlike tag size) is NOT stored in device
+ kernel superblock and if you use different algorithm, you MUST specify
+ it in every open command, for example:
+ $ integritysetup format <device> --tag-size 32 --integrity sha256
+ $ integritysetup open <device> <name> --integrity sha256
+
+ For more info, see integrity man page.
+
+* Veritysetup command can now format and activate dm-verity devices
+ that contain Forward Error Correction (FEC) (Reed-Solomon code is used).
+ This feature is used on most of Android devices already (available since
+ Linux kernel 4.5).
+
+ There are new options --fec-device, --fec-offset to specify data area
+ with correction code and --fec-roots that set Redd-Solomon generator roots.
+ This setting can be used for format command (veritysetup will calculate
+ and store RS codes) or open command (veritysetup configures kernel
+ dm-verity to use RS codes).
+
+ For more info see veritysetup man page.
+
+* Support for larger sector sizes for crypt devices.
+
+ LUKS2 and plain crypt devices can be now configured with larger encryption
+ sector (typically 4096 bytes, sector size must be the power of two,
+ maximal sector size is 4096 bytes for portability).
+ Large sector size can decrease encryption overhead and can also help
+ with some specific crypto hardware accelerators that perform very
+ badly with 512 bytes sectors.
+
+ Note that if you configure such a larger sector of the device that does use
+ smaller physical sector, there is a possibility of a data corruption during
+ power fail (partial sector writes).
+
+ WARNING: If you use different sector size for a plain device after data were
+ stored, the decryption will produce garbage.
+
+ For LUKS2, the sector size is stored in metadata and cannot be changed later.
+
+LUKS2 format and features
+~~~~~~~~~~~~~~~~~~~~~~~~~
+The LUKS2 is an on-disk storage format designed to provide simple key
+management, primarily intended for Full Disk Encryption based on dm-crypt.
+
+The LUKS2 is inspired by LUKS1 format and in some specific situations (most
+of the default configurations) can be converted in-place from LUKS1.
+
+The LUKS2 format is designed to allow future updates of various
+parts without the need to modify binary structures and internally
+uses JSON text format for metadata. Compilation now requires the json-c library
+that is used for JSON data processing.
+
+On-disk format provides redundancy of metadata, detection
+of metadata corruption and automatic repair from metadata copy.
+
+NOTE: For security reasons, there is no redundancy in keyslots binary data
+(encrypted keys) but the format allows adding such a feature in future.
+
+NOTE: to operate correctly, LUKS2 requires locking of metadata.
+Locking is performed by using flock() system call for images in file
+and for block device by using a specific lock file in /run/lock/cryptsetup.
+
+This directory must be created by distribution (do not rely on internal
+fallback). For systemd-based distribution, you can simply install
+scripts/cryptsetup.conf into tmpfiles.d directory.
+
+For more details see LUKS2-format.txt and LUKS2-locking.txt in the docs
+directory. (Please note this is just overview, there will be more formal
+documentation later.)
+
+LUKS2 use
+~~~~~~~~~
+
+LUKS2 allows using all possible configurations as LUKS1.
+
+To format device as LUKS2, you have to add "--type luks2" during format:
+
+ $ cryptsetup luksFormat --type luks2 <device>
+
+All commands issued later will recognize the new format automatically.
+
+The newly added features in LUKS2 include:
+
+* Authenticated disk (sector) encryption (EXPERIMENTAL)
+
+ Legacy Full disk encryption (FDE), for example, LUKS1, is a length-preserving
+ encryption (plaintext is the same size as a ciphertext).
+ Such FDE can provide data confidentiality, but cannot provide sound data
+ integrity protection.
+
+ Full disk authenticated encryption is a way how to provide both
+ confidentiality and data integrity protection. Integrity protection here means
+ not only detection of random data corruption (silent data corruption) but also
+ prevention of an unauthorized intentional change of disk sector content.
+
+ NOTE: Integrity protection of this type cannot prevent a replay attack.
+ An attacker can replace the device or its part of the old content, and it
+ cannot be detected.
+ If you need such protection, better use integrity protection on a higher layer.
+
+ For data integrity protection on the sector level, we need additional
+ per-sector metadata space. In LUKS2 this space is provided by a new
+ device-mapper dm-integrity target (available since kernel 4.12).
+ Here the integrity target provides only reliable per-sector metadata store,
+ and the whole authenticated encryption is performed inside dm-crypt stacked
+ over the dm-integrity device.
+
+ For encryption, Authenticated Encryption with Additional Data (AEAD) is used.
+ Every sector is processed as a encryption request of this format:
+
+ |----- AAD -------|------ DATA -------|-- AUTH TAG --|
+ | (authenticated) | (auth+encryption) | |
+ | sector_LE | IV | sector in/out | tag in/out |
+
+ AEAD encrypts the whole sector and also authenticates sector number
+ (to detect sector relocation) and also authenticates Initialization Vector.
+
+ AEAD encryption produces encrypted data and authentication tag.
+ The authenticated tag is then stored in per-sector metadata space provided
+ by dm-integrity.
+
+ Most of the current AEAD algorithms requires IV as a nonce, value that is
+ never reused. Because sector number, as an IV, cannot be used in this
+ environment, we use a new random IV (IV is a random value generated by system
+ RNG on every write). This random IV is then stored in the per-sector metadata
+ as well.
+
+ Because the authentication tag (and IV) requires additional space, the device
+ provided for a user has less capacity. Also, the data journalling means that
+ writes are performed twice, decreasing throughput.
+
+ This integrity protection works better with SSDs. If you want to ignore
+ dm-integrity data journal (because journalling is performed on some higher
+ layer or you just want to trade-off performance to safe recovery), you can
+ switch journal off with --integrity-no-journal option.
+ (This flag can be stored persistently as well.)
+
+ Note that (similar to integritysetup) the device read will fail if
+ authentication tag is not initialized (no previous write).
+ By default cryptsetup run wipe of a device (writing zeroes) to initialize
+ authentication tags. This operation can be very time-consuming.
+ You can skip device wipe using --integrity-no-wipe option.
+
+ To format LUKS2 device with integrity protection, use new --integrity option.
+
+ For now, there are very few AEAD algorithms that can be used, and some
+ of them are known to be problematic. In this release we support only
+ a few of AEAD algorithms (options are for now hard coded), later this
+ extension will be completely algorithm-agnostic.
+
+ For testing of authenticated encryption, these algorithms work for now:
+
+ 1) aes-xts-plain64 with hmac-sha256 or hmac-sha512 as the authentication tag.
+ (Common FDE mode + independent authentication tag. Authentication key
+ for HMAC is independently generated. This mode is very slow.)
+ $ cryptsetup luksFormat --type luks2 <device> --cipher aes-xts-plain64 --integrity hmac-sha256
+
+ 2) aes-gcm-random (native AEAD mode)
+ DO NOT USE in production! The GCM mode uses only 96-bit nonce,
+ and possible collision means fatal security problem.
+ GCM mode has very good hardware support through AES-NI, so it is useful
+ for performance testing.
+ $ cryptsetup luksFormat --type luks2 <device> --cipher aes-gcm-random --integrity aead
+
+ 3) ChaCha20 with Poly1305 authenticator (according to RFC7539)
+ $ cryptsetup luksFormat --type luks2 <device> --cipher chacha20-random --integrity poly1305
+
+ To specify AES128/AES256 just specify proper key size (without possible
+ authentication key). Other symmetric ciphers, like Serpent or Twofish,
+ should work as well. The mode 1) and 2) should be compatible with IEEE 1619.1
+ standard recommendation.
+
+ There will be better suitable authenticated modes available soon
+ For now we are just preparing framework to enable it (and hopefully improve security of FDE).
+
+ FDE authenticated encryption is not a replacement for filesystem layer
+ authenticated encryption. The goal is to provide at least something because
+ data integrity protection is often completely ignored in today systems.
+
+* New memory-hard PBKDF
+
+ LUKS1 introduced Password-Based Key Derivation Function v2 as a tool to
+ increase attacker cost for a dictionary and brute force attacks.
+ The PBKDF2 uses iteration count to increase time of key derivation.
+ Unfortunately, with modern GPUs, the PBKDF2 calculations can be run
+ in parallel and PBKDF2 can no longer provide the best available protection.
+ Increasing iteration count just cannot prevent massive parallel dictionary
+ password attacks in long-term.
+
+ To solve this problem, a new PBKDF, based on so-called memory-hard functions
+ can be used. Key derivation with memory-hard function requires a certain
+ amount of memory to compute its output. The memory requirement is very
+ costly for GPUs and prevents these systems to operate effectively,
+ increasing cost for attackers.
+
+ LUKS2 introduces support for Argon2i and Argon2id as a PBKDF.
+ Argon2 is the winner of Password Hashing Competition and is currently
+ in final RFC draft specification.
+
+ For now, libcryptsetup contains the embedded copy of reference implementation
+ of Argon2 (that is easily portable to all architectures).
+ Later, once this function is available in common crypto libraries, it will
+ switch to external implementation. (This happened for LUKS1 and PBKDF2
+ as well years ago.)
+ With using reference implementation (that is not optimized for speed), there
+ is some performance penalty. However, using memory-hard PBKDF should still
+ significantly complicate GPU-optimized dictionary and brute force attacks.
+
+ The Argon2 uses three costs: memory, time (number of iterations) and parallel
+ (number of threads).
+ Note that time and memory cost highly influences each other (accessing a lot
+ of memory takes more time).
+
+ There is a new benchmark that tries to calculate costs to take similar way as
+ in LUKS1 (where iteration is measured to take 1-2 seconds on user system).
+ Because now there are more cost variables, it prefers time cost (iterations)
+ and tries to find required memory that fits. (IOW required memory cost can be
+ lower if the benchmarks are not able to find required parameters.)
+ The benchmark cannot run too long, so it tries to approximate next step
+ for benchmarking.
+
+ For now, default LUKS2 PBKDF algorithm is Argon2i (data independent variant)
+ with memory cost set to 128MB, time to 800ms and parallel thread according
+ to available CPU cores but no more than 4.
+
+ All default parameters can be set during compile time and also set on
+ the command line by using --pbkdf, --pbkdf-memory, --pbkdf-parallel and
+ --iter-time options.
+ (Or without benchmark directly by using --pbkdf-force-iterations, see below.)
+
+ You can still use PBKDF2 even for LUKS2 by specifying --pbkdf pbkdf2 option.
+ (Then only iteration count is applied.)
+
+* Use of kernel keyring
+
+ Kernel keyring is a storage for sensitive material (like cryptographic keys)
+ inside Linux kernel.
+
+ LUKS2 uses keyring for two major functions:
+
+ - To store volume key for dm-crypt where it avoids sending volume key in
+ every device-mapper ioctl structure. Volume key is also no longer directly
+ visible in a dm-crypt mapping table. The key is not available for the user
+ after dm-crypt configuration (obviously except direct memory scan).
+ Use of kernel keyring can be disabled in runtime by --disable-keyring option.
+
+ - As a tool to automatically unlock LUKS device if a passphrase is put into
+ kernel keyring and proper keyring token is configured.
+
+ This allows storing a secret (passphrase) to kernel per-user keyring by
+ some external tool (for example some TPM handler) and LUKS2, if configured,
+ will automatically search in the keyring and unlock the system.
+ For more info see Tokens section below.
+
+* Persistent flags
+ The activation flags (like allow-discards) can be stored in metadata and used
+ automatically by all later activations (even without using crypttab).
+
+ To store activation flags permanently, use activation command with required
+ flags and add --persistent option.
+
+ For example, to mark device to always activate with TRIM enabled,
+ use (for LUKS2 type):
+
+ $ cryptsetup open <device> <name> --allow-discards --persistent
+
+ You can check persistent flags in dump command output:
+
+ $ cryptsetup luksDump <device>
+
+* Tokens and auto-activation
+
+ A LUKS2 token is an object that can be described "how to get passphrase or key"
+ to unlock particular keyslot.
+ (Also it can be used to store any additional metadata, and with
+ the libcryptsetup interface it can be used to define user token types.)
+
+ Cryptsetup internally implements keyring token. Cryptsetup tries to use
+ available tokens before asking for the passphrase. For keyring token,
+ it means that if the passphrase is available under specified identifier
+ inside kernel keyring, the device is automatically activated using this
+ stored passphrase.
+
+ Example of using LUKS2 keyring token:
+
+ # Adding token to metadata with "my_token" identifier (by default it applies to all keyslots).
+ $ cryptsetup token add --key-description "my_token" <device>
+
+ # Storing passphrase to user keyring (this can be done by an external application)
+ $ echo -n <passphrase> | keyctl padd user my_token @u
+
+ # Now cryptsetup activates automatically if it finds correct passphrase
+ $ cryptsetup open <device> <name>
+
+ The main reason to use tokens this way is to separate possible hardware
+ handlers from cryptsetup code.
+
+* Keyslot priorities
+
+ LUKS2 keyslot can have a new priority attribute.
+ The default is "normal". The "prefer" priority tell the keyslot to be tried
+ before other keyslots. Priority "ignore" means that keyslot will never be
+ used if not specified explicitly (it can be used for backup administrator
+ passwords that are used only situations when a user forgets own passphrase).
+
+ The priority of keyslot can be set with new config command, for example
+ $ cryptsetup config <device> --key-slot 1 --priority prefer
+
+ Setting priority to normal will reset slot to normal state.
+
+* LUKS2 label and subsystem
+
+ The header now contains additional fields for label and subsystem (additional
+ label). These fields can be used similar to filesystem label and will be
+ visible in udev rules to possible filtering. (Note that blkid do not yet
+ contain the LUKS scanning code).
+
+ By default both labels are empty. Label and subsystem are always set together
+ (no option means clear the label) with the config command:
+
+ $ cryptsetup config <device> --label my_device --subsystem ""
+
+* In-place conversion form LUKS1
+
+ To allow easy testing and transition to the new LUKS2 format, there is a new
+ convert command that allows in-place conversion from the LUKS1 format and,
+ if there are no incompatible options, also conversion back from LUKS2
+ to LUKS1 format.
+
+ Note this command can be used only on some LUKS1 devices (some device header
+ sizes are not supported).
+ This command is dangerous, never run it without header backup!
+ If something fails in the middle of conversion (IO error), the header
+ is destroyed. (Note that conversion requires move of keyslot data area to
+ a different offset.)
+
+ To convert header in-place to LUKS2 format, use
+ $ cryptsetup convert <device> --type luks2
+
+ To convert it back to LUKS1 format, use
+ $ cryptsetup convert <device> --type luks1
+
+ You can verify LUKS version with luksDump command.
+ $ cryptsetup luksDump <device>
+
+ Note that some LUKS2 features will make header incompatible with LUKS1 and
+ conversion will be rejected (for example using new Argon2 PBKDF or integrity
+ extensions). Some minor attributes can be lost in conversion.
+
+Other changes
+~~~~~~~~~~~~~
+
+* Explicit KDF iterations count setting
+
+ With new PBKDF interface, there is also the possibility to setup PBKDF costs
+ directly, avoiding benchmarks. This can be useful if device is formatted to be
+ primarily used on a different system.
+
+ The option --pbkdf-force-iterations is available for both LUKS1 and LUKS2
+ format. Using this option can cause device to have either very low or very
+ high PBKDF costs.
+ In the first case it means bad protection to dictionary attacks, in the second
+ case, it can mean extremely high unlocking time or memory requirements.
+ Use only if you are sure what you are doing!
+
+ Not that this setting also affects iteration count for the key digest.
+ For LUKS1 iteration count for digest will be approximately 1/8 of requested
+ value, for LUKS2 and "pbkdf2" digest minimal PBKDF2 iteration count (1000)
+ will be used. You cannot set lower iteration count than the internal minimum
+ (1000 for PBKDF2).
+
+ To format LUKS1 device with forced iteration count (and no benchmarking), use
+ $ cryptsetup luksFormat <device> --pbkdf-force-iterations 22222
+
+ For LUKS2 it is always better to specify full settings (do not rely on default
+ cost values).
+ For example, we can set to use Argon2id with iteration cost 5, memory 128000
+ and parallel set 1:
+ $ cryptsetup luksFormat --type luks2 <device> \
+ --pbkdf argon2id --pbkdf-force-iterations 5 --pbkdf-memory 128000 --pbkdf-parallel 1
+
+* VeraCrypt PIM
+
+ Cryptsetup can now also open VeraCrypt device that uses Personal Iteration
+ Multiplier (PIM). PIM is an integer value that user must remember additionally
+ to passphrase and influences PBKDF2 iteration count (without it VeraCrypt uses
+ a fixed number of iterations).
+
+ To open VeraCrypt device with PIM settings, use --veracrypt-pim (to specify
+ PIM on the command line) or --veracrypt-query-pim to query PIM interactively.
+
+* Support for plain64be IV
+
+ The plain64be is big-endian variant of plain64 Initialization Vector. It is
+ used in some images of hardware-based disk encryption systems. Supporting this
+ variant allows using dm-crypt to map such images through cryptsetup.
+
+* Deferral removal
+
+ Cryptsetup now can mark device for deferred removal by using a new option
+ --deferred. This means that close command will not fail if the device is still
+ in use, but will instruct the kernel to remove the device automatically after
+ use count drops to zero (for example, once the filesystem is unmounted).
+
+* A lot of updates to man pages and many minor changes that would make this
+ release notes too long ;-)
+
+Libcryptsetup API changes
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These API functions were removed, libcryptsetup no longer handles password
+retries from terminal (application should handle terminal operations itself):
+ crypt_set_password_callback;
+ crypt_set_timeout;
+ crypt_set_password_retry;
+ crypt_set_password_verify;
+
+This call is removed (no need to keep typo backward compatibility,
+the proper function is crypt_set_iteration_time :-)
+ crypt_set_iterarion_time;
+
+These calls were removed because are not safe, use per-context
+error callbacks instead:
+ crypt_last_error;
+ crypt_get_error;
+
+The PBKDF benchmark was replaced by a new function that uses new KDF structure
+ crypt_benchmark_kdf; (removed)
+ crypt_benchmark_pbkdf; (new API call)
+
+These new calls are now exported, for details see libcryptsetup.h:
+ crypt_keyslot_add_by_key;
+ crypt_keyslot_set_priority;
+ crypt_keyslot_get_priority;
+
+ crypt_token_json_get;
+ crypt_token_json_set;
+ crypt_token_status;
+ crypt_token_luks2_keyring_get;
+ crypt_token_luks2_keyring_set;
+ crypt_token_assign_keyslot;
+ crypt_token_unassign_keyslot;
+ crypt_token_register;
+
+ crypt_activate_by_token;
+ crypt_activate_by_keyring;
+ crypt_deactivate_by_name;
+
+ crypt_metadata_locking;
+ crypt_volume_key_keyring;
+ crypt_get_integrity_info;
+ crypt_get_sector_size;
+ crypt_persistent_flags_set;
+ crypt_persistent_flags_get;
+ crypt_set_pbkdf_type;
+ crypt_get_pbkdf_type;
+
+ crypt_convert;
+ crypt_keyfile_read;
+ crypt_wipe;
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* There will be better documentation and examples.
+
+* There will be some more formal definition of the threat model for integrity
+ protection. (And a link to some papers discussing integrity protection,
+ once it is, hopefully, accepted and published.)
+
+* Offline re-encrypt tool LUKS2 support is currently limited.
+ There will be online LUKS2 re-encryption tool in future.
+
+* Authenticated encryption will use new algorithms from CAESAR competition
+ (https://competitions.cr.yp.to/caesar.html) once these algorithms are available
+ in kernel (more on this later).
+ NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
+ in kernel have too small 96-bit nonces that are problematic with
+ randomly generated IVs (the collision probability is not negligible).
+ For the GCM, nonce collision is a fatal problem.
+
+* Authenticated encryption do not set encryption for dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* Some utilities (blkid, systemd-cryptsetup) have already support for LUKS
+ but not yet in released version (support in crypttab etc).
+
+* There are some examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be deprecated soon in favor
+ of python bindings to libblockdev library (that can already handle LUKS1 devices).
diff --git a/docs/v2.0.1-ReleaseNotes b/docs/v2.0.1-ReleaseNotes
new file mode 100644
index 0000000..0cc13b9
--- /dev/null
+++ b/docs/v2.0.1-ReleaseNotes
@@ -0,0 +1,109 @@
+Cryptsetup 2.0.1 Release Notes
+==============================
+Stable and bug-fix release with experimental features.
+
+This version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+To provide all security features of authenticated encryption we need
+a better nonce-reuse resistant algorithm in the kernel (see note below).
+For now, please use authenticated encryption as an experimental feature.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* To store volume key into kernel keyring, kernel 4.15 with dm-crypt 1.18.1
+ is required. If a volume key is stored in keyring (LUKS2 only),
+ the dm-crypt v1.15.0 through v1.18.0 contains a serious bug that may cause
+ data corruption for ciphers with ESSIV.
+ (The key for ESSIV is zeroed because of code misplacement.)
+ This bug is not present for LUKS1 or any other IVs used in LUKS modes.
+ This change is not visible to the user (except dmsetup output).
+
+* Increase maximum allowed PBKDF memory-cost limit to 4 GiB.
+ The Argon2 PBKDF uses 1GiB by default; this is also limited by the amount
+ of physical memory available (maximum is half of the physical memory).
+
+* Use /run/cryptsetup as default for cryptsetup locking dir.
+ There were problems with sharing /run/lock with lockdev, and in the early
+ boot, the directory was missing.
+ The directory can be changed with --with-luks2-lock-path and
+ --with-luks2-lock-dir-perms configure switches.
+
+* Introduce new 64-bit byte-offset *keyfile_device_offset functions.
+
+ The keyfile interface was designed, well, for keyfiles. Unfortunately,
+ there are user cases where a keyfile can be placed on a device, and
+ size_t offset can overflow on 32-bit systems.
+
+ New set of functions that allow 64-bit offsets even on 32bit systems
+ are now available:
+
+ - crypt_resume_by_keyfile_device_offset
+ - crypt_keyslot_add_by_keyfile_device_offset
+ - crypt_activate_by_keyfile_device_offset
+ - crypt_keyfile_device_read
+
+ The new functions have added the _device_ in name.
+ Old functions are just internal wrappers around these.
+
+ Also cryptsetup --keyfile-offset and --new-keyfile-offset now allows
+ 64-bit offsets as parameters.
+
+* Add error hint for wrongly formatted cipher strings in LUKS1 and
+ properly fail in luksFormat if cipher format is missing required IV.
+ For now, crypto API quietly used cipher without IV if a cipher
+ algorithm without IV specification was used (e.g., aes-xts).
+ This caused fail later during activation.
+
+* Configure check for a recent Argon2 lib to support mandatory Argon2id.
+
+* Fix for the cryptsetup-reencrypt static build if pwquality is enabled.
+
+* Update LUKS1 standard doc (https links in the bibliography).
+
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* There will be better documentation and examples.
+
+* There will be some more formal definition of the threat model for integrity
+ protection. (And a link to some papers discussing integrity protection,
+ once it is, hopefully, accepted and published.)
+
+* Offline re-encrypt tool LUKS2 support is currently limited.
+ There will be online LUKS2 re-encryption tool in future.
+
+* Authenticated encryption will use new algorithms from CAESAR competition
+ (https://competitions.cr.yp.to/caesar.html) once these algorithms are
+ available in the kernel (more on this later).
+ NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
+ in the kernel have too small 96-bit nonces that are problematic with
+ randomly generated IVs (the collision probability is not negligible).
+ For the GCM, nonce collision is a fatal problem.
+
+* Authenticated encryption do not set encryption for a dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* There are examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be deprecated soon in favor
+ of python bindings to the libblockdev library (that can already handle LUKS1
+ devices).
diff --git a/docs/v2.0.2-ReleaseNotes b/docs/v2.0.2-ReleaseNotes
new file mode 100644
index 0000000..bda57fd
--- /dev/null
+++ b/docs/v2.0.2-ReleaseNotes
@@ -0,0 +1,93 @@
+Cryptsetup 2.0.2 Release Notes
+==============================
+Stable and bug-fix release with experimental features.
+
+Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+To provide all security features of authenticated encryption, we need
+a better nonce-reuse resistant algorithm in the kernel (see note below).
+For now, please use authenticated encryption as an experimental feature.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix a regression in early detection of inactive keyslot for luksKillSlot.
+ It tried to ask for passphrase even for already erased keyslot.
+
+* Fix a regression in loopaesOpen processing for keyfile on standard input.
+ Use of "-" argument was not working properly.
+
+* Add LUKS2 specific options for cryptsetup-reencrypt.
+ Tokens and persistent flags are now transferred during reencryption;
+ change of PBKDF keyslot parameters is now supported and allows one
+ to set precalculated values (no benchmarks).
+
+* Do not allow LUKS2 --persistent and --test-passphrase cryptsetup flags
+ combination. Persistent flags are now stored only if the device was
+ successfully activated with the specified flags.
+
+* Fix integritysetup format after recent Linux kernel changes that
+ requires to setup key for HMAC in all cases.
+ Previously integritysetup allowed HMAC with zero key that behaves
+ like a plain hash.
+
+* Fix VeraCrypt PIM handling that modified internal iteration counts
+ even for subsequent activations. The PIM count is no longer printed
+ in debug log as it is sensitive information.
+ Also, the code now skips legacy TrueCrypt algorithms if a PIM
+ is specified (they cannot be used with PIM anyway).
+
+* PBKDF values cannot be set (even with force parameters) below
+ hardcoded minimums. For PBKDF2 is it 1000 iterations, for Argon2
+ it is 4 iterations and 32 KiB of memory cost.
+
+* Introduce new crypt_token_is_assigned() API function for reporting
+ the binding between token and keyslots.
+
+* Allow crypt_token_json_set() API function to create internal token types.
+ Do not allow unknown fields in internal token objects.
+
+* Print message in cryptsetup that about was aborted if a user did not
+ answer YES in a query.
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* There will be better documentation and examples.
+
+* There will be some more formal definition of the threat model for integrity
+ protection. (And a link to some papers discussing integrity protection,
+ once it is, hopefully, accepted and published.)
+
+* Authenticated encryption will use new algorithms from CAESAR competition
+ https://competitions.cr.yp.to/caesar-submissions.html.
+ We plan to use AEGIS and MORUS, as CAESAR finalists.
+
+ NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
+ in the kernel have too small 96-bit nonces that are problematic with
+ randomly generated IVs (the collision probability is not negligible).
+
+* Authenticated encryption do not set encryption for a dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* There are examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be deprecated in version 2.1
+ in favor of python bindings to the libblockdev library.
diff --git a/docs/v2.0.3-ReleaseNotes b/docs/v2.0.3-ReleaseNotes
new file mode 100644
index 0000000..d2b209b
--- /dev/null
+++ b/docs/v2.0.3-ReleaseNotes
@@ -0,0 +1,121 @@
+Cryptsetup 2.0.3 Release Notes
+==============================
+Stable bug-fix release with new features.
+
+Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+To provide all security features of authenticated encryption, we need
+a better nonce-reuse resistant algorithm in the kernel (see note below).
+For now, please use authenticated encryption as an experimental feature.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Expose interface to unbound LUKS2 keyslots.
+ Unbound LUKS2 keyslot allows storing a key material that is independent
+ of master volume key (it is not bound to encrypted data segment).
+
+* New API extensions for unbound keyslots (LUKS2 only)
+ crypt_keyslot_get_key_size() and crypt_volume_key_get()
+ These functions allow one to get key and key size for unbound keyslots.
+
+* New enum value CRYPT_SLOT_UNBOUND for keyslot status (LUKS2 only).
+
+* Add --unbound keyslot option to the cryptsetup luksAddKey command.
+
+* Add crypt_get_active_integrity_failures() call to get integrity
+ failure count for dm-integrity devices.
+
+* Add crypt_get_pbkdf_default() function to get per-type PBKDF default
+ setting.
+
+* Add new flag to crypt_keyslot_add_by_key() to force update device
+ volume key. This call is mainly intended for a wrapped key change.
+
+* Allow volume key store in a file with cryptsetup.
+ The --dump-master-key together with --master-key-file allows cryptsetup
+ to store the binary volume key to a file instead of standard output.
+
+* Add support detached header for cryptsetup-reencrypt command.
+
+* Fix VeraCrypt PIM handling - use proper iterations count formula
+ for PBKDF2-SHA512 and PBKDF2-Whirlpool used in system volumes.
+
+* Fix cryptsetup tcryptDump for VeraCrypt PIM (support --veracrypt-pim).
+
+* Add --with-default-luks-format configure time option.
+ (Option to override default LUKS format version.)
+
+* Fix LUKS version conversion for detached (and trimmed) LUKS headers.
+
+* Add luksConvertKey cryptsetup command that converts specific keyslot
+ from one PBKDF to another.
+
+* Do not allow conversion to LUKS2 if LUKSMETA (external tool metadata)
+ header is detected.
+
+* More cleanup and hardening of LUKS2 keyslot specific validation options.
+ Add more checks for cipher validity before writing metadata on-disk.
+
+* Do not allow LUKS1 version downconversion if the header contains tokens.
+
+* Add "paes" family ciphers (AES wrapped key scheme for mainframes)
+ to allowed ciphers.
+ Specific wrapped ley configuration logic must be done by 3rd party tool,
+ LUKS2 stores only keyslot material and allow activation of the device.
+
+* Add support for --check-at-most-once option (kernel 4.17) to veritysetup.
+ This flag can be dangerous; if you can control underlying device
+ (you can change its content after it was verified) it will no longer
+ prevent reading tampered data and also it does not prevent silent
+ data corruptions that appear after the block was once read.
+
+* Fix return code (EPERM instead of EINVAL) and retry count for bad
+ passphrase on non-tty input.
+
+* Enable support for FEC decoding in veritysetup to check dm-verity devices
+ with additional Reed-Solomon code in userspace (verify command).
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* There will be better documentation and examples (planned for 2.0.4).
+
+* There will be some more formal definition of the threat model for integrity
+ protection. (And a link to some papers discussing integrity protection,
+ once it is, hopefully, accepted and published.)
+
+* Authenticated encryption will use new algorithms from CAESAR competition
+ https://competitions.cr.yp.to/caesar-submissions.html.
+ We plan to use AEGIS and MORUS, as CAESAR finalists.
+
+ NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
+ in the kernel have too small 96-bit nonces that are problematic with
+ randomly generated IVs (the collision probability is not negligible).
+
+* Authenticated encryption do not set encryption for a dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* There are examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be REMOVED in version 2.1
+ in favor of python bindings to the libblockdev library.
+ See https://github.com/storaged-project/libblockdev/releases/tag/2.17-1 that
+ already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
diff --git a/docs/v2.0.4-ReleaseNotes b/docs/v2.0.4-ReleaseNotes
new file mode 100644
index 0000000..9731f59
--- /dev/null
+++ b/docs/v2.0.4-ReleaseNotes
@@ -0,0 +1,119 @@
+Cryptsetup 2.0.4 Release Notes
+==============================
+Stable bug-fix release with new features.
+
+Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+To provide all security features of authenticated encryption, we need
+a better nonce-reuse resistant algorithm in the kernel (see note below).
+For now, please use authenticated encryption as an experimental feature.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Use the libblkid (blockid) library to detect foreign signatures
+ on a device before LUKS format and LUKS2 auto-recovery.
+
+ This change fixes an unexpected recovery using the secondary
+ LUKS2 header after a device was already overwritten with
+ another format (filesystem or LVM physical volume).
+
+ LUKS2 will not recreate a primary header if it detects a valid
+ foreign signature. In this situation, a user must always
+ use cryptsetup repair command for the recovery.
+
+ Note that libcryptsetup and utilities are now linked to libblkid
+ as a new dependence.
+
+ To compile code without blockid support (strongly discouraged),
+ use --disable-blkid configure switch.
+
+* Add prompt for format and repair actions in cryptsetup and
+ integritysetup if foreign signatures are detected on the device
+ through the blockid library.
+
+ After the confirmation, all known signatures are then wiped as
+ part of the format or repair procedure.
+
+* Print consistent verbose message about keyslot and token numbers.
+ For keyslot actions: Key slot <number> unlocked/created/removed.
+ For token actions: Token <number> created/removed.
+
+* Print error, if a non-existent token is tried to be removed.
+
+* Add support for LUKS2 token definition export and import.
+
+ The token command now can export/import customized token JSON file
+ directly from command line. See the man page for more details.
+
+* Add support for new dm-integrity superblock version 2.
+
+* Add an error message when nothing was read from a key file.
+
+* Update cryptsetup man pages, including --type option usage.
+
+* Add a snapshot of LUKS2 format specification to documentation
+ and accordingly fix supported secondary header offsets.
+
+* Add bundled optimized Argon2 SSE (X86_64 platform) code.
+
+ If the bundled Argon2 code is used and the new configure switch
+ --enable-internal-sse-argon2 option is present, and compiler flags
+ support required optimization, the code will try to use optimized
+ and faster variant.
+
+ Always use the shared library (--enable-libargon2) if possible.
+
+ This option was added because an enterprise distribution
+ rejected to support the shared Argon2 library and native support
+ in generic cryptographic libraries is not ready yet.
+
+* Fix compilation with crypto backend for LibreSSL >= 2.7.0.
+ LibreSSL introduced OpenSSL 1.1.x API functions, so compatibility
+ wrapper must be commented out.
+
+* Fix on-disk header size calculation for LUKS2 format if a specific
+ data alignment is requested. Until now, the code used default size
+ that could be wrong for converted devices.
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Authenticated encryption will use new algorithms from CAESAR competition
+ https://competitions.cr.yp.to/caesar-submissions.html.
+ We plan to use AEGIS and MORUS (in kernel 4.18), as CAESAR finalists.
+
+ NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
+ in the kernel have too small 96-bit nonces that are problematic with
+ randomly generated IVs (the collision probability is not negligible).
+
+ For more info about LUKS2 authenticated encryption, please see our paper
+ https://arxiv.org/abs/1807.00309
+
+* Authenticated encryption do not set encryption for a dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* There are examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be REMOVED in version 2.1
+ in favor of python bindings to the libblockdev library.
+ See https://github.com/storaged-project/libblockdev/releases that
+ already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
+
diff --git a/docs/v2.0.5-ReleaseNotes b/docs/v2.0.5-ReleaseNotes
new file mode 100644
index 0000000..907d5aa
--- /dev/null
+++ b/docs/v2.0.5-ReleaseNotes
@@ -0,0 +1,102 @@
+Cryptsetup 2.0.5 Release Notes
+==============================
+Stable bug-fix release with new features.
+
+Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Wipe full header areas (including unused) during LUKS format.
+
+ Since this version, the whole area up to the data offset is zeroed,
+ and subsequently, all keyslots areas are wiped with random data.
+ This ensures that no remaining old data remains in the LUKS header
+ areas, but it could slow down format operation on some devices.
+ Previously only first 4k (or 32k for LUKS2) and the used keyslot
+ was overwritten in the format operation.
+
+* Several fixes to error messages that were unintentionally replaced
+ in previous versions with a silent exit code.
+ More descriptive error messages were added, including error
+ messages if
+ - a device is unusable (not a block device, no access, etc.),
+ - a LUKS device is not detected,
+ - LUKS header load code detects unsupported version,
+ - a keyslot decryption fails (also happens in the cipher check),
+ - converting an inactive keyslot.
+
+* Device activation fails if data area overlaps with LUKS header.
+
+* Code now uses explicit_bzero to wipe memory if available
+ (instead of own implementation).
+
+* Additional VeraCrypt modes are now supported, including Camellia
+ and Kuznyechik symmetric ciphers (and cipher chains) and Streebog
+ hash function. These were introduced in a recent VeraCrypt upstream.
+
+ Note that Kuznyechik requires out-of-tree kernel module and
+ Streebog hash function is available only with the gcrypt cryptographic
+ backend for now.
+
+* Fixes static build for integritysetup if the pwquality library is used.
+
+* Allows passphrase change for unbound keyslots.
+
+* Fixes removed keyslot number in verbose message for luksKillSlot,
+ luksRemoveKey and erase command.
+
+* Adds blkid scan when attempting to open a plain device and warn the user
+ about existing device signatures in a ciphertext device.
+
+* Remove LUKS header signature if luksFormat fails to add the first keyslot.
+
+* Remove O_SYNC from device open and use fsync() to speed up
+ wipe operation considerably.
+
+* Create --master-key-file in luksDump and fail if the file already exists.
+
+* Fixes a bug when LUKS2 authenticated encryption with a detached header
+ wiped the header device instead of dm-integrity data device area (causing
+ unnecessary LUKS2 header auto recovery).
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Authenticated encryption should use new algorithms from CAESAR competition
+ https://competitions.cr.yp.to/caesar-submissions.html.
+ AEGIS and MORUS are already available in kernel 4.18.
+
+ For more info about LUKS2 authenticated encryption, please see our paper
+ https://arxiv.org/abs/1807.00309
+
+ Please note that authenticated encryption is still an experimental feature
+ and can have performance problems for hish-speed devices and device
+ with larger IO blocks (like RAID).
+
+* Authenticated encryption do not set encryption for a dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* There are examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be REMOVED in version 2.1
+ in favor of python bindings to the libblockdev library.
+ See https://github.com/storaged-project/libblockdev/releases that
+ already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
diff --git a/docs/v2.0.6-ReleaseNotes b/docs/v2.0.6-ReleaseNotes
new file mode 100644
index 0000000..7fe276a
--- /dev/null
+++ b/docs/v2.0.6-ReleaseNotes
@@ -0,0 +1,97 @@
+Cryptsetup 2.0.6 Release Notes
+==============================
+Stable bug-fix release.
+All users of cryptsetup 2.0.x should upgrade to this version.
+
+Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported
+forever as well as a traditional and fully backward compatible format.
+
+Please note that authenticated disk encryption, non-cryptographic
+data integrity protection (dm-integrity), use of Argon2 Password-Based
+Key Derivation Function and the LUKS2 on-disk format itself are new
+features and can contain some bugs.
+
+Please do not use LUKS2 without properly configured backup or in
+production systems that need to be compatible with older systems.
+
+Changes since version 2.0.5
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix support of larger metadata areas in LUKS2 header.
+
+ This release properly supports all specified metadata areas, as documented
+ in LUKS2 format description (see docs/on-disk-format-luks2.pdf in archive).
+
+ Currently, only default metadata area size is used (in format or convert).
+ Later cryptsetup versions will allow increasing this metadata area size.
+
+* If AEAD (authenticated encryption) is used, cryptsetup now tries to check
+ if the requested AEAD algorithm with specified key size is available
+ in kernel crypto API.
+ This change avoids formatting a device that cannot be later activated.
+
+ For this function, the kernel must be compiled with the
+ CONFIG_CRYPTO_USER_API_AEAD option enabled.
+ Note that kernel user crypto API options (CONFIG_CRYPTO_USER_API and
+ CONFIG_CRYPTO_USER_API_SKCIPHER) are already mandatory for LUKS2.
+
+* Fix setting of integrity no-journal flag.
+ Now you can store this flag to metadata using --persistent option.
+
+* Fix cryptsetup-reencrypt to not keep temporary reencryption headers
+ if interrupted during initial password prompt.
+
+* Adds early check to plain and LUKS2 formats to disallow device format
+ if device size is not aligned to requested sector size.
+ Previously it was possible, and the device was rejected to activate by
+ kernel later.
+
+* Fix checking of hash algorithms availability for PBKDF early.
+ Previously LUKS2 format allowed non-existent hash algorithm with
+ invalid keyslot preventing the device from activation.
+
+* Allow Adiantum cipher construction (a non-authenticated length-preserving
+ fast encryption scheme), so it can be used both for data encryption and
+ keyslot encryption in LUKS1/2 devices.
+
+ For benchmark, use:
+ # cryptsetup benchmark -c xchacha12,aes-adiantum
+ # cryptsetup benchmark -c xchacha20,aes-adiantum
+
+ For LUKS format:
+ # cryptsetup luksFormat -c xchacha20,aes-adiantum-plain64 -s 256 <device>
+
+ The support for Adiantum will be merged in Linux kernel 4.21.
+ For more info see the paper https://eprint.iacr.org/2018/720.
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Authenticated encryption should use new algorithms from CAESAR competition
+ https://competitions.cr.yp.to/caesar-submissions.html.
+ AEGIS and MORUS are already available in kernel 4.18.
+
+ For more info about LUKS2 authenticated encryption, please see our paper
+ https://arxiv.org/abs/1807.00309
+
+ Please note that authenticated encryption is still an experimental feature
+ and can have performance problems for high-speed devices and device
+ with larger IO blocks (like RAID).
+
+* Authenticated encryption do not set encryption for a dm-integrity journal.
+
+ While it does not influence data confidentiality or integrity protection,
+ an attacker can get some more information from data journal or cause that
+ system will corrupt sectors after journal replay. (That corruption will be
+ detected though.)
+
+* There are examples of user-defined tokens inside misc/luks2_keyslot_example
+ directory (like a simple external program that uses libssh to unlock LUKS2
+ using remote keyfile).
+
+* The python binding (pycryptsetup) contains only basic functionality for LUKS1
+ (it is not updated for new features) and will be REMOVED in version 2.1
+ in favor of python bindings to the libblockdev library.
+ See https://github.com/storaged-project/libblockdev/releases that
+ already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
diff --git a/docs/v2.1.0-ReleaseNotes b/docs/v2.1.0-ReleaseNotes
new file mode 100644
index 0000000..87222cb
--- /dev/null
+++ b/docs/v2.1.0-ReleaseNotes
@@ -0,0 +1,210 @@
+Cryptsetup 2.1.0 Release Notes
+==============================
+Stable release with new features and bug fixes.
+
+Cryptsetup 2.1 version uses a new on-disk LUKS2 format as the default
+LUKS format and increases default LUKS2 header size.
+
+The legacy LUKS (referenced as LUKS1) will be fully supported forever
+as well as a traditional and fully backward compatible format.
+
+When upgrading a stable distribution, please use configure option
+--with-default-luks-format=LUKS1 to maintain backward compatibility.
+
+This release also switches to OpenSSL as a default cryptographic
+backend for LUKS header processing. Use --with-crypto_backend=gcrypt
+configure option if you need to preserve legacy libgcrypt backend.
+
+Please do not use LUKS2 without properly configured backup or
+in production systems that need to be compatible with older systems.
+
+Changes since version 2.0.6
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* The default for cryptsetup LUKS format action is now LUKS2.
+ You can use LUKS1 with cryptsetup option --type luks1.
+
+* The default size of the LUKS2 header is increased to 16 MB.
+ It includes metadata and the area used for binary keyslots;
+ it means that LUKS header backup is now 16MB in size.
+
+ Note, that used keyslot area is much smaller, but this increase
+ of reserved space allows implementation of later extensions
+ (like online reencryption).
+ It is fully compatible with older cryptsetup 2.0.x versions.
+ If you require to create LUKS2 header with the same size as
+ in the 2.0.x version, use --offset 8192 option for luksFormat
+ (units are in 512-bytes sectors; see notes below).
+
+* Cryptsetup now doubles LUKS default key size if XTS mode is used
+ (XTS mode uses two internal keys). This does not apply if key size
+ is explicitly specified on the command line and it does not apply
+ for the plain mode.
+ This fixes a confusion with AES and 256bit key in XTS mode where
+ code used AES128 and not AES256 as often expected.
+
+ Also, the default keyslot encryption algorithm (if cannot be derived
+ from data encryption algorithm) is now available as configure
+ options --with-luks2-keyslot-cipher and --with-luks2-keyslot-keybits.
+ The default is aes-xts-plain64 with 2 * 256-bits key.
+
+* Default cryptographic backend used for LUKS header processing is now
+ OpenSSL. For years, OpenSSL provided better performance for PBKDF.
+
+ NOTE: Cryptsetup/libcryptsetup supports several cryptographic
+ library backends. The fully supported are libgcrypt, OpenSSL and
+ kernel crypto API. FIPS mode extensions are maintained only for
+ libgcrypt and OpenSSL. Nettle and NSS are usable only for some
+ subset of algorithms and cannot provide full backward compatibility.
+ You can always switch to other backends by using a configure switch,
+ for libgcrypt (compatibility for older distributions) use:
+ --with-crypto_backend=gcrypt
+
+* The Python bindings are no longer supported and the code was removed
+ from cryptsetup distribution. Please use the libblockdev project
+ that already covers most of the libcryptsetup functionality
+ including LUKS2.
+
+* Cryptsetup now allows using --offset option also for luksFormat.
+ It means that the specified offset value is used for data offset.
+ LUKS2 header areas are automatically adjusted according to this value.
+ (Note units are in 512-byte sectors due to the previous definition
+ of this option in plain mode.)
+ This option can replace --align-payload with absolute alignment value.
+
+* Cryptsetup now supports new refresh action (that is the alias for
+ "open --refresh").
+ It allows changes of parameters for an active device (like root
+ device mapping), for example, it can enable or disable TRIM support
+ on-the-fly.
+ It is supported for LUKS1, LUKS2, plain and loop-AES devices.
+
+* Integritysetup now supports mode with detached data device through
+ new --data-device option.
+ Since kernel 4.18 there is a possibility to specify external data
+ device for dm-integrity that stores all integrity tags.
+
+* Integritysetup now supports automatic integrity recalculation
+ through new --integrity-recalculate option.
+ Linux kernel since version 4.18 supports automatic background
+ recalculation of integrity tags for dm-integrity.
+
+Other changes and fixes
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix for crypt_wipe call to allocate space if the header is backed
+ by a file. This means that if you use detached header file, it will
+ now have always the full size after luksFormat, even if only
+ a few keyslots are used.
+
+* Fixes to offline cryptsetup-reencrypt to preserve LUKS2 keyslots
+ area sizes after reencryption and fixes for some other issues when
+ creating temporary reencryption headers.
+
+* Added some FIPS mode workarounds. We cannot (yet) use Argon2 in
+ FIPS mode, libcryptsetup now fallbacks to use PBKDF2 in FIPS mode.
+
+* Rejects conversion to LUKS1 if PBKDF2 hash algorithms
+ in keyslots differ.
+
+* The hash setting on command line now applies also to LUKS2 PBKDF2
+ digest. In previous versions, the LUKS2 key digest used PBKDF2-SHA256
+ (except for converted headers).
+
+* Allow LUKS2 keyslots area to increase if data offset allows it.
+ Cryptsetup can fine-tune LUKS2 metadata area sizes through
+ --luks2-metadata-size=BYTES and --luks2-keyslots-size=BYTES.
+ Please DO NOT use these low-level options until you need it for
+ some very specific additional feature.
+ Also, the code now prints these LUKS2 header area sizes in dump
+ command.
+
+* For LUKS2, keyslot can use different encryption that data with
+ new options --keyslot-key-size=BITS and --keyslot-cipher=STRING
+ in all commands that create new LUKS keyslot.
+ Please DO NOT use these low-level options until you need it for
+ some very specific additional feature.
+
+* Code now avoids data flush when reading device status through
+ device-mapper.
+
+* The Nettle crypto backend and the userspace kernel crypto API
+ backend were enhanced to allow more available hash functions
+ (like SHA3 variants).
+
+* Upstream code now does not require libgcrypt-devel
+ for autoconfigure, because OpenSSL is the default.
+ The libgcrypt does not use standard pkgconfig detection and
+ requires specific macro (part of libgcrypt development files)
+ to be always present during autoconfigure.
+ With other crypto backends, like OpenSSL, this makes no sense,
+ so this part of autoconfigure is now optional.
+
+* Cryptsetup now understands new --debug-json option that allows
+ an additional dump of some JSON information. These are no longer
+ present in standard debug output because it could contain some
+ specific LUKS header parameters.
+
+* The luksDump contains the hash algorithm used in Anti-Forensic
+ function.
+
+* All debug messages are now sent through configured log callback
+ functions, so an application can easily use own debug messages
+ handling. In previous versions debug messages were printed directly
+ to standard output.)
+
+Libcryptsetup API additions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These new calls are now exported, for details see libcryptsetup.h:
+
+ * crypt_init_data_device
+ * crypt_get_metadata_device_name
+ functions to init devices with separate metadata and data device
+ before a format function is called.
+
+ * crypt_set_data_offset
+ sets the data offset for LUKS to the specified value
+ in 512-byte sectors.
+ It should replace alignment calculation in LUKS param structures.
+
+ * crypt_get_metadata_size
+ * crypt_set_metadata_size
+ allows one to set/get area sizes in LUKS header
+ (according to specification).
+
+ * crypt_get_default_type
+ get default compiled-in LUKS type (version).
+
+ * crypt_get_pbkdf_type_params
+ allows one to get compiled-in PBKDF parameters.
+
+ * crypt_keyslot_set_encryption
+ * crypt_keyslot_get_encryption
+ allows one to set/get per-keyslot encryption algorithm for LUKS2.
+
+ * crypt_keyslot_get_pbkdf
+ allows one to get PBKDF parameters per-keyslot.
+
+ and these new defines:
+ * CRYPT_LOG_DEBUG_JSON (message type for JSON debug)
+ * CRYPT_DEBUG_JSON (log level for JSON debug)
+ * CRYPT_ACTIVATE_RECALCULATE (dm-integrity recalculate flag)
+ * CRYPT_ACTIVATE_REFRESH (new open with refresh flag)
+
+All existing API calls should remain backward compatible.
+
+Unfinished things & TODO for next releases
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Optional authenticated encryption is still an experimental feature
+ and can have performance problems for high-speed devices and device
+ with larger IO blocks (like RAID).
+
+* Authenticated encryption does not use encryption for a dm-integrity
+ journal. While it does not influence data confidentiality or
+ integrity protection, an attacker can get some more information
+ from data journal or cause that system will corrupt sectors after
+ journal replay. (That corruption will be detected though.)
+
+* The LUKS2 metadata area increase is mainly needed for the new online
+ reencryption as the major feature for the next release.
diff --git a/docs/v2.2.0-ReleaseNotes b/docs/v2.2.0-ReleaseNotes
new file mode 100644
index 0000000..b1fd363
--- /dev/null
+++ b/docs/v2.2.0-ReleaseNotes
@@ -0,0 +1,279 @@
+Cryptsetup 2.2.0 Release Notes
+==============================
+Stable release with new experimental features and bug fixes.
+
+Cryptsetup 2.2 version introduces a new LUKS2 online reencryption
+extension that allows reencryption of mounted LUKS2 devices
+(device in use) in the background.
+
+Online reencryption is a complex feature. Please be sure you
+have a full data backup before using this feature.
+
+Changes since version 2.1.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+LUKS2 online reencryption
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The reencryption is intended to provide a reliable way to change
+volume key or an algorithm change while the encrypted device is still
+in use.
+
+It is based on userspace-only approach (no kernel changes needed)
+that uses the device-mapper subsystem to remap active devices on-the-fly
+dynamically. The device is split into several segments (encrypted by old
+key, new key and so-called hotzone, where reencryption is actively running).
+
+The flexible LUKS2 metadata format is used to store intermediate states
+(segment mappings) and both version of keyslots (old and new keys).
+Also, it provides a binary area (in the unused keyslot area space)
+to provide recovery metadata in the case of unexpected failure during
+reencryption. LUKS2 header is during the reencryption marked with
+"online-reencryption" keyword. After the reencryption is finished,
+this keyword is removed, and the device is backward compatible with all
+older cryptsetup tools (that support LUKS2).
+
+The recovery supports three resilience modes:
+
+ - checksum: default mode, where individual checksums of ciphertext hotzone
+ sectors are stored, so the recovery process can detect which sectors were
+ already reencrypted. It requires that the device sector write is atomic.
+
+ - journal: the hotzone is journaled in the binary area
+ (so the data are written twice)
+
+ - none: performance mode; there is no protection
+ (similar to old offline reencryption)
+
+These resilience modes are not available if reencryption uses data shift.
+
+Note: until we have full documentation (both of the process and metadata),
+please refer to Ondrej's slides (some slight details are no longer relevant)
+https://okozina.fedorapeople.org/online-disk-reencryption-with-luks2-compact.pdf
+
+The offline reencryption tool (cryptsetup-reencrypt) is still supported
+for both LUKS1 and LUKS2 format.
+
+Cryptsetup examples for reencryption
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The reencryption feature is integrated directly into cryptsetup utility
+as the new "reencrypt" action (command).
+
+There are three basic modes - to perform reencryption (change of already
+existing LUKS2 device), to add encryption to plaintext device and to remove
+encryption from a device (decryption).
+
+In all cases, if existing LUKS2 metadata contains information about
+the ongoing reencryption process, following reencrypt command continues
+with the ongoing reencryption process until it is finished.
+
+You can activate a device with ongoing reencryption as the standard LUKS2
+device, but the reencryption process will not continue until the cryptsetup
+reencrypt command is issued.
+
+
+1) Reencryption
+~~~~~~~~~~~~~~~
+This mode is intended to change any attribute of the data encryption
+(change of the volume key, algorithm or sector size).
+Note that authenticated encryption is not yet supported.
+
+You can start the reencryption process by specifying a LUKS2 device or with
+a detached LUKS2 header.
+The code should automatically recognize if the device is in use (and if it
+should use online mode of reencryption).
+
+If you do not specify parameters, only volume key is changed
+(a new random key is generated).
+
+# cryptsetup reencrypt <device> [--header <hdr>]
+
+You can also start reencryption using active mapped device name:
+ # cryptsetup reencrypt --active-name <name>
+
+You can also specify the resilience mode (none, checksum, journal) with
+--resilience=<mode> option, for checksum mode also the hash algorithm with
+--resilience-hash=<alg> (only hash algorithms supported by cryptographic
+backend are available).
+
+The maximal size of reencryption hotzone can be limited by
+--hotzone-size=<size> option and applies to all reencryption modes.
+Note that for checksum and journal mode hotzone size is also limited
+by available space in binary keyslot area.
+
+2) Encryption
+~~~~~~~~~~~~~
+This mode provides a way to encrypt a plaintext device to LUKS2 format.
+This option requires reduction of device size (for LUKS2 header) or new
+detached header.
+
+ # cryptsetup reencrypt <device> --encrypt --reduce-device-size <size>
+
+Or with detached header:
+ # cryptsetup reencrypt <device> --encrypt --header <hdr>
+
+3) Decryption
+~~~~~~~~~~~~~
+This mode provides the removal of existing LUKS2 encryption and replacing
+a device with plaintext content only.
+For now, we support only decryption with a detached header.
+
+ # cryptsetup reencrypt <device> --decrypt --header <hdr>
+
+For all three modes, you can split the process to metadata initialization
+(prepare keyslots and segments but do not run reencryption yet) and the data
+reencryption step by using --init-only option.
+
+Prepares metadata:
+ # cryptsetup reencrypt --init-only <parameters>
+
+Starts the data processing:
+ # cryptsetup reencrypt <device>
+
+Please note, that due to the Linux kernel limitation, the encryption or
+decryption process cannot be run entirely online - there must be at least
+short offline window where operation adds/removes device-mapper crypt (LUKS2) layer.
+This step should also include modification of /etc/crypttab and fstab UUIDs,
+but it is out of the scope of cryptsetup tools.
+
+Limitations
+~~~~~~~~~~~
+Most of these limitations will be (hopefully) fixed in next versions.
+
+* Only one active keyslot is supported (all old keyslots will be removed
+ after reencryption).
+
+* Only block devices are now supported as parameters. As a workaround
+ for images in a file, please explicitly map a loop device over the image
+ and use the loop device as the parameter.
+
+* Devices with authenticated encryption are not supported. (Later it will
+ be limited by the fixed per-sector metadata, per-sector metadata size
+ cannot be changed without a new device format operation.)
+
+* The reencryption uses userspace crypto library, with fallback to
+ the kernel (if available). There can be some specific configurations
+ where the fallback does not provide optimal performance.
+
+* There are no translations of error messages until the final release
+ (some messages can be rephrased as well).
+
+* The repair command is not finished; the recovery of interrupted
+ reencryption is made automatically on the first device activation.
+
+* Reencryption triggers too many udev scans on metadata updates (on closing
+ write enabled file descriptors). This has a negative performance impact on the whole
+ reencryption and generates excessive I/O load on the system.
+
+New libcryptsetup reencryption API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The libcryptsetup contains new API calls that are used to setup and
+run the reencryption.
+
+Note that there can be some changes in API implementation of these functions
+and/or some new function can be introduced in final cryptsetup 2.2 release.
+
+New API symbols (see documentation in libcryptsetup.h)
+* struct crypt_params_reencrypt - reencryption parameters
+
+* crypt_reencrypt_init_by_passphrase
+* crypt_reencrypt_init_by_keyring
+ - function to configure LUKS2 metadata for reencryption;
+ if metadata already exists, it configures the context from this metadata
+
+* crypt_reencrypt
+ - run the reencryption process (processing the data)
+ - the optional callback function can be used to interrupt the reencryption
+ or report the progress.
+
+* crypt_reencrypt_status
+ - function to query LUKS2 metadata about the reencryption state
+
+Other changes and fixes
+~~~~~~~~~~~~~~~~~~~~~~~
+* Add optional global serialization lock for memory hard PBKDF.
+ (The --serialize-memory-hard-pbkdf option in cryptsetup and
+ CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF in activation flag.)
+
+ This is an "ugly" optional workaround for a situation when multiple devices
+ are being activated in parallel (like systemd crypttab activation).
+ The system instead of returning ENOMEM (no memory available) starts
+ out-of-memory (OOM) killer to kill processes randomly.
+
+ Until we find a reliable way how to work with memory-hard function
+ in these situations, cryptsetup provide a way how to serialize memory-hard
+ unlocking among parallel cryptsetup instances to workaround this problem.
+ This flag is intended to be used only in very specific situations,
+ never use it directly :-)
+
+* Abort conversion to LUKS1 with incompatible sector size that is
+ not supported in LUKS1.
+
+* Report error (-ENOENT) if no LUKS keyslots are available. User can now
+ distinguish between a wrong passphrase and no keyslot available.
+
+* Fix a possible segfault in detached header handling (double free).
+
+* Add integritysetup support for bitmap mode introduced in Linux kernel 5.2.
+ Integritysetup now supports --integrity-bitmap-mode option and
+ --bitmap-sector-per-bit and --bitmap-flush-time commandline options.
+
+ In the bitmap operation mode, if a bit in the bitmap is 1, the corresponding
+ region's data and integrity tags are not synchronized - if the machine
+ crashes, the unsynchronized regions will be recalculated.
+ The bitmap mode is faster than the journal mode because we don't have
+ to write the data twice, but it is also less reliable, because if data
+ corruption happens when the machine crashes, it may not be detected.
+ This can be used only for standalone devices, not with dm-crypt.
+
+* The libcryptsetup now keeps all file descriptors to underlying device
+ open during the whole lifetime of crypt device context to avoid excessive
+ scanning in udev (udev run scan on every descriptor close).
+
+* The luksDump command now prints more info for reencryption keyslot
+ (when a device is in-reencryption).
+
+* New --device-size parameter is supported for LUKS2 reencryption.
+ It may be used to encrypt/reencrypt only the initial part of the data
+ device if the user is aware that the rest of the device is empty.
+
+ Note: This change causes API break since the last rc0 release
+ (crypt_params_reencrypt structure contains additional field).
+
+* New --resume-only parameter is supported for LUKS2 reencryption.
+ This flag resumes reencryption process if it exists (not starting
+ new reencryption).
+
+* The repair command now tries LUKS2 reencryption recovery if needed.
+
+* If reencryption device is a file image, an interactive dialog now
+ asks if reencryption should be run safely in offline mode
+ (if autodetection of active devices failed).
+
+* Fix activation through a token where dm-crypt volume key was not
+ set through keyring (but using old device-mapper table parameter mode).
+
+* Online reencryption can now retain all keyslots (if all passphrases
+ are provided). Note that keyslot numbers will change in this case.
+
+* Allow volume key file to be used if no LUKS2 keyslots are present.
+ If all keyslots are removed, LUKS2 has no longer information about
+ the volume key size (there is only key digest present).
+ Please use --key-size option to open the device or add a new keyslot
+ in these cases.
+
+* Print a warning if online reencrypt is called over LUKS1 (not supported).
+
+* Fix TCRYPT KDF failure in FIPS mode.
+ Some crypto backends support plain hash in FIPS mode but not for PBKDF2.
+
+* Remove FIPS mode restriction for crypt_volume_key_get.
+ It is an application responsibility to use this API in the proper context.
+
+* Reduce keyslots area size in luksFormat when the header device is too small.
+ Unless user explicitly asks for keyslots areas size (either via
+ --luks2-keyslots-size or --offset) reduce keyslots size so that it fits
+ in metadata device.
+
+* Make resize action accept --device-size parameter (supports units suffix).
diff --git a/docs/v2.2.1-ReleaseNotes b/docs/v2.2.1-ReleaseNotes
new file mode 100644
index 0000000..34bacc1
--- /dev/null
+++ b/docs/v2.2.1-ReleaseNotes
@@ -0,0 +1,36 @@
+Cryptsetup 2.2.1 Release Notes
+==============================
+Stable bug-fix release.
+
+This version contains a fix for a possible data corruption bug
+on 32-bit platforms.
+All users of cryptsetup 2.1 and 2.2 should upgrade to this version.
+
+Changes since version 2.2.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix possible data length and IV offset overflow on 32bit architectures.
+ Other 64-bit architectures are not affected.
+
+ The flawed helper function prototypes (introduced in version 2.1.0) used
+ size_t type, that is 32-bit integer on 32-bit systems.
+ This patch fixes the problem to properly use 64-bit types.
+
+ If the offset parameter addresses devices larger than 2TB, the value
+ overflows and stores incorrect information in the metadata.
+ For example, integrity device is smaller than expected size if used
+ over large disk on 32-bit architecture.
+
+ This issue is not present with the standard LUKS1/LUKS2 devices without
+ integrity extensions.
+
+* Fix a regression in TrueCrypt/VeraCrypt system partition activation.
+
+* Reinstate missing backing file hint for loop device.
+
+ If the encrypted device is backed by a file (loopback), cryptsetup now
+ shows the path to the backing file in passphrase query (as in 1.x version).
+
+* LUKS2 reencryption block size is now aligned to reported optimal IO size.
+ This change eliminates possible non-aligned device warnings in kernel log
+ during reencryption.
diff --git a/docs/v2.2.2-ReleaseNotes b/docs/v2.2.2-ReleaseNotes
new file mode 100644
index 0000000..9e68641
--- /dev/null
+++ b/docs/v2.2.2-ReleaseNotes
@@ -0,0 +1,56 @@
+Cryptsetup 2.2.2 Release Notes
+==============================
+Stable bug-fix release.
+
+All users of cryptsetup 2.1 and 2.2 should upgrade to this version.
+
+Changes since version 2.2.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Print error message if a keyslot open failed for a different reason
+ than wrong passwords (for example there is not enough memory).
+ Only an exit code was present in this case.
+
+* The progress function switches unit sizes (B/s to GiB/s) according
+ to the actual speed. Also, it properly calculates speed in the case
+ of a resumed reencryption operation.
+
+* The --version now supports short -V short option and better handles
+ common option priorities.
+
+* If cryptsetup wipes signatures during format actions through blkid,
+ it also prints signature device offsets.
+
+* Compilation now properly uses LTLIBINTL gettext setting in Makefiles.
+
+* Device-mapper backend now supports new DM_GET_TARGET_VERSION ioctl
+ (available since Linux kernel 5.4).
+ This should help to detect some kernel/userspace incompatibilities
+ earlier later after a failed device activation.
+
+* Fixes LUKS2 reencryption on systems without kernel keyring.
+
+* Fixes unlocking prompt for partitions mapped through loop devices
+ (to properly show the backing device).
+
+* For LUKS2 decryption, a device is now marked for deferred removal
+ to be automatically deactivated.
+
+* Reencryption now limits hotzone size to be maximal 1 GiB or 1/4
+ system memory (if lower).
+
+* Reencryption now retains activation flags during online reencryption.
+
+* Reencryption now allows LUKS2 device to activate device right after
+ LUKS2 encryption is initialized through optional active device name
+ for cryptsetup reencrypt --encrypt command.
+ This could help with automated encryption during boot.
+
+ NOTE: It means that part of the device is still not encrypted during
+ activation. Use with care!
+
+* Fixes failure in resize and plain format activation if activated device
+ size was not aligned to underlying logical device size.
+
+* Fixes conversion to LUKS2 format with detached header if a detached
+ header size was smaller than the expected aligned LUKS1 header size.
diff --git a/docs/v2.3.0-ReleaseNotes b/docs/v2.3.0-ReleaseNotes
new file mode 100644
index 0000000..a3eb3ec
--- /dev/null
+++ b/docs/v2.3.0-ReleaseNotes
@@ -0,0 +1,209 @@
+Cryptsetup 2.3.0 Release Notes
+==============================
+Stable release with new experimental features and bug fixes.
+
+Cryptsetup 2.3 version introduces support for BitLocker-compatible
+devices (BITLK format). This format is used in Windows systems,
+and in combination with a filesystem driver, cryptsetup now provides
+native read-write access to BitLocker Full Disk Encryption devices.
+
+The BITLK implementation is based on publicly available information
+and it is an independent and opensource implementation that allows
+one to access this proprietary disk encryption.
+
+Changes since version 2.2.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* BITLK (Windows BitLocker compatible) device access
+
+ BITLK userspace implementation is based on the master thesis and code
+ provided by Vojtech Trefny. Also, thanks to other opensource projects
+ like libbde (that provide alternative approach to decode this format)
+ we were able to verify cryptsetup implementation.
+
+ NOTE: Support for the BITLK device is EXPERIMENTAL and will require
+ a lot of testing. If you get some error message (mainly unsupported
+ metadata in the on-disk header), please help us by submitting an issue
+ to cryptsetup project, so we can fix it. Thank you!
+
+ Cryptsetup supports BITLK activation through passphrase or recovery
+ passphrase for existing devices (BitLocker and Bitlocker to Go).
+
+ Activation through TPM, SmartCard, or any other key protector
+ is not supported. And in some situations, mainly for TPM bind to some
+ PCR registers, it could be even impossible on Linux in the future.
+
+ All metadata (key protectors) are handled read-only, cryptsetup cannot
+ create or modify them. Except for old devices (created in old Vista
+ systems), all format variants should be recognized.
+
+ Data devices can be activated read-write (followed by mounting through
+ the proper filesystem driver). To access filesystem on the decrypted device
+ you need properly installed driver (vfat, NTFS or exFAT).
+
+ Foe AES-XTS, activation is supported on all recent Linux kernels.
+
+ For older AES-CBC encryption, Linux Kernel version 5.3 is required
+ (support for special IV variant); for AES-CBC with Elephant diffuser,
+ Linux Kernel 5.6 is required.
+
+ Please note that CBC variants are legacy, and we provide it only
+ for backward compatibility (to be able to access old drives).
+
+ Cryptsetup command now supports the new "bitlk" format and implement dump,
+ open, status, and close actions.
+
+ To activate a BITLK device, use
+
+ # cryptsetup open --type bitlk <device> <name>
+ or with alias
+ # cryptsetup bitlkOpen <device> <name>
+
+ Then with properly installed fs driver (usually NTFS, vfat or exFAT),
+ you can mount the plaintext device /dev/mapper<name> device as a common
+ filesystem.
+
+ To print metadata information about BITLK device, use
+ # crypotsetup bitlkDump <device>
+
+ To print information about the active device, use
+ # cryptsetup status <name>
+
+ Example (activation of disk image):
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ # Recent blkid recognizes BitLocker device,just to verity
+ # blkid bitlocker_xts_ntfs.img
+ bitlocker_xts_ntfs.img: TYPE="BitLocker"
+
+ # Print visible metadata information (on-disk, form the image)
+ # cryptsetup bitlkDump bitlocker_xts_ntfs.img
+ Info for BITLK device bitlocker_xts_ntfs.img.
+ Version: 2
+ GUID: ...
+ Created: Wed Oct 23 17:38:15 2019
+ Description: DESKTOP-xxxxxxx E: 23.10.2019
+ Cipher name: aes
+ Cipher mode: xts-plain64
+ Cipher key: 128 bits
+
+ Keyslots:
+ 0: VMK
+ GUID: ...
+ Protection: VMK protected with passphrase
+ Salt: ...
+ Key data size: 44 [bytes]
+ 1: VMK
+ GUID: ...
+ Protection: VMK protected with recovery passphrase
+ Salt: ...
+ Key data size: 44 [bytes]
+ 2: FVEK
+ Key data size: 44 [bytes]
+
+ # Activation (recovery passphrase works the same as password)
+ # cryptsetup bitlkOpen bitlocker_xts_ntfs.img test -v
+ Enter passphrase for bitlocker_xts_ntfs.img:
+ Command successful.
+
+ # Information about the active device
+ # cryptsetup status test
+ /dev/mapper/test is active.
+ type: BITLK
+ cipher: aes-xts-plain64
+ keysize: 128 bits
+ ...
+
+ # Plaintext device should now contain decrypted NTFS filesystem
+ # blkid /dev/mapper/test
+ /dev/mapper/test: UUID="..." TYPE="ntfs"
+
+ # And can be mounted
+ # mount /dev/mapper/test /mnt/tst
+
+ # Deactivation
+ # umount /mnt/tst
+ # cryptsetup close test
+
+* Veritysetup now supports activation with additional PKCS7 signature
+ of root hash through --root-hash-signature option.
+ The signature uses an in-kernel trusted key to validate the signature
+ of the root hash during activation. This option requires Linux kernel
+ 5.4 with DM_VERITY_VERIFY_ROOTHASH_SIG option.
+
+ Verity devices activated with signature now has a special flag
+ (with signature) active in device status (veritysetup status <name>).
+
+ Usage:
+ # veritysetup open <data_device> name <hash_device> <root_hash> \
+ --root-hash-signature=<roothash_p7_sig_file>
+
+* Integritysetup now calculates hash integrity size according to algorithm
+ instead of requiring an explicit tag size.
+
+ Previously, when integritysetup formats a device with hash or
+ HMAC integrity checksums, it required explicitly tag size entry from
+ a user (or used default value).
+ This led to confusion and unexpected shortened tag sizes.
+
+ Now, libcryptsetup calculates tag size according to real hash output.
+ Tag size can also be specified, then it warns if these values differ.
+
+* Integritysetup now supports fixed padding for dm-integrity devices.
+
+ There was an in-kernel bug that wasted a lot of space when using metadata
+ areas for integrity-protected devices if a larger sector size than
+ 512 bytes was used.
+ This problem affects both stand-alone dm-integrity and also LUKS2 with
+ authenticated encryption and larger sector size.
+
+ The new extension to dm-integrity superblock is needed, so devices
+ with the new optimal padding cannot be activated on older systems.
+
+ Integritysetup/Cryptsetup will use new padding automatically if it
+ detects the proper kernel. To create a compatible device with
+ the old padding, use --integrity-legacy-padding option.
+
+* A lot of fixes to online LUKS2 reecryption.
+
+* Add crypt_resume_by_volume_key() function to libcryptsetup.
+ If a user has a volume key available, the LUKS device can be resumed
+ directly using the provided volume key.
+ No keyslot derivation is needed, only the key digest is checked.
+
+* Implement active device suspend info.
+ Add CRYPT_ACTIVATE_SUSPENDED bit to crypt_get_active_device() flags
+ that informs the caller that device is suspended (luksSuspend).
+
+* Allow --test-passphrase for a detached header.
+ Before this fix, we required a data device specified on the command
+ line even though it was not necessary for the passphrase check.
+
+* Allow --key-file option in legacy offline encryption.
+ The option was ignored for LUKS1 encryption initialization.
+
+* Export memory safe functions.
+ To make developing of some extensions simpler, we now export
+ functions to handle memory with proper wipe on deallocation.
+
+* Fail crypt_keyslot_get_pbkdf for inactive LUKS1 keyslot.
+
+Libcryptsetup API extensions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The libcryptsetup API is backward compatible for existing symbols.
+
+New symbols
+ crypt_set_compatibility
+ crypt_get_compatibility;
+ crypt_resume_by_volume_key;
+ crypt_activate_by_signed_key;
+ crypt_safe_alloc;
+ crypt_safe_realloc;
+ crypt_safe_free;
+ crypt_safe_memzero;
+
+New defines introduced :
+ CRYPT_BITLK "BITLK" - BITLK (BitLocker-compatible mode
+ CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING - dm-integrity legacy padding
+ CRYPT_VERITY_ROOT_HASH_SIGNATURE - dm-verity root hash signature
+ CRYPT_ACTIVATE_SUSPENDED - device suspended info flag
diff --git a/docs/v2.3.1-ReleaseNotes b/docs/v2.3.1-ReleaseNotes
new file mode 100644
index 0000000..1c1d365
--- /dev/null
+++ b/docs/v2.3.1-ReleaseNotes
@@ -0,0 +1,45 @@
+Cryptsetup 2.3.1 Release Notes
+==============================
+Stable bug-fix release.
+
+All users of cryptsetup 2.x should upgrade to this version.
+
+Changes since version 2.3.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Support VeraCrypt 128 bytes passwords.
+ VeraCrypt now allows passwords of maximal length 128 bytes
+ (compared to legacy TrueCrypt where it was limited by 64 bytes).
+
+* Strip extra newline from BitLocker recovery keys
+ There might be a trailing newline added by the text editor when
+ the recovery passphrase was passed using the --key-file option.
+
+* Detect separate libiconv library.
+ It should fix compilation issues on distributions with iconv
+ implemented in a separate library.
+
+* Various fixes and workarounds to build on old Linux distributions.
+
+* Split lines with hexadecimal digest printing for large key-sizes.
+
+* Do not wipe the device with no integrity profile.
+ With --integrity none we performed useless full device wipe.
+
+* Workaround for dm-integrity kernel table bug.
+ Some kernels show an invalid dm-integrity mapping table
+ if superblock contains the "recalculate" bit. This causes
+ integritysetup to not recognize the dm-integrity device.
+ Integritysetup now specifies kernel options such a way that
+ even on unpatched kernels mapping table is correct.
+
+* Print error message if LUKS1 keyslot cannot be processed.
+ If the crypto backend is missing support for hash algorithms
+ used in PBKDF2, the error message was not visible.
+
+* Properly align LUKS2 keyslots area on conversion.
+ If the LUKS1 payload offset (data offset) is not aligned
+ to 4 KiB boundary, new LUKS2 keyslots area in now aligned properly.
+
+* Validate LUKS2 earlier on conversion to not corrupt the device
+ if binary keyslots areas metadata are not correct.
diff --git a/docs/v2.3.2-ReleaseNotes b/docs/v2.3.2-ReleaseNotes
new file mode 100644
index 0000000..b8b8250
--- /dev/null
+++ b/docs/v2.3.2-ReleaseNotes
@@ -0,0 +1,42 @@
+Cryptsetup 2.3.2 Release Notes
+==============================
+Stable bug-fix release.
+
+All users of cryptsetup 2.x should upgrade to this version.
+
+Changes since version 2.3.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Support compilation with json-c library version 0.14.
+
+* Update FAQ document for some LUKS2 specific information.
+
+* Add option to dump content of LUKS2 unbound keyslot:
+ cryptsetup luksDump --unbound -S <slot> <device>
+ or optionally with --master-key-file option.
+
+ The slot number --key-slot (-S) option is mandatory here.
+
+ An unbound keyslot store a key is that is not assigned to data
+ area on disk (LUKS2 allows one to store arbitrary keys).
+
+* Rephrase some error messages and remove redundant end-of-lines.
+
+* Add support for discards (TRIM) for standalone dm-integrity devices.
+ Linux kernel 5.7 adds support for optional discard/TRIM operation
+ over dm-integrity devices.
+
+ It is now supported through --allow-discards integritysetup option.
+ Note you need to add this flag in all activation calls.
+
+ Note that this option cannot be used for LUKS2 authenticated encryption
+ (that uses dm-integrity for storing additional per-sector metadata).
+
+* Fix cryptsetup-reencrypt to work on devices that do not allow
+ direct-io device access.
+
+* Fix a crash in the BitLocker-compatible code error path.
+
+* Fix Veracrypt compatible support for longer (>64 bytes) passphrases.
+ It allows some older images to be correctly opened again.
+ The issue was introduced in version 2.3.1.
diff --git a/docs/v2.3.3-ReleaseNotes b/docs/v2.3.3-ReleaseNotes
new file mode 100644
index 0000000..75471ac
--- /dev/null
+++ b/docs/v2.3.3-ReleaseNotes
@@ -0,0 +1,42 @@
+Cryptsetup 2.3.3 Release Notes
+==============================
+Stable bug-fix release.
+
+All users of cryptsetup 2.x should upgrade to this version.
+
+Changes since version 2.3.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix BitLocker compatible device access that uses native 4kB sectors.
+
+ Devices formatted with storage that natively support 4096-bytes
+ sectors can also use this sector size for encryption units.
+
+* Support large IV count (--iv-large-sectors) cryptsetup option
+ for plain device mapping.
+
+ The large IV count is supported in dm-crypt together with larger
+ sector encryption. It counts the Initialization Vector (IV) in
+ a larger sector size instead of 512-bytes sectors.
+
+ This option does not have any performance or security impact,
+ but it can be used for accessing incompatible existing disk images
+ from other systems.
+
+ Only open action with plain device type and sector size > 512 bytes
+ are supported.
+
+* Fix a memory leak in BitLocker compatible handling.
+
+* Allow EBOIV (Initialization Vector algorithm) use.
+
+ The EBOIV initialization vector is intended to be used internally
+ with BitLocker devices (for CBC mode). It can now be used also
+ outside of the BitLocker compatible code.
+
+* Require both keyslot cipher and key size options.
+
+ If these LUKS2 keyslot parameters were not specified together,
+ cryptsetup silently failed.
+
+* Update to man pages and FAQ.
diff --git a/docs/v2.3.4-ReleaseNotes b/docs/v2.3.4-ReleaseNotes
new file mode 100644
index 0000000..46c5f14
--- /dev/null
+++ b/docs/v2.3.4-ReleaseNotes
@@ -0,0 +1,112 @@
+Cryptsetup 2.3.4 Release Notes
+==============================
+Stable bug-fix release with a security fix (32-bit only).
+
+All users of cryptsetup 2.2.x and later should upgrade to this version.
+
+Changes since version 2.3.3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix a possible out-of-bounds memory write while validating LUKS2 data
+ segments metadata (CVE-2020-14382).
+
+ This problem can be triggered only on 32-bit builds (64-bit systems
+ are not affected).
+
+ LUKS2 format validation code contains a bug in segments validation code
+ where the code does not check for possible overflow on memory allocation.
+
+ Due to the bug, the libcryptsetup can be tricked to expect such allocation
+ was successful. Later it may read data from image crafted by an attacker and
+ actually write such data beyond allocated memory.
+
+ The bug was introduced in cryptsetup 2.2.0. All later releases until 2.3.4
+ are affected.
+
+ If you only backport the fix for this CVE, these master branch git commits
+ should be backported:
+ 52f5cb8cedf22fb3e14c744814ec8af7614146c7
+ 46ee71edcd13e1dad50815ad65c28779aa6f7503
+ 752c9a52798f11d3b765b673ebaa3058eb25316e
+
+ Thanks to Tobias Stoeckmann for discovering this issue.
+
+* Ignore reported optimal IO size if not aligned to minimal page size.
+
+ Some USB enclosures report bogus block device topology (see lsblk -t) that
+ prevents LUKS2 format with 4k sector size (reported values are not correctly
+ aligned). The code now ignores such values and uses the default alignment.
+
+* Added support for new no_read/write_wrokqueue dm-crypt options (kernel 5.9).
+
+ These performance options, introduced in kernel 5.9, configure dm-crypt
+ to bypass read or write workqueues and run encryption synchronously.
+
+ Use --perf-no_read_workqueue or --perf-no_write_workqueue cryptsetup arguments
+ to use these dm-crypt flags.
+
+ These options are available only for low-level dm-crypt performance tuning,
+ use only if you need a change to default dm-crypt behavior.
+
+ For LUKS2, these flags can be persistently stored in metadata with
+ the --persistent option.
+
+* Added support panic_on_corruption option for dm-verity devices (kernel 5.9).
+
+ Veritysetup now supports --panic-on-corruption argument that configures
+ the dm-verity device to panics kernel if a corruption is detected.
+
+ This option is intended for specific configurations, do not use it in
+ standard configurations.
+
+* Support --master-key-file option for online LUKS2 reencryption
+
+ This can be used for reencryption of devices that uses protected key AES cipher
+ on some mainframes crypto accelerators.
+
+* Always return EEXIST error code if a device already exists.
+
+ Some libcryptsetup functions (activate_by*) now return EEXIST error code,
+ so the caller can distinguish that call fails because some parallel process
+ already activated the device.
+ Previously all fails returned EINVAL (invalid value).
+
+* Fix a problem in integritysetup if a hash algorithm has dash in the name.
+
+ If users want to use blake2b/blake2s, the kernel algorithm name includes
+ a dash (like "blake2s-256").
+ These algorithms can now be used for integritysetup devices.
+
+* Fix crypto backend to properly handle ECB mode.
+
+ Even though it should never be used, it should still work for testing :)
+ This fixes a bug introduced in cryptsetup version 2.3.2.
+
+* TrueCrypt/VeraCrypt compatible mode now supports the activation of devices
+ with a larger sector.
+
+ TrueCrypt/VeraCrypt always uses 512-byte sector for encryption, but for devices
+ with a larger native sector, it stores this value in the header.
+
+ This patch allows activation of such devices, basically ignoring
+ the mentioned sector size.
+
+* LUKS2: Do not create excessively large headers.
+
+ When creating a LUKS2 header with a specified --offset larger than
+ the LUKS2 header size, do not create a larger file than needed.
+
+* Fix unspecified sector size for BitLocker compatible mode.
+
+ Some BitLocker devices can contain zeroed sector size in the header.
+ In this case, the 512-byte sector should be used.
+ The bug was introduced in version 2.3.3.
+
+* Fix reading key data size in metadata for BitLocker compatible mode.
+
+ Such devices with an unexpected entry in metadata can now be activated.
+
+ Thanks to all users reporting these problems, BitLocker metadata documentation
+ is not publicly available, and we depend only on these reports.
+
+* Fix typos in documentation.
diff --git a/docs/v2.3.5-ReleaseNotes b/docs/v2.3.5-ReleaseNotes
new file mode 100644
index 0000000..bad4fdf
--- /dev/null
+++ b/docs/v2.3.5-ReleaseNotes
@@ -0,0 +1,181 @@
+Cryptsetup 2.3.5 Release Notes
+==============================
+Stable bug-fix release with minor extensions.
+
+All users of cryptsetup 2.x and later should upgrade to this version.
+
+Changes since version 2.3.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix partial reads of passphrase from an interactive terminal.
+ Some stable kernels (5.3.11) started to return buffer from a terminal
+ in parts of maximal size 64 bytes.
+ This breaks the reading of passphrases longer than 64 characters
+ entered through an interactive terminal. The change is already fixed
+ in later kernel releases, but tools now support such partial read from
+ terminal properly.
+
+* Fix maximal length of password entered through a terminal.
+ Now the maximal interactive passphrase length is exactly
+ 512 characters (not 511).
+
+* integritysetup: support new dm-integrity HMAC recalculation options.
+
+ In older kernels (since version 4.19), an attacker can force
+ an automatic recalculation of integrity tags by modifying
+ the dm-integrity superblock.
+ This is a problem with a keyed algorithms (HMAC), where it expects
+ nobody can trigger such recalculation without the key.
+ (Automatic recalculation will start after the next activation.)
+
+ Note that dm-integrity in standalone mode was *not* supposed
+ to provide cryptographic data integrity protection.
+ Despite that, we try to keep the system secure if keyed algorithms
+ are used.
+ Thank Daniel Glöckner for the original report of this problem.
+
+ Authenticated encryption that provides data integrity protection (in
+ combination with dm-crypt and LUKS2) is not affected by this problem.
+
+ The fix in the kernel for this problem contains two parts.
+
+ Firstly, the dm-integrity kernel module disables integrity
+ recalculation if keyed algorithms (HMAC) are used.
+ This change is included in long-term stable kernels.
+
+ Secondly, since the kernel version 5.11, dm-integrity introduces
+ modified protection where a journal-integrity algorithm guards
+ superblock; also, journal sections are protected. An attacker cannot
+ copy sectors from one journal section to another, and the superblock
+ also contains salt to prevent header replacement from another device.
+
+ If you want to protect data with HMAC, you should always also use HMAC
+ for --journal-integrity. Keys can be independent.
+ If HMAC is used for data but not for the journal, the recalculation
+ option is disabled.
+
+ If you need to use (insecure) backward compatibility implementation,
+ two new integritysetup options are introduced:
+ - Use --integrity-legacy-recalc (instead of --integrity-recalc)
+ to allow recalculation on legacy devices.
+ - Use --integrity-legacy-hmac in format action to force old insecure
+ HMAC format.
+
+ Libcryptsetup API also introduces flags
+ CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC and
+ CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC
+ to set these through crypt_set_compatibility() call.
+
+* integritysetup: display of recalculating sector in dump command.
+
+* veritysetup: fix verity FEC if stored in the same image with hashes.
+
+ Optional FEC (Forward Error Correction) data should cover the whole
+ data area, hashes (Merkle tree), and optionally additional metadata
+ (located after hash area).
+
+ Unfortunately, if FEC data is stored in the same file as hash,
+ the calculation wrongly used the whole file size, thus overlaps with
+ the FEC area itself. This produced unusable and too large FEC data.
+ There is no problem if the FEC image is a separate image.
+
+ The problem is now fixed, introducing FEC blocks calculation as:
+ - If the hash device is in a separate image, metadata covers the
+ whole rest of the image after the hash area. (Unchanged behavior.)
+ - If hash and FEC device is in the image, metadata ends on the FEC
+ area offset.
+
+ Note: there is also a fix for FEC in the dm-verity kernel (on the way
+ to stable kernels) that fixes error correction with larger RS roots.
+
+* veritysetup: run FEC repair check even if root hash fails.
+
+ Note: The userspace FEC verify command reports are only informational
+ for now. Code does not check verity hash after FEC recovery in
+ userspace. The Reed-Solomon decoder can then report the possibility
+ that it fixed data even if parity is too damaged.
+ This will be fixed in the next major release.
+
+* veritysetup: do not process hash image if hash area is empty.
+
+ Sometimes the device is so small that there is only a root hash
+ needed, and the hash area is not used.
+ Also, the size of the hash image is not increased for hash block
+ alignment in this case.
+
+* veritysetup: store verity hash algorithm in superblock in lowercase.
+
+ Otherwise, the kernel could refuse the activation of the device.
+
+* bitlk: fix a crash if the device disappears during BitLocker scan.
+
+* bitlk: show a better error when trying to open an NTFS device.
+
+ Both BitLocker version 1 and NTFS have the same signature.
+ If a user opens an NTFS device without BitLocker, it now correctly
+ informs that it is not a BITLK device.
+
+* bitlk: add support for startup key protected VMKs.
+
+ The startup key can be provided in --key-file option for open command.
+
+* Fix LUKS1 repair code (regression since version 1.7.x).
+
+ We cannot trust possibly broken keyslots metadata in repair, so the
+ code recalculates them instead.
+ This makes the repair code working again when the master boot record
+ signature overwrites the LUKS header.
+
+* Fix luksKeyChange for LUKS2 with assigned tokens.
+
+ The token references are now correctly assigned to the new keyslot
+ number.
+
+* Fix cryptsetup resize using LUKS2 tokens.
+
+ Code needlessly asked for passphrase even though volume key was
+ already unlocked via LUKS2 token.
+
+* Print a visible error if device resize is not supported.
+
+* Add error message when suspending wrong non-LUKS device.
+
+* Fix default XTS mode key size in reencryption.
+
+ The same luksFormat logic (double key size because XTS uses two keys)
+ is applied in the reencryption code.
+
+* Rephrase missing locking directory warning and move it to debug level.
+
+ The system should later provide a safe transition to tempdir
+ configuration, so creating locking directory inside libcryptsetup
+ call is safe.
+
+* Many fixes for the use of cipher_null (empty debug cipher).
+
+ Support for this empty cipher was intended as a debug feature and for
+ measuring performance overhead. Unfortunately, many systems started to
+ use it as an "empty shell" for LUKS (to enable encryption later).
+
+ This use is very dangerous and it creates a false sense of security.
+
+ Anyway, to not break such systems, we try to support these
+ configurations.
+ Using cipher_null in any production system is strongly discouraged!
+
+ Fixes include:
+ - allow LUKS resume for a device with cipher_null.
+ - do not upload key in keyring when data cipher is null.
+ - switch to default cipher when reencrypting cipher_null device.
+ - replace possible bogus cipher_null keyslots before reencryption.
+ - fix broken detection of null cipher in LUKS2.
+ cipher_null is no longer possible to be used in keyslot encryption
+ in LUKS2, it can be used only for data for debugging purposes.
+
+* Fixes for libpasswdqc 2.0.x (optional passphrase quality check).
+
+* Fixes for problems discovered by various tools for code analysis.
+
+ Fixes include a rework of libpopt command line option string leaks.
+
+* Various fixes to man pages.
diff --git a/docs/v2.3.6-ReleaseNotes b/docs/v2.3.6-ReleaseNotes
new file mode 100644
index 0000000..deb975e
--- /dev/null
+++ b/docs/v2.3.6-ReleaseNotes
@@ -0,0 +1,56 @@
+Cryptsetup 2.3.6 Release Notes
+==============================
+Stable bug-fix release with minor extensions.
+
+All users of cryptsetup 2.x and later should upgrade to this version.
+
+Changes since version 2.3.5
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* integritysetup: Fix possible dm-integrity mapping table truncation.
+
+ While integritysetup in standalone mode (no encryption) was not
+ designed to provide keyed (and cryptographically strong) data
+ integrity protection, some options can use such algorithms (HMAC).
+
+ If a key is used, it is directly sent to the kernel dm-integrity as
+ a mapping table option (no key derivation is performed).
+ For HMAC, such a key could be quite long (up to 4096 bytes in
+ integritysetup CLI).
+
+ Unfortunately, due to fixed buffers and not correctly checking string
+ truncation, some parameter combinations could cause truncation
+ of the dm-integrity mapping table.
+ In most cases, the table was rejected by the kernel.
+ The worst possible case was key truncation for HMAC options
+ (internal_hash and journal_mac dm-integrity table options).
+
+ This release fixes possible truncation and also adds more sanity
+ checks to reject truncated options.
+ Also, integritysetup now mentions maximal allowed key size
+ in --help output.
+
+ For old standalone dm-integrity devices where the key length was
+ truncated, you have to modify (shorten) --integrity-key-size
+ resp. --journal-integrity-key-size option now.
+
+ This bug is _not_ present for dm-crypt/LUKS, LUKS2 (including
+ integrity protection), or dm-verity devices; it affects only
+ standalone dm-integrity with HMAC integrity protection.
+
+* cryptsetup: Backup header can be used to activate TCRYPT device.
+ Use --header option to specify the header.
+
+* cryptsetup: Avoid LUKS2 decryption without detached header.
+ This feature will be added later and is currently not supported.
+
+* Additional fixes and workarounds for common warnings produced
+ by some static analysis tools (like gcc-11 analyzer) and additional
+ code hardening.
+
+* Fix standalone libintl detection for compiled tests.
+
+* Add Blake2b and Blake2s hash support for crypto backends.
+ Kernel and gcrypt crypto backend support all variants.
+ OpenSSL supports only Blake2b-512 and Blake2s-256.
+ Crypto backend supports kernel notation e.g. "blake2b-512".
diff --git a/docs/v2.4.0-ReleaseNotes b/docs/v2.4.0-ReleaseNotes
new file mode 100644
index 0000000..2d70e0a
--- /dev/null
+++ b/docs/v2.4.0-ReleaseNotes
@@ -0,0 +1,302 @@
+Cryptsetup 2.4.0 Release Notes
+==============================
+Stable release with new features and bug fixes.
+
+This version introduces support for external libraries
+(plugins) for handling LUKS2 token objects.
+
+Changes since version 2.3.6
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* External LUKS token plugins
+
+ A LUKS2 token is an object that can describe how to get a passphrase
+ to unlock a particular keyslot. The generic metadata format is part
+ of the LUKS2 specification.
+
+ Cryptsetup 2.4 adds the possibility to implement token handlers
+ in external libraries (possibly provided by other projects).
+
+ A token library allows cryptsetup to understand metadata and provide
+ basic operations. Currently external tokens may be used to unlock
+ keyslots for following CLI actions: open (luksOpen),
+ refresh (open --refresh), resize and dump (prints token specific
+ content).
+
+ LUKS2 devices cannot be resumed (luksResume action) via tokens yet.
+ Support for resume and other actions will be added later.
+
+ The library now provides an interface that automatically tries to load
+ an external library for a token object in LUKS2 metadata.
+
+ Token libraries should be installed in the cryptsetup subdirectory
+ (usually /lib*/cryptsetup). This path is configurable through
+ --with-luks2-external-tokens-path configure option.
+
+ The external plugin loading can be compiled entirely out if
+ --disable-external-tokens configure option is used. The external token
+ interface can also be disabled runtime on the command line by
+ --disable-external-tokens cryptsetup switch or by calling
+ crypt_token_external_disable() API function.
+
+ The name of the loaded token library is determined from the JSON LUKS
+ metadata token object type. For example, "ssh" token will load library
+ "libcryptsetup-token-ssh.so".
+
+ External projects can use this interface to handle specific hardware
+ without introducing additional dependencies to libcryptsetup core.
+
+ As of cryptsetup 2.4.0 release systemd project already merged upstream
+ native cryptsetup token handler for its systemd-tpm2 LUKS2 token
+ released originally in systemd-v248. The token can be created using
+ systemd-cryptenroll utility and devices may be manipulated either by
+ systemd-cryptsetup cli or by cryptsetup for actions listed above.
+
+ Other tokens like systemd-fido2 and systemd-pkcs11 are currently
+ in-review.
+
+* Experimental SSH token
+
+ As a demonstration of the external LUKS2 token interface, a new SSH
+ token handler and cryptsetup-ssh utility is now provided and compiled
+ by default.
+
+ Crypsetup SSH token allows using remote keyfile through SSH protocol
+ (it will authenticate through SSH certificates).
+
+ You can disable the build of this token library with
+ --disable-ssh-token configure option.
+
+To configure the token metadata, you need cryptsetup-ssh utility.
+
+Activation of the device is then performed by the cryptsetup utility.
+
+Example (how to activate LUKS2 through remote keyfile):
+
+ - configure existing LUKS2 device with keyslot activated by a keyfile
+ # cryptsetup luksAddKey <device> keyfile --key-slot 2
+
+ - store that keyfile on a remote system accessible through SSH
+
+ - configure SSH to use certificate for authentication
+
+ - add a LUKS2 token with cryptsetup-ssh utility:
+ # cryptsetup-ssh add <device>1 --key-slot 2 \
+ --ssh-server test-vm \
+ --ssh-user test \
+ --ssh-path /home/test/keyfile \
+ --ssh-keypath /home/test/.ssh/test_rsa_key
+
+ - you should see token metadata now with "cryptsetup luksDump ..."
+ ...
+ Tokens:
+ 0: ssh
+ ssh_server: test-vm
+ ssh_user: test
+ ssh_path: /home/test/keyfile
+ ssh_key_path: /home/test/.ssh/test_rsa_key
+ Keyslot: 2
+
+
+ - activation now should be automatic
+ # cryptsetup open <device> test --verbose
+ SSH token initiating ssh session.
+ Key slot 2 unlocked.
+ Command successful.
+
+ - to remove a token, you can use "cryptsetup token remove" command
+ (no plugin library required)
+
+ Please note SSH token is just demonstration of plugin interface API,
+ it is an EXPERIMENTAL feature.
+
+* Add cryptsetup --token-type parameter.
+
+ It restricts token type to the parameter value in case no specific
+ token-id is selected.
+
+* Support for token based activation with PIN.
+
+ If specific token requires PIN to unlock keyslot passphrase and
+ --token-only parameter was used cryptsetup asks for additional
+ token PIN.
+
+* Respect keyslot priority with token-based activation.
+
+* Default LUKS2 PBKDF is now Argon2id
+
+ Cryptsetup LUKS2 was using Argon2 while there were two versions,
+ data-independent (Argon2i) suitable for the KDF use case and
+ Argon2d (data-dependent). Later Argon2id was introduced as a new
+ mandatory algorithm.
+
+ We switched the password-based key derivation algorithms
+ following the latest version of Argon2 RFC draft
+ (https://datatracker.ietf.org/doc/draft-irtf-cfrg-argon2/) to Argon2id
+ (from Argon2i) as it is the mandatory and primary version
+ of the Argon2 algorithm.
+
+ There is no need to modify older containers; the main reason is that
+ RFC makes Argon2id the primary variant, while Argon2i subvariant is
+ only optional.
+ Argon2id provides better protection to side-channel attacks while
+ still providing protection to time-memory tradeoffs.
+
+ We will switch to OpenSSL implementation once it is available.
+ With a crystal ball as a reference, it could happen early in
+ OpenSSL 3.1 release.
+ Watch https://github.com/openssl/openssl/issues/4091.
+
+* Increase minimal memory cost for Argon2 benchmark to 64MiB.
+
+ This patch increases the benchmarking value to 64 MiB (as minimal
+ suggested values in Argon2 RFC). For compatibility reasons, we still
+ allow older limits if set by a parameter.
+
+ NOTE: Argon2 RFC draft defines suggested parameters for disk
+ encryption, but the LUKS2 approach is slightly different. We need to
+ provide platform-independent values. The values in the draft expect
+ 64bit systems (suggesting using 6 GiB of RAM). In comparison, we need
+ to provide compatibility with all 32bit systems, so allocating more
+ than 4GiB memory is not an option for LUKS2.
+
+ The maximal limit in LUKS2 stays for 4 GiB, and by default LUKS2 PBKDF
+ benchmarking sets maximum to 1 GIB, preferring an increase of CPU cost
+ while running benchmark
+
+* Autodetect optimal encryption sector size on LUKS2 format.
+
+ While the support for larger encryption sectors is supported
+ for several releases, it required an additional parameter.
+
+ Code now uses automatic detection of 4096-bytes native sector devices
+ and automatically enables 4096-bytes encryption size for LUKS2.
+
+ If no setor size option is used, sector size is detected
+ automatically by cryptsetup. For libcryptsetup API, autodetection
+ happens once you specify sector_size to 0.
+
+ NOTE: crypt_format() function runs autodetection ONLY if you
+ recompile your application to the new API symbol version.
+ For backward compatibility, older applications ignore this parameter.
+
+* Use VeraCrypt option by default and add --disable-veracrypt option.
+
+ While TrueCrypt is no longer developed and supported since 2014,
+ VeraCrypt devices (a successor of TrueCrypt) are much more used today.
+
+ Default is now to support VeraCrypt format (in addition to TrueCrypt),
+ making the --veracrypt option obsolete (ignored as it is the default).
+
+ If you need to disable VeraCrypt support, use the new option
+ --disable-veracrypt.
+
+ This option increases the time to recognize wrong passwords because
+ some VeraCrypt modes use a high PBKDF2 iteration count, and the code
+ must try all variants. This could be limited by using --hash and
+ --cipher options mentioned below.
+
+* Support --hash and --cipher to limit opening time for TCRYPT type
+
+ If a user knows which particular PBKDF2 hash or cipher is used for
+ TrueCrypt/VeraCrypt container, TCRYPT format now supports --hash and
+ --cipher option.
+
+ Note the value means substring (all cipher chains containing
+ the cipher substring are tried).
+
+ For example, you can use
+ # cryptsetup tcryptDump --hash sha512 <container>
+
+ Note: to speed up the scan, the hash option (used for PBKDF)2 matters.
+ Cipher variants are scanned very quickly.
+
+ Use with care.
+ It can reveal some sensitive attributes of the container!
+
+* Fixed default OpenSSL crypt backend support for OpenSSL3.
+
+ For OpenSSL version 3, we need to load legacy provider for older hash
+ and ciphers. For example, RIPEMD160 and Whirlpool hash algorithms are
+ no longer available by default.
+
+ NOTE: the plain format still uses RIPEMD160 for password hashing by
+ default. Changing the default would cause incompatibilities for many
+ old systems. Nevertheless, such a change will be needed very soon.
+
+* integritysetup: add integrity-recalculate-reset flag.
+
+ The new dm-integrity option in kernel 5.13 can restart recalculation
+ from the beginning of the device.
+ It can be used to change the integrity checksum function.
+
+ New integritysetup --integrity-recalculate-reset option is added to
+ integritysetup, and CRYPT_ACTIVATE_RECALCULATE_RESET flag to API.
+
+* cryptsetup: retains keyslot number in luksChangeKey for LUKS2.
+
+ In LUKS1, any change in keyslot means keyslot number change.
+
+ In LUKS2, we can retain the keyslot number.
+ Now luksKeyChange and crypt_keyslot_change_by_passphrase() API
+ retains keyslot number for LUKS2 by default.
+
+* Fix cryptsetup resize using LUKS2 tokens.
+
+ Fix a bug where cryptsetup needlessly asked for a passphrase even
+ though the volume key was already unlocked via LUKS2 token.
+
+* Add close --deferred and --cancel-deferred options.
+
+ All command-line utilities now understand deferred options for the
+ close command. Deferred close means that the device is removed
+ automagically after the last user closed the device.
+ Cancel deferred means to cancel this operation (so the device remains
+ active even if there a no longer active users).
+
+ CRYPT_DEACTIVATE_DEFERRED and CRYPT_DEACTIVATE_DEFERRED_CANCEL flags
+ are now available for API.
+
+* Rewritten command-line option parsing to avoid libpopt arguments
+ memory leaks.
+
+ Note: some distributions use patched lipopt that still leaks memory
+ inside internal code (see Debian bug 941814).
+
+* Add --test-args option.
+
+ New --test-args option can be used for syntax checking for valid
+ command-line arguments with no actions performed.
+ Note that it cannot detect unknown algorithm names and similar where
+ we need call API functions.
+
+* veritysetup: add --root-hash-file option
+ Allow passing the root hash via a file, rather than verbatim on
+ the command line, for the open, verify, and format actions.
+
+* libcryptsetup C API extensions (see libcryptsetup.h for details)
+
+ - crypt_logf - a printf like log function
+ - crypt_dump_json - dump LUKS2 metadata in JSON format
+ - crypt_header_is_detached - check if context use detached header
+ - crypt_token_max - get maximal tokens number
+ - crypt_token_external_path - get path for plugins (or NULL)
+ - crypt_token_external_disable - disable runtime support for plugins
+ - crypt_activate_by_token_pin - activate by token with additional PIN
+ - crypt_reencrypt_run - fixed API for deprecated crypt_reencrypt
+
+ The token plugin library interface cosists from these versioned
+ exported symbols (for details see header file and SSH token example):
+ cryptsetup_token_open
+ cryptsetup_token_open_pin
+ cryptsetup_token_buffer_free
+ cryptsetup_token_validate
+ cryptsetup_token_dump
+ cryptsetup_token_version
+
+ Since version 2.4 libcryptsetup uses exact symbol versioning
+ Newly introduced functions have CRYPTSETUP_2.4 namespace (the old
+ symbol always used CRYPTSETUP_2.0).
+ There is no change in soname (the library is backward compatible).
+
+ * Many fixes and additions to documentation and man pages.
diff --git a/docs/v2.4.1-ReleaseNotes b/docs/v2.4.1-ReleaseNotes
new file mode 100644
index 0000000..7aac27d
--- /dev/null
+++ b/docs/v2.4.1-ReleaseNotes
@@ -0,0 +1,47 @@
+Cryptsetup 2.4.1 Release Notes
+==============================
+Stable bug-fix release with minor extensions.
+
+All users of cryptsetup 2.4.0 should upgrade to this version.
+
+Changes since version 2.4.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix compilation for libc implementations without dlvsym().
+
+ Some alternative libc implementations (like musl) do not provide
+ versioned symbols dlvsym function. Code now fallbacks to dlsym
+ operation for dynamic LUKS2 token load.
+ It is up to maintainers to ensure that LUKS2 token plugins are
+ compiled for the supported version.
+
+* Fix compilation and tests on systems with non-standard libraries
+ (standalone argp library, external gettext library, BusyBox
+ implementations of standard tools).
+
+* Try to workaround some issues on systems without udev support.
+ NOTE: non-udev systems cannot provide all functionality for kernel
+ device-mapper, and some operations can fail.
+
+* Fixes for OpenSSL3 crypto backend (including FIPS mode).
+ Because cryptsetup still requires some hash functions implemented
+ in OpenSSL3 legacy provider, crypto backend now uses its library
+ context and tries to load both default and legacy OpenSSL3 providers.
+
+ If FIPS mode is detected, no library context is used, and it is up
+ to the OpenSSL system-wide policy to load proper providers.
+
+ NOTE: We still use some deprecated API in the OpenSSL3 backend,
+ and there are some known problems in OpenSSL 3.0.0.
+
+* Print error message when assigning a token to an inactive keyslot.
+
+* Fix offset bug in LUKS2 encryption code if --offset option was used.
+
+* Do not allow LUKS2 decryption for devices with data offset.
+ Such devices cannot be used after decryption.
+
+* Fix LUKS1 cryptsetup repair command for some specific problems.
+ Repair code can now fix wrongly used initialization vector
+ specification in ECB mode (that is insecure anyway!) and repair
+ the upper-case hash specification in the LUKS1 header.
diff --git a/docs/v2.4.2-ReleaseNotes b/docs/v2.4.2-ReleaseNotes
new file mode 100644
index 0000000..3c40011
--- /dev/null
+++ b/docs/v2.4.2-ReleaseNotes
@@ -0,0 +1,37 @@
+Cryptsetup 2.4.2 Release Notes
+==============================
+Stable bug-fix release.
+
+All users of cryptsetup 2.4.1 should upgrade to this version.
+
+Changes since version 2.4.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix possible large memory allocation if LUKS2 header size is invalid.
+ LUKS2 code read the full header to buffer to verify the checksum.
+ The maximal supported header size now limits the memory allocation.
+
+* Fix memory corruption in debug message printing LUKS2 checksum.
+
+* veritysetup: remove link to the UUID library for the static build.
+
+* Remove link to pwquality library for integritysetup and veritysetup.
+ These tools do not read passphrases.
+
+* OpenSSL3 backend: avoid remaining deprecated calls in API.
+ Crypto backend no longer use API deprecated in OpenSSL 3.0
+
+
+* Check if kernel device-mapper create device failed in an early phase.
+ This happens when a concurrent creation of device-mapper devices
+ meets in the very early state.
+
+* Do not set compiler optimization flag for Argon2 KDF if the memory
+ wipe is implemented in libc.
+
+* Do not attempt to unload LUKS2 tokens if external tokens are disabled.
+ This allows building a static binary with --disable-external-tokens.
+
+* LUKS convert: also check sysfs for device activity.
+ If udev symlink is missing, code fallbacks to sysfs scan to prevent
+ data corruption for the active device.
diff --git a/docs/v2.4.3-ReleaseNotes b/docs/v2.4.3-ReleaseNotes
new file mode 100644
index 0000000..d1b6178
--- /dev/null
+++ b/docs/v2.4.3-ReleaseNotes
@@ -0,0 +1,101 @@
+Cryptsetup 2.4.3 Release Notes
+==============================
+Stable security bug-fix release that fixes CVE-2021-4122.
+
+All users of cryptsetup 2.4.x must upgrade to this version.
+
+Changes since version 2.4.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Fix possible attacks against data confidentiality through LUKS2 online
+ reencryption extension crash recovery (CVE-2021-4122).
+
+ An attacker can modify on-disk metadata to simulate decryption in
+ progress with crashed (unfinished) reencryption step and persistently
+ decrypt part of the LUKS device.
+
+ This attack requires repeated physical access to the LUKS device but
+ no knowledge of user passphrases.
+
+ The decryption step is performed after a valid user activates
+ the device with a correct passphrase and modified metadata.
+ There are no visible warnings for the user that such recovery happened
+ (except using the luksDump command). The attack can also be reversed
+ afterward (simulating crashed encryption from a plaintext) with
+ possible modification of revealed plaintext.
+
+ The size of possible decrypted data depends on configured LUKS2 header
+ size (metadata size is configurable for LUKS2).
+ With the default parameters (16 MiB LUKS2 header) and only one
+ allocated keyslot (512 bit key for AES-XTS), simulated decryption with
+ checksum resilience SHA1 (20 bytes checksum for 4096-byte blocks),
+ the maximal decrypted size can be over 3GiB.
+
+ The attack is not applicable to LUKS1 format, but the attacker can
+ update metadata in place to LUKS2 format as an additional step.
+ For such a converted LUKS2 header, the keyslot area is limited to
+ decrypted size (with SHA1 checksums) over 300 MiB.
+
+ The issue is present in all cryptsetup releases since 2.2.0.
+ Versions 1.x, 2.0.x, and 2.1.x are not affected, as these do not
+ contain LUKS2 reencryption extension.
+
+ The problem was caused by reusing a mechanism designed for actual
+ reencryption operation without reassessing the security impact for new
+ encryption and decryption operations. While the reencryption requires
+ calculating and verifying both key digests, no digest was needed to
+ initiate decryption recovery if the destination is plaintext (no
+ encryption key). Also, some metadata (like encryption cipher) is not
+ protected, and an attacker could change it. Note that LUKS2 protects
+ visible metadata only when a random change occurs. It does not protect
+ against intentional modification but such modification must not cause
+ a violation of data confidentiality.
+
+ The fix introduces additional digest protection of reencryption
+ metadata. The digest is calculated from known keys and critical
+ reencryption metadata. Now an attacker cannot create correct metadata
+ digest without knowledge of a passphrase for used keyslots.
+ For more details, see LUKS2 On-Disk Format Specification version 1.1.0.
+
+ The former reencryption operation (without the additional digest) is no
+ longer supported (reencryption with the digest is not backward
+ compatible). You need to finish in-progress reencryption before
+ updating to new packages. The alternative approach is to perform
+ a repair command from the updated package to recalculate reencryption
+ digest and fix metadata.
+ The reencryption repair operation always require a user passphrase.
+
+ WARNING: Devices with older reencryption in progress can be no longer
+ activated without performing the action mentioned above.
+
+ Encryption in progress can be detected by running the luksDump command
+ (output includes reencrypt keyslot with reencryption parameters). Also,
+ during the active reencryption, no keyslot operations are available
+ (change of passphrases, etc.).
+
+ The issue was found by Milan Broz as cryptsetup maintainer.
+
+Other changes
+~~~~~~~~~~~~~
+* Add configure option --disable-luks2-reencryption to completely disable
+ LUKS2 reencryption code.
+
+ When used, the libcryptsetup library can read metadata with
+ reencryption code, but all reencryption API calls and cryptsetup
+ reencrypt commands are disabled.
+
+ Devices with online reencryption in progress cannot be activated.
+ This option can cause some incompatibilities. Please use with care.
+
+* Improve internal metadata validation code for reencryption metadata.
+
+* Add updated documentation for LUKS2 On-Disk Format Specification
+ version 1.1.0 (with reencryption extension description and updated
+ metadata description). See docs/on-disk-format-luks2.pdf or online
+ version in https://gitlab.com/cryptsetup/LUKS2-docs repository.
+
+* Fix support for bitlk (BitLocker compatible) startup key with new
+ metadata entry introduced in Windows 11.
+
+* Fix space restriction for LUKS2 reencryption with data shift.
+ The code required more space than was needed.
diff --git a/docs/v2.5.0-ReleaseNotes b/docs/v2.5.0-ReleaseNotes
new file mode 100644
index 0000000..f5bdeec
--- /dev/null
+++ b/docs/v2.5.0-ReleaseNotes
@@ -0,0 +1,291 @@
+Cryptsetup 2.5.0 Release Notes
+==============================
+Stable release with new features and bug fixes.
+
+Changes since version 2.4.3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Split manual pages into per-action pages and use AsciiDoc format.
+
+ Manual pages are now generated from AsciiDoc format, allowing easy
+ conditional modifications for per-action options.
+
+ Generation of man pages requires the asciidoctor tool installed.
+
+ Pre-generated man pages are also included in the distribution tarball.
+ You can use --disable-asciidoc configure option to skip man page
+ generation completely. In this case, pre-generated man pages will be
+ used for installation.
+
+ For cryptsetup, there is main man page (cryptsetup.8) that references
+ separate man pages for each command (for example, cryptsetup-open.8).
+ You can open such a man page by simply running "man cryptsetup open".
+ Also, man pages for action aliases are available (cryptsetup-luksOpen.8
+ is an alias for cryptsetup-open.8, etc.)
+
+LUKS volume reencryption changes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Remove cryptsetup-reencrypt tool from the project and move reencryption
+ to already existing "cryptsetup reencrypt" command.
+
+ Cryptsetup reencrypt now handles both LUKS1 and LUKS2 reencryption,
+ encryption, and decryption.
+
+ If you need to emulate the old cryptsetup-reencrypt binary, use simple
+ wrappers script running "exec cryptsetup reencrypt $@".
+
+ All command line options should be compatible. An exception is the
+ reencryption of LUKS2 volumes with old LUKS1 reencryption code that was
+ replaced by native and more resilient LUKS2 reencryption.
+
+* LUKS2: implement --decryption option that allows LUKS removal. The
+ operation can run online or offline and supports the data shift option.
+
+ During the initialization, the LUKS2 header is exported to a file.
+ The first data segment is moved to the head of the data device in place
+ of the original header.
+
+ The feature internally introduces several new resilience modes
+ (combination of existing modes datashift and "checksum" or "journal").
+ Datashift resilience mode is applied for data moved towards the first
+ segment, and the first segment is then decrypted in place.
+
+ This decryption mode is not backward compatible with prior LUKS2
+ reencryption. Interrupted operations in progress cannot be resumed
+ using older cryptsetup releases.
+
+* Reencryption metadata options that are not compatible with recent code
+ (features implemented in more recent releases) are now only read, but
+ code will not activate or modify such metadata.
+ Reencryption metadata contains a version that is validated when
+ reencryption is resumed.
+ For more info, see the updated LUKS2 on-disk format specification.
+
+ Safe operation of reencryption is to always finish the operation with
+ only one version of the tools.
+
+* Fix decryption operation with --active-name option and restrict
+ it to be used only with LUKS2.
+
+* Do not refresh reencryption digest when not needed.
+ This should speed up the reencryption resume process.
+
+* Store proper resilience data in LUKS2 reencrypt initialization.
+ Resuming reencryption now does not require specification of resilience
+ type parameters if these are the same as during initialization.
+
+* Properly wipe the unused area after reencryption with datashift in
+ the forward direction.
+
+* Check datashift value against larger sector size.
+ For example, it could cause an issue if misaligned 4K sector appears
+ during decryption.
+
+* Do not allow sector size increase reencryption in offline mode.
+ The eventual logical block size increase on the dm-crypt device above
+ may lead to an unusable filesystem. Do not allow offline reencryption
+ when sector size increase is requested.
+
+ You can use --force-offline-reencrypt option to override this check
+ (and potentially destroy the data).
+
+* Do not allow dangerous sector size change during reencryption.
+ By changing the encryption sector size during reencryption, a user
+ may increase the effective logical block size for the dm-crypt active
+ device.
+
+ Do not allow encryption sector size to be increased over the value
+ provided by fs superblock in BLOCK_SIZE property.
+
+* Ask the user for confirmation before resuming reencryption.
+ The prompt is not shown in batch mode or when the user explicitly asks
+ for a reencryption resume via --resume-only.
+
+* Do not resume reencryption with conflicting parameters.
+ For example, if the operation was initialized as --encrypt, do not
+ allow resume with opposing parameter --decrypt and vice versa.
+ Also, the code now checks for conflicting resilience parameters
+ (datashift cannot be changed after initialization).
+
+* Add --force-offline-reencrypt option.
+ It can be used to enforce offline reencryption in batch mode when
+ the device is a regular file; therefore, cryptsetup cannot detect
+ properly active devices using it.
+ Also, it may be useful to override the active device auto-detection
+ for specific storage configurations (dangerous!).
+
+* Do not allow nested encryption in LUKS reencrypt.
+ Avoid accidental nested encryption via cryptsetup reencrypt --encrypt.
+
+* Fix --test-passphrase when the device is in reencryption.
+
+* Do not upload keys in keyring during offline reencryption.
+ Reencryption runs in userspace, so the kernel does not need the key.
+
+* Support all options allowed with luksFormat with encrypt action.
+
+* Add prompt if LUKS2 decryption is run with a detached header.
+
+* Add warning for reencryption of file image and mention
+ the possible use of --force-offline-reencrypt option.
+
+Other changes
+~~~~~~~~~~~~~
+
+* Add resize action to integritysetup.
+ This allows resizing of standalone integrity devices.
+
+* Support --device-size option (that allows unit specification) for plain
+ devices (existing --size option requires 512-byte sectors units).
+
+* Fix detection of encryption sector size if a detached header is used.
+
+* Remove obsolete dracut plugin reencryption example.
+
+* Fix possible keyslot area size overflow during conversion to LUKS2.
+ If keyslots are not sorted according to binary area offset, the area
+ size calculation was wrong and could overflow.
+
+* Hardening and fixes to LUKS2 validation functions:
+
+ * Log a visible error if convert fails due to validation check.
+
+ * Check for interval (keyslot and segment area) overflow.
+
+ * Check cipher availability before LUKS conversion to LUKS2.
+ Some historic incompatibilities are ignored for LUKS1 but do not
+ work for LUKS2.
+
+ * Add empty string check to LUKS2 metadata JSON validation.
+ Most of the LUKS2 fields cannot be empty.
+
+ * Fix JSON objects validation to check JSON object type properly.
+
+* TCRYPT: Properly apply retry count and continue if some PBKDF variant
+ is unavailable.
+
+* BITLK: Add a warning when activating a device with the wrong size
+ stored in metadata.
+
+* BITLK: Add BitLocker volume size to dump command.
+
+* BITLK: Fix possible UTF16 buffer overflow in volume key dump.
+
+* BITLK: Skip question if the batch mode is set for volume key dump.
+
+* BITLK: Check dm-zero availability in the kernel.
+ Bitlocker compatible mode uses dm-zero to mask metadata area.
+ The device cannot be activated if dm-zero is not available.
+
+* Fix error message for LUKS2-only cryptsetup commands to explicitly
+ state LUKS2 version is required.
+
+* Fix error message for incompatible dm-integrity metadata.
+ If the integritysetup tool is too old, kernel dm-integrity may use
+ a more recent version of dm-integrity metadata.
+
+* Properly deactivate the integrity device even if the LUKS2 header
+ is no longer available.
+ If LUKS2 is used with integrity protection, there is always
+ a dm-integrity device underneath that must be deactivated.
+
+* Allow use of --header option for cryptsetup close.
+ This can be used to check that the activated device has the same UUID.
+
+* Fix activation of LUKS2 device with integrity and detached header.
+ The kernel-parsed dm-integrity superblock is always located on the
+ data device, the incorrectly used detached header device here.
+
+* Add ZEROOUT IOCTL support for crypt_wipe API call.
+ For block devices, we can use optimized in-kernel BLKZEROOUT ioctl.
+
+* VERITY: set loopback sector size according to dm-verity block sizes.
+ Verity block size has the same limits, so we can optimize the loop
+ device to increase performance.
+
+* Other Documentation and man page improvements:
+
+ * Update LUKS2 on-disk format description.
+
+ * Add per-keyslot LUKS2 options to the man page.
+ Some options were missing for LUKS2 luksAddKey and luksChangeKey.
+
+ * Fix cryptsetup manpage to use PBKDF consistently.
+
+ * Add compile info to README. This information was lost when we removed
+ the default automake INSTALL file.
+
+ * Use volume key consistently in FAQ and man pages.
+
+ * Use markdown version of FAQ directly for installation.
+
+ * Clarify graceful reencryption interruption.
+ Currently, it can be interrupted by both SIGINT and SIGTERM signals.
+
+ * Add new mailing list info.
+
+ * Mention non-cryptographic xxhash64 hash for integrity protection.
+
+* veritysetup: dump device sizes.
+ Calculating device sizes for verity devices is a little bit tricky.
+ Data, hash, and FEC can share devices or be separate devices.
+ Now dump command prints used device sizes, but it requires that
+ the user specifies all values that are not stored in superblock
+ (like FEC device and FEC roots).
+
+* Fix check for argp_usage in configure if argp-standalone lib is used.
+
+* Add constant time memcmp and hexa print implementation and use it for
+ cryptographic keys handling.
+
+* Display progress when wiping the end of the resized device.
+
+* LUKS2 token: prefer token PIN query before passphrase in some cases.
+ When a user provides --token-type or specific --token-id, a token PIN
+ query is preferred to a passphrase query.
+
+* LUKS2 token: allow tokens to be replaced with --token-replace option
+ for cryptsetup token command.
+
+* LUKS2 token: do not continue operation when interrupted in PIN prompt.
+
+* Add --progress-json parameter to utilities.
+ Progress data can now be printed out in JSON format suitable for
+ machine processing.
+
+* Embedded Argon2 PBKDF: optimize and simplify thread exit.
+
+* Avoid using SHA1 in tests and fix new enforcements introduced in FIPS
+ provider for OpenSSL3 (like minimal parameters for PBKDF2).
+
+* Use custom UTF conversion and avoid linking to iconv as a dependency.
+
+* Reimplement BASE64 with simplified code instead of coreutils version.
+
+* Fix regression when warning messages were not displayed
+ if some kernel feature is not supported (2.4.2).
+
+* Add support for --key-slot option in luksResume action.
+
+Libcryptsetup API extensions and changes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Properly define uint32_t constants in API.
+ This is not a real change, but it avoids strict compiler warnings.
+
+* crypt_resume_by_token_pin() - Resume crypt device using LUKS2 token.
+
+* crypt_get_label() - Get the label of the LUKS2 device.
+
+* crypt_get_subsystem() - Get the subsystem label of the LUKS2 device.
+
+* Make CRYPT_WIPE_ENCRYPTED_ZERO crypt_wipe() option obsolete.
+ It was never implemented (the idea was to speed up wipe), but with
+ the recent RNG performance changes, it makes no longer sense.
+
+* Add struct crypt_params_reencrypt changes related to decryption.
+
+* Improve crypt_reencrypt_status() return values.
+ Empty or any non-LUKS types now returns CRYPT_REENCRYPT_INVALID status.
+ For LUKS1 devices, it returns CRYPT_REENCRYPT_NONE.
diff --git a/docs/v2.6.0-ReleaseNotes b/docs/v2.6.0-ReleaseNotes
new file mode 100644
index 0000000..6303945
--- /dev/null
+++ b/docs/v2.6.0-ReleaseNotes
@@ -0,0 +1,236 @@
+Cryptsetup 2.6.0 Release Notes
+==============================
+Stable release with new features and bug fixes.
+
+Changes since version 2.5.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Introduce support for handling macOS FileVault2 devices (FVAULT2).
+
+ Cryptsetup now supports the mapping of FileVault2 full-disk encryption
+ by Apple for the macOS operating system using a native Linux kernel.
+ You can open an existing USB FileVault portable device and (with
+ the hfsplus filesystem driver) access the native data read/write.
+
+ Cryptsetup supports only (legacy) FileVault2 based on Core Storage
+ and HFS+ filesystem (introduced in MacOS X 10.7 Lion).
+ It does NOT support the new version of FileVault based on the APFS
+ filesystem used in recent macOS versions.
+
+ Header formatting and changes are not supported; cryptsetup never
+ changes the metadata on the device.
+
+ FVAULT2 extension requires kernel userspace crypto API and kernel
+ driver for HFS+ (hfsplus) filesystem (available on most systems today).
+
+ Example of using FileVault2 formatted USB device:
+
+ A typical encrypted device contains three partitions; the FileVault
+ encrypted partition is here sda2:
+
+ $ lsblk -o NAME,FSTYPE,LABEL /dev/sda
+ NAME FSTYPE LABEL
+ sda
+ |-sda1 vfat EFI
+ |-sda2
+ `-sda3 hfsplus Boot OS X
+
+ Note: blkid does not recognize FileVault2 format yet.
+
+ To dump metadata information about the device, you can use
+ the fvault2Dump command:
+
+ $ cryptsetup fvault2Dump /dev/sda2
+ Header information for FVAULT2 device /dev/sda2.
+ Physical volume UUID: 6f353c05-daae-4e76-a0ee-6a9569a22d81
+ Family UUID: f82cceb0-a788-4815-945a-53d57fcd55a8
+ Logical volume offset: 67108864 [bytes]
+ Logical volume size: 3288334336 [bytes]
+ Cipher: aes
+ Cipher mode: xts-plain64
+ PBKDF2 iterations: 97962
+ PBKDF2 salt: 173a4ec7447662ec79ca7a47df6c2a01
+
+ To activate the device, use open --type fvault2 option:
+
+ $ cryptsetup open --type fvault2 /dev/sda2 test
+ Enter passphrase for /dev/sda2: ...
+
+ And check the status of the active device:
+
+ $ cryptsetup status test
+ /dev/mapper/test is active.
+ type: FVAULT2
+ cipher: aes-xts-plain64
+ keysize: 256 bits
+ key location: dm-crypt
+ device: /dev/sda2
+ sector size: 512
+ offset: 131072 sectors
+ size: 6422528 sectors
+ mode: read/write
+
+ Now, if the kernel contains hfsplus filesystem driver, you can mount
+ decrypted content:
+
+ $ mount /dev/mapper/test /mnt/test
+
+ For more info about implementation, please refer to the master thesis
+ by Pavel Tobias, which was the source for this extension.
+ https://is.muni.cz/th/p0aok/?lang=en
+
+* libcryptsetup: no longer use global memory locking through mlockall()
+
+ For many years, libcryptsetup locked all memory (including dependent
+ library address space) to prevent swapping sensitive content outside
+ of RAM.
+
+ This strategy no longer works as the locking of basic libraries exceeds
+ the memory locking limit if running as a non-root user.
+
+ Libcryptsetup now locks only memory ranges containing sensitive
+ material (keys) through crypt_safe_alloc() calls.
+
+ This change solves many reported mysterious problems of unexpected
+ failures. If the initial lock was still under the limit and succeeded,
+ some following memory allocation could fail later as it exceeded
+ the locking limit. If the initial locking fails, memory locking
+ was quietly ignored completely.
+
+ The whole crypt_memory_lock() API call is deprecated; it no longer
+ calls memlockall().
+
+* libcryptsetup: process priority is increased only for key derivation
+ (PBKDF) calls.
+
+ Increasing priority was tight to memory locking and works only if
+ running under superuser.
+ Only PBKDF calls and benchmarking now increase the process priority.
+
+* Add new LUKS keyslot context handling functions and API.
+
+ In practice, the luksAddKey action does two operations.
+ It unlocks the existing device volume key and stores the unlocked
+ volume key in a new keyslot.
+ Previously the options were limited to key files and passphrases.
+
+ Newly available methods (keyslot contexts) are passphrase, keyfile,
+ key (binary representation), and LUKS2 token.
+
+ To unlock a keyslot user may:
+ - provide existing passphrase via interactive prompt (default method)
+ - use --key-file option to provide a file with a valid passphrase
+ - provide volume key directly via --volume-key-file
+ - unlock keyslot via all available LUKS2 tokens by --token-only
+ - unlock keyslot via specific token with --token-id
+ - unlock keyslot via specific token type by --token-type
+
+ To provide the passphrase for a new keyslot, a user may:
+ - provide existing passphrase via interactive prompt (default method)
+ - use --new-keyfile to read the passphrase from the file
+ - use --new-token-id to select LUKS2 token to get passphrase
+ for new keyslot. The new keyslot is assigned to the selected token
+ id if the operation is successful.
+
+* The volume key may now be extracted using a passphrase, keyfile, or
+ token. For LUKS devices, it also returns the volume key after
+ a successful crypt_format call.
+
+* Fix --disable-luks2-reencryption configuration option.
+
+* cryptsetup: Print a better error message and warning if the format
+ produces an image without space available for data.
+
+ Activation now fails early with a more descriptive message.
+
+* Print error if anti-forensic LUKS2 hash setting is not available.
+ If the specified hash was not available, activation quietly failed.
+
+* Fix internal crypt segment compare routine if the user
+ specified cipher in kernel format (capi: prefix).
+
+* cryptsetup: Add token unassign action.
+
+ This action allows removing token binding on specific keyslot.
+
+* veritysetup: add support for --use-tasklets option.
+
+ This option sets try_verify_in_tasklet kernel dm-verity option
+ (available since Linux kernel 6.0) to allow some performance
+ improvement on specific systems.
+
+* Provide pkgconfig Require.private settings.
+
+ While we do not completely provide static build on udev systems,
+ it helps produce statically linked binaries in certain situations.
+
+* Always update automake library files if autogen.sh is run.
+
+ For several releases, we distributed older automake scripts by mistake.
+
+* reencryption: Fix user defined moved segment size in LUKS2 decryption.
+
+ The --hotzone-size argument was ignored in cases where the actual data
+ size was less than the original LUKS2 data offset.
+
+* Delegate FIPS mode detection to configured crypto backend.
+ System FIPS mode check no longer depends on /etc/system-fips file.
+
+* tests: externally provided systemd plugin is now optionally compiled
+ from systemd git and tested with cryptsetup
+
+* tests: initial integration to OSS-fuzz project with basic crypt_load()
+ test for LUKS2 and JSON mutated fuzzing.
+
+ For more info, see README in tests/fuzz directory.
+
+* Update documentation, including FAQ and man pages.
+
+Libcryptsetup API extensions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The libcryptsetup API is backward compatible with existing symbols.
+
+New symbols:
+ crypt_keyslot_context_init_by_passphrase
+ crypt_keyslot_context_init_by_keyfile
+ crypt_keyslot_context_init_by_token
+ crypt_keyslot_context_init_by_volume_key
+ crypt_keyslot_context_get_error
+ crypt_keyslot_context_set_pin
+ crypt_keyslot_context_get_type
+ crypt_keyslot_context_free
+ crypt_keyslot_add_by_keyslot_context
+ crypt_volume_key_get_by_keyslot_context
+
+New defines:
+ CRYPT_FVAULT2 "FVAULT2" (FileVault2 compatible mode)
+
+Keyslot context types:
+ CRYPT_KC_TYPE_PASSPHRASE
+ CRYPT_KC_TYPE_KEYFILE
+ CRYPT_KC_TYPE_TOKEN
+ CRYPT_KC_TYPE_KEY
+
+ CRYPT_ACTIVATE_TASKLETS (dm-verity: use tasklets activation flag)
+
+WARNING!
+~~~~~~~~
+The next version of cryptsetup will change the encryption mode and key
+derivation option for the PLAIN format.
+
+This change will cause backward incompatibility.
+For this reason, the user will have to specify the exact parameters
+for cipher, key size, and key derivation parameters for plain format.
+
+The default encryption mode will be AES-XTS with 512bit key (AES-256).
+The CBC mode is no longer considered the best default, as it allows easy
+bit-flipped ciphertext modification attacks and performance problems.
+
+For the passphrase hashing in plain mode, the encryption key is directly
+derived through iterative hashing from a user-provided passphrase
+(except a keyfile that is not hashed).
+
+The default hash is RIPEMD160, which is no longer the best default
+option. The exact change will be yet discussed but should include
+the possibility of using a password-based key derivation function
+instead of iterative hashing.
diff --git a/docs/v2.6.1-ReleaseNotes b/docs/v2.6.1-ReleaseNotes
new file mode 100644
index 0000000..82012b9
--- /dev/null
+++ b/docs/v2.6.1-ReleaseNotes
@@ -0,0 +1,50 @@
+Cryptsetup 2.6.1 Release Notes
+==============================
+Stable bug-fix release with minor extensions.
+
+All users of cryptsetup 2.6.0 should upgrade to this version.
+
+Changes since version 2.6.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* bitlk: Fixes for BitLocker-compatible on-disk metadata parser
+ (found by new cryptsetup OSS-Fuzz fuzzers).
+ - Fix a possible memory leak if the metadata contains more than
+ one description field.
+ - Harden parsing of metadata entries for key and description entries.
+ - Fix broken metadata parsing that can cause a crash or out of memory.
+
+* Fix possible iteration overflow in OpenSSL2 PBKDF2 crypto backend.
+ OpenSSL2 uses a signed integer for PBKDF2 iteration count.
+ As cryptsetup uses an unsigned value, this can lead to overflow and
+ a decrease in the actual iteration count.
+ This situation can happen only if the user specifies
+ --pbkdf-force-iterations option.
+ OpenSSL3 (and other supported crypto backends) are not affected.
+
+* Fix compilation for new ISO C standards (gcc with -std=c11 and higher).
+
+* fvault2: Fix compilation with very old uuid.h.
+
+* verity: Fix possible hash offset setting overflow.
+
+* bitlk: Fix use of startup BEK key on big-endian platforms.
+
+* Fix compilation with latest musl library.
+ Recent musl no longer implements lseek64() in some configurations.
+ Use lseek() as 64-bit offset is mandatory for cryptsetup.
+
+* Do not initiate encryption (reencryption command) when the header and
+ data devices are the same.
+ If data device reduction is not requsted, this leads to data corruption
+ since LUKS metadata was written over the data device.
+
+* Fix possible memory leak if crypt_load() fails.
+
+* Always use passphrases with a minimal 8 chars length for benchmarking.
+ Some enterprise distributions decided to set an unconditional check
+ for PBKDF2 password length when running in FIPS mode.
+ This questionable change led to unexpected failures during LUKS format
+ and keyslot operations, where short passwords were used for
+ benchmarking PBKDF2 speed.
+ PBKDF2 benchmark calculations should not be affected by this change.
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
new file mode 100644
index 0000000..2e60a90
--- /dev/null
+++ b/lib/Makemodule.am
@@ -0,0 +1,111 @@
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA += lib/libcryptsetup.pc
+
+lib_LTLIBRARIES += libcryptsetup.la
+
+noinst_LTLIBRARIES += libutils_io.la
+
+include_HEADERS += lib/libcryptsetup.h
+
+EXTRA_DIST += lib/libcryptsetup.pc.in lib/libcryptsetup.sym
+
+libutils_io_la_CFLAGS = $(AM_CFLAGS)
+
+libutils_io_la_SOURCES = \
+ lib/utils_io.c \
+ lib/utils_io.h
+
+libcryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS)
+
+libcryptsetup_la_DEPENDENCIES = libutils_io.la libcrypto_backend.la lib/libcryptsetup.sym
+
+libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
+ -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
+ -version-info @LIBCRYPTSETUP_VERSION_INFO@
+
+libcryptsetup_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@
+
+libcryptsetup_la_LIBADD = \
+ @UUID_LIBS@ \
+ @DEVMAPPER_LIBS@ \
+ @CRYPTO_LIBS@ \
+ @LIBARGON2_LIBS@ \
+ @JSON_C_LIBS@ \
+ @BLKID_LIBS@ \
+ @DL_LIBS@ \
+ $(LTLIBINTL) \
+ libcrypto_backend.la \
+ libutils_io.la
+
+libcryptsetup_la_SOURCES = \
+ lib/setup.c \
+ lib/internal.h \
+ lib/bitops.h \
+ lib/nls.h \
+ lib/libcryptsetup.h \
+ lib/libcryptsetup_macros.h \
+ lib/libcryptsetup_symver.h \
+ lib/utils.c \
+ lib/utils_benchmark.c \
+ lib/utils_crypt.c \
+ lib/utils_crypt.h \
+ lib/utils_loop.c \
+ lib/utils_loop.h \
+ lib/utils_devpath.c \
+ lib/utils_wipe.c \
+ lib/utils_device.c \
+ lib/utils_keyring.c \
+ lib/utils_keyring.h \
+ lib/utils_device_locking.c \
+ lib/utils_device_locking.h \
+ lib/utils_pbkdf.c \
+ lib/utils_safe_memory.c \
+ lib/utils_storage_wrappers.c \
+ lib/utils_storage_wrappers.h \
+ lib/libdevmapper.c \
+ lib/utils_dm.h \
+ lib/volumekey.c \
+ lib/random.c \
+ lib/crypt_plain.c \
+ lib/integrity/integrity.h \
+ lib/integrity/integrity.c \
+ lib/loopaes/loopaes.h \
+ lib/loopaes/loopaes.c \
+ lib/tcrypt/tcrypt.h \
+ lib/tcrypt/tcrypt.c \
+ lib/keyslot_context.h \
+ lib/keyslot_context.c \
+ lib/luks1/af.h \
+ lib/luks1/af.c \
+ lib/luks1/keyencryption.c \
+ lib/luks1/keymanage.c \
+ lib/luks1/luks.h \
+ lib/verity/verity_hash.c \
+ lib/verity/verity_fec.c \
+ lib/verity/verity.c \
+ lib/verity/verity.h \
+ lib/verity/rs_encode_char.c \
+ lib/verity/rs_decode_char.c \
+ lib/verity/rs.h \
+ lib/luks2/luks2_disk_metadata.c \
+ lib/luks2/luks2_json_format.c \
+ lib/luks2/luks2_json_metadata.c \
+ lib/luks2/luks2_luks1_convert.c \
+ lib/luks2/luks2_digest.c \
+ lib/luks2/luks2_digest_pbkdf2.c \
+ lib/luks2/luks2_keyslot.c \
+ lib/luks2/luks2_keyslot_luks2.c \
+ lib/luks2/luks2_keyslot_reenc.c \
+ lib/luks2/luks2_reencrypt.c \
+ lib/luks2/luks2_reencrypt_digest.c \
+ lib/luks2/luks2_segment.c \
+ lib/luks2/luks2_token_keyring.c \
+ lib/luks2/luks2_token.c \
+ lib/luks2/luks2_internal.h \
+ lib/luks2/luks2.h \
+ lib/utils_blkid.c \
+ lib/utils_blkid.h \
+ lib/bitlk/bitlk.h \
+ lib/bitlk/bitlk.c \
+ lib/fvault2/fvault2.h \
+ lib/fvault2/fvault2.c
diff --git a/lib/bitlk/bitlk.c b/lib/bitlk/bitlk.c
new file mode 100644
index 0000000..de7bcea
--- /dev/null
+++ b/lib/bitlk/bitlk.c
@@ -0,0 +1,1460 @@
+/*
+ * BITLK (BitLocker-compatible) volume handling
+ *
+ * Copyright (C) 2019-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2019-2023 Milan Broz
+ * Copyright (C) 2019-2023 Vojtech Trefny
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <uuid/uuid.h>
+#include <time.h>
+#include <limits.h>
+
+#include "bitlk.h"
+#include "internal.h"
+
+#define BITLK_BOOTCODE_V1 "\xeb\x52\x90"
+#define BITLK_BOOTCODE_V2 "\xeb\x58\x90"
+#define BITLK_SIGNATURE "-FVE-FS-"
+#define BITLK_SIGNATURE_TOGO "MSWIN4.1"
+#define BITLK_HEADER_METADATA_OFFSET 160
+#define BITLK_HEADER_METADATA_OFFSET_TOGO 424
+
+/* FVE metadata header is split into two parts */
+#define BITLK_FVE_METADATA_BLOCK_HEADER_LEN 64
+#define BITLK_FVE_METADATA_HEADER_LEN 48
+#define BITLK_FVE_METADATA_HEADERS_LEN BITLK_FVE_METADATA_BLOCK_HEADER_LEN + BITLK_FVE_METADATA_HEADER_LEN
+
+/* total size of the FVE area (64 KiB) */
+#define BITLK_FVE_METADATA_SIZE 64 * 1024
+
+#define BITLK_ENTRY_HEADER_LEN 8
+#define BITLK_VMK_HEADER_LEN 28
+
+#define BITLK_OPEN_KEY_METADATA_LEN 12
+
+#define BITLK_RECOVERY_KEY_LEN 55
+#define BITLK_RECOVERY_PARTS 8
+#define BITLK_RECOVERY_PART_LEN 6
+
+#define BITLK_BEK_FILE_HEADER_LEN 48
+#define BITLK_STARTUP_KEY_HEADER_LEN 24
+
+#define BITLK_KDF_HASH "sha256"
+#define BITLK_KDF_ITERATION_COUNT 0x100000
+
+/* maximum number of segments for the DM device */
+#define MAX_BITLK_SEGMENTS 10
+
+/* January 1, 1970 as MS file time */
+#define EPOCH_AS_FILETIME 116444736000000000
+#define HUNDREDS_OF_NANOSECONDS 10000000
+
+/* not available in older version of libuuid */
+#ifndef UUID_STR_LEN
+#define UUID_STR_LEN 37
+#endif
+
+/* known types of GUIDs from the BITLK superblock */
+const uint8_t BITLK_GUID_NORMAL[16] = { 0x3b, 0xd6, 0x67, 0x49, 0x29, 0x2e, 0xd8, 0x4a,
+ 0x83, 0x99, 0xf6, 0xa3, 0x39, 0xe3, 0xd0, 0x01 };
+const uint8_t BITLK_GUID_EOW[16] = { 0x3b, 0x4d, 0xa8, 0x92, 0x80, 0xdd, 0x0e, 0x4d,
+ 0x9e, 0x4e, 0xb1, 0xe3, 0x28, 0x4e, 0xae, 0xd8 };
+
+/* taken from libfdisk gpt.c -- TODO: this is a good candidate for adding to libuuid */
+struct bitlk_guid {
+ uint32_t time_low;
+ uint16_t time_mid;
+ uint16_t time_hi_and_version;
+ uint8_t clock_seq_hi;
+ uint8_t clock_seq_low;
+ uint8_t node[6];
+} __attribute__ ((packed));
+
+static void swap_guid(struct bitlk_guid *guid) {
+ guid->time_low = swab32(guid->time_low);
+ guid->time_mid = swab16(guid->time_mid);
+ guid->time_hi_and_version = swab16(guid->time_hi_and_version);
+}
+
+static void guid_to_string(struct bitlk_guid *guid, char *out) {
+ swap_guid(guid);
+ uuid_unparse((unsigned char *) guid, out);
+}
+
+typedef enum {
+ BITLK_SEGTYPE_CRYPT,
+ BITLK_SEGTYPE_ZERO,
+} BitlkSegmentType;
+
+struct segment {
+ uint64_t offset;
+ uint64_t length;
+ uint64_t iv_offset;
+ BitlkSegmentType type;
+};
+
+struct bitlk_signature {
+ uint8_t boot_code[3];
+ uint8_t signature[8];
+ uint16_t sector_size;
+} __attribute__ ((packed));
+
+struct bitlk_superblock {
+ struct bitlk_guid guid;
+ uint64_t fve_offset[3];
+} __attribute__ ((packed));
+
+struct bitlk_fve_metadata {
+ /* FVE metadata block header */
+ uint8_t signature[8];
+ uint16_t fve_size;
+ uint16_t fve_version;
+ uint16_t curr_state;
+ uint16_t next_state;
+ uint64_t volume_size;
+ uint32_t unknown2;
+ uint32_t volume_header_size;
+ uint64_t fve_offset[3];
+ uint64_t volume_header_offset;
+ /* FVE metadata header */
+ uint32_t metadata_size;
+ uint32_t metadata_version;
+ uint32_t metadata_header_size;
+ uint32_t metada_size_copy;
+ struct bitlk_guid guid;
+ uint32_t next_nonce;
+ uint16_t encryption;
+ uint16_t unknown3;
+ uint64_t creation_time;
+} __attribute__ ((packed));
+
+struct bitlk_entry_header_block {
+ uint64_t offset;
+ uint64_t size;
+} __attribute__ ((packed));
+
+struct bitlk_entry_vmk {
+ struct bitlk_guid guid;
+ uint8_t modified[8];
+ uint16_t _unknown;
+ uint16_t protection;
+} __attribute__ ((packed));
+
+struct bitlk_kdf_data {
+ char last_sha256[32];
+ char initial_sha256[32];
+ char salt[16];
+ uint64_t count;
+};
+
+struct bitlk_bek_header {
+ uint32_t metadata_size;
+ uint32_t metadata_version;
+ uint32_t metadata_header_size;
+ uint32_t metada_size_copy;
+ struct bitlk_guid guid;
+ uint32_t next_nonce;
+ uint16_t encryption;
+ uint16_t unknown;
+ uint64_t creation_time;
+} __attribute__ ((packed));
+
+static BITLKVMKProtection get_vmk_protection(uint16_t protection)
+{
+ switch (protection) {
+ case 0x0000:
+ return BITLK_PROTECTION_CLEAR_KEY;
+ case 0x0100:
+ return BITLK_PROTECTION_TPM;
+ case 0x0200:
+ return BITLK_PROTECTION_STARTUP_KEY;
+ case 0x0500:
+ return BITLK_PROTECTION_TPM_PIN;
+ case 0x0800:
+ return BITLK_PROTECTION_RECOVERY_PASSPHRASE;
+ case 0x1000:
+ return BITLK_PROTECTION_SMART_CARD;
+ case 0x2000:
+ return BITLK_PROTECTION_PASSPHRASE;
+ default:
+ return BITLK_PROTECTION_UNKNOWN;
+ }
+}
+
+static const char* get_vmk_protection_string(BITLKVMKProtection protection)
+{
+ switch (protection) {
+ case BITLK_PROTECTION_CLEAR_KEY:
+ return "VMK protected with clear key";
+ case BITLK_PROTECTION_TPM:
+ return "VMK protected with TPM";
+ case BITLK_PROTECTION_STARTUP_KEY:
+ return "VMK protected with startup key";
+ case BITLK_PROTECTION_TPM_PIN:
+ return "VMK protected with TPM and PIN";
+ case BITLK_PROTECTION_PASSPHRASE:
+ return "VMK protected with passphrase";
+ case BITLK_PROTECTION_RECOVERY_PASSPHRASE:
+ return "VMK protected with recovery passphrase";
+ case BITLK_PROTECTION_SMART_CARD:
+ return "VMK protected with smart card";
+ default:
+ return "VMK with unknown protection";
+ }
+}
+
+static const char* get_bitlk_type_string(BITLKEncryptionType type)
+{
+ switch (type)
+ {
+ case BITLK_ENCRYPTION_TYPE_NORMAL:
+ return "normal";
+ case BITLK_ENCRYPTION_TYPE_EOW:
+ return "encrypt-on-write";
+ default:
+ return "unknown";
+ }
+}
+
+static uint64_t filetime_to_unixtime(uint64_t time)
+{
+ return (time - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS;
+}
+
+static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, int end, struct bitlk_vmk **vmk)
+{
+ uint16_t key_entry_size = 0;
+ uint16_t key_entry_type = 0;
+ uint16_t key_entry_value = 0;
+ size_t key_size = 0;
+ char *string = NULL;
+ const char *key = NULL;
+ struct volume_key *vk = NULL;
+ bool supported = false;
+ int r = 0;
+
+ /* only passphrase or recovery passphrase vmks are supported (can be used to activate) */
+ supported = (*vmk)->protection == BITLK_PROTECTION_PASSPHRASE ||
+ (*vmk)->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE ||
+ (*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY;
+
+ while ((end - start) >= (ssize_t)(sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value))) {
+ /* size of this entry */
+ memcpy(&key_entry_size, data + start, sizeof(key_entry_size));
+ key_entry_size = le16_to_cpu(key_entry_size);
+ if (key_entry_size == 0)
+ break;
+
+ if (key_entry_size > (end - start))
+ return -EINVAL;
+
+ /* type and value of this entry */
+ memcpy(&key_entry_type, data + start + sizeof(key_entry_size), sizeof(key_entry_type));
+ memcpy(&key_entry_value,
+ data + start + sizeof(key_entry_size) + sizeof(key_entry_type),
+ sizeof(key_entry_value));
+ key_entry_type = le16_to_cpu(key_entry_type);
+ key_entry_value = le16_to_cpu(key_entry_value);
+
+ if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) {
+ if (supported) {
+ log_err(cd, _("Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."), key_entry_type);
+ return -EINVAL;
+ } else {
+ log_dbg(cd, "Unexpected metadata entry type '%u' found when parsing unsupported VMK.", key_entry_type);
+ }
+ }
+
+ /* stretch key with salt, skip 4 B (encryption method of the stretch key) */
+ if (key_entry_value == BITLK_ENTRY_VALUE_STRETCH_KEY) {
+ if ((end - start) < (BITLK_ENTRY_HEADER_LEN + BITLK_SALT_SIZE + 4))
+ return -EINVAL;
+ memcpy((*vmk)->salt,
+ data + start + BITLK_ENTRY_HEADER_LEN + 4,
+ BITLK_SALT_SIZE);
+ /* AES-CCM encrypted key */
+ } else if (key_entry_value == BITLK_ENTRY_VALUE_ENCRYPTED_KEY) {
+ if (key_entry_size < (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE))
+ return -EINVAL;
+ /* nonce */
+ memcpy((*vmk)->nonce,
+ data + start + BITLK_ENTRY_HEADER_LEN,
+ BITLK_NONCE_SIZE);
+ /* MAC tag */
+ memcpy((*vmk)->mac_tag,
+ data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE,
+ BITLK_VMK_MAC_TAG_SIZE);
+ /* AES-CCM encrypted key */
+ key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE);
+ key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE;
+ vk = crypt_alloc_volume_key(key_size, key);
+ if (vk == NULL)
+ return -ENOMEM;
+ crypt_volume_key_add_next(&((*vmk)->vk), vk);
+ /* clear key for a partially decrypted volume */
+ } else if (key_entry_value == BITLK_ENTRY_VALUE_KEY) {
+ /* We currently don't want to support opening a partially decrypted
+ * device so we don't need to store this key.
+ *
+ * key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + 4);
+ * key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + 4;
+ * vk = crypt_alloc_volume_key(key_size, key);
+ * if (vk == NULL)
+ * return -ENOMEM;
+ * crypt_volume_key_add_next(&((*vmk)->vk), vk);
+ */
+ log_dbg(cd, "Skipping clear key metadata entry.");
+ /* unknown timestamps in recovery protected VMK */
+ } else if (key_entry_value == BITLK_ENTRY_VALUE_RECOVERY_TIME) {
+ ;
+ } else if (key_entry_value == BITLK_ENTRY_VALUE_STRING) {
+ if (key_entry_size < BITLK_ENTRY_HEADER_LEN)
+ return -EINVAL;
+ string = malloc((key_entry_size - BITLK_ENTRY_HEADER_LEN) * 2 + 1);
+ if (!string)
+ return -ENOMEM;
+ r = crypt_utf16_to_utf8(&string, CONST_CAST(char16_t *)(data + start + BITLK_ENTRY_HEADER_LEN),
+ key_entry_size - BITLK_ENTRY_HEADER_LEN);
+ if (r < 0 || !string) {
+ free(string);
+ log_err(cd, _("Invalid string found when parsing Volume Master Key."));
+ return -EINVAL;
+ } else if ((*vmk)->name != NULL) {
+ if (supported) {
+ log_err(cd, _("Unexpected string ('%s') found when parsing supported Volume Master Key."), string);
+ free(string);
+ return -EINVAL;
+ }
+ log_dbg(cd, "Unexpected string ('%s') found when parsing unsupported VMK.", string);
+ free(string);
+ string = NULL;
+ } else {
+ /* Assume that strings in VMK are the name of the VMK */
+ (*vmk)->name = string;
+ string = NULL;
+ }
+ /* no idea what this is, lets hope it's not important */
+ } else if (key_entry_value == BITLK_ENTRY_VALUE_USE_KEY && (*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY) {
+ ;
+ } else {
+ if (supported) {
+ log_err(cd, _("Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."), key_entry_value);
+ return -EINVAL;
+ } else {
+ log_dbg(cd, "Unexpected metadata entry value '%u' found when parsing unsupported VMK.", key_entry_value);
+ }
+ }
+
+ start += key_entry_size;
+ }
+
+ return 0;
+}
+
+void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek)
+{
+ if (!fvek)
+ return;
+
+ crypt_free_volume_key(fvek->vk);
+ free(fvek);
+}
+
+void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk)
+{
+ struct bitlk_vmk *vmk_next = NULL;
+
+ while (vmk) {
+ if (vmk->guid)
+ free(vmk->guid);
+ if (vmk->name)
+ free(vmk->name);
+ crypt_free_volume_key(vmk->vk);
+ vmk_next = vmk->next;
+ free(vmk);
+ vmk = vmk_next;
+ }
+}
+
+void BITLK_bitlk_metadata_free(struct bitlk_metadata *metadata)
+{
+ if (!metadata)
+ return;
+
+ free(metadata->guid);
+ if (metadata->description)
+ free(metadata->description);
+ BITLK_bitlk_vmk_free(metadata->vmks);
+ BITLK_bitlk_fvek_free(metadata->fvek);
+}
+
+int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
+{
+ int devfd;
+ struct device *device = crypt_metadata_device(cd);
+ struct bitlk_signature sig = {};
+ struct bitlk_superblock sb = {};
+ struct bitlk_fve_metadata fve = {};
+ struct bitlk_entry_vmk entry_vmk = {};
+ uint8_t *fve_entries = NULL;
+ size_t fve_entries_size = 0;
+ uint32_t fve_metadata_size = 0;
+ int fve_offset = 0;
+ char guid_buf[UUID_STR_LEN] = {0};
+ uint16_t entry_size = 0;
+ uint16_t entry_type = 0;
+ int i = 0;
+ int r = 0;
+ int start = 0;
+ size_t key_size = 0;
+ const char *key = NULL;
+ char *description = NULL;
+
+ struct bitlk_vmk *vmk = NULL;
+ struct bitlk_vmk *vmk_p = params->vmks;
+
+ devfd = device_open(cd, crypt_data_device(cd), O_RDONLY);
+ if (devfd < 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* read and check the signature */
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), &sig, sizeof(sig), 0) != sizeof(sig)) {
+ log_dbg(cd, "Failed to read BITLK signature from %s.", device_path(device));
+ r = -EIO;
+ goto out;
+ }
+
+ if (memcmp(sig.signature, BITLK_SIGNATURE, sizeof(sig.signature)) == 0) {
+ params->togo = false;
+ fve_offset = BITLK_HEADER_METADATA_OFFSET;
+ } else if (memcmp(sig.signature, BITLK_SIGNATURE_TOGO, sizeof(sig.signature)) == 0) {
+ params->togo = true;
+ fve_offset = BITLK_HEADER_METADATA_OFFSET_TOGO;
+ } else {
+ log_dbg(cd, "Invalid or unknown signature for BITLK device.");
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (memcmp(sig.boot_code, BITLK_BOOTCODE_V1, sizeof(sig.boot_code)) == 0) {
+ log_err(cd, _("BITLK version 1 is currently not supported."));
+ r = -ENOTSUP;
+ goto out;
+ } else if (memcmp(sig.boot_code, BITLK_BOOTCODE_V2, sizeof(sig.boot_code)) == 0)
+ ;
+ else {
+ log_err(cd, _("Invalid or unknown boot signature for BITLK device."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ params->sector_size = le16_to_cpu(sig.sector_size);
+ if (params->sector_size == 0) {
+ log_dbg(cd, "Got sector size 0, assuming 512.");
+ params->sector_size = SECTOR_SIZE;
+ }
+
+ if (!(params->sector_size == 512 || params->sector_size == 4096)) {
+ log_err(cd, _("Unsupported sector size %" PRIu16 "."), params->sector_size);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* read GUID and FVE metadata offsets */
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), &sb, sizeof(sb), fve_offset) != sizeof(sb)) {
+ log_err(cd, _("Failed to read BITLK header from %s."), device_path(device));
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* get encryption "type" based on the GUID from BITLK superblock */
+ if (memcmp(&sb.guid, BITLK_GUID_NORMAL, 16) == 0)
+ params->type = BITLK_ENCRYPTION_TYPE_NORMAL;
+ else if (memcmp(&sb.guid, BITLK_GUID_EOW, 16) == 0)
+ params->type = BITLK_ENCRYPTION_TYPE_EOW;
+ else
+ params->type = BITLK_ENCRYPTION_TYPE_UNKNOWN;
+ log_dbg(cd, "BITLK type from GUID: %s.", get_bitlk_type_string(params->type));
+
+ for (i = 0; i < 3; i++)
+ params->metadata_offset[i] = le64_to_cpu(sb.fve_offset[i]);
+
+ log_dbg(cd, "Reading BITLK FVE metadata of size %zu on device %s, offset %" PRIu64 ".",
+ sizeof(fve), device_path(device), params->metadata_offset[0]);
+
+ /* read FVE metadata from the first metadata area */
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), &fve, sizeof(fve), params->metadata_offset[0]) != sizeof(fve) ||
+ memcmp(fve.signature, BITLK_SIGNATURE, sizeof(fve.signature)) ||
+ le16_to_cpu(fve.fve_version) != 2) {
+ log_err(cd, _("Failed to read BITLK FVE metadata from %s."), device_path(device));
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* check encryption state for the device */
+ params->state = true;
+ if (le16_to_cpu(fve.curr_state) != BITLK_STATE_NORMAL || le16_to_cpu(fve.next_state) != BITLK_STATE_NORMAL) {
+ params->state = false;
+ log_dbg(cd, "Unknown/unsupported state detected. Current state: %"PRIu16", next state: %"PRIu16".",
+ le16_to_cpu(fve.curr_state), le16_to_cpu(fve.next_state));
+ }
+
+ params->volume_size = le64_to_cpu(fve.volume_size);
+ params->metadata_version = le16_to_cpu(fve.fve_version);
+
+ switch (le16_to_cpu(fve.encryption)) {
+ /* AES-CBC with Elephant difuser */
+ case 0x8000:
+ params->key_size = 256;
+ params->cipher = "aes";
+ params->cipher_mode = "cbc-elephant";
+ break;
+ case 0x8001:
+ params->key_size = 512;
+ params->cipher = "aes";
+ params->cipher_mode = "cbc-elephant";
+ break;
+ /* AES-CBC */
+ case 0x8002:
+ params->key_size = 128;
+ params->cipher = "aes";
+ params->cipher_mode = "cbc-eboiv";
+ break;
+ case 0x8003:
+ params->key_size = 256;
+ params->cipher = "aes";
+ params->cipher_mode = "cbc-eboiv";
+ break;
+ /* AES-XTS */
+ case 0x8004:
+ params->key_size = 256;
+ params->cipher = "aes";
+ params->cipher_mode = "xts-plain64";
+ break;
+ case 0x8005:
+ params->key_size = 512;
+ params->cipher = "aes";
+ params->cipher_mode = "xts-plain64";
+ break;
+ default:
+ log_err(cd, _("Unknown or unsupported encryption type."));
+ params->key_size = 0;
+ params->cipher = NULL;
+ params->cipher_mode = NULL;
+ r = -ENOTSUP;
+ goto out;
+ };
+
+ /* device GUID */
+ guid_to_string(&fve.guid, guid_buf);
+ params->guid = strdup(guid_buf);
+ if (!params->guid) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ params->creation_time = filetime_to_unixtime(le64_to_cpu(fve.creation_time));
+
+ fve_metadata_size = le32_to_cpu(fve.metadata_size);
+ if (fve_metadata_size < (BITLK_FVE_METADATA_HEADER_LEN + sizeof(entry_size) + sizeof(entry_type)) ||
+ fve_metadata_size > BITLK_FVE_METADATA_SIZE) {
+ r = -EINVAL;
+ goto out;
+ }
+ fve_entries_size = fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN;
+
+ /* read and parse all FVE metadata entries */
+ fve_entries = malloc(fve_entries_size);
+ if (!fve_entries) {
+ r = -ENOMEM;
+ goto out;
+ }
+ memset(fve_entries, 0, fve_entries_size);
+
+ log_dbg(cd, "Reading BITLK FVE metadata entries of size %zu on device %s, offset %" PRIu64 ".",
+ fve_entries_size, device_path(device), params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN);
+
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), fve_entries, fve_entries_size,
+ params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN) != (ssize_t)fve_entries_size) {
+ log_err(cd, _("Failed to read BITLK metadata entries from %s."), device_path(device));
+ r = -EINVAL;
+ goto out;
+ }
+
+ while ((fve_entries_size - start) >= (sizeof(entry_size) + sizeof(entry_type))) {
+
+ /* size of this entry */
+ memcpy(&entry_size, fve_entries + start, sizeof(entry_size));
+ entry_size = le16_to_cpu(entry_size);
+ if (entry_size == 0)
+ break;
+
+ if (entry_size > (fve_entries_size - start)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* type of this entry */
+ memcpy(&entry_type, fve_entries + start + sizeof(entry_size), sizeof(entry_type));
+ entry_type = le16_to_cpu(entry_type);
+
+ /* VMK */
+ if (entry_type == BITLK_ENTRY_TYPE_VMK) {
+ if (entry_size < (BITLK_ENTRY_HEADER_LEN + sizeof(entry_vmk))) {
+ r = -EINVAL;
+ goto out;
+ }
+ /* skip first four variables in the entry (entry size, type, value and version) */
+ memcpy(&entry_vmk,
+ fve_entries + start + BITLK_ENTRY_HEADER_LEN,
+ sizeof(entry_vmk));
+
+ vmk = malloc(sizeof(struct bitlk_vmk));
+ if (!vmk) {
+ r = -ENOMEM;
+ goto out;
+ }
+ memset(vmk, 0, sizeof(struct bitlk_vmk));
+
+ guid_to_string(&entry_vmk.guid, guid_buf);
+ vmk->guid = strdup (guid_buf);
+
+ vmk->name = NULL;
+
+ vmk->protection = get_vmk_protection(le16_to_cpu(entry_vmk.protection));
+
+ /* more data in another entry list */
+ r = parse_vmk_entry(cd, fve_entries,
+ start + BITLK_ENTRY_HEADER_LEN + BITLK_VMK_HEADER_LEN,
+ start + entry_size, &vmk);
+ if (r < 0) {
+ BITLK_bitlk_vmk_free(vmk);
+ goto out;
+ }
+
+ if (params->vmks == NULL)
+ params->vmks = vmk;
+ else
+ vmk_p->next = vmk;
+
+ vmk_p = vmk;
+ vmk = vmk->next;
+ /* FVEK */
+ } else if (entry_type == BITLK_ENTRY_TYPE_FVEK && !params->fvek) {
+ if (entry_size < (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE)) {
+ r = -EINVAL;
+ goto out;
+ }
+ params->fvek = malloc(sizeof(struct bitlk_fvek));
+ if (!params->fvek) {
+ r = -ENOMEM;
+ goto out;
+ }
+ memcpy(params->fvek->nonce,
+ fve_entries + start + BITLK_ENTRY_HEADER_LEN,
+ BITLK_NONCE_SIZE);
+ /* MAC tag */
+ memcpy(params->fvek->mac_tag,
+ fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE,
+ BITLK_VMK_MAC_TAG_SIZE);
+ /* AES-CCM encrypted key */
+ key_size = entry_size - (BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE);
+ key = (const char *) fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE;
+ params->fvek->vk = crypt_alloc_volume_key(key_size, key);
+ if (params->fvek->vk == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+ /* volume header info (location and size) */
+ } else if (entry_type == BITLK_ENTRY_TYPE_VOLUME_HEADER) {
+ struct bitlk_entry_header_block entry_header;
+ if ((fve_entries_size - start) < (BITLK_ENTRY_HEADER_LEN + sizeof(entry_header))) {
+ r = -EINVAL;
+ goto out;
+ }
+ memcpy(&entry_header,
+ fve_entries + start + BITLK_ENTRY_HEADER_LEN,
+ sizeof(entry_header));
+ params->volume_header_offset = le64_to_cpu(entry_header.offset);
+ params->volume_header_size = le64_to_cpu(entry_header.size);
+ /* volume description (utf-16 string) */
+ } else if (entry_type == BITLK_ENTRY_TYPE_DESCRIPTION && !params->description) {
+ if (entry_size < BITLK_ENTRY_HEADER_LEN) {
+ r = -EINVAL;
+ goto out;
+ }
+ description = malloc((entry_size - BITLK_ENTRY_HEADER_LEN) * 2 + 1);
+ if (!description) {
+ r = -ENOMEM;
+ goto out;
+ }
+ r = crypt_utf16_to_utf8(&description, CONST_CAST(char16_t *)(fve_entries + start + BITLK_ENTRY_HEADER_LEN),
+ entry_size - BITLK_ENTRY_HEADER_LEN);
+ if (r < 0) {
+ free(description);
+ BITLK_bitlk_vmk_free(vmk);
+ log_err(cd, _("Failed to convert BITLK volume description"));
+ goto out;
+ }
+ params->description = description;
+ }
+
+ start += entry_size;
+ }
+
+out:
+ if (fve_entries)
+ free(fve_entries);
+ return r;
+}
+
+int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_metadata *params)
+{
+ struct volume_key *vk_p;
+ struct bitlk_vmk *vmk_p;
+ int next_id = 0;
+ int i = 0;
+
+ log_std(cd, "Info for BITLK%s device %s.\n", params->togo ? " To Go" : "", device_path(device));
+ log_std(cd, "Version: \t%u\n", params->metadata_version);
+ log_std(cd, "GUID: \t%s\n", params->guid);
+ log_std(cd, "Sector size: \t%u [bytes]\n", params->sector_size);
+ log_std(cd, "Volume size: \t%" PRIu64 " [bytes]\n", params->volume_size);
+ log_std(cd, "Created: \t%s", ctime((time_t *)&(params->creation_time)));
+ log_std(cd, "Description: \t%s\n", params->description);
+ log_std(cd, "Cipher name: \t%s\n", params->cipher);
+ log_std(cd, "Cipher mode: \t%s\n", params->cipher_mode);
+ log_std(cd, "Cipher key: \t%u bits\n", params->key_size);
+
+ log_std(cd, "\n");
+
+ log_std(cd, "Keyslots:\n");
+ vmk_p = params->vmks;
+ while (vmk_p) {
+ log_std(cd, " %d: VMK\n", next_id);
+ if (vmk_p->name != NULL) {
+ log_std(cd, "\tName: \t%s\n", vmk_p->name);
+ }
+ log_std(cd, "\tGUID: \t%s\n", vmk_p->guid);
+ log_std(cd, "\tProtection: \t%s\n", get_vmk_protection_string (vmk_p->protection));
+ log_std(cd, "\tSalt: \t");
+ crypt_log_hex(cd, (const char *) vmk_p->salt, 16, "", 0, NULL);
+ log_std(cd, "\n");
+
+ vk_p = vmk_p->vk;
+ while (vk_p) {
+ log_std(cd, "\tKey data size:\t%zu [bytes]\n", vk_p->keylength);
+ vk_p = vk_p->next;
+ }
+ vmk_p = vmk_p->next;
+ next_id++;
+ }
+
+ log_std(cd, " %d: FVEK\n", next_id);
+ log_std(cd, "\tKey data size:\t%zu [bytes]\n", params->fvek->vk->keylength);
+
+ log_std(cd, "\n");
+
+ log_std(cd, "Metadata segments:\n");
+
+ for (i = 0; i < 3; i++) {
+ log_std(cd, " %d: FVE metadata area\n", i);
+ log_std(cd, "\tOffset: \t%" PRIu64 " [bytes]\n", params->metadata_offset[i]);
+ log_std(cd, "\tSize: \t%d [bytes]\n", BITLK_FVE_METADATA_SIZE);
+ }
+
+ log_std(cd, " %d: Volume header\n", i);
+ log_std(cd, "\tOffset: \t%" PRIu64 " [bytes]\n", params->volume_header_offset);
+ log_std(cd, "\tSize: \t%" PRIu64 " [bytes]\n", params->volume_header_size);
+ log_std(cd, "\tCipher: \t%s-%s\n", params->cipher, params->cipher_mode);
+
+ return 0;
+}
+
+/* check if given passphrase can be a recovery key (has right format) and convert it */
+static int get_recovery_key(struct crypt_device *cd,
+ const char *password,
+ size_t passwordLen,
+ struct volume_key **rc_key)
+{
+ unsigned int i, j = 0;
+ uint16_t parts[BITLK_RECOVERY_PARTS] = {0};
+ char part_str[BITLK_RECOVERY_PART_LEN + 1] = {0};
+ long part_num = 0;
+
+ /* check the passphrase it should be:
+ - 55 characters
+ - 8 groups of 6 divided by '-'
+ - each part is a number dividable by 11
+ */
+ if (passwordLen != BITLK_RECOVERY_KEY_LEN) {
+ if (passwordLen == BITLK_RECOVERY_KEY_LEN + 1 && password[passwordLen - 1] == '\n') {
+ /* looks like a recovery key with an extra newline, possibly from a key file */
+ passwordLen--;
+ log_dbg(cd, "Possible extra EOL stripped from the recovery key.");
+ } else
+ return 0;
+ }
+
+ for (i = BITLK_RECOVERY_PART_LEN; i < passwordLen; i += BITLK_RECOVERY_PART_LEN + 1) {
+ if (password[i] != '-')
+ return 0;
+ }
+
+ for (i = 0, j = 0; i < passwordLen; i += BITLK_RECOVERY_PART_LEN + 1, j++) {
+ strncpy(part_str, password + i, BITLK_RECOVERY_PART_LEN);
+
+ errno = 0;
+ part_num = strtol(part_str, NULL, 10);
+ if ((errno == ERANGE && (part_num == LONG_MAX || part_num == LONG_MIN)) ||
+ (errno != 0 && part_num == 0))
+ return -errno;
+
+ if (part_num % 11 != 0)
+ return 0;
+ parts[j] = cpu_to_le16(part_num / 11);
+ }
+
+ *rc_key = crypt_alloc_volume_key(16, (const char*) parts);
+ if (*rc_key == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int parse_external_key_entry(struct crypt_device *cd,
+ const char *data,
+ int start,
+ int end,
+ struct volume_key **vk,
+ const struct bitlk_metadata *params)
+{
+ uint16_t key_entry_size = 0;
+ uint16_t key_entry_type = 0;
+ uint16_t key_entry_value = 0;
+ size_t key_size = 0;
+ const char *key = NULL;
+ struct bitlk_guid guid;
+ char guid_buf[UUID_STR_LEN] = {0};
+
+ while ((end - start) >= (ssize_t)(sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value))) {
+ /* size of this entry */
+ memcpy(&key_entry_size, data + start, sizeof(key_entry_size));
+ key_entry_size = le16_to_cpu(key_entry_size);
+ if (key_entry_size == 0)
+ break;
+
+ if (key_entry_size > (end - start))
+ return -EINVAL;
+
+ /* type and value of this entry */
+ memcpy(&key_entry_type, data + start + sizeof(key_entry_size), sizeof(key_entry_type));
+ memcpy(&key_entry_value,
+ data + start + sizeof(key_entry_size) + sizeof(key_entry_type),
+ sizeof(key_entry_value));
+ key_entry_type = le16_to_cpu(key_entry_type);
+ key_entry_value = le16_to_cpu(key_entry_value);
+
+ if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY && key_entry_type != BITLK_ENTRY_TYPE_VOLUME_GUID) {
+ log_err(cd, _("Unexpected metadata entry type '%u' found when parsing external key."), key_entry_type);
+ return -EINVAL;
+ }
+
+ if (key_entry_value == BITLK_ENTRY_VALUE_KEY) {
+ if (key_entry_size < (BITLK_ENTRY_HEADER_LEN + 4))
+ return -EINVAL;
+ key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + 4);
+ key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + 4;
+ *vk = crypt_alloc_volume_key(key_size, key);
+ if (*vk == NULL)
+ return -ENOMEM;
+ return 0;
+ /* optional "ExternalKey" string, we can safely ignore it */
+ } else if (key_entry_value == BITLK_ENTRY_VALUE_STRING)
+ ;
+ /* GUID of the BitLocker device we are trying to open with this key */
+ else if (key_entry_value == BITLK_ENTRY_VALUE_GUID) {
+ if ((end - start) < (ssize_t)(BITLK_ENTRY_HEADER_LEN + sizeof(struct bitlk_guid)))
+ return -EINVAL;
+ memcpy(&guid, data + start + BITLK_ENTRY_HEADER_LEN, sizeof(struct bitlk_guid));
+ guid_to_string(&guid, guid_buf);
+ if (strcmp(guid_buf, params->guid) != 0) {
+ log_err(cd, _("BEK file GUID '%s' does not match GUID of the volume."), guid_buf);
+ return -EINVAL;
+ }
+ } else {
+ log_err(cd, _("Unexpected metadata entry value '%u' found when parsing external key."), key_entry_value);
+ return -EINVAL;
+ }
+
+ start += key_entry_size;
+ }
+
+ /* if we got here we failed to parse the metadata */
+ return -EINVAL;
+}
+
+/* check if given passphrase can be a startup key (has right format) and convert it */
+static int get_startup_key(struct crypt_device *cd,
+ const char *password,
+ size_t passwordLen,
+ const struct bitlk_vmk *vmk,
+ struct volume_key **su_key,
+ const struct bitlk_metadata *params)
+{
+ struct bitlk_bek_header bek_header = {0};
+ char guid_buf[UUID_STR_LEN] = {0};
+
+ uint16_t key_entry_size = 0;
+ uint16_t key_entry_type = 0;
+ uint16_t key_entry_value = 0;
+
+ if (passwordLen < (BITLK_BEK_FILE_HEADER_LEN + sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value)))
+ return -EPERM;
+
+ memcpy(&bek_header, password, BITLK_BEK_FILE_HEADER_LEN);
+
+ /* metadata should contain GUID of the VMK this startup key is used for */
+ guid_to_string(&bek_header.guid, guid_buf);
+ if (strcmp(guid_buf, vmk->guid) == 0)
+ log_dbg(cd, "Found matching startup key for VMK %s", vmk->guid);
+ else
+ return -EPERM;
+
+ if (le32_to_cpu(bek_header.metadata_version) != 1) {
+ log_err(cd, _("Unsupported BEK metadata version %" PRIu32), le32_to_cpu(bek_header.metadata_version));
+ return -ENOTSUP;
+ }
+
+ if (le32_to_cpu(bek_header.metadata_size) != passwordLen) {
+ log_err(cd, _("Unexpected BEK metadata size %" PRIu32 " does not match BEK file length"),
+ le32_to_cpu(bek_header.metadata_size));
+ return -EINVAL;
+ }
+
+ /* we are expecting exactly one metadata entry starting immediately after the header */
+ memcpy(&key_entry_size, password + BITLK_BEK_FILE_HEADER_LEN, sizeof(key_entry_size));
+ key_entry_size = le16_to_cpu(key_entry_size);
+ if (key_entry_size < BITLK_ENTRY_HEADER_LEN) {
+ log_dbg(cd, "Unexpected metadata entry size %" PRIu16 " when parsing BEK file", key_entry_size);
+ return -EINVAL;
+ }
+
+ /* type and value of this entry */
+ memcpy(&key_entry_type, password + BITLK_BEK_FILE_HEADER_LEN + sizeof(key_entry_size), sizeof(key_entry_type));
+ memcpy(&key_entry_value,
+ password + BITLK_BEK_FILE_HEADER_LEN + sizeof(key_entry_size) + sizeof(key_entry_type),
+ sizeof(key_entry_value));
+ key_entry_type = le16_to_cpu(key_entry_type);
+ key_entry_value = le16_to_cpu(key_entry_value);
+
+ if (key_entry_type == BITLK_ENTRY_TYPE_STARTUP_KEY && key_entry_value == BITLK_ENTRY_VALUE_EXTERNAL_KEY) {
+ return parse_external_key_entry(cd, password,
+ BITLK_BEK_FILE_HEADER_LEN + BITLK_ENTRY_HEADER_LEN + BITLK_STARTUP_KEY_HEADER_LEN,
+ passwordLen, su_key, params);
+ } else {
+ log_err(cd, _("Unexpected metadata entry found when parsing startup key."));
+ log_dbg(cd, "Entry type: %u, entry value: %u", key_entry_type, key_entry_value);
+ return -EINVAL;
+ }
+}
+
+static int bitlk_kdf(struct crypt_device *cd,
+ const char *password,
+ size_t passwordLen,
+ bool recovery,
+ const uint8_t *salt,
+ struct volume_key **vk)
+{
+ struct bitlk_kdf_data kdf = {};
+ struct crypt_hash *hd = NULL;
+ int len = 0;
+ char16_t *utf16Password = NULL;
+ int i = 0;
+ int r = 0;
+
+ memcpy(kdf.salt, salt, 16);
+
+ r = crypt_hash_init(&hd, BITLK_KDF_HASH);
+ if (r < 0)
+ return r;
+ len = crypt_hash_size(BITLK_KDF_HASH);
+ if (len < 0) {
+ crypt_hash_destroy(hd);
+ return len;
+ }
+
+ if (!recovery) {
+ /* passphrase: convert to UTF-16 first, then sha256(sha256(pw)) */
+ utf16Password = crypt_safe_alloc(sizeof(char16_t) * (passwordLen + 1));
+ if (!utf16Password) {
+ r = -ENOMEM;
+ goto out;
+ }
+ r = crypt_utf8_to_utf16(&utf16Password, CONST_CAST(char*)password, passwordLen);
+ if (r < 0)
+ goto out;
+
+ crypt_hash_write(hd, (char*)utf16Password, passwordLen * 2);
+ r = crypt_hash_final(hd, kdf.initial_sha256, len);
+ if (r < 0)
+ goto out;
+
+ crypt_hash_write(hd, kdf.initial_sha256, len);
+ r = crypt_hash_final(hd, kdf.initial_sha256, len);
+ if (r < 0)
+ goto out;
+ } else {
+ /* recovery passphrase: already converted in #get_recovery_key, now just sha256(rpw) */
+ crypt_hash_write(hd, password, passwordLen);
+ r = crypt_hash_final(hd, kdf.initial_sha256, len);
+ if (r < 0)
+ goto out;
+ }
+
+ for (i = 0; i < BITLK_KDF_ITERATION_COUNT; i++) {
+ crypt_hash_write(hd, (const char*) &kdf, sizeof(kdf));
+ r = crypt_hash_final(hd, kdf.last_sha256, len);
+ if (r < 0)
+ goto out;
+ kdf.count = cpu_to_le64(le64_to_cpu(kdf.count) + 1);
+ }
+
+ *vk = crypt_alloc_volume_key(len, kdf.last_sha256);
+
+out:
+ crypt_safe_free(utf16Password);
+ if (hd)
+ crypt_hash_destroy(hd);
+ return r;
+}
+
+static int decrypt_key(struct crypt_device *cd,
+ struct volume_key **vk,
+ struct volume_key *enc_key,
+ struct volume_key *key,
+ const uint8_t *tag, size_t tag_size,
+ const uint8_t *iv, size_t iv_size,
+ bool is_fvek)
+{
+ char *outbuf;
+ int r;
+ uint16_t key_size = 0;
+
+ outbuf = crypt_safe_alloc(enc_key->keylength);
+ if (!outbuf)
+ return -ENOMEM;
+
+ r = crypt_bitlk_decrypt_key(key->key, key->keylength, enc_key->key, outbuf, enc_key->keylength,
+ (const char*)iv, iv_size, (const char*)tag, tag_size);
+ if (r < 0) {
+ if (r == -ENOTSUP)
+ log_err(cd, _("This operation is not supported."));
+ goto out;
+ }
+
+ /* key_data has it's size as part of the metadata */
+ memcpy(&key_size, outbuf, 2);
+ key_size = le16_to_cpu(key_size);
+ if (enc_key->keylength != key_size) {
+ log_err(cd, _("Unexpected key data size."));
+ log_dbg(cd, "Expected key data size: %zu, got %" PRIu16 "", enc_key->keylength, key_size);
+
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (is_fvek && strcmp(crypt_get_cipher_mode(cd), "cbc-elephant") == 0 &&
+ crypt_get_volume_key_size(cd) == 32) {
+ /* 128bit AES-CBC with Elephant -- key size is 256 bit (2 keys) but key data is 512 bits,
+ data: 16B CBC key, 16B empty, 16B elephant key, 16B empty */
+ memcpy(outbuf + 16 + BITLK_OPEN_KEY_METADATA_LEN,
+ outbuf + 2 * 16 + BITLK_OPEN_KEY_METADATA_LEN, 16);
+ key_size = 32 + BITLK_OPEN_KEY_METADATA_LEN;
+ }
+
+
+ *vk = crypt_alloc_volume_key(key_size - BITLK_OPEN_KEY_METADATA_LEN,
+ (const char *)(outbuf + BITLK_OPEN_KEY_METADATA_LEN));
+ r = *vk ? 0 : -ENOMEM;
+out:
+ crypt_safe_free(outbuf);
+ return r;
+}
+
+int BITLK_get_volume_key(struct crypt_device *cd,
+ const char *password,
+ size_t passwordLen,
+ const struct bitlk_metadata *params,
+ struct volume_key **open_fvek_key)
+{
+ int r = 0;
+ struct volume_key *open_vmk_key = NULL;
+ struct volume_key *vmk_dec_key = NULL;
+ struct volume_key *recovery_key = NULL;
+ const struct bitlk_vmk *next_vmk = NULL;
+
+ next_vmk = params->vmks;
+ while (next_vmk) {
+ if (next_vmk->protection == BITLK_PROTECTION_PASSPHRASE) {
+ r = bitlk_kdf(cd, password, passwordLen, false, next_vmk->salt, &vmk_dec_key);
+ if (r) {
+ /* something wrong happened, but we still want to check other key slots */
+ next_vmk = next_vmk->next;
+ continue;
+ }
+ } else if (next_vmk->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE) {
+ r = get_recovery_key(cd, password, passwordLen, &recovery_key);
+ if (r) {
+ /* something wrong happened, but we still want to check other key slots */
+ next_vmk = next_vmk->next;
+ continue;
+ }
+ if (recovery_key == NULL) {
+ /* r = 0 but no key -> given passphrase is not a recovery passphrase */
+ r = -EPERM;
+ next_vmk = next_vmk->next;
+ continue;
+ }
+ log_dbg(cd, "Trying to use given password as a recovery key.");
+ r = bitlk_kdf(cd, recovery_key->key, recovery_key->keylength,
+ true, next_vmk->salt, &vmk_dec_key);
+ crypt_free_volume_key(recovery_key);
+ if (r)
+ return r;
+ } else if (next_vmk->protection == BITLK_PROTECTION_STARTUP_KEY) {
+ r = get_startup_key(cd, password, passwordLen, next_vmk, &vmk_dec_key, params);
+ if (r) {
+ next_vmk = next_vmk->next;
+ continue;
+ }
+ log_dbg(cd, "Trying to use external key found in provided password.");
+ } else {
+ /* only passphrase, recovery passphrase and startup key VMKs supported right now */
+ log_dbg(cd, "Skipping %s", get_vmk_protection_string(next_vmk->protection));
+ next_vmk = next_vmk->next;
+ if (r == 0)
+ /* we need to set error code in case we have only unsupported VMKs */
+ r = -ENOTSUP;
+ continue;
+ }
+
+ log_dbg(cd, "Trying to decrypt %s.", get_vmk_protection_string(next_vmk->protection));
+ r = decrypt_key(cd, &open_vmk_key, next_vmk->vk, vmk_dec_key,
+ next_vmk->mac_tag, BITLK_VMK_MAC_TAG_SIZE,
+ next_vmk->nonce, BITLK_NONCE_SIZE, false);
+ if (r < 0) {
+ log_dbg(cd, "Failed to decrypt VMK using provided passphrase.");
+ crypt_free_volume_key(vmk_dec_key);
+ if (r == -ENOTSUP)
+ return r;
+ next_vmk = next_vmk->next;
+ continue;
+ }
+ crypt_free_volume_key(vmk_dec_key);
+
+ r = decrypt_key(cd, open_fvek_key, params->fvek->vk, open_vmk_key,
+ params->fvek->mac_tag, BITLK_VMK_MAC_TAG_SIZE,
+ params->fvek->nonce, BITLK_NONCE_SIZE, true);
+ if (r < 0) {
+ log_dbg(cd, "Failed to decrypt FVEK using VMK.");
+ crypt_free_volume_key(open_vmk_key);
+ if (r == -ENOTSUP)
+ return r;
+ } else {
+ crypt_free_volume_key(open_vmk_key);
+ break;
+ }
+
+ next_vmk = next_vmk->next;
+ }
+
+ if (r) {
+ log_dbg(cd, "No more VMKs to try.");
+ return r;
+ }
+
+ return 0;
+}
+
+static int _activate_check(struct crypt_device *cd,
+ const struct bitlk_metadata *params)
+{
+ const struct bitlk_vmk *next_vmk = NULL;
+
+ if (!params->state) {
+ log_err(cd, _("This BITLK device is in an unsupported state and cannot be activated."));
+ return -ENOTSUP;
+ }
+
+ if (params->type != BITLK_ENCRYPTION_TYPE_NORMAL) {
+ log_err(cd, _("BITLK devices with type '%s' cannot be activated."), get_bitlk_type_string(params->type));
+ return -ENOTSUP;
+ }
+
+ next_vmk = params->vmks;
+ while (next_vmk) {
+ if (next_vmk->protection == BITLK_PROTECTION_CLEAR_KEY) {
+ log_err(cd, _("Activation of partially decrypted BITLK device is not supported."));
+ return -ENOTSUP;
+ }
+ next_vmk = next_vmk->next;
+ }
+
+ return 0;
+}
+
+static int _activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *open_fvek_key,
+ const struct bitlk_metadata *params,
+ uint32_t flags)
+{
+ int r = 0;
+ int i = 0;
+ int j = 0;
+ int min = 0;
+ int num_segments = 0;
+ struct crypt_dm_active_device dmd = {
+ .flags = flags,
+ };
+ struct dm_target *next_segment = NULL;
+ struct segment segments[MAX_BITLK_SEGMENTS] = {};
+ struct segment temp;
+ uint64_t next_start = 0;
+ uint64_t next_end = 0;
+ uint64_t last_segment = 0;
+ uint32_t dmt_flags = 0;
+
+ r = _activate_check(cd, params);
+ if (r)
+ return r;
+
+ r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL,
+ 0, &dmd.size, &dmd.flags);
+ if (r)
+ return r;
+
+ if (dmd.size * SECTOR_SIZE != params->volume_size)
+ log_std(cd, _("WARNING: BitLocker volume size %" PRIu64 " does not match the underlying device size %" PRIu64 ""),
+ params->volume_size,
+ dmd.size * SECTOR_SIZE);
+
+ /* there will be always 4 dm-zero segments: 3x metadata, 1x FS header */
+ for (i = 0; i < 3; i++) {
+ segments[num_segments].offset = params->metadata_offset[i] / SECTOR_SIZE;
+ segments[num_segments].length = BITLK_FVE_METADATA_SIZE / SECTOR_SIZE;
+ segments[num_segments].iv_offset = 0;
+ segments[num_segments].type = BITLK_SEGTYPE_ZERO;
+ num_segments++;
+ }
+ segments[num_segments].offset = params->volume_header_offset / SECTOR_SIZE;
+ segments[num_segments].length = params->volume_header_size / SECTOR_SIZE;
+ segments[num_segments].iv_offset = 0;
+ segments[num_segments].type = BITLK_SEGTYPE_ZERO;
+ num_segments++;
+
+ /* filesystem header (moved from the special location) */
+ segments[num_segments].offset = 0;
+ segments[num_segments].length = params->volume_header_size / SECTOR_SIZE;
+ segments[num_segments].iv_offset = params->volume_header_offset / SECTOR_SIZE;
+ segments[num_segments].type = BITLK_SEGTYPE_CRYPT;
+ num_segments++;
+
+ /* now fill gaps between the dm-zero segments with dm-crypt */
+ last_segment = params->volume_header_size / SECTOR_SIZE;
+ while (true) {
+ next_start = dmd.size;
+ next_end = dmd.size;
+
+ /* start of the next segment: end of the first existing segment after the last added */
+ for (i = 0; i < num_segments; i++)
+ if (segments[i].offset + segments[i].length < next_start && segments[i].offset + segments[i].length >= last_segment)
+ next_start = segments[i].offset + segments[i].length;
+
+ /* end of the next segment: start of the next segment after start we found above */
+ for (i = 0; i < num_segments; i++)
+ if (segments[i].offset < next_end && segments[i].offset >= next_start)
+ next_end = segments[i].offset;
+
+ /* two zero segments next to each other, just bump the last_segment
+ so the algorithm moves */
+ if (next_end - next_start == 0) {
+ last_segment = next_end + 1;
+ continue;
+ }
+
+ segments[num_segments].offset = next_start;
+ segments[num_segments].length = next_end - next_start;
+ segments[num_segments].iv_offset = next_start;
+ segments[num_segments].type = BITLK_SEGTYPE_CRYPT;
+ last_segment = next_end;
+ num_segments++;
+
+ if (next_end == dmd.size)
+ break;
+
+ if (num_segments == 10) {
+ log_dbg(cd, "Failed to calculate number of dm-crypt segments for open.");
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* device mapper needs the segment sorted */
+ for (i = 0; i < num_segments - 1; i++) {
+ min = i;
+ for (j = i + 1; j < num_segments; j++)
+ if (segments[j].offset < segments[min].offset)
+ min = j;
+
+ if (min != i) {
+ temp.offset = segments[min].offset;
+ temp.length = segments[min].length;
+ temp.iv_offset = segments[min].iv_offset;
+ temp.type = segments[min].type;
+
+ segments[min].offset = segments[i].offset;
+ segments[min].length = segments[i].length;
+ segments[min].iv_offset = segments[i].iv_offset;
+ segments[min].type = segments[i].type;
+
+ segments[i].offset = temp.offset;
+ segments[i].length = temp.length;
+ segments[i].iv_offset = temp.iv_offset;
+ segments[i].type = temp.type;
+ }
+ }
+
+ if (params->sector_size != SECTOR_SIZE)
+ dmd.flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
+
+ r = dm_targets_allocate(&dmd.segment, num_segments);
+ if (r)
+ goto out;
+ next_segment = &dmd.segment;
+
+ for (i = 0; i < num_segments; i++) {
+ if (segments[i].type == BITLK_SEGTYPE_ZERO)
+ r = dm_zero_target_set(next_segment,
+ segments[i].offset,
+ segments[i].length);
+ else if (segments[i].type == BITLK_SEGTYPE_CRYPT)
+ r = dm_crypt_target_set(next_segment,
+ segments[i].offset,
+ segments[i].length,
+ crypt_data_device(cd),
+ open_fvek_key,
+ crypt_get_cipher_spec(cd),
+ segments[i].iv_offset,
+ segments[i].iv_offset,
+ NULL, 0,
+ params->sector_size);
+ if (r)
+ goto out;
+
+ next_segment = next_segment->next;
+ }
+
+ log_dbg(cd, "Trying to activate BITLK on device %s%s%s.",
+ device_path(crypt_data_device(cd)), name ? " with name " :"", name ?: "");
+
+ r = dm_create_device(cd, name, CRYPT_BITLK, &dmd);
+ if (r < 0) {
+ dm_flags(cd, DM_CRYPT, &dmt_flags);
+ if (!strcmp(params->cipher_mode, "cbc-eboiv") && !(dmt_flags & DM_BITLK_EBOIV_SUPPORTED)) {
+ log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for BITLK IV."));
+ r = -ENOTSUP;
+ }
+ if (!strcmp(params->cipher_mode, "cbc-elephant") && !(dmt_flags & DM_BITLK_ELEPHANT_SUPPORTED)) {
+ log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."));
+ r = -ENOTSUP;
+ }
+ if ((dmd.flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED)) {
+ log_err(cd, _("Cannot activate device, kernel dm-crypt is missing support for large sector size."));
+ r = -ENOTSUP;
+ }
+ if (dm_flags(cd, DM_ZERO, &dmt_flags) < 0) {
+ log_err(cd, _("Cannot activate device, kernel dm-zero module is missing."));
+ r = -ENOTSUP;
+ }
+ }
+out:
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int BITLK_activate_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ const char *password,
+ size_t passwordLen,
+ const struct bitlk_metadata *params,
+ uint32_t flags)
+{
+ int r = 0;
+ struct volume_key *open_fvek_key = NULL;
+
+ r = _activate_check(cd, params);
+ if (r)
+ return r;
+
+ r = BITLK_get_volume_key(cd, password, passwordLen, params, &open_fvek_key);
+ if (r < 0)
+ goto out;
+
+ /* Password verify only */
+ if (!name)
+ goto out;
+
+ r = _activate(cd, name, open_fvek_key, params, flags);
+out:
+ crypt_free_volume_key(open_fvek_key);
+ return r;
+}
+
+int BITLK_activate_by_volume_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size,
+ const struct bitlk_metadata *params,
+ uint32_t flags)
+{
+ int r = 0;
+ struct volume_key *open_fvek_key = NULL;
+
+ r = _activate_check(cd, params);
+ if (r)
+ return r;
+
+ open_fvek_key = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!open_fvek_key)
+ return -ENOMEM;
+
+ r = _activate(cd, name, open_fvek_key, params, flags);
+
+ crypt_free_volume_key(open_fvek_key);
+ return r;
+}
diff --git a/lib/bitlk/bitlk.h b/lib/bitlk/bitlk.h
new file mode 100644
index 0000000..54d3dc7
--- /dev/null
+++ b/lib/bitlk/bitlk.h
@@ -0,0 +1,148 @@
+/*
+ * BITLK (BitLocker-compatible) header definition
+ *
+ * Copyright (C) 2019-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2019-2023 Milan Broz
+ * Copyright (C) 2019-2023 Vojtech Trefny
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_BITLK_H
+#define _CRYPTSETUP_BITLK_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+struct crypt_device;
+struct device;
+struct volume_key;
+
+#define BITLK_NONCE_SIZE 12
+#define BITLK_SALT_SIZE 16
+#define BITLK_VMK_MAC_TAG_SIZE 16
+
+#define BITLK_STATE_NORMAL 0x0004
+
+typedef enum {
+ BITLK_ENCRYPTION_TYPE_NORMAL = 0,
+ BITLK_ENCRYPTION_TYPE_EOW,
+ BITLK_ENCRYPTION_TYPE_UNKNOWN,
+} BITLKEncryptionType;
+
+typedef enum {
+ BITLK_PROTECTION_CLEAR_KEY = 0,
+ BITLK_PROTECTION_TPM,
+ BITLK_PROTECTION_STARTUP_KEY,
+ BITLK_PROTECTION_TPM_PIN,
+ BITLK_PROTECTION_RECOVERY_PASSPHRASE,
+ BITLK_PROTECTION_PASSPHRASE,
+ BITLK_PROTECTION_SMART_CARD,
+ BITLK_PROTECTION_UNKNOWN,
+} BITLKVMKProtection;
+
+typedef enum {
+ BITLK_ENTRY_TYPE_PROPERTY = 0x0000,
+ BITLK_ENTRY_TYPE_VMK = 0x0002,
+ BITLK_ENTRY_TYPE_FVEK = 0x0003,
+ BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006,
+ BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007,
+ BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f,
+ BITLK_ENTRY_TYPE_VOLUME_GUID = 0x0019,
+} BITLKFVEEntryType;
+
+typedef enum {
+ BITLK_ENTRY_VALUE_ERASED = 0x0000,
+ BITLK_ENTRY_VALUE_KEY = 0x0001,
+ BITLK_ENTRY_VALUE_STRING = 0x0002,
+ BITLK_ENTRY_VALUE_STRETCH_KEY = 0x0003,
+ BITLK_ENTRY_VALUE_USE_KEY = 0x0004,
+ BITLK_ENTRY_VALUE_ENCRYPTED_KEY = 0x0005,
+ BITLK_ENTRY_VALUE_TPM_KEY = 0x0006,
+ BITLK_ENTRY_VALUE_VALIDATION = 0x0007,
+ BITLK_ENTRY_VALUE_VMK = 0x0008,
+ BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009,
+ BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f,
+ BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015,
+ BITLK_ENTRY_VALUE_GUID = 0x0017,
+} BITLKFVEEntryValue;
+
+struct bitlk_vmk {
+ char *guid;
+ char *name;
+ BITLKVMKProtection protection;
+ uint8_t salt[BITLK_SALT_SIZE];
+ uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
+ uint8_t nonce[BITLK_NONCE_SIZE];
+ struct volume_key *vk;
+ struct bitlk_vmk *next;
+};
+
+struct bitlk_fvek {
+ uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
+ uint8_t nonce[BITLK_NONCE_SIZE];
+ struct volume_key *vk;
+};
+
+struct bitlk_metadata {
+ uint16_t sector_size;
+ uint64_t volume_size;
+ bool togo;
+ bool state;
+ BITLKEncryptionType type;
+ const char *cipher;
+ const char *cipher_mode;
+ uint16_t key_size;
+ char *guid;
+ uint64_t creation_time;
+ char *description;
+ uint64_t metadata_offset[3];
+ uint32_t metadata_version;
+ uint64_t volume_header_offset;
+ uint64_t volume_header_size;
+ struct bitlk_vmk *vmks;
+ struct bitlk_fvek *fvek;
+};
+
+int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params);
+
+int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_metadata *params);
+
+int BITLK_get_volume_key(struct crypt_device *cd,
+ const char *password,
+ size_t passwordLen,
+ const struct bitlk_metadata *params,
+ struct volume_key **open_fvek_key);
+
+int BITLK_activate_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ const char *password,
+ size_t passwordLen,
+ const struct bitlk_metadata *params,
+ uint32_t flags);
+
+int BITLK_activate_by_volume_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size,
+ const struct bitlk_metadata *params,
+ uint32_t flags);
+
+void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek);
+void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk);
+void BITLK_bitlk_metadata_free(struct bitlk_metadata *params);
+
+#endif
diff --git a/lib/bitops.h b/lib/bitops.h
new file mode 100644
index 0000000..a991687
--- /dev/null
+++ b/lib/bitops.h
@@ -0,0 +1,123 @@
+/*
+ * No copyright is claimed. This code is in the public domain; do with
+ * it what you wish.
+ *
+ * Written by Karel Zak <kzak@redhat.com>
+ */
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#include <stdint.h>
+#include <sys/param.h>
+
+#if defined(HAVE_BYTESWAP_H)
+# include <byteswap.h>
+#endif
+
+#if defined(HAVE_ENDIAN_H)
+# include <endian.h>
+#elif defined(HAVE_SYS_ENDIAN_H) /* BSDs have them here */
+# include <sys/endian.h>
+#endif
+
+#if defined(__OpenBSD__)
+# include <sys/types.h>
+# define be16toh(x) betoh16(x)
+# define be32toh(x) betoh32(x)
+# define be64toh(x) betoh64(x)
+#endif
+
+/*
+ * Fallbacks
+ */
+#ifndef bswap_16
+# define bswap_16(x) ((((x) & 0x00FF) << 8) | \
+ (((x) & 0xFF00) >> 8))
+#endif
+
+#ifndef bswap_32
+# define bswap_32(x) ((((x) & 0x000000FF) << 24) | \
+ (((x) & 0x0000FF00) << 8) | \
+ (((x) & 0x00FF0000) >> 8) | \
+ (((x) & 0xFF000000) >> 24))
+#endif
+
+#ifndef bswap_64
+# define bswap_64(x) ((((x) & 0x00000000000000FFULL) << 56) | \
+ (((x) & 0x000000000000FF00ULL) << 40) | \
+ (((x) & 0x0000000000FF0000ULL) << 24) | \
+ (((x) & 0x00000000FF000000ULL) << 8) | \
+ (((x) & 0x000000FF00000000ULL) >> 8) | \
+ (((x) & 0x0000FF0000000000ULL) >> 24) | \
+ (((x) & 0x00FF000000000000ULL) >> 40) | \
+ (((x) & 0xFF00000000000000ULL) >> 56))
+#endif
+
+#ifndef htobe16
+# if !defined(WORDS_BIGENDIAN)
+# define htobe16(x) bswap_16 (x)
+# define htole16(x) (x)
+# define be16toh(x) bswap_16 (x)
+# define le16toh(x) (x)
+# define htobe32(x) bswap_32 (x)
+# define htole32(x) (x)
+# define be32toh(x) bswap_32 (x)
+# define le32toh(x) (x)
+# define htobe64(x) bswap_64 (x)
+# define htole64(x) (x)
+# define be64toh(x) bswap_64 (x)
+# define le64toh(x) (x)
+# else
+# define htobe16(x) (x)
+# define htole16(x) bswap_16 (x)
+# define be16toh(x) (x)
+# define le16toh(x) bswap_16 (x)
+# define htobe32(x) (x)
+# define htole32(x) bswap_32 (x)
+# define be32toh(x) (x)
+# define le32toh(x) bswap_32 (x)
+# define htobe64(x) (x)
+# define htole64(x) bswap_64 (x)
+# define be64toh(x) (x)
+# define le64toh(x) bswap_64 (x)
+# endif
+#endif
+
+/*
+ * Byte swab macros (based on linux/byteorder/swab.h)
+ */
+#define swab16(x) bswap_16(x)
+#define swab32(x) bswap_32(x)
+#define swab64(x) bswap_64(x)
+
+#define cpu_to_le16(x) ((uint16_t) htole16(x))
+#define cpu_to_le32(x) ((uint32_t) htole32(x))
+#define cpu_to_le64(x) ((uint64_t) htole64(x))
+
+#define cpu_to_be16(x) ((uint16_t) htobe16(x))
+#define cpu_to_be32(x) ((uint32_t) htobe32(x))
+#define cpu_to_be64(x) ((uint64_t) htobe64(x))
+
+#define le16_to_cpu(x) ((uint16_t) le16toh(x))
+#define le32_to_cpu(x) ((uint32_t) le32toh(x))
+#define le64_to_cpu(x) ((uint64_t) le64toh(x))
+
+#define be16_to_cpu(x) ((uint16_t) be16toh(x))
+#define be32_to_cpu(x) ((uint32_t) be32toh(x))
+#define be64_to_cpu(x) ((uint64_t) be64toh(x))
+
+/*
+ * Bit map related macros. Usually provided by libc.
+ */
+#ifndef NBBY
+# define NBBY CHAR_BIT
+#endif
+
+#ifndef setbit
+# define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+# define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+# define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+# define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+#endif
+
+#endif /* BITOPS_H */
diff --git a/lib/crypt_plain.c b/lib/crypt_plain.c
new file mode 100644
index 0000000..c839b09
--- /dev/null
+++ b/lib/crypt_plain.c
@@ -0,0 +1,117 @@
+/*
+ * cryptsetup plain device helper functions
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "libcryptsetup.h"
+#include "internal.h"
+
+static int hash(const char *hash_name, size_t key_size, char *key,
+ size_t passphrase_size, const char *passphrase)
+{
+ struct crypt_hash *md = NULL;
+ size_t len;
+ int round, i, r = 0;
+
+ if (crypt_hash_init(&md, hash_name))
+ return -ENOENT;
+
+ len = crypt_hash_size(hash_name);
+
+ for(round = 0; key_size && !r; round++) {
+ /* hack from hashalot to avoid null bytes in key */
+ for(i = 0; i < round; i++)
+ if (crypt_hash_write(md, "A", 1))
+ r = 1;
+
+ if (crypt_hash_write(md, passphrase, passphrase_size))
+ r = 1;
+
+ if (len > key_size)
+ len = key_size;
+
+ if (crypt_hash_final(md, key, len))
+ r = 1;
+
+ key += len;
+ key_size -= len;
+ }
+
+ crypt_hash_destroy(md);
+ return r;
+}
+
+#define PLAIN_HASH_LEN_MAX 256
+
+int crypt_plain_hash(struct crypt_device *cd,
+ const char *hash_name,
+ char *key, size_t key_size,
+ const char *passphrase, size_t passphrase_size)
+{
+ char hash_name_buf[PLAIN_HASH_LEN_MAX], *s;
+ size_t hash_size, pad_size;
+ int r;
+
+ log_dbg(cd, "Plain: hashing passphrase using %s.", hash_name);
+
+ if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX)
+ return -EINVAL;
+ strncpy(hash_name_buf, hash_name, PLAIN_HASH_LEN_MAX);
+ hash_name_buf[PLAIN_HASH_LEN_MAX - 1] = '\0';
+
+ /* hash[:hash_length] */
+ if ((s = strchr(hash_name_buf, ':'))) {
+ *s = '\0';
+ s++;
+ if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
+ log_dbg(cd, "Hash length is not a number");
+ return -EINVAL;
+ }
+ if (hash_size > key_size) {
+ log_dbg(cd, "Hash length %zd > key length %zd",
+ hash_size, key_size);
+ return -EINVAL;
+ }
+ pad_size = key_size - hash_size;
+ } else {
+ hash_size = key_size;
+ pad_size = 0;
+ }
+
+ /* No hash, copy passphrase directly */
+ if (!strcmp(hash_name_buf, "plain")) {
+ if (passphrase_size < hash_size) {
+ log_dbg(cd, "Too short plain passphrase.");
+ return -EINVAL;
+ }
+ memcpy(key, passphrase, hash_size);
+ r = 0;
+ } else
+ r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase);
+
+ if (r == 0 && pad_size)
+ memset(key + hash_size, 0, pad_size);
+
+ return r;
+}
diff --git a/lib/crypto_backend/Makemodule.am b/lib/crypto_backend/Makemodule.am
new file mode 100644
index 0000000..7507763
--- /dev/null
+++ b/lib/crypto_backend/Makemodule.am
@@ -0,0 +1,41 @@
+noinst_LTLIBRARIES += libcrypto_backend.la
+
+libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@
+
+libcrypto_backend_la_SOURCES = \
+ lib/crypto_backend/crypto_backend.h \
+ lib/crypto_backend/crypto_backend_internal.h \
+ lib/crypto_backend/crypto_cipher_kernel.c \
+ lib/crypto_backend/crypto_storage.c \
+ lib/crypto_backend/pbkdf_check.c \
+ lib/crypto_backend/crc32.c \
+ lib/crypto_backend/base64.c \
+ lib/crypto_backend/utf8.c \
+ lib/crypto_backend/argon2_generic.c \
+ lib/crypto_backend/cipher_generic.c \
+ lib/crypto_backend/cipher_check.c
+
+if CRYPTO_BACKEND_GCRYPT
+libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_gcrypt.c
+endif
+if CRYPTO_BACKEND_OPENSSL
+libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_openssl.c
+endif
+if CRYPTO_BACKEND_NSS
+libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nss.c
+endif
+if CRYPTO_BACKEND_KERNEL
+libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_kernel.c
+endif
+if CRYPTO_BACKEND_NETTLE
+libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nettle.c
+endif
+
+if CRYPTO_INTERNAL_PBKDF2
+libcrypto_backend_la_SOURCES += lib/crypto_backend/pbkdf2_generic.c
+endif
+
+if CRYPTO_INTERNAL_ARGON2
+libcrypto_backend_la_DEPENDENCIES = libargon2.la
+libcrypto_backend_la_LIBADD = libargon2.la
+endif
diff --git a/lib/crypto_backend/argon2/LICENSE b/lib/crypto_backend/argon2/LICENSE
new file mode 100644
index 0000000..de14cd2
--- /dev/null
+++ b/lib/crypto_backend/argon2/LICENSE
@@ -0,0 +1,30 @@
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
+
+ the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
+ moral rights retained by the original author(s) and/or performer(s);
+ publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
+ rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
+ rights protecting the extraction, dissemination, use and reuse of data in a Work;
+ database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
+ other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
+ Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
+ Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
+ Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
diff --git a/lib/crypto_backend/argon2/Makemodule.am b/lib/crypto_backend/argon2/Makemodule.am
new file mode 100644
index 0000000..6fef2f1
--- /dev/null
+++ b/lib/crypto_backend/argon2/Makemodule.am
@@ -0,0 +1,30 @@
+noinst_LTLIBRARIES += libargon2.la
+
+libargon2_la_CFLAGS = $(AM_CFLAGS) -std=c89 -pthread -O3
+libargon2_la_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I lib/crypto_backend/argon2 \
+ -I lib/crypto_backend/argon2/blake2
+
+libargon2_la_SOURCES = \
+ lib/crypto_backend/argon2/blake2/blake2b.c \
+ lib/crypto_backend/argon2/blake2/blake2.h \
+ lib/crypto_backend/argon2/blake2/blake2-impl.h \
+ lib/crypto_backend/argon2/argon2.c \
+ lib/crypto_backend/argon2/argon2.h \
+ lib/crypto_backend/argon2/core.c \
+ lib/crypto_backend/argon2/core.h \
+ lib/crypto_backend/argon2/encoding.c \
+ lib/crypto_backend/argon2/encoding.h \
+ lib/crypto_backend/argon2/thread.c \
+ lib/crypto_backend/argon2/thread.h
+
+if CRYPTO_INTERNAL_SSE_ARGON2
+libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-opt.h \
+ lib/crypto_backend/argon2/opt.c
+else
+libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-ref.h \
+ lib/crypto_backend/argon2/ref.c
+endif
+
+EXTRA_DIST += lib/crypto_backend/argon2/LICENSE
+EXTRA_DIST += lib/crypto_backend/argon2/README
diff --git a/lib/crypto_backend/argon2/README b/lib/crypto_backend/argon2/README
new file mode 100644
index 0000000..5376b52
--- /dev/null
+++ b/lib/crypto_backend/argon2/README
@@ -0,0 +1,5 @@
+This is bundled Argon2 algorithm library, copied from
+ https://github.com/P-H-C/phc-winner-argon2
+
+For more info see Password Hashing Competition site:
+ https://password-hashing.net/
diff --git a/lib/crypto_backend/argon2/argon2.c b/lib/crypto_backend/argon2/argon2.c
new file mode 100644
index 0000000..c784fca
--- /dev/null
+++ b/lib/crypto_backend/argon2/argon2.c
@@ -0,0 +1,458 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "argon2.h"
+#include "encoding.h"
+#include "core.h"
+
+/* to silent gcc -Wcast-qual for const cast */
+#define CONST_CAST(x) (x)(uintptr_t)
+
+const char *argon2_type2string(argon2_type type, int uppercase) {
+ switch (type) {
+ case Argon2_d:
+ return uppercase ? "Argon2d" : "argon2d";
+ case Argon2_i:
+ return uppercase ? "Argon2i" : "argon2i";
+ case Argon2_id:
+ return uppercase ? "Argon2id" : "argon2id";
+ }
+
+ return NULL;
+}
+
+int argon2_ctx(argon2_context *context, argon2_type type) {
+ /* 1. Validate all inputs */
+ int result = validate_inputs(context);
+ uint32_t memory_blocks, segment_length;
+ argon2_instance_t instance;
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+
+ if (Argon2_d != type && Argon2_i != type && Argon2_id != type) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+
+ /* 2. Align memory size */
+ /* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
+ memory_blocks = context->m_cost;
+
+ if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
+ memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
+ }
+
+ segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
+ /* Ensure that all segments have equal length */
+ memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
+
+ instance.version = context->version;
+ instance.memory = NULL;
+ instance.passes = context->t_cost;
+ instance.memory_blocks = memory_blocks;
+ instance.segment_length = segment_length;
+ instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
+ instance.lanes = context->lanes;
+ instance.threads = context->threads;
+ instance.type = type;
+
+ if (instance.threads > instance.lanes) {
+ instance.threads = instance.lanes;
+ }
+
+ /* 3. Initialization: Hashing inputs, allocating memory, filling first
+ * blocks
+ */
+ result = initialize(&instance, context);
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+
+ /* 4. Filling memory */
+ result = fill_memory_blocks(&instance);
+
+ if (ARGON2_OK != result) {
+ return result;
+ }
+ /* 5. Finalization */
+ finalize(context, &instance);
+
+ return ARGON2_OK;
+}
+
+int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt, const size_t saltlen,
+ void *hash, const size_t hashlen, char *encoded,
+ const size_t encodedlen, argon2_type type,
+ const uint32_t version){
+
+ argon2_context context;
+ int result;
+ uint8_t *out;
+
+ if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ if (saltlen > ARGON2_MAX_SALT_LENGTH) {
+ return ARGON2_SALT_TOO_LONG;
+ }
+
+ if (hashlen > ARGON2_MAX_OUTLEN) {
+ return ARGON2_OUTPUT_TOO_LONG;
+ }
+
+ if (hashlen < ARGON2_MIN_OUTLEN) {
+ return ARGON2_OUTPUT_TOO_SHORT;
+ }
+
+ out = malloc(hashlen);
+ if (!out) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ context.out = (uint8_t *)out;
+ context.outlen = (uint32_t)hashlen;
+ context.pwd = CONST_CAST(uint8_t *)pwd;
+ context.pwdlen = (uint32_t)pwdlen;
+ context.salt = CONST_CAST(uint8_t *)salt;
+ context.saltlen = (uint32_t)saltlen;
+ context.secret = NULL;
+ context.secretlen = 0;
+ context.ad = NULL;
+ context.adlen = 0;
+ context.t_cost = t_cost;
+ context.m_cost = m_cost;
+ context.lanes = parallelism;
+ context.threads = parallelism;
+ context.allocate_cbk = NULL;
+ context.free_cbk = NULL;
+ context.flags = ARGON2_DEFAULT_FLAGS;
+ context.version = version;
+
+ result = argon2_ctx(&context, type);
+
+ if (result != ARGON2_OK) {
+ clear_internal_memory(out, hashlen);
+ free(out);
+ return result;
+ }
+
+ /* if raw hash requested, write it */
+ if (hash) {
+ memcpy(hash, out, hashlen);
+ }
+
+ /* if encoding requested, write it */
+ if (encoded && encodedlen) {
+ if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
+ clear_internal_memory(out, hashlen); /* wipe buffers if error */
+ clear_internal_memory(encoded, encodedlen);
+ free(out);
+ return ARGON2_ENCODING_FAIL;
+ }
+ }
+ clear_internal_memory(out, hashlen);
+ free(out);
+
+ return ARGON2_OK;
+}
+
+int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen,
+ char *encoded, const size_t encodedlen) {
+
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_i,
+ ARGON2_VERSION_NUMBER);
+}
+
+int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash, const size_t hashlen) {
+
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER);
+}
+
+int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen,
+ char *encoded, const size_t encodedlen) {
+
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_d,
+ ARGON2_VERSION_NUMBER);
+}
+
+int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash, const size_t hashlen) {
+
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER);
+}
+
+int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, const size_t hashlen,
+ char *encoded, const size_t encodedlen) {
+
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ NULL, hashlen, encoded, encodedlen, Argon2_id,
+ ARGON2_VERSION_NUMBER);
+}
+
+int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash, const size_t hashlen) {
+ return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
+ hash, hashlen, NULL, 0, Argon2_id,
+ ARGON2_VERSION_NUMBER);
+}
+
+static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
+ size_t i;
+ uint8_t d = 0U;
+
+ for (i = 0U; i < len; i++) {
+ d |= b1[i] ^ b2[i];
+ }
+ return (int)((1 & ((d - 1) >> 8)) - 1);
+}
+
+int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
+ argon2_type type) {
+
+ argon2_context ctx;
+ uint8_t *desired_result = NULL;
+
+ int ret = ARGON2_OK;
+
+ size_t encoded_len;
+ uint32_t max_field_len;
+
+ if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ if (encoded == NULL) {
+ return ARGON2_DECODING_FAIL;
+ }
+
+ encoded_len = strlen(encoded);
+ if (encoded_len > UINT32_MAX) {
+ return ARGON2_DECODING_FAIL;
+ }
+
+ /* No field can be longer than the encoded length */
+ /* coverity[strlen_assign] */
+ max_field_len = (uint32_t)encoded_len;
+
+ ctx.saltlen = max_field_len;
+ ctx.outlen = max_field_len;
+
+ ctx.salt = malloc(ctx.saltlen);
+ ctx.out = malloc(ctx.outlen);
+ if (!ctx.salt || !ctx.out) {
+ ret = ARGON2_MEMORY_ALLOCATION_ERROR;
+ goto fail;
+ }
+
+ ctx.pwd = CONST_CAST(uint8_t *)pwd;
+ ctx.pwdlen = (uint32_t)pwdlen;
+
+ ret = decode_string(&ctx, encoded, type);
+ if (ret != ARGON2_OK) {
+ goto fail;
+ }
+
+ /* Set aside the desired result, and get a new buffer. */
+ desired_result = ctx.out;
+ ctx.out = malloc(ctx.outlen);
+ if (!ctx.out) {
+ ret = ARGON2_MEMORY_ALLOCATION_ERROR;
+ goto fail;
+ }
+
+ ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
+ if (ret != ARGON2_OK) {
+ goto fail;
+ }
+
+fail:
+ free(ctx.salt);
+ free(ctx.out);
+ free(desired_result);
+
+ return ret;
+}
+
+int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
+
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
+}
+
+int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
+
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
+}
+
+int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
+
+ return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
+}
+
+int argon2d_ctx(argon2_context *context) {
+ return argon2_ctx(context, Argon2_d);
+}
+
+int argon2i_ctx(argon2_context *context) {
+ return argon2_ctx(context, Argon2_i);
+}
+
+int argon2id_ctx(argon2_context *context) {
+ return argon2_ctx(context, Argon2_id);
+}
+
+int argon2_verify_ctx(argon2_context *context, const char *hash,
+ argon2_type type) {
+ int ret = argon2_ctx(context, type);
+ if (ret != ARGON2_OK) {
+ return ret;
+ }
+
+ if (argon2_compare(CONST_CAST(uint8_t *)hash, context->out, context->outlen)) {
+ return ARGON2_VERIFY_MISMATCH;
+ }
+
+ return ARGON2_OK;
+}
+
+int argon2d_verify_ctx(argon2_context *context, const char *hash) {
+ return argon2_verify_ctx(context, hash, Argon2_d);
+}
+
+int argon2i_verify_ctx(argon2_context *context, const char *hash) {
+ return argon2_verify_ctx(context, hash, Argon2_i);
+}
+
+int argon2id_verify_ctx(argon2_context *context, const char *hash) {
+ return argon2_verify_ctx(context, hash, Argon2_id);
+}
+
+const char *argon2_error_message(int error_code) {
+ switch (error_code) {
+ case ARGON2_OK:
+ return "OK";
+ case ARGON2_OUTPUT_PTR_NULL:
+ return "Output pointer is NULL";
+ case ARGON2_OUTPUT_TOO_SHORT:
+ return "Output is too short";
+ case ARGON2_OUTPUT_TOO_LONG:
+ return "Output is too long";
+ case ARGON2_PWD_TOO_SHORT:
+ return "Password is too short";
+ case ARGON2_PWD_TOO_LONG:
+ return "Password is too long";
+ case ARGON2_SALT_TOO_SHORT:
+ return "Salt is too short";
+ case ARGON2_SALT_TOO_LONG:
+ return "Salt is too long";
+ case ARGON2_AD_TOO_SHORT:
+ return "Associated data is too short";
+ case ARGON2_AD_TOO_LONG:
+ return "Associated data is too long";
+ case ARGON2_SECRET_TOO_SHORT:
+ return "Secret is too short";
+ case ARGON2_SECRET_TOO_LONG:
+ return "Secret is too long";
+ case ARGON2_TIME_TOO_SMALL:
+ return "Time cost is too small";
+ case ARGON2_TIME_TOO_LARGE:
+ return "Time cost is too large";
+ case ARGON2_MEMORY_TOO_LITTLE:
+ return "Memory cost is too small";
+ case ARGON2_MEMORY_TOO_MUCH:
+ return "Memory cost is too large";
+ case ARGON2_LANES_TOO_FEW:
+ return "Too few lanes";
+ case ARGON2_LANES_TOO_MANY:
+ return "Too many lanes";
+ case ARGON2_PWD_PTR_MISMATCH:
+ return "Password pointer is NULL, but password length is not 0";
+ case ARGON2_SALT_PTR_MISMATCH:
+ return "Salt pointer is NULL, but salt length is not 0";
+ case ARGON2_SECRET_PTR_MISMATCH:
+ return "Secret pointer is NULL, but secret length is not 0";
+ case ARGON2_AD_PTR_MISMATCH:
+ return "Associated data pointer is NULL, but ad length is not 0";
+ case ARGON2_MEMORY_ALLOCATION_ERROR:
+ return "Memory allocation error";
+ case ARGON2_FREE_MEMORY_CBK_NULL:
+ return "The free memory callback is NULL";
+ case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
+ return "The allocate memory callback is NULL";
+ case ARGON2_INCORRECT_PARAMETER:
+ return "Argon2_Context context is NULL";
+ case ARGON2_INCORRECT_TYPE:
+ return "There is no such version of Argon2";
+ case ARGON2_OUT_PTR_MISMATCH:
+ return "Output pointer mismatch";
+ case ARGON2_THREADS_TOO_FEW:
+ return "Not enough threads";
+ case ARGON2_THREADS_TOO_MANY:
+ return "Too many threads";
+ case ARGON2_MISSING_ARGS:
+ return "Missing arguments";
+ case ARGON2_ENCODING_FAIL:
+ return "Encoding failed";
+ case ARGON2_DECODING_FAIL:
+ return "Decoding failed";
+ case ARGON2_THREAD_FAIL:
+ return "Threading failure";
+ case ARGON2_DECODING_LENGTH_FAIL:
+ return "Some of encoded parameters are too long or too short";
+ case ARGON2_VERIFY_MISMATCH:
+ return "The password does not match the supplied hash";
+ default:
+ return "Unknown error code";
+ }
+}
+
+size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
+ uint32_t saltlen, uint32_t hashlen, argon2_type type) {
+ if (!argon2_type2string(type, 0))
+ return 0;
+ return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
+ numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
+ b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1;
+}
diff --git a/lib/crypto_backend/argon2/argon2.h b/lib/crypto_backend/argon2/argon2.h
new file mode 100644
index 0000000..20df933
--- /dev/null
+++ b/lib/crypto_backend/argon2/argon2.h
@@ -0,0 +1,437 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ARGON2_H
+#define ARGON2_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <limits.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Symbols visibility control */
+#ifdef A2_VISCTL
+#define ARGON2_PUBLIC __attribute__((visibility("default")))
+#define ARGON2_LOCAL __attribute__ ((visibility ("hidden")))
+#elif _MSC_VER
+#define ARGON2_PUBLIC __declspec(dllexport)
+#define ARGON2_LOCAL
+#else
+#define ARGON2_PUBLIC
+#define ARGON2_LOCAL
+#endif
+
+/*
+ * Argon2 input parameter restrictions
+ */
+
+/* Minimum and maximum number of lanes (degree of parallelism) */
+#define ARGON2_MIN_LANES UINT32_C(1)
+#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
+
+/* Minimum and maximum number of threads */
+#define ARGON2_MIN_THREADS UINT32_C(1)
+#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
+
+/* Number of synchronization points between lanes per pass */
+#define ARGON2_SYNC_POINTS UINT32_C(4)
+
+/* Minimum and maximum digest size in bytes */
+#define ARGON2_MIN_OUTLEN UINT32_C(4)
+#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
+#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
+
+#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
+/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */
+#define ARGON2_MAX_MEMORY_BITS \
+ ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
+#define ARGON2_MAX_MEMORY \
+ ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
+
+/* Minimum and maximum number of passes */
+#define ARGON2_MIN_TIME UINT32_C(1)
+#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum password length in bytes */
+#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
+#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum associated data length in bytes */
+#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
+#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum salt length in bytes */
+#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
+#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
+
+/* Minimum and maximum key length in bytes */
+#define ARGON2_MIN_SECRET UINT32_C(0)
+#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
+
+/* Flags to determine which fields are securely wiped (default = no wipe). */
+#define ARGON2_DEFAULT_FLAGS UINT32_C(0)
+#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
+#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
+
+/* Global flag to determine if we are wiping internal memory buffers. This flag
+ * is defined in core.c and defaults to 1 (wipe internal memory). */
+extern int FLAG_clear_internal_memory;
+
+/* Error codes */
+typedef enum Argon2_ErrorCodes {
+ ARGON2_OK = 0,
+
+ ARGON2_OUTPUT_PTR_NULL = -1,
+
+ ARGON2_OUTPUT_TOO_SHORT = -2,
+ ARGON2_OUTPUT_TOO_LONG = -3,
+
+ ARGON2_PWD_TOO_SHORT = -4,
+ ARGON2_PWD_TOO_LONG = -5,
+
+ ARGON2_SALT_TOO_SHORT = -6,
+ ARGON2_SALT_TOO_LONG = -7,
+
+ ARGON2_AD_TOO_SHORT = -8,
+ ARGON2_AD_TOO_LONG = -9,
+
+ ARGON2_SECRET_TOO_SHORT = -10,
+ ARGON2_SECRET_TOO_LONG = -11,
+
+ ARGON2_TIME_TOO_SMALL = -12,
+ ARGON2_TIME_TOO_LARGE = -13,
+
+ ARGON2_MEMORY_TOO_LITTLE = -14,
+ ARGON2_MEMORY_TOO_MUCH = -15,
+
+ ARGON2_LANES_TOO_FEW = -16,
+ ARGON2_LANES_TOO_MANY = -17,
+
+ ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
+ ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
+ ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
+ ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
+
+ ARGON2_MEMORY_ALLOCATION_ERROR = -22,
+
+ ARGON2_FREE_MEMORY_CBK_NULL = -23,
+ ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
+
+ ARGON2_INCORRECT_PARAMETER = -25,
+ ARGON2_INCORRECT_TYPE = -26,
+
+ ARGON2_OUT_PTR_MISMATCH = -27,
+
+ ARGON2_THREADS_TOO_FEW = -28,
+ ARGON2_THREADS_TOO_MANY = -29,
+
+ ARGON2_MISSING_ARGS = -30,
+
+ ARGON2_ENCODING_FAIL = -31,
+
+ ARGON2_DECODING_FAIL = -32,
+
+ ARGON2_THREAD_FAIL = -33,
+
+ ARGON2_DECODING_LENGTH_FAIL = -34,
+
+ ARGON2_VERIFY_MISMATCH = -35
+} argon2_error_codes;
+
+/* Memory allocator types --- for external allocation */
+typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
+typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
+
+/* Argon2 external data structures */
+
+/*
+ *****
+ * Context: structure to hold Argon2 inputs:
+ * output array and its length,
+ * password and its length,
+ * salt and its length,
+ * secret and its length,
+ * associated data and its length,
+ * number of passes, amount of used memory (in KBytes, can be rounded up a bit)
+ * number of parallel threads that will be run.
+ * All the parameters above affect the output hash value.
+ * Additionally, two function pointers can be provided to allocate and
+ * deallocate the memory (if NULL, memory will be allocated internally).
+ * Also, three flags indicate whether to erase password, secret as soon as they
+ * are pre-hashed (and thus not needed anymore), and the entire memory
+ *****
+ * Simplest situation: you have output array out[8], password is stored in
+ * pwd[32], salt is stored in salt[16], you do not have keys nor associated
+ * data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
+ * 4 parallel lanes.
+ * You want to erase the password, but you're OK with last pass not being
+ * erased. You want to use the default memory allocator.
+ * Then you initialize:
+ Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
+ */
+typedef struct Argon2_Context {
+ uint8_t *out; /* output array */
+ uint32_t outlen; /* digest length */
+
+ uint8_t *pwd; /* password array */
+ uint32_t pwdlen; /* password length */
+
+ uint8_t *salt; /* salt array */
+ uint32_t saltlen; /* salt length */
+
+ uint8_t *secret; /* key array */
+ uint32_t secretlen; /* key length */
+
+ uint8_t *ad; /* associated data array */
+ uint32_t adlen; /* associated data length */
+
+ uint32_t t_cost; /* number of passes */
+ uint32_t m_cost; /* amount of memory requested (KB) */
+ uint32_t lanes; /* number of lanes */
+ uint32_t threads; /* maximum number of threads */
+
+ uint32_t version; /* version number */
+
+ allocate_fptr allocate_cbk; /* pointer to memory allocator */
+ deallocate_fptr free_cbk; /* pointer to memory deallocator */
+
+ uint32_t flags; /* array of bool options */
+} argon2_context;
+
+/* Argon2 primitive type */
+typedef enum Argon2_type {
+ Argon2_d = 0,
+ Argon2_i = 1,
+ Argon2_id = 2
+} argon2_type;
+
+/* Version of the algorithm */
+typedef enum Argon2_version {
+ ARGON2_VERSION_10 = 0x10,
+ ARGON2_VERSION_13 = 0x13,
+ ARGON2_VERSION_NUMBER = ARGON2_VERSION_13
+} argon2_version;
+
+/*
+ * Function that gives the string representation of an argon2_type.
+ * @param type The argon2_type that we want the string for
+ * @param uppercase Whether the string should have the first letter uppercase
+ * @return NULL if invalid type, otherwise the string representation.
+ */
+ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase);
+
+/*
+ * Function that performs memory-hard hashing with certain degree of parallelism
+ * @param context Pointer to the Argon2 internal structure
+ * @return Error code if smth is wrong, ARGON2_OK otherwise
+ */
+ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);
+
+/**
+ * Hashes a password with Argon2i, producing an encoded hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hashlen Desired length of the hash in bytes
+ * @param encoded Buffer where to write the encoded hash
+ * @param encodedlen Size of the buffer (thus max size of the encoded hash)
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost,
+ const uint32_t m_cost,
+ const uint32_t parallelism,
+ const void *pwd, const size_t pwdlen,
+ const void *salt, const size_t saltlen,
+ const size_t hashlen, char *encoded,
+ const size_t encodedlen);
+
+/**
+ * Hashes a password with Argon2i, producing a raw hash at @hash
+ * @param t_cost Number of iterations
+ * @param m_cost Sets memory usage to m_cost kibibytes
+ * @param parallelism Number of threads and compute lanes
+ * @param pwd Pointer to password
+ * @param pwdlen Password size in bytes
+ * @param salt Pointer to salt
+ * @param saltlen Salt size in bytes
+ * @param hash Buffer where to write the raw hash - updated by the function
+ * @param hashlen Desired length of the hash in bytes
+ * @pre Different parallelism levels will give different results
+ * @pre Returns ARGON2_OK if successful
+ */
+ARGON2_PUBLIC int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash,
+ const size_t hashlen);
+
+ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,
+ const uint32_t m_cost,
+ const uint32_t parallelism,
+ const void *pwd, const size_t pwdlen,
+ const void *salt, const size_t saltlen,
+ const size_t hashlen, char *encoded,
+ const size_t encodedlen);
+
+ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash,
+ const size_t hashlen);
+
+ARGON2_PUBLIC int argon2id_hash_encoded(const uint32_t t_cost,
+ const uint32_t m_cost,
+ const uint32_t parallelism,
+ const void *pwd, const size_t pwdlen,
+ const void *salt, const size_t saltlen,
+ const size_t hashlen, char *encoded,
+ const size_t encodedlen);
+
+ARGON2_PUBLIC int argon2id_hash_raw(const uint32_t t_cost,
+ const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash,
+ const size_t hashlen);
+
+/* generic function underlying the above ones */
+ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
+ const uint32_t parallelism, const void *pwd,
+ const size_t pwdlen, const void *salt,
+ const size_t saltlen, void *hash,
+ const size_t hashlen, char *encoded,
+ const size_t encodedlen, argon2_type type,
+ const uint32_t version);
+
+/**
+ * Verifies a password against an encoded string
+ * Encoded string is restricted as in validate_inputs()
+ * @param encoded String encoding parameters, salt, hash
+ * @param pwd Pointer to password
+ * @pre Returns ARGON2_OK if successful
+ */
+ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd,
+ const size_t pwdlen);
+
+ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,
+ const size_t pwdlen);
+
+ARGON2_PUBLIC int argon2id_verify(const char *encoded, const void *pwd,
+ const size_t pwdlen);
+
+/* generic function underlying the above ones */
+ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,
+ const size_t pwdlen, argon2_type type);
+
+/**
+ * Argon2d: Version of Argon2 that picks memory blocks depending
+ * on the password and salt. Only for side-channel-free
+ * environment!!
+ *****
+ * @param context Pointer to current Argon2 context
+ * @return Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
+
+/**
+ * Argon2i: Version of Argon2 that picks memory blocks
+ * independent on the password and salt. Good for side-channels,
+ * but worse w.r.t. tradeoff attacks if only one pass is used.
+ *****
+ * @param context Pointer to current Argon2 context
+ * @return Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2i_ctx(argon2_context *context);
+
+/**
+ * Argon2id: Version of Argon2 where the first half-pass over memory is
+ * password-independent, the rest are password-dependent (on the password and
+ * salt). OK against side channels (they reduce to 1/2-pass Argon2i), and
+ * better with w.r.t. tradeoff attacks (similar to Argon2d).
+ *****
+ * @param context Pointer to current Argon2 context
+ * @return Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2id_ctx(argon2_context *context);
+
+/**
+ * Verify if a given password is correct for Argon2d hashing
+ * @param context Pointer to current Argon2 context
+ * @param hash The password hash to verify. The length of the hash is
+ * specified by the context outlen member
+ * @return Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);
+
+/**
+ * Verify if a given password is correct for Argon2i hashing
+ * @param context Pointer to current Argon2 context
+ * @param hash The password hash to verify. The length of the hash is
+ * specified by the context outlen member
+ * @return Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash);
+
+/**
+ * Verify if a given password is correct for Argon2id hashing
+ * @param context Pointer to current Argon2 context
+ * @param hash The password hash to verify. The length of the hash is
+ * specified by the context outlen member
+ * @return Zero if successful, a non zero error code otherwise
+ */
+ARGON2_PUBLIC int argon2id_verify_ctx(argon2_context *context,
+ const char *hash);
+
+/* generic function underlying the above ones */
+ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,
+ argon2_type type);
+
+/**
+ * Get the associated error message for given error code
+ * @return The error message associated with the given error code
+ */
+ARGON2_PUBLIC const char *argon2_error_message(int error_code);
+
+/**
+ * Returns the encoded hash length for the given input parameters
+ * @param t_cost Number of iterations
+ * @param m_cost Memory usage in kibibytes
+ * @param parallelism Number of threads; used to compute lanes
+ * @param saltlen Salt size in bytes
+ * @param hashlen Hash size in bytes
+ * @param type The argon2_type that we want the encoded length for
+ * @return The encoded hash length in bytes
+ */
+ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
+ uint32_t parallelism, uint32_t saltlen,
+ uint32_t hashlen, argon2_type type);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/lib/crypto_backend/argon2/blake2/blake2-impl.h b/lib/crypto_backend/argon2/blake2/blake2-impl.h
new file mode 100644
index 0000000..dcac827
--- /dev/null
+++ b/lib/crypto_backend/argon2/blake2/blake2-impl.h
@@ -0,0 +1,154 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef PORTABLE_BLAKE2_IMPL_H
+#define PORTABLE_BLAKE2_IMPL_H
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+#define BLAKE2_INLINE __inline
+#elif defined(__GNUC__) || defined(__clang__)
+#define BLAKE2_INLINE __inline__
+#else
+#define BLAKE2_INLINE
+#endif
+
+/* Argon2 Team - Begin Code */
+/*
+ Not an exhaustive list, but should cover the majority of modern platforms
+ Additionally, the code will always be correct---this is only a performance
+ tweak.
+*/
+#if (defined(__BYTE_ORDER__) && \
+ (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
+ defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
+ defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \
+ defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \
+ defined(_M_ARM)
+#define NATIVE_LITTLE_ENDIAN
+#endif
+/* Argon2 Team - End Code */
+
+static BLAKE2_INLINE uint32_t load32(const void *src) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+ uint32_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = (const uint8_t *)src;
+ uint32_t w = *p++;
+ w |= (uint32_t)(*p++) << 8;
+ w |= (uint32_t)(*p++) << 16;
+ w |= (uint32_t)(*p++) << 24;
+ return w;
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load64(const void *src) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+ uint64_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
+#else
+ const uint8_t *p = (const uint8_t *)src;
+ uint64_t w = *p++;
+ w |= (uint64_t)(*p++) << 8;
+ w |= (uint64_t)(*p++) << 16;
+ w |= (uint64_t)(*p++) << 24;
+ w |= (uint64_t)(*p++) << 32;
+ w |= (uint64_t)(*p++) << 40;
+ w |= (uint64_t)(*p++) << 48;
+ w |= (uint64_t)(*p++) << 56;
+ return w;
+#endif
+}
+
+static BLAKE2_INLINE void store32(void *dst, uint32_t w) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = (uint8_t *)dst;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+#endif
+}
+
+static BLAKE2_INLINE void store64(void *dst, uint64_t w) {
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = (uint8_t *)dst;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+#endif
+}
+
+static BLAKE2_INLINE uint64_t load48(const void *src) {
+ const uint8_t *p = (const uint8_t *)src;
+ uint64_t w = *p++;
+ w |= (uint64_t)(*p++) << 8;
+ w |= (uint64_t)(*p++) << 16;
+ w |= (uint64_t)(*p++) << 24;
+ w |= (uint64_t)(*p++) << 32;
+ w |= (uint64_t)(*p++) << 40;
+ return w;
+}
+
+static BLAKE2_INLINE void store48(void *dst, uint64_t w) {
+ uint8_t *p = (uint8_t *)dst;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+ w >>= 8;
+ *p++ = (uint8_t)w;
+}
+
+static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) {
+ return (w >> c) | (w << (32 - c));
+}
+
+static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
+ return (w >> c) | (w << (64 - c));
+}
+
+#endif
diff --git a/lib/crypto_backend/argon2/blake2/blake2.h b/lib/crypto_backend/argon2/blake2/blake2.h
new file mode 100644
index 0000000..0c1b0ee
--- /dev/null
+++ b/lib/crypto_backend/argon2/blake2/blake2.h
@@ -0,0 +1,89 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef PORTABLE_BLAKE2_H
+#define PORTABLE_BLAKE2_H
+
+#include "../argon2.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum blake2b_constant {
+ BLAKE2B_BLOCKBYTES = 128,
+ BLAKE2B_OUTBYTES = 64,
+ BLAKE2B_KEYBYTES = 64,
+ BLAKE2B_SALTBYTES = 16,
+ BLAKE2B_PERSONALBYTES = 16
+};
+
+#pragma pack(push, 1)
+typedef struct __blake2b_param {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint32_t leaf_length; /* 8 */
+ uint64_t node_offset; /* 16 */
+ uint8_t node_depth; /* 17 */
+ uint8_t inner_length; /* 18 */
+ uint8_t reserved[14]; /* 32 */
+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+} blake2b_param;
+#pragma pack(pop)
+
+typedef struct __blake2b_state {
+ uint64_t h[8];
+ uint64_t t[2];
+ uint64_t f[2];
+ uint8_t buf[BLAKE2B_BLOCKBYTES];
+ unsigned buflen;
+ unsigned outlen;
+ uint8_t last_node;
+} blake2b_state;
+
+/* Ensure param structs have not been wrongly padded */
+/* Poor man's static_assert */
+enum {
+ blake2_size_check_0 = 1 / !!(CHAR_BIT == 8),
+ blake2_size_check_2 =
+ 1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)
+};
+
+/* Streaming API */
+ARGON2_LOCAL int blake2b_init(blake2b_state *S, size_t outlen);
+ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
+ size_t keylen);
+ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
+ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
+ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, size_t outlen);
+
+/* Simple API */
+ARGON2_LOCAL int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
+ const void *key, size_t keylen);
+
+/* Argon2 Team - Begin Code */
+ARGON2_LOCAL int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
+/* Argon2 Team - End Code */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/lib/crypto_backend/argon2/blake2/blake2b.c b/lib/crypto_backend/argon2/blake2/blake2b.c
new file mode 100644
index 0000000..d8f69e8
--- /dev/null
+++ b/lib/crypto_backend/argon2/blake2/blake2b.c
@@ -0,0 +1,392 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "blake2.h"
+#include "blake2-impl.h"
+
+void clear_internal_memory(void *v, size_t n);
+
+static const uint64_t blake2b_IV[8] = {
+ UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
+ UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
+ UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
+ UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
+
+static const unsigned int blake2b_sigma[12][16] = {
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
+ {11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
+ {7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
+ {9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
+ {2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
+ {12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
+ {13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
+ {6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
+ {10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
+};
+
+static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
+ S->f[1] = (uint64_t)-1;
+}
+
+static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
+ if (S->last_node) {
+ blake2b_set_lastnode(S);
+ }
+ S->f[0] = (uint64_t)-1;
+}
+
+static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
+ uint64_t inc) {
+ S->t[0] += inc;
+ S->t[1] += (S->t[0] < inc);
+}
+
+static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
+ clear_internal_memory(S, sizeof(*S)); /* wipe */
+ blake2b_set_lastblock(S); /* invalidate for further use */
+}
+
+static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
+ memset(S, 0, sizeof(*S));
+ memcpy(S->h, blake2b_IV, sizeof(S->h));
+}
+
+int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
+ const unsigned char *p = (const unsigned char *)P;
+ unsigned int i;
+
+ if (NULL == P || NULL == S) {
+ return -1;
+ }
+
+ blake2b_init0(S);
+ /* IV XOR Parameter Block */
+ for (i = 0; i < 8; ++i) {
+ S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
+ }
+ S->outlen = P->digest_length;
+ return 0;
+}
+
+/* Sequential blake2b initialization */
+int blake2b_init(blake2b_state *S, size_t outlen) {
+ blake2b_param P;
+
+ if (S == NULL) {
+ return -1;
+ }
+
+ if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
+ blake2b_invalidate_state(S);
+ return -1;
+ }
+
+ /* Setup Parameter Block for unkeyed BLAKE2 */
+ P.digest_length = (uint8_t)outlen;
+ P.key_length = 0;
+ P.fanout = 1;
+ P.depth = 1;
+ P.leaf_length = 0;
+ P.node_offset = 0;
+ P.node_depth = 0;
+ P.inner_length = 0;
+ memset(P.reserved, 0, sizeof(P.reserved));
+ memset(P.salt, 0, sizeof(P.salt));
+ memset(P.personal, 0, sizeof(P.personal));
+
+ return blake2b_init_param(S, &P);
+}
+
+int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
+ size_t keylen) {
+ blake2b_param P;
+
+ if (S == NULL) {
+ return -1;
+ }
+
+ if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
+ blake2b_invalidate_state(S);
+ return -1;
+ }
+
+ if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) {
+ blake2b_invalidate_state(S);
+ return -1;
+ }
+
+ /* Setup Parameter Block for keyed BLAKE2 */
+ P.digest_length = (uint8_t)outlen;
+ P.key_length = (uint8_t)keylen;
+ P.fanout = 1;
+ P.depth = 1;
+ P.leaf_length = 0;
+ P.node_offset = 0;
+ P.node_depth = 0;
+ P.inner_length = 0;
+ memset(P.reserved, 0, sizeof(P.reserved));
+ memset(P.salt, 0, sizeof(P.salt));
+ memset(P.personal, 0, sizeof(P.personal));
+
+ if (blake2b_init_param(S, &P) < 0) {
+ blake2b_invalidate_state(S);
+ return -1;
+ }
+
+ {
+ uint8_t block[BLAKE2B_BLOCKBYTES];
+ memset(block, 0, BLAKE2B_BLOCKBYTES);
+ memcpy(block, key, keylen);
+ blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
+ /* Burn the key from stack */
+ clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
+ }
+ return 0;
+}
+
+static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
+ uint64_t m[16];
+ uint64_t v[16];
+ unsigned int i, r;
+
+ for (i = 0; i < 16; ++i) {
+ m[i] = load64(block + i * sizeof(m[i]));
+ }
+
+ for (i = 0; i < 8; ++i) {
+ v[i] = S->h[i];
+ }
+
+ v[8] = blake2b_IV[0];
+ v[9] = blake2b_IV[1];
+ v[10] = blake2b_IV[2];
+ v[11] = blake2b_IV[3];
+ v[12] = blake2b_IV[4] ^ S->t[0];
+ v[13] = blake2b_IV[5] ^ S->t[1];
+ v[14] = blake2b_IV[6] ^ S->f[0];
+ v[15] = blake2b_IV[7] ^ S->f[1];
+
+#define G(r, i, a, b, c, d) \
+ do { \
+ a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
+ d = rotr64(d ^ a, 32); \
+ c = c + d; \
+ b = rotr64(b ^ c, 24); \
+ a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
+ d = rotr64(d ^ a, 16); \
+ c = c + d; \
+ b = rotr64(b ^ c, 63); \
+ } while ((void)0, 0)
+
+#define ROUND(r) \
+ do { \
+ G(r, 0, v[0], v[4], v[8], v[12]); \
+ G(r, 1, v[1], v[5], v[9], v[13]); \
+ G(r, 2, v[2], v[6], v[10], v[14]); \
+ G(r, 3, v[3], v[7], v[11], v[15]); \
+ G(r, 4, v[0], v[5], v[10], v[15]); \
+ G(r, 5, v[1], v[6], v[11], v[12]); \
+ G(r, 6, v[2], v[7], v[8], v[13]); \
+ G(r, 7, v[3], v[4], v[9], v[14]); \
+ } while ((void)0, 0)
+
+ for (r = 0; r < 12; ++r) {
+ ROUND(r);
+ }
+
+ for (i = 0; i < 8; ++i) {
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+ }
+
+#undef G
+#undef ROUND
+}
+
+int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
+ const uint8_t *pin = (const uint8_t *)in;
+
+ if (inlen == 0) {
+ return 0;
+ }
+
+ /* Sanity check */
+ if (S == NULL || in == NULL) {
+ return -1;
+ }
+
+ /* Is this a reused state? */
+ if (S->f[0] != 0) {
+ return -1;
+ }
+
+ if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) {
+ /* Complete current block */
+ size_t left = S->buflen;
+ size_t fill = BLAKE2B_BLOCKBYTES - left;
+ memcpy(&S->buf[left], pin, fill);
+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+ blake2b_compress(S, S->buf);
+ S->buflen = 0;
+ inlen -= fill;
+ pin += fill;
+ /* Avoid buffer copies when possible */
+ while (inlen > BLAKE2B_BLOCKBYTES) {
+ blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
+ blake2b_compress(S, pin);
+ inlen -= BLAKE2B_BLOCKBYTES;
+ pin += BLAKE2B_BLOCKBYTES;
+ }
+ }
+ memcpy(&S->buf[S->buflen], pin, inlen);
+ S->buflen += (unsigned int)inlen;
+ return 0;
+}
+
+int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
+ uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
+ unsigned int i;
+
+ /* Sanity checks */
+ if (S == NULL || out == NULL || outlen < S->outlen) {
+ return -1;
+ }
+
+ /* Is this a reused state? */
+ if (S->f[0] != 0) {
+ return -1;
+ }
+
+ blake2b_increment_counter(S, S->buflen);
+ blake2b_set_lastblock(S);
+ memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
+ blake2b_compress(S, S->buf);
+
+ for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
+ store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
+ }
+
+ memcpy(out, buffer, S->outlen);
+ clear_internal_memory(buffer, sizeof(buffer));
+ clear_internal_memory(S->buf, sizeof(S->buf));
+ clear_internal_memory(S->h, sizeof(S->h));
+ return 0;
+}
+
+int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
+ const void *key, size_t keylen) {
+ blake2b_state S;
+ int ret = -1;
+
+ /* Verify parameters */
+ if (NULL == in && inlen > 0) {
+ goto fail;
+ }
+
+ if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) {
+ goto fail;
+ }
+
+ if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
+ goto fail;
+ }
+
+ if (keylen > 0) {
+ if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
+ goto fail;
+ }
+ } else {
+ if (blake2b_init(&S, outlen) < 0) {
+ goto fail;
+ }
+ }
+
+ if (blake2b_update(&S, in, inlen) < 0) {
+ goto fail;
+ }
+ ret = blake2b_final(&S, out, outlen);
+
+fail:
+ clear_internal_memory(&S, sizeof(S));
+ return ret;
+}
+
+/* Argon2 Team - Begin Code */
+int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
+ uint8_t *out = (uint8_t *)pout;
+ blake2b_state blake_state;
+ uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
+ int ret = -1;
+
+ if (outlen > UINT32_MAX) {
+ goto fail;
+ }
+
+ /* Ensure little-endian byte order! */
+ store32(outlen_bytes, (uint32_t)outlen);
+
+#define TRY(statement) \
+ do { \
+ ret = statement; \
+ if (ret < 0) { \
+ goto fail; \
+ } \
+ } while ((void)0, 0)
+
+ if (outlen <= BLAKE2B_OUTBYTES) {
+ TRY(blake2b_init(&blake_state, outlen));
+ TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
+ TRY(blake2b_update(&blake_state, in, inlen));
+ TRY(blake2b_final(&blake_state, out, outlen));
+ } else {
+ uint32_t toproduce;
+ uint8_t out_buffer[BLAKE2B_OUTBYTES];
+ uint8_t in_buffer[BLAKE2B_OUTBYTES];
+ TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
+ TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
+ TRY(blake2b_update(&blake_state, in, inlen));
+ TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
+ memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
+ out += BLAKE2B_OUTBYTES / 2;
+ toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
+
+ while (toproduce > BLAKE2B_OUTBYTES) {
+ memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
+ TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
+ BLAKE2B_OUTBYTES, NULL, 0));
+ memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
+ out += BLAKE2B_OUTBYTES / 2;
+ toproduce -= BLAKE2B_OUTBYTES / 2;
+ }
+
+ memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
+ TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
+ 0));
+ memcpy(out, out_buffer, toproduce);
+ }
+fail:
+ clear_internal_memory(&blake_state, sizeof(blake_state));
+ return ret;
+#undef TRY
+}
+/* Argon2 Team - End Code */
diff --git a/lib/crypto_backend/argon2/blake2/blamka-round-opt.h b/lib/crypto_backend/argon2/blake2/blamka-round-opt.h
new file mode 100644
index 0000000..3127f2a
--- /dev/null
+++ b/lib/crypto_backend/argon2/blake2/blamka-round-opt.h
@@ -0,0 +1,471 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef BLAKE_ROUND_MKA_OPT_H
+#define BLAKE_ROUND_MKA_OPT_H
+
+#include "blake2-impl.h"
+
+#include <emmintrin.h>
+#if defined(__SSSE3__)
+#include <tmmintrin.h> /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */
+#endif
+
+#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
+#include <x86intrin.h>
+#endif
+
+#if !defined(__AVX512F__)
+#if !defined(__AVX2__)
+#if !defined(__XOP__)
+#if defined(__SSSE3__)
+#define r16 \
+ (_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define r24 \
+ (_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define _mm_roti_epi64(x, c) \
+ (-(c) == 32) \
+ ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
+ : (-(c) == 24) \
+ ? _mm_shuffle_epi8((x), r24) \
+ : (-(c) == 16) \
+ ? _mm_shuffle_epi8((x), r16) \
+ : (-(c) == 63) \
+ ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_add_epi64((x), (x))) \
+ : _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
+ _mm_slli_epi64((x), 64 - (-(c))))
+#else /* defined(__SSE2__) */
+#define _mm_roti_epi64(r, c) \
+ _mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
+#endif
+#else
+#endif
+
+static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
+ const __m128i z = _mm_mul_epu32(x, y);
+ return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
+}
+
+#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = fBlaMka(A0, B0); \
+ A1 = fBlaMka(A1, B1); \
+ \
+ D0 = _mm_xor_si128(D0, A0); \
+ D1 = _mm_xor_si128(D1, A1); \
+ \
+ D0 = _mm_roti_epi64(D0, -32); \
+ D1 = _mm_roti_epi64(D1, -32); \
+ \
+ C0 = fBlaMka(C0, D0); \
+ C1 = fBlaMka(C1, D1); \
+ \
+ B0 = _mm_xor_si128(B0, C0); \
+ B1 = _mm_xor_si128(B1, C1); \
+ \
+ B0 = _mm_roti_epi64(B0, -24); \
+ B1 = _mm_roti_epi64(B1, -24); \
+ } while ((void)0, 0)
+
+#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = fBlaMka(A0, B0); \
+ A1 = fBlaMka(A1, B1); \
+ \
+ D0 = _mm_xor_si128(D0, A0); \
+ D1 = _mm_xor_si128(D1, A1); \
+ \
+ D0 = _mm_roti_epi64(D0, -16); \
+ D1 = _mm_roti_epi64(D1, -16); \
+ \
+ C0 = fBlaMka(C0, D0); \
+ C1 = fBlaMka(C1, D1); \
+ \
+ B0 = _mm_xor_si128(B0, C0); \
+ B1 = _mm_xor_si128(B1, C1); \
+ \
+ B0 = _mm_roti_epi64(B0, -63); \
+ B1 = _mm_roti_epi64(B1, -63); \
+ } while ((void)0, 0)
+
+#if defined(__SSSE3__)
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
+ __m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
+ B0 = t0; \
+ B1 = t1; \
+ \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ \
+ t0 = _mm_alignr_epi8(D1, D0, 8); \
+ t1 = _mm_alignr_epi8(D0, D1, 8); \
+ D0 = t1; \
+ D1 = t0; \
+ } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
+ __m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
+ B0 = t0; \
+ B1 = t1; \
+ \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ \
+ t0 = _mm_alignr_epi8(D0, D1, 8); \
+ t1 = _mm_alignr_epi8(D1, D0, 8); \
+ D0 = t1; \
+ D1 = t0; \
+ } while ((void)0, 0)
+#else /* SSE2 */
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0 = D0; \
+ __m128i t1 = B0; \
+ D0 = C0; \
+ C0 = C1; \
+ C1 = D0; \
+ D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \
+ D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \
+ B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \
+ B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \
+ } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ __m128i t0, t1; \
+ t0 = C0; \
+ C0 = C1; \
+ C1 = t0; \
+ t0 = B0; \
+ t1 = D0; \
+ B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \
+ B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \
+ D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \
+ D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \
+ } while ((void)0, 0)
+#endif
+
+#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+ \
+ UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ } while ((void)0, 0)
+#else /* __AVX2__ */
+
+#include <immintrin.h>
+
+#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
+#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
+#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
+#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
+
+#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i ml = _mm256_mul_epu32(A0, B0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+ D0 = _mm256_xor_si256(D0, A0); \
+ D0 = rotr32(D0); \
+ \
+ ml = _mm256_mul_epu32(C0, D0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+ \
+ B0 = _mm256_xor_si256(B0, C0); \
+ B0 = rotr24(B0); \
+ \
+ ml = _mm256_mul_epu32(A1, B1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+ D1 = _mm256_xor_si256(D1, A1); \
+ D1 = rotr32(D1); \
+ \
+ ml = _mm256_mul_epu32(C1, D1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+ \
+ B1 = _mm256_xor_si256(B1, C1); \
+ B1 = rotr24(B1); \
+ } while((void)0, 0);
+
+#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i ml = _mm256_mul_epu32(A0, B0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
+ D0 = _mm256_xor_si256(D0, A0); \
+ D0 = rotr16(D0); \
+ \
+ ml = _mm256_mul_epu32(C0, D0); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
+ B0 = _mm256_xor_si256(B0, C0); \
+ B0 = rotr63(B0); \
+ \
+ ml = _mm256_mul_epu32(A1, B1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
+ D1 = _mm256_xor_si256(D1, A1); \
+ D1 = rotr16(D1); \
+ \
+ ml = _mm256_mul_epu32(C1, D1); \
+ ml = _mm256_add_epi64(ml, ml); \
+ C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
+ B1 = _mm256_xor_si256(B1, C1); \
+ B1 = rotr63(B1); \
+ } while((void)0, 0);
+
+#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ \
+ B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while((void)0, 0);
+
+#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+ __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+ B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ \
+ tmp1 = C0; \
+ C0 = C1; \
+ C1 = tmp1; \
+ \
+ tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
+ tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
+ D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ } while(0);
+
+#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ \
+ B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+ D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while((void)0, 0);
+
+#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ __m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
+ __m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
+ B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ \
+ tmp1 = C0; \
+ C0 = C1; \
+ C1 = tmp1; \
+ \
+ tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
+ tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
+ D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
+ D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
+ } while((void)0, 0);
+
+#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do{ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ } while((void)0, 0);
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do{ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ \
+ UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ } while((void)0, 0);
+
+#endif /* __AVX2__ */
+
+#else /* __AVX512F__ */
+
+#include <immintrin.h>
+
+#define ror64(x, n) _mm512_ror_epi64((x), (n))
+
+static __m512i muladd(__m512i x, __m512i y)
+{
+ __m512i z = _mm512_mul_epu32(x, y);
+ return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
+}
+
+#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = muladd(A0, B0); \
+ A1 = muladd(A1, B1); \
+\
+ D0 = _mm512_xor_si512(D0, A0); \
+ D1 = _mm512_xor_si512(D1, A1); \
+\
+ D0 = ror64(D0, 32); \
+ D1 = ror64(D1, 32); \
+\
+ C0 = muladd(C0, D0); \
+ C1 = muladd(C1, D1); \
+\
+ B0 = _mm512_xor_si512(B0, C0); \
+ B1 = _mm512_xor_si512(B1, C1); \
+\
+ B0 = ror64(B0, 24); \
+ B1 = ror64(B1, 24); \
+ } while ((void)0, 0)
+
+#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ A0 = muladd(A0, B0); \
+ A1 = muladd(A1, B1); \
+\
+ D0 = _mm512_xor_si512(D0, A0); \
+ D1 = _mm512_xor_si512(D1, A1); \
+\
+ D0 = ror64(D0, 16); \
+ D1 = ror64(D1, 16); \
+\
+ C0 = muladd(C0, D0); \
+ C1 = muladd(C1, D1); \
+\
+ B0 = _mm512_xor_si512(B0, C0); \
+ B1 = _mm512_xor_si512(B1, C1); \
+\
+ B0 = ror64(B0, 63); \
+ B1 = ror64(B1, 63); \
+ } while ((void)0, 0)
+
+#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
+\
+ C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+\
+ D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
+ } while ((void)0, 0)
+
+#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
+ B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
+\
+ C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
+ C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
+\
+ D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
+ D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
+ do { \
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+\
+ DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+\
+ G1(A0, B0, C0, D0, A1, B1, C1, D1); \
+ G2(A0, B0, C0, D0, A1, B1, C1, D1); \
+\
+ UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
+ } while ((void)0, 0)
+
+#define SWAP_HALVES(A0, A1) \
+ do { \
+ __m512i t0, t1; \
+ t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
+ t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
+ A0 = t0; \
+ A1 = t1; \
+ } while((void)0, 0)
+
+#define SWAP_QUARTERS(A0, A1) \
+ do { \
+ SWAP_HALVES(A0, A1); \
+ A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+ A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+ } while((void)0, 0)
+
+#define UNSWAP_QUARTERS(A0, A1) \
+ do { \
+ A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
+ A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
+ SWAP_HALVES(A0, A1); \
+ } while((void)0, 0)
+
+#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
+ do { \
+ SWAP_HALVES(A0, B0); \
+ SWAP_HALVES(C0, D0); \
+ SWAP_HALVES(A1, B1); \
+ SWAP_HALVES(C1, D1); \
+ BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+ SWAP_HALVES(A0, B0); \
+ SWAP_HALVES(C0, D0); \
+ SWAP_HALVES(A1, B1); \
+ SWAP_HALVES(C1, D1); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
+ do { \
+ SWAP_QUARTERS(A0, A1); \
+ SWAP_QUARTERS(B0, B1); \
+ SWAP_QUARTERS(C0, C1); \
+ SWAP_QUARTERS(D0, D1); \
+ BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
+ UNSWAP_QUARTERS(A0, A1); \
+ UNSWAP_QUARTERS(B0, B1); \
+ UNSWAP_QUARTERS(C0, C1); \
+ UNSWAP_QUARTERS(D0, D1); \
+ } while ((void)0, 0)
+
+#endif /* __AVX512F__ */
+#endif /* BLAKE_ROUND_MKA_OPT_H */
diff --git a/lib/crypto_backend/argon2/blake2/blamka-round-ref.h b/lib/crypto_backend/argon2/blake2/blamka-round-ref.h
new file mode 100644
index 0000000..16cfc1c
--- /dev/null
+++ b/lib/crypto_backend/argon2/blake2/blamka-round-ref.h
@@ -0,0 +1,56 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef BLAKE_ROUND_MKA_H
+#define BLAKE_ROUND_MKA_H
+
+#include "blake2.h"
+#include "blake2-impl.h"
+
+/* designed by the Lyra PHC team */
+static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) {
+ const uint64_t m = UINT64_C(0xFFFFFFFF);
+ const uint64_t xy = (x & m) * (y & m);
+ return x + y + 2 * xy;
+}
+
+#define G(a, b, c, d) \
+ do { \
+ a = fBlaMka(a, b); \
+ d = rotr64(d ^ a, 32); \
+ c = fBlaMka(c, d); \
+ b = rotr64(b ^ c, 24); \
+ a = fBlaMka(a, b); \
+ d = rotr64(d ^ a, 16); \
+ c = fBlaMka(c, d); \
+ b = rotr64(b ^ c, 63); \
+ } while ((void)0, 0)
+
+#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
+ v12, v13, v14, v15) \
+ do { \
+ G(v0, v4, v8, v12); \
+ G(v1, v5, v9, v13); \
+ G(v2, v6, v10, v14); \
+ G(v3, v7, v11, v15); \
+ G(v0, v5, v10, v15); \
+ G(v1, v6, v11, v12); \
+ G(v2, v7, v8, v13); \
+ G(v3, v4, v9, v14); \
+ } while ((void)0, 0)
+
+#endif
diff --git a/lib/crypto_backend/argon2/core.c b/lib/crypto_backend/argon2/core.c
new file mode 100644
index 0000000..f128d84
--- /dev/null
+++ b/lib/crypto_backend/argon2/core.c
@@ -0,0 +1,646 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+/*For memory wiping*/
+#ifdef _MSC_VER
+#include <windows.h>
+#include <winbase.h> /* For SecureZeroMemory */
+#endif
+#if defined __STDC_LIB_EXT1__
+#define __STDC_WANT_LIB_EXT1__ 1
+#endif
+#define VC_GE_2005(version) (version >= 1400)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "core.h"
+#include "thread.h"
+#include "blake2/blake2.h"
+#include "blake2/blake2-impl.h"
+
+#ifdef GENKAT
+#include "genkat.h"
+#endif
+
+#if defined(__clang__)
+#if __has_attribute(optnone)
+#define NOT_OPTIMIZED __attribute__((optnone))
+#endif
+#elif defined(__GNUC__)
+#define GCC_VERSION \
+ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#if GCC_VERSION >= 40400
+#define NOT_OPTIMIZED __attribute__((optimize("O0")))
+#endif
+#endif
+#ifndef NOT_OPTIMIZED
+#define NOT_OPTIMIZED
+#endif
+
+/***************Instance and Position constructors**********/
+void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
+
+void copy_block(block *dst, const block *src) {
+ memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
+}
+
+void xor_block(block *dst, const block *src) {
+ int i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ dst->v[i] ^= src->v[i];
+ }
+}
+
+static void load_block(block *dst, const void *input) {
+ unsigned i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
+ }
+}
+
+static void store_block(void *output, const block *src) {
+ unsigned i;
+ for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
+ store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
+ }
+}
+
+/***************Memory functions*****************/
+
+int allocate_memory(const argon2_context *context, uint8_t **memory,
+ size_t num, size_t size) {
+ size_t memory_size = num*size;
+ if (memory == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ /* 1. Check for multiplication overflow */
+ if (size != 0 && memory_size / size != num) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ /* 2. Try to allocate with appropriate allocator */
+ if (context->allocate_cbk) {
+ (context->allocate_cbk)(memory, memory_size);
+ } else {
+ *memory = malloc(memory_size);
+ }
+
+ if (*memory == NULL) {
+ return ARGON2_MEMORY_ALLOCATION_ERROR;
+ }
+
+ return ARGON2_OK;
+}
+
+void free_memory(const argon2_context *context, uint8_t *memory,
+ size_t num, size_t size) {
+ size_t memory_size = num*size;
+ clear_internal_memory(memory, memory_size);
+ if (context->free_cbk) {
+ (context->free_cbk)(memory, memory_size);
+ } else {
+ free(memory);
+ }
+}
+
+#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
+void secure_wipe_memory(void *v, size_t n) {
+ SecureZeroMemory(v, n);
+}
+#elif defined memset_s
+void secure_wipe_memory(void *v, size_t n) {
+ memset_s(v, n, 0, n);
+}
+#elif defined(HAVE_EXPLICIT_BZERO)
+void secure_wipe_memory(void *v, size_t n) {
+ explicit_bzero(v, n);
+}
+#else
+void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
+ static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
+ memset_sec(v, 0, n);
+}
+#endif
+
+/* Memory clear flag defaults to true. */
+int FLAG_clear_internal_memory = 1;
+void clear_internal_memory(void *v, size_t n) {
+ if (FLAG_clear_internal_memory && v) {
+ secure_wipe_memory(v, n);
+ }
+}
+
+void finalize(const argon2_context *context, argon2_instance_t *instance) {
+ if (context != NULL && instance != NULL) {
+ block blockhash;
+ uint32_t l;
+
+ copy_block(&blockhash, instance->memory + instance->lane_length - 1);
+
+ /* XOR the last blocks */
+ for (l = 1; l < instance->lanes; ++l) {
+ uint32_t last_block_in_lane =
+ l * instance->lane_length + (instance->lane_length - 1);
+ xor_block(&blockhash, instance->memory + last_block_in_lane);
+ }
+
+ /* Hash the result */
+ {
+ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+ store_block(blockhash_bytes, &blockhash);
+ blake2b_long(context->out, context->outlen, blockhash_bytes,
+ ARGON2_BLOCK_SIZE);
+ /* clear blockhash and blockhash_bytes */
+ clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE);
+ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
+ }
+
+#ifdef GENKAT
+ print_tag(context->out, context->outlen);
+#endif
+
+ free_memory(context, (uint8_t *)instance->memory,
+ instance->memory_blocks, sizeof(block));
+ }
+}
+
+uint32_t index_alpha(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint32_t pseudo_rand,
+ int same_lane) {
+ /*
+ * Pass 0:
+ * This lane : all already finished segments plus already constructed
+ * blocks in this segment
+ * Other lanes : all already finished segments
+ * Pass 1+:
+ * This lane : (SYNC_POINTS - 1) last segments plus already constructed
+ * blocks in this segment
+ * Other lanes : (SYNC_POINTS - 1) last segments
+ */
+ uint32_t reference_area_size;
+ uint64_t relative_position;
+ uint32_t start_position, absolute_position;
+
+ if (0 == position->pass) {
+ /* First pass */
+ if (0 == position->slice) {
+ /* First slice */
+ reference_area_size =
+ position->index - 1; /* all but the previous */
+ } else {
+ if (same_lane) {
+ /* The same lane => add current segment */
+ reference_area_size =
+ position->slice * instance->segment_length +
+ position->index - 1;
+ } else {
+ reference_area_size =
+ position->slice * instance->segment_length +
+ ((position->index == 0) ? (-1) : 0);
+ }
+ }
+ } else {
+ /* Second pass */
+ if (same_lane) {
+ reference_area_size = instance->lane_length -
+ instance->segment_length + position->index -
+ 1;
+ } else {
+ reference_area_size = instance->lane_length -
+ instance->segment_length +
+ ((position->index == 0) ? (-1) : 0);
+ }
+ }
+
+ /* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
+ * relative position */
+ relative_position = pseudo_rand;
+ relative_position = relative_position * relative_position >> 32;
+ relative_position = reference_area_size - 1 -
+ (reference_area_size * relative_position >> 32);
+
+ /* 1.2.5 Computing starting position */
+ start_position = 0;
+
+ if (0 != position->pass) {
+ start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
+ ? 0
+ : (position->slice + 1) * instance->segment_length;
+ }
+
+ /* 1.2.6. Computing absolute position */
+ absolute_position = (start_position + relative_position) %
+ instance->lane_length; /* absolute position */
+ return absolute_position;
+}
+
+/* Single-threaded version for p=1 case */
+static int fill_memory_blocks_st(argon2_instance_t *instance) {
+ uint32_t r, s, l;
+
+ for (r = 0; r < instance->passes; ++r) {
+ for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
+ for (l = 0; l < instance->lanes; ++l) {
+ argon2_position_t position = {r, l, (uint8_t)s, 0};
+ fill_segment(instance, position);
+ }
+ }
+#ifdef GENKAT
+ internal_kat(instance, r); /* Print all memory blocks */
+#endif
+ }
+ return ARGON2_OK;
+}
+
+#if !defined(ARGON2_NO_THREADS)
+
+#ifdef _WIN32
+static unsigned __stdcall fill_segment_thr(void *thread_data)
+#else
+static void *fill_segment_thr(void *thread_data)
+#endif
+{
+ argon2_thread_data *my_data = thread_data;
+ fill_segment(my_data->instance_ptr, my_data->pos);
+ return 0;
+}
+
+/* Multi-threaded version for p > 1 case */
+static int fill_memory_blocks_mt(argon2_instance_t *instance) {
+ uint32_t r, s;
+ argon2_thread_handle_t *thread = NULL;
+ argon2_thread_data *thr_data = NULL;
+ int rc = ARGON2_OK;
+
+ /* 1. Allocating space for threads */
+ thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t));
+ if (thread == NULL) {
+ rc = ARGON2_MEMORY_ALLOCATION_ERROR;
+ goto fail;
+ }
+
+ thr_data = calloc(instance->lanes, sizeof(argon2_thread_data));
+ if (thr_data == NULL) {
+ rc = ARGON2_MEMORY_ALLOCATION_ERROR;
+ goto fail;
+ }
+
+ for (r = 0; r < instance->passes; ++r) {
+ for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
+ uint32_t l, ll;
+
+ /* 2. Calling threads */
+ for (l = 0; l < instance->lanes; ++l) {
+ argon2_position_t position;
+
+ /* 2.1 Join a thread if limit is exceeded */
+ if (l >= instance->threads) {
+ if (argon2_thread_join(thread[l - instance->threads])) {
+ rc = ARGON2_THREAD_FAIL;
+ goto fail;
+ }
+ }
+
+ /* 2.2 Create thread */
+ position.pass = r;
+ position.lane = l;
+ position.slice = (uint8_t)s;
+ position.index = 0;
+ thr_data[l].instance_ptr =
+ instance; /* preparing the thread input */
+ memcpy(&(thr_data[l].pos), &position,
+ sizeof(argon2_position_t));
+ if (argon2_thread_create(&thread[l], &fill_segment_thr,
+ (void *)&thr_data[l])) {
+ /* Wait for already running threads */
+ for (ll = 0; ll < l; ++ll)
+ argon2_thread_join(thread[ll]);
+ rc = ARGON2_THREAD_FAIL;
+ goto fail;
+ }
+
+ /* fill_segment(instance, position); */
+ /*Non-thread equivalent of the lines above */
+ }
+
+ /* 3. Joining remaining threads */
+ for (l = instance->lanes - instance->threads; l < instance->lanes;
+ ++l) {
+ if (argon2_thread_join(thread[l])) {
+ rc = ARGON2_THREAD_FAIL;
+ goto fail;
+ }
+ }
+ }
+
+#ifdef GENKAT
+ internal_kat(instance, r); /* Print all memory blocks */
+#endif
+ }
+
+fail:
+ if (thread != NULL) {
+ free(thread);
+ }
+ if (thr_data != NULL) {
+ free(thr_data);
+ }
+ return rc;
+}
+
+#endif /* ARGON2_NO_THREADS */
+
+int fill_memory_blocks(argon2_instance_t *instance) {
+ if (instance == NULL || instance->lanes == 0) {
+ return ARGON2_INCORRECT_PARAMETER;
+ }
+#if defined(ARGON2_NO_THREADS)
+ return fill_memory_blocks_st(instance);
+#else
+ return instance->threads == 1 ?
+ fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
+#endif
+}
+
+int validate_inputs(const argon2_context *context) {
+ if (NULL == context) {
+ return ARGON2_INCORRECT_PARAMETER;
+ }
+
+ if (NULL == context->out) {
+ return ARGON2_OUTPUT_PTR_NULL;
+ }
+
+ /* Validate output length */
+ if (ARGON2_MIN_OUTLEN > context->outlen) {
+ return ARGON2_OUTPUT_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_OUTLEN < context->outlen) {
+ return ARGON2_OUTPUT_TOO_LONG;
+ }
+
+ /* Validate password (required param) */
+ if (NULL == context->pwd) {
+ if (0 != context->pwdlen) {
+ return ARGON2_PWD_PTR_MISMATCH;
+ }
+ }
+#if ARGON2_MIN_PWD_LENGTH > 0 /* cryptsetup: fix gcc warning */
+ if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
+ return ARGON2_PWD_TOO_SHORT;
+ }
+#endif
+ if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
+ return ARGON2_PWD_TOO_LONG;
+ }
+
+ /* Validate salt (required param) */
+ if (NULL == context->salt) {
+ if (0 != context->saltlen) {
+ return ARGON2_SALT_PTR_MISMATCH;
+ }
+ }
+
+ if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
+ return ARGON2_SALT_TOO_SHORT;
+ }
+
+ if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
+ return ARGON2_SALT_TOO_LONG;
+ }
+
+ /* Validate secret (optional param) */
+ if (NULL == context->secret) {
+ if (0 != context->secretlen) {
+ return ARGON2_SECRET_PTR_MISMATCH;
+ }
+ } else {
+#if ARGON2_MIN_SECRET > 0 /* cryptsetup: fix gcc warning */
+ if (ARGON2_MIN_SECRET > context->secretlen) {
+ return ARGON2_SECRET_TOO_SHORT;
+ }
+#endif
+ if (ARGON2_MAX_SECRET < context->secretlen) {
+ return ARGON2_SECRET_TOO_LONG;
+ }
+ }
+
+ /* Validate associated data (optional param) */
+ if (NULL == context->ad) {
+ if (0 != context->adlen) {
+ return ARGON2_AD_PTR_MISMATCH;
+ }
+ } else {
+#if ARGON2_MIN_AD_LENGTH > 0 /* cryptsetup: fix gcc warning */
+ if (ARGON2_MIN_AD_LENGTH > context->adlen) {
+ return ARGON2_AD_TOO_SHORT;
+ }
+#endif
+ if (ARGON2_MAX_AD_LENGTH < context->adlen) {
+ return ARGON2_AD_TOO_LONG;
+ }
+ }
+
+ /* Validate memory cost */
+ if (ARGON2_MIN_MEMORY > context->m_cost) {
+ return ARGON2_MEMORY_TOO_LITTLE;
+ }
+#if 0 /* UINT32_MAX, cryptsetup: fix gcc warning */
+ if (ARGON2_MAX_MEMORY < context->m_cost) {
+ return ARGON2_MEMORY_TOO_MUCH;
+ }
+#endif
+ if (context->m_cost < 8 * context->lanes) {
+ return ARGON2_MEMORY_TOO_LITTLE;
+ }
+
+ /* Validate time cost */
+ if (ARGON2_MIN_TIME > context->t_cost) {
+ return ARGON2_TIME_TOO_SMALL;
+ }
+
+ if (ARGON2_MAX_TIME < context->t_cost) {
+ return ARGON2_TIME_TOO_LARGE;
+ }
+
+ /* Validate lanes */
+ if (ARGON2_MIN_LANES > context->lanes) {
+ return ARGON2_LANES_TOO_FEW;
+ }
+
+ if (ARGON2_MAX_LANES < context->lanes) {
+ return ARGON2_LANES_TOO_MANY;
+ }
+
+ /* Validate threads */
+ if (ARGON2_MIN_THREADS > context->threads) {
+ return ARGON2_THREADS_TOO_FEW;
+ }
+
+ if (ARGON2_MAX_THREADS < context->threads) {
+ return ARGON2_THREADS_TOO_MANY;
+ }
+
+ if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
+ return ARGON2_FREE_MEMORY_CBK_NULL;
+ }
+
+ if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
+ return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
+ }
+
+ return ARGON2_OK;
+}
+
+void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
+ uint32_t l;
+ /* Make the first and second block in each lane as G(H0||0||i) or
+ G(H0||1||i) */
+ uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
+ for (l = 0; l < instance->lanes; ++l) {
+
+ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
+ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+ ARGON2_PREHASH_SEED_LENGTH);
+ load_block(&instance->memory[l * instance->lane_length + 0],
+ blockhash_bytes);
+
+ store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
+ blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
+ ARGON2_PREHASH_SEED_LENGTH);
+ load_block(&instance->memory[l * instance->lane_length + 1],
+ blockhash_bytes);
+ }
+ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
+}
+
+void initial_hash(uint8_t *blockhash, argon2_context *context,
+ argon2_type type) {
+ blake2b_state BlakeHash;
+ uint8_t value[sizeof(uint32_t)];
+
+ if (NULL == context || NULL == blockhash) {
+ return;
+ }
+
+ blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
+
+ store32(&value, context->lanes);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ store32(&value, context->outlen);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ store32(&value, context->m_cost);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ store32(&value, context->t_cost);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ store32(&value, context->version);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ store32(&value, (uint32_t)type);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ store32(&value, context->pwdlen);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ if (context->pwd != NULL) {
+ blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
+ context->pwdlen);
+
+ if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
+ secure_wipe_memory(context->pwd, context->pwdlen);
+ context->pwdlen = 0;
+ }
+ }
+
+ store32(&value, context->saltlen);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ if (context->salt != NULL) {
+ blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
+ context->saltlen);
+ }
+
+ store32(&value, context->secretlen);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ if (context->secret != NULL) {
+ blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
+ context->secretlen);
+
+ if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
+ secure_wipe_memory(context->secret, context->secretlen);
+ context->secretlen = 0;
+ }
+ }
+
+ store32(&value, context->adlen);
+ blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
+
+ if (context->ad != NULL) {
+ blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
+ context->adlen);
+ }
+
+ blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
+}
+
+int initialize(argon2_instance_t *instance, argon2_context *context) {
+ uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
+ int result = ARGON2_OK;
+
+ if (instance == NULL || context == NULL)
+ return ARGON2_INCORRECT_PARAMETER;
+ instance->context_ptr = context;
+
+ /* 1. Memory allocation */
+ result = allocate_memory(context, (uint8_t **)&(instance->memory),
+ instance->memory_blocks, sizeof(block));
+ if (result != ARGON2_OK) {
+ return result;
+ }
+
+ /* 2. Initial hashing */
+ /* H_0 + 8 extra bytes to produce the first blocks */
+ /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
+ /* Hashing all inputs */
+ initial_hash(blockhash, context, instance->type);
+ /* Zeroing 8 extra bytes */
+ clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
+ ARGON2_PREHASH_SEED_LENGTH -
+ ARGON2_PREHASH_DIGEST_LENGTH);
+
+#ifdef GENKAT
+ initial_kat(blockhash, context, instance->type);
+#endif
+
+ /* 3. Creating first blocks, we always have at least two blocks in a slice
+ */
+ fill_first_blocks(blockhash, instance);
+ /* Clearing the hash */
+ clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
+
+ return ARGON2_OK;
+}
diff --git a/lib/crypto_backend/argon2/core.h b/lib/crypto_backend/argon2/core.h
new file mode 100644
index 0000000..59e2564
--- /dev/null
+++ b/lib/crypto_backend/argon2/core.h
@@ -0,0 +1,228 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ARGON2_CORE_H
+#define ARGON2_CORE_H
+
+#include "argon2.h"
+
+#define CONST_CAST(x) (x)(uintptr_t)
+
+/**********************Argon2 internal constants*******************************/
+
+enum argon2_core_constants {
+ /* Memory block size in bytes */
+ ARGON2_BLOCK_SIZE = 1024,
+ ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
+ ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
+ ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
+ ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
+
+ /* Number of pseudo-random values generated by one call to Blake in Argon2i
+ to
+ generate reference block positions */
+ ARGON2_ADDRESSES_IN_BLOCK = 128,
+
+ /* Pre-hashing digest length and its extension*/
+ ARGON2_PREHASH_DIGEST_LENGTH = 64,
+ ARGON2_PREHASH_SEED_LENGTH = 72
+};
+
+/*************************Argon2 internal data types***********************/
+
+/*
+ * Structure for the (1KB) memory block implemented as 128 64-bit words.
+ * Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
+ * bounds checking).
+ */
+typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
+
+/*****************Functions that work with the block******************/
+
+/* Initialize each byte of the block with @in */
+void init_block_value(block *b, uint8_t in);
+
+/* Copy block @src to block @dst */
+void copy_block(block *dst, const block *src);
+
+/* XOR @src onto @dst bytewise */
+void xor_block(block *dst, const block *src);
+
+/*
+ * Argon2 instance: memory pointer, number of passes, amount of memory, type,
+ * and derived values.
+ * Used to evaluate the number and location of blocks to construct in each
+ * thread
+ */
+typedef struct Argon2_instance_t {
+ block *memory; /* Memory pointer */
+ uint32_t version;
+ uint32_t passes; /* Number of passes */
+ uint32_t memory_blocks; /* Number of blocks in memory */
+ uint32_t segment_length;
+ uint32_t lane_length;
+ uint32_t lanes;
+ uint32_t threads;
+ argon2_type type;
+ int print_internals; /* whether to print the memory blocks */
+ argon2_context *context_ptr; /* points back to original context */
+} argon2_instance_t;
+
+/*
+ * Argon2 position: where we construct the block right now. Used to distribute
+ * work between threads.
+ */
+typedef struct Argon2_position_t {
+ uint32_t pass;
+ uint32_t lane;
+ uint8_t slice;
+ uint32_t index;
+} argon2_position_t;
+
+/*Struct that holds the inputs for thread handling FillSegment*/
+typedef struct Argon2_thread_data {
+ argon2_instance_t *instance_ptr;
+ argon2_position_t pos;
+} argon2_thread_data;
+
+/*************************Argon2 core functions********************************/
+
+/* Allocates memory to the given pointer, uses the appropriate allocator as
+ * specified in the context. Total allocated memory is num*size.
+ * @param context argon2_context which specifies the allocator
+ * @param memory pointer to the pointer to the memory
+ * @param size the size in bytes for each element to be allocated
+ * @param num the number of elements to be allocated
+ * @return ARGON2_OK if @memory is a valid pointer and memory is allocated
+ */
+int allocate_memory(const argon2_context *context, uint8_t **memory,
+ size_t num, size_t size);
+
+/*
+ * Frees memory at the given pointer, uses the appropriate deallocator as
+ * specified in the context. Also cleans the memory using clear_internal_memory.
+ * @param context argon2_context which specifies the deallocator
+ * @param memory pointer to buffer to be freed
+ * @param size the size in bytes for each element to be deallocated
+ * @param num the number of elements to be deallocated
+ */
+void free_memory(const argon2_context *context, uint8_t *memory,
+ size_t num, size_t size);
+
+/* Function that securely cleans the memory. This ignores any flags set
+ * regarding clearing memory. Usually one just calls clear_internal_memory.
+ * @param mem Pointer to the memory
+ * @param s Memory size in bytes
+ */
+void secure_wipe_memory(void *v, size_t n);
+
+/* Function that securely clears the memory if FLAG_clear_internal_memory is
+ * set. If the flag isn't set, this function does nothing.
+ * @param mem Pointer to the memory
+ * @param s Memory size in bytes
+ */
+void clear_internal_memory(void *v, size_t n);
+
+/*
+ * Computes absolute position of reference block in the lane following a skewed
+ * distribution and using a pseudo-random value as input
+ * @param instance Pointer to the current instance
+ * @param position Pointer to the current position
+ * @param pseudo_rand 32-bit pseudo-random value used to determine the position
+ * @param same_lane Indicates if the block will be taken from the current lane.
+ * If so we can reference the current segment
+ * @pre All pointers must be valid
+ */
+uint32_t index_alpha(const argon2_instance_t *instance,
+ const argon2_position_t *position, uint32_t pseudo_rand,
+ int same_lane);
+
+/*
+ * Function that validates all inputs against predefined restrictions and return
+ * an error code
+ * @param context Pointer to current Argon2 context
+ * @return ARGON2_OK if everything is all right, otherwise one of error codes
+ * (all defined in <argon2.h>
+ */
+int validate_inputs(const argon2_context *context);
+
+/*
+ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
+ * password and secret if needed
+ * @param context Pointer to the Argon2 internal structure containing memory
+ * pointer, and parameters for time and space requirements.
+ * @param blockhash Buffer for pre-hashing digest
+ * @param type Argon2 type
+ * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
+ * allocated
+ */
+void initial_hash(uint8_t *blockhash, argon2_context *context,
+ argon2_type type);
+
+/*
+ * Function creates first 2 blocks per lane
+ * @param instance Pointer to the current instance
+ * @param blockhash Pointer to the pre-hashing digest
+ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
+ */
+void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
+
+/*
+ * Function allocates memory, hashes the inputs with Blake, and creates first
+ * two blocks. Returns the pointer to the main memory with 2 blocks per lane
+ * initialized
+ * @param context Pointer to the Argon2 internal structure containing memory
+ * pointer, and parameters for time and space requirements.
+ * @param instance Current Argon2 instance
+ * @return Zero if successful, -1 if memory failed to allocate. @context->state
+ * will be modified if successful.
+ */
+int initialize(argon2_instance_t *instance, argon2_context *context);
+
+/*
+ * XORing the last block of each lane, hashing it, making the tag. Deallocates
+ * the memory.
+ * @param context Pointer to current Argon2 context (use only the out parameters
+ * from it)
+ * @param instance Pointer to current instance of Argon2
+ * @pre instance->state must point to necessary amount of memory
+ * @pre context->out must point to outlen bytes of memory
+ * @pre if context->free_cbk is not NULL, it should point to a function that
+ * deallocates memory
+ */
+void finalize(const argon2_context *context, argon2_instance_t *instance);
+
+/*
+ * Function that fills the segment using previous segments also from other
+ * threads
+ * @param context current context
+ * @param instance Pointer to the current instance
+ * @param position Current position
+ * @pre all block pointers must be valid
+ */
+void fill_segment(const argon2_instance_t *instance,
+ argon2_position_t position);
+
+/*
+ * Function that fills the entire memory t_cost times based on the first two
+ * blocks in each lane
+ * @param instance Pointer to the current instance
+ * @return ARGON2_OK if successful, @context->state
+ */
+int fill_memory_blocks(argon2_instance_t *instance);
+
+#endif
diff --git a/lib/crypto_backend/argon2/encoding.c b/lib/crypto_backend/argon2/encoding.c
new file mode 100644
index 0000000..a717263
--- /dev/null
+++ b/lib/crypto_backend/argon2/encoding.c
@@ -0,0 +1,462 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "encoding.h"
+#include "core.h"
+
+/*
+ * Example code for a decoder and encoder of "hash strings", with Argon2
+ * parameters.
+ *
+ * This code comprises three sections:
+ *
+ * -- The first section contains generic Base64 encoding and decoding
+ * functions. It is conceptually applicable to any hash function
+ * implementation that uses Base64 to encode and decode parameters,
+ * salts and outputs. It could be made into a library, provided that
+ * the relevant functions are made public (non-static) and be given
+ * reasonable names to avoid collisions with other functions.
+ *
+ * -- The second section is specific to Argon2. It encodes and decodes
+ * the parameters, salts and outputs. It does not compute the hash
+ * itself.
+ *
+ * The code was originally written by Thomas Pornin <pornin@bolet.org>,
+ * to whom comments and remarks may be sent. It is released under what
+ * should amount to Public Domain or its closest equivalent; the
+ * following mantra is supposed to incarnate that fact with all the
+ * proper legal rituals:
+ *
+ * ---------------------------------------------------------------------
+ * This file is provided under the terms of Creative Commons CC0 1.0
+ * Public Domain Dedication. To the extent possible under law, the
+ * author (Thomas Pornin) has waived all copyright and related or
+ * neighboring rights to this file. This work is published from: Canada.
+ * ---------------------------------------------------------------------
+ *
+ * Copyright (c) 2015 Thomas Pornin
+ */
+
+/* ==================================================================== */
+/*
+ * Common code; could be shared between different hash functions.
+ *
+ * Note: the Base64 functions below assume that uppercase letters (resp.
+ * lowercase letters) have consecutive numerical codes, that fit on 8
+ * bits. All modern systems use ASCII-compatible charsets, where these
+ * properties are true. If you are stuck with a dinosaur of a system
+ * that still defaults to EBCDIC then you already have much bigger
+ * interoperability issues to deal with.
+ */
+
+/*
+ * Some macros for constant-time comparisons. These work over values in
+ * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
+ */
+#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
+#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
+#define GE(x, y) (GT(y, x) ^ 0xFF)
+#define LT(x, y) GT(y, x)
+#define LE(x, y) GE(y, x)
+
+/*
+ * Convert value x (0..63) to corresponding Base64 character.
+ */
+static int b64_byte_to_char(unsigned x) {
+ return (LT(x, 26) & (x + 'A')) |
+ (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
+ (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
+ (EQ(x, 63) & '/');
+}
+
+/*
+ * Convert character c to the corresponding 6-bit value. If character c
+ * is not a Base64 character, then 0xFF (255) is returned.
+ */
+static unsigned b64_char_to_byte(int c) {
+ unsigned x;
+
+ x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
+ (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
+ (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
+ (EQ(c, '/') & 63);
+ return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
+}
+
+/*
+ * Convert some bytes to Base64. 'dst_len' is the length (in characters)
+ * of the output buffer 'dst'; if that buffer is not large enough to
+ * receive the result (including the terminating 0), then (size_t)-1
+ * is returned. Otherwise, the zero-terminated Base64 string is written
+ * in the buffer, and the output length (counted WITHOUT the terminating
+ * zero) is returned.
+ */
+static size_t to_base64(char *dst, size_t dst_len, const void *src,
+ size_t src_len) {
+ size_t olen;
+ const unsigned char *buf;
+ unsigned acc, acc_len;
+
+ olen = (src_len / 3) << 2;
+ switch (src_len % 3) {
+ case 2:
+ olen++;
+ /* fall through */
+ case 1:
+ olen += 2;
+ break;
+ }
+ if (dst_len <= olen) {
+ return (size_t)-1;
+ }
+ acc = 0;
+ acc_len = 0;
+ buf = (const unsigned char *)src;
+ while (src_len-- > 0) {
+ acc = (acc << 8) + (*buf++);
+ acc_len += 8;
+ while (acc_len >= 6) {
+ acc_len -= 6;
+ *dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
+ }
+ }
+ if (acc_len > 0) {
+ *dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
+ }
+ *dst++ = 0;
+ return olen;
+}
+
+/*
+ * Decode Base64 chars into bytes. The '*dst_len' value must initially
+ * contain the length of the output buffer '*dst'; when the decoding
+ * ends, the actual number of decoded bytes is written back in
+ * '*dst_len'.
+ *
+ * Decoding stops when a non-Base64 character is encountered, or when
+ * the output buffer capacity is exceeded. If an error occurred (output
+ * buffer is too small, invalid last characters leading to unprocessed
+ * buffered bits), then NULL is returned; otherwise, the returned value
+ * points to the first non-Base64 character in the source stream, which
+ * may be the terminating zero.
+ */
+static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
+ size_t len;
+ unsigned char *buf;
+ unsigned acc, acc_len;
+
+ buf = (unsigned char *)dst;
+ len = 0;
+ acc = 0;
+ acc_len = 0;
+ for (;;) {
+ unsigned d;
+
+ d = b64_char_to_byte(*src);
+ if (d == 0xFF) {
+ break;
+ }
+ src++;
+ acc = (acc << 6) + d;
+ acc_len += 6;
+ if (acc_len >= 8) {
+ acc_len -= 8;
+ if ((len++) >= *dst_len) {
+ return NULL;
+ }
+ *buf++ = (acc >> acc_len) & 0xFF;
+ }
+ }
+
+ /*
+ * If the input length is equal to 1 modulo 4 (which is
+ * invalid), then there will remain 6 unprocessed bits;
+ * otherwise, only 0, 2 or 4 bits are buffered. The buffered
+ * bits must also all be zero.
+ */
+ if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
+ return NULL;
+ }
+ *dst_len = len;
+ return src;
+}
+
+/*
+ * Decode decimal integer from 'str'; the value is written in '*v'.
+ * Returned value is a pointer to the next non-decimal character in the
+ * string. If there is no digit at all, or the value encoding is not
+ * minimal (extra leading zeros), or the value does not fit in an
+ * 'unsigned long', then NULL is returned.
+ */
+static const char *decode_decimal(const char *str, unsigned long *v) {
+ const char *orig;
+ unsigned long acc;
+
+ acc = 0;
+ for (orig = str;; str++) {
+ int c;
+
+ c = *str;
+ if (c < '0' || c > '9') {
+ break;
+ }
+ c -= '0';
+ if (acc > (ULONG_MAX / 10)) {
+ return NULL;
+ }
+ acc *= 10;
+ if ((unsigned long)c > (ULONG_MAX - acc)) {
+ return NULL;
+ }
+ acc += (unsigned long)c;
+ }
+ if (str == orig || (*orig == '0' && str != (orig + 1))) {
+ return NULL;
+ }
+ *v = acc;
+ return str;
+}
+
+/* ==================================================================== */
+/*
+ * Code specific to Argon2.
+ *
+ * The code below applies the following format:
+ *
+ * $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
+ *
+ * where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
+ * fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
+ * characters, no newline or whitespace).
+ *
+ * The last two binary chunks (encoded in Base64) are, in that order,
+ * the salt and the output. Both are required. The binary salt length and the
+ * output length must be in the allowed ranges defined in argon2.h.
+ *
+ * The ctx struct must contain buffers large enough to hold the salt and pwd
+ * when it is fed into decode_string.
+ */
+
+int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
+
+/* check for prefix */
+#define CC(prefix) \
+ do { \
+ size_t cc_len = strlen(prefix); \
+ if (strncmp(str, prefix, cc_len) != 0) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ str += cc_len; \
+ } while ((void)0, 0)
+
+/* optional prefix checking with supplied code */
+#define CC_opt(prefix, code) \
+ do { \
+ size_t cc_len = strlen(prefix); \
+ if (strncmp(str, prefix, cc_len) == 0) { \
+ str += cc_len; \
+ { code; } \
+ } \
+ } while ((void)0, 0)
+
+/* Decoding prefix into decimal */
+#define DECIMAL(x) \
+ do { \
+ unsigned long dec_x; \
+ str = decode_decimal(str, &dec_x); \
+ if (str == NULL) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (x) = dec_x; \
+ } while ((void)0, 0)
+
+
+/* Decoding prefix into uint32_t decimal */
+#define DECIMAL_U32(x) \
+ do { \
+ unsigned long dec_x; \
+ str = decode_decimal(str, &dec_x); \
+ if (str == NULL || dec_x > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (x) = (uint32_t)dec_x; \
+ } while ((void)0, 0)
+
+
+/* Decoding base64 into a binary buffer */
+#define BIN(buf, max_len, len) \
+ do { \
+ size_t bin_len = (max_len); \
+ str = from_base64(buf, &bin_len, str); \
+ if (str == NULL || bin_len > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (len) = (uint32_t)bin_len; \
+ } while ((void)0, 0)
+
+ size_t maxsaltlen = ctx->saltlen;
+ size_t maxoutlen = ctx->outlen;
+ int validation_result;
+ const char* type_string;
+
+ /* We should start with the argon2_type we are using */
+ type_string = argon2_type2string(type, 0);
+ if (!type_string) {
+ return ARGON2_INCORRECT_TYPE;
+ }
+
+ CC("$");
+ CC(type_string);
+
+ /* Reading the version number if the default is suppressed */
+ ctx->version = ARGON2_VERSION_10;
+ CC_opt("$v=", DECIMAL_U32(ctx->version));
+
+ CC("$m=");
+ DECIMAL_U32(ctx->m_cost);
+ CC(",t=");
+ DECIMAL_U32(ctx->t_cost);
+ CC(",p=");
+ DECIMAL_U32(ctx->lanes);
+ ctx->threads = ctx->lanes;
+
+ CC("$");
+ BIN(ctx->salt, maxsaltlen, ctx->saltlen);
+ CC("$");
+ BIN(ctx->out, maxoutlen, ctx->outlen);
+
+ /* The rest of the fields get the default values */
+ ctx->secret = NULL;
+ ctx->secretlen = 0;
+ ctx->ad = NULL;
+ ctx->adlen = 0;
+ ctx->allocate_cbk = NULL;
+ ctx->free_cbk = NULL;
+ ctx->flags = ARGON2_DEFAULT_FLAGS;
+
+ /* On return, must have valid context */
+ validation_result = validate_inputs(ctx);
+ if (validation_result != ARGON2_OK) {
+ return validation_result;
+ }
+
+ /* Can't have any additional characters */
+ if (*str == 0) {
+ return ARGON2_OK;
+ } else {
+ return ARGON2_DECODING_FAIL;
+ }
+#undef CC
+#undef CC_opt
+#undef DECIMAL
+#undef BIN
+}
+
+int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
+ argon2_type type) {
+#define SS(str) \
+ do { \
+ size_t pp_len = strlen(str); \
+ if (pp_len >= dst_len) { \
+ return ARGON2_ENCODING_FAIL; \
+ } \
+ memcpy(dst, str, pp_len + 1); \
+ dst += pp_len; \
+ dst_len -= pp_len; \
+ } while ((void)0, 0)
+
+#define SX(x) \
+ do { \
+ char tmp[30]; \
+ sprintf(tmp, "%lu", (unsigned long)(x)); \
+ SS(tmp); \
+ } while ((void)0, 0)
+
+#define SB(buf, len) \
+ do { \
+ size_t sb_len = to_base64(dst, dst_len, buf, len); \
+ if (sb_len == (size_t)-1) { \
+ return ARGON2_ENCODING_FAIL; \
+ } \
+ dst += sb_len; \
+ dst_len -= sb_len; \
+ } while ((void)0, 0)
+
+ const char* type_string = argon2_type2string(type, 0);
+ int validation_result = validate_inputs(ctx);
+
+ if (!type_string) {
+ return ARGON2_ENCODING_FAIL;
+ }
+
+ if (validation_result != ARGON2_OK) {
+ return validation_result;
+ }
+
+
+ SS("$");
+ SS(type_string);
+
+ SS("$v=");
+ SX(ctx->version);
+
+ SS("$m=");
+ SX(ctx->m_cost);
+ SS(",t=");
+ SX(ctx->t_cost);
+ SS(",p=");
+ SX(ctx->lanes);
+
+ SS("$");
+ SB(ctx->salt, ctx->saltlen);
+
+ SS("$");
+ SB(ctx->out, ctx->outlen);
+ return ARGON2_OK;
+
+#undef SS
+#undef SX
+#undef SB
+}
+
+size_t b64len(uint32_t len) {
+ size_t olen = ((size_t)len / 3) << 2;
+
+ switch (len % 3) {
+ case 2:
+ olen++;
+ /* fall through */
+ case 1:
+ olen += 2;
+ break;
+ }
+
+ return olen;
+}
+
+size_t numlen(uint32_t num) {
+ size_t len = 1;
+ while (num >= 10) {
+ ++len;
+ num = num / 10;
+ }
+ return len;
+}
diff --git a/lib/crypto_backend/argon2/encoding.h b/lib/crypto_backend/argon2/encoding.h
new file mode 100644
index 0000000..5b8b2dd
--- /dev/null
+++ b/lib/crypto_backend/argon2/encoding.h
@@ -0,0 +1,57 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ENCODING_H
+#define ENCODING_H
+#include "argon2.h"
+
+#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
+#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
+#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
+
+/*
+* encode an Argon2 hash string into the provided buffer. 'dst_len'
+* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
+* is less than the number of required characters (including the
+* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
+*
+* on success, ARGON2_OK is returned.
+*/
+int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
+ argon2_type type);
+
+/*
+* Decodes an Argon2 hash string into the provided structure 'ctx'.
+* The only fields that must be set prior to this call are ctx.saltlen and
+* ctx.outlen (which must be the maximal salt and out length values that are
+* allowed), ctx.salt and ctx.out (which must be buffers of the specified
+* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
+*
+* Invalid input string causes an error. On success, the ctx is valid and all
+* fields have been initialized.
+*
+* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
+*/
+int decode_string(argon2_context *ctx, const char *str, argon2_type type);
+
+/* Returns the length of the encoded byte stream with length len */
+size_t b64len(uint32_t len);
+
+/* Returns the length of the encoded number num */
+size_t numlen(uint32_t num);
+
+#endif
diff --git a/lib/crypto_backend/argon2/opt.c b/lib/crypto_backend/argon2/opt.c
new file mode 100644
index 0000000..6c5e403
--- /dev/null
+++ b/lib/crypto_backend/argon2/opt.c
@@ -0,0 +1,283 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "argon2.h"
+#include "core.h"
+
+#include "blake2/blake2.h"
+#include "blake2/blamka-round-opt.h"
+
+/*
+ * Function fills a new memory block and optionally XORs the old block over the new one.
+ * Memory must be initialized.
+ * @param state Pointer to the just produced block. Content will be updated(!)
+ * @param ref_block Pointer to the reference block
+ * @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
+ * @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
+ * @pre all block pointers must be valid
+ */
+#if defined(__AVX512F__)
+static void fill_block(__m512i *state, const block *ref_block,
+ block *next_block, int with_xor) {
+ __m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
+ unsigned int i;
+
+ if (with_xor) {
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
+ block_XY[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i));
+ }
+ } else {
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm512_xor_si512(
+ state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
+ }
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_1(
+ state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
+ state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ BLAKE2_ROUND_2(
+ state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
+ state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
+ state[i] = _mm512_xor_si512(state[i], block_XY[i]);
+ _mm512_storeu_si512((__m512i *)next_block->v + i, state[i]);
+ }
+}
+#elif defined(__AVX2__)
+static void fill_block(__m256i *state, const block *ref_block,
+ block *next_block, int with_xor) {
+ __m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
+ unsigned int i;
+
+ if (with_xor) {
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
+ block_XY[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i));
+ }
+ } else {
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm256_xor_si256(
+ state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
+ }
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
+ state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
+ state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
+ }
+
+ for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
+ state[i] = _mm256_xor_si256(state[i], block_XY[i]);
+ _mm256_storeu_si256((__m256i *)next_block->v + i, state[i]);
+ }
+}
+#else
+static void fill_block(__m128i *state, const block *ref_block,
+ block *next_block, int with_xor) {
+ __m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
+ unsigned int i;
+
+ if (with_xor) {
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
+ block_XY[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((const __m128i *)next_block->v + i));
+ }
+ } else {
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ block_XY[i] = state[i] = _mm_xor_si128(
+ state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
+ }
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
+ state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
+ state[8 * i + 6], state[8 * i + 7]);
+ }
+
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
+ state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
+ state[8 * 6 + i], state[8 * 7 + i]);
+ }
+
+ for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
+ state[i] = _mm_xor_si128(state[i], block_XY[i]);
+ _mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
+ }
+}
+#endif
+
+static void next_addresses(block *address_block, block *input_block) {
+ /*Temporary zero-initialized blocks*/
+#if defined(__AVX512F__)
+ __m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
+ __m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
+#elif defined(__AVX2__)
+ __m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
+ __m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
+#else
+ __m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
+ __m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
+#endif
+
+ memset(zero_block, 0, sizeof(zero_block));
+ memset(zero2_block, 0, sizeof(zero2_block));
+
+ /*Increasing index counter*/
+ input_block->v[6]++;
+
+ /*First iteration of G*/
+ fill_block(zero_block, input_block, address_block, 0);
+
+ /*Second iteration of G*/
+ fill_block(zero2_block, address_block, address_block, 0);
+}
+
+void fill_segment(const argon2_instance_t *instance,
+ argon2_position_t position) {
+ block *ref_block = NULL, *curr_block = NULL;
+ block address_block, input_block;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index, i;
+#if defined(__AVX512F__)
+ __m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
+#elif defined(__AVX2__)
+ __m256i state[ARGON2_HWORDS_IN_BLOCK];
+#else
+ __m128i state[ARGON2_OWORDS_IN_BLOCK];
+#endif
+ int data_independent_addressing;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ data_independent_addressing =
+ (instance->type == Argon2_i) ||
+ (instance->type == Argon2_id && (position.pass == 0) &&
+ (position.slice < ARGON2_SYNC_POINTS / 2));
+
+ if (data_independent_addressing) {
+ init_block_value(&input_block, 0);
+
+ input_block.v[0] = position.pass;
+ input_block.v[1] = position.lane;
+ input_block.v[2] = position.slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+
+ /* Don't forget to generate the first block of addresses: */
+ if (data_independent_addressing) {
+ next_addresses(&address_block, &input_block);
+ }
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ next_addresses(&address_block, &input_block);
+ }
+ pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ } else {
+ pseudo_rand = instance->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block =
+ instance->memory + instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->memory + curr_offset;
+ if (ARGON2_VERSION_10 == instance->version) {
+ /* version 1.2.1 and earlier: overwrite, not XOR */
+ fill_block(state, ref_block, curr_block, 0);
+ } else {
+ if(0 == position.pass) {
+ fill_block(state, ref_block, curr_block, 0);
+ } else {
+ fill_block(state, ref_block, curr_block, 1);
+ }
+ }
+ }
+}
diff --git a/lib/crypto_backend/argon2/ref.c b/lib/crypto_backend/argon2/ref.c
new file mode 100644
index 0000000..10e45eb
--- /dev/null
+++ b/lib/crypto_backend/argon2/ref.c
@@ -0,0 +1,194 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "argon2.h"
+#include "core.h"
+
+#include "blake2/blamka-round-ref.h"
+#include "blake2/blake2-impl.h"
+#include "blake2/blake2.h"
+
+
+/*
+ * Function fills a new memory block and optionally XORs the old block over the new one.
+ * @next_block must be initialized.
+ * @param prev_block Pointer to the previous block
+ * @param ref_block Pointer to the reference block
+ * @param next_block Pointer to the block to be constructed
+ * @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
+ * @pre all block pointers must be valid
+ */
+static void fill_block(const block *prev_block, const block *ref_block,
+ block *next_block, int with_xor) {
+ block blockR, block_tmp;
+ unsigned i;
+
+ copy_block(&blockR, ref_block);
+ xor_block(&blockR, prev_block);
+ copy_block(&block_tmp, &blockR);
+ /* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */
+ if (with_xor) {
+ /* Saving the next block contents for XOR over: */
+ xor_block(&block_tmp, next_block);
+ /* Now blockR = ref_block + prev_block and
+ block_tmp = ref_block + prev_block + next_block */
+ }
+
+ /* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
+ (16,17,..31)... finally (112,113,...127) */
+ for (i = 0; i < 8; ++i) {
+ BLAKE2_ROUND_NOMSG(
+ blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
+ blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
+ blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
+ blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
+ blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
+ blockR.v[16 * i + 15]);
+ }
+
+ /* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
+ (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
+ for (i = 0; i < 8; i++) {
+ BLAKE2_ROUND_NOMSG(
+ blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
+ blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
+ blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
+ blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
+ blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
+ blockR.v[2 * i + 113]);
+ }
+
+ copy_block(next_block, &block_tmp);
+ xor_block(next_block, &blockR);
+}
+
+static void next_addresses(block *address_block, block *input_block,
+ const block *zero_block) {
+ input_block->v[6]++;
+ fill_block(zero_block, input_block, address_block, 0);
+ fill_block(zero_block, address_block, address_block, 0);
+}
+
+void fill_segment(const argon2_instance_t *instance,
+ argon2_position_t position) {
+ block *ref_block = NULL, *curr_block = NULL;
+ block address_block, input_block, zero_block;
+ uint64_t pseudo_rand, ref_index, ref_lane;
+ uint32_t prev_offset, curr_offset;
+ uint32_t starting_index;
+ uint32_t i;
+ int data_independent_addressing;
+
+ if (instance == NULL) {
+ return;
+ }
+
+ data_independent_addressing =
+ (instance->type == Argon2_i) ||
+ (instance->type == Argon2_id && (position.pass == 0) &&
+ (position.slice < ARGON2_SYNC_POINTS / 2));
+
+ if (data_independent_addressing) {
+ init_block_value(&zero_block, 0);
+ init_block_value(&input_block, 0);
+
+ input_block.v[0] = position.pass;
+ input_block.v[1] = position.lane;
+ input_block.v[2] = position.slice;
+ input_block.v[3] = instance->memory_blocks;
+ input_block.v[4] = instance->passes;
+ input_block.v[5] = instance->type;
+ }
+
+ starting_index = 0;
+
+ if ((0 == position.pass) && (0 == position.slice)) {
+ starting_index = 2; /* we have already generated the first two blocks */
+
+ /* Don't forget to generate the first block of addresses: */
+ if (data_independent_addressing) {
+ next_addresses(&address_block, &input_block, &zero_block);
+ }
+ }
+
+ /* Offset of the current block */
+ curr_offset = position.lane * instance->lane_length +
+ position.slice * instance->segment_length + starting_index;
+
+ if (0 == curr_offset % instance->lane_length) {
+ /* Last block in this lane */
+ prev_offset = curr_offset + instance->lane_length - 1;
+ } else {
+ /* Previous block */
+ prev_offset = curr_offset - 1;
+ }
+
+ for (i = starting_index; i < instance->segment_length;
+ ++i, ++curr_offset, ++prev_offset) {
+ /*1.1 Rotating prev_offset if needed */
+ if (curr_offset % instance->lane_length == 1) {
+ prev_offset = curr_offset - 1;
+ }
+
+ /* 1.2 Computing the index of the reference block */
+ /* 1.2.1 Taking pseudo-random value from the previous block */
+ if (data_independent_addressing) {
+ if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
+ next_addresses(&address_block, &input_block, &zero_block);
+ }
+ pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
+ } else {
+ pseudo_rand = instance->memory[prev_offset].v[0];
+ }
+
+ /* 1.2.2 Computing the lane of the reference block */
+ ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
+
+ if ((position.pass == 0) && (position.slice == 0)) {
+ /* Can not reference other lanes yet */
+ ref_lane = position.lane;
+ }
+
+ /* 1.2.3 Computing the number of possible reference block within the
+ * lane.
+ */
+ position.index = i;
+ ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
+ ref_lane == position.lane);
+
+ /* 2 Creating a new block */
+ ref_block =
+ instance->memory + instance->lane_length * ref_lane + ref_index;
+ curr_block = instance->memory + curr_offset;
+ if (ARGON2_VERSION_10 == instance->version) {
+ /* version 1.2.1 and earlier: overwrite, not XOR */
+ fill_block(instance->memory + prev_offset, ref_block, curr_block, 0);
+ } else {
+ if(0 == position.pass) {
+ fill_block(instance->memory + prev_offset, ref_block,
+ curr_block, 0);
+ } else {
+ fill_block(instance->memory + prev_offset, ref_block,
+ curr_block, 1);
+ }
+ }
+ }
+}
diff --git a/lib/crypto_backend/argon2/thread.c b/lib/crypto_backend/argon2/thread.c
new file mode 100644
index 0000000..9fd15ed
--- /dev/null
+++ b/lib/crypto_backend/argon2/thread.c
@@ -0,0 +1,49 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#if !defined(ARGON2_NO_THREADS)
+
+#include "thread.h"
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+int argon2_thread_create(argon2_thread_handle_t *handle,
+ argon2_thread_func_t func, void *args) {
+ if (NULL == handle || func == NULL) {
+ return -1;
+ }
+#if defined(_WIN32)
+ *handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
+ return *handle != 0 ? 0 : -1;
+#else
+ return pthread_create(handle, NULL, func, args);
+#endif
+}
+
+int argon2_thread_join(argon2_thread_handle_t handle) {
+#if defined(_WIN32)
+ if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
+ return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
+ }
+ return -1;
+#else
+ return pthread_join(handle, NULL);
+#endif
+}
+
+#endif /* ARGON2_NO_THREADS */
diff --git a/lib/crypto_backend/argon2/thread.h b/lib/crypto_backend/argon2/thread.h
new file mode 100644
index 0000000..478e260
--- /dev/null
+++ b/lib/crypto_backend/argon2/thread.h
@@ -0,0 +1,62 @@
+/*
+ * Argon2 reference source code package - reference C implementations
+ *
+ * Copyright 2015
+ * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
+ *
+ * You may use this work under the terms of a Creative Commons CC0 1.0
+ * License/Waiver or the Apache Public License 2.0, at your option. The terms of
+ * these licenses can be found at:
+ *
+ * - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
+ * - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * You should have received a copy of both of these licenses along with this
+ * software. If not, they may be obtained at the above URLs.
+ */
+
+#ifndef ARGON2_THREAD_H
+#define ARGON2_THREAD_H
+
+#if !defined(ARGON2_NO_THREADS)
+
+/*
+ Here we implement an abstraction layer for the simpĺe requirements
+ of the Argon2 code. We only require 3 primitives---thread creation,
+ joining, and termination---so full emulation of the pthreads API
+ is unwarranted. Currently we wrap pthreads and Win32 threads.
+
+ The API defines 2 types: the function pointer type,
+ argon2_thread_func_t,
+ and the type of the thread handle---argon2_thread_handle_t.
+*/
+#if defined(_WIN32)
+#include <process.h>
+typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
+typedef uintptr_t argon2_thread_handle_t;
+#else
+#include <pthread.h>
+typedef void *(*argon2_thread_func_t)(void *);
+typedef pthread_t argon2_thread_handle_t;
+#endif
+
+/* Creates a thread
+ * @param handle pointer to a thread handle, which is the output of this
+ * function. Must not be NULL.
+ * @param func A function pointer for the thread's entry point. Must not be
+ * NULL.
+ * @param args Pointer that is passed as an argument to @func. May be NULL.
+ * @return 0 if @handle and @func are valid pointers and a thread is successfully
+ * created.
+ */
+int argon2_thread_create(argon2_thread_handle_t *handle,
+ argon2_thread_func_t func, void *args);
+
+/* Waits for a thread to terminate
+ * @param handle Handle to a thread created with argon2_thread_create.
+ * @return 0 if @handle is a valid handle, and joining completed successfully.
+*/
+int argon2_thread_join(argon2_thread_handle_t handle);
+
+#endif /* ARGON2_NO_THREADS */
+#endif
diff --git a/lib/crypto_backend/argon2_generic.c b/lib/crypto_backend/argon2_generic.c
new file mode 100644
index 0000000..0ce67da
--- /dev/null
+++ b/lib/crypto_backend/argon2_generic.c
@@ -0,0 +1,79 @@
+/*
+ * Argon2 PBKDF2 library wrapper
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include "crypto_backend_internal.h"
+#if HAVE_ARGON2_H
+#include <argon2.h>
+#else
+#include "argon2/argon2.h"
+#endif
+
+#define CONST_CAST(x) (x)(uintptr_t)
+
+int argon2(const char *type, const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+#if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H
+ return -EINVAL;
+#else
+ argon2_type atype;
+ argon2_context context = {
+ .flags = ARGON2_DEFAULT_FLAGS,
+ .version = ARGON2_VERSION_NUMBER,
+ .t_cost = (uint32_t)iterations,
+ .m_cost = (uint32_t)memory,
+ .lanes = (uint32_t)parallel,
+ .threads = (uint32_t)parallel,
+ .out = (uint8_t *)key,
+ .outlen = (uint32_t)key_length,
+ .pwd = CONST_CAST(uint8_t *)password,
+ .pwdlen = (uint32_t)password_length,
+ .salt = CONST_CAST(uint8_t *)salt,
+ .saltlen = (uint32_t)salt_length,
+ };
+ int r;
+
+ if (!strcmp(type, "argon2i"))
+ atype = Argon2_i;
+ else if(!strcmp(type, "argon2id"))
+ atype = Argon2_id;
+ else
+ return -EINVAL;
+
+ switch (argon2_ctx(&context, atype)) {
+ case ARGON2_OK:
+ r = 0;
+ break;
+ case ARGON2_MEMORY_ALLOCATION_ERROR:
+ case ARGON2_FREE_MEMORY_CBK_NULL:
+ case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
+ r = -ENOMEM;
+ break;
+ default:
+ r = -EINVAL;
+ }
+
+ return r;
+#endif
+}
diff --git a/lib/crypto_backend/base64.c b/lib/crypto_backend/base64.c
new file mode 100644
index 0000000..42f70cb
--- /dev/null
+++ b/lib/crypto_backend/base64.c
@@ -0,0 +1,276 @@
+/*
+ * Base64 "Not encryption" helpers, copied and adapted from systemd project.
+ *
+ * Copyright (C) 2010 Lennart Poettering
+ *
+ * cryptsetup related changes
+ * Copyright (C) 2021-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "crypto_backend.h"
+
+#define WHITESPACE " \t\n\r"
+
+/* https://tools.ietf.org/html/rfc4648#section-4 */
+static char base64char(int x)
+{
+ static const char table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ return table[x & 63];
+}
+
+static int unbase64char(char c)
+{
+ unsigned offset;
+
+ if (c >= 'A' && c <= 'Z')
+ return c - 'A';
+
+ offset = 'Z' - 'A' + 1;
+
+ if (c >= 'a' && c <= 'z')
+ return c - 'a' + offset;
+
+ offset += 'z' - 'a' + 1;
+
+ if (c >= '0' && c <= '9')
+ return c - '0' + offset;
+
+ offset += '9' - '0' + 1;
+
+ if (c == '+')
+ return offset;
+
+ offset++;
+
+ if (c == '/')
+ return offset;
+
+ return -EINVAL;
+}
+
+int crypt_base64_encode(char **out, size_t *out_length, const char *in, size_t in_length)
+{
+ char *r, *z;
+ const uint8_t *x;
+
+ assert(in || in_length == 0);
+ assert(out);
+
+ /* three input bytes makes four output bytes, padding is added so we must round up */
+ z = r = malloc(4 * (in_length + 2) / 3 + 1);
+ if (!r)
+ return -ENOMEM;
+
+ for (x = (const uint8_t *)in; x < (const uint8_t*)in + (in_length / 3) * 3; x += 3) {
+ /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
+ *(z++) = base64char((x[1] & 15) << 2 | x[2] >> 6); /* 00YYYYZZ */
+ *(z++) = base64char(x[2] & 63); /* 00ZZZZZZ */
+ }
+
+ switch (in_length % 3) {
+ case 2:
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4 | x[1] >> 4); /* 00XXYYYY */
+ *(z++) = base64char((x[1] & 15) << 2); /* 00YYYY00 */
+ *(z++) = '=';
+
+ break;
+ case 1:
+ *(z++) = base64char(x[0] >> 2); /* 00XXXXXX */
+ *(z++) = base64char((x[0] & 3) << 4); /* 00XX0000 */
+ *(z++) = '=';
+ *(z++) = '=';
+
+ break;
+ }
+
+ *z = 0;
+ *out = r;
+ if (out_length)
+ *out_length = z - r;
+ return 0;
+}
+
+static int unbase64_next(const char **p, size_t *l)
+{
+ int ret;
+
+ assert(p);
+ assert(l);
+
+ /* Find the next non-whitespace character, and decode it. If we find padding, we return it as INT_MAX. We
+ * greedily skip all preceding and all following whitespace. */
+
+ for (;;) {
+ if (*l == 0)
+ return -EPIPE;
+
+ if (!strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip leading whitespace */
+ (*p)++, (*l)--;
+ }
+
+ if (**p == '=')
+ ret = INT_MAX; /* return padding as INT_MAX */
+ else {
+ ret = unbase64char(**p);
+ if (ret < 0)
+ return ret;
+ }
+
+ for (;;) {
+ (*p)++, (*l)--;
+
+ if (*l == 0)
+ break;
+ if (!strchr(WHITESPACE, **p))
+ break;
+
+ /* Skip following whitespace */
+ }
+
+ return ret;
+}
+
+int crypt_base64_decode(char **out, size_t *out_length, const char *in, size_t in_length)
+{
+ uint8_t *buf = NULL;
+ const char *x;
+ uint8_t *z;
+ size_t len;
+ int r;
+
+ assert(in || in_length == 0);
+ assert(out);
+ assert(out_length);
+
+ if (in_length == (size_t) -1)
+ in_length = strlen(in);
+
+ /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra
+ * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */
+ len = (in_length / 4) * 3 + (in_length % 4 != 0 ? (in_length % 4) - 1 : 0);
+
+ buf = malloc(len + 1);
+ if (!buf)
+ return -ENOMEM;
+
+ for (x = in, z = buf;;) {
+ int a, b, c, d; /* a == 00XXXXXX; b == 00YYYYYY; c == 00ZZZZZZ; d == 00WWWWWW */
+
+ a = unbase64_next(&x, &in_length);
+ if (a == -EPIPE) /* End of string */
+ break;
+ if (a < 0) {
+ r = a;
+ goto err;
+ }
+ if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */
+ r = -EINVAL;
+ goto err;
+ }
+
+ b = unbase64_next(&x, &in_length);
+ if (b < 0) {
+ r = b;
+ goto err;
+ }
+ if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */
+ r = -EINVAL;
+ goto err;
+ }
+
+ c = unbase64_next(&x, &in_length);
+ if (c < 0) {
+ r = c;
+ goto err;
+ }
+
+ d = unbase64_next(&x, &in_length);
+ if (d < 0) {
+ r = d;
+ goto err;
+ }
+
+ if (c == INT_MAX) { /* Padding at the third character */
+
+ if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */
+ r = -EINVAL;
+ goto err;
+ }
+
+ /* b == 00YY0000 */
+ if (b & 15) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ if (in_length > 0) { /* Trailing rubbish? */
+ r = -ENAMETOOLONG;
+ goto err;
+ }
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */
+ break;
+ }
+
+ if (d == INT_MAX) {
+ /* c == 00ZZZZ00 */
+ if (c & 3) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ if (in_length > 0) { /* Trailing rubbish? */
+ r = -ENAMETOOLONG;
+ goto err;
+ }
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ break;
+ }
+
+ *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */
+ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */
+ *(z++) = (uint8_t) c << 6 | (uint8_t) d; /* ZZWWWWWW */
+ }
+
+ *z = 0;
+
+ *out_length = (size_t) (z - buf);
+ *out = (char *)buf;
+ return 0;
+err:
+ free(buf);
+
+ /* Ignore other errors in crypt_backend */
+ if (r != -ENOMEM)
+ r = -EINVAL;
+
+ return r;
+}
diff --git a/lib/crypto_backend/cipher_check.c b/lib/crypto_backend/cipher_check.c
new file mode 100644
index 0000000..98ec1a5
--- /dev/null
+++ b/lib/crypto_backend/cipher_check.c
@@ -0,0 +1,161 @@
+/*
+ * Cipher performance check
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <time.h>
+#include "crypto_backend_internal.h"
+
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+#endif
+
+/*
+ * This is not simulating storage, so using disk block causes extreme overhead.
+ * Let's use some fixed block size where results are more reliable...
+ */
+#define CIPHER_BLOCK_BYTES 65536
+
+/*
+ * If the measured value is lower, encrypted buffer is probably too small
+ * and calculated values are not reliable.
+ */
+#define CIPHER_TIME_MIN_MS 0.001
+
+/*
+ * The whole test depends on Linux kernel usermode crypto API for now.
+ * (The same implementations are used in dm-crypt though.)
+ */
+
+static int time_ms(struct timespec *start, struct timespec *end, double *ms)
+{
+ double start_ms, end_ms;
+
+ start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
+ end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
+
+ *ms = end_ms - start_ms;
+ return 0;
+}
+
+static int cipher_perf_one(const char *name, const char *mode, char *buffer, size_t buffer_size,
+ const char *key, size_t key_size, const char *iv, size_t iv_size, int enc)
+{
+ struct crypt_cipher_kernel cipher;
+ size_t done = 0, block = CIPHER_BLOCK_BYTES;
+ int r;
+
+ if (buffer_size < block)
+ block = buffer_size;
+
+ r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size);
+ if (r < 0)
+ return r;
+
+ while (done < buffer_size) {
+ if ((done + block) > buffer_size)
+ block = buffer_size - done;
+
+ if (enc)
+ r = crypt_cipher_encrypt_kernel(&cipher, &buffer[done], &buffer[done],
+ block, iv, iv_size);
+ else
+ r = crypt_cipher_decrypt_kernel(&cipher, &buffer[done], &buffer[done],
+ block, iv, iv_size);
+ if (r < 0)
+ break;
+
+ done += block;
+ }
+
+ crypt_cipher_destroy_kernel(&cipher);
+
+ return r;
+}
+static int cipher_measure(const char *name, const char *mode, char *buffer, size_t buffer_size,
+ const char *key, size_t key_size, const char *iv, size_t iv_size,
+ int encrypt, double *ms)
+{
+ struct timespec start, end;
+ int r;
+
+ /*
+ * Using getrusage would be better here but the precision
+ * is not adequate, so better stick with CLOCK_MONOTONIC
+ */
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &start) < 0)
+ return -EINVAL;
+
+ r = cipher_perf_one(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, encrypt);
+ if (r < 0)
+ return r;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &end) < 0)
+ return -EINVAL;
+
+ r = time_ms(&start, &end, ms);
+ if (r < 0)
+ return r;
+
+ if (*ms < CIPHER_TIME_MIN_MS)
+ return -ERANGE;
+
+ return 0;
+}
+
+static double speed_mbs(unsigned long bytes, double ms)
+{
+ double speed = bytes, s = ms / 1000.;
+
+ return speed / (1024 * 1024) / s;
+}
+
+int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
+ const char *key, size_t key_size, const char *iv, size_t iv_size,
+ double *encryption_mbs, double *decryption_mbs)
+{
+ double ms_enc, ms_dec, ms;
+ int r, repeat_enc, repeat_dec;
+
+ ms_enc = 0.0;
+ repeat_enc = 1;
+ while (ms_enc < 1000.0) {
+ r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 1, &ms);
+ if (r < 0)
+ return r;
+ ms_enc += ms;
+ repeat_enc++;
+ }
+
+ ms_dec = 0.0;
+ repeat_dec = 1;
+ while (ms_dec < 1000.0) {
+ r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 0, &ms);
+ if (r < 0)
+ return r;
+ ms_dec += ms;
+ repeat_dec++;
+ }
+
+ *encryption_mbs = speed_mbs(buffer_size * repeat_enc, ms_enc);
+ *decryption_mbs = speed_mbs(buffer_size * repeat_dec, ms_dec);
+
+ return 0;
+}
diff --git a/lib/crypto_backend/cipher_generic.c b/lib/crypto_backend/cipher_generic.c
new file mode 100644
index 0000000..b3a4407
--- /dev/null
+++ b/lib/crypto_backend/cipher_generic.c
@@ -0,0 +1,89 @@
+/*
+ * Linux kernel cipher generic utilities
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include "crypto_backend.h"
+
+struct cipher_alg {
+ const char *name;
+ const char *mode;
+ int blocksize;
+ bool wrapped_key;
+};
+
+static const struct cipher_alg cipher_algs[] = {
+ { "cipher_null", NULL, 16, false },
+ { "aes", NULL, 16, false },
+ { "serpent", NULL, 16, false },
+ { "twofish", NULL, 16, false },
+ { "anubis", NULL, 16, false },
+ { "blowfish", NULL, 8, false },
+ { "camellia", NULL, 16, false },
+ { "cast5", NULL, 8, false },
+ { "cast6", NULL, 16, false },
+ { "des", NULL, 8, false },
+ { "des3_ede", NULL, 8, false },
+ { "khazad", NULL, 8, false },
+ { "seed", NULL, 16, false },
+ { "tea", NULL, 8, false },
+ { "xtea", NULL, 8, false },
+ { "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */
+ { "xchacha12,aes", "adiantum", 32, false },
+ { "xchacha20,aes", "adiantum", 32, false },
+ { "sm4", NULL, 16, false },
+ { NULL, NULL, 0, false }
+};
+
+static const struct cipher_alg *_get_alg(const char *name, const char *mode)
+{
+ int i = 0;
+
+ while (name && cipher_algs[i].name) {
+ if (!strcasecmp(name, cipher_algs[i].name))
+ if (!mode || !cipher_algs[i].mode ||
+ !strncasecmp(mode, cipher_algs[i].mode, strlen(cipher_algs[i].mode)))
+ return &cipher_algs[i];
+ i++;
+ }
+ return NULL;
+}
+
+int crypt_cipher_ivsize(const char *name, const char *mode)
+{
+ const struct cipher_alg *ca = _get_alg(name, mode);
+
+ if (!ca)
+ return -EINVAL;
+
+ if (mode && !strcasecmp(mode, "ecb"))
+ return 0;
+
+ return ca->blocksize;
+}
+
+int crypt_cipher_wrapped_key(const char *name, const char *mode)
+{
+ const struct cipher_alg *ca = _get_alg(name, mode);
+
+ return ca ? (int)ca->wrapped_key : 0;
+}
diff --git a/lib/crypto_backend/crc32.c b/lib/crypto_backend/crc32.c
new file mode 100644
index 0000000..9009b02
--- /dev/null
+++ b/lib/crypto_backend/crc32.c
@@ -0,0 +1,183 @@
+/*
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ *
+ * First, the polynomial itself and its table of feedback terms. The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
+ * the MSB being 1.
+ *
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term. In our
+ * implementation, that means shifting towards the right. Why do we
+ * do it this way? Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term. UARTs transmit
+ * characters in order from LSB to MSB. By storing the CRC this way,
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to high-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part. Reception works similarly.
+ *
+ * The feedback terms table consists of 256, 32-bit entries. Notes
+ *
+ * The table can be generated at runtime if desired; code to do so
+ * is shown later. It might not be obvious, but the feedback
+ * terms simply represent the results of eight shift/xor opera-
+ * tions for all combinations of data and CRC register values.
+ *
+ * The values must be right-shifted by eight bits by the "updcrc"
+ * logic; the shift must be unsigned (bring in zeroes). On some
+ * hardware you could probably optimize the shift in assembler by
+ * using byte-swap instructions.
+ * polynomial $edb88320
+ *
+ */
+
+#include <stdio.h>
+
+#include "crypto_backend.h"
+
+static const uint32_t crc32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+static const uint32_t crc32c_tab[] = {
+ 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL,
+ 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL,
+ 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L,
+ 0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
+ 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L,
+ 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL,
+ 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L,
+ 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
+ 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL,
+ 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L,
+ 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L,
+ 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
+ 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL,
+ 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L,
+ 0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L,
+ 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
+ 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL,
+ 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL,
+ 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L,
+ 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
+ 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL,
+ 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L,
+ 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL,
+ 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
+ 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL,
+ 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL,
+ 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L,
+ 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
+ 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L,
+ 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL,
+ 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL,
+ 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
+ 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L,
+ 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL,
+ 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L,
+ 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
+ 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L,
+ 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL,
+ 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L,
+ 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
+ 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L,
+ 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L,
+ 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L,
+ 0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
+ 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL,
+ 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L,
+ 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L,
+ 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
+ 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL,
+ 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L,
+ 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L,
+ 0xAD7D5351L
+};
+
+/*
+ * This a generic crc32() function, it takes seed as an argument,
+ * and does __not__ xor at the end. Then individual users can do
+ * whatever they need.
+ */
+static uint32_t compute_crc32(
+ const uint32_t *crc32_tab,
+ uint32_t seed,
+ const unsigned char *buf,
+ size_t len)
+{
+ uint32_t crc = seed;
+ const unsigned char *p = buf;
+
+ while(len-- > 0)
+ crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+
+ return crc;
+}
+
+uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
+{
+ return compute_crc32(crc32_tab, seed, buf, len);
+}
+
+uint32_t crypt_crc32c(uint32_t seed, const unsigned char *buf, size_t len)
+{
+ return compute_crc32(crc32c_tab, seed, buf, len);
+}
diff --git a/lib/crypto_backend/crypto_backend.h b/lib/crypto_backend/crypto_backend.h
new file mode 100644
index 0000000..88562e9
--- /dev/null
+++ b/lib/crypto_backend/crypto_backend.h
@@ -0,0 +1,161 @@
+/*
+ * crypto backend implementation
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef _CRYPTO_BACKEND_H
+#define _CRYPTO_BACKEND_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#ifdef HAVE_UCHAR_H
+#include <uchar.h>
+#else
+#define char32_t uint32_t
+#define char16_t uint16_t
+#endif
+
+struct crypt_hash;
+struct crypt_hmac;
+struct crypt_cipher;
+struct crypt_storage;
+
+int crypt_backend_init(bool fips);
+void crypt_backend_destroy(void);
+
+#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
+#define CRYPT_BACKEND_PBKDF2_INT (1 << 1) /* Iteration in PBKDF2 is signed int and can overflow */
+
+uint32_t crypt_backend_flags(void);
+const char *crypt_backend_version(void);
+
+/* HASH */
+int crypt_hash_size(const char *name);
+int crypt_hash_init(struct crypt_hash **ctx, const char *name);
+int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length);
+int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length);
+void crypt_hash_destroy(struct crypt_hash *ctx);
+
+/* HMAC */
+int crypt_hmac_size(const char *name);
+int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
+ const void *key, size_t key_length);
+int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length);
+int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length);
+void crypt_hmac_destroy(struct crypt_hmac *ctx);
+
+/* RNG (if fips parameter set, must provide FIPS compliance) */
+enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 };
+int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
+
+
+/* PBKDF*/
+struct crypt_pbkdf_limits {
+ uint32_t min_iterations, max_iterations;
+ uint32_t min_memory, max_memory, min_bench_memory;
+ uint32_t min_parallel, max_parallel;
+};
+
+int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *l);
+int crypt_pbkdf(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel);
+int crypt_pbkdf_perf(const char *kdf, const char *hash,
+ const char *password, size_t password_size,
+ const char *salt, size_t salt_size,
+ size_t volume_key_size, uint32_t time_ms,
+ uint32_t max_memory_kb, uint32_t parallel_threads,
+ uint32_t *iterations_out, uint32_t *memory_out,
+ int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr);
+
+/* CRC32 */
+uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len);
+uint32_t crypt_crc32c(uint32_t seed, const unsigned char *buf, size_t len);
+
+/* Base64 */
+int crypt_base64_encode(char **out, size_t *out_length, const char *in, size_t in_length);
+int crypt_base64_decode(char **out, size_t *out_length, const char *in, size_t in_length);
+
+/* UTF8/16 */
+int crypt_utf16_to_utf8(char **out, const char16_t *s, size_t length /* bytes! */);
+int crypt_utf8_to_utf16(char16_t **out, const char *s, size_t length);
+
+/* Block ciphers */
+int crypt_cipher_ivsize(const char *name, const char *mode);
+int crypt_cipher_wrapped_key(const char *name, const char *mode);
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key, size_t key_length);
+void crypt_cipher_destroy(struct crypt_cipher *ctx);
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length);
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length);
+bool crypt_cipher_kernel_only(struct crypt_cipher *ctx);
+
+/* Benchmark of kernel cipher performance */
+int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
+ const char *key, size_t key_size, const char *iv, size_t iv_size,
+ double *encryption_mbs, double *decryption_mbs);
+
+/* Check availability of a cipher (in kernel only) */
+int crypt_cipher_check_kernel(const char *name, const char *mode,
+ const char *integrity, size_t key_length);
+
+/* Storage encryption wrappers */
+int crypt_storage_init(struct crypt_storage **ctx, size_t sector_size,
+ const char *cipher, const char *cipher_mode,
+ const void *key, size_t key_length, bool large_iv);
+void crypt_storage_destroy(struct crypt_storage *ctx);
+int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t iv_offset,
+ uint64_t length, char *buffer);
+int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t iv_offset,
+ uint64_t length, char *buffer);
+
+bool crypt_storage_kernel_only(struct crypt_storage *ctx);
+
+/* Temporary Bitlk helper */
+int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length);
+
+/* Memzero helper (memset on stack can be optimized out) */
+static inline void crypt_backend_memzero(void *s, size_t n)
+{
+#ifdef HAVE_EXPLICIT_BZERO
+ explicit_bzero(s, n);
+#else
+ volatile uint8_t *p = (volatile uint8_t *)s;
+ while(n--) *p++ = 0;
+#endif
+}
+
+/* Memcmp helper (memcmp in constant time) */
+int crypt_backend_memeq(const void *m1, const void *m2, size_t n);
+
+/* crypto backend running in FIPS mode */
+bool crypt_fips_mode(void);
+
+#endif /* _CRYPTO_BACKEND_H */
diff --git a/lib/crypto_backend/crypto_backend_internal.h b/lib/crypto_backend/crypto_backend_internal.h
new file mode 100644
index 0000000..9b1cc69
--- /dev/null
+++ b/lib/crypto_backend/crypto_backend_internal.h
@@ -0,0 +1,75 @@
+/*
+ * crypto backend implementation
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef _CRYPTO_BACKEND_INTERNAL_H
+#define _CRYPTO_BACKEND_INTERNAL_H
+
+#include "crypto_backend.h"
+
+/* internal PBKDF2 implementation */
+int pkcs5_pbkdf2(const char *hash,
+ const char *P, size_t Plen,
+ const char *S, size_t Slen,
+ unsigned int c,
+ unsigned int dkLen, char *DK,
+ unsigned int hash_block_size);
+
+/* Argon2 implementation wrapper */
+int argon2(const char *type, const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel);
+
+/* Block ciphers: fallback to kernel crypto API */
+
+struct crypt_cipher_kernel {
+ int tfmfd;
+ int opfd;
+};
+
+int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
+ const char *mode, const void *key, size_t key_length);
+int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length);
+int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length);
+void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx);
+int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length);
+
+/* Internal implementation for constant time memory comparison */
+static inline int crypt_internal_memeq(const void *m1, const void *m2, size_t n)
+{
+ const unsigned char *_m1 = (const unsigned char *) m1;
+ const unsigned char *_m2 = (const unsigned char *) m2;
+ unsigned char result = 0;
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ result |= _m1[i] ^ _m2[i];
+
+ return result;
+}
+
+#endif /* _CRYPTO_BACKEND_INTERNAL_H */
diff --git a/lib/crypto_backend/crypto_cipher_kernel.c b/lib/crypto_backend/crypto_cipher_kernel.c
new file mode 100644
index 0000000..3460717
--- /dev/null
+++ b/lib/crypto_backend/crypto_cipher_kernel.c
@@ -0,0 +1,351 @@
+/*
+ * Linux kernel userspace API crypto backend implementation (skcipher)
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include "crypto_backend_internal.h"
+
+#ifdef ENABLE_AF_ALG
+
+#include <linux/if_alg.h>
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+#ifndef ALG_SET_AEAD_AUTHSIZE
+#define ALG_SET_AEAD_AUTHSIZE 5
+#endif
+
+/*
+ * ciphers
+ *
+ * ENOENT - algorithm not available
+ * ENOTSUP - AF_ALG family not available
+ * (but cannot check specifically for skcipher API)
+ */
+static int _crypt_cipher_init(struct crypt_cipher_kernel *ctx,
+ const void *key, size_t key_length,
+ size_t tag_length, struct sockaddr_alg *sa)
+{
+ if (!ctx)
+ return -EINVAL;
+
+ ctx->opfd = -1;
+ ctx->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (ctx->tfmfd < 0) {
+ crypt_cipher_destroy_kernel(ctx);
+ return -ENOTSUP;
+ }
+
+ if (bind(ctx->tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
+ crypt_cipher_destroy_kernel(ctx);
+ return -ENOENT;
+ }
+
+ if (setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
+ crypt_cipher_destroy_kernel(ctx);
+ return -EINVAL;
+ }
+
+ if (tag_length && setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, tag_length) < 0) {
+ crypt_cipher_destroy_kernel(ctx);
+ return -EINVAL;
+ }
+
+ ctx->opfd = accept(ctx->tfmfd, NULL, 0);
+ if (ctx->opfd < 0) {
+ crypt_cipher_destroy_kernel(ctx);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "skcipher",
+ };
+ int r;
+
+ if (!strcmp(name, "cipher_null"))
+ key_length = 0;
+
+ r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
+ if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
+ return -EINVAL;
+
+ return _crypt_cipher_init(ctx, key, key_length, 0, &sa);
+}
+
+/* The in/out should be aligned to page boundary */
+static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
+ const char *in, size_t in_length,
+ char *out, size_t out_length,
+ const char *iv, size_t iv_length,
+ uint32_t direction)
+{
+ int r = 0;
+ ssize_t len;
+ struct af_alg_iv *alg_iv;
+ struct cmsghdr *header;
+ uint32_t *type;
+ struct iovec iov = {
+ .iov_base = (void*)(uintptr_t)in,
+ .iov_len = in_length,
+ };
+ int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
+ char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
+ struct msghdr msg = {
+ .msg_control = buffer,
+ .msg_controllen = sizeof(buffer),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ if (!in || !out || !in_length)
+ return -EINVAL;
+
+ if ((!iv && iv_length) || (iv && !iv_length))
+ return -EINVAL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Set encrypt/decrypt operation */
+ header = CMSG_FIRSTHDR(&msg);
+ if (!header)
+ return -EINVAL;
+
+ header->cmsg_level = SOL_ALG;
+ header->cmsg_type = ALG_SET_OP;
+ header->cmsg_len = CMSG_LEN(sizeof(*type));
+ type = (void*)CMSG_DATA(header);
+ *type = direction;
+
+ /* Set IV */
+ if (iv) {
+ header = CMSG_NXTHDR(&msg, header);
+ if (!header)
+ return -EINVAL;
+
+ header->cmsg_level = SOL_ALG;
+ header->cmsg_type = ALG_SET_IV;
+ header->cmsg_len = iv_msg_size;
+ alg_iv = (void*)CMSG_DATA(header);
+ alg_iv->ivlen = iv_length;
+ memcpy(alg_iv->iv, iv, iv_length);
+ }
+
+ len = sendmsg(ctx->opfd, &msg, 0);
+ if (len != (ssize_t)(in_length))
+ r = -EIO;
+ else {
+ len = read(ctx->opfd, out, out_length);
+ if (len != (ssize_t)out_length)
+ r = -EIO;
+ }
+
+ crypt_backend_memzero(buffer, sizeof(buffer));
+ return r;
+}
+
+int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return _crypt_cipher_crypt(ctx, in, length, out, length,
+ iv, iv_length, ALG_OP_ENCRYPT);
+}
+
+int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return _crypt_cipher_crypt(ctx, in, length, out, length,
+ iv, iv_length, ALG_OP_DECRYPT);
+}
+
+void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx)
+{
+ if (ctx->tfmfd >= 0)
+ close(ctx->tfmfd);
+ if (ctx->opfd >= 0)
+ close(ctx->opfd);
+
+ ctx->tfmfd = -1;
+ ctx->opfd = -1;
+}
+
+int crypt_cipher_check_kernel(const char *name, const char *mode,
+ const char *integrity, size_t key_length)
+{
+ struct crypt_cipher_kernel c;
+ char mode_name[64], tmp_salg_name[180], *real_mode = NULL, *cipher_iv = NULL, *key;
+ const char *salg_type;
+ bool aead;
+ int r;
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ };
+
+ aead = integrity && strcmp(integrity, "none");
+
+ /* Remove IV if present */
+ if (mode) {
+ strncpy(mode_name, mode, sizeof(mode_name));
+ mode_name[sizeof(mode_name) - 1] = 0;
+ cipher_iv = strchr(mode_name, '-');
+ if (cipher_iv) {
+ *cipher_iv = '\0';
+ real_mode = mode_name;
+ }
+ }
+
+ salg_type = aead ? "aead" : "skcipher";
+ r = snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type);
+ if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
+ return -EINVAL;
+
+ memset(tmp_salg_name, 0, sizeof(tmp_salg_name));
+
+ /* FIXME: this is duplicating a part of devmapper backend */
+ if (aead && !strcmp(integrity, "poly1305"))
+ r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc7539(%s,%s)", name, integrity);
+ else if (!real_mode)
+ r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name);
+ else if (aead && !strcmp(real_mode, "ccm"))
+ r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc4309(%s(%s))", real_mode, name);
+ else
+ r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
+
+ if (r < 0 || (size_t)r >= sizeof(tmp_salg_name))
+ return -EINVAL;
+
+ memcpy(sa.salg_name, tmp_salg_name, sizeof(sa.salg_name));
+
+ key = malloc(key_length);
+ if (!key)
+ return -ENOMEM;
+
+ /* We cannot use RNG yet, any key works here, tweak the first part if it is split key (XTS). */
+ memset(key, 0xab, key_length);
+ *key = 0xef;
+
+ r = _crypt_cipher_init(&c, key, key_length, 0, &sa);
+ crypt_cipher_destroy_kernel(&c);
+ free(key);
+
+ return r;
+}
+
+int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+ struct crypt_cipher_kernel c;
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "aead",
+ .salg_name = "ccm(aes)",
+ };
+ int r;
+ char buffer[128], ccm_iv[16];
+
+ if (length + tag_length > sizeof(buffer))
+ return -EINVAL;
+
+ if (iv_length > sizeof(ccm_iv) - 2)
+ return -EINVAL;
+
+ r = _crypt_cipher_init(&c, key, key_length, tag_length, &sa);
+ if (r < 0)
+ return r;
+
+ memcpy(buffer, in, length);
+ memcpy(buffer + length, tag, tag_length);
+
+ /* CCM IV - RFC3610 */
+ memset(ccm_iv, 0, sizeof(ccm_iv));
+ ccm_iv[0] = 15 - iv_length - 1;
+ memcpy(ccm_iv + 1, iv, iv_length);
+ memset(ccm_iv + 1 + iv_length, 0, ccm_iv[0] + 1);
+ iv_length = sizeof(ccm_iv);
+
+ r = _crypt_cipher_crypt(&c, buffer, length + tag_length, out, length,
+ ccm_iv, iv_length, ALG_OP_DECRYPT);
+
+ crypt_cipher_destroy_kernel(&c);
+ crypt_backend_memzero(buffer, sizeof(buffer));
+
+ return r;
+}
+
+#else /* ENABLE_AF_ALG */
+int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ return -ENOTSUP;
+}
+
+void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx)
+{
+ return;
+}
+
+int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return -EINVAL;
+}
+int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return -EINVAL;
+}
+int crypt_cipher_check_kernel(const char *name, const char *mode,
+ const char *integrity, size_t key_length)
+{
+ /* Cannot check, expect success. */
+ return 0;
+}
+int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+ return -ENOTSUP;
+}
+#endif
diff --git a/lib/crypto_backend/crypto_gcrypt.c b/lib/crypto_backend/crypto_gcrypt.c
new file mode 100644
index 0000000..e974aa8
--- /dev/null
+++ b/lib/crypto_backend/crypto_gcrypt.c
@@ -0,0 +1,573 @@
+/*
+ * GCRYPT crypto backend implementation
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <gcrypt.h>
+#include "crypto_backend_internal.h"
+
+static int crypto_backend_initialised = 0;
+static int crypto_backend_secmem = 1;
+static int crypto_backend_whirlpool_bug = -1;
+static char version[64];
+
+struct crypt_hash {
+ gcry_md_hd_t hd;
+ int hash_id;
+ int hash_len;
+};
+
+struct crypt_hmac {
+ gcry_md_hd_t hd;
+ int hash_id;
+ int hash_len;
+};
+
+struct crypt_cipher {
+ bool use_kernel;
+ union {
+ struct crypt_cipher_kernel kernel;
+ gcry_cipher_hd_t hd;
+ } u;
+};
+
+struct hash_alg {
+ const char *name;
+ const char *gcrypt_name;
+};
+
+/*
+ * Test for wrong Whirlpool variant,
+ * Ref: https://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
+ */
+static void crypt_hash_test_whirlpool_bug(void)
+{
+ struct crypt_hash *h;
+ char buf[2] = "\0\0", hash_out1[64], hash_out2[64];
+ int r;
+
+ if (crypto_backend_whirlpool_bug >= 0)
+ return;
+
+ crypto_backend_whirlpool_bug = 0;
+ if (crypt_hash_init(&h, "whirlpool"))
+ return;
+
+ /* One shot */
+ if ((r = crypt_hash_write(h, &buf[0], 2)) ||
+ (r = crypt_hash_final(h, hash_out1, 64))) {
+ crypt_hash_destroy(h);
+ return;
+ }
+
+ /* Split buf (crypt_hash_final resets hash state) */
+ if ((r = crypt_hash_write(h, &buf[0], 1)) ||
+ (r = crypt_hash_write(h, &buf[1], 1)) ||
+ (r = crypt_hash_final(h, hash_out2, 64))) {
+ crypt_hash_destroy(h);
+ return;
+ }
+
+ crypt_hash_destroy(h);
+
+ if (memcmp(hash_out1, hash_out2, 64))
+ crypto_backend_whirlpool_bug = 1;
+}
+
+int crypt_backend_init(bool fips __attribute__((unused)))
+{
+ int r;
+
+ if (crypto_backend_initialised)
+ return 0;
+
+ if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
+ if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
+ return -ENOSYS;
+ }
+
+/* If gcrypt compiled to support POSIX 1003.1e capabilities,
+ * it drops all privileges during secure memory initialisation.
+ * For now, the only workaround is to disable secure memory in gcrypt.
+ * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
+ * and it locks its memory space anyway.
+ */
+#if 0
+ gcry_control (GCRYCTL_DISABLE_SECMEM);
+ crypto_backend_secmem = 0;
+#else
+
+ gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
+ gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+ gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
+#endif
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+ }
+
+ crypto_backend_initialised = 1;
+ crypt_hash_test_whirlpool_bug();
+
+ r = snprintf(version, sizeof(version), "gcrypt %s%s%s",
+ gcry_check_version(NULL),
+ crypto_backend_secmem ? "" : ", secmem disabled",
+ crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "");
+ if (r < 0 || (size_t)r >= sizeof(version))
+ return -EINVAL;
+
+ return 0;
+}
+
+void crypt_backend_destroy(void)
+{
+ if (crypto_backend_initialised)
+ gcry_control(GCRYCTL_TERM_SECMEM);
+
+ crypto_backend_initialised = 0;
+}
+
+const char *crypt_backend_version(void)
+{
+ return crypto_backend_initialised ? version : "";
+}
+
+uint32_t crypt_backend_flags(void)
+{
+ return 0;
+}
+
+static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
+{
+ const char *hash_name = name;
+ int i;
+ static struct hash_alg hash_algs[] = {
+ { "blake2b-160", "blake2b_160" },
+ { "blake2b-256", "blake2b_256" },
+ { "blake2b-384", "blake2b_384" },
+ { "blake2b-512", "blake2b_512" },
+ { "blake2s-128", "blake2s_128" },
+ { "blake2s-160", "blake2s_160" },
+ { "blake2s-224", "blake2s_224" },
+ { "blake2s-256", "blake2s_256" },
+ { NULL, NULL, }};
+
+ if (!name)
+ return NULL;
+
+ /* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
+ * in libgcrypt < 1.6.0 */
+ if (!strcasecmp(name, "whirlpool_gcryptbug")) {
+#if GCRYPT_VERSION_NUMBER >= 0x010601
+ if (flags)
+ *flags |= GCRY_MD_FLAG_BUGEMU1;
+#endif
+ hash_name = "whirlpool";
+ }
+
+ i = 0;
+ while (hash_algs[i].name) {
+ if (!strcasecmp(name, hash_algs[i].name)) {
+ hash_name = hash_algs[i].gcrypt_name;
+ break;
+ }
+ i++;
+ }
+
+ return hash_name;
+}
+
+/* HASH */
+int crypt_hash_size(const char *name)
+{
+ int hash_id;
+
+ assert(crypto_backend_initialised);
+
+ hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL));
+ if (!hash_id)
+ return -EINVAL;
+
+ return gcry_md_get_algo_dlen(hash_id);
+}
+
+int crypt_hash_init(struct crypt_hash **ctx, const char *name)
+{
+ struct crypt_hash *h;
+ unsigned int flags = 0;
+
+ assert(crypto_backend_initialised);
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
+ if (!h->hash_id) {
+ free(h);
+ return -EINVAL;
+ }
+
+ if (gcry_md_open(&h->hd, h->hash_id, flags)) {
+ free(h);
+ return -EINVAL;
+ }
+
+ h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
+ *ctx = h;
+ return 0;
+}
+
+static void crypt_hash_restart(struct crypt_hash *ctx)
+{
+ gcry_md_reset(ctx->hd);
+}
+
+int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
+{
+ gcry_md_write(ctx->hd, buffer, length);
+ return 0;
+}
+
+int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
+{
+ unsigned char *hash;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ hash = gcry_md_read(ctx->hd, ctx->hash_id);
+ if (!hash)
+ return -EINVAL;
+
+ memcpy(buffer, hash, length);
+ crypt_hash_restart(ctx);
+
+ return 0;
+}
+
+void crypt_hash_destroy(struct crypt_hash *ctx)
+{
+ gcry_md_close(ctx->hd);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* HMAC */
+int crypt_hmac_size(const char *name)
+{
+ return crypt_hash_size(name);
+}
+
+int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
+ const void *key, size_t key_length)
+{
+ struct crypt_hmac *h;
+ unsigned int flags = GCRY_MD_FLAG_HMAC;
+
+ assert(crypto_backend_initialised);
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
+ if (!h->hash_id) {
+ free(h);
+ return -EINVAL;
+ }
+
+ if (gcry_md_open(&h->hd, h->hash_id, flags)) {
+ free(h);
+ return -EINVAL;
+ }
+
+ if (gcry_md_setkey(h->hd, key, key_length)) {
+ gcry_md_close(h->hd);
+ free(h);
+ return -EINVAL;
+ }
+
+ h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
+ *ctx = h;
+ return 0;
+}
+
+static void crypt_hmac_restart(struct crypt_hmac *ctx)
+{
+ gcry_md_reset(ctx->hd);
+}
+
+int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
+{
+ gcry_md_write(ctx->hd, buffer, length);
+ return 0;
+}
+
+int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
+{
+ unsigned char *hash;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ hash = gcry_md_read(ctx->hd, ctx->hash_id);
+ if (!hash)
+ return -EINVAL;
+
+ memcpy(buffer, hash, length);
+ crypt_hmac_restart(ctx);
+
+ return 0;
+}
+
+void crypt_hmac_destroy(struct crypt_hmac *ctx)
+{
+ gcry_md_close(ctx->hd);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* RNG */
+int crypt_backend_rng(char *buffer, size_t length, int quality, int fips __attribute__((unused)))
+{
+ switch(quality) {
+ case CRYPT_RND_NORMAL:
+ gcry_randomize(buffer, length, GCRY_STRONG_RANDOM);
+ break;
+ case CRYPT_RND_SALT:
+ case CRYPT_RND_KEY:
+ default:
+ gcry_randomize(buffer, length, GCRY_VERY_STRONG_RANDOM);
+ break;
+ }
+ return 0;
+}
+
+static int pbkdf2(const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations)
+{
+ const char *hash_name = crypt_hash_compat_name(hash, NULL);
+
+#if USE_INTERNAL_PBKDF2
+ return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
+ iterations, key_length, key, 0);
+#else /* USE_INTERNAL_PBKDF2 */
+ int hash_id = gcry_md_map_name(hash_name);
+
+ if (!hash_id)
+ return -EINVAL;
+
+ if (gcry_kdf_derive(password, password_length, GCRY_KDF_PBKDF2, hash_id,
+ salt, salt_length, iterations, key_length, key))
+ return -EINVAL;
+
+ return 0;
+#endif /* USE_INTERNAL_PBKDF2 */
+}
+
+/* PBKDF */
+int crypt_pbkdf(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ if (!kdf)
+ return -EINVAL;
+
+ if (!strcmp(kdf, "pbkdf2"))
+ return pbkdf2(hash, password, password_length, salt, salt_length,
+ key, key_length, iterations);
+ else if (!strncmp(kdf, "argon2", 6))
+ return argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+ return -EINVAL;
+}
+
+/* Block ciphers */
+static int _cipher_init(gcry_cipher_hd_t *hd, const char *name,
+ const char *mode, const void *buffer, size_t length)
+{
+ int cipher_id, mode_id;
+
+ cipher_id = gcry_cipher_map_name(name);
+ if (cipher_id == GCRY_CIPHER_MODE_NONE)
+ return -ENOENT;
+
+ if (!strcmp(mode, "ecb"))
+ mode_id = GCRY_CIPHER_MODE_ECB;
+ else if (!strcmp(mode, "cbc"))
+ mode_id = GCRY_CIPHER_MODE_CBC;
+#if HAVE_DECL_GCRY_CIPHER_MODE_XTS
+ else if (!strcmp(mode, "xts"))
+ mode_id = GCRY_CIPHER_MODE_XTS;
+#endif
+ else
+ return -ENOENT;
+
+ if (gcry_cipher_open(hd, cipher_id, mode_id, 0))
+ return -EINVAL;
+
+ if (gcry_cipher_setkey(*hd, buffer, length)) {
+ gcry_cipher_close(*hd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ struct crypt_cipher *h;
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ if (!_cipher_init(&h->u.hd, name, mode, key, key_length)) {
+ h->use_kernel = false;
+ *ctx = h;
+ return 0;
+ }
+
+ r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ h->use_kernel = true;
+ *ctx = h;
+ return 0;
+}
+
+void crypt_cipher_destroy(struct crypt_cipher *ctx)
+{
+ if (ctx->use_kernel)
+ crypt_cipher_destroy_kernel(&ctx->u.kernel);
+ else
+ gcry_cipher_close(ctx->u.hd);
+ free(ctx);
+}
+
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ if (ctx->use_kernel)
+ return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
+
+ if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length))
+ return -EINVAL;
+
+ if (gcry_cipher_encrypt(ctx->u.hd, out, length, in, length))
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ if (ctx->use_kernel)
+ return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
+
+ if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length))
+ return -EINVAL;
+
+ if (gcry_cipher_decrypt(ctx->u.hd, out, length, in, length))
+ return -EINVAL;
+
+ return 0;
+}
+
+bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
+{
+ return ctx->use_kernel;
+}
+
+int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+#ifdef GCRY_CCM_BLOCK_LEN
+ gcry_cipher_hd_t hd;
+ uint64_t l[3];
+ int r = -EINVAL;
+
+ if (gcry_cipher_open(&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CCM, 0))
+ return -EINVAL;
+
+ if (gcry_cipher_setkey(hd, key, key_length))
+ goto out;
+
+ if (gcry_cipher_setiv(hd, iv, iv_length))
+ goto out;
+
+ l[0] = length;
+ l[1] = 0;
+ l[2] = tag_length;
+ if (gcry_cipher_ctl(hd, GCRYCTL_SET_CCM_LENGTHS, l, sizeof(l)))
+ goto out;
+
+ if (gcry_cipher_decrypt(hd, out, length, in, length))
+ goto out;
+
+ if (gcry_cipher_checktag(hd, tag, tag_length))
+ goto out;
+
+ r = 0;
+out:
+ gcry_cipher_close(hd);
+ return r;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
+{
+ return crypt_internal_memeq(m1, m2, n);
+}
+
+#if !ENABLE_FIPS
+bool crypt_fips_mode(void) { return false; }
+#else
+bool crypt_fips_mode(void)
+{
+ static bool fips_mode = false, fips_checked = false;
+
+ if (fips_checked)
+ return fips_mode;
+
+ fips_mode = gcry_fips_mode_active();
+ fips_checked = true;
+
+ return fips_mode;
+}
+#endif /* ENABLE FIPS */
diff --git a/lib/crypto_backend/crypto_kernel.c b/lib/crypto_backend/crypto_kernel.c
new file mode 100644
index 0000000..8493c0a
--- /dev/null
+++ b/lib/crypto_backend/crypto_kernel.c
@@ -0,0 +1,428 @@
+/*
+ * Linux kernel userspace API crypto backend implementation
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/utsname.h>
+#include <linux/if_alg.h>
+#include "crypto_backend_internal.h"
+
+#ifndef AF_ALG
+#define AF_ALG 38
+#endif
+#ifndef SOL_ALG
+#define SOL_ALG 279
+#endif
+
+static int crypto_backend_initialised = 0;
+static char version[256];
+
+struct hash_alg {
+ const char *name;
+ const char *kernel_name;
+ int length;
+ unsigned int block_length;
+};
+
+static struct hash_alg hash_algs[] = {
+ { "sha1", "sha1", 20, 64 },
+ { "sha224", "sha224", 28, 64 },
+ { "sha256", "sha256", 32, 64 },
+ { "sha384", "sha384", 48, 128 },
+ { "sha512", "sha512", 64, 128 },
+ { "ripemd160", "rmd160", 20, 64 },
+ { "whirlpool", "wp512", 64, 64 },
+ { "sha3-224", "sha3-224", 28, 144 },
+ { "sha3-256", "sha3-256", 32, 136 },
+ { "sha3-384", "sha3-384", 48, 104 },
+ { "sha3-512", "sha3-512", 64, 72 },
+ { "stribog256","streebog256", 32, 64 },
+ { "stribog512","streebog512", 64, 64 },
+ { "sm3", "sm3", 32, 64 },
+ { "blake2b-160","blake2b-160",20, 128 },
+ { "blake2b-256","blake2b-256",32, 128 },
+ { "blake2b-384","blake2b-384",48, 128 },
+ { "blake2b-512","blake2b-512",64, 128 },
+ { "blake2s-128","blake2s-128",16, 64 },
+ { "blake2s-160","blake2s-160",20, 64 },
+ { "blake2s-224","blake2s-224",28, 64 },
+ { "blake2s-256","blake2s-256",32, 64 },
+ { NULL, NULL, 0, 0 }
+};
+
+struct crypt_hash {
+ int tfmfd;
+ int opfd;
+ int hash_len;
+};
+
+struct crypt_hmac {
+ int tfmfd;
+ int opfd;
+ int hash_len;
+};
+
+struct crypt_cipher {
+ struct crypt_cipher_kernel ck;
+};
+
+static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd,
+ const void *key, size_t key_length)
+{
+ *tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+ if (*tfmfd < 0)
+ return -ENOTSUP;
+
+ if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
+ close(*tfmfd);
+ *tfmfd = -1;
+ return -ENOENT;
+ }
+
+ if (key && setsockopt(*tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
+ close(*tfmfd);
+ *tfmfd = -1;
+ return -EINVAL;
+ }
+
+ *opfd = accept(*tfmfd, NULL, 0);
+ if (*opfd < 0) {
+ close(*tfmfd);
+ *tfmfd = -1;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int crypt_backend_init(bool fips __attribute__((unused)))
+{
+ struct utsname uts;
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ .salg_name = "sha256",
+ };
+ int r, tfmfd = -1, opfd = -1;
+
+ if (crypto_backend_initialised)
+ return 0;
+
+ if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
+ return -EINVAL;
+
+ r = snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
+ uts.sysname, uts.release);
+ if (r < 0 || (size_t)r >= sizeof(version))
+ return -EINVAL;
+
+ if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0)
+ return -EINVAL;
+
+ close(tfmfd);
+ close(opfd);
+
+ crypto_backend_initialised = 1;
+ return 0;
+}
+
+void crypt_backend_destroy(void)
+{
+ crypto_backend_initialised = 0;
+}
+
+uint32_t crypt_backend_flags(void)
+{
+ return CRYPT_BACKEND_KERNEL;
+}
+
+const char *crypt_backend_version(void)
+{
+ return crypto_backend_initialised ? version : "";
+}
+
+static struct hash_alg *_get_alg(const char *name)
+{
+ int i = 0;
+
+ while (name && hash_algs[i].name) {
+ if (!strcmp(name, hash_algs[i].name))
+ return &hash_algs[i];
+ i++;
+ }
+ return NULL;
+}
+
+/* HASH */
+int crypt_hash_size(const char *name)
+{
+ struct hash_alg *ha = _get_alg(name);
+
+ return ha ? ha->length : -EINVAL;
+}
+
+int crypt_hash_init(struct crypt_hash **ctx, const char *name)
+{
+ struct crypt_hash *h;
+ struct hash_alg *ha;
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ };
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ ha = _get_alg(name);
+ if (!ha) {
+ free(h);
+ return -EINVAL;
+ }
+ h->hash_len = ha->length;
+
+ strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name)-1);
+
+ if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, NULL, 0) < 0) {
+ free(h);
+ return -EINVAL;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
+{
+ ssize_t r;
+
+ r = send(ctx->opfd, buffer, length, MSG_MORE);
+ if (r < 0 || (size_t)r < length)
+ return -EIO;
+
+ return 0;
+}
+
+int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
+{
+ ssize_t r;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ r = read(ctx->opfd, buffer, length);
+ if (r < 0)
+ return -EIO;
+
+ return 0;
+}
+
+void crypt_hash_destroy(struct crypt_hash *ctx)
+{
+ if (ctx->tfmfd >= 0)
+ close(ctx->tfmfd);
+ if (ctx->opfd >= 0)
+ close(ctx->opfd);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* HMAC */
+int crypt_hmac_size(const char *name)
+{
+ return crypt_hash_size(name);
+}
+
+int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
+ const void *key, size_t key_length)
+{
+ struct crypt_hmac *h;
+ struct hash_alg *ha;
+ struct sockaddr_alg sa = {
+ .salg_family = AF_ALG,
+ .salg_type = "hash",
+ };
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ ha = _get_alg(name);
+ if (!ha) {
+ free(h);
+ return -EINVAL;
+ }
+ h->hash_len = ha->length;
+
+ r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
+ "hmac(%s)", ha->kernel_name);
+ if (r < 0 || (size_t)r >= sizeof(sa.salg_name)) {
+ free(h);
+ return -EINVAL;
+ }
+
+ if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, key, key_length) < 0) {
+ free(h);
+ return -EINVAL;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
+{
+ ssize_t r;
+
+ r = send(ctx->opfd, buffer, length, MSG_MORE);
+ if (r < 0 || (size_t)r < length)
+ return -EIO;
+
+ return 0;
+}
+
+int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
+{
+ ssize_t r;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ r = read(ctx->opfd, buffer, length);
+ if (r < 0)
+ return -EIO;
+
+ return 0;
+}
+
+void crypt_hmac_destroy(struct crypt_hmac *ctx)
+{
+ if (ctx->tfmfd >= 0)
+ close(ctx->tfmfd);
+ if (ctx->opfd >= 0)
+ close(ctx->opfd);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* RNG - N/A */
+int crypt_backend_rng(char *buffer __attribute__((unused)), size_t length __attribute__((unused)),
+ int quality __attribute__((unused)), int fips __attribute__((unused)))
+{
+ return -EINVAL;
+}
+
+/* PBKDF */
+int crypt_pbkdf(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ struct hash_alg *ha;
+
+ if (!kdf)
+ return -EINVAL;
+
+ if (!strcmp(kdf, "pbkdf2")) {
+ ha = _get_alg(hash);
+ if (!ha)
+ return -EINVAL;
+
+ return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
+ iterations, key_length, key, ha->block_length);
+ } else if (!strncmp(kdf, "argon2", 6)) {
+ return argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+ }
+
+ return -EINVAL;
+}
+
+/* Block ciphers */
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ struct crypt_cipher *h;
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+void crypt_cipher_destroy(struct crypt_cipher *ctx)
+{
+ crypt_cipher_destroy_kernel(&ctx->ck);
+ free(ctx);
+}
+
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
+}
+
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
+}
+
+bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
+{
+ return true;
+}
+
+int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+ return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
+ iv, iv_length, tag, tag_length);
+}
+
+int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
+{
+ return crypt_internal_memeq(m1, m2, n);
+}
+
+bool crypt_fips_mode(void)
+{
+ return false;
+}
diff --git a/lib/crypto_backend/crypto_nettle.c b/lib/crypto_backend/crypto_nettle.c
new file mode 100644
index 0000000..086e4fc
--- /dev/null
+++ b/lib/crypto_backend/crypto_nettle.c
@@ -0,0 +1,460 @@
+/*
+ * Nettle crypto backend implementation
+ *
+ * Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <nettle/sha.h>
+#include <nettle/sha3.h>
+#include <nettle/hmac.h>
+#include <nettle/pbkdf2.h>
+#include <nettle/memops.h>
+#include "crypto_backend_internal.h"
+
+#if HAVE_NETTLE_VERSION_H
+#include <nettle/version.h>
+#define VSTR(s) STR(s)
+#define STR(s) #s
+static const char *version = "Nettle "VSTR(NETTLE_VERSION_MAJOR)"."VSTR(NETTLE_VERSION_MINOR);
+#else
+static const char *version = "Nettle";
+#endif
+
+typedef void (*init_func) (void *);
+typedef void (*update_func) (void *, size_t, const uint8_t *);
+typedef void (*digest_func) (void *, size_t, uint8_t *);
+typedef void (*set_key_func) (void *, size_t, const uint8_t *);
+
+struct hash_alg {
+ const char *name;
+ int length;
+ init_func init;
+ update_func update;
+ digest_func digest;
+ update_func hmac_update;
+ digest_func hmac_digest;
+ set_key_func hmac_set_key;
+};
+
+/* Missing HMAC wrappers in Nettle */
+#define HMAC_FCE(xxx) \
+struct xhmac_##xxx##_ctx HMAC_CTX(struct xxx##_ctx); \
+static void xhmac_##xxx##_set_key(struct xhmac_##xxx##_ctx *ctx, \
+size_t key_length, const uint8_t *key) \
+{HMAC_SET_KEY(ctx, &nettle_##xxx, key_length, key);} \
+static void xhmac_##xxx##_update(struct xhmac_##xxx##_ctx *ctx, \
+size_t length, const uint8_t *data) \
+{xxx##_update(&ctx->state, length, data);} \
+static void xhmac_##xxx##_digest(struct xhmac_##xxx##_ctx *ctx, \
+size_t length, uint8_t *digest) \
+{HMAC_DIGEST(ctx, &nettle_##xxx, length, digest);}
+
+HMAC_FCE(sha3_224);
+HMAC_FCE(sha3_256);
+HMAC_FCE(sha3_384);
+HMAC_FCE(sha3_512);
+
+static struct hash_alg hash_algs[] = {
+ { "sha1", SHA1_DIGEST_SIZE,
+ (init_func) sha1_init,
+ (update_func) sha1_update,
+ (digest_func) sha1_digest,
+ (update_func) hmac_sha1_update,
+ (digest_func) hmac_sha1_digest,
+ (set_key_func) hmac_sha1_set_key,
+ },
+ { "sha224", SHA224_DIGEST_SIZE,
+ (init_func) sha224_init,
+ (update_func) sha224_update,
+ (digest_func) sha224_digest,
+ (update_func) hmac_sha224_update,
+ (digest_func) hmac_sha224_digest,
+ (set_key_func) hmac_sha224_set_key,
+ },
+ { "sha256", SHA256_DIGEST_SIZE,
+ (init_func) sha256_init,
+ (update_func) sha256_update,
+ (digest_func) sha256_digest,
+ (update_func) hmac_sha256_update,
+ (digest_func) hmac_sha256_digest,
+ (set_key_func) hmac_sha256_set_key,
+ },
+ { "sha384", SHA384_DIGEST_SIZE,
+ (init_func) sha384_init,
+ (update_func) sha384_update,
+ (digest_func) sha384_digest,
+ (update_func) hmac_sha384_update,
+ (digest_func) hmac_sha384_digest,
+ (set_key_func) hmac_sha384_set_key,
+ },
+ { "sha512", SHA512_DIGEST_SIZE,
+ (init_func) sha512_init,
+ (update_func) sha512_update,
+ (digest_func) sha512_digest,
+ (update_func) hmac_sha512_update,
+ (digest_func) hmac_sha512_digest,
+ (set_key_func) hmac_sha512_set_key,
+ },
+ { "ripemd160", RIPEMD160_DIGEST_SIZE,
+ (init_func) ripemd160_init,
+ (update_func) ripemd160_update,
+ (digest_func) ripemd160_digest,
+ (update_func) hmac_ripemd160_update,
+ (digest_func) hmac_ripemd160_digest,
+ (set_key_func) hmac_ripemd160_set_key,
+ },
+/* Nettle prior to version 3.2 has incompatible SHA3 implementation */
+#if NETTLE_SHA3_FIPS202
+ { "sha3-224", SHA3_224_DIGEST_SIZE,
+ (init_func) sha3_224_init,
+ (update_func) sha3_224_update,
+ (digest_func) sha3_224_digest,
+ (update_func) xhmac_sha3_224_update,
+ (digest_func) xhmac_sha3_224_digest,
+ (set_key_func) xhmac_sha3_224_set_key,
+ },
+ { "sha3-256", SHA3_256_DIGEST_SIZE,
+ (init_func) sha3_256_init,
+ (update_func) sha3_256_update,
+ (digest_func) sha3_256_digest,
+ (update_func) xhmac_sha3_256_update,
+ (digest_func) xhmac_sha3_256_digest,
+ (set_key_func) xhmac_sha3_256_set_key,
+ },
+ { "sha3-384", SHA3_384_DIGEST_SIZE,
+ (init_func) sha3_384_init,
+ (update_func) sha3_384_update,
+ (digest_func) sha3_384_digest,
+ (update_func) xhmac_sha3_384_update,
+ (digest_func) xhmac_sha3_384_digest,
+ (set_key_func) xhmac_sha3_384_set_key,
+ },
+ { "sha3-512", SHA3_512_DIGEST_SIZE,
+ (init_func) sha3_512_init,
+ (update_func) sha3_512_update,
+ (digest_func) sha3_512_digest,
+ (update_func) xhmac_sha3_512_update,
+ (digest_func) xhmac_sha3_512_digest,
+ (set_key_func) xhmac_sha3_512_set_key,
+ },
+#endif
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, }
+};
+
+struct crypt_hash {
+ const struct hash_alg *hash;
+ union {
+ struct sha1_ctx sha1;
+ struct sha224_ctx sha224;
+ struct sha256_ctx sha256;
+ struct sha384_ctx sha384;
+ struct sha512_ctx sha512;
+ struct ripemd160_ctx ripemd160;
+ struct sha3_224_ctx sha3_224;
+ struct sha3_256_ctx sha3_256;
+ struct sha3_384_ctx sha3_384;
+ struct sha3_512_ctx sha3_512;
+ } nettle_ctx;
+};
+
+struct crypt_hmac {
+ const struct hash_alg *hash;
+ union {
+ struct hmac_sha1_ctx sha1;
+ struct hmac_sha224_ctx sha224;
+ struct hmac_sha256_ctx sha256;
+ struct hmac_sha384_ctx sha384;
+ struct hmac_sha512_ctx sha512;
+ struct hmac_ripemd160_ctx ripemd160;
+ struct xhmac_sha3_224_ctx sha3_224;
+ struct xhmac_sha3_256_ctx sha3_256;
+ struct xhmac_sha3_384_ctx sha3_384;
+ struct xhmac_sha3_512_ctx sha3_512;
+ } nettle_ctx;
+ size_t key_length;
+ uint8_t *key;
+};
+
+struct crypt_cipher {
+ struct crypt_cipher_kernel ck;
+};
+
+uint32_t crypt_backend_flags(void)
+{
+ return 0;
+}
+
+static struct hash_alg *_get_alg(const char *name)
+{
+ int i = 0;
+
+ while (name && hash_algs[i].name) {
+ if (!strcmp(name, hash_algs[i].name))
+ return &hash_algs[i];
+ i++;
+ }
+ return NULL;
+}
+
+int crypt_backend_init(bool fips __attribute__((unused)))
+{
+ return 0;
+}
+
+void crypt_backend_destroy(void)
+{
+ return;
+}
+
+const char *crypt_backend_version(void)
+{
+ return version;
+}
+
+/* HASH */
+int crypt_hash_size(const char *name)
+{
+ struct hash_alg *ha = _get_alg(name);
+
+ return ha ? ha->length : -EINVAL;
+}
+
+int crypt_hash_init(struct crypt_hash **ctx, const char *name)
+{
+ struct crypt_hash *h;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->hash = _get_alg(name);
+ if (!h->hash) {
+ free(h);
+ return -EINVAL;
+ }
+
+ h->hash->init(&h->nettle_ctx);
+
+ *ctx = h;
+ return 0;
+}
+
+static void crypt_hash_restart(struct crypt_hash *ctx)
+{
+ ctx->hash->init(&ctx->nettle_ctx);
+}
+
+int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
+{
+ ctx->hash->update(&ctx->nettle_ctx, length, (const uint8_t*)buffer);
+ return 0;
+}
+
+int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
+{
+ if (length > (size_t)ctx->hash->length)
+ return -EINVAL;
+
+ ctx->hash->digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
+ crypt_hash_restart(ctx);
+ return 0;
+}
+
+void crypt_hash_destroy(struct crypt_hash *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* HMAC */
+int crypt_hmac_size(const char *name)
+{
+ return crypt_hash_size(name);
+}
+
+int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
+ const void *key, size_t key_length)
+{
+ struct crypt_hmac *h;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+ memset(ctx, 0, sizeof(*ctx));
+
+
+ h->hash = _get_alg(name);
+ if (!h->hash) {
+ free(h);
+ return -EINVAL;
+ }
+
+ h->key = malloc(key_length);
+ if (!h->key) {
+ free(h);
+ return -ENOMEM;
+ }
+
+ memcpy(h->key, key, key_length);
+ h->key_length = key_length;
+
+ h->hash->init(&h->nettle_ctx);
+ h->hash->hmac_set_key(&h->nettle_ctx, h->key_length, h->key);
+
+ *ctx = h;
+ return 0;
+}
+
+static void crypt_hmac_restart(struct crypt_hmac *ctx)
+{
+ ctx->hash->hmac_set_key(&ctx->nettle_ctx, ctx->key_length, ctx->key);
+}
+
+int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
+{
+ ctx->hash->hmac_update(&ctx->nettle_ctx, length, (const uint8_t *)buffer);
+ return 0;
+}
+
+int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
+{
+ if (length > (size_t)ctx->hash->length)
+ return -EINVAL;
+
+ ctx->hash->hmac_digest(&ctx->nettle_ctx, length, (uint8_t *)buffer);
+ crypt_hmac_restart(ctx);
+ return 0;
+}
+
+void crypt_hmac_destroy(struct crypt_hmac *ctx)
+{
+ memset(ctx->key, 0, ctx->key_length);
+ free(ctx->key);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* RNG - N/A */
+int crypt_backend_rng(char *buffer __attribute__((unused)),
+ size_t length __attribute__((unused)),
+ int quality __attribute__((unused)),
+ int fips __attribute__((unused)))
+{
+ return -EINVAL;
+}
+
+/* PBKDF */
+int crypt_pbkdf(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ struct crypt_hmac *h;
+ int r;
+
+ if (!kdf)
+ return -EINVAL;
+
+ if (!strcmp(kdf, "pbkdf2")) {
+ r = crypt_hmac_init(&h, hash, password, password_length);
+ if (r < 0)
+ return r;
+
+ nettle_pbkdf2(&h->nettle_ctx, h->hash->hmac_update,
+ h->hash->hmac_digest, h->hash->length, iterations,
+ salt_length, (const uint8_t *)salt, key_length,
+ (uint8_t *)key);
+ crypt_hmac_destroy(h);
+ return 0;
+ } else if (!strncmp(kdf, "argon2", 6)) {
+ return argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+ }
+
+ return -EINVAL;
+}
+
+/* Block ciphers */
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ struct crypt_cipher *h;
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+void crypt_cipher_destroy(struct crypt_cipher *ctx)
+{
+ crypt_cipher_destroy_kernel(&ctx->ck);
+ free(ctx);
+}
+
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
+}
+
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
+}
+
+bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
+{
+ return true;
+}
+
+int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+ return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
+ iv, iv_length, tag, tag_length);
+}
+
+int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
+{
+ /* The logic is inverse to memcmp... */
+ return !memeql_sec(m1, m2, n);
+}
+
+bool crypt_fips_mode(void)
+{
+ return false;
+}
diff --git a/lib/crypto_backend/crypto_nss.c b/lib/crypto_backend/crypto_nss.c
new file mode 100644
index 0000000..c154812
--- /dev/null
+++ b/lib/crypto_backend/crypto_nss.c
@@ -0,0 +1,407 @@
+/*
+ * NSS crypto backend implementation
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <nss.h>
+#include <pk11pub.h>
+#include "crypto_backend_internal.h"
+
+#define CONST_CAST(x) (x)(uintptr_t)
+
+static int crypto_backend_initialised = 0;
+static char version[64];
+
+struct hash_alg {
+ const char *name;
+ SECOidTag oid;
+ CK_MECHANISM_TYPE ck_type;
+ int length;
+ unsigned int block_length;
+};
+
+static struct hash_alg hash_algs[] = {
+ { "sha1", SEC_OID_SHA1, CKM_SHA_1_HMAC, 20, 64 },
+ { "sha256", SEC_OID_SHA256, CKM_SHA256_HMAC, 32, 64 },
+ { "sha384", SEC_OID_SHA384, CKM_SHA384_HMAC, 48, 128 },
+ { "sha512", SEC_OID_SHA512, CKM_SHA512_HMAC, 64, 128 },
+// { "ripemd160", SEC_OID_RIPEMD160, CKM_RIPEMD160_HMAC, 20, 64 },
+ { NULL, 0, 0, 0 }
+};
+
+struct crypt_hash {
+ PK11Context *md;
+ const struct hash_alg *hash;
+};
+
+struct crypt_hmac {
+ PK11Context *md;
+ PK11SymKey *key;
+ PK11SlotInfo *slot;
+ const struct hash_alg *hash;
+};
+
+struct crypt_cipher {
+ struct crypt_cipher_kernel ck;
+};
+
+static struct hash_alg *_get_alg(const char *name)
+{
+ int i = 0;
+
+ while (name && hash_algs[i].name) {
+ if (!strcmp(name, hash_algs[i].name))
+ return &hash_algs[i];
+ i++;
+ }
+ return NULL;
+}
+
+int crypt_backend_init(bool fips __attribute__((unused)))
+{
+ int r;
+
+ if (crypto_backend_initialised)
+ return 0;
+
+ if (NSS_NoDB_Init(".") != SECSuccess)
+ return -EINVAL;
+
+#if HAVE_DECL_NSS_GETVERSION
+ r = snprintf(version, sizeof(version), "NSS %s", NSS_GetVersion());
+#else
+ r = snprintf(version, sizeof(version), "NSS");
+#endif
+ if (r < 0 || (size_t)r >= sizeof(version))
+ return -EINVAL;
+
+ crypto_backend_initialised = 1;
+ return 0;
+}
+
+void crypt_backend_destroy(void)
+{
+ crypto_backend_initialised = 0;
+}
+
+uint32_t crypt_backend_flags(void)
+{
+ return 0;
+}
+
+const char *crypt_backend_version(void)
+{
+ return crypto_backend_initialised ? version : "";
+}
+
+/* HASH */
+int crypt_hash_size(const char *name)
+{
+ struct hash_alg *ha = _get_alg(name);
+
+ return ha ? ha->length : -EINVAL;
+}
+
+int crypt_hash_init(struct crypt_hash **ctx, const char *name)
+{
+ struct crypt_hash *h;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->hash = _get_alg(name);
+ if (!h->hash) {
+ free(h);
+ return -EINVAL;
+ }
+
+ h->md = PK11_CreateDigestContext(h->hash->oid);
+ if (!h->md) {
+ free(h);
+ return -EINVAL;
+ }
+
+ if (PK11_DigestBegin(h->md) != SECSuccess) {
+ PK11_DestroyContext(h->md, PR_TRUE);
+ free(h);
+ return -EINVAL;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+static int crypt_hash_restart(struct crypt_hash *ctx)
+{
+ if (PK11_DigestBegin(ctx->md) != SECSuccess)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
+{
+ if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
+{
+ unsigned char tmp[64];
+ unsigned int tmp_len;
+
+ if (length > (size_t)ctx->hash->length)
+ return -EINVAL;
+
+ if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
+ return -EINVAL;
+
+ memcpy(buffer, tmp, length);
+ crypt_backend_memzero(tmp, sizeof(tmp));
+
+ if (tmp_len < length)
+ return -EINVAL;
+
+ if (crypt_hash_restart(ctx))
+ return -EINVAL;
+
+ return 0;
+}
+
+void crypt_hash_destroy(struct crypt_hash *ctx)
+{
+ PK11_DestroyContext(ctx->md, PR_TRUE);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* HMAC */
+int crypt_hmac_size(const char *name)
+{
+ return crypt_hash_size(name);
+}
+
+int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
+ const void *key, size_t key_length)
+{
+ struct crypt_hmac *h;
+ SECItem keyItem;
+ SECItem noParams;
+
+ keyItem.type = siBuffer;
+ keyItem.data = CONST_CAST(unsigned char *)key;
+ keyItem.len = (int)key_length;
+
+ noParams.type = siBuffer;
+ noParams.data = 0;
+ noParams.len = 0;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+ memset(ctx, 0, sizeof(*ctx));
+
+
+ h->hash = _get_alg(name);
+ if (!h->hash)
+ goto err;
+
+ h->slot = PK11_GetInternalKeySlot();
+ if (!h->slot)
+ goto err;
+
+ h->key = PK11_ImportSymKey(h->slot, h->hash->ck_type, PK11_OriginUnwrap,
+ CKA_SIGN, &keyItem, NULL);
+ if (!h->key)
+ goto err;
+
+ h->md = PK11_CreateContextBySymKey(h->hash->ck_type, CKA_SIGN, h->key,
+ &noParams);
+ if (!h->md)
+ goto err;
+
+ if (PK11_DigestBegin(h->md) != SECSuccess)
+ goto err;
+
+ *ctx = h;
+ return 0;
+err:
+ crypt_hmac_destroy(h);
+ return -EINVAL;
+}
+
+static int crypt_hmac_restart(struct crypt_hmac *ctx)
+{
+ if (PK11_DigestBegin(ctx->md) != SECSuccess)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
+{
+ if (PK11_DigestOp(ctx->md, CONST_CAST(unsigned char *)buffer, length) != SECSuccess)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
+{
+ unsigned char tmp[64];
+ unsigned int tmp_len;
+
+ if (length > (size_t)ctx->hash->length)
+ return -EINVAL;
+
+ if (PK11_DigestFinal(ctx->md, tmp, &tmp_len, length) != SECSuccess)
+ return -EINVAL;
+
+ memcpy(buffer, tmp, length);
+ crypt_backend_memzero(tmp, sizeof(tmp));
+
+ if (tmp_len < length)
+ return -EINVAL;
+
+ if (crypt_hmac_restart(ctx))
+ return -EINVAL;
+
+ return 0;
+}
+
+void crypt_hmac_destroy(struct crypt_hmac *ctx)
+{
+ if (ctx->key)
+ PK11_FreeSymKey(ctx->key);
+ if (ctx->slot)
+ PK11_FreeSlot(ctx->slot);
+ if (ctx->md)
+ PK11_DestroyContext(ctx->md, PR_TRUE);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* RNG */
+int crypt_backend_rng(char *buffer, size_t length, int quality __attribute__((unused)), int fips)
+{
+ if (fips)
+ return -EINVAL;
+
+ if (PK11_GenerateRandom((unsigned char *)buffer, length) != SECSuccess)
+ return -EINVAL;
+
+ return 0;
+}
+
+/* PBKDF */
+int crypt_pbkdf(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ struct hash_alg *ha;
+
+ if (!kdf)
+ return -EINVAL;
+
+ if (!strcmp(kdf, "pbkdf2")) {
+ ha = _get_alg(hash);
+ if (!ha)
+ return -EINVAL;
+
+ return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
+ iterations, key_length, key, ha->block_length);
+ } else if (!strncmp(kdf, "argon2", 6)) {
+ return argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+ }
+
+ return -EINVAL;
+}
+
+/* Block ciphers */
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ struct crypt_cipher *h;
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ *ctx = h;
+ return 0;
+}
+
+void crypt_cipher_destroy(struct crypt_cipher *ctx)
+{
+ crypt_cipher_destroy_kernel(&ctx->ck);
+ free(ctx);
+}
+
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
+}
+
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
+}
+
+bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
+{
+ return true;
+}
+
+int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+ return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
+ iv, iv_length, tag, tag_length);
+}
+
+int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
+{
+ return NSS_SecureMemcmp(m1, m2, n);
+}
+
+bool crypt_fips_mode(void)
+{
+ return false;
+}
diff --git a/lib/crypto_backend/crypto_openssl.c b/lib/crypto_backend/crypto_openssl.c
new file mode 100644
index 0000000..607ec38
--- /dev/null
+++ b/lib/crypto_backend/crypto_openssl.c
@@ -0,0 +1,849 @@
+/*
+ * OPENSSL crypto backend implementation
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ *
+ * You must obey the GNU Lesser General Public License in all respects
+ * for all of the code used other than OpenSSL.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/rand.h>
+#include "crypto_backend_internal.h"
+#if OPENSSL_VERSION_MAJOR >= 3
+#include <openssl/provider.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+static OSSL_PROVIDER *ossl_legacy = NULL;
+static OSSL_PROVIDER *ossl_default = NULL;
+static OSSL_LIB_CTX *ossl_ctx = NULL;
+static char backend_version[256] = "OpenSSL";
+#endif
+
+#define CONST_CAST(x) (x)(uintptr_t)
+
+static int crypto_backend_initialised = 0;
+
+struct crypt_hash {
+ EVP_MD_CTX *md;
+ const EVP_MD *hash_id;
+ int hash_len;
+};
+
+struct crypt_hmac {
+#if OPENSSL_VERSION_MAJOR >= 3
+ EVP_MAC *mac;
+ EVP_MAC_CTX *md;
+ EVP_MAC_CTX *md_org;
+#else
+ HMAC_CTX *md;
+ const EVP_MD *hash_id;
+#endif
+ int hash_len;
+};
+
+struct crypt_cipher {
+ bool use_kernel;
+ union {
+ struct crypt_cipher_kernel kernel;
+ struct {
+ EVP_CIPHER_CTX *hd_enc;
+ EVP_CIPHER_CTX *hd_dec;
+ const EVP_CIPHER *cipher_type;
+ size_t iv_length;
+ } lib;
+ } u;
+};
+
+struct hash_alg {
+ const char *name;
+ const char *openssl_name;
+};
+
+/*
+ * Compatible wrappers for OpenSSL < 1.1.0 and LibreSSL < 2.7.0
+ */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
+
+static int openssl_backend_init(bool fips __attribute__((unused)))
+{
+ OpenSSL_add_all_algorithms();
+ return 0;
+}
+
+static void openssl_backend_exit(void)
+{
+}
+
+static const char *openssl_backend_version(void)
+{
+ return SSLeay_version(SSLEAY_VERSION);
+}
+
+static EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+ EVP_MD_CTX *md = malloc(sizeof(*md));
+
+ if (md)
+ EVP_MD_CTX_init(md);
+
+ return md;
+}
+
+static void EVP_MD_CTX_free(EVP_MD_CTX *md)
+{
+ EVP_MD_CTX_cleanup(md);
+ free(md);
+}
+
+static HMAC_CTX *HMAC_CTX_new(void)
+{
+ HMAC_CTX *md = malloc(sizeof(*md));
+
+ if (md)
+ HMAC_CTX_init(md);
+
+ return md;
+}
+
+static void HMAC_CTX_free(HMAC_CTX *md)
+{
+ HMAC_CTX_cleanup(md);
+ free(md);
+}
+#else
+static void openssl_backend_exit(void)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ if (ossl_legacy)
+ OSSL_PROVIDER_unload(ossl_legacy);
+ if (ossl_default)
+ OSSL_PROVIDER_unload(ossl_default);
+ if (ossl_ctx)
+ OSSL_LIB_CTX_free(ossl_ctx);
+
+ ossl_legacy = NULL;
+ ossl_default = NULL;
+ ossl_ctx = NULL;
+#endif
+}
+
+static int openssl_backend_init(bool fips)
+{
+/*
+ * OpenSSL >= 3.0.0 provides some algorithms in legacy provider
+ */
+#if OPENSSL_VERSION_MAJOR >= 3
+ int r;
+
+ /*
+ * In FIPS mode we keep default OpenSSL context & global config
+ */
+ if (!fips) {
+ ossl_ctx = OSSL_LIB_CTX_new();
+ if (!ossl_ctx)
+ return -EINVAL;
+
+ ossl_default = OSSL_PROVIDER_try_load(ossl_ctx, "default", 0);
+ if (!ossl_default) {
+ OSSL_LIB_CTX_free(ossl_ctx);
+ return -EINVAL;
+ }
+
+ /* Optional */
+ ossl_legacy = OSSL_PROVIDER_try_load(ossl_ctx, "legacy", 0);
+ }
+
+ r = snprintf(backend_version, sizeof(backend_version), "%s %s%s%s",
+ OpenSSL_version(OPENSSL_VERSION),
+ ossl_default ? "[default]" : "",
+ ossl_legacy ? "[legacy]" : "",
+ fips ? "[fips]" : "");
+
+ if (r < 0 || (size_t)r >= sizeof(backend_version)) {
+ openssl_backend_exit();
+ return -EINVAL;
+ }
+#endif
+ return 0;
+}
+
+static const char *openssl_backend_version(void)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ return backend_version;
+#else
+ return OpenSSL_version(OPENSSL_VERSION);
+#endif
+}
+#endif
+
+int crypt_backend_init(bool fips)
+{
+ if (crypto_backend_initialised)
+ return 0;
+
+ if (openssl_backend_init(fips))
+ return -EINVAL;
+
+ crypto_backend_initialised = 1;
+ return 0;
+}
+
+void crypt_backend_destroy(void)
+{
+ /*
+ * If Destructor was already called, we must not call it again
+ */
+ if (!crypto_backend_initialised)
+ return;
+
+ crypto_backend_initialised = 0;
+
+ openssl_backend_exit();
+}
+
+uint32_t crypt_backend_flags(void)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ return 0;
+#else
+ return CRYPT_BACKEND_PBKDF2_INT;
+#endif
+}
+
+const char *crypt_backend_version(void)
+{
+ return openssl_backend_version();
+}
+
+static const char *crypt_hash_compat_name(const char *name)
+{
+ const char *hash_name = name;
+ int i;
+ static struct hash_alg hash_algs[] = {
+ { "blake2b-512", "blake2b512" },
+ { "blake2s-256", "blake2s256" },
+ { NULL, NULL, }};
+
+ if (!name)
+ return NULL;
+
+ i = 0;
+ while (hash_algs[i].name) {
+ if (!strcasecmp(name, hash_algs[i].name)) {
+ hash_name = hash_algs[i].openssl_name;
+ break;
+ }
+ i++;
+ }
+
+ return hash_name;
+}
+
+static const EVP_MD *hash_id_get(const char *name)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ return EVP_MD_fetch(ossl_ctx, crypt_hash_compat_name(name), NULL);
+#else
+ return EVP_get_digestbyname(crypt_hash_compat_name(name));
+#endif
+}
+
+static void hash_id_free(const EVP_MD *hash_id)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ EVP_MD_free(CONST_CAST(EVP_MD*)hash_id);
+#endif
+}
+
+static const EVP_CIPHER *cipher_type_get(const char *name)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ return EVP_CIPHER_fetch(ossl_ctx, name, NULL);
+#else
+ return EVP_get_cipherbyname(name);
+#endif
+}
+
+static void cipher_type_free(const EVP_CIPHER *cipher_type)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ EVP_CIPHER_free(CONST_CAST(EVP_CIPHER*)cipher_type);
+#endif
+}
+
+/* HASH */
+int crypt_hash_size(const char *name)
+{
+ int size;
+ const EVP_MD *hash_id;
+
+ hash_id = hash_id_get(name);
+ if (!hash_id)
+ return -EINVAL;
+
+ size = EVP_MD_size(hash_id);
+ hash_id_free(hash_id);
+ return size;
+}
+
+int crypt_hash_init(struct crypt_hash **ctx, const char *name)
+{
+ struct crypt_hash *h;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->md = EVP_MD_CTX_new();
+ if (!h->md) {
+ free(h);
+ return -ENOMEM;
+ }
+
+ h->hash_id = hash_id_get(name);
+ if (!h->hash_id) {
+ EVP_MD_CTX_free(h->md);
+ free(h);
+ return -EINVAL;
+ }
+
+ if (EVP_DigestInit_ex(h->md, h->hash_id, NULL) != 1) {
+ hash_id_free(h->hash_id);
+ EVP_MD_CTX_free(h->md);
+ free(h);
+ return -EINVAL;
+ }
+
+ h->hash_len = EVP_MD_size(h->hash_id);
+ *ctx = h;
+ return 0;
+}
+
+static int crypt_hash_restart(struct crypt_hash *ctx)
+{
+ if (EVP_DigestInit_ex(ctx->md, ctx->hash_id, NULL) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
+{
+ if (EVP_DigestUpdate(ctx->md, buffer, length) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
+{
+ unsigned char tmp[EVP_MAX_MD_SIZE];
+ unsigned int tmp_len = 0;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ if (EVP_DigestFinal_ex(ctx->md, tmp, &tmp_len) != 1)
+ return -EINVAL;
+
+ memcpy(buffer, tmp, length);
+ crypt_backend_memzero(tmp, sizeof(tmp));
+
+ if (tmp_len < length)
+ return -EINVAL;
+
+ if (crypt_hash_restart(ctx))
+ return -EINVAL;
+
+ return 0;
+}
+
+void crypt_hash_destroy(struct crypt_hash *ctx)
+{
+ hash_id_free(ctx->hash_id);
+ EVP_MD_CTX_free(ctx->md);
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* HMAC */
+int crypt_hmac_size(const char *name)
+{
+ return crypt_hash_size(name);
+}
+
+int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
+ const void *key, size_t key_length)
+{
+ struct crypt_hmac *h;
+#if OPENSSL_VERSION_MAJOR >= 3
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, CONST_CAST(void*)name, 0),
+ OSSL_PARAM_END
+ };
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->mac = EVP_MAC_fetch(ossl_ctx, OSSL_MAC_NAME_HMAC, NULL);
+ if (!h->mac) {
+ free(h);
+ return -EINVAL;
+ }
+
+ h->md = EVP_MAC_CTX_new(h->mac);
+ if (!h->md) {
+ EVP_MAC_free(h->mac);
+ free(h);
+ return -ENOMEM;
+ }
+
+ if (EVP_MAC_init(h->md, key, key_length, params) != 1) {
+ EVP_MAC_CTX_free(h->md);
+ EVP_MAC_free(h->mac);
+ free(h);
+ return -EINVAL;
+ }
+
+ h->hash_len = EVP_MAC_CTX_get_mac_size(h->md);
+ h->md_org = EVP_MAC_CTX_dup(h->md);
+#else
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ h->md = HMAC_CTX_new();
+ if (!h->md) {
+ free(h);
+ return -ENOMEM;
+ }
+
+ h->hash_id = hash_id_get(name);
+ if (!h->hash_id) {
+ HMAC_CTX_free(h->md);
+ free(h);
+ return -EINVAL;
+ }
+
+ HMAC_Init_ex(h->md, key, key_length, h->hash_id, NULL);
+
+ h->hash_len = EVP_MD_size(h->hash_id);
+#endif
+ *ctx = h;
+ return 0;
+}
+
+static int crypt_hmac_restart(struct crypt_hmac *ctx)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ EVP_MAC_CTX_free(ctx->md);
+ ctx->md = EVP_MAC_CTX_dup(ctx->md_org);
+ if (!ctx->md)
+ return -EINVAL;
+#else
+ HMAC_Init_ex(ctx->md, NULL, 0, ctx->hash_id, NULL);
+#endif
+ return 0;
+}
+
+int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ return EVP_MAC_update(ctx->md, (const unsigned char *)buffer, length) == 1 ? 0 : -EINVAL;
+#else
+ HMAC_Update(ctx->md, (const unsigned char *)buffer, length);
+ return 0;
+#endif
+}
+
+int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
+{
+ unsigned char tmp[EVP_MAX_MD_SIZE];
+#if OPENSSL_VERSION_MAJOR >= 3
+ size_t tmp_len = 0;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ if (EVP_MAC_final(ctx->md, tmp, &tmp_len, sizeof(tmp)) != 1)
+ return -EINVAL;
+#else
+ unsigned int tmp_len = 0;
+
+ if (length > (size_t)ctx->hash_len)
+ return -EINVAL;
+
+ HMAC_Final(ctx->md, tmp, &tmp_len);
+#endif
+ memcpy(buffer, tmp, length);
+ crypt_backend_memzero(tmp, sizeof(tmp));
+
+ if (tmp_len < length)
+ return -EINVAL;
+
+ if (crypt_hmac_restart(ctx))
+ return -EINVAL;
+
+ return 0;
+}
+
+void crypt_hmac_destroy(struct crypt_hmac *ctx)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ EVP_MAC_CTX_free(ctx->md);
+ EVP_MAC_CTX_free(ctx->md_org);
+ EVP_MAC_free(ctx->mac);
+#else
+ hash_id_free(ctx->hash_id);
+ HMAC_CTX_free(ctx->md);
+#endif
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+/* RNG */
+int crypt_backend_rng(char *buffer, size_t length,
+ int quality __attribute__((unused)), int fips __attribute__((unused)))
+{
+ if (RAND_bytes((unsigned char *)buffer, length) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int openssl_pbkdf2(const char *password, size_t password_length,
+ const char *salt, size_t salt_length, uint32_t iterations,
+ const char *hash, char *key, size_t key_length)
+{
+ int r;
+#if OPENSSL_VERSION_MAJOR >= 3
+ EVP_KDF_CTX *ctx;
+ EVP_KDF *pbkdf2;
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ CONST_CAST(void*)password, password_length),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT,
+ CONST_CAST(void*)salt, salt_length),
+ OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, &iterations),
+ OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST,
+ CONST_CAST(void*)hash, 0),
+ OSSL_PARAM_END
+ };
+
+ pbkdf2 = EVP_KDF_fetch(ossl_ctx, "pbkdf2", NULL);
+ if (!pbkdf2)
+ return -EINVAL;
+
+ ctx = EVP_KDF_CTX_new(pbkdf2);
+ if (!ctx) {
+ EVP_KDF_free(pbkdf2);
+ return -EINVAL;
+ }
+
+ r = EVP_KDF_derive(ctx, (unsigned char*)key, key_length, params);
+
+ EVP_KDF_CTX_free(ctx);
+ EVP_KDF_free(pbkdf2);
+#else
+ const EVP_MD *hash_id = EVP_get_digestbyname(crypt_hash_compat_name(hash));
+ if (!hash_id)
+ return -EINVAL;
+
+ /* OpenSSL2 has iteration as signed int, avoid overflow */
+ if (iterations > INT_MAX)
+ return -EINVAL;
+
+ r = PKCS5_PBKDF2_HMAC(password, (int)password_length, (const unsigned char *)salt,
+ (int)salt_length, iterations, hash_id, (int)key_length, (unsigned char*) key);
+#endif
+ return r == 1 ? 0 : -EINVAL;
+}
+
+static int openssl_argon2(const char *type, const char *password, size_t password_length,
+ const char *salt, size_t salt_length, char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ return argon2(type, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+}
+
+/* PBKDF */
+int crypt_pbkdf(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ if (!kdf)
+ return -EINVAL;
+
+ if (!strcmp(kdf, "pbkdf2"))
+ return openssl_pbkdf2(password, password_length, salt, salt_length,
+ iterations, hash, key, key_length);
+ if (!strncmp(kdf, "argon2", 6))
+ return openssl_argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+ return -EINVAL;
+}
+
+/* Block ciphers */
+static void _cipher_destroy(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const EVP_CIPHER **cipher_type)
+{
+ EVP_CIPHER_CTX_free(*hd_enc);
+ *hd_enc = NULL;
+
+ EVP_CIPHER_CTX_free(*hd_dec);
+ *hd_dec = NULL;
+
+ cipher_type_free(*cipher_type);
+ *cipher_type = NULL;
+}
+
+static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const EVP_CIPHER **cipher_type, const char *name,
+ const char *mode, const void *key, size_t key_length, size_t *iv_length)
+{
+ char cipher_name[256];
+ const EVP_CIPHER *type;
+ int r, key_bits;
+
+ key_bits = key_length * 8;
+ if (!strcmp(mode, "xts"))
+ key_bits /= 2;
+
+ r = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", name, key_bits, mode);
+ if (r < 0 || (size_t)r >= sizeof(cipher_name))
+ return -EINVAL;
+
+ type = cipher_type_get(cipher_name);
+ if (!type)
+ return -ENOENT;
+
+ if (EVP_CIPHER_key_length(type) != (int)key_length) {
+ cipher_type_free(type);
+ return -EINVAL;
+ }
+
+ *hd_enc = EVP_CIPHER_CTX_new();
+ *hd_dec = EVP_CIPHER_CTX_new();
+ *iv_length = EVP_CIPHER_iv_length(type);
+
+ if (!*hd_enc || !*hd_dec) {
+ cipher_type_free(type);
+ return -EINVAL;
+ }
+
+ if (EVP_EncryptInit_ex(*hd_enc, type, NULL, key, NULL) != 1 ||
+ EVP_DecryptInit_ex(*hd_dec, type, NULL, key, NULL) != 1) {
+ _cipher_destroy(hd_enc, hd_dec, &type);
+ return -EINVAL;
+ }
+
+ if (EVP_CIPHER_CTX_set_padding(*hd_enc, 0) != 1 ||
+ EVP_CIPHER_CTX_set_padding(*hd_dec, 0) != 1) {
+ _cipher_destroy(hd_enc, hd_dec, &type);
+ return -EINVAL;
+ }
+
+ *cipher_type = type;
+
+ return 0;
+}
+
+int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
+ const char *mode, const void *key, size_t key_length)
+{
+ struct crypt_cipher *h;
+ int r;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return -ENOMEM;
+
+ if (!_cipher_init(&h->u.lib.hd_enc, &h->u.lib.hd_dec, &h->u.lib.cipher_type, name, mode, key,
+ key_length, &h->u.lib.iv_length)) {
+ h->use_kernel = false;
+ *ctx = h;
+ return 0;
+ }
+
+ r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ h->use_kernel = true;
+ *ctx = h;
+ return 0;
+}
+
+void crypt_cipher_destroy(struct crypt_cipher *ctx)
+{
+ if (ctx->use_kernel)
+ crypt_cipher_destroy_kernel(&ctx->u.kernel);
+ else
+ _cipher_destroy(&ctx->u.lib.hd_enc, &ctx->u.lib.hd_dec, &ctx->u.lib.cipher_type);
+ free(ctx);
+}
+
+static int _cipher_encrypt(struct crypt_cipher *ctx, const unsigned char *in, unsigned char *out,
+ int length, const unsigned char *iv, size_t iv_length)
+{
+ int len;
+
+ if (ctx->u.lib.iv_length != iv_length)
+ return -EINVAL;
+
+ if (EVP_EncryptInit_ex(ctx->u.lib.hd_enc, NULL, NULL, NULL, iv) != 1)
+ return -EINVAL;
+
+ if (EVP_EncryptUpdate(ctx->u.lib.hd_enc, out, &len, in, length) != 1)
+ return -EINVAL;
+
+ if (EVP_EncryptFinal(ctx->u.lib.hd_enc, out + len, &len) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int _cipher_decrypt(struct crypt_cipher *ctx, const unsigned char *in, unsigned char *out,
+ int length, const unsigned char *iv, size_t iv_length)
+{
+ int len;
+
+ if (ctx->u.lib.iv_length != iv_length)
+ return -EINVAL;
+
+ if (EVP_DecryptInit_ex(ctx->u.lib.hd_dec, NULL, NULL, NULL, iv) != 1)
+ return -EINVAL;
+
+ if (EVP_DecryptUpdate(ctx->u.lib.hd_dec, out, &len, in, length) != 1)
+ return -EINVAL;
+
+ if (EVP_DecryptFinal(ctx->u.lib.hd_dec, out + len, &len) != 1)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_cipher_encrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ if (ctx->use_kernel)
+ return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
+
+ return _cipher_encrypt(ctx, (const unsigned char*)in,
+ (unsigned char *)out, length, (const unsigned char*)iv, iv_length);
+}
+
+int crypt_cipher_decrypt(struct crypt_cipher *ctx,
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length)
+{
+ if (ctx->use_kernel)
+ return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
+
+ return _cipher_decrypt(ctx, (const unsigned char*)in,
+ (unsigned char *)out, length, (const unsigned char*)iv, iv_length);
+}
+
+bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
+{
+ return ctx->use_kernel;
+}
+
+int crypt_bitlk_decrypt_key(const void *key, size_t key_length __attribute__((unused)),
+ const char *in, char *out, size_t length,
+ const char *iv, size_t iv_length,
+ const char *tag, size_t tag_length)
+{
+#ifdef EVP_CTRL_CCM_SET_IVLEN
+ EVP_CIPHER_CTX *ctx;
+ int len = 0, r = -EINVAL;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (!ctx)
+ return -EINVAL;
+
+ if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL) != 1)
+ goto out;
+
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_length, NULL) != 1)
+ goto out;
+ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_length, CONST_CAST(void*)tag) != 1)
+ goto out;
+
+ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, (const unsigned char*)iv) != 1)
+ goto out;
+
+ if (EVP_DecryptUpdate(ctx, (unsigned char*)out, &len, (const unsigned char*)in, length) == 1)
+ r = 0;
+out:
+ EVP_CIPHER_CTX_free(ctx);
+ return r;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
+{
+ return CRYPTO_memcmp(m1, m2, n);
+}
+
+#if !ENABLE_FIPS
+bool crypt_fips_mode(void) { return false; }
+#else
+static bool openssl_fips_mode(void)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ return EVP_default_properties_is_fips_enabled(NULL);
+#else
+ return FIPS_mode();
+#endif
+}
+
+bool crypt_fips_mode(void)
+{
+ static bool fips_mode = false, fips_checked = false;
+
+ if (fips_checked)
+ return fips_mode;
+
+ fips_mode = openssl_fips_mode();
+ fips_checked = true;
+
+ return fips_mode;
+}
+#endif /* ENABLE FIPS */
diff --git a/lib/crypto_backend/crypto_storage.c b/lib/crypto_backend/crypto_storage.c
new file mode 100644
index 0000000..13479dd
--- /dev/null
+++ b/lib/crypto_backend/crypto_storage.c
@@ -0,0 +1,347 @@
+/*
+ * Generic wrapper for storage encryption modes and Initial Vectors
+ * (reimplementation of some functions from Linux dm-crypt kernel)
+ *
+ * Copyright (C) 2014-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <strings.h>
+#include "bitops.h"
+#include "crypto_backend.h"
+
+#define SECTOR_SHIFT 9
+
+/*
+ * Internal IV helper
+ * IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
+ */
+struct crypt_sector_iv {
+ enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type;
+ int iv_size;
+ char *iv;
+ struct crypt_cipher *cipher;
+ int shift;
+};
+
+/* Block encryption storage context */
+struct crypt_storage {
+ size_t sector_size;
+ unsigned iv_shift;
+ struct crypt_cipher *cipher;
+ struct crypt_sector_iv cipher_iv;
+};
+
+static int int_log2(unsigned int x)
+{
+ int r = 0;
+ for (x >>= 1; x > 0; x >>= 1)
+ r++;
+ return r;
+}
+
+static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
+ const char *cipher_name, const char *mode_name,
+ const char *iv_name, const void *key, size_t key_length,
+ size_t sector_size)
+{
+ int r;
+
+ memset(ctx, 0, sizeof(*ctx));
+
+ ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
+ if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
+ return -ENOENT;
+
+ if (!strcmp(cipher_name, "cipher_null") ||
+ !strcmp(mode_name, "ecb")) {
+ if (iv_name)
+ return -EINVAL;
+ ctx->type = IV_NONE;
+ ctx->iv_size = 0;
+ return 0;
+ } else if (!iv_name) {
+ return -EINVAL;
+ } else if (!strcasecmp(iv_name, "null")) {
+ ctx->type = IV_NULL;
+ } else if (!strcasecmp(iv_name, "plain64")) {
+ ctx->type = IV_PLAIN64;
+ } else if (!strcasecmp(iv_name, "plain64be")) {
+ ctx->type = IV_PLAIN64BE;
+ } else if (!strcasecmp(iv_name, "plain")) {
+ ctx->type = IV_PLAIN;
+ } else if (!strncasecmp(iv_name, "essiv:", 6)) {
+ struct crypt_hash *h = NULL;
+ char *hash_name = strchr(iv_name, ':');
+ int hash_size;
+ char tmp[256];
+
+ if (!hash_name)
+ return -EINVAL;
+
+ hash_size = crypt_hash_size(++hash_name);
+ if (hash_size < 0)
+ return -ENOENT;
+
+ if ((unsigned)hash_size > sizeof(tmp))
+ return -EINVAL;
+
+ if (crypt_hash_init(&h, hash_name))
+ return -EINVAL;
+
+ r = crypt_hash_write(h, key, key_length);
+ if (r) {
+ crypt_hash_destroy(h);
+ return r;
+ }
+
+ r = crypt_hash_final(h, tmp, hash_size);
+ crypt_hash_destroy(h);
+ if (r) {
+ crypt_backend_memzero(tmp, sizeof(tmp));
+ return r;
+ }
+
+ r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
+ tmp, hash_size);
+ crypt_backend_memzero(tmp, sizeof(tmp));
+ if (r)
+ return r;
+
+ ctx->type = IV_ESSIV;
+ } else if (!strncasecmp(iv_name, "benbi", 5)) {
+ int log = int_log2(ctx->iv_size);
+ if (log > SECTOR_SHIFT)
+ return -EINVAL;
+
+ ctx->type = IV_BENBI;
+ ctx->shift = SECTOR_SHIFT - log;
+ } else if (!strncasecmp(iv_name, "eboiv", 5)) {
+ r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
+ key, key_length);
+ if (r)
+ return r;
+
+ ctx->type = IV_EBOIV;
+ ctx->shift = int_log2(sector_size);
+ } else
+ return -ENOENT;
+
+ ctx->iv = malloc(ctx->iv_size);
+ if (!ctx->iv)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
+{
+ uint64_t val, *u64_iv;
+ uint32_t *u32_iv;
+
+ switch (ctx->type) {
+ case IV_NONE:
+ break;
+ case IV_NULL:
+ memset(ctx->iv, 0, ctx->iv_size);
+ break;
+ case IV_PLAIN:
+ memset(ctx->iv, 0, ctx->iv_size);
+ u32_iv = (void *)ctx->iv;
+ *u32_iv = cpu_to_le32(sector & 0xffffffff);
+ break;
+ case IV_PLAIN64:
+ memset(ctx->iv, 0, ctx->iv_size);
+ u64_iv = (void *)ctx->iv;
+ *u64_iv = cpu_to_le64(sector);
+ break;
+ case IV_PLAIN64BE:
+ memset(ctx->iv, 0, ctx->iv_size);
+ /* iv_size is at least of size u64; usually it is 16 bytes */
+ u64_iv = (void *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)];
+ *u64_iv = cpu_to_be64(sector);
+ break;
+ case IV_ESSIV:
+ memset(ctx->iv, 0, ctx->iv_size);
+ u64_iv = (void *)ctx->iv;
+ *u64_iv = cpu_to_le64(sector);
+ return crypt_cipher_encrypt(ctx->cipher,
+ ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
+ break;
+ case IV_BENBI:
+ memset(ctx->iv, 0, ctx->iv_size);
+ val = cpu_to_be64((sector << ctx->shift) + 1);
+ memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
+ break;
+ case IV_EBOIV:
+ memset(ctx->iv, 0, ctx->iv_size);
+ u64_iv = (void *)ctx->iv;
+ *u64_iv = cpu_to_le64(sector << ctx->shift);
+ return crypt_cipher_encrypt(ctx->cipher,
+ ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
+{
+ if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV)
+ crypt_cipher_destroy(ctx->cipher);
+
+ if (ctx->iv) {
+ memset(ctx->iv, 0, ctx->iv_size);
+ free(ctx->iv);
+ }
+
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+/* Block encryption storage wrappers */
+
+int crypt_storage_init(struct crypt_storage **ctx,
+ size_t sector_size,
+ const char *cipher,
+ const char *cipher_mode,
+ const void *key, size_t key_length,
+ bool large_iv)
+{
+ struct crypt_storage *s;
+ char mode_name[64];
+ char *cipher_iv = NULL;
+ int r = -EIO;
+
+ if (sector_size < (1 << SECTOR_SHIFT) ||
+ sector_size > (1 << (SECTOR_SHIFT + 3)) ||
+ sector_size & (sector_size - 1))
+ return -EINVAL;
+
+ s = malloc(sizeof(*s));
+ if (!s)
+ return -ENOMEM;
+ memset(s, 0, sizeof(*s));
+
+ /* Remove IV if present */
+ strncpy(mode_name, cipher_mode, sizeof(mode_name));
+ mode_name[sizeof(mode_name) - 1] = 0;
+ cipher_iv = strchr(mode_name, '-');
+ if (cipher_iv) {
+ *cipher_iv = '\0';
+ cipher_iv++;
+ }
+
+ r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
+ if (r) {
+ crypt_storage_destroy(s);
+ return r;
+ }
+
+ r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size);
+ if (r) {
+ crypt_storage_destroy(s);
+ return r;
+ }
+
+ s->sector_size = sector_size;
+ s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
+
+ *ctx = s;
+ return 0;
+}
+
+int crypt_storage_decrypt(struct crypt_storage *ctx,
+ uint64_t iv_offset,
+ uint64_t length, char *buffer)
+{
+ uint64_t i;
+ int r = 0;
+
+ if (length & (ctx->sector_size - 1))
+ return -EINVAL;
+
+ if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
+ return -EINVAL;
+
+ for (i = 0; i < length; i += ctx->sector_size) {
+ r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
+ if (r)
+ break;
+ r = crypt_cipher_decrypt(ctx->cipher,
+ &buffer[i],
+ &buffer[i],
+ ctx->sector_size,
+ ctx->cipher_iv.iv,
+ ctx->cipher_iv.iv_size);
+ if (r)
+ break;
+ }
+
+ return r;
+}
+
+int crypt_storage_encrypt(struct crypt_storage *ctx,
+ uint64_t iv_offset,
+ uint64_t length, char *buffer)
+{
+ uint64_t i;
+ int r = 0;
+
+ if (length & (ctx->sector_size - 1))
+ return -EINVAL;
+
+ if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
+ return -EINVAL;
+
+ for (i = 0; i < length; i += ctx->sector_size) {
+ r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
+ if (r)
+ break;
+ r = crypt_cipher_encrypt(ctx->cipher,
+ &buffer[i],
+ &buffer[i],
+ ctx->sector_size,
+ ctx->cipher_iv.iv,
+ ctx->cipher_iv.iv_size);
+ if (r)
+ break;
+ }
+
+ return r;
+}
+
+void crypt_storage_destroy(struct crypt_storage *ctx)
+{
+ if (!ctx)
+ return;
+
+ crypt_sector_iv_destroy(&ctx->cipher_iv);
+
+ if (ctx->cipher)
+ crypt_cipher_destroy(ctx->cipher);
+
+ memset(ctx, 0, sizeof(*ctx));
+ free(ctx);
+}
+
+bool crypt_storage_kernel_only(struct crypt_storage *ctx)
+{
+ return crypt_cipher_kernel_only(ctx->cipher);
+}
diff --git a/lib/crypto_backend/pbkdf2_generic.c b/lib/crypto_backend/pbkdf2_generic.c
new file mode 100644
index 0000000..9e87e19
--- /dev/null
+++ b/lib/crypto_backend/pbkdf2_generic.c
@@ -0,0 +1,232 @@
+/*
+ * Implementation of Password-Based Cryptography as per PKCS#5
+ * Copyright (C) 2002,2003 Simon Josefsson
+ * Copyright (C) 2004 Free Software Foundation
+ *
+ * cryptsetup related changes
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <errno.h>
+#include <alloca.h>
+#include "crypto_backend_internal.h"
+
+static int hash_buf(const char *src, size_t src_len,
+ char *dst, size_t dst_len,
+ const char *hash_name)
+{
+ struct crypt_hash *hd = NULL;
+ int r;
+
+ if (crypt_hash_init(&hd, hash_name))
+ return -EINVAL;
+
+ r = crypt_hash_write(hd, src, src_len);
+
+ if (!r)
+ r = crypt_hash_final(hd, dst, dst_len);
+
+ crypt_hash_destroy(hd);
+ return r;
+}
+
+/*
+ * 5.2 PBKDF2
+ *
+ * PBKDF2 applies a pseudorandom function (see Appendix B.1 for an
+ * example) to derive keys. The length of the derived key is essentially
+ * unbounded. (However, the maximum effective search space for the
+ * derived key may be limited by the structure of the underlying
+ * pseudorandom function. See Appendix B.1 for further discussion.)
+ * PBKDF2 is recommended for new applications.
+ *
+ * PBKDF2 (P, S, c, dkLen)
+ *
+ * Options: PRF underlying pseudorandom function (hLen
+ * denotes the length in octets of the
+ * pseudorandom function output)
+ *
+ * Input: P password, an octet string (ASCII or UTF-8)
+ * S salt, an octet string
+ * c iteration count, a positive integer
+ * dkLen intended length in octets of the derived
+ * key, a positive integer, at most
+ * (2^32 - 1) * hLen
+ *
+ * Output: DK derived key, a dkLen-octet string
+ */
+
+/*
+ * if hash_block_size is not zero, the HMAC key is pre-hashed
+ * inside this function.
+ * This prevents situation when crypto backend doesn't support
+ * long HMAC keys or it tries hash long key in every iteration
+ * (because of crypt_final() cannot do simple key reset.
+ */
+
+#define MAX_PRF_BLOCK_LEN 80
+
+int pkcs5_pbkdf2(const char *hash,
+ const char *P, size_t Plen,
+ const char *S, size_t Slen,
+ unsigned int c, unsigned int dkLen,
+ char *DK, unsigned int hash_block_size)
+{
+ struct crypt_hmac *hmac;
+ char U[MAX_PRF_BLOCK_LEN];
+ char T[MAX_PRF_BLOCK_LEN];
+ char P_hash[MAX_PRF_BLOCK_LEN];
+ int i, k, rc = -EINVAL;
+ unsigned int u, hLen, l, r;
+ size_t tmplen = Slen + 4;
+ char *tmp;
+
+ tmp = alloca(tmplen);
+ if (tmp == NULL)
+ return -ENOMEM;
+
+ hLen = crypt_hmac_size(hash);
+ if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
+ return -EINVAL;
+
+ if (c == 0)
+ return -EINVAL;
+
+ if (dkLen == 0)
+ return -EINVAL;
+
+ /*
+ *
+ * Steps:
+ *
+ * 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
+ * stop.
+ */
+
+ if (dkLen > 4294967295U)
+ return -EINVAL;
+
+ /*
+ * 2. Let l be the number of hLen-octet blocks in the derived key,
+ * rounding up, and let r be the number of octets in the last
+ * block:
+ *
+ * l = CEIL (dkLen / hLen) ,
+ * r = dkLen - (l - 1) * hLen .
+ *
+ * Here, CEIL (x) is the "ceiling" function, i.e. the smallest
+ * integer greater than, or equal to, x.
+ */
+
+ l = dkLen / hLen;
+ if (dkLen % hLen)
+ l++;
+ r = dkLen - (l - 1) * hLen;
+
+ /*
+ * 3. For each block of the derived key apply the function F defined
+ * below to the password P, the salt S, the iteration count c, and
+ * the block index to compute the block:
+ *
+ * T_1 = F (P, S, c, 1) ,
+ * T_2 = F (P, S, c, 2) ,
+ * ...
+ * T_l = F (P, S, c, l) ,
+ *
+ * where the function F is defined as the exclusive-or sum of the
+ * first c iterates of the underlying pseudorandom function PRF
+ * applied to the password P and the concatenation of the salt S
+ * and the block index i:
+ *
+ * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
+ *
+ * where
+ *
+ * U_1 = PRF (P, S || INT (i)) ,
+ * U_2 = PRF (P, U_1) ,
+ * ...
+ * U_c = PRF (P, U_{c-1}) .
+ *
+ * Here, INT (i) is a four-octet encoding of the integer i, most
+ * significant octet first.
+ *
+ * 4. Concatenate the blocks and extract the first dkLen octets to
+ * produce a derived key DK:
+ *
+ * DK = T_1 || T_2 || ... || T_l<0..r-1>
+ *
+ * 5. Output the derived key DK.
+ *
+ * Note. The construction of the function F follows a "belt-and-
+ * suspenders" approach. The iterates U_i are computed recursively to
+ * remove a degree of parallelism from an opponent; they are exclusive-
+ * ored together to reduce concerns about the recursion degenerating
+ * into a small set of values.
+ *
+ */
+
+ /* If hash_block_size is provided, hash password in advance. */
+ if (hash_block_size > 0 && Plen > hash_block_size) {
+ if (hash_buf(P, Plen, P_hash, hLen, hash))
+ return -EINVAL;
+
+ if (crypt_hmac_init(&hmac, hash, P_hash, hLen))
+ return -EINVAL;
+ crypt_backend_memzero(P_hash, sizeof(P_hash));
+ } else {
+ if (crypt_hmac_init(&hmac, hash, P, Plen))
+ return -EINVAL;
+ }
+
+ for (i = 1; (unsigned int) i <= l; i++) {
+ memset(T, 0, hLen);
+
+ for (u = 1; u <= c ; u++) {
+ if (u == 1) {
+ memcpy(tmp, S, Slen);
+ tmp[Slen + 0] = (i & 0xff000000) >> 24;
+ tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
+ tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
+ tmp[Slen + 3] = (i & 0x000000ff) >> 0;
+
+ if (crypt_hmac_write(hmac, tmp, tmplen))
+ goto out;
+ } else {
+ if (crypt_hmac_write(hmac, U, hLen))
+ goto out;
+ }
+
+ if (crypt_hmac_final(hmac, U, hLen))
+ goto out;
+
+ for (k = 0; (unsigned int) k < hLen; k++)
+ T[k] ^= U[k];
+ }
+
+ memcpy(DK + (i - 1) * hLen, T, (unsigned int) i == l ? r : hLen);
+ }
+ rc = 0;
+out:
+ crypt_hmac_destroy(hmac);
+ crypt_backend_memzero(U, sizeof(U));
+ crypt_backend_memzero(T, sizeof(T));
+ crypt_backend_memzero(tmp, tmplen);
+
+ return rc;
+}
diff --git a/lib/crypto_backend/pbkdf_check.c b/lib/crypto_backend/pbkdf_check.c
new file mode 100644
index 0000000..53a2da9
--- /dev/null
+++ b/lib/crypto_backend/pbkdf_check.c
@@ -0,0 +1,443 @@
+/*
+ * PBKDF performance check
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ * Copyright (C) 2016-2020 Ondrej Mosnacek
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include "crypto_backend.h"
+
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
+#endif
+
+#define BENCH_MIN_MS 250
+#define BENCH_MIN_MS_FAST 10
+#define BENCH_PERCENT_ATLEAST 95
+#define BENCH_PERCENT_ATMOST 110
+#define BENCH_SAMPLES_FAST 3
+#define BENCH_SAMPLES_SLOW 1
+
+/* These PBKDF2 limits must be never violated */
+int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *limits)
+{
+ if (!kdf || !limits)
+ return -EINVAL;
+
+ if (!strcmp(kdf, "pbkdf2")) {
+ limits->min_iterations = 1000; /* recommendation in NIST SP 800-132 */
+ limits->max_iterations = UINT32_MAX;
+ limits->min_memory = 0; /* N/A */
+ limits->min_bench_memory=0; /* N/A */
+ limits->max_memory = 0; /* N/A */
+ limits->min_parallel = 0; /* N/A */
+ limits->max_parallel = 0; /* N/A */
+ return 0;
+ } else if (!strcmp(kdf, "argon2i") || !strcmp(kdf, "argon2id")) {
+ limits->min_iterations = 4;
+ limits->max_iterations = UINT32_MAX;
+ limits->min_memory = 32; /* hard limit */
+ limits->min_bench_memory=64*1024; /* 64 MiB minimum for benchmark */
+ limits->max_memory = 4*1024*1024; /* 4GiB */
+ limits->min_parallel = 1;
+ limits->max_parallel = 4;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static long time_ms(struct rusage *start, struct rusage *end)
+{
+ int count_kernel_time = 0;
+ long ms;
+
+ if (crypt_backend_flags() & CRYPT_BACKEND_KERNEL)
+ count_kernel_time = 1;
+
+ /*
+ * If there is no self usage info, count system time.
+ * This seem like getrusage() bug in some hypervisors...
+ */
+ if (!end->ru_utime.tv_sec && !start->ru_utime.tv_sec &&
+ !end->ru_utime.tv_usec && !start->ru_utime.tv_usec)
+ count_kernel_time = 1;
+
+ ms = (end->ru_utime.tv_sec - start->ru_utime.tv_sec) * 1000;
+ ms += (end->ru_utime.tv_usec - start->ru_utime.tv_usec) / 1000;
+
+ if (count_kernel_time) {
+ ms += (end->ru_stime.tv_sec - start->ru_stime.tv_sec) * 1000;
+ ms += (end->ru_stime.tv_usec - start->ru_stime.tv_usec) / 1000;
+ }
+
+ return ms;
+}
+
+static long timespec_ms(struct timespec *start, struct timespec *end)
+{
+ return (end->tv_sec - start->tv_sec) * 1000 +
+ (end->tv_nsec - start->tv_nsec) / (1000 * 1000);
+}
+
+static int measure_argon2(const char *kdf, const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t t_cost, uint32_t m_cost, uint32_t parallel,
+ size_t samples, long ms_atleast, long *out_ms)
+{
+ long ms, ms_min = LONG_MAX;
+ int r;
+ size_t i;
+
+ for (i = 0; i < samples; i++) {
+ struct timespec tstart, tend;
+
+ /*
+ * NOTE: We must use clock_gettime here, because Argon2 can run over
+ * multiple threads, and thus we care about real time, not CPU time!
+ */
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &tstart) < 0)
+ return -EINVAL;
+
+ r = crypt_pbkdf(kdf, NULL, password, password_length, salt,
+ salt_length, key, key_length, t_cost, m_cost, parallel);
+ if (r < 0)
+ return r;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &tend) < 0)
+ return -EINVAL;
+
+ ms = timespec_ms(&tstart, &tend);
+ if (ms < 0)
+ return -EINVAL;
+
+ if (ms < ms_atleast) {
+ /* early exit */
+ ms_min = ms;
+ break;
+ }
+ if (ms < ms_min) {
+ ms_min = ms;
+ }
+ }
+ *out_ms = ms_min;
+ return 0;
+}
+
+#define CONTINUE 0
+#define FINAL 1
+static int next_argon2_params(uint32_t *t_cost, uint32_t *m_cost,
+ uint32_t min_t_cost, uint32_t min_m_cost,
+ uint32_t max_m_cost, long ms, uint32_t target_ms)
+{
+ uint32_t old_t_cost, old_m_cost, new_t_cost, new_m_cost;
+ uint64_t num, denom;
+
+ old_t_cost = *t_cost;
+ old_m_cost = *m_cost;
+
+ if ((uint32_t)ms > target_ms) {
+ /* decreasing, first try to lower t_cost, then m_cost */
+ num = (uint64_t)*t_cost * (uint64_t)target_ms;
+ denom = (uint64_t)ms;
+ new_t_cost = (uint32_t)(num / denom);
+ if (new_t_cost < min_t_cost) {
+ num = (uint64_t)*t_cost * (uint64_t)*m_cost *
+ (uint64_t)target_ms;
+ denom = (uint64_t)min_t_cost * (uint64_t)ms;
+ *t_cost = min_t_cost;
+ *m_cost = (uint32_t)(num / denom);
+ if (*m_cost < min_m_cost) {
+ *m_cost = min_m_cost;
+ return FINAL;
+ }
+ } else {
+ *t_cost = new_t_cost;
+ }
+ } else {
+ /* increasing, first try to increase m_cost, then t_cost */
+ num = (uint64_t)*m_cost * (uint64_t)target_ms;
+ denom = (uint64_t)ms;
+ new_m_cost = (uint32_t)(num / denom);
+ if (new_m_cost > max_m_cost) {
+ num = (uint64_t)*t_cost * (uint64_t)*m_cost *
+ (uint64_t)target_ms;
+ denom = (uint64_t)max_m_cost * (uint64_t)ms;
+ *t_cost = (uint32_t)(num / denom);
+ *m_cost = max_m_cost;
+ if (*t_cost <= min_t_cost) {
+ *t_cost = min_t_cost;
+ return FINAL;
+ }
+ } else if (new_m_cost < min_m_cost) {
+ *m_cost = min_m_cost;
+ return FINAL;
+ } else {
+ *m_cost = new_m_cost;
+ }
+ }
+
+ /* do not continue if it is the same as in the previous run */
+ if (old_t_cost == *t_cost && old_m_cost == *m_cost)
+ return FINAL;
+
+ return CONTINUE;
+}
+
+static int crypt_argon2_check(const char *kdf, const char *password,
+ size_t password_length, const char *salt,
+ size_t salt_length, size_t key_length,
+ uint32_t min_t_cost, uint32_t min_m_cost, uint32_t max_m_cost,
+ uint32_t parallel, uint32_t target_ms,
+ uint32_t *out_t_cost, uint32_t *out_m_cost,
+ int (*progress)(uint32_t time_ms, void *usrptr),
+ void *usrptr)
+{
+ int r = 0;
+ char *key = NULL;
+ uint32_t t_cost, m_cost;
+ long ms;
+ long ms_atleast = (long)target_ms * BENCH_PERCENT_ATLEAST / 100;
+ long ms_atmost = (long)target_ms * BENCH_PERCENT_ATMOST / 100;
+
+ if (key_length <= 0 || target_ms <= 0)
+ return -EINVAL;
+
+ if (min_m_cost < (parallel * 8))
+ min_m_cost = parallel * 8;
+
+ if (max_m_cost < min_m_cost)
+ return -EINVAL;
+
+ key = malloc(key_length);
+ if (!key)
+ return -ENOMEM;
+
+ t_cost = min_t_cost;
+ m_cost = min_m_cost;
+
+ /* 1. Find some small parameters, s. t. ms >= BENCH_MIN_MS: */
+ while (1) {
+ r = measure_argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, t_cost, m_cost, parallel,
+ BENCH_SAMPLES_FAST, BENCH_MIN_MS, &ms);
+ if (!r) {
+ /* Update parameters to actual measurement */
+ *out_t_cost = t_cost;
+ *out_m_cost = m_cost;
+ if (progress && progress((uint32_t)ms, usrptr))
+ r = -EINTR;
+ }
+
+ if (r < 0)
+ goto out;
+
+ if (ms >= BENCH_MIN_MS)
+ break;
+
+ if (m_cost == max_m_cost) {
+ if (ms < BENCH_MIN_MS_FAST)
+ t_cost *= 16;
+ else {
+ uint32_t new = (t_cost * BENCH_MIN_MS) / (uint32_t)ms;
+ if (new == t_cost)
+ break;
+
+ t_cost = new;
+ }
+ } else {
+ if (ms < BENCH_MIN_MS_FAST)
+ m_cost *= 16;
+ else {
+ uint32_t new = (m_cost * BENCH_MIN_MS) / (uint32_t)ms;
+ if (new == m_cost)
+ break;
+
+ m_cost = new;
+ }
+ if (m_cost > max_m_cost) {
+ m_cost = max_m_cost;
+ }
+ }
+ }
+ /*
+ * 2. Use the params obtained in (1.) to estimate the target params.
+ * 3. Then repeatedly measure the candidate params and if they fall out of
+ * the acceptance range (+-5 %), try to improve the estimate:
+ */
+ do {
+ if (next_argon2_params(&t_cost, &m_cost, min_t_cost, min_m_cost,
+ max_m_cost, ms, target_ms)) {
+ /* Update parameters to final computation */
+ *out_t_cost = t_cost;
+ *out_m_cost = m_cost;
+ break;
+ }
+
+ r = measure_argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, t_cost, m_cost, parallel,
+ BENCH_SAMPLES_SLOW, ms_atleast, &ms);
+
+ if (!r) {
+ /* Update parameters to actual measurement */
+ *out_t_cost = t_cost;
+ *out_m_cost = m_cost;
+ if (progress && progress((uint32_t)ms, usrptr))
+ r = -EINTR;
+ }
+
+ if (r < 0)
+ break;
+
+ } while (ms < ms_atleast || ms > ms_atmost);
+out:
+ if (key) {
+ crypt_backend_memzero(key, key_length);
+ free(key);
+ }
+ return r;
+}
+
+/* This code benchmarks PBKDF and returns iterations/second using specified hash */
+static int crypt_pbkdf_check(const char *kdf, const char *hash,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ size_t key_length, uint32_t *iter_secs, uint32_t target_ms,
+ int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
+
+{
+ struct rusage rstart, rend;
+ int r = 0, step = 0;
+ long ms = 0;
+ char *key = NULL;
+ uint32_t iterations;
+ double PBKDF2_temp;
+
+ if (!kdf || !hash || key_length <= 0)
+ return -EINVAL;
+
+ key = malloc(key_length);
+ if (!key)
+ return -ENOMEM;
+
+ *iter_secs = 0;
+ iterations = 1 << 15;
+ while (1) {
+ if (getrusage(RUSAGE_SELF, &rstart) < 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = crypt_pbkdf(kdf, hash, password, password_length, salt,
+ salt_length, key, key_length, iterations, 0, 0);
+
+ if (r < 0)
+ goto out;
+
+ if (getrusage(RUSAGE_SELF, &rend) < 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ ms = time_ms(&rstart, &rend);
+ if (ms) {
+ PBKDF2_temp = (double)iterations * target_ms / ms;
+ if (PBKDF2_temp > UINT32_MAX) {
+ r = -EINVAL;
+ goto out;
+ }
+ *iter_secs = (uint32_t)PBKDF2_temp;
+ }
+
+ if (progress && progress((uint32_t)ms, usrptr)) {
+ r = -EINTR;
+ goto out;
+ }
+
+ if (ms > 500)
+ break;
+
+ if (ms <= 62)
+ iterations <<= 4;
+ else if (ms <= 125)
+ iterations <<= 3;
+ else if (ms <= 250)
+ iterations <<= 2;
+ else
+ iterations <<= 1;
+
+ if (++step > 10 || !iterations) {
+ r = -EINVAL;
+ goto out;
+ }
+ }
+out:
+ if (key) {
+ crypt_backend_memzero(key, key_length);
+ free(key);
+ }
+ return r;
+}
+
+int crypt_pbkdf_perf(const char *kdf, const char *hash,
+ const char *password, size_t password_size,
+ const char *salt, size_t salt_size,
+ size_t volume_key_size, uint32_t time_ms,
+ uint32_t max_memory_kb, uint32_t parallel_threads,
+ uint32_t *iterations_out, uint32_t *memory_out,
+ int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
+{
+ struct crypt_pbkdf_limits pbkdf_limits;
+ int r = -EINVAL;
+ uint32_t min_memory;
+
+ if (!kdf || !iterations_out || !memory_out)
+ return -EINVAL;
+
+ r = crypt_pbkdf_get_limits(kdf, &pbkdf_limits);
+ if (r < 0)
+ return r;
+
+ min_memory = pbkdf_limits.min_bench_memory;
+ if (min_memory > max_memory_kb)
+ min_memory = max_memory_kb;
+
+ *memory_out = 0;
+ *iterations_out = 0;
+
+ if (!strcmp(kdf, "pbkdf2"))
+ r = crypt_pbkdf_check(kdf, hash, password, password_size,
+ salt, salt_size, volume_key_size,
+ iterations_out, time_ms, progress, usrptr);
+
+ else if (!strncmp(kdf, "argon2", 6))
+ r = crypt_argon2_check(kdf, password, password_size,
+ salt, salt_size, volume_key_size,
+ pbkdf_limits.min_iterations,
+ min_memory,
+ max_memory_kb,
+ parallel_threads, time_ms, iterations_out,
+ memory_out, progress, usrptr);
+ return r;
+}
diff --git a/lib/crypto_backend/utf8.c b/lib/crypto_backend/utf8.c
new file mode 100644
index 0000000..24e0d8d
--- /dev/null
+++ b/lib/crypto_backend/utf8.c
@@ -0,0 +1,288 @@
+/*
+ * UTF8/16 helpers, copied and adapted from systemd project.
+ *
+ * Copyright (C) 2010 Lennart Poettering
+ *
+ * cryptsetup related changes
+ * Copyright (C) 2021-2023 Vojtech Trefny
+
+ * Parts of the original systemd implementation are based on the GLIB utf8
+ * validation functions.
+ * gutf8.c - Operations on UTF-8 strings.
+ *
+ * Copyright (C) 1999 Tom Tromey
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <errno.h>
+#include <endian.h>
+
+#include "crypto_backend.h"
+
+static inline bool utf16_is_surrogate(char16_t c)
+{
+ return c >= 0xd800U && c <= 0xdfffU;
+}
+
+static inline bool utf16_is_trailing_surrogate(char16_t c)
+{
+ return c >= 0xdc00U && c <= 0xdfffU;
+}
+
+static inline char32_t utf16_surrogate_pair_to_unichar(char16_t lead, char16_t trail)
+{
+ return ((((char32_t) lead - 0xd800U) << 10) + ((char32_t) trail - 0xdc00U) + 0x10000U);
+}
+
+/**
+ * utf8_encode_unichar() - Encode single UCS-4 character as UTF-8
+ * @out_utf8: output buffer of at least 4 bytes or NULL
+ * @g: UCS-4 character to encode
+ *
+ * This encodes a single UCS-4 character as UTF-8 and writes it into @out_utf8.
+ * The length of the character is returned. It is not zero-terminated! If the
+ * output buffer is NULL, only the length is returned.
+ *
+ * Returns: The length in bytes that the UTF-8 representation does or would
+ * occupy.
+ */
+static size_t utf8_encode_unichar(char *out_utf8, char32_t g)
+{
+ if (g < (1 << 7)) {
+ if (out_utf8)
+ out_utf8[0] = g & 0x7f;
+ return 1;
+ } else if (g < (1 << 11)) {
+ if (out_utf8) {
+ out_utf8[0] = 0xc0 | ((g >> 6) & 0x1f);
+ out_utf8[1] = 0x80 | (g & 0x3f);
+ }
+ return 2;
+ } else if (g < (1 << 16)) {
+ if (out_utf8) {
+ out_utf8[0] = 0xe0 | ((g >> 12) & 0x0f);
+ out_utf8[1] = 0x80 | ((g >> 6) & 0x3f);
+ out_utf8[2] = 0x80 | (g & 0x3f);
+ }
+ return 3;
+ } else if (g < (1 << 21)) {
+ if (out_utf8) {
+ out_utf8[0] = 0xf0 | ((g >> 18) & 0x07);
+ out_utf8[1] = 0x80 | ((g >> 12) & 0x3f);
+ out_utf8[2] = 0x80 | ((g >> 6) & 0x3f);
+ out_utf8[3] = 0x80 | (g & 0x3f);
+ }
+ return 4;
+ }
+
+ return 0;
+}
+
+/**
+ * crypt_utf16_to_utf8()
+ * @out: output buffer, should be 2 * @length + 1 long
+ * @s: string to convert
+ * @length: length of @s in bytes
+ *
+ * Converts a UTF16LE encoded string to a UTF8 encoded string.
+ *
+ * Returns: 0 on success, negative errno otherwise
+ */
+int crypt_utf16_to_utf8(char **out, const char16_t *s, size_t length /* bytes! */)
+{
+ const uint8_t *f;
+ char *t;
+
+ assert(s);
+ assert(out);
+ assert(*out);
+
+ /* Input length is in bytes, i.e. the shortest possible character takes 2 bytes. Each unicode character may
+ * take up to 4 bytes in UTF-8. Let's also account for a trailing NUL byte. */
+ if (length * 2 < length)
+ return -EOVERFLOW; /* overflow */
+
+ f = (const uint8_t*) s;
+ t = *out;
+
+ while (f + 1 < (const uint8_t*) s + length) {
+ char16_t w1, w2;
+
+ /* see RFC 2781 section 2.2 */
+
+ w1 = f[1] << 8 | f[0];
+ f += 2;
+
+ if (!utf16_is_surrogate(w1)) {
+ t += utf8_encode_unichar(t, w1);
+ continue;
+ }
+
+ if (utf16_is_trailing_surrogate(w1))
+ continue; /* spurious trailing surrogate, ignore */
+
+ if (f + 1 >= (const uint8_t*) s + length)
+ break;
+
+ w2 = f[1] << 8 | f[0];
+ f += 2;
+
+ if (!utf16_is_trailing_surrogate(w2)) {
+ f -= 2;
+ continue; /* surrogate missing its trailing surrogate, ignore */
+ }
+
+ t += utf8_encode_unichar(t, utf16_surrogate_pair_to_unichar(w1, w2));
+ }
+
+ *t = 0;
+ return 0;
+}
+
+/* count of characters used to encode one unicode char */
+static size_t utf8_encoded_expected_len(uint8_t c)
+{
+ if (c < 0x80)
+ return 1;
+ if ((c & 0xe0) == 0xc0)
+ return 2;
+ if ((c & 0xf0) == 0xe0)
+ return 3;
+ if ((c & 0xf8) == 0xf0)
+ return 4;
+ if ((c & 0xfc) == 0xf8)
+ return 5;
+ if ((c & 0xfe) == 0xfc)
+ return 6;
+
+ return 0;
+}
+
+/* decode one unicode char */
+static int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar)
+{
+ char32_t unichar;
+ size_t len, i;
+
+ assert(str);
+
+ len = utf8_encoded_expected_len(str[0]);
+
+ switch (len) {
+ case 1:
+ *ret_unichar = (char32_t)str[0];
+ return 0;
+ case 2:
+ unichar = str[0] & 0x1f;
+ break;
+ case 3:
+ unichar = (char32_t)str[0] & 0x0f;
+ break;
+ case 4:
+ unichar = (char32_t)str[0] & 0x07;
+ break;
+ case 5:
+ unichar = (char32_t)str[0] & 0x03;
+ break;
+ case 6:
+ unichar = (char32_t)str[0] & 0x01;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 1; i < len; i++) {
+ if (((char32_t)str[i] & 0xc0) != 0x80)
+ return -EINVAL;
+
+ unichar <<= 6;
+ unichar |= (char32_t)str[i] & 0x3f;
+ }
+
+ *ret_unichar = unichar;
+
+ return 0;
+}
+
+static size_t utf16_encode_unichar(char16_t *out, char32_t c)
+{
+ /* Note that this encodes as little-endian. */
+
+ switch (c) {
+
+ case 0 ... 0xd7ffU:
+ case 0xe000U ... 0xffffU:
+ out[0] = htole16(c);
+ return 1;
+
+ case 0x10000U ... 0x10ffffU:
+ c -= 0x10000U;
+ out[0] = htole16((c >> 10) + 0xd800U);
+ out[1] = htole16((c & 0x3ffU) + 0xdc00U);
+ return 2;
+
+ default: /* A surrogate (invalid) */
+ return 0;
+ }
+}
+
+/**
+ * crypt_utf8_to_utf16()
+ * @out: output buffer, should be @length + 1 long
+ * @s: string to convert
+ * @length: length of @s in bytes
+ *
+ * Converts a UTF8 encoded string to a UTF16LE encoded string.
+ *
+ * Returns: 0 on success, negative errno otherwise
+ */
+int crypt_utf8_to_utf16(char16_t **out, const char *s, size_t length)
+{
+ char16_t *p;
+ size_t i;
+ int r;
+
+ assert(s);
+
+ p = *out;
+
+ for (i = 0; i < length;) {
+ char32_t unichar;
+ size_t e;
+
+ e = utf8_encoded_expected_len(s[i]);
+ if (e <= 1) /* Invalid and single byte characters are copied as they are */
+ goto copy;
+
+ if (i + e > length) /* sequence longer than input buffer, then copy as-is */
+ goto copy;
+
+ r = utf8_encoded_to_unichar(s + i, &unichar);
+ if (r < 0) /* sequence invalid, then copy as-is */
+ goto copy;
+
+ p += utf16_encode_unichar(p, unichar);
+ i += e;
+ continue;
+
+ copy:
+ *(p++) = htole16(s[i++]);
+ }
+
+ *p = 0;
+ return 0;
+}
diff --git a/lib/fvault2/fvault2.c b/lib/fvault2/fvault2.c
new file mode 100644
index 0000000..0b0c9ce
--- /dev/null
+++ b/lib/fvault2/fvault2.c
@@ -0,0 +1,1057 @@
+/*
+ * FVAULT2 (FileVault2-compatible) volume handling
+ *
+ * Copyright (C) 2021-2022 Pavel Tobias
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <regex.h>
+#include <stdio.h>
+#include <uuid/uuid.h>
+
+#include "internal.h"
+#include "fvault2.h"
+
+/* Core Storage signature/magic; "CS" big-endian */
+#define FVAULT2_CORE_STORAGE_MAGIC 0x4353
+
+/* size of the physical volume header in bytes */
+#define FVAULT2_VOL_HEADER_SIZE 512
+
+/* size of a single metadata block in bytes */
+#define FVAULT2_MD_BLOCK_SIZE 8192
+
+/* maximal offset to read metadata block */
+#define FVAULT2_MAX_OFF 1024*1024*1024
+
+/* encrypted metadata parsing progress flags (see _read_encrypted_metadata) */
+#define FVAULT2_ENC_MD_PARSED_0x0019 0b001
+#define FVAULT2_ENC_MD_PARSED_0x001A 0b010
+#define FVAULT2_ENC_MD_PARSED_0x0305 0b100
+#define FVAULT2_ENC_MD_PARSED_NONE 0b000
+#define FVAULT2_ENC_MD_PARSED_ALL 0b111
+
+/* sizes of decoded PassphraseWrappedKEKStruct and KEKWrappedVolumeKeyStruct */
+#define FVAULT2_PWK_SIZE 284
+#define FVAULT2_KWVK_SIZE 256
+
+/* size of an AES-128 key */
+#define FVAULT2_AES_KEY_SIZE 16
+
+/* size of the volume key and the encrypted metadata decryption key */
+#define FVAULT2_XTS_KEY_SIZE (FVAULT2_AES_KEY_SIZE * 2)
+
+/* size of an XTS tweak value */
+#define FVAULT2_XTS_TWEAK_SIZE 16
+
+/* size of a binary representation of a UUID */
+#define FVAULT2_UUID_BIN_SIZE 16
+
+struct crc32_checksum {
+ uint32_t value;
+ uint32_t seed;
+} __attribute__((packed));
+
+struct volume_header {
+ struct crc32_checksum checksum;
+ uint16_t version;
+ uint16_t block_type;
+ uint8_t unknown1[52];
+ uint64_t ph_vol_size;
+ uint8_t unknown2[16];
+ uint16_t magic;
+ uint32_t checksum_algo;
+ uint8_t unknown3[2];
+ uint32_t block_size;
+ uint32_t metadata_size;
+ uint64_t disklbl_blkoff;
+ uint64_t other_md_blkoffs[3];
+ uint8_t unknown4[32];
+ uint32_t key_data_size;
+ uint32_t cipher;
+ uint8_t key_data[FVAULT2_AES_KEY_SIZE];
+ uint8_t unknown5[112];
+ uint8_t ph_vol_uuid[FVAULT2_UUID_BIN_SIZE];
+ uint8_t unknown6[192];
+} __attribute__((packed));
+
+struct volume_groups_descriptor {
+ uint8_t unknown1[8];
+ uint64_t enc_md_blocks_n;
+ uint8_t unknown2[16];
+ uint64_t enc_md_blkoff;
+} __attribute__((packed));
+
+struct metadata_block_header {
+ struct crc32_checksum checksum;
+ uint16_t version;
+ uint16_t block_type;
+ uint8_t unknown1[20];
+ uint64_t block_num;
+ uint8_t unknown2[8];
+ uint32_t block_size;
+ uint8_t unknown3[12];
+} __attribute__((packed));
+
+struct metadata_block_0x0011 {
+ struct metadata_block_header header;
+ uint32_t md_size;
+ uint8_t unknown1[4];
+ struct crc32_checksum checksum;
+ uint8_t unknown2[140];
+ uint32_t vol_gr_des_off;
+} __attribute__((packed));
+
+struct metadata_block_0x0019 {
+ struct metadata_block_header header;
+ uint8_t unknown1[40];
+ uint32_t xml_comp_size;
+ uint32_t xml_uncomp_size;
+ uint32_t xml_off;
+ uint32_t xml_size;
+} __attribute__((packed));
+
+struct metadata_block_0x001a {
+ struct metadata_block_header header;
+ uint8_t unknown1[64];
+ uint32_t xml_off;
+ uint32_t xml_size;
+} __attribute__((packed));
+
+struct metadata_block_0x0305 {
+ struct metadata_block_header header;
+ uint32_t entries_n;
+ uint8_t unknown1[36];
+ uint32_t log_vol_blkoff;
+} __attribute__((packed));
+
+struct passphrase_wrapped_kek {
+ uint32_t pbkdf2_salt_type;
+ uint32_t pbkdf2_salt_size;
+ uint8_t pbkdf2_salt[FVAULT2_PBKDF2_SALT_SIZE];
+ uint32_t wrapped_kek_type;
+ uint32_t wrapped_kek_size;
+ uint8_t wrapped_kek[FVAULT2_WRAPPED_KEY_SIZE];
+ uint8_t unknown1[112];
+ uint32_t pbkdf2_iters;
+} __attribute__((packed));
+
+struct kek_wrapped_volume_key {
+ uint32_t wrapped_vk_type;
+ uint32_t wrapped_vk_size;
+ uint8_t wrapped_vk[FVAULT2_WRAPPED_KEY_SIZE];
+} __attribute__((packed));
+
+/**
+ * Test whether all bytes of a chunk of memory are equal to a constant value.
+ * @param[in] value the value all bytes should be equal to
+ * @param[in] data the tested chunk of memory
+ * @param[in] data_size byte-size of the chunk of memory
+ */
+static bool _filled_with(
+ uint8_t value,
+ const void *data,
+ size_t data_size)
+{
+ const uint8_t *data_bytes = data;
+ size_t i;
+
+ for (i = 0; i < data_size; i++)
+ if (data_bytes[i] != value)
+ return false;
+
+ return true;
+}
+
+/**
+ * Assert the validity of the CRC checksum of a chunk of memory.
+ * @param[in] data a chunk of memory starting with a crc32_checksum struct
+ * @param[in] data_size the size of the chunk of memory in bytes
+ */
+static int _check_crc(
+ const void *data,
+ size_t data_size)
+{
+ const size_t crc_size = sizeof(struct crc32_checksum);
+ uint32_t seed;
+ uint32_t value;
+
+ assert(data_size >= crc_size);
+
+ value = le32_to_cpu(((const struct crc32_checksum *)data)->value);
+ seed = le32_to_cpu(((const struct crc32_checksum *)data)->seed);
+ if (seed != 0xffffffff)
+ return -EINVAL;
+
+ if (crypt_crc32c(seed, (const uint8_t *)data + crc_size,
+ data_size - crc_size) != value)
+ return -EINVAL;
+
+ return 0;
+}
+
+/**
+ * Unwrap an AES-wrapped key.
+ * @param[in] kek the KEK with which the key has been wrapped
+ * @param[in] kek_size the size of the KEK in bytes
+ * @param[in] key_wrapped the wrapped key
+ * @param[in] key_wrapped_size the size of the wrapped key in bytes
+ * @param[out] key_buf key an output buffer for the unwrapped key
+ * @param[in] key_buf_size the size of the output buffer in bytes
+ */
+static int _unwrap_key(
+ const void *kek,
+ size_t kek_size,
+ const void *key_wrapped,
+ size_t key_wrapped_size,
+ void *key_buf,
+ size_t key_buf_size)
+{
+ /* Algorithm and notation taken from NIST Special Publication 800-38F:
+ https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
+
+ This implementation supports only 128-bit KEKs and wrapped keys. */
+
+ int r = 0;
+ struct crypt_cipher *cipher = NULL;
+ void *cipher_in = NULL;
+ void *cipher_out = NULL;
+ uint64_t a;
+ uint64_t r2;
+ uint64_t r3;
+ uint64_t t;
+ uint64_t r2_prev;
+
+ assert(kek_size == 16 && key_wrapped_size == 24 && key_buf_size == 16);
+
+ r = crypt_cipher_init(&cipher, "aes", "ecb", kek, kek_size);
+ if (r < 0)
+ goto out;
+
+ cipher_in = malloc(16);
+ if (cipher_in == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ cipher_out = malloc(16);
+ if (cipher_out == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /* CHAPTER 6.1, ALGORITHM 2: W^-1(C) */
+
+ /* initialize variables */
+ a = ((const uint64_t *)key_wrapped)[0]; /* A = C_1 (see step 1c) */
+ r2 = ((const uint64_t *)key_wrapped)[1]; /* R_1 = C_2 (see step 1d) */
+ r3 = ((const uint64_t *)key_wrapped)[2]; /* R_2 = C_3 (see step 1d) */
+
+ /* calculate intermediate values for each t = s, ..., 1 (see step 2),
+ where s = 6 * (n - 1) (see step 1a) */
+ for (t = 6 * (3 - 1); t > 0; t--) {
+ /* store current R2 for later assignment (see step 2c) */
+ r2_prev = r2;
+
+ /* prepare input for CIPH^{-1}_K (see steps 2a, 2b) */
+ ((uint64_t *)cipher_in)[0] = a ^ cpu_to_be64(t);
+ ((uint64_t *)cipher_in)[1] = r3;
+
+ /* A||R2 = CIPH^{-1}_K(...) (see steps 2a, 2b) */
+ r = crypt_cipher_decrypt(cipher, cipher_in, cipher_out, 16, NULL, 0);
+ if (r < 0)
+ goto out;
+ a = ((uint64_t *)cipher_out)[0];
+ r2 = ((uint64_t *)cipher_out)[1];
+
+ /* assign previous R2 (see step 2c) */
+ r3 = r2_prev;
+ }
+
+ /* note that A||R_1||R_2 holds the result S (see step 3) */
+
+ /* CHAPTER 6.2, ALGORITHM 4: KW-AD(C) */
+
+ /* check whether MSB_{64}(S) (= A) matches ICV1 (see step 3) */
+ if (a != 0xA6A6A6A6A6A6A6A6) {
+ r = -EPERM;
+ goto out;
+ }
+
+ /* return LSB_{128}(S) (= R_1||R_2) (see step 4) */
+ ((uint64_t *)key_buf)[0] = r2;
+ ((uint64_t *)key_buf)[1] = r3;
+out:
+ free(cipher_in);
+ free(cipher_out);
+ if (cipher != NULL)
+ crypt_cipher_destroy(cipher);
+ return r;
+}
+
+/**
+ * Search XML plist data for a property and return its value.
+ * @param[in] xml a 0-terminated string containing the XML plist data
+ * @param[in] prop_key a 0-terminated string with the seeked property's key
+ * @param[in] prop_type a 0-terminated string with the seeked property's type
+ * @param[out] value a 0-terminated string with the found property's value
+ */
+static int _search_xml(
+ const char *xml,
+ const char *prop_key,
+ const char *prop_type,
+ char **value)
+{
+ int r = 0;
+ char *pattern = NULL;
+ bool regex_ready = false;
+ regex_t regex;
+ regmatch_t match[2];
+ const char *value_start;
+ size_t value_len;
+
+ if (asprintf(&pattern, "<key>%s</key><%s[^>]*>([^<]+)</%s>",
+ prop_key, prop_type, prop_type) < 0) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (regcomp(&regex, pattern, REG_EXTENDED) != 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ regex_ready = true;
+
+ if (regexec(&regex, xml, 2, match, 0) != 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ value_start = xml + match[1].rm_so;
+ value_len = match[1].rm_eo - match[1].rm_so;
+
+ *value = calloc(value_len + 1, 1);
+ if (*value == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(*value, value_start, value_len);
+out:
+ free(pattern);
+ if (regex_ready)
+ regfree(&regex);
+ return r;
+}
+
+/**
+ * Extract relevant info from a metadata block of type 0x0019.
+ * @param[in] md_block the pre-read and decrypted metadata block
+ * @param[out] pbkdf2_iters number of PBKDF2 iterations
+ * @param[out] pbkdf2_salt PBKDF2 salt (intermt. key derivation from passphrase)
+ * @param[out] wrapped_kek KEK AES-wrapped with passphrase-derived key
+ * @param[out] wrapped_vk volume key AES-wrapped with KEK
+ */
+static int _parse_metadata_block_0x0019(
+ const struct metadata_block_0x0019 *md_block,
+ uint32_t *pbkdf2_iters,
+ uint8_t *pbkdf2_salt,
+ uint8_t *wrapped_kek,
+ uint8_t *wrapped_vk)
+{
+ int r = 0;
+ char *xml = NULL;
+ char *pwk_base64 = NULL;
+ char *kwvk_base64 = NULL;
+ struct passphrase_wrapped_kek *pwk = NULL;
+ struct kek_wrapped_volume_key *kwvk = NULL;
+ size_t decoded_size;
+ uint32_t xml_off = le32_to_cpu(md_block->xml_off);
+ uint32_t xml_size = le32_to_cpu(md_block->xml_size);
+
+ if (xml_off + xml_size > FVAULT2_MD_BLOCK_SIZE)
+ return -EINVAL;
+
+ xml = strndup((const char *)md_block + xml_off, xml_size);
+ if (xml == NULL)
+ return -ENOMEM;
+
+ r = _search_xml(xml, "PassphraseWrappedKEKStruct", "data", &pwk_base64);
+ if (r < 0)
+ goto out;
+ r = crypt_base64_decode((char **)&pwk, &decoded_size, pwk_base64, strlen(pwk_base64));
+ if (r < 0)
+ goto out;
+ if (decoded_size != FVAULT2_PWK_SIZE) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = _search_xml(xml, "KEKWrappedVolumeKeyStruct", "data", &kwvk_base64);
+ if (r < 0)
+ goto out;
+ r = crypt_base64_decode((char **)&kwvk, &decoded_size, kwvk_base64, strlen(kwvk_base64));
+ if (r < 0)
+ goto out;
+ if (decoded_size != FVAULT2_KWVK_SIZE) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ *pbkdf2_iters = le32_to_cpu(pwk->pbkdf2_iters);
+ memcpy(pbkdf2_salt, pwk->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE);
+ memcpy(wrapped_kek, pwk->wrapped_kek, FVAULT2_WRAPPED_KEY_SIZE);
+ memcpy(wrapped_vk, kwvk->wrapped_vk, FVAULT2_WRAPPED_KEY_SIZE);
+out:
+ free(xml);
+ free(pwk_base64);
+ free(kwvk_base64);
+ free(pwk);
+ free(kwvk);
+ return r;
+}
+
+/**
+ * Validate a UUID string and reformat it to match system defaults.
+ * @param[in] uuid_in the original UUID string
+ * @param[out] uuid_out the reformatted UUID string
+ */
+static int _reformat_uuid(
+ const char *uuid_in,
+ char *uuid_out)
+{
+ uint8_t uuid_bin[FVAULT2_UUID_LEN];
+ int r;
+
+ r = uuid_parse(uuid_in, uuid_bin);
+ if (r < 0)
+ return -EINVAL;
+
+ uuid_unparse(uuid_bin, uuid_out);
+ return 0;
+}
+
+/**
+ * Extract relevant info from a metadata block of type 0x001A.
+ * @param[in] md_block the pre-read and decrypted metadata block
+ * @param[out] log_vol_size encrypted logical volume size in bytes
+ * @param[out] family_uuid logical volume family UUID
+ */
+static int _parse_metadata_block_0x001a(
+ const struct metadata_block_0x001a *md_block,
+ uint64_t *log_vol_size,
+ char *family_uuid)
+{
+ int r = 0;
+ char *xml = NULL;
+ char *log_vol_size_str = NULL;
+ char *family_uuid_str = NULL;
+ uint32_t xml_off = le32_to_cpu(md_block->xml_off);
+ uint32_t xml_size = le32_to_cpu(md_block->xml_size);
+
+ if (xml_off + xml_size > FVAULT2_MD_BLOCK_SIZE)
+ return -EINVAL;
+
+ xml = strndup((const char *)md_block + xml_off, xml_size);
+ if (xml == NULL)
+ return -ENOMEM;
+
+ r = _search_xml(xml, "com.apple.corestorage.lv.size", "integer", &log_vol_size_str);
+ if (r < 0)
+ goto out;
+ *log_vol_size = strtoull(log_vol_size_str, NULL, 16);
+ if (*log_vol_size == 0 || *log_vol_size == ULLONG_MAX) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = _search_xml(xml, "com.apple.corestorage.lv.familyUUID", "string", &family_uuid_str);
+ if (r < 0)
+ goto out;
+ r = _reformat_uuid(family_uuid_str, family_uuid);
+ if (r < 0)
+ goto out;
+out:
+ free(xml);
+ free(log_vol_size_str);
+ free(family_uuid_str);
+ return r;
+}
+
+/**
+ * Extract relevant info from a metadata block of type 0x0305.
+ * @param[in] md_block the pre-read and decrypted metadata block
+ * @param[out] log_vol_blkoff block-offset of the encrypted logical volume
+ */
+static int _parse_metadata_block_0x0305(
+ const struct metadata_block_0x0305 *md_block,
+ uint32_t *log_vol_blkoff)
+{
+ *log_vol_blkoff = le32_to_cpu(md_block->log_vol_blkoff);
+ return 0;
+}
+
+/**
+ * Extract relevant info from the physical volume header.
+ * @param[in] devfd opened device file descriptor
+ * @param[in] cd crypt_device passed into FVAULT2_read_metadata
+ * @param[out] block_size used to compute byte-offsets from block-offsets
+ * @param[out] disklbl_blkoff block-offset of the disk label block
+ * @param[out] ph_vol_uuid physical volume UUID
+ * @param[out] enc_md_key AES-XTS key used to decrypt the encrypted metadata
+ */
+static int _read_volume_header(
+ int devfd,
+ struct crypt_device *cd,
+ uint64_t *block_size,
+ uint64_t *disklbl_blkoff,
+ char *ph_vol_uuid,
+ struct volume_key **enc_md_key)
+{
+ int r = 0;
+ struct device *dev = crypt_metadata_device(cd);
+ struct volume_header *vol_header = NULL;
+
+ assert(sizeof(*vol_header) == FVAULT2_VOL_HEADER_SIZE);
+
+ vol_header = malloc(FVAULT2_VOL_HEADER_SIZE);
+ if (vol_header == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ log_dbg(cd, "Reading FVAULT2 volume header of size %u bytes.", FVAULT2_VOL_HEADER_SIZE);
+ if (read_blockwise(devfd, device_block_size(cd, dev),
+ device_alignment(dev), vol_header,
+ FVAULT2_VOL_HEADER_SIZE) != FVAULT2_VOL_HEADER_SIZE) {
+ log_err(cd, _("Could not read %u bytes of volume header."), FVAULT2_VOL_HEADER_SIZE);
+ r = -EIO;
+ goto out;
+ }
+
+ r = _check_crc(vol_header, FVAULT2_VOL_HEADER_SIZE);
+ if (r < 0) {
+ log_dbg(cd, "CRC mismatch.");
+ goto out;
+ }
+
+ if (le16_to_cpu(vol_header->version) != 1) {
+ log_err(cd, _("Unsupported FVAULT2 version %" PRIu16 "."),
+ le16_to_cpu(vol_header->version));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (be16_to_cpu(vol_header->magic) != FVAULT2_CORE_STORAGE_MAGIC) {
+ log_dbg(cd, "Invalid Core Storage magic bytes.");
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (le32_to_cpu(vol_header->key_data_size) != FVAULT2_AES_KEY_SIZE) {
+ log_dbg(cd, "Unsupported AES key size: %" PRIu32 " bytes.",
+ le32_to_cpu(vol_header->key_data_size));
+ r = -EINVAL;
+ goto out;
+ }
+
+ *enc_md_key = crypt_alloc_volume_key(FVAULT2_XTS_KEY_SIZE, NULL);
+ if (*enc_md_key == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ *block_size = le32_to_cpu(vol_header->block_size);
+ *disklbl_blkoff = le64_to_cpu(vol_header->disklbl_blkoff);
+ uuid_unparse(vol_header->ph_vol_uuid, ph_vol_uuid);
+ memcpy((*enc_md_key)->key, vol_header->key_data, FVAULT2_AES_KEY_SIZE);
+ memcpy((*enc_md_key)->key + FVAULT2_AES_KEY_SIZE,
+ vol_header->ph_vol_uuid, FVAULT2_AES_KEY_SIZE);
+out:
+ free(vol_header);
+ return r;
+}
+
+/**
+ * Extract info from the disk label block and the volume groups descriptor.
+ * @param[in] devfd opened device file descriptor
+ * @param[in] cd crypt_device passed into FVAULT2_read_metadata
+ * @param[in] block_size used to compute byte-offsets from block-offsets
+ * @param[in] disklbl_blkoff block-offset of the disk label block
+ * @param[out] enc_md_blkoff block-offset of the encrypted metadata
+ * @param[out] enc_md_blocks_n total count of encrypted metadata blocks
+ */
+static int _read_disklabel(
+ int devfd,
+ struct crypt_device *cd,
+ uint64_t block_size,
+ uint64_t disklbl_blkoff,
+ uint64_t *enc_md_blkoff,
+ uint64_t *enc_md_blocks_n)
+{
+ int r = 0;
+ uint64_t off;
+ ssize_t size;
+ void *md_block = NULL;
+ struct metadata_block_0x0011 *md_block_11;
+ struct volume_groups_descriptor *vol_gr_des = NULL;
+ struct device *dev = crypt_metadata_device(cd);
+
+ md_block = malloc(FVAULT2_MD_BLOCK_SIZE);
+ if (md_block == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (uint64_mult_overflow(&off, disklbl_blkoff, block_size) ||
+ off > FVAULT2_MAX_OFF) {
+ log_dbg(cd, "Device offset overflow.");
+ r = -EINVAL;
+ goto out;
+ }
+ size = FVAULT2_MD_BLOCK_SIZE;
+ log_dbg(cd, "Reading FVAULT2 disk label header of size %zu bytes.", size);
+ if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
+ device_alignment(dev), md_block, size, off) != size) {
+ r = -EIO;
+ goto out;
+ }
+
+ r = _check_crc(md_block, FVAULT2_MD_BLOCK_SIZE);
+ if (r < 0) {
+ log_dbg(cd, "CRC mismatch.");
+ goto out;
+ }
+
+ vol_gr_des = malloc(sizeof(*vol_gr_des));
+ if (vol_gr_des == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ md_block_11 = md_block;
+ off += le32_to_cpu(md_block_11->vol_gr_des_off);
+ if (off > FVAULT2_MAX_OFF) {
+ log_dbg(cd, "Device offset overflow.");
+ r = -EINVAL;
+ goto out;
+ }
+ size = sizeof(struct volume_groups_descriptor);
+ log_dbg(cd, "Reading FVAULT2 volume groups descriptor of size %zu bytes.", size);
+ if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
+ device_alignment(dev), vol_gr_des, size, off) != size) {
+ r = -EIO;
+ goto out;
+ }
+
+ *enc_md_blkoff = le64_to_cpu(vol_gr_des->enc_md_blkoff);
+ *enc_md_blocks_n = le64_to_cpu(vol_gr_des->enc_md_blocks_n);
+out:
+ free(md_block);
+ free(vol_gr_des);
+ return r;
+}
+
+/**
+ * Extract info from relevant encrypted metadata blocks.
+ * @param[in] devfd opened device file descriptor
+ * @param[in] cd crypt_device passed into FVAULT2_read_metadata
+ * @param[in] block_size used to compute byte-offsets from block-offsets
+ * @param[in] start_blkoff block-offset of the start of the encrypted metadata
+ * @param[in] blocks_n total count of encrypted metadata blocks
+ * @param[in] key AES-XTS key for decryption
+ * @param[out] params decryption parameters struct to fill
+ */
+static int _read_encrypted_metadata(
+ int devfd,
+ struct crypt_device *cd,
+ uint64_t block_size,
+ uint64_t start_blkoff,
+ uint64_t blocks_n,
+ const struct volume_key *key,
+ struct fvault2_params *params)
+{
+ int r = 0;
+ int status = FVAULT2_ENC_MD_PARSED_NONE;
+ struct device *dev = crypt_metadata_device(cd);
+ struct crypt_cipher *cipher = NULL;
+ void *tweak;
+ void *md_block_enc = NULL;
+ void *md_block = NULL;
+ struct metadata_block_header *md_block_header;
+ uint32_t log_vol_blkoff;
+ uint64_t i, start_off;
+ off_t off;
+ unsigned int block_type;
+
+ tweak = calloc(FVAULT2_XTS_TWEAK_SIZE, 1);
+ if (tweak == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ md_block_enc = malloc(FVAULT2_MD_BLOCK_SIZE);
+ if (md_block_enc == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ md_block = malloc(FVAULT2_MD_BLOCK_SIZE);
+ if (md_block == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = crypt_cipher_init(&cipher, "aes", "xts", key->key, FVAULT2_XTS_KEY_SIZE);
+ if (r < 0)
+ goto out;
+
+ if (uint64_mult_overflow(&start_off, start_blkoff, block_size) ||
+ start_off > FVAULT2_MAX_OFF) {
+ log_dbg(cd, "Device offset overflow.");
+ r = -EINVAL;
+ goto out;
+ }
+
+ log_dbg(cd, "Reading FVAULT2 encrypted metadata blocks.");
+ for (i = 0; i < blocks_n; i++) {
+ off = start_off + i * FVAULT2_MD_BLOCK_SIZE;
+ if (off > FVAULT2_MAX_OFF) {
+ log_dbg(cd, "Device offset overflow.");
+ r = -EINVAL;
+ goto out;
+ }
+ if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
+ device_alignment(dev), md_block_enc,
+ FVAULT2_MD_BLOCK_SIZE, off)
+ != FVAULT2_MD_BLOCK_SIZE) {
+ r = -EIO;
+ goto out;
+ }
+
+ if (_filled_with(0, md_block_enc, FVAULT2_MD_BLOCK_SIZE))
+ break;
+
+ *(uint64_t *)tweak = cpu_to_le64(i);
+ r = crypt_cipher_decrypt(cipher, md_block_enc, md_block,
+ FVAULT2_MD_BLOCK_SIZE, tweak, FVAULT2_XTS_TWEAK_SIZE);
+ if (r < 0)
+ goto out;
+
+ r = _check_crc(md_block, FVAULT2_MD_BLOCK_SIZE);
+ if (r < 0) {
+ log_dbg(cd, "CRC mismatch.");
+ goto out;
+ }
+
+ md_block_header = md_block;
+ block_type = le16_to_cpu(md_block_header->block_type);
+ switch (block_type) {
+ case 0x0019:
+ log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x0019.", i);
+ r = _parse_metadata_block_0x0019(md_block,
+ &params->pbkdf2_iters,
+ (uint8_t *)params->pbkdf2_salt,
+ (uint8_t *)params->wrapped_kek,
+ (uint8_t *)params->wrapped_vk);
+ if (r < 0)
+ goto out;
+ status |= FVAULT2_ENC_MD_PARSED_0x0019;
+ break;
+
+ case 0x001A:
+ log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x001A.", i);
+ r = _parse_metadata_block_0x001a(md_block,
+ &params->log_vol_size,
+ params->family_uuid);
+ if (r < 0)
+ goto out;
+ status |= FVAULT2_ENC_MD_PARSED_0x001A;
+ break;
+
+ case 0x0305:
+ log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x0305.", i);
+ r = _parse_metadata_block_0x0305(md_block,
+ &log_vol_blkoff);
+ if (r < 0)
+ goto out;
+ if (uint64_mult_overflow(&params->log_vol_off,
+ log_vol_blkoff, block_size)) {
+ log_dbg(cd, "Device offset overflow.");
+ r = -EINVAL;
+ goto out;
+ }
+ status |= FVAULT2_ENC_MD_PARSED_0x0305;
+ break;
+ }
+ }
+
+ if (status != FVAULT2_ENC_MD_PARSED_ALL) {
+ log_dbg(cd, "Necessary FVAULT2 metadata blocks not found.");
+ r = -EINVAL;
+ goto out;
+ }
+out:
+ free(tweak);
+ free(md_block_enc);
+ free(md_block);
+ if (cipher != NULL)
+ crypt_cipher_destroy(cipher);
+ return r;
+}
+
+/**
+ * Activate device.
+ * @param[in] cd crypt_device struct passed into FVAULT2_activate_by_*
+ * @param[in] name name of the mapped device
+ * @param[in] vol_key the pre-derived AES-XTS volume key
+ * @param[in] params logical volume decryption parameters
+ * @param[in] flags flags assigned to the crypt_dm_active_device struct
+ */
+static int _activate(
+ struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vol_key,
+ const struct fvault2_params *params,
+ uint32_t flags)
+{
+ int r = 0;
+ char *cipher = NULL;
+ struct crypt_dm_active_device dm_dev = {
+ .flags = flags,
+ .size = params->log_vol_size / SECTOR_SIZE
+ };
+
+ r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL,
+ crypt_get_data_offset(cd), &dm_dev.size, &dm_dev.flags);
+ if (r)
+ return r;
+
+ if (asprintf(&cipher, "%s-%s", params->cipher, params->cipher_mode) < 0)
+ return -ENOMEM;
+
+ r = dm_crypt_target_set(&dm_dev.segment, 0, dm_dev.size,
+ crypt_data_device(cd), vol_key, cipher,
+ crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
+ crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd),
+ crypt_get_sector_size(cd));
+
+ if (!r)
+ r = dm_create_device(cd, name, CRYPT_FVAULT2, &dm_dev);
+
+ dm_targets_free(cd, &dm_dev);
+ free(cipher);
+ return r;
+}
+
+int FVAULT2_read_metadata(
+ struct crypt_device *cd,
+ struct fvault2_params *params)
+{
+ int r = 0;
+ int devfd;
+ uint64_t block_size;
+ uint64_t disklbl_blkoff;
+ uint64_t enc_md_blkoff;
+ uint64_t enc_md_blocks_n;
+ struct volume_key *enc_md_key = NULL;
+ struct device *device = crypt_metadata_device(cd);
+
+ devfd = device_open(cd, device, O_RDONLY);
+ if (devfd < 0) {
+ log_err(cd, _("Cannot open device %s."), device_path(device));
+ return -EIO;
+ }
+
+ r = _read_volume_header(devfd, cd, &block_size, &disklbl_blkoff,
+ params->ph_vol_uuid, &enc_md_key);
+ if (r < 0)
+ goto out;
+
+ r = _read_disklabel(devfd, cd, block_size, disklbl_blkoff,
+ &enc_md_blkoff, &enc_md_blocks_n);
+ if (r < 0)
+ goto out;
+
+ r = _read_encrypted_metadata(devfd, cd, block_size, enc_md_blkoff,
+ enc_md_blocks_n, enc_md_key, params);
+ if (r < 0)
+ goto out;
+
+ params->cipher = "aes";
+ params->cipher_mode = "xts-plain64";
+ params->key_size = FVAULT2_XTS_KEY_SIZE;
+out:
+ crypt_free_volume_key(enc_md_key);
+ return r;
+}
+
+int FVAULT2_get_volume_key(
+ struct crypt_device *cd,
+ const char *passphrase,
+ size_t passphrase_len,
+ const struct fvault2_params *params,
+ struct volume_key **vol_key)
+{
+ int r = 0;
+ uint8_t family_uuid_bin[FVAULT2_UUID_BIN_SIZE];
+ struct volume_key *passphrase_key = NULL;
+ struct volume_key *kek = NULL;
+ struct crypt_hash *hash = NULL;
+
+ *vol_key = NULL;
+
+ if (uuid_parse(params->family_uuid, family_uuid_bin) < 0) {
+ log_dbg(cd, "Could not parse logical volume family UUID: %s.",
+ params->family_uuid);
+ r = -EINVAL;
+ goto out;
+ }
+
+ passphrase_key = crypt_alloc_volume_key(FVAULT2_AES_KEY_SIZE, NULL);
+ if (passphrase_key == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = crypt_pbkdf("pbkdf2", "sha256", passphrase, passphrase_len,
+ params->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE, passphrase_key->key,
+ FVAULT2_AES_KEY_SIZE, params->pbkdf2_iters, 0, 0);
+ if (r < 0)
+ goto out;
+
+ kek = crypt_alloc_volume_key(FVAULT2_AES_KEY_SIZE, NULL);
+ if (kek == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = _unwrap_key(passphrase_key->key, FVAULT2_AES_KEY_SIZE, params->wrapped_kek,
+ FVAULT2_WRAPPED_KEY_SIZE, kek->key, FVAULT2_AES_KEY_SIZE);
+ if (r < 0)
+ goto out;
+
+ *vol_key = crypt_alloc_volume_key(FVAULT2_XTS_KEY_SIZE, NULL);
+ if (*vol_key == NULL) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = _unwrap_key(kek->key, FVAULT2_AES_KEY_SIZE, params->wrapped_vk,
+ FVAULT2_WRAPPED_KEY_SIZE, (*vol_key)->key, FVAULT2_AES_KEY_SIZE);
+ if (r < 0)
+ goto out;
+
+ r = crypt_hash_init(&hash, "sha256");
+ if (r < 0)
+ goto out;
+ r = crypt_hash_write(hash, (*vol_key)->key, FVAULT2_AES_KEY_SIZE);
+ if (r < 0)
+ goto out;
+ r = crypt_hash_write(hash, (char *)family_uuid_bin,
+ FVAULT2_UUID_BIN_SIZE);
+ if (r < 0)
+ goto out;
+ r = crypt_hash_final(hash, (*vol_key)->key + FVAULT2_AES_KEY_SIZE,
+ FVAULT2_AES_KEY_SIZE);
+ if (r < 0)
+ goto out;
+out:
+ crypt_free_volume_key(passphrase_key);
+ crypt_free_volume_key(kek);
+ if (r < 0) {
+ crypt_free_volume_key(*vol_key);
+ *vol_key = NULL;
+ }
+ if (hash != NULL)
+ crypt_hash_destroy(hash);
+ return r;
+}
+
+int FVAULT2_dump(
+ struct crypt_device *cd,
+ struct device *device,
+ const struct fvault2_params *params)
+{
+ log_std(cd, "Header information for FVAULT2 device %s.\n", device_path(device));
+
+ log_std(cd, "Physical volume UUID: \t%s\n", params->ph_vol_uuid);
+ log_std(cd, "Family UUID: \t%s\n", params->family_uuid);
+
+ log_std(cd, "Logical volume offset:\t%" PRIu64 " [bytes]\n", params->log_vol_off);
+
+ log_std(cd, "Logical volume size: \t%" PRIu64 " [bytes]\n",
+ params->log_vol_size);
+
+ log_std(cd, "Cipher: \t%s\n", params->cipher);
+ log_std(cd, "Cipher mode: \t%s\n", params->cipher_mode);
+
+ log_std(cd, "PBKDF2 iterations: \t%" PRIu32 "\n", params->pbkdf2_iters);
+
+ log_std(cd, "PBKDF2 salt: \t");
+ crypt_log_hex(cd, params->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE, " ", 0, NULL);
+ log_std(cd, "\n");
+
+ return 0;
+}
+
+int FVAULT2_activate_by_passphrase(
+ struct crypt_device *cd,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_len,
+ const struct fvault2_params *params,
+ uint32_t flags)
+{
+ int r;
+ struct volume_key *vol_key = NULL;
+
+ r = FVAULT2_get_volume_key(cd, passphrase, passphrase_len, params, &vol_key);
+ if (r < 0)
+ return r;
+
+ if (name)
+ r = _activate(cd, name, vol_key, params, flags);
+
+ crypt_free_volume_key(vol_key);
+ return r;
+}
+
+int FVAULT2_activate_by_volume_key(
+ struct crypt_device *cd,
+ const char *name,
+ const char *key,
+ size_t key_size,
+ const struct fvault2_params *params,
+ uint32_t flags)
+{
+ int r = 0;
+ struct volume_key *vol_key = NULL;
+
+ if (key_size != FVAULT2_XTS_KEY_SIZE)
+ return -EINVAL;
+
+ vol_key = crypt_alloc_volume_key(FVAULT2_XTS_KEY_SIZE, key);
+ if (vol_key == NULL)
+ return -ENOMEM;
+
+ r = _activate(cd, name, vol_key, params, flags);
+
+ crypt_free_volume_key(vol_key);
+ return r;
+}
diff --git a/lib/fvault2/fvault2.h b/lib/fvault2/fvault2.h
new file mode 100644
index 0000000..ce50ee3
--- /dev/null
+++ b/lib/fvault2/fvault2.h
@@ -0,0 +1,80 @@
+/*
+ * FVAULT2 (FileVault2-compatible) volume handling
+ *
+ * Copyright (C) 2021-2022 Pavel Tobias
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_FVAULT2_H
+#define _CRYPTSETUP_FVAULT2_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define FVAULT2_WRAPPED_KEY_SIZE 24
+#define FVAULT2_PBKDF2_SALT_SIZE 16
+#define FVAULT2_UUID_LEN 37
+
+struct crypt_device;
+struct volume_key;
+
+struct fvault2_params {
+ const char *cipher;
+ const char *cipher_mode;
+ uint16_t key_size;
+ uint32_t pbkdf2_iters;
+ char pbkdf2_salt[FVAULT2_PBKDF2_SALT_SIZE];
+ char wrapped_kek[FVAULT2_WRAPPED_KEY_SIZE];
+ char wrapped_vk[FVAULT2_WRAPPED_KEY_SIZE];
+ char family_uuid[FVAULT2_UUID_LEN];
+ char ph_vol_uuid[FVAULT2_UUID_LEN];
+ uint64_t log_vol_off;
+ uint64_t log_vol_size;
+};
+
+int FVAULT2_read_metadata(
+ struct crypt_device *cd,
+ struct fvault2_params *params);
+
+int FVAULT2_get_volume_key(
+ struct crypt_device *cd,
+ const char *passphrase,
+ size_t passphrase_len,
+ const struct fvault2_params *params,
+ struct volume_key **vol_key);
+
+int FVAULT2_dump(
+ struct crypt_device *cd,
+ struct device *device,
+ const struct fvault2_params *params);
+
+int FVAULT2_activate_by_passphrase(
+ struct crypt_device *cd,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_len,
+ const struct fvault2_params *params,
+ uint32_t flags);
+
+int FVAULT2_activate_by_volume_key(
+ struct crypt_device *cd,
+ const char *name,
+ const char *key,
+ size_t key_size,
+ const struct fvault2_params *params,
+ uint32_t flags);
+
+#endif
diff --git a/lib/integrity/integrity.c b/lib/integrity/integrity.c
new file mode 100644
index 0000000..aeadc82
--- /dev/null
+++ b/lib/integrity/integrity.c
@@ -0,0 +1,402 @@
+/*
+ * Integrity volume handling
+ *
+ * Copyright (C) 2016-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uuid/uuid.h>
+
+#include "integrity.h"
+#include "internal.h"
+
+/* For LUKS2, integrity metadata are on DATA device even for detached header! */
+static struct device *INTEGRITY_metadata_device(struct crypt_device *cd)
+{
+ const char *type = crypt_get_type(cd);
+
+ if (type && !strcmp(type, CRYPT_LUKS2))
+ return crypt_data_device(cd);
+
+ return crypt_metadata_device(cd);
+}
+
+static int INTEGRITY_read_superblock(struct crypt_device *cd,
+ struct device *device,
+ uint64_t offset, struct superblock *sb)
+{
+ int devfd, r;
+
+ devfd = device_open(cd, device, O_RDONLY);
+ if(devfd < 0)
+ return -EINVAL;
+
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
+ memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic))) {
+ log_dbg(cd, "No kernel dm-integrity metadata detected on %s.", device_path(device));
+ r = -EINVAL;
+ } else if (sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
+ log_err(cd, _("Incompatible kernel dm-integrity metadata (version %u) detected on %s."),
+ sb->version, device_path(device));
+ r = -EINVAL;
+ } else {
+ sb->integrity_tag_size = le16toh(sb->integrity_tag_size);
+ sb->journal_sections = le32toh(sb->journal_sections);
+ sb->provided_data_sectors = le64toh(sb->provided_data_sectors);
+ sb->recalc_sector = le64toh(sb->recalc_sector);
+ sb->flags = le32toh(sb->flags);
+ r = 0;
+ }
+
+ return r;
+}
+
+int INTEGRITY_read_sb(struct crypt_device *cd,
+ struct crypt_params_integrity *params,
+ uint32_t *flags)
+{
+ struct superblock sb;
+ int r;
+
+ r = INTEGRITY_read_superblock(cd, INTEGRITY_metadata_device(cd), 0, &sb);
+ if (r)
+ return r;
+
+ params->sector_size = SECTOR_SIZE << sb.log2_sectors_per_block;
+ params->tag_size = sb.integrity_tag_size;
+
+ if (flags)
+ *flags = sb.flags;
+
+ return 0;
+}
+
+int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset)
+{
+ struct superblock sb;
+ int r;
+
+ r = INTEGRITY_read_superblock(cd, device, offset, &sb);
+ if (r)
+ return r;
+
+ log_std(cd, "Info for integrity device %s.\n", device_path(device));
+ log_std(cd, "superblock_version %d\n", (unsigned)sb.version);
+ log_std(cd, "log2_interleave_sectors %d\n", sb.log2_interleave_sectors);
+ log_std(cd, "integrity_tag_size %u\n", sb.integrity_tag_size);
+ log_std(cd, "journal_sections %u\n", sb.journal_sections);
+ log_std(cd, "provided_data_sectors %" PRIu64 "\n", sb.provided_data_sectors);
+ log_std(cd, "sector_size %u\n", SECTOR_SIZE << sb.log2_sectors_per_block);
+ if (sb.version >= SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING))
+ log_std(cd, "recalc_sector %" PRIu64 "\n", sb.recalc_sector);
+ log_std(cd, "log2_blocks_per_bitmap %u\n", sb.log2_blocks_per_bitmap_bit);
+ log_std(cd, "flags %s%s%s%s%s\n",
+ sb.flags & SB_FLAG_HAVE_JOURNAL_MAC ? "have_journal_mac " : "",
+ sb.flags & SB_FLAG_RECALCULATING ? "recalculating " : "",
+ sb.flags & SB_FLAG_DIRTY_BITMAP ? "dirty_bitmap " : "",
+ sb.flags & SB_FLAG_FIXED_PADDING ? "fix_padding " : "",
+ sb.flags & SB_FLAG_FIXED_HMAC ? "fix_hmac " : "");
+
+ return 0;
+}
+
+int INTEGRITY_data_sectors(struct crypt_device *cd,
+ struct device *device, uint64_t offset,
+ uint64_t *data_sectors)
+{
+ struct superblock sb;
+ int r;
+
+ r = INTEGRITY_read_superblock(cd, device, offset, &sb);
+ if (r)
+ return r;
+
+ *data_sectors = sb.provided_data_sectors;
+ return 0;
+}
+
+int INTEGRITY_key_size(const char *integrity)
+{
+ if (!integrity)
+ return 0;
+
+ //FIXME: use crypto backend hash size
+ if (!strcmp(integrity, "aead"))
+ return 0;
+ else if (!strcmp(integrity, "hmac(sha1)"))
+ return 20;
+ else if (!strcmp(integrity, "hmac(sha256)"))
+ return 32;
+ else if (!strcmp(integrity, "hmac(sha512)"))
+ return 64;
+ else if (!strcmp(integrity, "poly1305"))
+ return 0;
+ else if (!strcmp(integrity, "none"))
+ return 0;
+
+ return -EINVAL;
+}
+
+/* Return hash or hmac(hash) size, if known */
+int INTEGRITY_hash_tag_size(const char *integrity)
+{
+ char hash[MAX_CIPHER_LEN];
+ int r;
+
+ if (!integrity)
+ return 0;
+
+ if (!strcmp(integrity, "crc32") || !strcmp(integrity, "crc32c"))
+ return 4;
+
+ if (!strcmp(integrity, "xxhash64"))
+ return 8;
+
+ r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
+ if (r == 1)
+ r = crypt_hash_size(hash);
+ else
+ r = crypt_hash_size(integrity);
+
+ return r < 0 ? 0 : r;
+}
+
+int INTEGRITY_tag_size(const char *integrity,
+ const char *cipher,
+ const char *cipher_mode)
+{
+ int iv_tag_size = 0, auth_tag_size = 0;
+
+ if (!cipher_mode)
+ iv_tag_size = 0;
+ else if (!strcmp(cipher_mode, "xts-random"))
+ iv_tag_size = 16;
+ else if (!strcmp(cipher_mode, "gcm-random"))
+ iv_tag_size = 12;
+ else if (!strcmp(cipher_mode, "ccm-random"))
+ iv_tag_size = 8;
+ else if (!strcmp(cipher_mode, "ctr-random"))
+ iv_tag_size = 16;
+ else if (!strcmp(cipher, "aegis256") && !strcmp(cipher_mode, "random"))
+ iv_tag_size = 32;
+ else if (!strcmp(cipher_mode, "random"))
+ iv_tag_size = 16;
+
+ //FIXME: use crypto backend hash size
+ if (!integrity || !strcmp(integrity, "none"))
+ auth_tag_size = 0;
+ else if (!strcmp(integrity, "aead"))
+ auth_tag_size = 16; /* gcm- mode only */
+ else if (!strcmp(integrity, "cmac(aes)"))
+ auth_tag_size = 16;
+ else if (!strcmp(integrity, "hmac(sha1)"))
+ auth_tag_size = 20;
+ else if (!strcmp(integrity, "hmac(sha256)"))
+ auth_tag_size = 32;
+ else if (!strcmp(integrity, "hmac(sha512)"))
+ auth_tag_size = 64;
+ else if (!strcmp(integrity, "poly1305")) {
+ if (iv_tag_size)
+ iv_tag_size = 12;
+ auth_tag_size = 16;
+ }
+
+ return iv_tag_size + auth_tag_size;
+}
+
+int INTEGRITY_create_dmd_device(struct crypt_device *cd,
+ const struct crypt_params_integrity *params,
+ struct volume_key *vk,
+ struct volume_key *journal_crypt_key,
+ struct volume_key *journal_mac_key,
+ struct crypt_dm_active_device *dmd,
+ uint32_t flags, uint32_t sb_flags)
+{
+ int r;
+
+ if (!dmd)
+ return -EINVAL;
+
+ *dmd = (struct crypt_dm_active_device) {
+ .flags = flags,
+ };
+
+ /* Workaround for kernel dm-integrity table bug */
+ if (sb_flags & SB_FLAG_RECALCULATING)
+ dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
+
+ r = INTEGRITY_data_sectors(cd, INTEGRITY_metadata_device(cd),
+ crypt_get_data_offset(cd) * SECTOR_SIZE, &dmd->size);
+ if (r < 0)
+ return r;
+
+ return dm_integrity_target_set(cd, &dmd->segment, 0, dmd->size,
+ INTEGRITY_metadata_device(cd), crypt_data_device(cd),
+ crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
+ crypt_get_sector_size(cd), vk, journal_crypt_key,
+ journal_mac_key, params);
+}
+
+int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
+ const char *name,
+ const char *type,
+ struct crypt_dm_active_device *dmd,
+ uint32_t sb_flags)
+{
+ int r;
+ uint32_t dmi_flags;
+ struct dm_target *tgt = &dmd->segment;
+
+ if (!single_segment(dmd) || tgt->type != DM_INTEGRITY)
+ return -EINVAL;
+
+ log_dbg(cd, "Trying to activate INTEGRITY device on top of %s, using name %s, tag size %d, provided sectors %" PRIu64".",
+ device_path(tgt->data_device), name, tgt->u.integrity.tag_size, dmd->size);
+
+ r = create_or_reload_device(cd, name, type, dmd);
+
+ if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
+ log_err(cd, _("Kernel does not support dm-integrity mapping."));
+ return -ENOTSUP;
+ }
+
+ if (r < 0 && (sb_flags & SB_FLAG_FIXED_PADDING) && !dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
+ !(dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED)) {
+ log_err(cd, _("Kernel does not support dm-integrity fixed metadata alignment."));
+ return -ENOTSUP;
+ }
+
+ if (r < 0 && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
+ !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC) &&
+ ((sb_flags & SB_FLAG_FIXED_HMAC) ?
+ (tgt->u.integrity.vk && !tgt->u.integrity.journal_integrity_key) :
+ (tgt->u.integrity.vk || tgt->u.integrity.journal_integrity_key))) {
+ log_err(cd, _("Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."));
+ return -ENOTSUP;
+ }
+
+ return r;
+}
+
+int INTEGRITY_activate(struct crypt_device *cd,
+ const char *name,
+ const struct crypt_params_integrity *params,
+ struct volume_key *vk,
+ struct volume_key *journal_crypt_key,
+ struct volume_key *journal_mac_key,
+ uint32_t flags, uint32_t sb_flags)
+{
+ struct crypt_dm_active_device dmdq = {}, dmd = {};
+ int r;
+
+ if (flags & CRYPT_ACTIVATE_REFRESH) {
+ r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE |
+ DM_ACTIVE_CRYPT_KEY |
+ DM_ACTIVE_INTEGRITY_PARAMS |
+ DM_ACTIVE_JOURNAL_CRYPT_KEY |
+ DM_ACTIVE_JOURNAL_MAC_KEY, &dmdq);
+ if (r < 0)
+ return r;
+
+ r = INTEGRITY_create_dmd_device(cd, params, vk ?: dmdq.segment.u.integrity.vk,
+ journal_crypt_key ?: dmdq.segment.u.integrity.journal_crypt_key,
+ journal_mac_key ?: dmdq.segment.u.integrity.journal_integrity_key,
+ &dmd, flags, sb_flags);
+
+ if (!r)
+ dmd.size = dmdq.size;
+ } else
+ r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
+ journal_mac_key, &dmd, flags, sb_flags);
+
+ if (!r)
+ r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags);
+
+ dm_targets_free(cd, &dmdq);
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int INTEGRITY_format(struct crypt_device *cd,
+ const struct crypt_params_integrity *params,
+ struct volume_key *journal_crypt_key,
+ struct volume_key *journal_mac_key)
+{
+ uint32_t dmi_flags;
+ char tmp_name[64], tmp_uuid[40];
+ struct crypt_dm_active_device dmdi = {
+ .size = 8,
+ .flags = CRYPT_ACTIVATE_PRIVATE, /* We always create journal but it can be unused later */
+ };
+ struct dm_target *tgt = &dmdi.segment;
+ int r;
+ uuid_t tmp_uuid_bin;
+ struct volume_key *vk = NULL;
+
+ uuid_generate(tmp_uuid_bin);
+ uuid_unparse(tmp_uuid_bin, tmp_uuid);
+
+ r = snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
+ if (r < 0 || (size_t)r >= sizeof(tmp_name))
+ return -EINVAL;
+
+ /* There is no data area, we can actually use fake zeroed key */
+ if (params && params->integrity_key_size)
+ vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
+
+ r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, INTEGRITY_metadata_device(cd),
+ crypt_data_device(cd), crypt_get_integrity_tag_size(cd),
+ crypt_get_data_offset(cd), crypt_get_sector_size(cd), vk,
+ journal_crypt_key, journal_mac_key, params);
+ if (r < 0) {
+ crypt_free_volume_key(vk);
+ return r;
+ }
+
+ log_dbg(cd, "Trying to format INTEGRITY device on top of %s, tmp name %s, tag size %d.",
+ device_path(tgt->data_device), tmp_name, tgt->u.integrity.tag_size);
+
+ r = device_block_adjust(cd, tgt->data_device, DEV_EXCL, tgt->u.integrity.offset, NULL, NULL);
+ if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
+ log_err(cd, _("Kernel does not support dm-integrity mapping."));
+ r = -ENOTSUP;
+ }
+ if (r) {
+ dm_targets_free(cd, &dmdi);
+ return r;
+ }
+
+ if (tgt->u.integrity.meta_device) {
+ r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL);
+ if (r) {
+ dm_targets_free(cd, &dmdi);
+ return r;
+ }
+ }
+
+ r = dm_create_device(cd, tmp_name, CRYPT_INTEGRITY, &dmdi);
+ crypt_free_volume_key(vk);
+ dm_targets_free(cd, &dmdi);
+ if (r)
+ return r;
+
+ return dm_remove_device(cd, tmp_name, CRYPT_DEACTIVATE_FORCE);
+}
diff --git a/lib/integrity/integrity.h b/lib/integrity/integrity.h
new file mode 100644
index 0000000..2883ef8
--- /dev/null
+++ b/lib/integrity/integrity.h
@@ -0,0 +1,101 @@
+/*
+ * Integrity header definition
+ *
+ * Copyright (C) 2016-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_INTEGRITY_H
+#define _CRYPTSETUP_INTEGRITY_H
+
+#include <stdint.h>
+
+struct crypt_device;
+struct device;
+struct crypt_params_integrity;
+struct volume_key;
+struct crypt_dm_active_device;
+
+/* dm-integrity helper */
+#define SB_MAGIC "integrt"
+#define SB_VERSION_1 1
+#define SB_VERSION_2 2
+#define SB_VERSION_3 3
+#define SB_VERSION_4 4
+#define SB_VERSION_5 5
+
+#define SB_FLAG_HAVE_JOURNAL_MAC (1 << 0)
+#define SB_FLAG_RECALCULATING (1 << 1) /* V2 only */
+#define SB_FLAG_DIRTY_BITMAP (1 << 2) /* V3 only */
+#define SB_FLAG_FIXED_PADDING (1 << 3) /* V4 only */
+#define SB_FLAG_FIXED_HMAC (1 << 4) /* V5 only */
+
+struct superblock {
+ uint8_t magic[8];
+ uint8_t version;
+ int8_t log2_interleave_sectors;
+ uint16_t integrity_tag_size;
+ uint32_t journal_sections;
+ uint64_t provided_data_sectors;
+ uint32_t flags;
+ uint8_t log2_sectors_per_block;
+ uint8_t log2_blocks_per_bitmap_bit; /* V3 only */
+ uint8_t pad[2];
+ uint64_t recalc_sector; /* V2 only */
+} __attribute__ ((packed));
+
+int INTEGRITY_read_sb(struct crypt_device *cd,
+ struct crypt_params_integrity *params,
+ uint32_t *flags);
+
+int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset);
+
+int INTEGRITY_data_sectors(struct crypt_device *cd,
+ struct device *device, uint64_t offset,
+ uint64_t *data_sectors);
+int INTEGRITY_key_size(const char *integrity);
+int INTEGRITY_tag_size(const char *integrity,
+ const char *cipher,
+ const char *cipher_mode);
+int INTEGRITY_hash_tag_size(const char *integrity);
+
+int INTEGRITY_format(struct crypt_device *cd,
+ const struct crypt_params_integrity *params,
+ struct volume_key *journal_crypt_key,
+ struct volume_key *journal_mac_key);
+
+int INTEGRITY_activate(struct crypt_device *cd,
+ const char *name,
+ const struct crypt_params_integrity *params,
+ struct volume_key *vk,
+ struct volume_key *journal_crypt_key,
+ struct volume_key *journal_mac_key,
+ uint32_t flags, uint32_t sb_flags);
+
+int INTEGRITY_create_dmd_device(struct crypt_device *cd,
+ const struct crypt_params_integrity *params,
+ struct volume_key *vk,
+ struct volume_key *journal_crypt_key,
+ struct volume_key *journal_mac_key,
+ struct crypt_dm_active_device *dmd,
+ uint32_t flags, uint32_t sb_flags);
+
+int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
+ const char *name,
+ const char *type,
+ struct crypt_dm_active_device *dmd,
+ uint32_t sb_flags);
+#endif
diff --git a/lib/internal.h b/lib/internal.h
new file mode 100644
index 0000000..b5cb4e3
--- /dev/null
+++ b/lib/internal.h
@@ -0,0 +1,253 @@
+/*
+ * libcryptsetup - cryptsetup library internal
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INTERNAL_H
+#define INTERNAL_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "nls.h"
+#include "bitops.h"
+#include "utils_blkid.h"
+#include "utils_crypt.h"
+#include "utils_loop.h"
+#include "utils_dm.h"
+#include "utils_keyring.h"
+#include "utils_io.h"
+#include "crypto_backend/crypto_backend.h"
+#include "utils_storage_wrappers.h"
+
+#include "libcryptsetup.h"
+
+#include "libcryptsetup_macros.h"
+#include "libcryptsetup_symver.h"
+
+#define LOG_MAX_LEN 4096
+#define MAX_DM_DEPS 32
+
+#define CRYPT_SUBDEV "SUBDEV" /* prefix for sublayered devices underneath public crypt types */
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
+struct crypt_device;
+struct luks2_reencrypt;
+
+struct volume_key {
+ int id;
+ size_t keylength;
+ const char *key_description;
+ struct volume_key *next;
+ char key[];
+};
+
+struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key);
+struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength);
+void crypt_free_volume_key(struct volume_key *vk);
+int crypt_volume_key_set_description(struct volume_key *key, const char *key_description);
+void crypt_volume_key_set_id(struct volume_key *vk, int id);
+int crypt_volume_key_get_id(const struct volume_key *vk);
+void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk);
+struct volume_key *crypt_volume_key_next(struct volume_key *vk);
+struct volume_key *crypt_volume_key_by_id(struct volume_key *vk, int id);
+
+struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd);
+int init_pbkdf_type(struct crypt_device *cd,
+ const struct crypt_pbkdf_type *pbkdf,
+ const char *dev_type);
+int verify_pbkdf_params(struct crypt_device *cd,
+ const struct crypt_pbkdf_type *pbkdf);
+int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
+ struct crypt_pbkdf_type *pbkdf,
+ size_t volume_key_size);
+const char *crypt_get_cipher_spec(struct crypt_device *cd);
+
+/* Device backend */
+struct device;
+int device_alloc(struct crypt_device *cd, struct device **device, const char *path);
+int device_alloc_no_check(struct device **device, const char *path);
+void device_close(struct crypt_device *cd, struct device *device);
+void device_free(struct crypt_device *cd, struct device *device);
+const char *device_path(const struct device *device);
+const char *device_dm_name(const struct device *device);
+const char *device_block_path(const struct device *device);
+void device_topology_alignment(struct crypt_device *cd,
+ struct device *device,
+ unsigned long *required_alignment, /* bytes */
+ unsigned long *alignment_offset, /* bytes */
+ unsigned long default_alignment);
+size_t device_block_size(struct crypt_device *cd, struct device *device);
+int device_read_ahead(struct device *device, uint32_t *read_ahead);
+int device_size(struct device *device, uint64_t *size);
+int device_open(struct crypt_device *cd, struct device *device, int flags);
+int device_open_excl(struct crypt_device *cd, struct device *device, int flags);
+void device_release_excl(struct crypt_device *cd, struct device *device);
+void device_disable_direct_io(struct device *device);
+int device_is_identical(struct device *device1, struct device *device2);
+int device_is_rotational(struct device *device);
+size_t device_alignment(struct device *device);
+int device_direct_io(const struct device *device);
+int device_fallocate(struct device *device, uint64_t size);
+void device_sync(struct crypt_device *cd, struct device *device);
+int device_check_size(struct crypt_device *cd,
+ struct device *device,
+ uint64_t req_offset, int falloc);
+void device_set_block_size(struct device *device, size_t size);
+size_t device_optimal_encryption_sector_size(struct crypt_device *cd, struct device *device);
+
+int device_open_locked(struct crypt_device *cd, struct device *device, int flags);
+int device_read_lock(struct crypt_device *cd, struct device *device);
+int device_write_lock(struct crypt_device *cd, struct device *device);
+void device_read_unlock(struct crypt_device *cd, struct device *device);
+void device_write_unlock(struct crypt_device *cd, struct device *device);
+bool device_is_locked(struct device *device);
+
+enum devcheck { DEV_OK = 0, DEV_EXCL = 1 };
+int device_check_access(struct crypt_device *cd,
+ struct device *device,
+ enum devcheck device_check);
+int device_block_adjust(struct crypt_device *cd,
+ struct device *device,
+ enum devcheck device_check,
+ uint64_t device_offset,
+ uint64_t *size,
+ uint32_t *flags);
+size_t size_round_up(size_t size, size_t block);
+
+int create_or_reload_device(struct crypt_device *cd, const char *name,
+ const char *type, struct crypt_dm_active_device *dmd);
+
+int create_or_reload_device_with_integrity(struct crypt_device *cd, const char *name,
+ const char *type, struct crypt_dm_active_device *dmd,
+ struct crypt_dm_active_device *dmdi);
+
+/* Receive backend devices from context helpers */
+struct device *crypt_metadata_device(struct crypt_device *cd);
+struct device *crypt_data_device(struct crypt_device *cd);
+
+int crypt_confirm(struct crypt_device *cd, const char *msg);
+
+char *crypt_lookup_dev(const char *dev_id);
+int crypt_dev_is_rotational(int major, int minor);
+int crypt_dev_is_partition(const char *dev_path);
+char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size);
+char *crypt_get_base_device(const char *dev_path);
+uint64_t crypt_dev_partition_offset(const char *dev_path);
+int lookup_by_disk_id(const char *dm_uuid);
+int lookup_by_sysfs_uuid_field(const char *dm_uuid);
+int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid);
+
+size_t crypt_getpagesize(void);
+unsigned crypt_cpusonline(void);
+uint64_t crypt_getphysmemory_kb(void);
+
+int init_crypto(struct crypt_device *ctx);
+
+#define log_dbg(c, x...) crypt_logf(c, CRYPT_LOG_DEBUG, x)
+#define log_std(c, x...) crypt_logf(c, CRYPT_LOG_NORMAL, x)
+#define log_verbose(c, x...) crypt_logf(c, CRYPT_LOG_VERBOSE, x)
+#define log_err(c, x...) crypt_logf(c, CRYPT_LOG_ERROR, x)
+
+int crypt_get_debug_level(void);
+
+void crypt_process_priority(struct crypt_device *cd, int *priority, bool raise);
+
+int crypt_metadata_locking_enabled(void);
+
+int crypt_random_init(struct crypt_device *ctx);
+int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int quality);
+void crypt_random_exit(void);
+int crypt_random_default_key_rng(void);
+
+int crypt_plain_hash(struct crypt_device *cd,
+ const char *hash_name,
+ char *key, size_t key_size,
+ const char *passphrase, size_t passphrase_size);
+int PLAIN_activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vk,
+ uint64_t size,
+ uint32_t flags);
+
+void *crypt_get_hdr(struct crypt_device *cd, const char *type);
+void crypt_set_luks2_reencrypt(struct crypt_device *cd, struct luks2_reencrypt *rh);
+struct luks2_reencrypt *crypt_get_luks2_reencrypt(struct crypt_device *cd);
+
+int onlyLUKS2(struct crypt_device *cd);
+int onlyLUKS2mask(struct crypt_device *cd, uint32_t mask);
+
+int crypt_wipe_device(struct crypt_device *cd,
+ struct device *device,
+ crypt_wipe_pattern pattern,
+ uint64_t offset,
+ uint64_t length,
+ size_t wipe_block_size,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr);
+
+/* Internal integrity helpers */
+const char *crypt_get_integrity(struct crypt_device *cd);
+int crypt_get_integrity_key_size(struct crypt_device *cd);
+int crypt_get_integrity_tag_size(struct crypt_device *cd);
+
+int crypt_key_in_keyring(struct crypt_device *cd);
+void crypt_set_key_in_keyring(struct crypt_device *cd, unsigned key_in_keyring);
+int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk);
+int crypt_use_keyring_for_vk(struct crypt_device *cd);
+void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *key_description, key_type_t ktype);
+void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks);
+
+static inline uint64_t compact_version(uint16_t major, uint16_t minor, uint16_t patch, uint16_t release)
+{
+ return (uint64_t)release | ((uint64_t)patch << 16) | ((uint64_t)minor << 32) | ((uint64_t)major << 48);
+}
+
+int kernel_version(uint64_t *kversion);
+
+int crypt_serialize_lock(struct crypt_device *cd);
+void crypt_serialize_unlock(struct crypt_device *cd);
+
+bool crypt_string_in(const char *str, char **list, size_t list_size);
+int crypt_strcmp(const char *a, const char *b);
+int crypt_compare_dm_devices(struct crypt_device *cd,
+ const struct crypt_dm_active_device *src,
+ const struct crypt_dm_active_device *tgt);
+static inline void *crypt_zalloc(size_t size) { return calloc(1, size); }
+
+static inline bool uint64_mult_overflow(uint64_t *u, uint64_t b, size_t size)
+{
+ *u = (uint64_t)b * size;
+ if ((uint64_t)(*u / size) != b)
+ return true;
+ return false;
+}
+
+#endif /* INTERNAL_H */
diff --git a/lib/keyslot_context.c b/lib/keyslot_context.c
new file mode 100644
index 0000000..89bd433
--- /dev/null
+++ b/lib/keyslot_context.c
@@ -0,0 +1,488 @@
+/*
+ * LUKS - Linux Unified Key Setup, keyslot unlock helpers
+ *
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2022-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+
+#include "luks1/luks.h"
+#include "luks2/luks2.h"
+#include "keyslot_context.h"
+
+static int get_luks2_key_by_passphrase(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ int segment,
+ struct volume_key **r_vk)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
+ assert(r_vk);
+
+ r = LUKS2_keyslot_open(cd, keyslot, segment, kc->u.p.passphrase, kc->u.p.passphrase_size, r_vk);
+ if (r < 0)
+ kc->error = r;
+
+ return r;
+}
+
+static int get_luks1_volume_key_by_passphrase(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
+ assert(r_vk);
+
+ r = LUKS_open_key_with_hdr(keyslot, kc->u.p.passphrase, kc->u.p.passphrase_size,
+ crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
+ if (r < 0)
+ kc->error = r;
+
+ return r;
+}
+
+static int get_luks2_volume_key_by_passphrase(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk)
+{
+ return get_luks2_key_by_passphrase(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
+}
+
+static int get_passphrase_by_passphrase(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ const char **r_passphrase,
+ size_t *r_passphrase_size)
+{
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_PASSPHRASE);
+ assert(r_passphrase);
+ assert(r_passphrase_size);
+
+ *r_passphrase = kc->u.p.passphrase;
+ *r_passphrase_size = kc->u.p.passphrase_size;
+
+ return 0;
+}
+
+static int get_passphrase_by_keyfile(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ const char **r_passphrase,
+ size_t *r_passphrase_size)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
+ assert(r_passphrase);
+ assert(r_passphrase_size);
+
+ if (!kc->i_passphrase) {
+ r = crypt_keyfile_device_read(cd, kc->u.kf.keyfile,
+ &kc->i_passphrase, &kc->i_passphrase_size,
+ kc->u.kf.keyfile_offset, kc->u.kf.keyfile_size, 0);
+ if (r < 0) {
+ kc->error = r;
+ return r;
+ }
+ }
+
+ *r_passphrase = kc->i_passphrase;
+ *r_passphrase_size = kc->i_passphrase_size;
+
+ return 0;
+}
+
+static int get_luks2_key_by_keyfile(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ int segment,
+ struct volume_key **r_vk)
+{
+ int r;
+ const char *passphrase;
+ size_t passphrase_size;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
+ assert(r_vk);
+
+ r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
+ if (r)
+ return r;
+
+ r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, r_vk);
+ if (r < 0)
+ kc->error = r;
+
+ return r;
+}
+
+static int get_luks2_volume_key_by_keyfile(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk)
+{
+ return get_luks2_key_by_keyfile(cd, kc, keyslot, CRYPT_DEFAULT_SEGMENT, r_vk);
+}
+
+static int get_luks1_volume_key_by_keyfile(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk)
+{
+ int r;
+ const char *passphrase;
+ size_t passphrase_size;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_KEYFILE);
+ assert(r_vk);
+
+ r = get_passphrase_by_keyfile(cd, kc, &passphrase, &passphrase_size);
+ if (r)
+ return r;
+
+ r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size,
+ crypt_get_hdr(cd, CRYPT_LUKS1), r_vk, cd);
+ if (r < 0)
+ kc->error = r;
+
+ return r;
+}
+
+static int get_key_by_key(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot __attribute__((unused)),
+ int segment __attribute__((unused)),
+ struct volume_key **r_vk)
+{
+ assert(kc && kc->type == CRYPT_KC_TYPE_KEY);
+ assert(r_vk);
+
+ if (!kc->u.k.volume_key) {
+ kc->error = -ENOENT;
+ return kc->error;
+ }
+
+ *r_vk = crypt_alloc_volume_key(kc->u.k.volume_key_size, kc->u.k.volume_key);
+ if (!*r_vk) {
+ kc->error = -ENOMEM;
+ return kc->error;
+ }
+
+ return 0;
+}
+
+static int get_volume_key_by_key(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot __attribute__((unused)),
+ struct volume_key **r_vk)
+{
+ return get_key_by_key(cd, kc, -2 /* unused */, -2 /* unused */, r_vk);
+}
+
+static int get_luks2_key_by_token(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot __attribute__((unused)),
+ int segment,
+ struct volume_key **r_vk)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_TOKEN);
+ assert(r_vk);
+
+ r = LUKS2_token_unlock_key(cd, crypt_get_hdr(cd, CRYPT_LUKS2), kc->u.t.id, kc->u.t.type,
+ kc->u.t.pin, kc->u.t.pin_size, segment, kc->u.t.usrptr, r_vk);
+ if (r < 0)
+ kc->error = r;
+
+ return r;
+}
+
+static int get_luks2_volume_key_by_token(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot __attribute__((unused)),
+ struct volume_key **r_vk)
+{
+ return get_luks2_key_by_token(cd, kc, -2 /* unused */, CRYPT_DEFAULT_SEGMENT, r_vk);
+}
+
+static int get_passphrase_by_token(struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ const char **r_passphrase,
+ size_t *r_passphrase_size)
+{
+ int r;
+
+ assert(cd);
+ assert(kc && kc->type == CRYPT_KC_TYPE_TOKEN);
+ assert(r_passphrase);
+ assert(r_passphrase_size);
+
+ if (!kc->i_passphrase) {
+ r = LUKS2_token_unlock_passphrase(cd, crypt_get_hdr(cd, CRYPT_LUKS2), kc->u.t.id,
+ kc->u.t.type, kc->u.t.pin, kc->u.t.pin_size,
+ kc->u.t.usrptr, &kc->i_passphrase, &kc->i_passphrase_size);
+ if (r < 0) {
+ kc->error = r;
+ return r;
+ }
+ kc->u.t.id = r;
+ }
+
+ *r_passphrase = kc->i_passphrase;
+ *r_passphrase_size = kc->i_passphrase_size;
+
+ return kc->u.t.id;
+}
+
+static void unlock_method_init_internal(struct crypt_keyslot_context *kc)
+{
+ assert(kc);
+
+ kc->error = 0;
+ kc->i_passphrase = NULL;
+ kc->i_passphrase_size = 0;
+}
+
+void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
+ const char *volume_key,
+ size_t volume_key_size)
+{
+ assert(kc);
+
+ kc->type = CRYPT_KC_TYPE_KEY;
+ kc->u.k.volume_key = volume_key;
+ kc->u.k.volume_key_size = volume_key_size;
+ kc->get_luks2_key = get_key_by_key;
+ kc->get_luks2_volume_key = get_volume_key_by_key;
+ kc->get_luks1_volume_key = get_volume_key_by_key;
+ kc->get_passphrase = NULL; /* keyslot key context does not provide passphrase */
+ unlock_method_init_internal(kc);
+}
+
+void crypt_keyslot_unlock_by_passphrase_init_internal(struct crypt_keyslot_context *kc,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ assert(kc);
+
+ kc->type = CRYPT_KC_TYPE_PASSPHRASE;
+ kc->u.p.passphrase = passphrase;
+ kc->u.p.passphrase_size = passphrase_size;
+ kc->get_luks2_key = get_luks2_key_by_passphrase;
+ kc->get_luks2_volume_key = get_luks2_volume_key_by_passphrase;
+ kc->get_luks1_volume_key = get_luks1_volume_key_by_passphrase;
+ kc->get_passphrase = get_passphrase_by_passphrase;
+ unlock_method_init_internal(kc);
+}
+
+void crypt_keyslot_unlock_by_keyfile_init_internal(struct crypt_keyslot_context *kc,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset)
+{
+ assert(kc);
+
+ kc->type = CRYPT_KC_TYPE_KEYFILE;
+ kc->u.kf.keyfile = keyfile;
+ kc->u.kf.keyfile_size = keyfile_size;
+ kc->u.kf.keyfile_offset = keyfile_offset;
+ kc->get_luks2_key = get_luks2_key_by_keyfile;
+ kc->get_luks2_volume_key = get_luks2_volume_key_by_keyfile;
+ kc->get_luks1_volume_key = get_luks1_volume_key_by_keyfile;
+ kc->get_passphrase = get_passphrase_by_keyfile;
+ unlock_method_init_internal(kc);
+}
+
+void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *kc,
+ int token,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr)
+{
+ assert(kc);
+
+ kc->type = CRYPT_KC_TYPE_TOKEN;
+ kc->u.t.id = token;
+ kc->u.t.type = type;
+ kc->u.t.pin = pin;
+ kc->u.t.pin_size = pin_size;
+ kc->u.t.usrptr = usrptr;
+ kc->get_luks2_key = get_luks2_key_by_token;
+ kc->get_luks2_volume_key = get_luks2_volume_key_by_token;
+ kc->get_luks1_volume_key = NULL; /* LUKS1 is not supported */
+ kc->get_passphrase = get_passphrase_by_token;
+ unlock_method_init_internal(kc);
+}
+
+void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *kc)
+{
+ if (!kc)
+ return;
+
+ crypt_safe_free(kc->i_passphrase);
+ kc->i_passphrase = NULL;
+ kc->i_passphrase_size = 0;
+}
+
+void crypt_keyslot_context_free(struct crypt_keyslot_context *kc)
+{
+ crypt_keyslot_context_destroy_internal(kc);
+ free(kc);
+}
+
+int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
+ const char *passphrase,
+ size_t passphrase_size,
+ struct crypt_keyslot_context **kc)
+{
+ struct crypt_keyslot_context *tmp;
+
+ if (!kc || !passphrase)
+ return -EINVAL;
+
+ tmp = malloc(sizeof(*tmp));
+ if (!tmp)
+ return -ENOMEM;
+
+ crypt_keyslot_unlock_by_passphrase_init_internal(tmp, passphrase, passphrase_size);
+
+ *kc = tmp;
+
+ return 0;
+}
+
+int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset,
+ struct crypt_keyslot_context **kc)
+{
+ struct crypt_keyslot_context *tmp;
+
+ if (!kc || !keyfile)
+ return -EINVAL;
+
+ tmp = malloc(sizeof(*tmp));
+ if (!tmp)
+ return -ENOMEM;
+
+ crypt_keyslot_unlock_by_keyfile_init_internal(tmp, keyfile, keyfile_size, keyfile_offset);
+
+ *kc = tmp;
+
+ return 0;
+}
+
+int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
+ int token,
+ const char *type,
+ const char *pin, size_t pin_size,
+ void *usrptr,
+ struct crypt_keyslot_context **kc)
+{
+ struct crypt_keyslot_context *tmp;
+
+ if (!kc || (token < 0 && token != CRYPT_ANY_TOKEN))
+ return -EINVAL;
+
+ tmp = malloc(sizeof(*tmp));
+ if (!tmp)
+ return -ENOMEM;
+
+ crypt_keyslot_unlock_by_token_init_internal(tmp, token, type, pin, pin_size, usrptr);
+
+ *kc = tmp;
+
+ return 0;
+}
+
+int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
+ const char *volume_key,
+ size_t volume_key_size,
+ struct crypt_keyslot_context **kc)
+{
+ struct crypt_keyslot_context *tmp;
+
+ if (!kc)
+ return -EINVAL;
+
+ tmp = malloc(sizeof(*tmp));
+ if (!tmp)
+ return -ENOMEM;
+
+ crypt_keyslot_unlock_by_key_init_internal(tmp, volume_key, volume_key_size);
+
+ *kc = tmp;
+
+ return 0;
+}
+
+int crypt_keyslot_context_get_error(struct crypt_keyslot_context *kc)
+{
+ return kc ? kc->error : -EINVAL;
+}
+
+int crypt_keyslot_context_set_pin(struct crypt_device *cd,
+ const char *pin, size_t pin_size,
+ struct crypt_keyslot_context *kc)
+{
+ if (!kc || kc->type != CRYPT_KC_TYPE_TOKEN)
+ return -EINVAL;
+
+ kc->u.t.pin = pin;
+ kc->u.t.pin_size = pin_size;
+ kc->error = 0;
+
+ return 0;
+}
+
+int crypt_keyslot_context_get_type(const struct crypt_keyslot_context *kc)
+{
+ return kc ? kc->type : -EINVAL;
+}
+
+const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc)
+{
+ assert(kc);
+
+ switch (kc->type) {
+ case CRYPT_KC_TYPE_PASSPHRASE:
+ return "passphrase";
+ case CRYPT_KC_TYPE_KEYFILE:
+ return "keyfile";
+ case CRYPT_KC_TYPE_TOKEN:
+ return "token";
+ case CRYPT_KC_TYPE_KEY:
+ return "key";
+ default:
+ return "<unknown>";
+ }
+}
diff --git a/lib/keyslot_context.h b/lib/keyslot_context.h
new file mode 100644
index 0000000..7ca7428
--- /dev/null
+++ b/lib/keyslot_context.h
@@ -0,0 +1,111 @@
+/*
+ * LUKS - Linux Unified Key Setup, keyslot unlock helpers
+ *
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2022-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef KEYSLOT_CONTEXT_H
+#define KEYSLOT_CONTEXT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "internal.h"
+
+typedef int (*keyslot_context_get_key) (
+ struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ int segment,
+ struct volume_key **r_vk);
+
+typedef int (*keyslot_context_get_volume_key) (
+ struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ int keyslot,
+ struct volume_key **r_vk);
+
+typedef int (*keyslot_context_get_passphrase) (
+ struct crypt_device *cd,
+ struct crypt_keyslot_context *kc,
+ const char **r_passphrase,
+ size_t *r_passphrase_size);
+
+/* crypt_keyslot_context */
+struct crypt_keyslot_context {
+ int type;
+
+ union {
+ struct {
+ const char *passphrase;
+ size_t passphrase_size;
+ } p;
+ struct {
+ const char *keyfile;
+ uint64_t keyfile_offset;
+ size_t keyfile_size;
+ } kf;
+ struct {
+ int id;
+ const char *type;
+ const char *pin;
+ size_t pin_size;
+ void *usrptr;
+ } t;
+ struct {
+ const char *volume_key;
+ size_t volume_key_size;
+ } k;
+ } u;
+
+ int error;
+
+ char *i_passphrase;
+ size_t i_passphrase_size;
+
+ keyslot_context_get_key get_luks2_key;
+ keyslot_context_get_volume_key get_luks1_volume_key;
+ keyslot_context_get_volume_key get_luks2_volume_key;
+ keyslot_context_get_passphrase get_passphrase;
+};
+
+void crypt_keyslot_context_destroy_internal(struct crypt_keyslot_context *method);
+
+void crypt_keyslot_unlock_by_key_init_internal(struct crypt_keyslot_context *kc,
+ const char *volume_key,
+ size_t volume_key_size);
+
+void crypt_keyslot_unlock_by_passphrase_init_internal(struct crypt_keyslot_context *kc,
+ const char *passphrase,
+ size_t passphrase_size);
+
+void crypt_keyslot_unlock_by_keyfile_init_internal(struct crypt_keyslot_context *kc,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset);
+
+void crypt_keyslot_unlock_by_token_init_internal(struct crypt_keyslot_context *kc,
+ int token,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr);
+
+const char *keyslot_context_type_string(const struct crypt_keyslot_context *kc);
+
+#endif /* KEYSLOT_CONTEXT_H */
diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h
new file mode 100644
index 0000000..e899829
--- /dev/null
+++ b/lib/libcryptsetup.h
@@ -0,0 +1,2881 @@
+/*
+ * libcryptsetup - cryptsetup library
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @file libcryptsetup.h
+ * @brief Public cryptsetup API
+ *
+ * For more verbose examples of LUKS related use cases,
+ * please read @ref index "examples".
+ */
+
+#ifndef _LIBCRYPTSETUP_H
+#define _LIBCRYPTSETUP_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * @defgroup crypt-init Cryptsetup device context initialization
+ * Set of functions for creating and destroying @e crypt_device context
+ * @addtogroup crypt-init
+ * @{
+ */
+
+struct crypt_device; /* crypt device handle */
+struct crypt_keyslot_context;
+
+/**
+ * Initialize crypt device handle and check if the provided device exists.
+ *
+ * @param cd Returns pointer to crypt device handle
+ * @param device Path to the backing device.
+ * If @e device is not a block device but a path to some file,
+ * the function will try to create a loopdevice and attach
+ * the file to the loopdevice with AUTOCLEAR flag set.
+ * If @e device is @e NULL function it will initialize dm backend only.
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note Note that logging is not initialized here, possible messages use
+ * default log function.
+ */
+int crypt_init(struct crypt_device **cd, const char *device);
+
+/**
+ * Initialize crypt device handle with optional data device and check
+ * if devices exist.
+ *
+ * @param cd Returns pointer to crypt device handle
+ * @param device Path to the backing device or detached header.
+ * @param data_device Path to the data device or @e NULL.
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note Note that logging is not initialized here, possible messages use
+ * default log function.
+ */
+int crypt_init_data_device(struct crypt_device **cd,
+ const char *device,
+ const char *data_device);
+
+/**
+ * Initialize crypt device handle from provided active device name,
+ * and, optionally, from separate metadata (header) device
+ * and check if provided device exists.
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @param cd returns crypt device handle for active device
+ * @param name name of active crypt device
+ * @param header_device optional device containing on-disk header
+ * (@e NULL if it the same as underlying device on there is no on-disk header)
+ *
+ * @post In case @e device points to active LUKS device but header load fails,
+ * context device type is set to @e NULL and @e 0 is returned as if it were successful.
+ * Context with @e NULL device type can only be deactivated by crypt_deactivate
+ *
+ * @note @link crypt_init_by_name @endlink is equivalent to calling
+ * crypt_init_by_name_and_header(cd, name, NULL);
+ */
+int crypt_init_by_name_and_header(struct crypt_device **cd,
+ const char *name,
+ const char *header_device);
+
+/**
+ * This is equivalent to call
+ * @ref crypt_init_by_name_and_header "crypt_init_by_name_and_header(cd, name, NULL)"
+ *
+ * @sa crypt_init_by_name_and_header
+ */
+int crypt_init_by_name(struct crypt_device **cd, const char *name);
+
+/**
+ * Release crypt device context and used memory.
+ *
+ * @param cd crypt device handle
+ */
+void crypt_free(struct crypt_device *cd);
+
+/**
+ * Set confirmation callback (yes/no).
+ *
+ * If code need confirmation (like resetting uuid or restoring LUKS header from file)
+ * this function is called. If not defined, everything is confirmed.
+ *
+ * Callback function @e confirm should return @e 0 if operation is declined,
+ * other values mean accepted.
+ *
+ * @param cd crypt device handle
+ * @param confirm user defined confirm callback reference; use
+ * @p msg for message for user to confirm and
+ * @p usrptr for identification in callback
+ * @param usrptr provided identification in callback
+ *
+ * @note Current version of cryptsetup API requires confirmation for UUID change and
+ * LUKS header restore only.
+ */
+void crypt_set_confirm_callback(struct crypt_device *cd,
+ int (*confirm)(const char *msg, void *usrptr),
+ void *usrptr);
+
+/**
+ * Set data device
+ * For LUKS it is encrypted data device when LUKS header is separated.
+ * For VERITY it is data device when hash device is separated.
+ *
+ * @param cd crypt device handle
+ * @param device path to device
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ */
+int crypt_set_data_device(struct crypt_device *cd, const char *device);
+
+/**
+ * Set data device offset in 512-byte sectors.
+ * Used for LUKS.
+ * This function is replacement for data alignment fields in LUKS param struct.
+ * If set to 0 (default), old behaviour is preserved.
+ * This value is reset on @link crypt_load @endlink.
+ *
+ * @param cd crypt device handle
+ * @param data_offset data offset in bytes
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ *
+ * @note Data offset must be aligned to multiple of 8 (alignment to 4096-byte sectors)
+ * and must be big enough to accommodate the whole LUKS header with all keyslots.
+ * @note Data offset is enforced by this function, device topology
+ * information is no longer used after calling this function.
+ */
+int crypt_set_data_offset(struct crypt_device *cd, uint64_t data_offset);
+
+/** @} */
+
+/**
+ * @defgroup crypt-log Cryptsetup logging
+ * Set of functions and defines used in cryptsetup for
+ * logging purposes
+ * @addtogroup crypt-log
+ * @{
+ */
+
+/** normal log level */
+#define CRYPT_LOG_NORMAL 0
+/** error log level */
+#define CRYPT_LOG_ERROR 1
+/** verbose log level */
+#define CRYPT_LOG_VERBOSE 2
+/** debug log level - always on stdout */
+#define CRYPT_LOG_DEBUG -1
+/** debug log level - additional JSON output (for LUKS2) */
+#define CRYPT_LOG_DEBUG_JSON -2
+
+/**
+ * Set log function.
+ *
+ * @param cd crypt device handle (can be @e NULL to set default log function)
+ * @param log user defined log function reference; use
+ * @p level for log level,
+ * @p msg for message, and
+ * @p usrptr for identification in callback
+ * @param usrptr provided identification in callback
+ */
+void crypt_set_log_callback(struct crypt_device *cd,
+ void (*log)(int level, const char *msg, void *usrptr),
+ void *usrptr);
+
+/**
+ * Defines log function or use the default one otherwise.
+ *
+ * @see crypt_set_log_callback
+ *
+ * @param cd crypt device handle
+ * @param level log level
+ * @param msg log message
+ */
+void crypt_log(struct crypt_device *cd, int level, const char *msg);
+
+/**
+ * Log function with variable arguments.
+ *
+ * @param cd crypt device handle
+ * @param level log level
+ * @param format formatted log message
+ */
+void crypt_logf(struct crypt_device *cd, int level, const char *format, ...);
+/** @} */
+
+/**
+ * @defgroup crypt-set Cryptsetup settings (RNG, PBKDF, locking)
+ * @addtogroup crypt-set
+ * @{
+ */
+
+/** CRYPT_RNG_URANDOM - use /dev/urandom */
+#define CRYPT_RNG_URANDOM 0
+/** CRYPT_RNG_RANDOM - use /dev/random (waits if no entropy in system) */
+#define CRYPT_RNG_RANDOM 1
+
+/**
+ * Set which RNG (random number generator) is used for generating long term key
+ *
+ * @param cd crypt device handle
+ * @param rng_type kernel random number generator to use
+ *
+ */
+void crypt_set_rng_type(struct crypt_device *cd, int rng_type);
+
+/**
+ * Get which RNG (random number generator) is used for generating long term key.
+ *
+ * @param cd crypt device handle
+ * @return RNG type on success or negative errno value otherwise.
+ *
+ */
+int crypt_get_rng_type(struct crypt_device *cd);
+
+/**
+ * PBKDF parameters.
+ */
+struct crypt_pbkdf_type {
+ const char *type; /**< PBKDF algorithm */
+ const char *hash; /**< Hash algorithm */
+ uint32_t time_ms; /**< Requested time cost [milliseconds] */
+ uint32_t iterations; /**< Iterations, 0 or benchmarked value. */
+ uint32_t max_memory_kb; /**< Requested or benchmarked memory cost [kilobytes] */
+ uint32_t parallel_threads;/**< Requested parallel cost [threads] */
+ uint32_t flags; /**< CRYPT_PBKDF* flags */
+};
+
+/** Iteration time set by crypt_set_iteration_time(), for compatibility only. */
+#define CRYPT_PBKDF_ITER_TIME_SET (UINT32_C(1) << 0)
+/** Never run benchmarks, use pre-set value or defaults. */
+#define CRYPT_PBKDF_NO_BENCHMARK (UINT32_C(1) << 1)
+
+/** PBKDF2 according to RFC2898, LUKS1 legacy */
+#define CRYPT_KDF_PBKDF2 "pbkdf2"
+/** Argon2i according to RFC */
+#define CRYPT_KDF_ARGON2I "argon2i"
+/** Argon2id according to RFC */
+#define CRYPT_KDF_ARGON2ID "argon2id"
+
+/**
+ * Set default PBKDF (Password-Based Key Derivation Algorithm) for next keyslot
+ * about to get created with any crypt_keyslot_add_*() call.
+ *
+ * @param cd crypt device handle
+ * @param pbkdf PBKDF parameters
+ *
+ * @return 0 on success or negative errno value otherwise.
+ *
+ * @note For LUKS1, only PBKDF2 is supported, other settings will be rejected.
+ * @note For non-LUKS context types the call succeeds, but PBKDF is not used.
+ */
+int crypt_set_pbkdf_type(struct crypt_device *cd,
+ const struct crypt_pbkdf_type *pbkdf);
+
+/**
+ * Get PBKDF (Password-Based Key Derivation Algorithm) parameters.
+ *
+ * @param pbkdf_type type of PBKDF
+ *
+ * @return struct on success or NULL value otherwise.
+ *
+ */
+const struct crypt_pbkdf_type *crypt_get_pbkdf_type_params(const char *pbkdf_type);
+
+/**
+ * Get default PBKDF (Password-Based Key Derivation Algorithm) settings for keyslots.
+ * Works only with LUKS device handles (both versions).
+ *
+ * @param type type of device (see @link crypt-type @endlink)
+ *
+ * @return struct on success or NULL value otherwise.
+ *
+ */
+const struct crypt_pbkdf_type *crypt_get_pbkdf_default(const char *type);
+
+/**
+ * Get current PBKDF (Password-Based Key Derivation Algorithm) settings for keyslots.
+ * Works only with LUKS device handles (both versions).
+ *
+ * @param cd crypt device handle
+ *
+ * @return struct on success or NULL value otherwise.
+ *
+ */
+const struct crypt_pbkdf_type *crypt_get_pbkdf_type(struct crypt_device *cd);
+
+/**
+ * Set how long should cryptsetup iterate in PBKDF2 function.
+ * Default value heads towards the iterations which takes around 1 second.
+ * \b Deprecated, only for backward compatibility.
+ * Use @link crypt_set_pbkdf_type @endlink.
+ *
+ * @param cd crypt device handle
+ * @param iteration_time_ms the time in ms
+ *
+ * @note If the time value is not acceptable for active PBKDF, value is quietly ignored.
+ */
+void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_ms);
+
+/**
+ * Helper to lock/unlock memory to avoid swap sensitive data to disk.
+ * \b Deprecated, only for backward compatibility. Memory with keys are locked automatically.
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param lock 0 to unlock otherwise lock memory
+ *
+ * @returns Value indicating whether the memory is locked (function can be called multiple times).
+ *
+ * @note Only root can do this.
+ * @note It locks/unlocks all process memory, not only crypt context.
+ */
+int crypt_memory_lock(struct crypt_device *cd, int lock) __attribute__((deprecated));
+
+/**
+ * Set global lock protection for on-disk metadata (file-based locking).
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param enable 0 to disable locking otherwise enable it (default)
+ *
+ * @returns @e 0 on success or negative errno value otherwise.
+ *
+ * @note Locking applied only for some metadata formats (LUKS2).
+ * @note The switch is global on the library level.
+ * In current version locking can be only switched off and cannot be switched on later.
+ */
+int crypt_metadata_locking(struct crypt_device *cd, int enable);
+
+/**
+ * Set metadata header area sizes. This applies only to LUKS2.
+ * These values limit amount of metadata anf number of supportable keyslots.
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param metadata_size size in bytes of JSON area + 4k binary header
+ * @param keyslots_size size in bytes of binary keyslots area
+ *
+ * @returns @e 0 on success or negative errno value otherwise.
+ *
+ * @note The metadata area is stored twice and both copies contain 4k binary header.
+ * Only 16,32,64,128,256,512,1024,2048 and 4096 kB value is allowed (see LUKS2 specification).
+ * @note Keyslots area size must be multiple of 4k with maximum 128MB.
+ */
+int crypt_set_metadata_size(struct crypt_device *cd,
+ uint64_t metadata_size,
+ uint64_t keyslots_size);
+
+/**
+ * Get metadata header area sizes. This applies only to LUKS2.
+ * These values limit amount of metadata anf number of supportable keyslots.
+ *
+ * @param cd crypt device handle
+ * @param metadata_size size in bytes of JSON area + 4k binary header
+ * @param keyslots_size size in bytes of binary keyslots area
+ *
+ * @returns @e 0 on success or negative errno value otherwise.
+ */
+int crypt_get_metadata_size(struct crypt_device *cd,
+ uint64_t *metadata_size,
+ uint64_t *keyslots_size);
+
+/** @} */
+
+/**
+ * @defgroup crypt-type Cryptsetup on-disk format types
+ * Set of functions, \#defines and structs related
+ * to on-disk format types
+ * @addtogroup crypt-type
+ * @{
+ */
+
+/** plain crypt device, no on-disk header */
+#define CRYPT_PLAIN "PLAIN"
+/** LUKS version 1 header on-disk */
+#define CRYPT_LUKS1 "LUKS1"
+/** LUKS version 2 header on-disk */
+#define CRYPT_LUKS2 "LUKS2"
+/** loop-AES compatibility mode */
+#define CRYPT_LOOPAES "LOOPAES"
+/** dm-verity mode */
+#define CRYPT_VERITY "VERITY"
+/** TCRYPT (TrueCrypt-compatible and VeraCrypt-compatible) mode */
+#define CRYPT_TCRYPT "TCRYPT"
+/** INTEGRITY dm-integrity device */
+#define CRYPT_INTEGRITY "INTEGRITY"
+/** BITLK (BitLocker-compatible mode) */
+#define CRYPT_BITLK "BITLK"
+/** FVAULT2 (FileVault2-compatible mode) */
+#define CRYPT_FVAULT2 "FVAULT2"
+
+/** LUKS any version */
+#define CRYPT_LUKS NULL
+
+/**
+ * Get device type
+ *
+ * @param cd crypt device handle
+ * @return string according to device type or @e NULL if not known.
+ */
+const char *crypt_get_type(struct crypt_device *cd);
+
+/**
+ * Get device default LUKS type
+ *
+ * @return string according to device type (CRYPT_LUKS1 or CRYPT_LUKS2).
+ */
+const char *crypt_get_default_type(void);
+
+/**
+ *
+ * Structure used as parameter for PLAIN device type.
+ *
+ * @see crypt_format
+ */
+struct crypt_params_plain {
+ const char *hash; /**< password hash function */
+ uint64_t offset; /**< offset in sectors */
+ uint64_t skip; /**< IV offset / initialization sector */
+ uint64_t size; /**< size of mapped device or @e 0 for autodetection */
+ uint32_t sector_size; /**< sector size in bytes (@e 0 means 512 for compatibility) */
+};
+
+/**
+ * Structure used as parameter for LUKS device type.
+ *
+ * @see crypt_format, crypt_load
+ *
+ * @note during crypt_format @e data_device attribute determines
+ * if the LUKS header is separated from encrypted payload device
+ *
+ */
+struct crypt_params_luks1 {
+ const char *hash; /**< hash used in LUKS header */
+ size_t data_alignment; /**< data area alignment in 512B sectors, data offset is multiple of this */
+ const char *data_device; /**< detached encrypted data device or @e NULL */
+};
+
+/**
+ *
+ * Structure used as parameter for loop-AES device type.
+ *
+ * @see crypt_format
+ *
+ */
+struct crypt_params_loopaes {
+ const char *hash; /**< key hash function */
+ uint64_t offset; /**< offset in sectors */
+ uint64_t skip; /**< IV offset / initialization sector */
+};
+
+/**
+ *
+ * Structure used as parameter for dm-verity device type.
+ *
+ * @see crypt_format, crypt_load
+ *
+ */
+struct crypt_params_verity {
+ const char *hash_name; /**< hash function */
+ const char *data_device; /**< data_device (CRYPT_VERITY_CREATE_HASH) */
+ const char *hash_device; /**< hash_device (output only) */
+ const char *fec_device; /**< fec_device (output only) */
+ const char *salt; /**< salt */
+ uint32_t salt_size; /**< salt size (in bytes) */
+ uint32_t hash_type; /**< in-kernel hashing type */
+ uint32_t data_block_size; /**< data block size (in bytes) */
+ uint32_t hash_block_size; /**< hash block size (in bytes) */
+ uint64_t data_size; /**< data area size (in data blocks) */
+ uint64_t hash_area_offset; /**< hash/header offset (in bytes) */
+ uint64_t fec_area_offset; /**< FEC/header offset (in bytes) */
+ uint32_t fec_roots; /**< Reed-Solomon FEC roots */
+ uint32_t flags; /**< CRYPT_VERITY* flags */
+};
+
+/** No on-disk header (only hashes) */
+#define CRYPT_VERITY_NO_HEADER (UINT32_C(1) << 0)
+/** Verity hash in userspace before activation */
+#define CRYPT_VERITY_CHECK_HASH (UINT32_C(1) << 1)
+/** Create hash - format hash device */
+#define CRYPT_VERITY_CREATE_HASH (UINT32_C(1) << 2)
+/** Root hash signature required for activation */
+#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (UINT32_C(1) << 3)
+
+/**
+ *
+ * Structure used as parameter for TCRYPT device type.
+ *
+ * @see crypt_load
+ *
+ */
+struct crypt_params_tcrypt {
+ const char *passphrase; /**< passphrase to unlock header (input only) */
+ size_t passphrase_size; /**< passphrase size (input only, max length is 64) */
+ const char **keyfiles; /**< keyfile paths to unlock header (input only) */
+ unsigned int keyfiles_count;/**< keyfiles count (input only) */
+ const char *hash_name; /**< hash function for PBKDF */
+ const char *cipher; /**< cipher chain c1[-c2[-c3]] */
+ const char *mode; /**< cipher block mode */
+ size_t key_size; /**< key size in bytes (the whole chain) */
+ uint32_t flags; /**< CRYPT_TCRYPT* flags */
+ uint32_t veracrypt_pim; /**< VeraCrypt Personal Iteration Multiplier */
+};
+
+/** Include legacy modes when scanning for header */
+#define CRYPT_TCRYPT_LEGACY_MODES (UINT32_C(1) << 0)
+/** Try to load hidden header (describing hidden device) */
+#define CRYPT_TCRYPT_HIDDEN_HEADER (UINT32_C(1) << 1)
+/** Try to load backup header */
+#define CRYPT_TCRYPT_BACKUP_HEADER (UINT32_C(1) << 2)
+/** Device contains encrypted system (with boot loader) */
+#define CRYPT_TCRYPT_SYSTEM_HEADER (UINT32_C(1) << 3)
+/** Include VeraCrypt modes when scanning for header,
+ * all other TCRYPT flags applies as well.
+ * VeraCrypt device is reported as TCRYPT type.
+ */
+#define CRYPT_TCRYPT_VERA_MODES (UINT32_C(1) << 4)
+
+/**
+ *
+ * Structure used as parameter for dm-integrity device type.
+ *
+ * @see crypt_format, crypt_load
+ *
+ * @note In bitmap tracking mode, the journal is implicitly disabled.
+ * As an ugly workaround for compatibility, journal_watermark is overloaded
+ * to mean 512-bytes sectors-per-bit and journal_commit_time means bitmap flush time.
+ * All other journal parameters are not applied in the bitmap mode.
+ */
+struct crypt_params_integrity {
+ uint64_t journal_size; /**< size of journal in bytes */
+ unsigned int journal_watermark; /**< journal flush watermark in percents; in bitmap mode sectors-per-bit */
+ unsigned int journal_commit_time; /**< journal commit time (or bitmap flush time) in ms */
+ uint32_t interleave_sectors; /**< number of interleave sectors (power of two) */
+ uint32_t tag_size; /**< tag size per-sector in bytes */
+ uint32_t sector_size; /**< sector size in bytes */
+ uint32_t buffer_sectors; /**< number of sectors in one buffer */
+ const char *integrity; /**< integrity algorithm, NULL for LUKS2 */
+ uint32_t integrity_key_size; /**< integrity key size in bytes, info only, 0 for LUKS2 */
+
+ const char *journal_integrity; /**< journal integrity algorithm */
+ const char *journal_integrity_key; /**< journal integrity key, only for crypt_load */
+ uint32_t journal_integrity_key_size; /**< journal integrity key size in bytes, only for crypt_load */
+
+ const char *journal_crypt; /**< journal encryption algorithm */
+ const char *journal_crypt_key; /**< journal crypt key, only for crypt_load */
+ uint32_t journal_crypt_key_size; /**< journal crypt key size in bytes, only for crypt_load */
+};
+
+/**
+ * Structure used as parameter for LUKS2 device type.
+ *
+ * @see crypt_format, crypt_load
+ *
+ * @note during crypt_format @e data_device attribute determines
+ * if the LUKS2 header is separated from encrypted payload device
+ *
+ */
+struct crypt_params_luks2 {
+ const struct crypt_pbkdf_type *pbkdf; /**< PBKDF (and hash) parameters or @e NULL*/
+ const char *integrity; /**< integrity algorithm or @e NULL */
+ const struct crypt_params_integrity *integrity_params; /**< Data integrity parameters or @e NULL*/
+ size_t data_alignment; /**< data area alignment in 512B sectors, data offset is multiple of this */
+ const char *data_device; /**< detached encrypted data device or @e NULL */
+ uint32_t sector_size; /**< encryption sector size, 0 triggers auto-detection for optimal encryption sector size */
+ const char *label; /**< header label or @e NULL*/
+ const char *subsystem; /**< header subsystem label or @e NULL*/
+};
+/** @} */
+
+/**
+ * @defgroup crypt-actions Cryptsetup device context actions
+ * Set of functions for formatting and manipulating with specific crypt_type
+ * @addtogroup crypt-actions
+ * @{
+ */
+
+/**
+ * Create (format) new crypt device (and possible header on-disk) but do not activate it.
+ *
+ * @pre @e cd contains initialized and not formatted device context (device type must @b not be set)
+ *
+ * @param cd crypt device handle
+ * @param type type of device (optional params struct must be of this type)
+ * @param cipher (e.g. "aes")
+ * @param cipher_mode including IV specification (e.g. "xts-plain")
+ * @param uuid requested UUID or @e NULL if it should be generated
+ * @param volume_key pre-generated volume key or @e NULL if it should be generated (only for LUKS)
+ * @param volume_key_size size of volume key in bytes.
+ * @param params crypt type specific parameters (see @link crypt-type @endlink)
+ *
+ * @returns @e 0 on success or negative errno value otherwise.
+ *
+ * @note Note that crypt_format does not create LUKS keyslot (any version). To create keyslot
+ * call any crypt_keyslot_add_* function.
+ * @note For VERITY @link crypt-type @endlink, only uuid parameter is used, other parameters
+ * are ignored and verity specific attributes are set through mandatory params option.
+ */
+int crypt_format(struct crypt_device *cd,
+ const char *type,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ const char *volume_key,
+ size_t volume_key_size,
+ void *params);
+
+/**
+ * Set format compatibility flags.
+ *
+ * @param cd crypt device handle
+ * @param flags CRYPT_COMPATIBILITY_* flags
+ */
+void crypt_set_compatibility(struct crypt_device *cd, uint32_t flags);
+
+/**
+ * Get compatibility flags.
+ *
+ * @param cd crypt device handle
+ *
+ * @returns compatibility flags
+ */
+uint32_t crypt_get_compatibility(struct crypt_device *cd);
+
+/** dm-integrity device uses less effective (legacy) padding (old kernels) */
+#define CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING (UINT32_C(1) << 0)
+/** dm-integrity device does not protect superblock with HMAC (old kernels) */
+#define CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC (UINT32_C(1) << 1)
+/** dm-integrity allow recalculating of volumes with HMAC keys (old kernels) */
+#define CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC (UINT32_C(1) << 2)
+
+/**
+ * Convert to new type for already existing device.
+ *
+ * @param cd crypt device handle
+ * @param type type of device (optional params struct must be of this type)
+ * @param params crypt type specific parameters (see @link crypt-type @endlink)
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ *
+ * @note Currently, only LUKS1->LUKS2 and LUKS2->LUKS1 conversions are supported.
+ * Not all LUKS2 devices may be converted back to LUKS1. To make such a conversion
+ * possible all active LUKS2 keyslots must be in LUKS1 compatible mode (i.e. pbkdf
+ * type must be PBKDF2) and device cannot be formatted with any authenticated
+ * encryption mode.
+ *
+ * @note Device must be offline for conversion. UUID change is not possible for active
+ * devices.
+ */
+int crypt_convert(struct crypt_device *cd,
+ const char *type,
+ void *params);
+
+/**
+ * Set new UUID for already existing device.
+ *
+ * @param cd crypt device handle
+ * @param uuid requested UUID or @e NULL if it should be generated
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ *
+ * @note Currently, only LUKS device type are supported
+ */
+int crypt_set_uuid(struct crypt_device *cd,
+ const char *uuid);
+
+/**
+ * Set new labels (label and subsystem) for already existing device.
+ *
+ * @param cd crypt device handle
+ * @param label requested label or @e NULL
+ * @param subsystem requested subsystem label or @e NULL
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ *
+ * @note Currently, only LUKS2 device type is supported
+ */
+int crypt_set_label(struct crypt_device *cd,
+ const char *label,
+ const char *subsystem);
+
+/**
+ * Get the label of an existing device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return label, or @e NULL otherwise
+ */
+const char *crypt_get_label(struct crypt_device *cd);
+
+/**
+ * Get the subsystem of an existing device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return subsystem, or @e NULL otherwise
+ */
+const char *crypt_get_subsystem(struct crypt_device *cd);
+
+/**
+ * Enable or disable loading of volume keys via kernel keyring. When set to
+ * 'enabled' library loads key in kernel keyring first and pass the key
+ * description to dm-crypt instead of binary key copy. If set to 'disabled'
+ * library fallbacks to old method of loading volume key directly in
+ * dm-crypt target.
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param enable 0 to disable loading of volume keys via kernel keyring
+ * (classical method) otherwise enable it (default)
+ *
+ * @returns @e 0 on success or negative errno value otherwise.
+ *
+ * @note Currently loading of volume keys via kernel keyring is supported
+ * (and enabled by default) only for LUKS2 devices.
+ * @note The switch is global on the library level.
+ */
+int crypt_volume_key_keyring(struct crypt_device *cd, int enable);
+
+/**
+ * Load crypt device parameters from on-disk header.
+ *
+ * @param cd crypt device handle
+ * @param requested_type @link crypt-type @endlink or @e NULL for all known
+ * @param params crypt type specific parameters (see @link crypt-type @endlink)
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ *
+ * @post In case LUKS header is read successfully but payload device is too small
+ * error is returned and device type in context is set to @e NULL
+ *
+ * @note Note that load works only for device types with on-disk metadata.
+ * @note Function does not print visible error message if metadata is not present.
+ *
+ */
+int crypt_load(struct crypt_device *cd,
+ const char *requested_type,
+ void *params);
+
+/**
+ * Try to repair crypt device LUKS on-disk header if invalid.
+ *
+ * @param cd crypt device handle
+ * @param requested_type @link crypt-type @endlink or @e NULL for all known
+ * @param params crypt type specific parameters (see @link crypt-type @endlink)
+ *
+ * @returns 0 on success or negative errno value otherwise.
+ *
+ * @note For LUKS2 device crypt_repair bypass blkid checks and
+ * perform auto-recovery even though there're third party device
+ * signatures found by blkid probes. Currently the crypt_repair on LUKS2
+ * works only if exactly one header checksum does not match or exactly
+ * one header is missing.
+ */
+int crypt_repair(struct crypt_device *cd,
+ const char *requested_type,
+ void *params);
+
+/**
+ * Resize crypt device.
+ *
+ * @param cd - crypt device handle
+ * @param name - name of device to resize
+ * @param new_size - new device size in sectors or @e 0 to use all of the underlying device size
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note Most notably it returns -EPERM when device was activated with volume key
+ * in kernel keyring and current device handle (context) doesn't have verified key
+ * loaded in kernel. To load volume key for already active device use any of
+ * @link crypt_activate_by_passphrase @endlink, @link crypt_activate_by_keyfile @endlink,
+ * @link crypt_activate_by_keyfile_offset @endlink, @link crypt_activate_by_volume_key @endlink,
+ * @link crypt_activate_by_keyring @endlink or @link crypt_activate_by_token @endlink with flag
+ * @e CRYPT_ACTIVATE_KEYRING_KEY raised and @e name parameter set to @e NULL.
+ */
+int crypt_resize(struct crypt_device *cd,
+ const char *name,
+ uint64_t new_size);
+
+/**
+ * Suspend crypt device.
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param name name of device to suspend
+ *
+ * @return 0 on success or negative errno value otherwise.
+ *
+ * @note Only LUKS device type is supported
+ *
+ */
+int crypt_suspend(struct crypt_device *cd,
+ const char *name);
+
+/**
+ * Resume crypt device using passphrase.
+ *
+ *
+ * @param cd crypt device handle
+ * @param name name of device to resume
+ * @param keyslot requested keyslot or CRYPT_ANY_SLOT
+ * @param passphrase passphrase used to unlock volume key
+ * @param passphrase_size size of @e passphrase (binary data)
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ *
+ * @note Only LUKS device type is supported
+ */
+int crypt_resume_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size);
+
+/**
+ * Resume crypt device using key file.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to resume
+ * @param keyslot requested keyslot or CRYPT_ANY_SLOT
+ * @param keyfile key file used to unlock volume key
+ * @param keyfile_size number of bytes to read from keyfile, 0 is unlimited
+ * @param keyfile_offset number of bytes to skip at start of keyfile
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ */
+int crypt_resume_by_keyfile_device_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset);
+
+/**
+ * Backward compatible crypt_resume_by_keyfile_device_offset() (with size_t offset).
+ */
+int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ size_t keyfile_offset);
+
+/**
+ * Backward compatible crypt_resume_by_keyfile_device_offset() (without offset).
+ */
+int crypt_resume_by_keyfile(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size);
+/**
+ * Resume crypt device using provided volume key.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to resume
+ * @param volume_key provided volume key
+ * @param volume_key_size size of volume_key
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_resume_by_volume_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size);
+/**
+ * Resume crypt device using LUKS2 token.
+ *
+ * @param cd LUKS2 crypt device handle
+ * @param name name of device to resume
+ * @param type restrict type of token, if @e NULL all types are allowed
+ * @param pin passphrase (or PIN) to unlock token (may be binary data)
+ * @param pin_size size of @e pin
+ * @param usrptr provided identification in callback
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ *
+ * @note EPERM errno means token provided passphrase successfully, but
+ * passphrase did not unlock any keyslot associated with the token.
+ *
+ * @note ENOENT errno means no token (or subsequently assigned keyslot) was
+ * eligible to resume LUKS2 device.
+ *
+ * @note ENOANO errno means that token is PIN protected and was either missing
+ * (NULL) or wrong.
+ *
+ * @note Negative EAGAIN errno means token handler requires additional hardware
+ * not present in the system to unlock keyslot.
+ *
+ * @note with @param token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
+ * to resume device using any available token. It may happen that various token handlers
+ * return different error codes. At the end loop returns error codes in the following
+ * order (from the most significant to the least) any negative errno except those
+ * listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
+ */
+int crypt_resume_by_token_pin(struct crypt_device *cd,
+ const char *name,
+ const char *type,
+ int token,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr);
+/** @} */
+
+/**
+ * @defgroup crypt-keyslot LUKS keyslots
+ * @addtogroup crypt-keyslot
+ * @{
+ */
+
+/** iterate through all keyslots and find first one that fits */
+#define CRYPT_ANY_SLOT -1
+
+/**
+ * Add key slot using provided passphrase.
+ *
+ * @pre @e cd contains initialized and formatted LUKS device context
+ *
+ * @param cd crypt device handle
+ * @param keyslot requested keyslot or @e CRYPT_ANY_SLOT
+ * @param passphrase passphrase used to unlock volume key
+ * @param passphrase_size size of passphrase (binary data)
+ * @param new_passphrase passphrase for new keyslot
+ * @param new_passphrase_size size of @e new_passphrase (binary data)
+ *
+ * @return allocated key slot number or negative errno otherwise.
+ */
+int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size,
+ const char *new_passphrase,
+ size_t new_passphrase_size);
+
+/**
+ * Change defined key slot using provided passphrase.
+ *
+ * @pre @e cd contains initialized and formatted LUKS device context
+ *
+ * @param cd crypt device handle
+ * @param keyslot_old old keyslot or @e CRYPT_ANY_SLOT
+ * @param keyslot_new new keyslot (can be the same as old)
+ * @param passphrase passphrase used to unlock volume key
+ * @param passphrase_size size of passphrase (binary data)
+ * @param new_passphrase passphrase for new keyslot
+ * @param new_passphrase_size size of @e new_passphrase (binary data)
+ *
+ * @return allocated key slot number or negative errno otherwise.
+ */
+int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size,
+ const char *new_passphrase,
+ size_t new_passphrase_size);
+
+/**
+* Add key slot using provided key file path.
+ *
+ * @pre @e cd contains initialized and formatted LUKS device context
+ *
+ * @param cd crypt device handle
+ * @param keyslot requested keyslot or @e CRYPT_ANY_SLOT
+ * @param keyfile key file used to unlock volume key
+ * @param keyfile_size number of bytes to read from keyfile, @e 0 is unlimited
+ * @param keyfile_offset number of bytes to skip at start of keyfile
+ * @param new_keyfile keyfile for new keyslot
+ * @param new_keyfile_size number of bytes to read from @e new_keyfile, @e 0 is unlimited
+ * @param new_keyfile_offset number of bytes to skip at start of new_keyfile
+ *
+ * @return allocated key slot number or negative errno otherwise.
+ */
+int crypt_keyslot_add_by_keyfile_device_offset(struct crypt_device *cd,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset,
+ const char *new_keyfile,
+ size_t new_keyfile_size,
+ uint64_t new_keyfile_offset);
+
+/**
+ * Backward compatible crypt_keyslot_add_by_keyfile_device_offset() (with size_t offset).
+ */
+int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ size_t keyfile_offset,
+ const char *new_keyfile,
+ size_t new_keyfile_size,
+ size_t new_keyfile_offset);
+
+/**
+ * Backward compatible crypt_keyslot_add_by_keyfile_device_offset() (without offset).
+ */
+int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ const char *new_keyfile,
+ size_t new_keyfile_size);
+
+/**
+ * Add key slot using provided volume key.
+ *
+ * @pre @e cd contains initialized and formatted LUKS device context
+ *
+ * @param cd crypt device handle
+ * @param keyslot requested keyslot or CRYPT_ANY_SLOT
+ * @param volume_key provided volume key or @e NULL if used after crypt_format
+ * @param volume_key_size size of volume_key
+ * @param passphrase passphrase for new keyslot
+ * @param passphrase_size size of passphrase
+ *
+ * @return allocated key slot number or negative errno otherwise.
+ */
+int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
+ int keyslot,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *passphrase,
+ size_t passphrase_size);
+
+/** create keyslot with volume key not associated with current dm-crypt segment */
+#define CRYPT_VOLUME_KEY_NO_SEGMENT (UINT32_C(1) << 0)
+
+/** create keyslot with new volume key and assign it to current dm-crypt segment */
+#define CRYPT_VOLUME_KEY_SET (UINT32_C(1) << 1)
+
+/** Assign key to first matching digest before creating new digest */
+#define CRYPT_VOLUME_KEY_DIGEST_REUSE (UINT32_C(1) << 2)
+
+/**
+ * Add key slot using provided key.
+ *
+ * @pre @e cd contains initialized and formatted LUKS2 device context
+ *
+ * @param cd crypt device handle
+ * @param keyslot requested keyslot or CRYPT_ANY_SLOT
+ * @param volume_key provided volume key or @e NULL (see note below)
+ * @param volume_key_size size of volume_key
+ * @param passphrase passphrase for new keyslot
+ * @param passphrase_size size of passphrase
+ * @param flags key flags to set
+ *
+ * @return allocated key slot number or negative errno otherwise.
+ *
+ * @note in case volume_key is @e NULL following first matching rule will apply:
+ * @li if cd is device handle used in crypt_format() by current process, the volume
+ * key generated (or passed) in crypt_format() will be stored in keyslot.
+ * @li if CRYPT_VOLUME_KEY_NO_SEGMENT flag is raised the new volume_key will be
+ * generated and stored in keyslot. The keyslot will become unbound (unusable to
+ * dm-crypt device activation).
+ * @li fails with -EINVAL otherwise
+ *
+ * @warning CRYPT_VOLUME_KEY_SET flag force updates volume key. It is @b not @b reencryption!
+ * By doing so you will most probably destroy your ciphertext data device. It's supposed
+ * to be used only in wrapped keys scheme for key refresh process where real (inner) volume
+ * key stays untouched. It may be involed on active @e keyslot which makes the (previously
+ * unbound) keyslot new regular keyslot.
+ */
+int crypt_keyslot_add_by_key(struct crypt_device *cd,
+ int keyslot,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags);
+
+/**
+ * @defgroup crypt-keyslot-context Crypt keyslot context
+ * @addtogroup crypt-keyslot-context
+ * @{
+ */
+
+/**
+ * Release crypt keyslot context and used memory.
+ *
+ * @param kc crypt keyslot context
+ */
+void crypt_keyslot_context_free(struct crypt_keyslot_context *kc);
+
+/**
+ * Initialize keyslot context via passphrase.
+ *
+ * @param cd crypt device handle initialized to LUKS device context
+ * @param passphrase passphrase for a keyslot
+ * @param passphrase_size size of passphrase
+ * @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_PASSPHRASE
+ *
+ * @return zero on success or negative errno otherwise.
+ */
+int crypt_keyslot_context_init_by_passphrase(struct crypt_device *cd,
+ const char *passphrase,
+ size_t passphrase_size,
+ struct crypt_keyslot_context **kc);
+
+/**
+ * Initialize keyslot context via key file path.
+ *
+ * @param cd crypt device handle initialized to LUKS device context
+ *
+ * @param keyfile key file with passphrase for a keyslot
+ * @param keyfile_size number of bytes to read from keyfile, @e 0 is unlimited
+ * @param keyfile_offset number of bytes to skip at start of keyfile
+ * @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEYFILE
+ *
+ * @return zero on success or negative errno otherwise.
+ */
+int crypt_keyslot_context_init_by_keyfile(struct crypt_device *cd,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset,
+ struct crypt_keyslot_context **kc);
+
+/**
+ * Initialize keyslot context via LUKS2 token.
+ *
+ * @param cd crypt device handle initialized to LUKS2 device context
+ *
+ * @param token token providing passphrase for a keyslot or CRYPT_ANY_TOKEN
+ * @param type restrict type of token, if @e NULL all types are allowed
+ * @param pin passphrase (or PIN) to unlock token (may be binary data)
+ * @param pin_size size of @e pin
+ * @param usrptr provided identification in callback
+ * @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_TOKEN
+ *
+ * @return zero on success or negative errno otherwise.
+ */
+int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
+ int token,
+ const char *type,
+ const char *pin, size_t pin_size,
+ void *usrptr,
+ struct crypt_keyslot_context **kc);
+
+/**
+ * Initialize keyslot context via key.
+ *
+ * @param cd crypt device handle initialized to LUKS device context
+ *
+ * @param volume_key provided volume key or @e NULL if used after crypt_format
+ * or with CRYPT_VOLUME_KEY_NO_SEGMENT flag
+ * @param volume_key_size size of volume_key
+ * @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEY
+ *
+ * @return zero on success or negative errno otherwise.
+ */
+int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
+ const char *volume_key,
+ size_t volume_key_size,
+ struct crypt_keyslot_context **kc);
+
+/**
+ * Get error code per keyslot context from last failed call.
+ *
+ * @note If @link crypt_keyslot_add_by_keyslot_context @endlink passed with
+ * no negative return code. The return value of this function is undefined.
+ *
+ * @param kc keyslot context involved in failed @link crypt_keyslot_add_by_keyslot_context @endlink
+ *
+ * @return Negative errno if keyslot context caused a failure, zero otherwise.
+ */
+int crypt_keyslot_context_get_error(struct crypt_keyslot_context *kc);
+
+/**
+ * Set new pin to token based keyslot context.
+ *
+ * @note Use when @link crypt_keyslot_add_by_keyslot_context @endlink failed
+ * and token keyslot context returned -ENOANO error code via
+ * @link crypt_keyslot_context_get_error @endlink.
+ *
+ * @param cd crypt device handle initialized to LUKS2 device context
+ * @param pin passphrase (or PIN) to unlock token (may be binary data)
+ * @param pin_size size of @e pin
+ * @param kc LUKS2 keyslot context (only @link CRYPT_KC_TYPE_TOKEN @endlink is allowed)
+ *
+ * @return zero on success or negative errno otherwise
+ */
+int crypt_keyslot_context_set_pin(struct crypt_device *cd,
+ const char *pin, size_t pin_size,
+ struct crypt_keyslot_context *kc);
+
+/**
+ * @defgroup crypt-keyslot-context-types Crypt keyslot context
+ * @addtogroup crypt-keyslot-context-types
+ * @{
+ */
+/** keyslot context initialized by passphrase (@link crypt_keyslot_context_init_by_passphrase @endlink) */
+#define CRYPT_KC_TYPE_PASSPHRASE INT16_C(1)
+/** keyslot context initialized by keyfile (@link crypt_keyslot_context_init_by_keyfile @endlink) */
+#define CRYPT_KC_TYPE_KEYFILE INT16_C(2)
+/** keyslot context initialized by token (@link crypt_keyslot_context_init_by_token @endlink) */
+#define CRYPT_KC_TYPE_TOKEN INT16_C(3)
+/** keyslot context initialized by volume key or unbound key (@link crypt_keyslot_context_init_by_volume_key @endlink) */
+#define CRYPT_KC_TYPE_KEY INT16_C(4)
+/** @} */
+
+/**
+ * Get type identifier for crypt keyslot context.
+ *
+ * @param kc keyslot context
+ *
+ * @return crypt keyslot context type id (see @link crypt-keyslot-context-types @endlink) or negative errno otherwise.
+ */
+int crypt_keyslot_context_get_type(const struct crypt_keyslot_context *kc);
+/** @} */
+
+/**
+ * Add key slot by volume key provided by keyslot context (kc). New
+ * keyslot will be protected by passphrase provided by new keyslot context (new_kc).
+ * See @link crypt-keyslot-context @endlink for context initialization routines.
+ *
+ * @pre @e cd contains initialized and formatted LUKS device context.
+ *
+ * @param cd crypt device handle
+ * @param keyslot_existing existing keyslot or CRYPT_ANY_SLOT to get volume key from.
+ * @param kc keyslot context providing volume key.
+ * @param keyslot_new new keyslot or CRYPT_ANY_SLOT (first free number is used).
+ * @param new_kc keyslot context providing passphrase for new keyslot.
+ * @param flags key flags to set
+ *
+ * @return allocated key slot number or negative errno otherwise.
+ *
+ * @note new_kc can not be @e CRYPT_KC_TYPE_KEY type keyslot context.
+ *
+ * @note For kc parameter with type @e CRYPT_KC_TYPE_KEY the keyslot_existing
+ * parameter is ignored.
+ *
+ * @note in case there is no active LUKS keyslot to get existing volume key from, one of following must apply:
+ * @li @e cd must be device handle used in crypt_format() by current process (it holds reference to generated volume key)
+ * @li kc must be of @e CRYPT_KC_TYPE_KEY type with valid volume key.
+ *
+ * @note With CRYPT_VOLUME_KEY_NO_SEGMENT flag raised and kc of type @e CRYPT_KC_TYPE_KEY with @e volume_key set to @e NULL
+ * the new volume_key will be generated and stored in new keyslot. The keyslot will become unbound (unusable to
+ * dm-crypt device activation).
+ *
+ * @warning CRYPT_VOLUME_KEY_SET flag force updates volume key. It is @b not @b reencryption!
+ * By doing so you will most probably destroy your ciphertext data device. It's supposed
+ * to be used only in wrapped keys scheme for key refresh process where real (inner) volume
+ * key stays untouched. It may be involed on active @e keyslot which makes the (previously
+ * unbound) keyslot new regular keyslot.
+ */
+int crypt_keyslot_add_by_keyslot_context(struct crypt_device *cd,
+ int keyslot_existing,
+ struct crypt_keyslot_context *kc,
+ int keyslot_new,
+ struct crypt_keyslot_context *new_kc,
+ uint32_t flags);
+
+/**
+ * Destroy (and disable) key slot.
+ *
+ * @pre @e cd contains initialized and formatted LUKS device context
+ *
+ * @param cd crypt device handle
+ * @param keyslot requested key slot to destroy
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note Note that there is no passphrase verification used.
+ */
+int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
+/** @} */
+
+/**
+ * @defgroup crypt-aflags Device runtime attributes
+ * Activation flags
+ * @addtogroup crypt-aflags
+ * @{
+ */
+
+/** device is read only */
+#define CRYPT_ACTIVATE_READONLY (UINT32_C(1) << 0)
+/** only reported for device without uuid */
+#define CRYPT_ACTIVATE_NO_UUID (UINT32_C(1) << 1)
+/** activate even if cannot grant exclusive access (DANGEROUS) */
+#define CRYPT_ACTIVATE_SHARED (UINT32_C(1) << 2)
+/** enable discards aka TRIM */
+#define CRYPT_ACTIVATE_ALLOW_DISCARDS (UINT32_C(1) << 3)
+/** skip global udev rules in activation ("private device"), input only */
+#define CRYPT_ACTIVATE_PRIVATE (UINT32_C(1) << 4)
+/** corruption detected (verity), output only */
+#define CRYPT_ACTIVATE_CORRUPTED (UINT32_C(1) << 5)
+/** use same_cpu_crypt option for dm-crypt */
+#define CRYPT_ACTIVATE_SAME_CPU_CRYPT (UINT32_C(1) << 6)
+/** use submit_from_crypt_cpus for dm-crypt */
+#define CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS (UINT32_C(1) << 7)
+/** dm-verity: ignore_corruption flag - ignore corruption, log it only */
+#define CRYPT_ACTIVATE_IGNORE_CORRUPTION (UINT32_C(1) << 8)
+/** dm-verity: restart_on_corruption flag - restart kernel on corruption */
+#define CRYPT_ACTIVATE_RESTART_ON_CORRUPTION (UINT32_C(1) << 9)
+/** dm-verity: ignore_zero_blocks - do not verify zero blocks */
+#define CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS (UINT32_C(1) << 10)
+/** key loaded in kernel keyring instead directly in dm-crypt */
+#define CRYPT_ACTIVATE_KEYRING_KEY (UINT32_C(1) << 11)
+/** dm-integrity: direct writes, do not use journal */
+#define CRYPT_ACTIVATE_NO_JOURNAL (UINT32_C(1) << 12)
+/** dm-integrity: recovery mode - no journal, no integrity checks */
+#define CRYPT_ACTIVATE_RECOVERY (UINT32_C(1) << 13)
+/** ignore persistently stored flags */
+#define CRYPT_ACTIVATE_IGNORE_PERSISTENT (UINT32_C(1) << 14)
+/** dm-verity: check_at_most_once - check data blocks only the first time */
+#define CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE (UINT32_C(1) << 15)
+/** allow activation check including unbound keyslots (keyslots without segments) */
+#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (UINT32_C(1) << 16)
+/** dm-integrity: activate automatic recalculation */
+#define CRYPT_ACTIVATE_RECALCULATE (UINT32_C(1) << 17)
+/** reactivate existing and update flags, input only */
+#define CRYPT_ACTIVATE_REFRESH (UINT32_C(1) << 18)
+/** Use global lock to serialize memory hard KDF on activation (OOM workaround) */
+#define CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF (UINT32_C(1) << 19)
+/** dm-integrity: direct writes, use bitmap to track dirty sectors */
+#define CRYPT_ACTIVATE_NO_JOURNAL_BITMAP (UINT32_C(1) << 20)
+/** device is suspended (key should be wiped from memory), output only */
+#define CRYPT_ACTIVATE_SUSPENDED (UINT32_C(1) << 21)
+/** use IV sector counted in sector_size instead of default 512 bytes sectors */
+#define CRYPT_ACTIVATE_IV_LARGE_SECTORS (UINT32_C(1) << 22)
+/** dm-verity: panic_on_corruption flag - panic kernel on corruption */
+#define CRYPT_ACTIVATE_PANIC_ON_CORRUPTION (UINT32_C(1) << 23)
+/** dm-crypt: bypass internal workqueue and process read requests synchronously. */
+#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (UINT32_C(1) << 24)
+/** dm-crypt: bypass internal workqueue and process write requests synchronously. */
+#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (UINT32_C(1) << 25)
+/** dm-integrity: reset automatic recalculation */
+#define CRYPT_ACTIVATE_RECALCULATE_RESET (UINT32_C(1) << 26)
+/** dm-verity: try to use tasklets */
+#define CRYPT_ACTIVATE_TASKLETS (UINT32_C(1) << 27)
+
+/**
+ * Active device runtime attributes
+ */
+struct crypt_active_device {
+ uint64_t offset; /**< offset in sectors */
+ uint64_t iv_offset; /**< IV initialization sector */
+ uint64_t size; /**< active device size */
+ uint32_t flags; /**< activation flags */
+};
+
+/**
+ * Receive runtime attributes of active crypt device.
+ *
+ * @param cd crypt device handle (can be @e NULL)
+ * @param name name of active device
+ * @param cad preallocated active device attributes to fill
+ *
+ * @return @e 0 on success or negative errno value otherwise
+ *
+ */
+int crypt_get_active_device(struct crypt_device *cd,
+ const char *name,
+ struct crypt_active_device *cad);
+
+/**
+ * Get detected number of integrity failures.
+ *
+ * @param cd crypt device handle (can be @e NULL)
+ * @param name name of active device
+ *
+ * @return number of integrity failures or @e 0 otherwise
+ *
+ */
+uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd,
+ const char *name);
+/** @} */
+
+/**
+ * @defgroup crypt-pflags LUKS2 Device persistent flags and requirements
+ * @addtogroup crypt-pflags
+ * @{
+ */
+
+/**
+ * LUKS2 header requirements
+ */
+/** Unfinished offline reencryption */
+#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (UINT32_C(1) << 0)
+/** Online reencryption in-progress */
+#define CRYPT_REQUIREMENT_ONLINE_REENCRYPT (UINT32_C(1) << 1)
+/** unknown requirement in header (output only) */
+#define CRYPT_REQUIREMENT_UNKNOWN (UINT32_C(1) << 31)
+
+/**
+ * Persistent flags type
+ */
+typedef enum {
+ CRYPT_FLAGS_ACTIVATION, /**< activation flags, @see aflags */
+ CRYPT_FLAGS_REQUIREMENTS /**< requirements flags */
+} crypt_flags_type;
+
+/**
+ * Set persistent flags.
+ *
+ * @param cd crypt device handle (can be @e NULL)
+ * @param type type to set (CRYPT_FLAGS_ACTIVATION or CRYPT_FLAGS_REQUIREMENTS)
+ * @param flags flags to set
+ *
+ * @return @e 0 on success or negative errno value otherwise
+ *
+ * @note Valid only for LUKS2.
+ *
+ * @note Not all activation flags can be stored. Only ALLOW_DISCARD,
+ * SAME_CPU_CRYPT, SUBMIT_FROM_CRYPT_CPU and NO_JOURNAL can be
+ * stored persistently.
+ *
+ * @note Only requirements flags recognised by current library may be set.
+ * CRYPT_REQUIREMENT_UNKNOWN is illegal (output only) in set operation.
+ */
+int crypt_persistent_flags_set(struct crypt_device *cd,
+ crypt_flags_type type,
+ uint32_t flags);
+
+/**
+ * Get persistent flags stored in header.
+ *
+ * @param cd crypt device handle (can be @e NULL)
+ * @param type flags type to retrieve (CRYPT_FLAGS_ACTIVATION or CRYPT_FLAGS_REQUIREMENTS)
+ * @param flags reference to output variable
+ *
+ * @return @e 0 on success or negative errno value otherwise
+ */
+int crypt_persistent_flags_get(struct crypt_device *cd,
+ crypt_flags_type type,
+ uint32_t *flags);
+/** @} */
+
+/**
+ * @defgroup crypt-activation Device activation
+ * @addtogroup crypt-activation
+ * @{
+ */
+
+/**
+ * Activate device or check passphrase.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create, if @e NULL only check passphrase
+ * @param keyslot requested keyslot to check or @e CRYPT_ANY_SLOT
+ * @param passphrase passphrase used to unlock volume key
+ * @param passphrase_size size of @e passphrase
+ * @param flags activation flags
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ */
+int crypt_activate_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags);
+
+/**
+ * Activate device or check using key file.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create, if @e NULL only check keyfile
+ * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT
+ * @param keyfile key file used to unlock volume key
+ * @param keyfile_size number of bytes to read from keyfile, 0 is unlimited
+ * @param keyfile_offset number of bytes to skip at start of keyfile
+ * @param flags activation flags
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ */
+int crypt_activate_by_keyfile_device_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset,
+ uint32_t flags);
+
+/**
+ * Backward compatible crypt_activate_by_keyfile_device_offset() (with size_t offset).
+ */
+int crypt_activate_by_keyfile_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ size_t keyfile_offset,
+ uint32_t flags);
+
+/**
+ * Backward compatible crypt_activate_by_keyfile_device_offset() (without offset).
+ */
+int crypt_activate_by_keyfile(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint32_t flags);
+
+/**
+ * Activate device using provided volume key.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create, if @e NULL only check volume key
+ * @param volume_key provided volume key (or @e NULL to use internal)
+ * @param volume_key_size size of volume_key
+ * @param flags activation flags
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note If @e NULL is used for volume_key, device has to be initialized
+ * by previous operation (like @ref crypt_format
+ * or @ref crypt_init_by_name)
+ * @note For VERITY the volume key means root hash required for activation.
+ * Because kernel dm-verity is always read only, you have to provide
+ * CRYPT_ACTIVATE_READONLY flag always.
+ * @note For TCRYPT the volume key should be always NULL
+ * the key from decrypted header is used instead.
+ */
+int crypt_activate_by_volume_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size,
+ uint32_t flags);
+
+/**
+ * Activate VERITY device using provided key and optional signature).
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create
+ * @param volume_key provided volume key
+ * @param volume_key_size size of volume_key
+ * @param signature buffer with signature for the key
+ * @param signature_size bsize of signature buffer
+ * @param flags activation flags
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note For VERITY the volume key means root hash required for activation.
+ * Because kernel dm-verity is always read only, you have to provide
+ * CRYPT_ACTIVATE_READONLY flag always.
+ */
+int crypt_activate_by_signed_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *signature,
+ size_t signature_size,
+ uint32_t flags);
+
+/**
+ * Activate device using passphrase stored in kernel keyring.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create, if @e NULL only check passphrase in keyring
+ * @param key_description kernel keyring key description library should look
+ * for passphrase in
+ * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT
+ * @param flags activation flags
+ *
+ * @return @e unlocked keyslot number on success or negative errno value otherwise.
+ *
+ * @note Keyslot passphrase must be stored in 'user' key type
+ * and the key has to be reachable for process context
+ * on behalf of which this function is called.
+ */
+int crypt_activate_by_keyring(struct crypt_device *cd,
+ const char *name,
+ const char *key_description,
+ int keyslot,
+ uint32_t flags);
+
+/** lazy deactivation - remove once last user releases it */
+#define CRYPT_DEACTIVATE_DEFERRED (UINT32_C(1) << 0)
+/** force deactivation - if the device is busy, it is replaced by error device */
+#define CRYPT_DEACTIVATE_FORCE (UINT32_C(1) << 1)
+/** if set, remove lazy deactivation */
+#define CRYPT_DEACTIVATE_DEFERRED_CANCEL (UINT32_C(1) << 2)
+
+/**
+ * Deactivate crypt device. This function tries to remove active device-mapper
+ * mapping from kernel. Also, sensitive data like the volume key are removed from
+ * memory
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param name name of device to deactivate
+ * @param flags deactivation flags
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ */
+int crypt_deactivate_by_name(struct crypt_device *cd,
+ const char *name,
+ uint32_t flags);
+
+/**
+ * Deactivate crypt device. See @ref crypt_deactivate_by_name with empty @e flags.
+ */
+int crypt_deactivate(struct crypt_device *cd, const char *name);
+/** @} */
+
+/**
+ * @defgroup crypt-key Volume Key manipulation
+ * @addtogroup crypt-key
+ * @{
+ */
+
+/**
+ * Get volume key from crypt device.
+ *
+ * @param cd crypt device handle
+ * @param keyslot use this keyslot or @e CRYPT_ANY_SLOT
+ * @param volume_key buffer for volume key
+ * @param volume_key_size on input, size of buffer @e volume_key,
+ * on output size of @e volume_key
+ * @param passphrase passphrase used to unlock volume key
+ * @param passphrase_size size of @e passphrase
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ *
+ * @note For TCRYPT cipher chain is the volume key concatenated
+ * for all ciphers in chain.
+ * @note For VERITY the volume key means root hash used for activation.
+ * @note For LUKS devices, if passphrase is @e NULL and volume key is cached in
+ * device context it returns the volume key generated in preceding
+ * @link crypt_format @endlink call.
+ */
+int crypt_volume_key_get(struct crypt_device *cd,
+ int keyslot,
+ char *volume_key,
+ size_t *volume_key_size,
+ const char *passphrase,
+ size_t passphrase_size);
+
+/**
+ * Get volume key from crypt device by keyslot context.
+ *
+ * @param cd crypt device handle
+ * @param keyslot use this keyslot or @e CRYPT_ANY_SLOT
+ * @param volume_key buffer for volume key
+ * @param volume_key_size on input, size of buffer @e volume_key,
+ * on output size of @e volume_key
+ * @param kc keyslot context used to unlock volume key
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ *
+ * @note See @link crypt-keyslot-context-types @endlink for info on keyslot
+ * context initialization.
+ * @note For TCRYPT cipher chain is the volume key concatenated
+ * for all ciphers in chain (kc may be NULL).
+ * @note For VERITY the volume key means root hash used for activation
+ * (kc may be NULL).
+ * @note For LUKS devices, if kc is @e NULL and volume key is cached in
+ * device context it returns the volume key generated in preceding
+ * @link crypt_format @endlink call.
+ * @note @link CRYPT_KC_TYPE_TOKEN @endlink keyslot context is usable only with LUKS2 devices.
+ * @note @link CRYPT_KC_TYPE_KEY @endlink keyslot context can not be used.
+ * @note To get LUKS2 unbound key, keyslot parameter must not be @e CRYPT_ANY_SLOT.
+ * @note EPERM errno means provided keyslot context could not unlock any (or selected)
+ * keyslot.
+ * @note ENOENT errno means no LUKS keyslot is available to retrieve volume key from
+ * and there's no cached volume key in device handle.
+ */
+int crypt_volume_key_get_by_keyslot_context(struct crypt_device *cd,
+ int keyslot,
+ char *volume_key,
+ size_t *volume_key_size,
+ struct crypt_keyslot_context *kc);
+
+/**
+ * Verify that provided volume key is valid for crypt device.
+ *
+ * @param cd crypt device handle
+ * @param volume_key provided volume key
+ * @param volume_key_size size of @e volume_key
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note Negative EPERM return value means that passed volume_key
+ * did not pass digest verification routine (not a valid volume
+ * key).
+ */
+int crypt_volume_key_verify(struct crypt_device *cd,
+ const char *volume_key,
+ size_t volume_key_size);
+/** @} */
+
+/**
+ * @defgroup crypt-devstat Crypt and Verity device status
+ * @addtogroup crypt-devstat
+ * @{
+ */
+
+/**
+ * Device status
+ */
+typedef enum {
+ CRYPT_INVALID, /**< device mapping is invalid in this context */
+ CRYPT_INACTIVE, /**< no such mapped device */
+ CRYPT_ACTIVE, /**< device is active */
+ CRYPT_BUSY /**< device is active and has open count > 0 */
+} crypt_status_info;
+
+/**
+ * Get status info about device name.
+ *
+ * @param cd crypt device handle, can be @e NULL
+ * @param name crypt device name
+ *
+ * @return value defined by crypt_status_info.
+ *
+ */
+crypt_status_info crypt_status(struct crypt_device *cd, const char *name);
+
+/**
+ * Dump text-formatted information about crypt or verity device to log output.
+ *
+ * @param cd crypt device handle
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_dump(struct crypt_device *cd);
+
+/**
+ * Dump JSON-formatted information about LUKS2 device
+ *
+ * @param cd crypt device handle (only LUKS2 format supported)
+ * @param json buffer with JSON, if NULL use log callback for output
+ * @param flags dump flags (reserved)
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_dump_json(struct crypt_device *cd, const char **json, uint32_t flags);
+
+/**
+ * Get cipher used in device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return used cipher, e.g. "aes" or @e NULL otherwise
+ *
+ */
+const char *crypt_get_cipher(struct crypt_device *cd);
+
+/**
+ * Get cipher mode used in device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return used cipher mode e.g. "xts-plain" or @e otherwise
+ *
+ */
+const char *crypt_get_cipher_mode(struct crypt_device *cd);
+
+/**
+ * Get device UUID.
+ *
+ * @param cd crypt device handle
+ *
+ * @return device UUID or @e NULL if not set
+ *
+ */
+const char *crypt_get_uuid(struct crypt_device *cd);
+
+/**
+ * Get path to underlying device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return path to underlying device name
+ *
+ */
+const char *crypt_get_device_name(struct crypt_device *cd);
+
+/**
+ * Get path to detached metadata device or @e NULL if it is not detached.
+ *
+ * @param cd crypt device handle
+ *
+ * @return path to underlying device name
+ *
+ */
+const char *crypt_get_metadata_device_name(struct crypt_device *cd);
+
+/**
+ * Get device offset in 512-bytes sectors where real data starts (on underlying device).
+ *
+ * @param cd crypt device handle
+ *
+ * @return device offset in sectors
+ *
+ */
+uint64_t crypt_get_data_offset(struct crypt_device *cd);
+
+/**
+ * Get IV offset in 512-bytes sectors (skip).
+ *
+ * @param cd crypt device handle
+ *
+ * @return IV offset
+ *
+ */
+uint64_t crypt_get_iv_offset(struct crypt_device *cd);
+
+/**
+ * Get size (in bytes) of volume key for crypt device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return volume key size
+ *
+ * @note For LUKS2, this function can be used only if there is at least
+ * one keyslot assigned to data segment.
+ */
+int crypt_get_volume_key_size(struct crypt_device *cd);
+
+/**
+ * Get size (in bytes) of encryption sector for crypt device.
+ *
+ * @param cd crypt device handle
+ *
+ * @return sector size
+ *
+ */
+int crypt_get_sector_size(struct crypt_device *cd);
+
+/**
+ * Check if initialized LUKS context uses detached header
+ * (LUKS header located on a different device than data.)
+ *
+ * @param cd crypt device handle
+ *
+ * @return @e 1 if detached header is used, @e 0 if not
+ * or negative errno value otherwise.
+ *
+ * @note This is a runtime attribute, it does not say
+ * if a LUKS device requires detached header.
+ * This function works only with LUKS devices.
+ */
+int crypt_header_is_detached(struct crypt_device *cd);
+
+/**
+ * Get device parameters for VERITY device.
+ *
+ * @param cd crypt device handle
+ * @param vp verity device info
+ *
+ * @e 0 on success or negative errno value otherwise.
+ *
+ */
+int crypt_get_verity_info(struct crypt_device *cd,
+ struct crypt_params_verity *vp);
+
+/**
+ * Get device parameters for INTEGRITY device.
+ *
+ * @param cd crypt device handle
+ * @param ip verity device info
+ *
+ * @e 0 on success or negative errno value otherwise.
+ *
+ */
+int crypt_get_integrity_info(struct crypt_device *cd,
+ struct crypt_params_integrity *ip);
+/** @} */
+
+/**
+ * @defgroup crypt-benchmark Benchmarking
+ * Benchmarking of algorithms
+ * @addtogroup crypt-benchmark
+ * @{
+ */
+
+/**
+ * Informational benchmark for ciphers.
+ *
+ * @param cd crypt device handle
+ * @param cipher (e.g. "aes")
+ * @param cipher_mode (e.g. "xts"), IV generator is ignored
+ * @param volume_key_size size of volume key in bytes
+ * @param iv_size size of IV in bytes
+ * @param buffer_size size of encryption buffer in bytes used in test
+ * @param encryption_mbs measured encryption speed in MiB/s
+ * @param decryption_mbs measured decryption speed in MiB/s
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note If encryption_buffer_size is too small and encryption time
+ * cannot be properly measured, -ERANGE is returned.
+ */
+int crypt_benchmark(struct crypt_device *cd,
+ const char *cipher,
+ const char *cipher_mode,
+ size_t volume_key_size,
+ size_t iv_size,
+ size_t buffer_size,
+ double *encryption_mbs,
+ double *decryption_mbs);
+
+/**
+ * Informational benchmark for PBKDF.
+ *
+ * @param cd crypt device handle
+ * @param pbkdf PBKDF parameters
+ * @param password password for benchmark
+ * @param password_size size of password
+ * @param salt salt for benchmark
+ * @param salt_size size of salt
+ * @param volume_key_size output volume key size
+ * @param progress callback function
+ * @param usrptr provided identification in callback
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_benchmark_pbkdf(struct crypt_device *cd,
+ struct crypt_pbkdf_type *pbkdf,
+ const char *password,
+ size_t password_size,
+ const char *salt,
+ size_t salt_size,
+ size_t volume_key_size,
+ int (*progress)(uint32_t time_ms, void *usrptr),
+ void *usrptr);
+/** @} */
+
+/**
+ * @addtogroup crypt-keyslot
+ * @{
+ */
+
+/**
+ * Crypt keyslot info
+ */
+typedef enum {
+ CRYPT_SLOT_INVALID, /**< invalid keyslot */
+ CRYPT_SLOT_INACTIVE, /**< keyslot is inactive (free) */
+ CRYPT_SLOT_ACTIVE, /**< keyslot is active (used) */
+ CRYPT_SLOT_ACTIVE_LAST,/**< keylost is active (used)
+ * and last used at the same time */
+ CRYPT_SLOT_UNBOUND /**< keyslot is active and not bound
+ * to any crypt segment (LUKS2 only) */
+} crypt_keyslot_info;
+
+/**
+ * Get information about particular key slot.
+ *
+ * @param cd crypt device handle
+ * @param keyslot requested keyslot to check or CRYPT_ANY_SLOT
+ *
+ * @return value defined by crypt_keyslot_info
+ *
+ */
+crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot);
+
+/**
+ * Crypt keyslot priority
+ */
+typedef enum {
+ CRYPT_SLOT_PRIORITY_INVALID =-1, /**< no such slot */
+ CRYPT_SLOT_PRIORITY_IGNORE = 0, /**< CRYPT_ANY_SLOT will ignore it for open */
+ CRYPT_SLOT_PRIORITY_NORMAL = 1, /**< default priority, tried after preferred */
+ CRYPT_SLOT_PRIORITY_PREFER = 2, /**< will try to open first */
+} crypt_keyslot_priority;
+
+/**
+ * Get keyslot priority (LUKS2)
+ *
+ * @param cd crypt device handle
+ * @param keyslot keyslot number
+ *
+ * @return value defined by crypt_keyslot_priority
+ */
+crypt_keyslot_priority crypt_keyslot_get_priority(struct crypt_device *cd, int keyslot);
+
+/**
+ * Set keyslot priority (LUKS2)
+ *
+ * @param cd crypt device handle
+ * @param keyslot keyslot number
+ * @param priority priority defined in crypt_keyslot_priority
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_keyslot_set_priority(struct crypt_device *cd, int keyslot, crypt_keyslot_priority priority);
+
+/**
+ * Get number of keyslots supported for device type.
+ *
+ * @param type crypt device type
+ *
+ * @return slot count or negative errno otherwise if device
+ * doesn't not support keyslots.
+ */
+int crypt_keyslot_max(const char *type);
+
+/**
+ * Get keyslot area pointers (relative to metadata device).
+ *
+ * @param cd crypt device handle
+ * @param keyslot keyslot number
+ * @param offset offset on metadata device (in bytes)
+ * @param length length of keyslot area (in bytes)
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ */
+int crypt_keyslot_area(struct crypt_device *cd,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length);
+
+/**
+ * Get size (in bytes) of stored key in particular keyslot.
+ * Use for LUKS2 unbound keyslots, for other keyslots it is the same as @ref crypt_get_volume_key_size
+ *
+ * @param cd crypt device handle
+ * @param keyslot keyslot number
+ *
+ * @return volume key size or negative errno value otherwise.
+ *
+ */
+int crypt_keyslot_get_key_size(struct crypt_device *cd, int keyslot);
+
+/**
+ * Get cipher and key size for keyslot encryption.
+ * Use for LUKS2 keyslot to set different encryption type than for data encryption.
+ * Parameters will be used for next keyslot operations.
+ *
+ * @param cd crypt device handle
+ * @param keyslot keyslot number of CRYPT_ANY_SLOT for default
+ * @param key_size encryption key size (in bytes)
+ *
+ * @return cipher specification on success or @e NULL.
+ *
+ * @note This is the encryption of keyslot itself, not the data encryption algorithm!
+ */
+const char *crypt_keyslot_get_encryption(struct crypt_device *cd, int keyslot, size_t *key_size);
+
+/**
+ * Get PBKDF parameters for keyslot.
+ *
+ * @param cd crypt device handle
+ * @param keyslot keyslot number
+ * @param pbkdf struct with returned PBKDF parameters
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_keyslot_get_pbkdf(struct crypt_device *cd, int keyslot, struct crypt_pbkdf_type *pbkdf);
+
+/**
+ * Set encryption for keyslot.
+ * Use for LUKS2 keyslot to set different encryption type than for data encryption.
+ * Parameters will be used for next keyslot operations that create or change a keyslot.
+ *
+ * @param cd crypt device handle
+ * @param cipher (e.g. "aes-xts-plain64")
+ * @param key_size encryption key size (in bytes)
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note To reset to default keyslot encryption (the same as for data)
+ * set cipher to NULL and key size to 0.
+ */
+int crypt_keyslot_set_encryption(struct crypt_device *cd,
+ const char *cipher,
+ size_t key_size);
+
+/**
+ * Get directory where mapped crypt devices are created
+ *
+ * @return the directory path
+ */
+const char *crypt_get_dir(void);
+
+/** @} */
+
+/**
+ * @defgroup crypt-backup Device metadata backup
+ * @addtogroup crypt-backup
+ * @{
+ */
+/**
+ * Backup header and keyslots to file.
+ *
+ * @param cd crypt device handle
+ * @param requested_type @link crypt-type @endlink or @e NULL for all known
+ * @param backup_file file to backup header to
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ */
+int crypt_header_backup(struct crypt_device *cd,
+ const char *requested_type,
+ const char *backup_file);
+
+/**
+ * Restore header and keyslots from backup file.
+ *
+ * @param cd crypt device handle
+ * @param requested_type @link crypt-type @endlink or @e NULL for all known
+ * @param backup_file file to restore header from
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ */
+int crypt_header_restore(struct crypt_device *cd,
+ const char *requested_type,
+ const char *backup_file);
+/** @} */
+
+/**
+ * @defgroup crypt-dbg Library debug level
+ * Set library debug level
+ * @addtogroup crypt-dbg
+ * @{
+ */
+
+/** Debug all */
+#define CRYPT_DEBUG_ALL -1
+/** Debug all with additional JSON dump (for LUKS2) */
+#define CRYPT_DEBUG_JSON -2
+/** Debug none */
+#define CRYPT_DEBUG_NONE 0
+
+/**
+ * Set the debug level for library
+ *
+ * @param level debug level
+ *
+ */
+void crypt_set_debug_level(int level);
+/** @} */
+
+/**
+ * @defgroup crypt-keyfile Function to read keyfile
+ * @addtogroup crypt-keyfile
+ * @{
+ */
+
+/**
+ * Read keyfile
+ *
+ * @param cd crypt device handle
+ * @param keyfile keyfile to read
+ * @param key buffer for key
+ * @param key_size_read size of read key
+ * @param keyfile_offset key offset in keyfile
+ * @param key_size exact key length to read from file or 0
+ * @param flags keyfile read flags
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note If key_size is set to zero we read internal max length
+ * and actual size read is returned via key_size_read parameter.
+ */
+int crypt_keyfile_device_read(struct crypt_device *cd,
+ const char *keyfile,
+ char **key, size_t *key_size_read,
+ uint64_t keyfile_offset,
+ size_t key_size,
+ uint32_t flags);
+
+/**
+ * Backward compatible crypt_keyfile_device_read() (with size_t offset).
+ */
+int crypt_keyfile_read(struct crypt_device *cd,
+ const char *keyfile,
+ char **key, size_t *key_size_read,
+ size_t keyfile_offset,
+ size_t key_size,
+ uint32_t flags);
+
+/** Read key only to the first end of line (\\n). */
+#define CRYPT_KEYFILE_STOP_EOL (UINT32_C(1) << 0)
+/** @} */
+
+/**
+ * @defgroup crypt-wipe Function to wipe device
+ * @addtogroup crypt-wipe
+ * @{
+ */
+/**
+ * Wipe pattern
+ */
+typedef enum {
+ CRYPT_WIPE_ZERO, /**< Fill with zeroes */
+ CRYPT_WIPE_RANDOM, /**< Use RNG to fill data */
+ CRYPT_WIPE_ENCRYPTED_ZERO, /**< Obsolete, same as CRYPT_WIPE_RANDOM */
+ CRYPT_WIPE_SPECIAL, /**< Compatibility only, do not use (Gutmann method) */
+} crypt_wipe_pattern;
+
+/**
+ * Wipe/Fill (part of) a device with the selected pattern.
+ *
+ * @param cd crypt device handle
+ * @param dev_path path to device to wipe or @e NULL if data device should be used
+ * @param pattern selected wipe pattern
+ * @param offset offset on device (in bytes)
+ * @param length length of area to be wiped (in bytes)
+ * @param wipe_block_size used block for wiping (one step) (in bytes)
+ * @param flags wipe flags
+ * @param progress callback function called after each @e wipe_block_size or @e NULL
+ * @param usrptr provided identification in callback
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @note A @e progress callback can interrupt wipe process by returning non-zero code.
+ *
+ * @note If the error values is -EIO or -EINTR, some part of the device could
+ * be overwritten. Other error codes (-EINVAL, -ENOMEM) means that no IO was performed.
+ */
+int crypt_wipe(struct crypt_device *cd,
+ const char *dev_path, /* if null, use data device */
+ crypt_wipe_pattern pattern,
+ uint64_t offset,
+ uint64_t length,
+ size_t wipe_block_size,
+ uint32_t flags,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr
+);
+
+/** Use direct-io */
+#define CRYPT_WIPE_NO_DIRECT_IO (UINT32_C(1) << 0)
+/** @} */
+
+/**
+ * @defgroup crypt-tokens LUKS2 token wrapper access
+ *
+ * Utilities for handling tokens LUKS2
+ * Token is a device or a method how to read password for particular keyslot
+ * automatically. It can be chunk of data stored on hardware token or
+ * just a metadata how to generate the password.
+ *
+ * @addtogroup crypt-tokens
+ * @{
+ */
+
+/**
+ * Get number of tokens supported for device type.
+ *
+ * @param type crypt device type
+ *
+ * @return token count or negative errno otherwise if device
+ * doesn't not support tokens.
+ *
+ * @note Real number of supported tokens for a particular device depends
+ * on usable metadata area size.
+ */
+int crypt_token_max(const char *type);
+
+/** Iterate through all tokens */
+#define CRYPT_ANY_TOKEN -1
+
+/**
+ * Get content of a token definition in JSON format.
+ *
+ * @param cd crypt device handle
+ * @param token token id
+ * @param json buffer with JSON
+ *
+ * @return allocated token id or negative errno otherwise.
+ */
+int crypt_token_json_get(struct crypt_device *cd,
+ int token,
+ const char **json);
+
+/**
+ * Store content of a token definition in JSON format.
+ *
+ * @param cd crypt device handle
+ * @param token token id or @e CRYPT_ANY_TOKEN to allocate new one
+ * @param json buffer with JSON or @e NULL to remove token
+ *
+ * @return allocated token id or negative errno otherwise.
+ *
+ * @note The buffer must be in proper JSON format and must contain at least
+ * string "type" with slot type and an array of string names "keyslots".
+ * Keyslots array contains assignments to particular slots and can be empty.
+ */
+int crypt_token_json_set(struct crypt_device *cd,
+ int token,
+ const char *json);
+
+/**
+ * Token info
+ */
+typedef enum {
+ CRYPT_TOKEN_INVALID, /**< token is invalid */
+ CRYPT_TOKEN_INACTIVE, /**< token is empty (free) */
+ CRYPT_TOKEN_INTERNAL, /**< active internal token with driver */
+ CRYPT_TOKEN_INTERNAL_UNKNOWN, /**< active internal token (reserved name) with missing token driver */
+ CRYPT_TOKEN_EXTERNAL, /**< active external (user defined) token with driver */
+ CRYPT_TOKEN_EXTERNAL_UNKNOWN, /**< active external (user defined) token with missing token driver */
+} crypt_token_info;
+
+/**
+ * Get info for specific token.
+ *
+ * @param cd crypt device handle
+ * @param token existing token id
+ * @param type pointer for returned type string
+ *
+ * @return token status info. For any returned status (besides CRYPT_TOKEN_INVALID
+ * and CRYPT_TOKEN_INACTIVE) and if type parameter is not NULL it will
+ * contain address of type string.
+ *
+ * @note if required, create a copy of string referenced in *type before calling next
+ * libcryptsetup API function. The reference may become invalid.
+ */
+crypt_token_info crypt_token_status(struct crypt_device *cd, int token, const char **type);
+
+/**
+ * LUKS2 keyring token parameters.
+ *
+ * @see crypt_token_builtin_set
+ *
+ */
+struct crypt_token_params_luks2_keyring {
+ const char *key_description; /**< Reference in keyring */
+};
+
+/**
+ * Create a new luks2 keyring token.
+ *
+ * @param cd crypt device handle
+ * @param token token id or @e CRYPT_ANY_TOKEN to allocate new one
+ * @param params luks2 keyring token params
+ *
+ * @return allocated token id or negative errno otherwise.
+ *
+ */
+int crypt_token_luks2_keyring_set(struct crypt_device *cd,
+ int token,
+ const struct crypt_token_params_luks2_keyring *params);
+
+/**
+ * Get LUKS2 keyring token params
+ *
+ * @param cd crypt device handle
+ * @param token existing luks2 keyring token id
+ * @param params returned luks2 keyring token params
+ *
+ * @return allocated token id or negative errno otherwise.
+ *
+ * @note do not call free() on params members. Members are valid only
+ * until next libcryptsetup function is called.
+ */
+int crypt_token_luks2_keyring_get(struct crypt_device *cd,
+ int token,
+ struct crypt_token_params_luks2_keyring *params);
+
+/**
+ * Assign a token to particular keyslot.
+ * (There can be more keyslots assigned to one token id.)
+ *
+ * @param cd crypt device handle
+ * @param token token id
+ * @param keyslot keyslot to be assigned to token (CRYPT_ANY SLOT
+ * assigns all active keyslots to token)
+ *
+ * @return allocated token id or negative errno otherwise.
+ */
+int crypt_token_assign_keyslot(struct crypt_device *cd,
+ int token,
+ int keyslot);
+
+/**
+ * Unassign a token from particular keyslot.
+ * (There can be more keyslots assigned to one token id.)
+ *
+ * @param cd crypt device handle
+ * @param token token id
+ * @param keyslot keyslot to be unassigned from token (CRYPT_ANY SLOT
+ * unassigns all active keyslots from token)
+ *
+ * @return allocated token id or negative errno otherwise.
+ */
+int crypt_token_unassign_keyslot(struct crypt_device *cd,
+ int token,
+ int keyslot);
+
+/**
+ * Get info about token assignment to particular keyslot.
+ *
+ * @param cd crypt device handle
+ * @param token token id
+ * @param keyslot keyslot
+ *
+ * @return 0 on success (token exists and is assigned to the keyslot),
+ * -ENOENT if token is not assigned to a keyslot (token, keyslot
+ * or both may be inactive) or other negative errno otherwise.
+ */
+int crypt_token_is_assigned(struct crypt_device *cd,
+ int token,
+ int keyslot);
+
+/**
+ * Token handler open function prototype.
+ * This function retrieves password from a token and return allocated buffer
+ * containing this password. This buffer has to be deallocated by calling
+ * free() function and content should be wiped before deallocation.
+ *
+ * @param cd crypt device handle
+ * @param token token id
+ * @param buffer returned allocated buffer with password
+ * @param buffer_len length of the buffer
+ * @param usrptr user data in @link crypt_activate_by_token @endlink
+ *
+ * @return 0 on success (token passed LUKS2 keyslot passphrase in buffer) or
+ * negative errno otherwise.
+ *
+ * @note Negative ENOANO errno means that token is PIN protected and caller should
+ * use @link crypt_activate_by_token_pin @endlink with PIN provided.
+ *
+ * @note Negative EAGAIN errno means token handler requires additional hardware
+ * not present in the system.
+ */
+typedef int (*crypt_token_open_func) (
+ struct crypt_device *cd,
+ int token,
+ char **buffer,
+ size_t *buffer_len,
+ void *usrptr);
+
+/**
+ * Token handler open with passphrase/PIN function prototype.
+ * This function retrieves password from a token and return allocated buffer
+ * containing this password. This buffer has to be deallocated by calling
+ * free() function and content should be wiped before deallocation.
+ *
+ * @param cd crypt device handle
+ * @param token token id
+ * @param pin passphrase (or PIN) to unlock token (may be binary data)
+ * @param pin_size size of @e pin
+ * @param buffer returned allocated buffer with password
+ * @param buffer_len length of the buffer
+ * @param usrptr user data in @link crypt_activate_by_token @endlink
+ *
+ * @return 0 on success (token passed LUKS2 keyslot passphrase in buffer) or
+ * negative errno otherwise.
+ *
+ * @note Negative ENOANO errno means that token is PIN protected and PIN was
+ * missing or wrong.
+ *
+ * @note Negative EAGAIN errno means token handler requires additional hardware
+ * not present in the system.
+ */
+typedef int (*crypt_token_open_pin_func) (
+ struct crypt_device *cd,
+ int token,
+ const char *pin,
+ size_t pin_size,
+ char **buffer,
+ size_t *buffer_len,
+ void *usrptr);
+
+/**
+ * Token handler buffer free function prototype.
+ * This function is used by library to free the buffer with keyslot
+ * passphrase when it's no longer needed. If not defined the library
+ * overwrites buffer with zeroes and call free().
+ *
+ * @param buffer the buffer with keyslot passphrase
+ * @param buffer_len the buffer length
+ */
+typedef void (*crypt_token_buffer_free_func) (void *buffer, size_t buffer_len);
+
+/**
+ * Token handler validate function prototype.
+ * This function validates JSON representation of user defined token for additional data
+ * specific for its token type. If defined in the handler, it's called
+ * during @link crypt_activate_by_token @endlink. It may also be called during
+ * @link crypt_token_json_set @endlink when appropriate token handler was registered before
+ * with @link crypt_token_register @endlink.
+ *
+ * @param cd crypt device handle
+ * @param json buffer with JSON
+ */
+typedef int (*crypt_token_validate_func) (struct crypt_device *cd, const char *json);
+
+/**
+ * Token handler dump function prototype.
+ * This function is supposed to print token implementation specific details. It gets
+ * called during @link crypt_dump @endlink if token handler was registered before.
+ *
+ * @param cd crypt device handle
+ * @param json buffer with token JSON
+ *
+ * @note dump implementations are advised to use @link crypt_log @endlink function
+ * to dump token details.
+ */
+typedef void (*crypt_token_dump_func) (struct crypt_device *cd, const char *json);
+
+/**
+ * Token handler version function prototype.
+ * This function is supposed to return pointer to version string information.
+ *
+ * @note The returned string is advised to contain only version.
+ * For example '1.0.0' or 'v1.2.3.4'.
+ *
+ */
+typedef const char * (*crypt_token_version_func) (void);
+
+/**
+ * Token handler
+ */
+typedef struct {
+ const char *name; /**< token handler name */
+ crypt_token_open_func open; /**< token handler open function */
+ crypt_token_buffer_free_func buffer_free; /**< token handler buffer_free function (optional) */
+ crypt_token_validate_func validate; /**< token handler validate function (optional) */
+ crypt_token_dump_func dump; /**< token handler dump function (optional) */
+} crypt_token_handler;
+
+/**
+ * Register token handler
+ *
+ * @param handler token handler to register
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_token_register(const crypt_token_handler *handler);
+
+/**
+ * Report configured path where library searches for external token handlers
+ *
+ * @return @e absolute path when external tokens are enabled or @e NULL otherwise.
+ */
+const char *crypt_token_external_path(void);
+
+/**
+ * Disable external token handlers (plugins) support
+ * If disabled, it cannot be enabled again.
+ */
+void crypt_token_external_disable(void);
+
+/** ABI version for external token in libcryptsetup-token-[name].so */
+#define CRYPT_TOKEN_ABI_VERSION1 "CRYPTSETUP_TOKEN_1.0"
+
+/** open by token - ABI exported symbol for external token (mandatory) */
+#define CRYPT_TOKEN_ABI_OPEN "cryptsetup_token_open"
+/** open by token with PIN - ABI exported symbol for external token */
+#define CRYPT_TOKEN_ABI_OPEN_PIN "cryptsetup_token_open_pin"
+/** deallocate callback - ABI exported symbol for external token */
+#define CRYPT_TOKEN_ABI_BUFFER_FREE "cryptsetup_token_buffer_free"
+/** validate token metadata - ABI exported symbol for external token */
+#define CRYPT_TOKEN_ABI_VALIDATE "cryptsetup_token_validate"
+/** dump token metadata - ABI exported symbol for external token */
+#define CRYPT_TOKEN_ABI_DUMP "cryptsetup_token_dump"
+/** token version - ABI exported symbol for external token */
+#define CRYPT_TOKEN_ABI_VERSION "cryptsetup_token_version"
+
+/**
+ * Activate device or check key using a token.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create, if @e NULL only check token
+ * @param token requested token to check or CRYPT_ANY_TOKEN to check all
+ * @param usrptr provided identification in callback
+ * @param flags activation flags
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ *
+ * @note EPERM errno means token provided passphrase successfully, but
+ * passphrase did not unlock any keyslot associated with the token.
+ *
+ * @note ENOENT errno means no token (or subsequently assigned keyslot) was
+ * eligible to unlock device.
+ *
+ * @note ENOANO errno means that token is PIN protected and you should call
+ * @link crypt_activate_by_token_pin @endlink with PIN
+ *
+ * @note Negative EAGAIN errno means token handler requires additional hardware
+ * not present in the system.
+ *
+ * @note with @e token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
+ * to unlock device using any available token. It may happen that various token handlers
+ * return different error codes. At the end loop returns error codes in the following
+ * order (from the most significant to the least) any negative errno except those
+ * listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
+ */
+int crypt_activate_by_token(struct crypt_device *cd,
+ const char *name,
+ int token,
+ void *usrptr,
+ uint32_t flags);
+
+/**
+ * Activate device or check key using a token with PIN.
+ *
+ * @param cd crypt device handle
+ * @param name name of device to create, if @e NULL only check token
+ * @param type restrict type of token, if @e NULL all types are allowed
+ * @param token requested token to check or CRYPT_ANY_TOKEN to check all
+ * @param pin passphrase (or PIN) to unlock token (may be binary data)
+ * @param pin_size size of @e pin
+ * @param usrptr provided identification in callback
+ * @param flags activation flags
+ *
+ * @return unlocked key slot number or negative errno otherwise.
+ *
+ * @note EPERM errno means token provided passphrase successfully, but
+ * passphrase did not unlock any keyslot associated with the token.
+ *
+ * @note ENOENT errno means no token (or subsequently assigned keyslot) was
+ * eligible to unlock device.
+ *
+ * @note ENOANO errno means that token is PIN protected and was either missing
+ * (NULL) or wrong.
+ *
+ * @note Negative EAGAIN errno means token handler requires additional hardware
+ * not present in the system.
+ *
+ * @note with @e token set to CRYPT_ANY_TOKEN libcryptsetup runs best effort loop
+ * to unlock device using any available token. It may happen that various token handlers
+ * return different error codes. At the end loop returns error codes in the following
+ * order (from the most significant to the least) any negative errno except those
+ * listed below, non negative token id (success), -ENOANO, -EAGAIN, -EPERM, -ENOENT.
+ */
+int crypt_activate_by_token_pin(struct crypt_device *cd,
+ const char *name,
+ const char *type,
+ int token,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr,
+ uint32_t flags);
+/** @} */
+
+/**
+ * @defgroup crypt-reencryption LUKS2 volume reencryption support
+ *
+ * Set of functions to handling LUKS2 volume reencryption
+ *
+ * @addtogroup crypt-reencryption
+ * @{
+ */
+
+/** Initialize reencryption metadata but do not run reencryption yet. (in) */
+#define CRYPT_REENCRYPT_INITIALIZE_ONLY (UINT32_C(1) << 0)
+/** Move the first segment, used only with datashift resilience mode
+ * and subvariants. (in/out) */
+#define CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT (UINT32_C(1) << 1)
+/** Resume already initialized reencryption only. (in) */
+#define CRYPT_REENCRYPT_RESUME_ONLY (UINT32_C(1) << 2)
+/** Run reencryption recovery only. (in) */
+#define CRYPT_REENCRYPT_RECOVERY (UINT32_C(1) << 3)
+/** Reencryption requires metadata protection. (in/out) */
+#define CRYPT_REENCRYPT_REPAIR_NEEDED (UINT32_C(1) << 4)
+
+/**
+ * Reencryption direction
+ */
+typedef enum {
+ CRYPT_REENCRYPT_FORWARD = 0, /**< forward direction */
+ CRYPT_REENCRYPT_BACKWARD /**< backward direction */
+} crypt_reencrypt_direction_info;
+
+/**
+ * Reencryption mode
+ */
+typedef enum {
+ CRYPT_REENCRYPT_REENCRYPT = 0, /**< Reencryption mode */
+ CRYPT_REENCRYPT_ENCRYPT, /**< Encryption mode */
+ CRYPT_REENCRYPT_DECRYPT, /**< Decryption mode */
+} crypt_reencrypt_mode_info;
+
+/**
+ * LUKS2 reencryption options.
+ */
+struct crypt_params_reencrypt {
+ crypt_reencrypt_mode_info mode; /**< Reencryption mode, immutable after first init. */
+ crypt_reencrypt_direction_info direction; /**< Reencryption direction, immutable after first init. */
+ const char *resilience; /**< Resilience mode: "none", "checksum", "journal", "datashift",
+ "datashift-checksum" or "datashift-journal".
+ "datashift" mode is immutable, "datashift-" subvariant can be only
+ changed to other "datashift-" subvariant */
+ const char *hash; /**< Used hash for "checksum" resilience type, ignored otherwise. */
+ uint64_t data_shift; /**< Used in "datashift" mode (and subvariants), must be non-zero,
+ immutable after first init. */
+ uint64_t max_hotzone_size; /**< Maximum hotzone size (may be lowered by library). For "datashift-" subvariants
+ it is used to set size of moved segment (decryption only). */
+ uint64_t device_size; /**< Reencrypt only initial part of the data device. */
+ const struct crypt_params_luks2 *luks2; /**< LUKS2 parameters for the final reencryption volume.*/
+ uint32_t flags; /**< Reencryption flags. */
+};
+
+/**
+ * Initialize reencryption metadata using passphrase.
+ *
+ * This function initializes on-disk metadata to include all reencryption segments,
+ * according to the provided options.
+ * If metadata already contains ongoing reencryption metadata, it loads these parameters
+ * (in this situation all parameters except @e name and @e passphrase can be omitted).
+ *
+ * @param cd crypt device handle
+ * @param name name of active device or @e NULL for offline reencryption
+ * @param passphrase passphrase used to unlock volume key
+ * @param passphrase_size size of @e passphrase (binary data)
+ * @param keyslot_old keyslot to unlock existing device or CRYPT_ANY_SLOT
+ * @param keyslot_new existing (unbound) reencryption keyslot; must be set except for decryption
+ * @param cipher cipher specification (e.g. "aes")
+ * @param cipher_mode cipher mode and IV (e.g. "xts-plain64")
+ * @param params reencryption parameters @link crypt_params_reencrypt @endlink.
+ *
+ * @return reencryption key slot number or negative errno otherwise.
+ */
+int crypt_reencrypt_init_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ int keyslot_old,
+ int keyslot_new,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct crypt_params_reencrypt *params);
+
+/**
+ * Initialize reencryption metadata using passphrase in keyring.
+ *
+ * This function initializes on-disk metadata to include all reencryption segments,
+ * according to the provided options.
+ * If metadata already contains ongoing reencryption metadata, it loads these parameters
+ * (in this situation all parameters except @e name and @e key_description can be omitted).
+ *
+ * @param cd crypt device handle
+ * @param name name of active device or @e NULL for offline reencryption
+ * @param key_description passphrase (key) identification in keyring
+ * @param keyslot_old keyslot to unlock existing device or CRYPT_ANY_SLOT
+ * @param keyslot_new existing (unbound) reencryption keyslot; must be set except for decryption
+ * @param cipher cipher specification (e.g. "aes")
+ * @param cipher_mode cipher mode and IV (e.g. "xts-plain64")
+ * @param params reencryption parameters @link crypt_params_reencrypt @endlink.
+ *
+ * @return reencryption key slot number or negative errno otherwise.
+ */
+int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
+ const char *name,
+ const char *key_description,
+ int keyslot_old,
+ int keyslot_new,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct crypt_params_reencrypt *params);
+
+/**
+ * Legacy data reencryption function.
+ *
+ * @param cd crypt device handle
+ * @param progress is a callback function reporting device \b size,
+ * current \b offset of reencryption and provided \b usrptr identification
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ *
+ * @deprecated Use @link crypt_reencrypt_run @endlink instead.
+ */
+int crypt_reencrypt(struct crypt_device *cd,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
+__attribute__((deprecated));
+
+/**
+ * Run data reencryption.
+ *
+ * @param cd crypt device handle
+ * @param progress is a callback function reporting device \b size,
+ * current \b offset of reencryption and provided \b usrptr identification
+ * @param usrptr progress specific data
+ *
+ * @return @e 0 on success or negative errno value otherwise.
+ */
+int crypt_reencrypt_run(struct crypt_device *cd,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr);
+
+/**
+ * Reencryption status info
+ */
+typedef enum {
+ CRYPT_REENCRYPT_NONE = 0, /**< No reencryption in progress */
+ CRYPT_REENCRYPT_CLEAN, /**< Ongoing reencryption in a clean state. */
+ CRYPT_REENCRYPT_CRASH, /**< Aborted reencryption that need internal recovery. */
+ CRYPT_REENCRYPT_INVALID /**< Invalid state. */
+} crypt_reencrypt_info;
+
+/**
+ * LUKS2 reencryption status.
+ *
+ * @param cd crypt device handle
+ * @param params reencryption parameters
+ *
+ * @return reencryption status info and parameters.
+ */
+crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd,
+ struct crypt_params_reencrypt *params);
+/** @} */
+
+/**
+ * @defgroup crypt-memory Safe memory helpers functions
+ * @addtogroup crypt-memory
+ * @{
+ */
+
+/**
+ * Allocate safe memory (content is safely wiped on deallocation).
+ *
+ * @param size size of memory in bytes
+ *
+ * @return pointer to allocated memory or @e NULL.
+ */
+void *crypt_safe_alloc(size_t size);
+
+/**
+ * Release safe memory, content is safely wiped.
+ * The pointer must be allocated with @link crypt_safe_alloc @endlink
+ *
+ * @param data pointer to memory to be deallocated
+ */
+void crypt_safe_free(void *data);
+
+/**
+ * Reallocate safe memory (content is copied and safely wiped on deallocation).
+ *
+ * @param data pointer to memory to be deallocated
+ * @param size new size of memory in bytes
+ *
+ * @return pointer to allocated memory or @e NULL.
+ */
+void *crypt_safe_realloc(void *data, size_t size);
+
+/**
+ * Safe clear memory area (compile should not compile this call out).
+ *
+ * @param data pointer to memory to be cleared
+ * @param size size of memory in bytes
+ */
+void crypt_safe_memzero(void *data, size_t size);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _LIBCRYPTSETUP_H */
diff --git a/lib/libcryptsetup.pc.in b/lib/libcryptsetup.pc.in
new file mode 100644
index 0000000..7836293
--- /dev/null
+++ b/lib/libcryptsetup.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: cryptsetup
+Description: cryptsetup library
+Version: @LIBCRYPTSETUP_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lcryptsetup
+Requires.private: @PKGMODULES@
diff --git a/lib/libcryptsetup.sym b/lib/libcryptsetup.sym
new file mode 100644
index 0000000..d0f0d98
--- /dev/null
+++ b/lib/libcryptsetup.sym
@@ -0,0 +1,167 @@
+CRYPTSETUP_2.0 {
+ global:
+ crypt_init;
+ crypt_init_data_device;
+ crypt_init_by_name;
+ crypt_init_by_name_and_header;
+
+ crypt_set_log_callback;
+ crypt_set_confirm_callback;
+ crypt_set_iteration_time;
+ crypt_set_uuid;
+ crypt_set_label;
+ crypt_set_data_device;
+
+ crypt_set_compatibility;
+ crypt_get_compatibility;
+
+ crypt_memory_lock;
+ crypt_metadata_locking;
+ crypt_format;
+ crypt_convert;
+ crypt_load;
+ crypt_repair;
+ crypt_resize;
+ crypt_suspend;
+ crypt_resume_by_passphrase;
+ crypt_resume_by_keyfile;
+ crypt_resume_by_keyfile_offset;
+ crypt_resume_by_keyfile_device_offset;
+ crypt_resume_by_volume_key;
+ crypt_free;
+
+ crypt_keyslot_add_by_passphrase;
+ crypt_keyslot_change_by_passphrase;
+ crypt_keyslot_add_by_keyfile;
+ crypt_keyslot_add_by_keyfile_offset;
+ crypt_keyslot_add_by_keyfile_device_offset;
+ crypt_keyslot_add_by_volume_key;
+ crypt_keyslot_add_by_key;
+
+ crypt_keyslot_set_priority;
+ crypt_keyslot_get_priority;
+
+ crypt_token_json_get;
+ crypt_token_json_set;
+ crypt_token_status;
+ crypt_token_luks2_keyring_get;
+ crypt_token_luks2_keyring_set;
+ crypt_token_assign_keyslot;
+ crypt_token_unassign_keyslot;
+ crypt_token_is_assigned;
+ crypt_token_register;
+
+ crypt_activate_by_token;
+
+ crypt_keyslot_destroy;
+ crypt_activate_by_passphrase;
+ crypt_activate_by_keyfile;
+ crypt_activate_by_keyfile_offset;
+ crypt_activate_by_keyfile_device_offset;
+ crypt_activate_by_volume_key;
+ crypt_activate_by_signed_key;
+ crypt_activate_by_keyring;
+ crypt_deactivate;
+ crypt_deactivate_by_name;
+ crypt_volume_key_get;
+ crypt_volume_key_verify;
+ crypt_volume_key_keyring;
+ crypt_status;
+ crypt_dump;
+ crypt_benchmark;
+ crypt_benchmark_pbkdf;
+ crypt_get_cipher;
+ crypt_get_cipher_mode;
+ crypt_get_integrity_info;
+ crypt_get_uuid;
+ crypt_set_data_offset;
+ crypt_get_data_offset;
+ crypt_get_iv_offset;
+ crypt_get_volume_key_size;
+ crypt_get_device_name;
+ crypt_get_metadata_device_name;
+ crypt_get_metadata_size;
+ crypt_set_metadata_size;
+ crypt_get_verity_info;
+ crypt_get_sector_size;
+
+ crypt_get_type;
+ crypt_get_default_type;
+ crypt_get_active_device;
+ crypt_get_active_integrity_failures;
+ crypt_persistent_flags_set;
+ crypt_persistent_flags_get;
+
+ crypt_set_rng_type;
+ crypt_get_rng_type;
+ crypt_set_pbkdf_type;
+ crypt_get_pbkdf_type;
+ crypt_get_pbkdf_type_params;
+ crypt_get_pbkdf_default;
+
+ crypt_keyslot_max;
+ crypt_keyslot_area;
+ crypt_keyslot_status;
+ crypt_keyslot_get_key_size;
+ crypt_keyslot_set_encryption;
+ crypt_keyslot_get_encryption;
+ crypt_keyslot_get_pbkdf;
+
+ crypt_get_dir;
+ crypt_set_debug_level;
+ crypt_log;
+
+ crypt_header_backup;
+ crypt_header_restore;
+
+ crypt_keyfile_read;
+ crypt_keyfile_device_read;
+
+ crypt_wipe;
+
+ crypt_reencrypt_init_by_passphrase;
+ crypt_reencrypt_init_by_keyring;
+ crypt_reencrypt;
+ crypt_reencrypt_status;
+
+ crypt_safe_alloc;
+ crypt_safe_realloc;
+ crypt_safe_free;
+ crypt_safe_memzero;
+ local:
+ *;
+};
+
+CRYPTSETUP_2.4 {
+ global:
+ crypt_reencrypt_run;
+ crypt_token_max;
+ crypt_header_is_detached;
+ crypt_logf;
+ crypt_activate_by_token_pin;
+ crypt_dump_json;
+ crypt_format;
+ crypt_token_external_disable;
+ crypt_token_external_path;
+} CRYPTSETUP_2.0;
+
+CRYPTSETUP_2.5 {
+ global:
+ crypt_get_label;
+ crypt_get_subsystem;
+ crypt_resume_by_token_pin;
+} CRYPTSETUP_2.4;
+
+CRYPTSETUP_2.6 {
+ global:
+ crypt_keyslot_context_free;
+ crypt_keyslot_context_init_by_passphrase;
+ crypt_keyslot_context_init_by_keyfile;
+ crypt_keyslot_context_init_by_token;
+ crypt_keyslot_context_init_by_volume_key;
+ crypt_keyslot_context_get_error;
+ crypt_keyslot_context_set_pin;
+ crypt_keyslot_context_get_type;
+ crypt_keyslot_add_by_keyslot_context;
+ crypt_volume_key_get_by_keyslot_context;
+} CRYPTSETUP_2.5;
diff --git a/lib/libcryptsetup_macros.h b/lib/libcryptsetup_macros.h
new file mode 100644
index 0000000..55187ab
--- /dev/null
+++ b/lib/libcryptsetup_macros.h
@@ -0,0 +1,70 @@
+/*
+ * Definitions of common constant and generic macros of libcryptsetup
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LIBCRYPTSETUP_MACROS_H
+#define _LIBCRYPTSETUP_MACROS_H
+
+/* to silent gcc -Wcast-qual for const cast */
+#define CONST_CAST(x) (x)(uintptr_t)
+
+/* to silent clang -Wcast-align when working with byte arrays */
+#define VOIDP_CAST(x) (x)(void*)
+
+#define UNUSED(x) (void)(x)
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+#define BITFIELD_SIZE(BF_PTR) (sizeof(*(BF_PTR)) * 8)
+
+#define MOVE_REF(x, y) \
+ do { \
+ __typeof__(x) *_px = &(x), *_py = &(y); \
+ *_px = *_py; \
+ *_py = NULL; \
+ } while (0)
+
+#define FREE_AND_NULL(x) do { free(x); x = NULL; } while (0)
+
+#define AT_LEAST(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
+
+#define SHIFT_4K 12
+#define SECTOR_SHIFT 9
+#define SECTOR_SIZE (1 << SECTOR_SHIFT)
+#define MAX_SECTOR_SIZE 4096 /* min page size among all platforms */
+#define ROUND_SECTOR(x) (((x) + SECTOR_SIZE - 1) / SECTOR_SIZE)
+
+#define MISALIGNED(a, b) ((a) & ((b) - 1))
+#define MISALIGNED_4K(a) MISALIGNED((a), 1 << SHIFT_4K)
+#define MISALIGNED_512(a) MISALIGNED((a), 1 << SECTOR_SHIFT)
+#define NOTPOW2(a) MISALIGNED((a), (a))
+
+#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
+#define DEFAULT_MEM_ALIGNMENT 4096
+
+#define DM_UUID_LEN 129
+#define DM_BY_ID_PREFIX "dm-uuid-"
+#define DM_BY_ID_PREFIX_LEN 8
+#define DM_UUID_PREFIX "CRYPT-"
+#define DM_UUID_PREFIX_LEN 6
+
+#endif /* _LIBCRYPTSETUP_MACROS_H */
diff --git a/lib/libcryptsetup_symver.h b/lib/libcryptsetup_symver.h
new file mode 100644
index 0000000..a5aa8f9
--- /dev/null
+++ b/lib/libcryptsetup_symver.h
@@ -0,0 +1,103 @@
+/*
+ * Helpers for defining versioned symbols
+ *
+ * Copyright (C) 2021-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LIBCRYPTSETUP_SYMVER_H
+#define _LIBCRYPTSETUP_SYMVER_H
+
+/*
+ * Note on usage:
+ *
+ * Do not use CRYPT_SYMBOL_EXPORT_NEW and CRYPT_SYMBOL_EXPORT_OLD on public
+ * symbols being exported only once. Linker will handle it automatically as
+ * always.
+ *
+ * It's supposed to be used only with symbols that are exported in at least
+ * two versions simultaneously as follows:
+ *
+ * - the latest version is marked with _NEW variant and all other compatible
+ * symbols should be marked with _OLD variant
+ *
+ * Examples:
+ *
+ * - int crypt_func_X(unsigned *x, long y) gets introduced in CRYPTSETUP_2.4.
+ *
+ * No need to use any macro referenced here, just add proper version
+ * mapping in libcryptsetup.sym file.
+ *
+ * In later version CRYPTSETUP_2.5 symbol crypt_func_X has to fixed
+ * in incompatible way by adding new function parameter. The new version
+ * has to be added in mapping file libcryptsetup.sym as well.
+ *
+ * The definition of compatible function gets prefixed with following macro:
+ *
+ * CRYPT_SYMBOL_EXPORT_OLD(int, crypt_func_X, 2, 4,
+ * unsigned *x, long y)
+ * {
+ * function body
+ * }
+ *
+ * Whereas new version introduced in CRYPTSETUP_2.5 is defined as follows:
+ *
+ * CRYPT_SYMBOL_EXPORT_NEW(int, crypt_func_X, 2, 5,
+ * unsigned *x, long y, void *new_parameter)
+ * {
+ * function body
+ * }
+ *
+ * If in later version CRYPTSETUP_2.6 yet another version of crypt_func_X gets
+ * introduced it will be prefixed with CRYPT_SYMBOL_EXPORT_NEW(int, crypt_func_X, 2, 6...)
+ * macro and all previous versions CRYPTSETUP_2.4 and CRYPTSETUP_2.5 will be
+ * under CRYPT_SYMBOL_EXPORT_OLD(int, crypt_func_X, ...) macro
+ */
+
+#if HAVE_ATTRIBUTE_SYMVER
+# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
+ __attribute__((__symver__(#_public_sym _ver_str #_maj "." #_min)))
+#endif
+
+#if !defined(_CRYPT_SYMVER) && (defined(__GNUC__) || defined(__clang__))
+# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
+ __asm__(".symver " #_local_sym "," #_public_sym _ver_str #_maj "." #_min);
+#endif
+
+#define _CRYPT_FUNC(_public_sym, _prefix_str, _maj, _min, _ret, ...) \
+ _ret __##_public_sym##_v##_maj##_##_min(__VA_ARGS__); \
+ _CRYPT_SYMVER(__##_public_sym##_v##_maj##_##_min, _public_sym, _prefix_str "CRYPTSETUP_", _maj, _min) \
+ _ret __##_public_sym##_v##_maj##_##_min(__VA_ARGS__)
+
+#ifdef _CRYPT_SYMVER
+
+# define CRYPT_SYMBOL_EXPORT_OLD(_ret, _public_sym, _maj, _min, ...) \
+ _CRYPT_FUNC(_public_sym, "@", _maj, _min, _ret, __VA_ARGS__)
+# define CRYPT_SYMBOL_EXPORT_NEW(_ret, _public_sym, _maj, _min, ...) \
+ _CRYPT_FUNC(_public_sym, "@@", _maj, _min, _ret, __VA_ARGS__)
+
+#else /* no support for symbol versioning at all */
+
+# define CRYPT_SYMBOL_EXPORT_OLD(_ret, _public_sym, _maj, _min, ...) \
+ static inline __attribute__((unused)) \
+ _ret __##_public_sym##_v##_maj##_##_min(__VA_ARGS__)
+
+# define CRYPT_SYMBOL_EXPORT_NEW(_ret, _public_sym, _maj, _min, ...) \
+ _ret _public_sym(__VA_ARGS__)
+
+#endif
+
+#endif /* _LIBCRYPTSETUP_SYMVER_H */
diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c
new file mode 100644
index 0000000..9c5fc0c
--- /dev/null
+++ b/lib/libdevmapper.c
@@ -0,0 +1,3181 @@
+/*
+ * libdevmapper - device-mapper backend for cryptsetup
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libdevmapper.h>
+#include <uuid/uuid.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+#include "internal.h"
+
+#define DM_CRYPT_TARGET "crypt"
+#define DM_VERITY_TARGET "verity"
+#define DM_INTEGRITY_TARGET "integrity"
+#define DM_LINEAR_TARGET "linear"
+#define DM_ERROR_TARGET "error"
+#define DM_ZERO_TARGET "zero"
+#define RETRY_COUNT 5
+
+/* Set if DM target versions were probed */
+static bool _dm_ioctl_checked = false;
+static bool _dm_crypt_checked = false;
+static bool _dm_verity_checked = false;
+static bool _dm_integrity_checked = false;
+static bool _dm_zero_checked = false;
+
+static int _quiet_log = 0;
+static uint32_t _dm_flags = 0;
+
+static struct crypt_device *_context = NULL;
+static int _dm_use_count = 0;
+
+/* Check if we have DM flag to instruct kernel to force wipe buffers */
+#if !HAVE_DECL_DM_TASK_SECURE_DATA
+static int dm_task_secure_data(struct dm_task *dmt) { return 1; }
+#endif
+
+/* Compatibility for old device-mapper without udev support */
+#if HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG
+#define CRYPT_TEMP_UDEV_FLAGS DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG | \
+ DM_UDEV_DISABLE_DISK_RULES_FLAG | \
+ DM_UDEV_DISABLE_OTHER_RULES_FLAG
+#define _dm_task_set_cookie dm_task_set_cookie
+#define _dm_udev_wait dm_udev_wait
+#else
+#define CRYPT_TEMP_UDEV_FLAGS 0
+static int _dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { return 0; }
+static int _dm_udev_wait(uint32_t cookie) { return 0; };
+#endif
+
+static int _dm_use_udev(void)
+{
+#ifdef USE_UDEV /* cannot be enabled if devmapper is too old */
+ return dm_udev_get_sync_support();
+#else
+ return 0;
+#endif
+}
+
+__attribute__((format(printf, 4, 5)))
+static void set_dm_error(int level,
+ const char *file __attribute__((unused)),
+ int line __attribute__((unused)),
+ const char *f, ...)
+{
+ char *msg = NULL;
+ va_list va;
+
+ va_start(va, f);
+ if (vasprintf(&msg, f, va) > 0) {
+ if (level < 4 && !_quiet_log) {
+ log_err(_context, "%s", msg);
+ } else {
+ /* We do not use DM visual stack backtrace here */
+ if (strncmp(msg, "<backtrace>", 11))
+ log_dbg(_context, "%s", msg);
+ }
+ }
+ free(msg);
+ va_end(va);
+}
+
+static int _dm_satisfies_version(unsigned target_maj, unsigned target_min, unsigned target_patch,
+ unsigned actual_maj, unsigned actual_min, unsigned actual_patch)
+{
+ if (actual_maj > target_maj)
+ return 1;
+
+ if (actual_maj == target_maj && actual_min > target_min)
+ return 1;
+
+ if (actual_maj == target_maj && actual_min == target_min && actual_patch >= target_patch)
+ return 1;
+
+ return 0;
+}
+
+static void _dm_set_crypt_compat(struct crypt_device *cd,
+ unsigned crypt_maj,
+ unsigned crypt_min,
+ unsigned crypt_patch)
+{
+ if (_dm_crypt_checked || crypt_maj == 0)
+ return;
+
+ log_dbg(cd, "Detected dm-crypt version %i.%i.%i.",
+ crypt_maj, crypt_min, crypt_patch);
+
+ if (_dm_satisfies_version(1, 2, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_KEY_WIPE_SUPPORTED;
+ else
+ log_dbg(cd, "Suspend and resume disabled, no wipe key support.");
+
+ if (_dm_satisfies_version(1, 10, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_LMK_SUPPORTED;
+
+ /* not perfect, 2.6.33 supports with 1.7.0 */
+ if (_dm_satisfies_version(1, 8, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_PLAIN64_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 11, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_DISCARDS_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 13, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_TCW_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 14, 0, crypt_maj, crypt_min, crypt_patch)) {
+ _dm_flags |= DM_SAME_CPU_CRYPT_SUPPORTED;
+ _dm_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED;
+ }
+
+ if (_dm_satisfies_version(1, 18, 1, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_KERNEL_KEYRING_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 17, 0, crypt_maj, crypt_min, crypt_patch)) {
+ _dm_flags |= DM_SECTOR_SIZE_SUPPORTED;
+ _dm_flags |= DM_CAPI_STRING_SUPPORTED;
+ }
+
+ if (_dm_satisfies_version(1, 19, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_BITLK_EBOIV_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 20, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_BITLK_ELEPHANT_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 22, 0, crypt_maj, crypt_min, crypt_patch))
+ _dm_flags |= DM_CRYPT_NO_WORKQUEUE_SUPPORTED;
+
+ _dm_crypt_checked = true;
+}
+
+static void _dm_set_verity_compat(struct crypt_device *cd,
+ unsigned verity_maj,
+ unsigned verity_min,
+ unsigned verity_patch)
+{
+ if (_dm_verity_checked || verity_maj == 0)
+ return;
+
+ log_dbg(cd, "Detected dm-verity version %i.%i.%i.",
+ verity_maj, verity_min, verity_patch);
+
+ _dm_flags |= DM_VERITY_SUPPORTED;
+
+ /*
+ * ignore_corruption, restart_on corruption is available since 1.2 (kernel 4.1)
+ * ignore_zero_blocks since 1.3 (kernel 4.5)
+ * (but some dm-verity targets 1.2 don't support it)
+ * FEC is added in 1.3 as well.
+ * Check at most once is added in 1.4 (kernel 4.17).
+ */
+ if (_dm_satisfies_version(1, 3, 0, verity_maj, verity_min, verity_patch)) {
+ _dm_flags |= DM_VERITY_ON_CORRUPTION_SUPPORTED;
+ _dm_flags |= DM_VERITY_FEC_SUPPORTED;
+ }
+
+ if (_dm_satisfies_version(1, 5, 0, verity_maj, verity_min, verity_patch))
+ _dm_flags |= DM_VERITY_SIGNATURE_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch))
+ _dm_flags |= DM_VERITY_PANIC_CORRUPTION_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 9, 0, verity_maj, verity_min, verity_patch))
+ _dm_flags |= DM_VERITY_TASKLETS_SUPPORTED;
+
+ _dm_verity_checked = true;
+}
+
+static void _dm_set_integrity_compat(struct crypt_device *cd,
+ unsigned integrity_maj,
+ unsigned integrity_min,
+ unsigned integrity_patch)
+{
+ if (_dm_integrity_checked || integrity_maj == 0)
+ return;
+
+ log_dbg(cd, "Detected dm-integrity version %i.%i.%i.",
+ integrity_maj, integrity_min, integrity_patch);
+
+ _dm_flags |= DM_INTEGRITY_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 2, 0, integrity_maj, integrity_min, integrity_patch))
+ _dm_flags |= DM_INTEGRITY_RECALC_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 3, 0, integrity_maj, integrity_min, integrity_patch))
+ _dm_flags |= DM_INTEGRITY_BITMAP_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch))
+ _dm_flags |= DM_INTEGRITY_FIX_PADDING_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 6, 0, integrity_maj, integrity_min, integrity_patch))
+ _dm_flags |= DM_INTEGRITY_DISCARDS_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 7, 0, integrity_maj, integrity_min, integrity_patch))
+ _dm_flags |= DM_INTEGRITY_FIX_HMAC_SUPPORTED;
+
+ if (_dm_satisfies_version(1, 8, 0, integrity_maj, integrity_min, integrity_patch))
+ _dm_flags |= DM_INTEGRITY_RESET_RECALC_SUPPORTED;
+
+ _dm_integrity_checked = true;
+}
+
+static void _dm_set_zero_compat(struct crypt_device *cd,
+ unsigned zero_maj,
+ unsigned zero_min,
+ unsigned zero_patch)
+{
+ if (_dm_zero_checked || zero_maj == 0)
+ return;
+
+ log_dbg(cd, "Detected dm-zero version %i.%i.%i.",
+ zero_maj, zero_min, zero_patch);
+
+ _dm_zero_checked = true;
+}
+
+/* We use this for loading target module */
+static void _dm_check_target(dm_target_type target_type)
+{
+#if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION
+ struct dm_task *dmt;
+ const char *target_name = NULL;
+
+ if (!(_dm_flags & DM_GET_TARGET_VERSION_SUPPORTED))
+ return;
+
+ if (target_type == DM_CRYPT)
+ target_name = DM_CRYPT_TARGET;
+ else if (target_type == DM_VERITY)
+ target_name = DM_VERITY_TARGET;
+ else if (target_type == DM_INTEGRITY)
+ target_name = DM_INTEGRITY_TARGET;
+ else
+ return;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_GET_TARGET_VERSION)))
+ return;
+
+ if (dm_task_set_name(dmt, target_name))
+ dm_task_run(dmt);
+
+ dm_task_destroy(dmt);
+#endif
+}
+
+static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_type)
+{
+ struct dm_task *dmt;
+ struct dm_versions *target, *last_target;
+ char dm_version[16];
+ unsigned dm_maj, dm_min, dm_patch;
+ int r = 0;
+
+ if ((target_type == DM_CRYPT && _dm_crypt_checked) ||
+ (target_type == DM_VERITY && _dm_verity_checked) ||
+ (target_type == DM_INTEGRITY && _dm_integrity_checked) ||
+ (target_type == DM_ZERO && _dm_zero_checked) ||
+ (target_type == DM_LINEAR) ||
+ (_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked))
+ return 1;
+
+ /* Shut up DM while checking */
+ _quiet_log = 1;
+
+ _dm_check_target(target_type);
+
+ if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+ goto out;
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version)))
+ goto out;
+
+ if (!_dm_ioctl_checked) {
+ if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3)
+ goto out;
+ log_dbg(cd, "Detected dm-ioctl version %u.%u.%u.", dm_maj, dm_min, dm_patch);
+
+ if (_dm_satisfies_version(4, 20, 0, dm_maj, dm_min, dm_patch))
+ _dm_flags |= DM_SECURE_SUPPORTED;
+#if HAVE_DECL_DM_TASK_DEFERRED_REMOVE
+ if (_dm_satisfies_version(4, 27, 0, dm_maj, dm_min, dm_patch))
+ _dm_flags |= DM_DEFERRED_SUPPORTED;
+#endif
+#if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION
+ if (_dm_satisfies_version(4, 41, 0, dm_maj, dm_min, dm_patch))
+ _dm_flags |= DM_GET_TARGET_VERSION_SUPPORTED;
+#endif
+ }
+
+ target = dm_task_get_versions(dmt);
+ do {
+ last_target = target;
+ if (!strcmp(DM_CRYPT_TARGET, target->name)) {
+ _dm_set_crypt_compat(cd, (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ } else if (!strcmp(DM_VERITY_TARGET, target->name)) {
+ _dm_set_verity_compat(cd, (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ } else if (!strcmp(DM_INTEGRITY_TARGET, target->name)) {
+ _dm_set_integrity_compat(cd, (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ } else if (!strcmp(DM_ZERO_TARGET, target->name)) {
+ _dm_set_zero_compat(cd, (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ }
+ target = VOIDP_CAST(struct dm_versions *)((char *) target + target->next);
+ } while (last_target != target);
+
+ r = 1;
+ if (!_dm_ioctl_checked)
+ log_dbg(cd, "Device-mapper backend running with UDEV support %sabled.",
+ _dm_use_udev() ? "en" : "dis");
+
+ _dm_ioctl_checked = true;
+out:
+ if (dmt)
+ dm_task_destroy(dmt);
+
+ _quiet_log = 0;
+ return r;
+}
+
+int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags)
+{
+ _dm_check_versions(cd, target);
+ *flags = _dm_flags;
+
+ if (target == DM_UNKNOWN &&
+ _dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked)
+ return 0;
+
+ if ((target == DM_CRYPT && _dm_crypt_checked) ||
+ (target == DM_VERITY && _dm_verity_checked) ||
+ (target == DM_INTEGRITY && _dm_integrity_checked) ||
+ (target == DM_ZERO && _dm_zero_checked) ||
+ (target == DM_LINEAR)) /* nothing to check */
+ return 0;
+
+ return -ENODEV;
+}
+
+/* This doesn't run any kernel checks, just set up userspace libdevmapper */
+void dm_backend_init(struct crypt_device *cd)
+{
+ if (!_dm_use_count++) {
+ log_dbg(cd, "Initialising device-mapper backend library.");
+ dm_log_init(set_dm_error);
+ dm_log_init_verbose(10);
+ }
+}
+
+void dm_backend_exit(struct crypt_device *cd)
+{
+ if (_dm_use_count && (!--_dm_use_count)) {
+ log_dbg(cd, "Releasing device-mapper backend.");
+ dm_log_init_verbose(0);
+ dm_log_init(NULL);
+ dm_lib_release();
+ }
+}
+
+/* libdevmapper is not context friendly, switch context on every DM call. */
+static int dm_init_context(struct crypt_device *cd, dm_target_type target)
+{
+ _context = cd;
+ if (!_dm_check_versions(cd, target)) {
+ if (getuid() || geteuid())
+ log_err(cd, _("Cannot initialize device-mapper, "
+ "running as non-root user."));
+ else
+ log_err(cd, _("Cannot initialize device-mapper. "
+ "Is dm_mod kernel module loaded?"));
+ _context = NULL;
+ return -ENOTSUP;
+ }
+ return 0;
+}
+static void dm_exit_context(void)
+{
+ _context = NULL;
+}
+
+/* Return path to DM device */
+char *dm_device_path(const char *prefix, int major, int minor)
+{
+ struct dm_task *dmt;
+ const char *name;
+ char path[PATH_MAX];
+
+ if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
+ return NULL;
+ if (!dm_task_set_minor(dmt, minor) ||
+ !dm_task_set_major(dmt, major) ||
+ !dm_task_no_flush(dmt) ||
+ !dm_task_run(dmt) ||
+ !(name = dm_task_get_name(dmt))) {
+ dm_task_destroy(dmt);
+ return NULL;
+ }
+
+ if (snprintf(path, sizeof(path), "%s%s", prefix ?: "", name) < 0)
+ path[0] = '\0';
+
+ dm_task_destroy(dmt);
+
+ return strdup(path);
+}
+
+char *dm_device_name(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st) < 0 || !S_ISBLK(st.st_mode))
+ return NULL;
+
+ return dm_device_path(NULL, major(st.st_rdev), minor(st.st_rdev));
+}
+
+static size_t int_log10(uint64_t x)
+{
+ uint64_t r = 0;
+ for (x /= 10; x > 0; x /= 10)
+ r++;
+ return r;
+}
+
+static int cipher_dm2c(const char *org_c, const char *org_i, unsigned tag_size,
+ char *c_dm, int c_dm_size,
+ char *i_dm, int i_dm_size)
+{
+ int c_size = 0, i_size = 0, i;
+ char cipher[MAX_CAPI_ONE_LEN], mode[MAX_CAPI_ONE_LEN], iv[MAX_CAPI_ONE_LEN+1],
+ tmp[MAX_CAPI_ONE_LEN], capi[MAX_CAPI_LEN];
+
+ if (!c_dm || !c_dm_size || !i_dm || !i_dm_size)
+ return -EINVAL;
+
+ i = sscanf(org_c, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", cipher, tmp);
+ if (i != 2)
+ return -EINVAL;
+
+ i = sscanf(tmp, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", mode, iv);
+ if (i == 1) {
+ memset(iv, 0, sizeof(iv));
+ strncpy(iv, mode, sizeof(iv)-1);
+ *mode = '\0';
+ if (snprintf(capi, sizeof(capi), "%s", cipher) < 0)
+ return -EINVAL;
+ } else if (i == 2) {
+ if (snprintf(capi, sizeof(capi), "%s(%s)", mode, cipher) < 0)
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ if (!org_i) {
+ /* legacy mode: CIPHER-MODE-IV*/
+ i_size = snprintf(i_dm, i_dm_size, "%s", "");
+ c_size = snprintf(c_dm, c_dm_size, "%s", org_c);
+ } else if (!strcmp(org_i, "none")) {
+ /* IV only: capi:MODE(CIPHER)-IV */
+ i_size = snprintf(i_dm, i_dm_size, " integrity:%u:none", tag_size);
+ c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv);
+ } else if (!strcmp(org_i, "aead") && !strcmp(mode, "ccm")) {
+ /* CCM AEAD: capi:rfc4309(MODE(CIPHER))-IV */
+ i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
+ c_size = snprintf(c_dm, c_dm_size, "capi:rfc4309(%s)-%s", capi, iv);
+ } else if (!strcmp(org_i, "aead")) {
+ /* AEAD: capi:MODE(CIPHER))-IV */
+ i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
+ c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv);
+ } else if (!strcmp(org_i, "poly1305")) {
+ /* POLY1305 AEAD: capi:rfc7539(MODE(CIPHER),POLY1305)-IV */
+ i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
+ c_size = snprintf(c_dm, c_dm_size, "capi:rfc7539(%s,poly1305)-%s", capi, iv);
+ } else {
+ /* other AEAD: capi:authenc(<AUTH>,MODE(CIPHER))-IV */
+ i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
+ c_size = snprintf(c_dm, c_dm_size, "capi:authenc(%s,%s)-%s", org_i, capi, iv);
+ }
+
+ if (c_size < 0 || c_size == c_dm_size)
+ return -EINVAL;
+ if (i_size < 0 || i_size == i_dm_size)
+ return -EINVAL;
+
+ return 0;
+}
+
+static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u)
+{
+ size_t r = snprintf(buf, buf_size, " %s:%u", s, u);
+ assert(r > 0 && r < buf_size);
+ return buf;
+}
+
+/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */
+static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
+{
+ int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0;
+ char *params = NULL, *hexkey = NULL;
+ char sector_feature[32], features[512], integrity_dm[256], cipher_dm[256];
+
+ if (!tgt)
+ return NULL;
+
+ r = cipher_dm2c(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size,
+ cipher_dm, sizeof(cipher_dm), integrity_dm, sizeof(integrity_dm));
+ if (r < 0)
+ return NULL;
+
+ if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS)
+ num_options++;
+ if (tgt->u.crypt.integrity)
+ num_options++;
+ if (tgt->u.crypt.sector_size != SECTOR_SIZE)
+ num_options++;
+
+ if (num_options) { /* MAX length int32 + 15 + 15 + 23 + 18 + 19 + 17 + 13 + int32 + integrity_str */
+ r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s%s", num_options,
+ (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "",
+ (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "",
+ (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "",
+ (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE) ? " no_read_workqueue" : "",
+ (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) ? " no_write_workqueue" : "",
+ (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) ? " iv_large_sectors" : "",
+ (tgt->u.crypt.sector_size != SECTOR_SIZE) ?
+ _uf(sector_feature, sizeof(sector_feature), "sector_size", tgt->u.crypt.sector_size) : "",
+ integrity_dm);
+ if (r < 0 || (size_t)r >= sizeof(features))
+ goto out;
+ } else
+ *features = '\0';
+
+ if (crypt_is_cipher_null(cipher_dm))
+ null_cipher = 1;
+
+ if (null_cipher)
+ hexkey = crypt_bytes_to_hex(0, NULL);
+ else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
+ keystr_len = strlen(tgt->u.crypt.vk->key_description) + int_log10(tgt->u.crypt.vk->keylength) + 10;
+ hexkey = crypt_safe_alloc(keystr_len);
+ if (!hexkey)
+ goto out;
+ r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description);
+ if (r < 0 || r >= keystr_len)
+ goto out;
+ } else
+ hexkey = crypt_bytes_to_hex(tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key);
+
+ if (!hexkey)
+ goto out;
+
+ max_size = strlen(hexkey) + strlen(cipher_dm) +
+ strlen(device_block_path(tgt->data_device)) +
+ strlen(features) + 64;
+ params = crypt_safe_alloc(max_size);
+ if (!params)
+ goto out;
+
+ r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s",
+ cipher_dm, hexkey, tgt->u.crypt.iv_offset,
+ device_block_path(tgt->data_device), tgt->u.crypt.offset,
+ features);
+ if (r < 0 || r >= max_size) {
+ crypt_safe_free(params);
+ params = NULL;
+ }
+out:
+ crypt_safe_free(hexkey);
+ return params;
+}
+
+/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */
+static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
+{
+ int max_size, max_fec_size, max_verify_size, r, num_options = 0;
+ struct crypt_params_verity *vp;
+ char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
+ char features[256], *fec_features = NULL, *verity_verify_args = NULL;
+
+ if (!tgt || !tgt->u.verity.vp)
+ return NULL;
+
+ vp = tgt->u.verity.vp;
+
+ /* These flags are not compatible */
+ if ((flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) &&
+ (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION))
+ flags &= ~CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
+ if ((flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) &&
+ (flags & (CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)))
+ flags &= ~CRYPT_ACTIVATE_IGNORE_CORRUPTION;
+
+ if (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_TASKLETS)
+ num_options++;
+
+ max_fec_size = (tgt->u.verity.fec_device ? strlen(device_block_path(tgt->u.verity.fec_device)) : 0) + 256;
+ fec_features = crypt_safe_alloc(max_fec_size);
+ if (!fec_features)
+ goto out;
+
+ if (tgt->u.verity.fec_device) { /* MAX length 21 + path + 11 + int64 + 12 + int64 + 11 + int32 */
+ num_options += 8;
+ r = snprintf(fec_features, max_fec_size,
+ " use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 " fec_roots %" PRIu32,
+ device_block_path(tgt->u.verity.fec_device), tgt->u.verity.fec_offset,
+ tgt->u.verity.fec_blocks, vp->fec_roots);
+ if (r < 0 || r >= max_fec_size)
+ goto out;
+ } else
+ *fec_features = '\0';
+
+ max_verify_size = (tgt->u.verity.root_hash_sig_key_desc ? strlen(tgt->u.verity.root_hash_sig_key_desc) : 0) + 32;
+ verity_verify_args = crypt_safe_alloc(max_verify_size);
+ if (!verity_verify_args)
+ goto out;
+ if (tgt->u.verity.root_hash_sig_key_desc) { /* MAX length 24 + key_str */
+ num_options += 2;
+ r = snprintf(verity_verify_args, max_verify_size,
+ " root_hash_sig_key_desc %s", tgt->u.verity.root_hash_sig_key_desc);
+ if (r < 0 || r >= max_verify_size)
+ goto out;
+ } else
+ *verity_verify_args = '\0';
+
+ if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 + 22 */
+ r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s", num_options,
+ (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "",
+ (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "",
+ (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? " panic_on_corruption" : "",
+ (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "",
+ (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "",
+ (flags & CRYPT_ACTIVATE_TASKLETS) ? " try_verify_in_tasklet" : "");
+ if (r < 0 || (size_t)r >= sizeof(features))
+ goto out;
+ } else
+ *features = '\0';
+
+ hexroot = crypt_bytes_to_hex(tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
+ if (!hexroot)
+ goto out;
+
+ hexsalt = crypt_bytes_to_hex(vp->salt_size, vp->salt);
+ if (!hexsalt)
+ goto out;
+
+ max_size = strlen(hexroot) + strlen(hexsalt) +
+ strlen(device_block_path(tgt->data_device)) +
+ strlen(device_block_path(tgt->u.verity.hash_device)) +
+ strlen(vp->hash_name) + strlen(features) + strlen(fec_features) + 128 +
+ strlen(verity_verify_args);
+
+ params = crypt_safe_alloc(max_size);
+ if (!params)
+ goto out;
+
+ r = snprintf(params, max_size,
+ "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s%s%s%s",
+ vp->hash_type, device_block_path(tgt->data_device),
+ device_block_path(tgt->u.verity.hash_device),
+ vp->data_block_size, vp->hash_block_size,
+ vp->data_size, tgt->u.verity.hash_offset,
+ vp->hash_name, hexroot, hexsalt, features, fec_features,
+ verity_verify_args);
+ if (r < 0 || r >= max_size) {
+ crypt_safe_free(params);
+ params = NULL;
+ }
+out:
+ crypt_safe_free(fec_features);
+ crypt_safe_free(verity_verify_args);
+ crypt_safe_free(hexroot);
+ crypt_safe_free(hexsalt);
+ return params;
+}
+
+static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags)
+{
+ int r, max_size, max_integrity, max_journal_integrity, max_journal_crypt, num_options = 0;
+ char *params_out = NULL, *params, *hexkey, mode, feature[6][32];
+ char *features, *integrity, *journal_integrity, *journal_crypt;
+
+ if (!tgt)
+ return NULL;
+
+ max_integrity = (tgt->u.integrity.integrity && tgt->u.integrity.vk ? tgt->u.integrity.vk->keylength * 2 : 0) +
+ (tgt->u.integrity.integrity ? strlen(tgt->u.integrity.integrity) : 0) + 32;
+ max_journal_integrity = (tgt->u.integrity.journal_integrity && tgt->u.integrity.journal_integrity_key ?
+ tgt->u.integrity.journal_integrity_key->keylength * 2 : 0) +
+ (tgt->u.integrity.journal_integrity ? strlen(tgt->u.integrity.journal_integrity) : 0) + 32;
+ max_journal_crypt = (tgt->u.integrity.journal_crypt && tgt->u.integrity.journal_crypt_key ?
+ tgt->u.integrity.journal_crypt_key->keylength * 2 : 0) +
+ (tgt->u.integrity.journal_crypt ? strlen(tgt->u.integrity.journal_crypt) : 0) + 32;
+ max_size = strlen(device_block_path(tgt->data_device)) +
+ (tgt->u.integrity.meta_device ? strlen(device_block_path(tgt->u.integrity.meta_device)) : 0) +
+ max_integrity + max_journal_integrity + max_journal_crypt + 512;
+
+ params = crypt_safe_alloc(max_size);
+ features = crypt_safe_alloc(max_size);
+ integrity = crypt_safe_alloc(max_integrity);
+ journal_integrity = crypt_safe_alloc(max_journal_integrity);
+ journal_crypt = crypt_safe_alloc(max_journal_crypt);
+ if (!params || !features || !integrity || !journal_integrity || !journal_crypt)
+ goto out;
+
+ if (tgt->u.integrity.integrity) { /* MAX length 16 + str_integrity + str_key */
+ num_options++;
+
+ if (tgt->u.integrity.vk) {
+ hexkey = crypt_bytes_to_hex(tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
+ if (!hexkey)
+ goto out;
+ } else
+ hexkey = NULL;
+
+ r = snprintf(integrity, max_integrity, " internal_hash:%s%s%s",
+ tgt->u.integrity.integrity, hexkey ? ":" : "", hexkey ?: "");
+ crypt_safe_free(hexkey);
+ if (r < 0 || r >= max_integrity)
+ goto out;
+ }
+
+ if (tgt->u.integrity.journal_integrity) { /* MAX length 14 + str_journal_integrity + str_key */
+ num_options++;
+
+ if (tgt->u.integrity.journal_integrity_key) {
+ hexkey = crypt_bytes_to_hex( tgt->u.integrity.journal_integrity_key->keylength,
+ tgt->u.integrity.journal_integrity_key->key);
+ if (!hexkey)
+ goto out;
+ } else
+ hexkey = NULL;
+
+ r = snprintf(journal_integrity, max_journal_integrity, " journal_mac:%s%s%s",
+ tgt->u.integrity.journal_integrity, hexkey ? ":" : "", hexkey ?: "");
+ crypt_safe_free(hexkey);
+ if (r < 0 || r >= max_journal_integrity)
+ goto out;
+ }
+
+ if (tgt->u.integrity.journal_crypt) { /* MAX length 15 + str_journal_crypt + str_key */
+ num_options++;
+
+ if (tgt->u.integrity.journal_crypt_key) {
+ hexkey = crypt_bytes_to_hex(tgt->u.integrity.journal_crypt_key->keylength,
+ tgt->u.integrity.journal_crypt_key->key);
+ if (!hexkey)
+ goto out;
+ } else
+ hexkey = NULL;
+
+ r = snprintf(journal_crypt, max_journal_crypt, " journal_crypt:%s%s%s",
+ tgt->u.integrity.journal_crypt, hexkey ? ":" : "", hexkey ?: "");
+ crypt_safe_free(hexkey);
+ if (r < 0 || r >= max_journal_crypt)
+ goto out;
+ }
+
+ if (tgt->u.integrity.journal_size)
+ num_options++;
+ if (tgt->u.integrity.journal_watermark)
+ num_options++;
+ if (tgt->u.integrity.journal_commit_time)
+ num_options++;
+ if (tgt->u.integrity.interleave_sectors)
+ num_options++;
+ if (tgt->u.integrity.sector_size)
+ num_options++;
+ if (tgt->u.integrity.buffer_sectors)
+ num_options++;
+ if (tgt->u.integrity.fix_padding)
+ num_options++;
+ if (tgt->u.integrity.fix_hmac)
+ num_options++;
+ if (tgt->u.integrity.legacy_recalc)
+ num_options++;
+ if (tgt->u.integrity.meta_device)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_RECALCULATE)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_RECALCULATE_RESET)
+ num_options++;
+ if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
+ num_options++;
+
+ r = snprintf(features, max_size, "%d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", num_options,
+ tgt->u.integrity.journal_size ? _uf(feature[0], sizeof(feature[0]), /* MAX length 17 + int32 */
+ "journal_sectors", (unsigned)(tgt->u.integrity.journal_size / SECTOR_SIZE)) : "",
+ tgt->u.integrity.journal_watermark ? _uf(feature[1], sizeof(feature[1]), /* MAX length 19 + int32 */
+ /* bitmap overloaded values */
+ (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "sectors_per_bit" : "journal_watermark",
+ tgt->u.integrity.journal_watermark) : "",
+ tgt->u.integrity.journal_commit_time ? _uf(feature[2], sizeof(feature[2]), /* MAX length 23 + int32 */
+ /* bitmap overloaded values */
+ (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "bitmap_flush_interval" : "commit_time",
+ tgt->u.integrity.journal_commit_time) : "",
+ tgt->u.integrity.interleave_sectors ? _uf(feature[3], sizeof(feature[3]), /* MAX length 20 + int32 */
+ "interleave_sectors", tgt->u.integrity.interleave_sectors) : "",
+ tgt->u.integrity.sector_size ? _uf(feature[4], sizeof(feature[4]), /* MAX length 12 + int32 */
+ "block_size", tgt->u.integrity.sector_size) : "",
+ tgt->u.integrity.buffer_sectors ? _uf(feature[5], sizeof(feature[5]), /* MAX length 16 + int32 */
+ "buffer_sectors", tgt->u.integrity.buffer_sectors) : "",
+ tgt->u.integrity.integrity ? integrity : "",
+ tgt->u.integrity.journal_integrity ? journal_integrity : "",
+ tgt->u.integrity.journal_crypt ? journal_crypt : "",
+ tgt->u.integrity.fix_padding ? " fix_padding" : "", /* MAX length 12 */
+ tgt->u.integrity.fix_hmac ? " fix_hmac" : "", /* MAX length 9 */
+ tgt->u.integrity.legacy_recalc ? " legacy_recalculate" : "", /* MAX length 19 */
+ flags & CRYPT_ACTIVATE_RECALCULATE ? " recalculate" : "", /* MAX length 12 */
+ flags & CRYPT_ACTIVATE_RECALCULATE_RESET ? " reset_recalculate" : "", /* MAX length 18 */
+ flags & CRYPT_ACTIVATE_ALLOW_DISCARDS ? " allow_discards" : "", /* MAX length 15 */
+ tgt->u.integrity.meta_device ? " meta_device:" : "", /* MAX length 13 + str_device */
+ tgt->u.integrity.meta_device ? device_block_path(tgt->u.integrity.meta_device) : "");
+ if (r < 0 || r >= max_size)
+ goto out;
+
+ if (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP)
+ mode = 'B';
+ else if (flags & CRYPT_ACTIVATE_RECOVERY)
+ mode = 'R';
+ else if (flags & CRYPT_ACTIVATE_NO_JOURNAL)
+ mode = 'D';
+ else
+ mode = 'J';
+
+ r = snprintf(params, max_size, "%s %" PRIu64 " %d %c %s",
+ device_block_path(tgt->data_device), tgt->u.integrity.offset,
+ tgt->u.integrity.tag_size, mode, features);
+ if (r < 0 || r >= max_size)
+ goto out;
+
+ params_out = params;
+out:
+ crypt_safe_free(features);
+ crypt_safe_free(integrity);
+ crypt_safe_free(journal_integrity);
+ crypt_safe_free(journal_crypt);
+ if (!params_out)
+ crypt_safe_free(params);
+
+ return params_out;
+}
+
+static char *get_dm_linear_params(const struct dm_target *tgt)
+{
+ char *params;
+ int r;
+ int max_size = strlen(device_block_path(tgt->data_device)) + int_log10(tgt->u.linear.offset) + 3;
+
+ params = crypt_safe_alloc(max_size);
+ if (!params)
+ return NULL;
+
+ r = snprintf(params, max_size, "%s %" PRIu64,
+ device_block_path(tgt->data_device), tgt->u.linear.offset);
+
+ if (r < 0 || r >= max_size) {
+ crypt_safe_free(params);
+ params = NULL;
+ }
+
+ return params;
+}
+
+static char *get_dm_zero_params(void)
+{
+ char *params = crypt_safe_alloc(1);
+ if (!params)
+ return NULL;
+
+ params[0] = 0;
+ return params;
+}
+
+/* DM helpers */
+static int _dm_remove(const char *name, int udev_wait, int deferred)
+{
+ int r = 0;
+ struct dm_task *dmt;
+ uint32_t cookie = 0;
+
+ if (!_dm_use_udev())
+ udev_wait = 0;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
+ return 0;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+#if HAVE_DECL_DM_TASK_RETRY_REMOVE
+ if (!dm_task_retry_remove(dmt))
+ goto out;
+#endif
+#if HAVE_DECL_DM_TASK_DEFERRED_REMOVE
+ if (deferred && !dm_task_deferred_remove(dmt))
+ goto out;
+#endif
+ if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK))
+ goto out;
+
+ r = dm_task_run(dmt);
+
+ if (udev_wait)
+ (void)_dm_udev_wait(cookie);
+out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+static int _dm_simple(int task, const char *name, uint32_t dmflags)
+{
+ int r = 0;
+ struct dm_task *dmt;
+
+ if (!(dmt = dm_task_create(task)))
+ return 0;
+
+ if (name && !dm_task_set_name(dmt, name))
+ goto out;
+
+ if (task == DM_DEVICE_SUSPEND &&
+ (dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt))
+ goto out;
+
+ if (task == DM_DEVICE_SUSPEND &&
+ (dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt))
+ goto out;
+
+ r = dm_task_run(dmt);
+out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+static int _dm_resume_device(const char *name, uint32_t flags);
+
+static int _error_device(const char *name, size_t size)
+{
+ struct dm_task *dmt;
+ int r = 0;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+ return 0;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
+ goto out;
+
+ if (!dm_task_set_ro(dmt))
+ goto out;
+
+ if (!dm_task_no_open_count(dmt))
+ goto out;
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (_dm_resume_device(name, 0)) {
+ _dm_simple(DM_DEVICE_CLEAR, name, 0);
+ goto out;
+ }
+
+ r = 1;
+out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+int dm_error_device(struct crypt_device *cd, const char *name)
+{
+ int r;
+ struct crypt_dm_active_device dmd;
+
+ if (!name)
+ return -EINVAL;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+
+ if ((dm_query_device(cd, name, 0, &dmd) >= 0) && _error_device(name, dmd.size))
+ r = 0;
+ else
+ r = -EINVAL;
+
+ dm_targets_free(cd, &dmd);
+
+ dm_exit_context();
+
+ return r;
+}
+
+int dm_clear_device(struct crypt_device *cd, const char *name)
+{
+ int r;
+
+ if (!name)
+ return -EINVAL;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+
+ if (_dm_simple(DM_DEVICE_CLEAR, name, 0))
+ r = 0;
+ else
+ r = -EINVAL;
+
+ dm_exit_context();
+
+ return r;
+}
+
+int dm_remove_device(struct crypt_device *cd, const char *name, uint32_t flags)
+{
+ struct crypt_dm_active_device dmd = {};
+ int r = -EINVAL;
+ int retries = (flags & CRYPT_DEACTIVATE_FORCE) ? RETRY_COUNT : 1;
+ int deferred = (flags & CRYPT_DEACTIVATE_DEFERRED) ? 1 : 0;
+ int error_target = 0;
+ uint32_t dmt_flags;
+
+ if (!name)
+ return -EINVAL;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+
+ if (deferred && !dm_flags(cd, DM_UNKNOWN, &dmt_flags) && !(dmt_flags & DM_DEFERRED_SUPPORTED)) {
+ log_err(cd, _("Requested deferred flag is not supported."));
+ dm_exit_context();
+ return -ENOTSUP;
+ }
+
+ do {
+ r = _dm_remove(name, 1, deferred) ? 0 : -EINVAL;
+ if (--retries && r) {
+ log_dbg(cd, "WARNING: other process locked internal device %s, %s.",
+ name, retries ? "retrying remove" : "giving up");
+ sleep(1);
+ if ((flags & CRYPT_DEACTIVATE_FORCE) && !error_target) {
+ /* If force flag is set, replace device with error, read-only target.
+ * it should stop processes from reading it and also removed underlying
+ * device from mapping, so it is usable again.
+ * Anyway, if some process try to read temporary cryptsetup device,
+ * it is bug - no other process should try touch it (e.g. udev).
+ */
+ if (!dm_query_device(cd, name, 0, &dmd)) {
+ _error_device(name, dmd.size);
+ error_target = 1;
+ }
+ }
+ }
+ } while (r == -EINVAL && retries);
+
+ dm_task_update_nodes();
+ dm_exit_context();
+
+ return r;
+}
+
+#define UUID_LEN 37 /* 36 + \0, libuuid ... */
+/*
+ * UUID has format: CRYPT-<devicetype>-[<uuid>-]<device name>
+ * CRYPT-PLAIN-name
+ * CRYPT-LUKS1-00000000000000000000000000000000-name
+ * CRYPT-TEMP-name
+ */
+static int dm_prepare_uuid(struct crypt_device *cd, const char *name, const char *type,
+ const char *uuid, char *buf, size_t buflen)
+{
+ char *ptr, uuid2[UUID_LEN] = {0};
+ uuid_t uu;
+ int i = 0;
+
+ /* Remove '-' chars */
+ if (uuid) {
+ if (uuid_parse(uuid, uu) < 0) {
+ log_dbg(cd, "Requested UUID %s has invalid format.", uuid);
+ return 0;
+ }
+
+ for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
+ if (uuid[i] != '-') {
+ *ptr = uuid[i];
+ ptr++;
+ }
+ }
+
+ i = snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s%s",
+ type ?: "", type ? "-" : "",
+ uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
+ name);
+ if (i < 0)
+ return 0;
+
+ log_dbg(cd, "DM-UUID is %s", buf);
+ if ((size_t)i >= buflen)
+ log_err(cd, _("DM-UUID for device %s was truncated."), name);
+
+ return 1;
+}
+
+int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type)
+{
+ int r_udev, r;
+ char *c;
+ char dev_uuid[DM_UUID_LEN + DM_BY_ID_PREFIX_LEN] = DM_BY_ID_PREFIX;
+
+ if (!dm_prepare_uuid(cd, "", type, uuid, dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN))
+ return -EINVAL;
+
+ c = strrchr(dev_uuid, '-');
+ if (!c)
+ return -EINVAL;
+
+ /* cut of dm name */
+ *c = '\0';
+
+ /* Either udev or sysfs can report that device is active. */
+ r = lookup_by_disk_id(dev_uuid);
+ if (r > 0)
+ return r;
+
+ r_udev = r;
+ r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
+
+ return r == -ENOENT ? r_udev : r;
+}
+
+static int _add_dm_targets(struct dm_task *dmt, struct crypt_dm_active_device *dmd)
+{
+ const char *target;
+ struct dm_target *tgt = &dmd->segment;
+
+ do {
+ switch (tgt->type) {
+ case DM_CRYPT:
+ target = DM_CRYPT_TARGET;
+ break;
+ case DM_VERITY:
+ target = DM_VERITY_TARGET;
+ break;
+ case DM_INTEGRITY:
+ target = DM_INTEGRITY_TARGET;
+ break;
+ case DM_LINEAR:
+ target = DM_LINEAR_TARGET;
+ break;
+ case DM_ZERO:
+ target = DM_ZERO_TARGET;
+ break;
+ default:
+ return -ENOTSUP;
+ }
+
+ if (!dm_task_add_target(dmt, tgt->offset, tgt->size, target, tgt->params))
+ return -EINVAL;
+
+ tgt = tgt->next;
+ } while (tgt);
+
+ return 0;
+}
+
+static void _destroy_dm_targets_params(struct crypt_dm_active_device *dmd)
+{
+ struct dm_target *t = &dmd->segment;
+
+ do {
+ crypt_safe_free(t->params);
+ t->params = NULL;
+ t = t->next;
+ } while (t);
+}
+
+static int _create_dm_targets_params(struct crypt_dm_active_device *dmd)
+{
+ int r;
+ struct dm_target *tgt = &dmd->segment;
+
+ do {
+ if (tgt->type == DM_CRYPT)
+ tgt->params = get_dm_crypt_params(tgt, dmd->flags);
+ else if (tgt->type == DM_VERITY)
+ tgt->params = get_dm_verity_params(tgt, dmd->flags);
+ else if (tgt->type == DM_INTEGRITY)
+ tgt->params = get_dm_integrity_params(tgt, dmd->flags);
+ else if (tgt->type == DM_LINEAR)
+ tgt->params = get_dm_linear_params(tgt);
+ else if (tgt->type == DM_ZERO)
+ tgt->params = get_dm_zero_params();
+ else {
+ r = -ENOTSUP;
+ goto err;
+ }
+
+ if (!tgt->params) {
+ r = -EINVAL;
+ goto err;
+ }
+ tgt = tgt->next;
+ } while (tgt);
+
+ return 0;
+err:
+ _destroy_dm_targets_params(dmd);
+ return r;
+}
+
+static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
+ struct crypt_dm_active_device *dmd)
+{
+ struct dm_task *dmt = NULL;
+ struct dm_info dmi;
+ char dev_uuid[DM_UUID_LEN] = {0};
+ int r = -EINVAL;
+ uint32_t cookie = 0, read_ahead = 0;
+ uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
+
+ if (dmd->flags & CRYPT_ACTIVATE_PRIVATE)
+ udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
+
+ /* All devices must have DM_UUID, only resize on old device is exception */
+ if (!dm_prepare_uuid(cd, name, type, dmd->uuid, dev_uuid, sizeof(dev_uuid)))
+ goto out;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
+ goto out;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ if (!dm_task_set_uuid(dmt, dev_uuid))
+ goto out;
+
+ if (!dm_task_secure_data(dmt))
+ goto out;
+ if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
+ goto out;
+
+ r = _create_dm_targets_params(dmd);
+ if (r)
+ goto out;
+
+ r = _add_dm_targets(dmt, dmd);
+ if (r)
+ goto out;
+
+ r = -EINVAL;
+
+#ifdef DM_READ_AHEAD_MINIMUM_FLAG
+ if (device_read_ahead(dmd->segment.data_device, &read_ahead) &&
+ !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
+ goto out;
+#endif
+ if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
+ goto out;
+
+ if (!dm_task_run(dmt)) {
+ r = dm_status_device(cd, name);;
+ if (r >= 0)
+ r = -EEXIST;
+ if (r != -EEXIST && r != -ENODEV)
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (dm_task_get_info(dmt, &dmi))
+ r = 0;
+
+ if (_dm_use_udev()) {
+ (void)_dm_udev_wait(cookie);
+ cookie = 0;
+ }
+
+ if (r < 0)
+ _dm_remove(name, 1, 0);
+
+out:
+ if (cookie && _dm_use_udev())
+ (void)_dm_udev_wait(cookie);
+
+ if (dmt)
+ dm_task_destroy(dmt);
+
+ dm_task_update_nodes();
+
+ /* If code just loaded target module, update versions */
+ _dm_check_versions(cd, dmd->segment.type);
+
+ _destroy_dm_targets_params(dmd);
+
+ return r;
+}
+
+static int _dm_resume_device(const char *name, uint32_t dmflags)
+{
+ struct dm_task *dmt;
+ int r = -EINVAL;
+ uint32_t cookie = 0;
+ uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
+
+ if (dmflags & DM_RESUME_PRIVATE)
+ udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
+ return r;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ if ((dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt))
+ goto out;
+
+ if ((dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt))
+ goto out;
+
+ if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
+ goto out;
+
+ if (dm_task_run(dmt))
+ r = 0;
+out:
+ if (cookie && _dm_use_udev())
+ (void)_dm_udev_wait(cookie);
+
+ dm_task_destroy(dmt);
+
+ dm_task_update_nodes();
+
+ return r;
+}
+
+static int _dm_reload_device(struct crypt_device *cd, const char *name,
+ struct crypt_dm_active_device *dmd)
+{
+ int r = -EINVAL;
+ struct dm_task *dmt = NULL;
+ uint32_t read_ahead = 0;
+
+ /* All devices must have DM_UUID, only resize on old device is exception */
+ if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+ goto out;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ if (!dm_task_secure_data(dmt))
+ goto out;
+ if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
+ goto out;
+
+ r = _create_dm_targets_params(dmd);
+ if (r)
+ goto out;
+
+ r = _add_dm_targets(dmt, dmd);
+ if (r)
+ goto out;
+
+ r = -EINVAL;
+
+#ifdef DM_READ_AHEAD_MINIMUM_FLAG
+ if (device_read_ahead(dmd->segment.data_device, &read_ahead) &&
+ !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
+ goto out;
+#endif
+
+ if (dm_task_run(dmt))
+ r = 0;
+out:
+ if (dmt)
+ dm_task_destroy(dmt);
+
+ /* If code just loaded target module, update versions */
+ _dm_check_versions(cd, dmd->segment.type);
+
+ _destroy_dm_targets_params(dmd);
+
+ return r;
+}
+
+static void crypt_free_verity_params(struct crypt_params_verity *vp)
+{
+ if (!vp)
+ return;
+
+ free(CONST_CAST(void*)vp->hash_name);
+ free(CONST_CAST(void*)vp->data_device);
+ free(CONST_CAST(void*)vp->hash_device);
+ free(CONST_CAST(void*)vp->fec_device);
+ free(CONST_CAST(void*)vp->salt);
+ free(vp);
+}
+
+static void _dm_target_free_query_path(struct crypt_device *cd, struct dm_target *tgt)
+{
+ switch(tgt->type) {
+ case DM_CRYPT:
+ crypt_free_volume_key(tgt->u.crypt.vk);
+ free(CONST_CAST(void*)tgt->u.crypt.cipher);
+ break;
+ case DM_INTEGRITY:
+ free(CONST_CAST(void*)tgt->u.integrity.integrity);
+ crypt_free_volume_key(tgt->u.integrity.vk);
+
+ free(CONST_CAST(void*)tgt->u.integrity.journal_integrity);
+ crypt_free_volume_key(tgt->u.integrity.journal_integrity_key);
+
+ free(CONST_CAST(void*)tgt->u.integrity.journal_crypt);
+ crypt_free_volume_key(tgt->u.integrity.journal_crypt_key);
+
+ device_free(cd, tgt->u.integrity.meta_device);
+ break;
+ case DM_VERITY:
+ crypt_free_verity_params(tgt->u.verity.vp);
+ device_free(cd, tgt->u.verity.hash_device);
+ free(CONST_CAST(void*)tgt->u.verity.root_hash);
+ free(CONST_CAST(void*)tgt->u.verity.root_hash_sig_key_desc);
+ /* fall through */
+ case DM_LINEAR:
+ /* fall through */
+ case DM_ERROR:
+ /* fall through */
+ case DM_ZERO:
+ break;
+ default:
+ log_err(cd, _("Unknown dm target type."));
+ return;
+ }
+
+ device_free(cd, tgt->data_device);
+}
+
+static void _dm_target_erase(struct crypt_device *cd, struct dm_target *tgt)
+{
+ if (tgt->direction == TARGET_EMPTY)
+ return;
+
+ if (tgt->direction == TARGET_QUERY)
+ _dm_target_free_query_path(cd, tgt);
+
+ if (tgt->type == DM_CRYPT)
+ free(CONST_CAST(void*)tgt->u.crypt.integrity);
+}
+
+void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd)
+{
+ struct dm_target *t = &dmd->segment, *next = t->next;
+
+ _dm_target_erase(cd, t);
+
+ while (next) {
+ t = next;
+ next = t->next;
+ _dm_target_erase(cd, t);
+ free(t);
+ }
+
+ memset(&dmd->segment, 0, sizeof(dmd->segment));
+}
+
+int dm_targets_allocate(struct dm_target *first, unsigned count)
+{
+ if (!first || first->next || !count)
+ return -EINVAL;
+
+ while (--count) {
+ first->next = crypt_zalloc(sizeof(*first));
+ if (!first->next)
+ return -ENOMEM;
+ first = first->next;
+ }
+
+ return 0;
+}
+
+static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dmt_flags)
+{
+ int ret = 0;
+
+ /* If discard not supported try to load without discard */
+ if ((*dmd_flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
+ !(dmt_flags & DM_DISCARDS_SUPPORTED)) {
+ log_dbg(cd, "Discard/TRIM is not supported");
+ *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS;
+ ret = 1;
+ }
+
+ /* If kernel keyring is not supported load key directly in dm-crypt */
+ if ((*dmd_flags & CRYPT_ACTIVATE_KEYRING_KEY) &&
+ !(dmt_flags & DM_KERNEL_KEYRING_SUPPORTED)) {
+ log_dbg(cd, "dm-crypt does not support kernel keyring");
+ *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_KEYRING_KEY;
+ ret = 1;
+ }
+
+ /* Drop performance options if not supported */
+ if ((*dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
+ !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) {
+ log_dbg(cd, "dm-crypt does not support performance options");
+ *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS);
+ ret = 1;
+ }
+
+ /* Drop no workqueue options if not supported */
+ if ((*dmd_flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
+ !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
+ log_dbg(cd, "dm-crypt does not support performance options");
+ *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+int dm_create_device(struct crypt_device *cd, const char *name,
+ const char *type,
+ struct crypt_dm_active_device *dmd)
+{
+ uint32_t dmt_flags = 0;
+ int r = -EINVAL;
+
+ if (!type || !dmd)
+ return -EINVAL;
+
+ if (dm_init_context(cd, dmd->segment.type))
+ return -ENOTSUP;
+
+ r = _dm_create_device(cd, name, type, dmd);
+ if (!r || r == -EEXIST)
+ goto out;
+
+ if (dm_flags(cd, dmd->segment.type, &dmt_flags))
+ goto out;
+
+ if ((dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
+ check_retry(cd, &dmd->flags, dmt_flags)) {
+ log_dbg(cd, "Retrying open without incompatible options.");
+ r = _dm_create_device(cd, name, type, dmd);
+ if (!r || r == -EEXIST)
+ goto out;
+ }
+
+ if (dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
+ !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) {
+ log_err(cd, _("Requested dm-crypt performance options are not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) &&
+ !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
+ log_err(cd, _("Requested dm-crypt performance options are not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
+ CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
+ CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
+ CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) &&
+ !(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED)) {
+ log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->flags & CRYPT_ACTIVATE_TASKLETS &&
+ !(dmt_flags & DM_VERITY_TASKLETS_SUPPORTED)) {
+ log_err(cd, _("Requested dm-verity tasklets option is not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION &&
+ !(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED)) {
+ log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->segment.type == DM_VERITY &&
+ dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED)) {
+ log_err(cd, _("Requested dm-verity FEC options are not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->segment.type == DM_CRYPT) {
+ if (dmd->segment.u.crypt.integrity && !(dmt_flags & DM_INTEGRITY_SUPPORTED)) {
+ log_err(cd, _("Requested data integrity options are not supported."));
+ r = -EINVAL;
+ }
+ if (dmd->segment.u.crypt.sector_size != SECTOR_SIZE && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED)) {
+ log_err(cd, _("Requested sector_size option is not supported."));
+ r = -EINVAL;
+ }
+ }
+
+ if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
+ !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED)) {
+ log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE_RESET) &&
+ !(dmt_flags & DM_INTEGRITY_RESET_RECALC_SUPPORTED)) {
+ log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
+ !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED)) {
+ log_err(cd, _("Discard/TRIM is not supported."));
+ r = -EINVAL;
+ }
+
+ if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) &&
+ !(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED)) {
+ log_err(cd, _("Requested dm-integrity bitmap mode is not supported."));
+ r = -EINVAL;
+ }
+out:
+ /*
+ * Print warning if activating dm-crypt cipher_null device unless it's reencryption helper or
+ * keyslot encryption helper device (LUKS1 cipher_null devices).
+ */
+ if (!r && !(dmd->flags & CRYPT_ACTIVATE_PRIVATE) && single_segment(dmd) && dmd->segment.type == DM_CRYPT &&
+ crypt_is_cipher_null(dmd->segment.u.crypt.cipher))
+ log_dbg(cd, "Activated dm-crypt device with cipher_null. Device is not encrypted.");
+
+ dm_exit_context();
+ return r;
+}
+
+int dm_reload_device(struct crypt_device *cd, const char *name,
+ struct crypt_dm_active_device *dmd, uint32_t dmflags, unsigned resume)
+{
+ int r;
+ uint32_t dmt_flags;
+
+ if (!dmd)
+ return -EINVAL;
+
+ if (dm_init_context(cd, dmd->segment.type))
+ return -ENOTSUP;
+
+ if (dm_flags(cd, DM_INTEGRITY, &dmt_flags) || !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED))
+ dmd->flags &= ~CRYPT_ACTIVATE_RECALCULATE;
+
+ r = _dm_reload_device(cd, name, dmd);
+
+ if (r == -EINVAL && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR)) {
+ if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
+ !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
+ log_err(cd, _("Requested dm-crypt performance options are not supported."));
+ if ((dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
+ !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
+ log_err(cd, _("Requested dm-crypt performance options are not supported."));
+ if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
+ !dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED))
+ log_err(cd, _("Discard/TRIM is not supported."));
+ if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
+ !dm_flags(cd, DM_INTEGRITY, &dmt_flags) && !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
+ log_err(cd, _("Discard/TRIM is not supported."));
+ }
+
+ if (!r && resume)
+ r = _dm_resume_device(name, dmflags | act2dmflags(dmd->flags));
+
+ dm_exit_context();
+ return r;
+}
+
+static int dm_status_dmi(const char *name, struct dm_info *dmi,
+ const char *target, char **status_line)
+{
+ struct dm_task *dmt;
+ uint64_t start, length;
+ char *target_type, *params = NULL;
+ int r = -EINVAL;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
+ return r;
+
+ if (!dm_task_no_flush(dmt))
+ goto out;
+
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (!dm_task_get_info(dmt, dmi))
+ goto out;
+
+ if (!dmi->exists) {
+ r = -ENODEV;
+ goto out;
+ }
+
+ r = -EEXIST;
+ dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &params);
+
+ if (!target_type || start != 0)
+ goto out;
+
+ if (target && strcmp(target_type, target))
+ goto out;
+
+ /* for target == NULL check all supported */
+ if (!target && (strcmp(target_type, DM_CRYPT_TARGET) &&
+ strcmp(target_type, DM_VERITY_TARGET) &&
+ strcmp(target_type, DM_INTEGRITY_TARGET) &&
+ strcmp(target_type, DM_LINEAR_TARGET) &&
+ strcmp(target_type, DM_ZERO_TARGET) &&
+ strcmp(target_type, DM_ERROR_TARGET)))
+ goto out;
+ r = 0;
+out:
+ if (!r && status_line && !(*status_line = strdup(params)))
+ r = -ENOMEM;
+
+ dm_task_destroy(dmt);
+
+ return r;
+}
+
+int dm_status_device(struct crypt_device *cd, const char *name)
+{
+ int r;
+ struct dm_info dmi;
+ struct stat st;
+
+ /* libdevmapper is too clever and handles
+ * path argument differently with error.
+ * Fail early here if parameter is non-existent path.
+ */
+ if (strchr(name, '/') && stat(name, &st) < 0)
+ return -ENODEV;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+ r = dm_status_dmi(name, &dmi, NULL, NULL);
+ dm_exit_context();
+
+ if (r < 0)
+ return r;
+
+ return (dmi.open_count > 0) ? 1 : 0;
+}
+
+int dm_status_suspended(struct crypt_device *cd, const char *name)
+{
+ int r;
+ struct dm_info dmi;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+ r = dm_status_dmi(name, &dmi, NULL, NULL);
+ dm_exit_context();
+
+ if (r < 0)
+ return r;
+
+ return dmi.suspended ? 1 : 0;
+}
+
+static int _dm_status_verity_ok(struct crypt_device *cd, const char *name)
+{
+ int r;
+ struct dm_info dmi;
+ char *status_line = NULL;
+
+ r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
+ if (r < 0 || !status_line) {
+ free(status_line);
+ return r;
+ }
+
+ log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
+ r = status_line[0] == 'V' ? 1 : 0;
+ free(status_line);
+
+ return r;
+}
+
+int dm_status_verity_ok(struct crypt_device *cd, const char *name)
+{
+ int r;
+
+ if (dm_init_context(cd, DM_VERITY))
+ return -ENOTSUP;
+ r = _dm_status_verity_ok(cd, name);
+ dm_exit_context();
+ return r;
+}
+
+int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count)
+{
+ int r;
+ struct dm_info dmi;
+ char *status_line = NULL;
+
+ if (dm_init_context(cd, DM_INTEGRITY))
+ return -ENOTSUP;
+
+ r = dm_status_dmi(name, &dmi, DM_INTEGRITY_TARGET, &status_line);
+ if (r < 0 || !status_line) {
+ free(status_line);
+ dm_exit_context();
+ return r;
+ }
+
+ log_dbg(cd, "Integrity volume %s failure status is %s.", name, status_line ?: "");
+ *count = strtoull(status_line, NULL, 10);
+ free(status_line);
+ dm_exit_context();
+
+ return 0;
+}
+
+/* FIXME use hex wrapper, user val wrappers for line parsing */
+static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags,
+ char *params, struct dm_target *tgt,
+ uint32_t *act_flags)
+{
+ uint64_t val64;
+ char *rcipher, *rintegrity, *key_, *rdevice, *endp, buffer[3], *arg, *key_desc;
+ unsigned int i, val;
+ int r;
+ size_t key_size;
+ struct device *data_device = NULL;
+ char *cipher = NULL, *integrity = NULL;
+ struct volume_key *vk = NULL;
+
+ tgt->type = DM_CRYPT;
+ tgt->direction = TARGET_QUERY;
+ tgt->u.crypt.sector_size = SECTOR_SIZE;
+
+ r = -EINVAL;
+
+ rcipher = strsep(&params, " ");
+ rintegrity = NULL;
+
+ /* skip */
+ key_ = strsep(&params, " ");
+ if (!params)
+ goto err;
+ val64 = strtoull(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ params++;
+
+ tgt->u.crypt.iv_offset = val64;
+
+ /* device */
+ rdevice = strsep(&params, " ");
+ if (get_flags & DM_ACTIVE_DEVICE) {
+ arg = crypt_lookup_dev(rdevice);
+ r = device_alloc(cd, &data_device, arg);
+ free(arg);
+ if (r < 0 && r != -ENOTBLK)
+ goto err;
+ }
+
+ r = -EINVAL;
+
+ /*offset */
+ if (!params)
+ goto err;
+ val64 = strtoull(params, &params, 10);
+ tgt->u.crypt.offset = val64;
+
+ tgt->u.crypt.tag_size = 0;
+
+ /* Features section, available since crypt target version 1.11 */
+ if (*params) {
+ if (*params != ' ')
+ goto err;
+ params++;
+
+ /* Number of arguments */
+ val64 = strtoull(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ params++;
+
+ for (i = 0; i < val64; i++) {
+ if (!params)
+ goto err;
+ arg = strsep(&params, " ");
+ if (!strcasecmp(arg, "allow_discards"))
+ *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
+ else if (!strcasecmp(arg, "same_cpu_crypt"))
+ *act_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
+ else if (!strcasecmp(arg, "submit_from_crypt_cpus"))
+ *act_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
+ else if (!strcasecmp(arg, "no_read_workqueue"))
+ *act_flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
+ else if (!strcasecmp(arg, "no_write_workqueue"))
+ *act_flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
+ else if (!strcasecmp(arg, "iv_large_sectors"))
+ *act_flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
+ else if (sscanf(arg, "integrity:%u:", &val) == 1) {
+ tgt->u.crypt.tag_size = val;
+ rintegrity = strchr(arg + strlen("integrity:"), ':');
+ if (!rintegrity)
+ goto err;
+ rintegrity++;
+ } else if (sscanf(arg, "sector_size:%u", &val) == 1) {
+ tgt->u.crypt.sector_size = val;
+ } else /* unknown option */
+ goto err;
+ }
+
+ /* All parameters should be processed */
+ if (params)
+ goto err;
+ }
+
+ /* cipher */
+ if (get_flags & DM_ACTIVE_CRYPT_CIPHER) {
+ r = crypt_capi_to_cipher(&cipher, &integrity, rcipher, rintegrity);
+ if (r < 0)
+ goto err;
+ }
+
+ r = -EINVAL;
+
+ if (key_[0] == ':')
+ *act_flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+
+ if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
+ /* we will trust kernel the key_string is in expected format */
+ if (key_[0] == ':') {
+ if (sscanf(key_ + 1, "%zu", &key_size) != 1)
+ goto err;
+ } else
+ key_size = strlen(key_) / 2;
+
+ vk = crypt_alloc_volume_key(key_size, NULL);
+ if (!vk) {
+ r = -ENOMEM;
+ goto err;
+ }
+
+ if (get_flags & DM_ACTIVE_CRYPT_KEY) {
+ if (key_[0] == ':') {
+ /* :<key_size>:<key_type>:<key_description> */
+ key_desc = NULL;
+ endp = strpbrk(key_ + 1, ":");
+ if (endp)
+ key_desc = strpbrk(endp + 1, ":");
+ if (!key_desc) {
+ r = -ENOMEM;
+ goto err;
+ }
+ key_desc++;
+ crypt_volume_key_set_description(vk, key_desc);
+ } else {
+ buffer[2] = '\0';
+ for(i = 0; i < vk->keylength; i++) {
+ memcpy(buffer, &key_[i * 2], 2);
+ vk->key[i] = strtoul(buffer, &endp, 16);
+ if (endp != &buffer[2]) {
+ r = -EINVAL;
+ goto err;
+ }
+ }
+ }
+ }
+ }
+ memset(key_, 0, strlen(key_));
+
+ if (cipher)
+ tgt->u.crypt.cipher = cipher;
+ if (integrity)
+ tgt->u.crypt.integrity = integrity;
+ if (data_device)
+ tgt->data_device = data_device;
+ if (vk)
+ tgt->u.crypt.vk = vk;
+ return 0;
+err:
+ free(cipher);
+ free(integrity);
+ device_free(cd, data_device);
+ crypt_free_volume_key(vk);
+ return r;
+}
+
+static int _dm_target_query_verity(struct crypt_device *cd,
+ uint32_t get_flags,
+ char *params,
+ struct dm_target *tgt,
+ uint32_t *act_flags)
+{
+ struct crypt_params_verity *vp = NULL;
+ uint32_t val32;
+ uint64_t val64;
+ ssize_t len;
+ char *str, *str2, *arg;
+ unsigned int i, features;
+ int r;
+ struct device *data_device = NULL, *hash_device = NULL, *fec_device = NULL;
+ char *hash_name = NULL, *root_hash = NULL, *salt = NULL, *fec_dev_str = NULL;
+ char *root_hash_sig_key_desc = NULL;
+
+ if (get_flags & DM_ACTIVE_VERITY_PARAMS) {
+ vp = crypt_zalloc(sizeof(*vp));
+ if (!vp)
+ return -ENOMEM;
+ }
+
+ tgt->type = DM_VERITY;
+ tgt->direction = TARGET_QUERY;
+ tgt->u.verity.vp = vp;
+
+ /* version */
+ val32 = strtoul(params, &params, 10);
+ if (*params != ' ')
+ return -EINVAL;
+ if (vp)
+ vp->hash_type = val32;
+ params++;
+
+ /* data device */
+ str = strsep(&params, " ");
+ if (!params)
+ return -EINVAL;
+ if (get_flags & DM_ACTIVE_DEVICE) {
+ str2 = crypt_lookup_dev(str);
+ r = device_alloc(cd, &data_device, str2);
+ free(str2);
+ if (r < 0 && r != -ENOTBLK)
+ return r;
+ }
+
+ r = -EINVAL;
+
+ /* hash device */
+ str = strsep(&params, " ");
+ if (!params)
+ goto err;
+ if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
+ str2 = crypt_lookup_dev(str);
+ r = device_alloc(cd, &hash_device, str2);
+ free(str2);
+ if (r < 0 && r != -ENOTBLK)
+ goto err;
+ }
+
+ r = -EINVAL;
+
+ /* data block size*/
+ val32 = strtoul(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ if (vp)
+ vp->data_block_size = val32;
+ params++;
+
+ /* hash block size */
+ val32 = strtoul(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ if (vp)
+ vp->hash_block_size = val32;
+ params++;
+
+ /* data blocks */
+ val64 = strtoull(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ if (vp)
+ vp->data_size = val64;
+ params++;
+
+ /* hash start */
+ val64 = strtoull(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ tgt->u.verity.hash_offset = val64;
+ params++;
+
+ /* hash algorithm */
+ str = strsep(&params, " ");
+ if (!params)
+ goto err;
+ if (vp) {
+ hash_name = strdup(str);
+ if (!hash_name) {
+ r = -ENOMEM;
+ goto err;
+ }
+ }
+
+ /* root digest */
+ str = strsep(&params, " ");
+ if (!params)
+ goto err;
+ len = crypt_hex_to_bytes(str, &str2, 0);
+ if (len < 0) {
+ r = len;
+ goto err;
+ }
+ tgt->u.verity.root_hash_size = len;
+ if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH)
+ root_hash = str2;
+ else
+ free(str2);
+
+ /* salt */
+ str = strsep(&params, " ");
+ if (vp) {
+ if (!strcmp(str, "-")) {
+ vp->salt_size = 0;
+ vp->salt = NULL;
+ } else {
+ len = crypt_hex_to_bytes(str, &str2, 0);
+ if (len < 0) {
+ r = len;
+ goto err;
+ }
+ vp->salt_size = len;
+ salt = str2;
+ }
+ }
+
+ r = -EINVAL;
+
+ /* Features section, available since verity target version 1.3 */
+ if (params) {
+ /* Number of arguments */
+ val64 = strtoull(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ params++;
+
+ features = (int)val64;
+ for (i = 0; i < features; i++) {
+ r = -EINVAL;
+ if (!params)
+ goto err;
+ arg = strsep(&params, " ");
+ if (!strcasecmp(arg, "ignore_corruption"))
+ *act_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION;
+ else if (!strcasecmp(arg, "restart_on_corruption"))
+ *act_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
+ else if (!strcasecmp(arg, "panic_on_corruption"))
+ *act_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
+ else if (!strcasecmp(arg, "ignore_zero_blocks"))
+ *act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
+ else if (!strcasecmp(arg, "check_at_most_once"))
+ *act_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
+ else if (!strcasecmp(arg, "try_verify_in_tasklet"))
+ *act_flags |= CRYPT_ACTIVATE_TASKLETS;
+ else if (!strcasecmp(arg, "use_fec_from_device")) {
+ str = strsep(&params, " ");
+ str2 = crypt_lookup_dev(str);
+ if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
+ r = device_alloc(cd, &fec_device, str2);
+ if (r < 0 && r != -ENOTBLK) {
+ free(str2);
+ goto err;
+ }
+ }
+ if (vp) {
+ free(fec_dev_str);
+ fec_dev_str = str2;
+ } else
+ free(str2);
+ i++;
+ } else if (!strcasecmp(arg, "fec_start")) {
+ val64 = strtoull(params, &params, 10);
+ if (*params)
+ params++;
+ tgt->u.verity.fec_offset = val64;
+ if (vp)
+ vp->fec_area_offset = val64 * vp->hash_block_size;
+ i++;
+ } else if (!strcasecmp(arg, "fec_blocks")) {
+ val64 = strtoull(params, &params, 10);
+ if (*params)
+ params++;
+ tgt->u.verity.fec_blocks = val64;
+ i++;
+ } else if (!strcasecmp(arg, "fec_roots")) {
+ val32 = strtoul(params, &params, 10);
+ if (*params)
+ params++;
+ if (vp)
+ vp->fec_roots = val32;
+ i++;
+ } else if (!strcasecmp(arg, "root_hash_sig_key_desc")) {
+ str = strsep(&params, " ");
+ if (!str)
+ goto err;
+ if (vp && !root_hash_sig_key_desc) {
+ root_hash_sig_key_desc = strdup(str);
+ if (!root_hash_sig_key_desc) {
+ r = -ENOMEM;
+ goto err;
+ }
+ /* not stored in params, but cannot be used without vp */
+ vp->flags |= CRYPT_VERITY_ROOT_HASH_SIGNATURE;
+ }
+ i++;
+ } else /* unknown option */
+ goto err;
+ }
+
+ /* All parameters should be processed */
+ if (params && *params) {
+ r = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (data_device)
+ tgt->data_device = data_device;
+ if (hash_device)
+ tgt->u.verity.hash_device = hash_device;
+ if (fec_device)
+ tgt->u.verity.fec_device = fec_device;
+ if (root_hash)
+ tgt->u.verity.root_hash = root_hash;
+ if (vp && hash_name)
+ vp->hash_name = hash_name;
+ if (vp && salt)
+ vp->salt = salt;
+ if (vp && fec_dev_str)
+ vp->fec_device = fec_dev_str;
+ if (root_hash_sig_key_desc)
+ tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
+
+ return 0;
+err:
+ device_free(cd, data_device);
+ device_free(cd, hash_device);
+ device_free(cd, fec_device);
+ free(root_hash_sig_key_desc);
+ free(root_hash);
+ free(hash_name);
+ free(salt);
+ free(fec_dev_str);
+ free(vp);
+ return r;
+}
+
+static int _dm_target_query_integrity(struct crypt_device *cd,
+ uint32_t get_flags,
+ char *params,
+ struct dm_target *tgt,
+ uint32_t *act_flags)
+{
+ uint32_t val32;
+ uint64_t val64;
+ char c, *str, *str2, *arg;
+ unsigned int i, features, val;
+ ssize_t len;
+ int r;
+ struct device *data_device = NULL, *meta_device = NULL;
+ char *integrity = NULL, *journal_crypt = NULL, *journal_integrity = NULL;
+ struct volume_key *vk = NULL;
+ struct volume_key *journal_integrity_key = NULL;
+ struct volume_key *journal_crypt_key = NULL;
+
+ tgt->type = DM_INTEGRITY;
+ tgt->direction = TARGET_QUERY;
+
+ /* data device */
+ str = strsep(&params, " ");
+ if (get_flags & DM_ACTIVE_DEVICE) {
+ str2 = crypt_lookup_dev(str);
+ r = device_alloc(cd, &data_device, str2);
+ free(str2);
+ if (r < 0 && r != -ENOTBLK)
+ return r;
+ }
+
+ r = -EINVAL;
+
+ /*offset */
+ if (!params)
+ goto err;
+ val64 = strtoull(params, &params, 10);
+ if (!*params || *params != ' ')
+ goto err;
+ tgt->u.integrity.offset = val64;
+
+ /* tag size*/
+ val32 = strtoul(params, &params, 10);
+ tgt->u.integrity.tag_size = val32;
+ if (!*params || *params != ' ')
+ goto err;
+
+ /* journal */
+ c = toupper(*(++params));
+ if (!*params || *(++params) != ' ' || (c != 'D' && c != 'J' && c != 'R' && c != 'B'))
+ goto err;
+ if (c == 'D')
+ *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
+ if (c == 'R')
+ *act_flags |= CRYPT_ACTIVATE_RECOVERY;
+ if (c == 'B') {
+ *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
+ *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;
+ }
+
+ tgt->u.integrity.sector_size = SECTOR_SIZE;
+
+ /* Features section */
+ if (params) {
+ /* Number of arguments */
+ val64 = strtoull(params, &params, 10);
+ if (*params != ' ')
+ goto err;
+ params++;
+
+ features = (int)val64;
+ for (i = 0; i < features; i++) {
+ r = -EINVAL;
+ if (!params)
+ goto err;
+ arg = strsep(&params, " ");
+ if (sscanf(arg, "journal_sectors:%u", &val) == 1)
+ tgt->u.integrity.journal_size = val * SECTOR_SIZE;
+ else if (sscanf(arg, "journal_watermark:%u", &val) == 1)
+ tgt->u.integrity.journal_watermark = val;
+ else if (sscanf(arg, "sectors_per_bit:%" PRIu64, &val64) == 1) {
+ if (val64 > UINT_MAX)
+ goto err;
+ /* overloaded value for bitmap mode */
+ tgt->u.integrity.journal_watermark = (unsigned int)val64;
+ } else if (sscanf(arg, "commit_time:%u", &val) == 1)
+ tgt->u.integrity.journal_commit_time = val;
+ else if (sscanf(arg, "bitmap_flush_interval:%u", &val) == 1)
+ /* overloaded value for bitmap mode */
+ tgt->u.integrity.journal_commit_time = val;
+ else if (sscanf(arg, "interleave_sectors:%u", &val) == 1)
+ tgt->u.integrity.interleave_sectors = val;
+ else if (sscanf(arg, "block_size:%u", &val) == 1)
+ tgt->u.integrity.sector_size = val;
+ else if (sscanf(arg, "buffer_sectors:%u", &val) == 1)
+ tgt->u.integrity.buffer_sectors = val;
+ else if (!strncmp(arg, "internal_hash:", 14) && !integrity) {
+ str = &arg[14];
+ arg = strsep(&str, ":");
+ if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
+ integrity = strdup(arg);
+ if (!integrity) {
+ r = -ENOMEM;
+ goto err;
+ }
+ }
+
+ if (str) {
+ len = crypt_hex_to_bytes(str, &str2, 1);
+ if (len < 0) {
+ r = len;
+ goto err;
+ }
+
+ r = 0;
+ if (get_flags & DM_ACTIVE_CRYPT_KEY) {
+ vk = crypt_alloc_volume_key(len, str2);
+ if (!vk)
+ r = -ENOMEM;
+ } else if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
+ vk = crypt_alloc_volume_key(len, NULL);
+ if (!vk)
+ r = -ENOMEM;
+ }
+ crypt_safe_free(str2);
+ if (r < 0)
+ goto err;
+ }
+ } else if (!strncmp(arg, "meta_device:", 12) && !meta_device) {
+ if (get_flags & DM_ACTIVE_DEVICE) {
+ str = crypt_lookup_dev(&arg[12]);
+ r = device_alloc(cd, &meta_device, str);
+ free(str);
+ if (r < 0 && r != -ENOTBLK)
+ goto err;
+ }
+ } else if (!strncmp(arg, "journal_crypt:", 14) && !journal_crypt) {
+ str = &arg[14];
+ arg = strsep(&str, ":");
+ if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
+ journal_crypt = strdup(arg);
+ if (!journal_crypt) {
+ r = -ENOMEM;
+ goto err;
+ }
+ }
+
+ if (str) {
+ len = crypt_hex_to_bytes(str, &str2, 1);
+ if (len < 0) {
+ r = len;
+ goto err;
+ }
+
+ r = 0;
+ if (get_flags & DM_ACTIVE_JOURNAL_CRYPT_KEY) {
+ journal_crypt_key = crypt_alloc_volume_key(len, str2);
+ if (!journal_crypt_key)
+ r = -ENOMEM;
+ } else if (get_flags & DM_ACTIVE_JOURNAL_CRYPT_KEYSIZE) {
+ journal_crypt_key = crypt_alloc_volume_key(len, NULL);
+ if (!journal_crypt_key)
+ r = -ENOMEM;
+ }
+ crypt_safe_free(str2);
+ if (r < 0)
+ goto err;
+ }
+ } else if (!strncmp(arg, "journal_mac:", 12) && !journal_integrity) {
+ str = &arg[12];
+ arg = strsep(&str, ":");
+ if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
+ journal_integrity = strdup(arg);
+ if (!journal_integrity) {
+ r = -ENOMEM;
+ goto err;
+ }
+ }
+
+ if (str) {
+ len = crypt_hex_to_bytes(str, &str2, 1);
+ if (len < 0) {
+ r = len;
+ goto err;
+ }
+
+ r = 0;
+ if (get_flags & DM_ACTIVE_JOURNAL_MAC_KEY) {
+ journal_integrity_key = crypt_alloc_volume_key(len, str2);
+ if (!journal_integrity_key)
+ r = -ENOMEM;
+ } else if (get_flags & DM_ACTIVE_JOURNAL_MAC_KEYSIZE) {
+ journal_integrity_key = crypt_alloc_volume_key(len, NULL);
+ if (!journal_integrity_key)
+ r = -ENOMEM;
+ }
+ crypt_safe_free(str2);
+ if (r < 0)
+ goto err;
+ }
+ } else if (!strcmp(arg, "recalculate")) {
+ *act_flags |= CRYPT_ACTIVATE_RECALCULATE;
+ } else if (!strcmp(arg, "reset_recalculate")) {
+ *act_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET;
+ } else if (!strcmp(arg, "fix_padding")) {
+ tgt->u.integrity.fix_padding = true;
+ } else if (!strcmp(arg, "fix_hmac")) {
+ tgt->u.integrity.fix_hmac = true;
+ } else if (!strcmp(arg, "legacy_recalculate")) {
+ tgt->u.integrity.legacy_recalc = true;
+ } else if (!strcmp(arg, "allow_discards")) {
+ *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
+ } else /* unknown option */
+ goto err;
+ }
+
+ /* All parameters should be processed */
+ if (params && *params) {
+ r = -EINVAL;
+ goto err;
+ }
+ }
+
+ if (data_device)
+ tgt->data_device = data_device;
+ if (meta_device)
+ tgt->u.integrity.meta_device = meta_device;
+ if (integrity)
+ tgt->u.integrity.integrity = integrity;
+ if (journal_crypt)
+ tgt->u.integrity.journal_crypt = journal_crypt;
+ if (journal_integrity)
+ tgt->u.integrity.journal_integrity = journal_integrity;
+ if (vk)
+ tgt->u.integrity.vk = vk;
+ if (journal_integrity_key)
+ tgt->u.integrity.journal_integrity_key = journal_integrity_key;
+ if (journal_crypt_key)
+ tgt->u.integrity.journal_crypt_key = journal_crypt_key;
+ return 0;
+err:
+ device_free(cd, data_device);
+ device_free(cd, meta_device);
+ free(integrity);
+ free(journal_crypt);
+ free(journal_integrity);
+ crypt_free_volume_key(vk);
+ crypt_free_volume_key(journal_integrity_key);
+ crypt_free_volume_key(journal_crypt_key);
+ return r;
+}
+
+static int _dm_target_query_linear(struct crypt_device *cd, struct dm_target *tgt,
+ uint32_t get_flags, char *params)
+{
+ uint64_t val64;
+ char *rdevice, *arg;
+ int r;
+ struct device *device = NULL;
+
+ /* device */
+ rdevice = strsep(&params, " ");
+ if (get_flags & DM_ACTIVE_DEVICE) {
+ arg = crypt_lookup_dev(rdevice);
+ r = device_alloc(cd, &device, arg);
+ free(arg);
+ if (r < 0 && r != -ENOTBLK)
+ return r;
+ }
+
+ r = -EINVAL;
+
+ /*offset */
+ if (!params)
+ goto err;
+ val64 = strtoull(params, &params, 10);
+
+ /* params should be empty now */
+ if (*params)
+ goto err;
+
+ tgt->type = DM_LINEAR;
+ tgt->direction = TARGET_QUERY;
+ tgt->data_device = device;
+ tgt->u.linear.offset = val64;
+
+ return 0;
+err:
+ device_free(cd, device);
+ return r;
+}
+
+static int _dm_target_query_error(struct dm_target *tgt)
+{
+ tgt->type = DM_ERROR;
+ tgt->direction = TARGET_QUERY;
+
+ return 0;
+}
+
+static int _dm_target_query_zero(struct dm_target *tgt)
+{
+ tgt->type = DM_ZERO;
+ tgt->direction = TARGET_QUERY;
+
+ return 0;
+}
+
+/*
+ * on error retval has to be negative
+ *
+ * also currently any _dm_target_query fn does not perform cleanup on error
+ */
+static int dm_target_query(struct crypt_device *cd, struct dm_target *tgt, const uint64_t *start,
+ const uint64_t *length, const char *target_type,
+ char *params, uint32_t get_flags, uint32_t *act_flags)
+{
+ int r = -ENOTSUP;
+
+ if (!strcmp(target_type, DM_CRYPT_TARGET))
+ r = _dm_target_query_crypt(cd, get_flags, params, tgt, act_flags);
+ else if (!strcmp(target_type, DM_VERITY_TARGET))
+ r = _dm_target_query_verity(cd, get_flags, params, tgt, act_flags);
+ else if (!strcmp(target_type, DM_INTEGRITY_TARGET))
+ r = _dm_target_query_integrity(cd, get_flags, params, tgt, act_flags);
+ else if (!strcmp(target_type, DM_LINEAR_TARGET))
+ r = _dm_target_query_linear(cd, tgt, get_flags, params);
+ else if (!strcmp(target_type, DM_ERROR_TARGET))
+ r = _dm_target_query_error(tgt);
+ else if (!strcmp(target_type, DM_ZERO_TARGET))
+ r = _dm_target_query_zero(tgt);
+
+ if (!r) {
+ tgt->offset = *start;
+ tgt->size = *length;
+ }
+
+ return r;
+}
+
+static int _dm_query_device(struct crypt_device *cd, const char *name,
+ uint32_t get_flags, struct crypt_dm_active_device *dmd)
+{
+ struct dm_target *t;
+ struct dm_task *dmt;
+ struct dm_info dmi;
+ uint64_t start, length;
+ char *target_type, *params;
+ const char *tmp_uuid;
+ void *next = NULL;
+ int r = -EINVAL;
+
+ t = &dmd->segment;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+ return r;
+ if (!dm_task_secure_data(dmt))
+ goto out;
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+ r = -ENODEV;
+ if (!dm_task_run(dmt))
+ goto out;
+
+ r = -EINVAL;
+ if (!dm_task_get_info(dmt, &dmi))
+ goto out;
+
+ if (!dmi.exists) {
+ r = -ENODEV;
+ goto out;
+ }
+
+ if (dmi.target_count <= 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* Never allow one to return empty key */
+ if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi.suspended) {
+ log_dbg(cd, "Cannot read volume key while suspended.");
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = dm_targets_allocate(&dmd->segment, dmi.target_count);
+ if (r)
+ goto out;
+
+ do {
+ next = dm_get_next_target(dmt, next, &start, &length,
+ &target_type, &params);
+
+ r = dm_target_query(cd, t, &start, &length, target_type, params, get_flags, &dmd->flags);
+ if (!r && t->type == DM_VERITY) {
+ r = _dm_status_verity_ok(cd, name);
+ if (r == 0)
+ dmd->flags |= CRYPT_ACTIVATE_CORRUPTED;
+ }
+
+ if (r < 0) {
+ if (r != -ENOTSUP)
+ log_err(cd, _("Failed to query dm-%s segment."), target_type);
+ goto out;
+ }
+
+ dmd->size += length;
+ t = t->next;
+ } while (next && t);
+
+ if (dmi.read_only)
+ dmd->flags |= CRYPT_ACTIVATE_READONLY;
+
+ if (dmi.suspended)
+ dmd->flags |= CRYPT_ACTIVATE_SUSPENDED;
+
+ tmp_uuid = dm_task_get_uuid(dmt);
+ if (!tmp_uuid)
+ dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
+ else if (get_flags & DM_ACTIVE_UUID) {
+ if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
+ dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
+ }
+
+ dmd->holders = 0;
+#if (HAVE_DECL_DM_DEVICE_HAS_HOLDERS && HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS)
+ if (get_flags & DM_ACTIVE_HOLDERS)
+ dmd->holders = (dm_device_has_mounted_fs(dmi.major, dmi.minor) ||
+ dm_device_has_holders(dmi.major, dmi.minor));
+#endif
+
+ r = (dmi.open_count > 0);
+out:
+ dm_task_destroy(dmt);
+
+ if (r < 0)
+ dm_targets_free(cd, dmd);
+
+ return r;
+}
+
+int dm_query_device(struct crypt_device *cd, const char *name,
+ uint32_t get_flags, struct crypt_dm_active_device *dmd)
+{
+ int r;
+
+ if (!dmd)
+ return -EINVAL;
+
+ memset(dmd, 0, sizeof(*dmd));
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+
+ r = _dm_query_device(cd, name, get_flags, dmd);
+
+ dm_exit_context();
+ return r;
+}
+
+static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps,
+ char **names, size_t names_offset, size_t names_length)
+{
+#if HAVE_DECL_DM_DEVICE_GET_NAME
+ struct crypt_dm_active_device dmd;
+ char dmname[PATH_MAX];
+ unsigned i;
+ int r, major, minor, count = 0;
+
+ if (!prefix || !deps)
+ return -EINVAL;
+
+ for (i = 0; i < deps->count; i++) {
+ major = major(deps->device[i]);
+ if (!dm_is_dm_major(major))
+ continue;
+
+ minor = minor(deps->device[i]);
+ if (!dm_device_get_name(major, minor, 0, dmname, PATH_MAX))
+ return -EINVAL;
+
+ memset(&dmd, 0, sizeof(dmd));
+ r = _dm_query_device(cd, dmname, DM_ACTIVE_UUID, &dmd);
+ if (r < 0)
+ continue;
+
+ if (!dmd.uuid ||
+ strncmp(prefix, dmd.uuid, strlen(prefix)) ||
+ crypt_string_in(dmname, names, names_length))
+ *dmname = '\0';
+
+ dm_targets_free(cd, &dmd);
+ free(CONST_CAST(void*)dmd.uuid);
+
+ if ((size_t)count >= (names_length - names_offset))
+ return -ENOMEM;
+
+ if (*dmname && !(names[names_offset + count++] = strdup(dmname)))
+ return -ENOMEM;
+ }
+
+ return count;
+#else
+ return -EINVAL;
+#endif
+}
+
+int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,
+ char **names, size_t names_length)
+{
+ struct dm_task *dmt;
+ struct dm_info dmi;
+ struct dm_deps *deps;
+ int r = -EINVAL;
+ size_t i, last = 0, offset = 0;
+
+ if (!name || !names_length || !names)
+ return -EINVAL;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+
+ while (name) {
+ if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
+ goto out;
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+
+ r = -ENODEV;
+ if (!dm_task_run(dmt))
+ goto out;
+
+ r = -EINVAL;
+ if (!dm_task_get_info(dmt, &dmi))
+ goto out;
+ if (!(deps = dm_task_get_deps(dmt)))
+ goto out;
+
+ r = -ENODEV;
+ if (!dmi.exists)
+ goto out;
+
+ r = _process_deps(cd, prefix, deps, names, offset, names_length - 1);
+ if (r < 0)
+ goto out;
+
+ dm_task_destroy(dmt);
+ dmt = NULL;
+
+ offset += r;
+ name = names[last++];
+ }
+
+ r = 0;
+out:
+ if (r < 0) {
+ for (i = 0; i < names_length - 1; i++)
+ free(names[i]);
+ *names = NULL;
+ }
+
+ if (dmt)
+ dm_task_destroy(dmt);
+
+ dm_exit_context();
+ return r;
+}
+
+static int _dm_message(const char *name, const char *msg)
+{
+ int r = 0;
+ struct dm_task *dmt;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
+ return 0;
+
+ if (!dm_task_secure_data(dmt))
+ goto out;
+
+ if (name && !dm_task_set_name(dmt, name))
+ goto out;
+
+ if (!dm_task_set_sector(dmt, (uint64_t) 0))
+ goto out;
+
+ if (!dm_task_set_message(dmt, msg))
+ goto out;
+
+ r = dm_task_run(dmt);
+out:
+ dm_task_destroy(dmt);
+ return r;
+}
+
+int dm_suspend_device(struct crypt_device *cd, const char *name, uint32_t dmflags)
+{
+ uint32_t dmt_flags;
+ int r = -ENOTSUP;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return r;
+
+ if (dmflags & DM_SUSPEND_WIPE_KEY) {
+ if (dm_flags(cd, DM_CRYPT, &dmt_flags))
+ goto out;
+
+ if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
+ goto out;
+ }
+
+ r = -EINVAL;
+
+ if (!_dm_simple(DM_DEVICE_SUSPEND, name, dmflags))
+ goto out;
+
+ if (dmflags & DM_SUSPEND_WIPE_KEY) {
+ if (!_dm_message(name, "key wipe")) {
+ _dm_resume_device(name, 0);
+ goto out;
+ }
+ }
+
+ r = 0;
+out:
+ dm_exit_context();
+ return r;
+}
+
+int dm_resume_device(struct crypt_device *cd, const char *name, uint32_t dmflags)
+{
+ int r;
+
+ if (dm_init_context(cd, DM_UNKNOWN))
+ return -ENOTSUP;
+
+ r = _dm_resume_device(name, dmflags);
+
+ dm_exit_context();
+
+ return r;
+}
+
+int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
+ const struct volume_key *vk)
+{
+ uint32_t dmt_flags;
+ int msg_size;
+ char *msg = NULL, *key = NULL;
+ int r = -ENOTSUP;
+
+ if (dm_init_context(cd, DM_CRYPT) || dm_flags(cd, DM_CRYPT, &dmt_flags))
+ return -ENOTSUP;
+
+ if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
+ goto out;
+
+ if (!vk->keylength)
+ msg_size = 11; // key set -
+ else if (vk->key_description)
+ msg_size = strlen(vk->key_description) + int_log10(vk->keylength) + 18;
+ else
+ msg_size = vk->keylength * 2 + 10; // key set <key>
+
+ msg = crypt_safe_alloc(msg_size);
+ if (!msg) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (vk->key_description) {
+ r = snprintf(msg, msg_size, "key set :%zu:logon:%s", vk->keylength, vk->key_description);
+ } else {
+ key = crypt_bytes_to_hex(vk->keylength, vk->key);
+ if (!key) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = snprintf(msg, msg_size, "key set %s", key);
+ }
+ if (r < 0 || r >= msg_size) {
+ r = -EINVAL;
+ goto out;
+ }
+ if (!_dm_message(name, msg) ||
+ _dm_resume_device(name, 0)) {
+ r = -EINVAL;
+ goto out;
+ }
+ r = 0;
+out:
+ crypt_safe_free(msg);
+ crypt_safe_free(key);
+ dm_exit_context();
+ return r;
+}
+
+int dm_cancel_deferred_removal(const char *name)
+{
+ return _dm_message(name, "@cancel_deferred_remove") ? 0 : -ENOTSUP;
+}
+
+const char *dm_get_dir(void)
+{
+ return dm_dir();
+}
+
+int dm_is_dm_device(int major)
+{
+ return dm_is_dm_major((uint32_t)major);
+}
+
+int dm_is_dm_kernel_name(const char *name)
+{
+ return strncmp(name, "dm-", 3) ? 0 : 1;
+}
+
+int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *data_device, struct volume_key *vk, const char *cipher,
+ uint64_t iv_offset, uint64_t data_offset, const char *integrity, uint32_t tag_size,
+ uint32_t sector_size)
+{
+ char *dm_integrity = NULL;
+
+ if (tag_size) {
+ /* Space for IV metadata only */
+ dm_integrity = strdup(integrity ?: "none");
+ if (!dm_integrity)
+ return -ENOMEM;
+ }
+
+ tgt->data_device = data_device;
+
+ tgt->type = DM_CRYPT;
+ tgt->direction = TARGET_SET;
+ tgt->u.crypt.vk = vk;
+ tgt->offset = seg_offset;
+ tgt->size = seg_size;
+
+ tgt->u.crypt.cipher = cipher;
+ tgt->u.crypt.integrity = dm_integrity;
+ tgt->u.crypt.iv_offset = iv_offset;
+ tgt->u.crypt.offset = data_offset;
+ tgt->u.crypt.tag_size = tag_size;
+ tgt->u.crypt.sector_size = sector_size;
+
+ return 0;
+}
+
+int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *data_device, struct device *hash_device, struct device *fec_device,
+ const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
+ uint64_t hash_offset_block, uint64_t fec_blocks, struct crypt_params_verity *vp)
+{
+ if (!data_device || !hash_device || !vp)
+ return -EINVAL;
+
+ tgt->type = DM_VERITY;
+ tgt->direction = TARGET_SET;
+ tgt->offset = seg_offset;
+ tgt->size = seg_size;
+ tgt->data_device = data_device;
+
+ tgt->u.verity.hash_device = hash_device;
+ tgt->u.verity.fec_device = fec_device;
+ tgt->u.verity.root_hash = root_hash;
+ tgt->u.verity.root_hash_size = root_hash_size;
+ tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
+ tgt->u.verity.hash_offset = hash_offset_block;
+ tgt->u.verity.fec_offset = vp->fec_area_offset / vp->hash_block_size;
+ tgt->u.verity.fec_blocks = fec_blocks;
+ tgt->u.verity.vp = vp;
+
+ return 0;
+}
+
+int dm_integrity_target_set(struct crypt_device *cd,
+ struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *meta_device,
+ struct device *data_device, uint64_t tag_size, uint64_t offset,
+ uint32_t sector_size, struct volume_key *vk,
+ struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key,
+ const struct crypt_params_integrity *ip)
+{
+ uint32_t dmi_flags;
+
+ if (!data_device)
+ return -EINVAL;
+
+ _dm_check_versions(cd, DM_INTEGRITY);
+
+ tgt->type = DM_INTEGRITY;
+ tgt->direction = TARGET_SET;
+ tgt->offset = seg_offset;
+ tgt->size = seg_size;
+ tgt->data_device = data_device;
+ if (meta_device != data_device)
+ tgt->u.integrity.meta_device = meta_device;
+ tgt->u.integrity.tag_size = tag_size;
+ tgt->u.integrity.offset = offset;
+ tgt->u.integrity.sector_size = sector_size;
+
+ tgt->u.integrity.vk = vk;
+ tgt->u.integrity.journal_crypt_key = journal_crypt_key;
+ tgt->u.integrity.journal_integrity_key = journal_mac_key;
+
+ if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
+ (dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED) &&
+ !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING))
+ tgt->u.integrity.fix_padding = true;
+
+ if (!dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
+ (dmi_flags & DM_INTEGRITY_FIX_HMAC_SUPPORTED) &&
+ !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC))
+ tgt->u.integrity.fix_hmac = true;
+
+ /* This flag can be backported, just try to set it always */
+ if (crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC)
+ tgt->u.integrity.legacy_recalc = true;
+
+ if (ip) {
+ tgt->u.integrity.journal_size = ip->journal_size;
+ tgt->u.integrity.journal_watermark = ip->journal_watermark;
+ tgt->u.integrity.journal_commit_time = ip->journal_commit_time;
+ tgt->u.integrity.interleave_sectors = ip->interleave_sectors;
+ tgt->u.integrity.buffer_sectors = ip->buffer_sectors;
+ tgt->u.integrity.journal_integrity = ip->journal_integrity;
+ tgt->u.integrity.journal_crypt = ip->journal_crypt;
+ tgt->u.integrity.integrity = ip->integrity;
+ }
+
+ return 0;
+}
+
+int dm_linear_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *data_device, uint64_t data_offset)
+{
+ if (!data_device)
+ return -EINVAL;
+
+ tgt->type = DM_LINEAR;
+ tgt->direction = TARGET_SET;
+ tgt->offset = seg_offset;
+ tgt->size = seg_size;
+ tgt->data_device = data_device;
+
+ tgt->u.linear.offset = data_offset;
+
+ return 0;
+}
+
+int dm_zero_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size)
+{
+ tgt->type = DM_ZERO;
+ tgt->direction = TARGET_SET;
+ tgt->offset = seg_offset;
+ tgt->size = seg_size;
+
+ return 0;
+}
diff --git a/lib/loopaes/loopaes.c b/lib/loopaes/loopaes.c
new file mode 100644
index 0000000..224d3d0
--- /dev/null
+++ b/lib/loopaes/loopaes.c
@@ -0,0 +1,253 @@
+/*
+ * loop-AES compatible volume handling
+ *
+ * Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libcryptsetup.h"
+#include "loopaes.h"
+#include "internal.h"
+
+static const char *get_hash(unsigned int key_size)
+{
+ const char *hash;
+
+ switch (key_size) {
+ case 16: hash = "sha256"; break;
+ case 24: hash = "sha384"; break;
+ case 32: hash = "sha512"; break;
+ default: hash = NULL;
+ }
+
+ return hash;
+}
+
+static unsigned char get_tweak(unsigned int keys_count)
+{
+ switch (keys_count) {
+ case 64: return 0x55;
+ case 65: return 0xF4;
+ default: break;
+ }
+ return 0x00;
+}
+
+static int hash_key(const char *src, size_t src_len,
+ char *dst, size_t dst_len,
+ const char *hash_name)
+{
+ struct crypt_hash *hd = NULL;
+ int r;
+
+ if (crypt_hash_init(&hd, hash_name))
+ return -EINVAL;
+
+ r = crypt_hash_write(hd, src, src_len);
+ if (!r)
+ r = crypt_hash_final(hd, dst, dst_len);
+
+ crypt_hash_destroy(hd);
+ return r;
+}
+
+static int hash_keys(struct crypt_device *cd,
+ struct volume_key **vk,
+ const char *hash_override,
+ const char **input_keys,
+ unsigned int keys_count,
+ unsigned int key_len_output,
+ unsigned int key_len_input)
+{
+ const char *hash_name;
+ char tweak, *key_ptr;
+ unsigned int i;
+ int r = 0;
+
+ hash_name = hash_override ?: get_hash(key_len_output);
+ tweak = get_tweak(keys_count);
+
+ if (!keys_count || !key_len_output || !hash_name || !key_len_input) {
+ log_err(cd, _("Key processing error (using hash %s)."),
+ hash_name ?: "[none]");
+ return -EINVAL;
+ }
+
+ *vk = crypt_alloc_volume_key((size_t)key_len_output * keys_count, NULL);
+ if (!*vk)
+ return -ENOMEM;
+
+ for (i = 0; i < keys_count; i++) {
+ key_ptr = &(*vk)->key[i * key_len_output];
+ r = hash_key(input_keys[i], key_len_input, key_ptr,
+ key_len_output, hash_name);
+ if (r < 0)
+ break;
+
+ key_ptr[0] ^= tweak;
+ }
+
+ if (r < 0 && *vk) {
+ crypt_free_volume_key(*vk);
+ *vk = NULL;
+ }
+ return r;
+}
+
+static int keyfile_is_gpg(char *buffer, size_t buffer_len)
+{
+ int r = 0;
+ int index = buffer_len < 100 ? buffer_len - 1 : 100;
+ char eos = buffer[index];
+
+ buffer[index] = '\0';
+ if (strstr(buffer, "BEGIN PGP MESSAGE"))
+ r = 1;
+ buffer[index] = eos;
+ return r;
+}
+
+int LOOPAES_parse_keyfile(struct crypt_device *cd,
+ struct volume_key **vk,
+ const char *hash,
+ unsigned int *keys_count,
+ char *buffer,
+ size_t buffer_len)
+{
+ const char *keys[LOOPAES_KEYS_MAX];
+ unsigned int key_lengths[LOOPAES_KEYS_MAX];
+ unsigned int i, key_index, key_len, offset;
+
+ log_dbg(cd, "Parsing loop-AES keyfile of size %zu.", buffer_len);
+
+ if (!buffer_len)
+ return -EINVAL;
+
+ if (keyfile_is_gpg(buffer, buffer_len)) {
+ log_err(cd, _("Detected not yet supported GPG encrypted keyfile."));
+ log_std(cd, _("Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"));
+ return -EINVAL;
+ }
+
+ /* Remove EOL in buffer */
+ for (i = 0; i < buffer_len; i++)
+ if (buffer[i] == '\n' || buffer[i] == '\r')
+ buffer[i] = '\0';
+
+ offset = 0;
+ key_index = 0;
+ key_lengths[0] = 0;
+ while (offset < buffer_len && key_index < LOOPAES_KEYS_MAX) {
+ keys[key_index] = &buffer[offset];
+ key_lengths[key_index] = 0;;
+ while (offset < buffer_len && buffer[offset]) {
+ offset++;
+ key_lengths[key_index]++;
+ }
+ if (offset == buffer_len) {
+ log_dbg(cd, "Unterminated key #%d in keyfile.", key_index);
+ log_err(cd, _("Incompatible loop-AES keyfile detected."));
+ return -EINVAL;
+ }
+ while (offset < buffer_len && !buffer[offset])
+ offset++;
+ key_index++;
+ }
+
+ /* All keys must be the same length */
+ key_len = key_lengths[0];
+ for (i = 0; i < key_index; i++)
+ if (!key_lengths[i] || (key_lengths[i] != key_len)) {
+ log_dbg(cd, "Unexpected length %d of key #%d (should be %d).",
+ key_lengths[i], i, key_len);
+ key_len = 0;
+ break;
+ }
+
+ if (offset != buffer_len || key_len == 0 ||
+ (key_index != 1 && key_index !=64 && key_index != 65)) {
+ log_err(cd, _("Incompatible loop-AES keyfile detected."));
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Keyfile: %d keys of length %d.", key_index, key_len);
+
+ *keys_count = key_index;
+ return hash_keys(cd, vk, hash, keys, key_index,
+ crypt_get_volume_key_size(cd), key_len);
+}
+
+int LOOPAES_activate(struct crypt_device *cd,
+ const char *name,
+ const char *base_cipher,
+ unsigned int keys_count,
+ struct volume_key *vk,
+ uint32_t flags)
+{
+ int r;
+ uint32_t req_flags, dmc_flags;
+ char *cipher = NULL;
+ struct crypt_dm_active_device dmd = {
+ .flags = flags,
+ };
+
+ r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL,
+ crypt_get_data_offset(cd), &dmd.size, &dmd.flags);
+ if (r)
+ return r;
+
+ if (keys_count == 1) {
+ req_flags = DM_PLAIN64_SUPPORTED;
+ r = asprintf(&cipher, "%s-%s", base_cipher, "cbc-plain64");
+ } else {
+ req_flags = DM_LMK_SUPPORTED;
+ r = asprintf(&cipher, "%s:%d-%s", base_cipher, 64, "cbc-lmk");
+ }
+ if (r < 0)
+ return -ENOMEM;
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
+ vk, cipher, crypt_get_iv_offset(cd),
+ crypt_get_data_offset(cd), crypt_get_integrity(cd),
+ crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
+
+ if (r) {
+ free(cipher);
+ return r;
+ }
+
+ log_dbg(cd, "Trying to activate loop-AES device %s using cipher %s.",
+ name, cipher);
+
+ r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd);
+
+ if (r < 0 && !dm_flags(cd, DM_CRYPT, &dmc_flags) &&
+ (dmc_flags & req_flags) != req_flags) {
+ log_err(cd, _("Kernel does not support loop-AES compatible mapping."));
+ r = -ENOTSUP;
+ }
+
+ dm_targets_free(cd, &dmd);
+ free(cipher);
+
+ return r;
+}
diff --git a/lib/loopaes/loopaes.h b/lib/loopaes/loopaes.h
new file mode 100644
index 0000000..a921694
--- /dev/null
+++ b/lib/loopaes/loopaes.h
@@ -0,0 +1,46 @@
+/*
+ * loop-AES compatible volume handling
+ *
+ * Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LOOPAES_H
+#define _LOOPAES_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+struct crypt_device;
+struct volume_key;
+
+#define LOOPAES_KEYS_MAX 65
+
+int LOOPAES_parse_keyfile(struct crypt_device *cd,
+ struct volume_key **vk,
+ const char *hash,
+ unsigned int *keys_count,
+ char *buffer,
+ size_t buffer_len);
+
+int LOOPAES_activate(struct crypt_device *cd,
+ const char *name,
+ const char *base_cipher,
+ unsigned int keys_count,
+ struct volume_key *vk,
+ uint32_t flags);
+#endif
diff --git a/lib/luks1/af.c b/lib/luks1/af.c
new file mode 100644
index 0000000..76afeac
--- /dev/null
+++ b/lib/luks1/af.c
@@ -0,0 +1,170 @@
+/*
+ * AFsplitter - Anti forensic information splitter
+ *
+ * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ *
+ * AFsplitter diffuses information over a large stripe of data,
+ * therefore supporting secure data destruction.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "internal.h"
+#include "af.h"
+
+static void XORblock(const char *src1, const char *src2, char *dst, size_t n)
+{
+ size_t j;
+
+ for (j = 0; j < n; j++)
+ dst[j] = src1[j] ^ src2[j];
+}
+
+static int hash_buf(const char *src, char *dst, uint32_t iv,
+ size_t len, const char *hash_name)
+{
+ struct crypt_hash *hd = NULL;
+ char *iv_char = (char *)&iv;
+ int r;
+
+ iv = be32_to_cpu(iv);
+ if (crypt_hash_init(&hd, hash_name))
+ return -EINVAL;
+
+ if ((r = crypt_hash_write(hd, iv_char, sizeof(uint32_t))))
+ goto out;
+
+ if ((r = crypt_hash_write(hd, src, len)))
+ goto out;
+
+ r = crypt_hash_final(hd, dst, len);
+out:
+ crypt_hash_destroy(hd);
+ return r;
+}
+
+/*
+ * diffuse: Information spreading over the whole dataset with
+ * the help of hash function.
+ */
+static int diffuse(char *src, char *dst, size_t size, const char *hash_name)
+{
+ int r, hash_size = crypt_hash_size(hash_name);
+ unsigned int digest_size;
+ unsigned int i, blocks, padding;
+
+ if (hash_size <= 0)
+ return -EINVAL;
+ digest_size = hash_size;
+
+ blocks = size / digest_size;
+ padding = size % digest_size;
+
+ for (i = 0; i < blocks; i++) {
+ r = hash_buf(src + digest_size * i,
+ dst + digest_size * i,
+ i, (size_t)digest_size, hash_name);
+ if (r < 0)
+ return r;
+ }
+
+ if (padding) {
+ r = hash_buf(src + digest_size * i,
+ dst + digest_size * i,
+ i, (size_t)padding, hash_name);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+/*
+ * Information splitting. The amount of data is multiplied by
+ * blocknumbers. The same blocksize and blocknumbers values
+ * must be supplied to AF_merge to recover information.
+ */
+int AF_split(struct crypt_device *ctx, const char *src, char *dst,
+ size_t blocksize, unsigned int blocknumbers, const char *hash)
+{
+ unsigned int i;
+ char *bufblock;
+ int r;
+
+ bufblock = crypt_safe_alloc(blocksize);
+ if (!bufblock)
+ return -ENOMEM;
+
+ /* process everything except the last block */
+ for (i = 0; i < blocknumbers - 1; i++) {
+ r = crypt_random_get(ctx, dst + blocksize * i, blocksize, CRYPT_RND_NORMAL);
+ if (r < 0)
+ goto out;
+
+ XORblock(dst + blocksize * i, bufblock, bufblock, blocksize);
+ r = diffuse(bufblock, bufblock, blocksize, hash);
+ if (r < 0)
+ goto out;
+ }
+ /* the last block is computed */
+ XORblock(src, bufblock, dst + blocksize * i, blocksize);
+ r = 0;
+out:
+ crypt_safe_free(bufblock);
+ return r;
+}
+
+int AF_merge(const char *src, char *dst,
+ size_t blocksize, unsigned int blocknumbers, const char *hash)
+{
+ unsigned int i;
+ char *bufblock;
+ int r;
+
+ bufblock = crypt_safe_alloc(blocksize);
+ if (!bufblock)
+ return -ENOMEM;
+
+ for (i = 0; i < blocknumbers - 1; i++) {
+ XORblock(src + blocksize * i, bufblock, bufblock, blocksize);
+ r = diffuse(bufblock, bufblock, blocksize, hash);
+ if (r < 0)
+ goto out;
+ }
+ XORblock(src + blocksize * i, bufblock, dst, blocksize);
+ r = 0;
+out:
+ crypt_safe_free(bufblock);
+ return r;
+}
+
+/* Size of final split data including sector alignment */
+size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers)
+{
+ size_t af_size;
+
+ /* data material * stripes */
+ af_size = blocksize * blocknumbers;
+
+ /* round up to sector */
+ af_size = (af_size + (SECTOR_SIZE - 1)) / SECTOR_SIZE;
+
+ return af_size;
+}
diff --git a/lib/luks1/af.h b/lib/luks1/af.h
new file mode 100644
index 0000000..8a2bceb
--- /dev/null
+++ b/lib/luks1/af.h
@@ -0,0 +1,67 @@
+/*
+ * AFsplitter - Anti forensic information splitter
+ *
+ * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ *
+ * AFsplitter diffuses information over a large stripe of data,
+ * therefore supporting secure data destruction.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_CRYPTSETUP_LUKS_AF_H
+#define INCLUDED_CRYPTSETUP_LUKS_AF_H
+
+#include <stddef.h>
+
+struct crypt_device;
+struct volume_key;
+
+/*
+ * AF_split operates on src and produces information split data in
+ * dst. src is assumed to be of the length blocksize. The data stripe
+ * dst points to must be capable of storing blocksize*blocknumbers.
+ * blocknumbers is the data multiplication factor.
+ *
+ * AF_merge does just the opposite: reproduces the information stored in
+ * src of the length blocksize*blocknumbers into dst of the length
+ * blocksize.
+ *
+ * On error, both functions return -1, 0 otherwise.
+ */
+
+int AF_split(struct crypt_device *ctx, const char *src, char *dst,
+ size_t blocksize, unsigned int blocknumbers, const char *hash);
+int AF_merge(const char *src, char *dst, size_t blocksize,
+ unsigned int blocknumbers, const char *hash);
+size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers);
+
+int LUKS_encrypt_to_storage(
+ char *src, size_t srcLength,
+ const char *cipher,
+ const char *cipher_mode,
+ struct volume_key *vk,
+ unsigned int sector,
+ struct crypt_device *ctx);
+
+int LUKS_decrypt_from_storage(
+ char *dst, size_t dstLength,
+ const char *cipher,
+ const char *cipher_mode,
+ struct volume_key *vk,
+ unsigned int sector,
+ struct crypt_device *ctx);
+
+#endif
diff --git a/lib/luks1/keyencryption.c b/lib/luks1/keyencryption.c
new file mode 100644
index 0000000..c1c8201
--- /dev/null
+++ b/lib/luks1/keyencryption.c
@@ -0,0 +1,268 @@
+/*
+ * LUKS - Linux Unified Key Setup
+ *
+ * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include "luks.h"
+#include "af.h"
+#include "internal.h"
+
+static void _error_hint(struct crypt_device *ctx, const char *device,
+ const char *cipher, const char *mode, size_t keyLength)
+{
+ char *c, cipher_spec[MAX_CIPHER_LEN * 3];
+
+ if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, mode) < 0)
+ return;
+
+ log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
+ "Check that kernel supports %s cipher (check syslog for more info)."),
+ device, cipher_spec);
+
+ if (!strncmp(mode, "xts", 3) && (keyLength != 256 && keyLength != 512))
+ log_err(ctx, _("Key size in XTS mode must be 256 or 512 bits."));
+ else if (!(c = strchr(mode, '-')) || strlen(c) < 4)
+ log_err(ctx, _("Cipher specification should be in [cipher]-[mode]-[iv] format."));
+}
+
+static int LUKS_endec_template(char *src, size_t srcLength,
+ const char *cipher, const char *cipher_mode,
+ struct volume_key *vk,
+ unsigned int sector,
+ ssize_t (*func)(int, size_t, size_t, void *, size_t),
+ int mode,
+ struct crypt_device *ctx)
+{
+ char name[PATH_MAX], path[PATH_MAX];
+ char cipher_spec[MAX_CIPHER_LEN * 3];
+ struct crypt_dm_active_device dmd = {
+ .flags = CRYPT_ACTIVATE_PRIVATE,
+ };
+ int r, devfd = -1, remove_dev = 0;
+ size_t bsize, keyslot_alignment, alignment;
+
+ log_dbg(ctx, "Using dmcrypt to access keyslot area.");
+
+ bsize = device_block_size(ctx, crypt_metadata_device(ctx));
+ alignment = device_alignment(crypt_metadata_device(ctx));
+ if (!bsize || !alignment)
+ return -EINVAL;
+
+ if (bsize > LUKS_ALIGN_KEYSLOTS)
+ keyslot_alignment = LUKS_ALIGN_KEYSLOTS;
+ else
+ keyslot_alignment = bsize;
+ dmd.size = size_round_up(srcLength, keyslot_alignment) / SECTOR_SIZE;
+
+ if (mode == O_RDONLY)
+ dmd.flags |= CRYPT_ACTIVATE_READONLY;
+
+ if (snprintf(name, sizeof(name), "temporary-cryptsetup-%d", getpid()) < 0)
+ return -ENOMEM;
+ if (snprintf(path, sizeof(path), "%s/%s", dm_get_dir(), name) < 0)
+ return -ENOMEM;
+ if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, cipher_mode) < 0)
+ return -ENOMEM;
+
+ r = device_block_adjust(ctx, crypt_metadata_device(ctx), DEV_OK,
+ sector, &dmd.size, &dmd.flags);
+ if (r < 0) {
+ log_err(ctx, _("Device %s does not exist or access denied."),
+ device_path(crypt_metadata_device(ctx)));
+ return -EIO;
+ }
+
+ if (mode != O_RDONLY && dmd.flags & CRYPT_ACTIVATE_READONLY) {
+ log_err(ctx, _("Cannot write to device %s, permission denied."),
+ device_path(crypt_metadata_device(ctx)));
+ return -EACCES;
+ }
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size,
+ crypt_metadata_device(ctx), vk, cipher_spec, 0, sector,
+ NULL, 0, SECTOR_SIZE);
+ if (r)
+ goto out;
+
+ r = dm_create_device(ctx, name, "TEMP", &dmd);
+ if (r < 0) {
+ if (r != -EACCES && r != -ENOTSUP)
+ _error_hint(ctx, device_path(crypt_metadata_device(ctx)),
+ cipher, cipher_mode, vk->keylength * 8);
+ r = -EIO;
+ goto out;
+ }
+ remove_dev = 1;
+
+ devfd = open(path, mode | O_DIRECT | O_SYNC);
+ if (devfd == -1) {
+ log_err(ctx, _("Failed to open temporary keystore device."));
+ r = -EIO;
+ goto out;
+ }
+
+ r = func(devfd, bsize, alignment, src, srcLength);
+ if (r < 0) {
+ log_err(ctx, _("Failed to access temporary keystore device."));
+ r = -EIO;
+ } else
+ r = 0;
+ out:
+ dm_targets_free(ctx, &dmd);
+ if (devfd != -1)
+ close(devfd);
+ if (remove_dev)
+ dm_remove_device(ctx, name, CRYPT_DEACTIVATE_FORCE);
+ return r;
+}
+
+int LUKS_encrypt_to_storage(char *src, size_t srcLength,
+ const char *cipher,
+ const char *cipher_mode,
+ struct volume_key *vk,
+ unsigned int sector,
+ struct crypt_device *ctx)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ struct crypt_storage *s;
+ int devfd, r = 0;
+
+ /* Only whole sector writes supported */
+ if (MISALIGNED_512(srcLength))
+ return -EINVAL;
+
+ /* Encrypt buffer */
+ r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
+
+ if (r)
+ log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",
+ cipher, cipher_mode, r);
+
+ /* Fallback to old temporary dmcrypt device */
+ if (r == -ENOTSUP || r == -ENOENT)
+ return LUKS_endec_template(src, srcLength, cipher, cipher_mode,
+ vk, sector, write_blockwise, O_RDWR, ctx);
+
+ if (r) {
+ _error_hint(ctx, device_path(device), cipher, cipher_mode,
+ vk->keylength * 8);
+ return r;
+ }
+
+ log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area.");
+
+ r = crypt_storage_encrypt(s, 0, srcLength, src);
+ crypt_storage_destroy(s);
+
+ if (r)
+ return r;
+
+ r = -EIO;
+
+ /* Write buffer to device */
+ if (device_is_locked(device))
+ devfd = device_open_locked(ctx, device, O_RDWR);
+ else
+ devfd = device_open(ctx, device, O_RDWR);
+ if (devfd < 0)
+ goto out;
+
+ if (write_lseek_blockwise(devfd, device_block_size(ctx, device),
+ device_alignment(device), src, srcLength,
+ sector * SECTOR_SIZE) < 0)
+ goto out;
+
+ r = 0;
+out:
+ device_sync(ctx, device);
+ if (r)
+ log_err(ctx, _("IO error while encrypting keyslot."));
+
+ return r;
+}
+
+int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
+ const char *cipher,
+ const char *cipher_mode,
+ struct volume_key *vk,
+ unsigned int sector,
+ struct crypt_device *ctx)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ struct crypt_storage *s;
+ struct stat st;
+ int devfd, r = 0;
+
+ /* Only whole sector reads supported */
+ if (MISALIGNED_512(dstLength))
+ return -EINVAL;
+
+ r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
+
+ if (r)
+ log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",
+ cipher, cipher_mode, r);
+
+ /* Fallback to old temporary dmcrypt device */
+ if (r == -ENOTSUP || r == -ENOENT)
+ return LUKS_endec_template(dst, dstLength, cipher, cipher_mode,
+ vk, sector, read_blockwise, O_RDONLY, ctx);
+
+ if (r) {
+ _error_hint(ctx, device_path(device), cipher, cipher_mode,
+ vk->keylength * 8);
+ return r;
+ }
+
+ log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area.");
+
+ /* Read buffer from device */
+ if (device_is_locked(device))
+ devfd = device_open_locked(ctx, device, O_RDONLY);
+ else
+ devfd = device_open(ctx, device, O_RDONLY);
+ if (devfd < 0) {
+ log_err(ctx, _("Cannot open device %s."), device_path(device));
+ crypt_storage_destroy(s);
+ return -EIO;
+ }
+
+ if (read_lseek_blockwise(devfd, device_block_size(ctx, device),
+ device_alignment(device), dst, dstLength,
+ sector * SECTOR_SIZE) < 0) {
+ if (!fstat(devfd, &st) && (st.st_size < (off_t)dstLength))
+ log_err(ctx, _("Device %s is too small."), device_path(device));
+ else
+ log_err(ctx, _("IO error while decrypting keyslot."));
+
+ crypt_storage_destroy(s);
+ return -EIO;
+ }
+
+ /* Decrypt buffer */
+ r = crypt_storage_decrypt(s, 0, dstLength, dst);
+ crypt_storage_destroy(s);
+
+ return r;
+}
diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c
new file mode 100644
index 0000000..fe49a00
--- /dev/null
+++ b/lib/luks1/keymanage.c
@@ -0,0 +1,1300 @@
+/*
+ * LUKS - Linux Unified Key Setup
+ *
+ * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2013-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <uuid/uuid.h>
+#include <limits.h>
+
+#include "luks.h"
+#include "af.h"
+#include "internal.h"
+
+int LUKS_keyslot_area(const struct luks_phdr *hdr,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length)
+{
+ if(keyslot >= LUKS_NUMKEYS || keyslot < 0)
+ return -EINVAL;
+
+ *offset = (uint64_t)hdr->keyblock[keyslot].keyMaterialOffset * SECTOR_SIZE;
+ *length = AF_split_sectors(hdr->keyBytes, LUKS_STRIPES) * SECTOR_SIZE;
+
+ return 0;
+}
+
+/* insertsort: because the array has 8 elements and it's mostly sorted. that's why */
+static void LUKS_sort_keyslots(const struct luks_phdr *hdr, int *array)
+{
+ int i, j, x;
+
+ for (i = 1; i < LUKS_NUMKEYS; i++) {
+ j = i;
+ while (j > 0 && hdr->keyblock[array[j-1]].keyMaterialOffset > hdr->keyblock[array[j]].keyMaterialOffset) {
+ x = array[j];
+ array[j] = array[j-1];
+ array[j-1] = x;
+ j--;
+ }
+ }
+}
+
+static int _is_not_lower(char *str, unsigned max_len)
+{
+ for(; *str && max_len; str++, max_len--)
+ if (isupper(*str))
+ return 1;
+ return 0;
+}
+
+static int _to_lower(char *str, unsigned max_len)
+{
+ int r = 0;
+
+ for(; *str && max_len; str++, max_len--)
+ if (isupper(*str)) {
+ *str = tolower(*str);
+ r = 1;
+ }
+
+ return r;
+}
+
+size_t LUKS_device_sectors(const struct luks_phdr *hdr)
+{
+ int sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+ LUKS_sort_keyslots(hdr, sorted_areas);
+
+ return hdr->keyblock[sorted_areas[LUKS_NUMKEYS-1]].keyMaterialOffset + AF_split_sectors(hdr->keyBytes, LUKS_STRIPES);
+}
+
+size_t LUKS_keyslots_offset(const struct luks_phdr *hdr)
+{
+ int sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+ LUKS_sort_keyslots(hdr, sorted_areas);
+
+ return hdr->keyblock[sorted_areas[0]].keyMaterialOffset;
+}
+
+static int LUKS_check_device_size(struct crypt_device *ctx, const struct luks_phdr *hdr, int falloc)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ uint64_t dev_sectors, hdr_sectors;
+
+ if (!hdr->keyBytes)
+ return -EINVAL;
+
+ if (device_size(device, &dev_sectors)) {
+ log_dbg(ctx, "Cannot get device size for device %s.", device_path(device));
+ return -EIO;
+ }
+
+ dev_sectors >>= SECTOR_SHIFT;
+ hdr_sectors = LUKS_device_sectors(hdr);
+ log_dbg(ctx, "Key length %u, device size %" PRIu64 " sectors, header size %"
+ PRIu64 " sectors.", hdr->keyBytes, dev_sectors, hdr_sectors);
+
+ if (hdr_sectors > dev_sectors) {
+ /* If it is header file, increase its size */
+ if (falloc && !device_fallocate(device, hdr_sectors << SECTOR_SHIFT))
+ return 0;
+
+ log_err(ctx, _("Device %s is too small. (LUKS1 requires at least %" PRIu64 " bytes.)"),
+ device_path(device), hdr_sectors * SECTOR_SIZE);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int LUKS_check_keyslots(struct crypt_device *ctx, const struct luks_phdr *phdr)
+{
+ int i, prev, next, sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ uint32_t secs_per_stripes = AF_split_sectors(phdr->keyBytes, LUKS_STRIPES);
+
+ LUKS_sort_keyslots(phdr, sorted_areas);
+
+ /* Check keyslot to prevent access outside of header and keyslot area */
+ for (i = 0; i < LUKS_NUMKEYS; i++) {
+ /* enforce stripes == 4000 */
+ if (phdr->keyblock[i].stripes != LUKS_STRIPES) {
+ log_dbg(ctx, "Invalid stripes count %u in keyslot %u.",
+ phdr->keyblock[i].stripes, i);
+ log_err(ctx, _("LUKS keyslot %u is invalid."), i);
+ return -1;
+ }
+
+ /* First sectors is the header itself */
+ if (phdr->keyblock[i].keyMaterialOffset * SECTOR_SIZE < sizeof(*phdr)) {
+ log_dbg(ctx, "Invalid offset %u in keyslot %u.",
+ phdr->keyblock[i].keyMaterialOffset, i);
+ log_err(ctx, _("LUKS keyslot %u is invalid."), i);
+ return -1;
+ }
+
+ /* Ignore following check for detached header where offset can be zero. */
+ if (phdr->payloadOffset == 0)
+ continue;
+
+ if (phdr->payloadOffset <= phdr->keyblock[i].keyMaterialOffset) {
+ log_dbg(ctx, "Invalid offset %u in keyslot %u (beyond data area offset %u).",
+ phdr->keyblock[i].keyMaterialOffset, i,
+ phdr->payloadOffset);
+ log_err(ctx, _("LUKS keyslot %u is invalid."), i);
+ return -1;
+ }
+
+ if (phdr->payloadOffset < (phdr->keyblock[i].keyMaterialOffset + secs_per_stripes)) {
+ log_dbg(ctx, "Invalid keyslot size %u (offset %u, stripes %u) in "
+ "keyslot %u (beyond data area offset %u).",
+ secs_per_stripes,
+ phdr->keyblock[i].keyMaterialOffset,
+ phdr->keyblock[i].stripes,
+ i, phdr->payloadOffset);
+ log_err(ctx, _("LUKS keyslot %u is invalid."), i);
+ return -1;
+ }
+ }
+
+ /* check no keyslot overlaps with each other */
+ for (i = 1; i < LUKS_NUMKEYS; i++) {
+ prev = sorted_areas[i-1];
+ next = sorted_areas[i];
+ if (phdr->keyblock[next].keyMaterialOffset <
+ (phdr->keyblock[prev].keyMaterialOffset + secs_per_stripes)) {
+ log_dbg(ctx, "Not enough space in LUKS keyslot %d.", prev);
+ log_err(ctx, _("LUKS keyslot %u is invalid."), prev);
+ return -1;
+ }
+ }
+ /* do not check last keyslot on purpose, it must be tested in device size check */
+
+ return 0;
+}
+
+static const char *dbg_slot_state(crypt_keyslot_info ki)
+{
+ switch(ki) {
+ case CRYPT_SLOT_INACTIVE:
+ return "INACTIVE";
+ case CRYPT_SLOT_ACTIVE:
+ return "ACTIVE";
+ case CRYPT_SLOT_ACTIVE_LAST:
+ return "ACTIVE_LAST";
+ case CRYPT_SLOT_INVALID:
+ default:
+ return "INVALID";
+ }
+}
+
+int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ struct luks_phdr hdr;
+ int fd, devfd, r = 0;
+ size_t hdr_size;
+ size_t buffer_size;
+ ssize_t ret;
+ char *buffer = NULL;
+
+ r = LUKS_read_phdr(&hdr, 1, 0, ctx);
+ if (r)
+ return r;
+
+ hdr_size = LUKS_device_sectors(&hdr) << SECTOR_SHIFT;
+ buffer_size = size_round_up(hdr_size, crypt_getpagesize());
+
+ buffer = malloc(buffer_size);
+ if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) {
+ r = -ENOMEM;
+ goto out;
+ }
+ memset(buffer, 0, buffer_size);
+
+ log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes).",
+ sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS);
+
+ log_dbg(ctx, "Output backup file size: %zu bytes.", buffer_size);
+
+ devfd = device_open(ctx, device, O_RDONLY);
+ if (devfd < 0) {
+ log_err(ctx, _("Device %s is not a valid LUKS device."), device_path(device));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (read_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
+ buffer, hdr_size, 0) < (ssize_t)hdr_size) {
+ r = -EIO;
+ goto out;
+ }
+
+ /* Wipe unused area, so backup cannot contain old signatures */
+ if (hdr.keyblock[0].keyMaterialOffset * SECTOR_SIZE == LUKS_ALIGN_KEYSLOTS)
+ memset(buffer + sizeof(hdr), 0, LUKS_ALIGN_KEYSLOTS - sizeof(hdr));
+
+ fd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
+ if (fd == -1) {
+ if (errno == EEXIST)
+ log_err(ctx, _("Requested header backup file %s already exists."), backup_file);
+ else
+ log_err(ctx, _("Cannot create header backup file %s."), backup_file);
+ r = -EINVAL;
+ goto out;
+ }
+ ret = write_buffer(fd, buffer, buffer_size);
+ close(fd);
+ if (ret < (ssize_t)buffer_size) {
+ log_err(ctx, _("Cannot write header backup file %s."), backup_file);
+ r = -EIO;
+ goto out;
+ }
+
+ r = 0;
+out:
+ crypt_safe_memzero(&hdr, sizeof(hdr));
+ crypt_safe_memzero(buffer, buffer_size);
+ free(buffer);
+ return r;
+}
+
+int LUKS_hdr_restore(
+ const char *backup_file,
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ int fd, r = 0, devfd = -1, diff_uuid = 0;
+ ssize_t ret, buffer_size = 0;
+ char *buffer = NULL, msg[200];
+ struct luks_phdr hdr_file;
+
+ r = LUKS_read_phdr_backup(backup_file, &hdr_file, 0, ctx);
+ if (r == -ENOENT)
+ return r;
+
+ if (!r)
+ buffer_size = LUKS_device_sectors(&hdr_file) << SECTOR_SHIFT;
+
+ if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
+ log_err(ctx, _("Backup file does not contain valid LUKS header."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ buffer = malloc(buffer_size);
+ if (!buffer) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ fd = open(backup_file, O_RDONLY);
+ if (fd == -1) {
+ log_err(ctx, _("Cannot open header backup file %s."), backup_file);
+ r = -EINVAL;
+ goto out;
+ }
+
+ ret = read_buffer(fd, buffer, buffer_size);
+ close(fd);
+ if (ret < buffer_size) {
+ log_err(ctx, _("Cannot read header backup file %s."), backup_file);
+ r = -EIO;
+ goto out;
+ }
+
+ r = LUKS_read_phdr(hdr, 0, 0, ctx);
+ if (r == 0) {
+ log_dbg(ctx, "Device %s already contains LUKS header, checking UUID and offset.", device_path(device));
+ if(hdr->payloadOffset != hdr_file.payloadOffset ||
+ hdr->keyBytes != hdr_file.keyBytes) {
+ log_err(ctx, _("Data offset or key size differs on device and backup, restore failed."));
+ r = -EINVAL;
+ goto out;
+ }
+ if (memcmp(hdr->uuid, hdr_file.uuid, UUID_STRING_L))
+ diff_uuid = 1;
+ }
+
+ if (snprintf(msg, sizeof(msg), _("Device %s %s%s"), device_path(device),
+ r ? _("does not contain LUKS header. Replacing header can destroy data on that device.") :
+ _("already contains LUKS header. Replacing header will destroy existing keyslots."),
+ diff_uuid ? _("\nWARNING: real device header has different UUID than backup!") : "") < 0) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (!crypt_confirm(ctx, msg)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes) to device %s.",
+ sizeof(*hdr), buffer_size - LUKS_ALIGN_KEYSLOTS, device_path(device));
+
+ devfd = device_open(ctx, device, O_RDWR);
+ if (devfd < 0) {
+ if (errno == EACCES)
+ log_err(ctx, _("Cannot write to device %s, permission denied."),
+ device_path(device));
+ else
+ log_err(ctx, _("Cannot open device %s."), device_path(device));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
+ buffer, buffer_size, 0) < buffer_size) {
+ r = -EIO;
+ goto out;
+ }
+
+ /* Be sure to reload new data */
+ r = LUKS_read_phdr(hdr, 1, 0, ctx);
+out:
+ device_sync(ctx, device);
+ crypt_safe_memzero(buffer, buffer_size);
+ free(buffer);
+ return r;
+}
+
+/* This routine should do some just basic recovery for known problems. */
+static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
+{
+ struct luks_phdr temp_phdr;
+ const unsigned char *sector = (const unsigned char*)phdr;
+ struct volume_key *vk;
+ int i, bad, r, need_write = 0;
+
+ if (phdr->keyBytes != 16 && phdr->keyBytes != 32 && phdr->keyBytes != 64) {
+ log_err(ctx, _("Non standard key size, manual repair required."));
+ return -EINVAL;
+ }
+
+ /*
+ * cryptsetup 1.0 did not align keyslots to 4k, cannot repair this one
+ * Also we cannot trust possibly broken keyslots metadata here through LUKS_keyslots_offset().
+ * Expect first keyslot is aligned, if not, then manual repair is necessary.
+ */
+ if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
+ log_err(ctx, _("Non standard keyslots alignment, manual repair required."));
+ return -EINVAL;
+ }
+
+ /*
+ * ECB mode does not use IV but legacy dmcrypt silently allows it.
+ * Today device cannot be activated anyway, so we need to fix it here.
+ */
+ if (!strncmp(phdr->cipherMode, "ecb-", 4)) {
+ log_err(ctx, _("Cipher mode repaired (%s -> %s)."), phdr->cipherMode, "ecb");
+ memset(phdr->cipherMode, 0, LUKS_CIPHERMODE_L);
+ strcpy(phdr->cipherMode, "ecb");
+ need_write = 1;
+ }
+
+ /*
+ * Old cryptsetup expects "sha1", gcrypt allows case insensitive names,
+ * so always convert hash to lower case in header
+ */
+ if (_to_lower(phdr->hashSpec, LUKS_HASHSPEC_L)) {
+ log_err(ctx, _("Cipher hash repaired to lowercase (%s)."), phdr->hashSpec);
+ if (crypt_hmac_size(phdr->hashSpec) < LUKS_DIGESTSIZE) {
+ log_err(ctx, _("Requested LUKS hash %s is not supported."), phdr->hashSpec);
+ return -EINVAL;
+ }
+ need_write = 1;
+ }
+
+ r = LUKS_check_cipher(ctx, phdr->keyBytes, phdr->cipherName, phdr->cipherMode);
+ if (r < 0)
+ return -EINVAL;
+
+ vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);
+ if (!vk)
+ return -ENOMEM;
+
+ log_verbose(ctx, _("Repairing keyslots."));
+
+ log_dbg(ctx, "Generating second header with the same parameters for check.");
+ /* cipherName, cipherMode, hashSpec, uuid are already null terminated */
+ /* payloadOffset - cannot check */
+ r = LUKS_generate_phdr(&temp_phdr, vk, phdr->cipherName, phdr->cipherMode,
+ phdr->hashSpec, phdr->uuid,
+ phdr->payloadOffset * SECTOR_SIZE, 0, 0, ctx);
+ if (r < 0)
+ goto out;
+
+ for(i = 0; i < LUKS_NUMKEYS; ++i) {
+ if (phdr->keyblock[i].active == LUKS_KEY_ENABLED) {
+ log_dbg(ctx, "Skipping repair for active keyslot %i.", i);
+ continue;
+ }
+
+ bad = 0;
+ if (phdr->keyblock[i].keyMaterialOffset != temp_phdr.keyblock[i].keyMaterialOffset) {
+ log_err(ctx, _("Keyslot %i: offset repaired (%u -> %u)."), i,
+ (unsigned)phdr->keyblock[i].keyMaterialOffset,
+ (unsigned)temp_phdr.keyblock[i].keyMaterialOffset);
+ phdr->keyblock[i].keyMaterialOffset = temp_phdr.keyblock[i].keyMaterialOffset;
+ bad = 1;
+ }
+
+ if (phdr->keyblock[i].stripes != temp_phdr.keyblock[i].stripes) {
+ log_err(ctx, _("Keyslot %i: stripes repaired (%u -> %u)."), i,
+ (unsigned)phdr->keyblock[i].stripes,
+ (unsigned)temp_phdr.keyblock[i].stripes);
+ phdr->keyblock[i].stripes = temp_phdr.keyblock[i].stripes;
+ bad = 1;
+ }
+
+ /* Known case - MSDOS partition table signature */
+ if (i == 6 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) {
+ log_err(ctx, _("Keyslot %i: bogus partition signature."), i);
+ bad = 1;
+ }
+
+ if(bad) {
+ log_err(ctx, _("Keyslot %i: salt wiped."), i);
+ phdr->keyblock[i].active = LUKS_KEY_DISABLED;
+ memset(&phdr->keyblock[i].passwordSalt, 0x00, LUKS_SALTSIZE);
+ phdr->keyblock[i].passwordIterations = 0;
+ }
+
+ if (bad)
+ need_write = 1;
+ }
+
+ /*
+ * check repair result before writing because repair can't fix out of order
+ * keyslot offsets and would corrupt header again
+ */
+ if (LUKS_check_keyslots(ctx, phdr))
+ r = -EINVAL;
+ else if (need_write) {
+ log_verbose(ctx, _("Writing LUKS header to disk."));
+ r = LUKS_write_phdr(phdr, ctx);
+ }
+out:
+ if (r)
+ log_err(ctx, _("Repair failed."));
+ crypt_free_volume_key(vk);
+ crypt_safe_memzero(&temp_phdr, sizeof(temp_phdr));
+ return r;
+}
+
+static int _check_and_convert_hdr(const char *device,
+ struct luks_phdr *hdr,
+ int require_luks_device,
+ int repair,
+ struct crypt_device *ctx)
+{
+ int r = 0;
+ unsigned int i;
+ char luksMagic[] = LUKS_MAGIC;
+
+ hdr->version = be16_to_cpu(hdr->version);
+ if (memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */
+ log_dbg(ctx, "LUKS header not detected.");
+ if (require_luks_device)
+ log_err(ctx, _("Device %s is not a valid LUKS device."), device);
+ return -EINVAL;
+ } else if (hdr->version != 1) {
+ log_err(ctx, _("Unsupported LUKS version %d."), hdr->version);
+ return -EINVAL;
+ }
+
+ hdr->hashSpec[LUKS_HASHSPEC_L - 1] = '\0';
+ if (crypt_hmac_size(hdr->hashSpec) < LUKS_DIGESTSIZE) {
+ log_err(ctx, _("Requested LUKS hash %s is not supported."), hdr->hashSpec);
+ r = -EINVAL;
+ }
+
+ /* Header detected */
+ hdr->payloadOffset = be32_to_cpu(hdr->payloadOffset);
+ hdr->keyBytes = be32_to_cpu(hdr->keyBytes);
+ hdr->mkDigestIterations = be32_to_cpu(hdr->mkDigestIterations);
+
+ for (i = 0; i < LUKS_NUMKEYS; ++i) {
+ hdr->keyblock[i].active = be32_to_cpu(hdr->keyblock[i].active);
+ hdr->keyblock[i].passwordIterations = be32_to_cpu(hdr->keyblock[i].passwordIterations);
+ hdr->keyblock[i].keyMaterialOffset = be32_to_cpu(hdr->keyblock[i].keyMaterialOffset);
+ hdr->keyblock[i].stripes = be32_to_cpu(hdr->keyblock[i].stripes);
+ }
+
+ if (LUKS_check_keyslots(ctx, hdr))
+ r = -EINVAL;
+
+ /* Avoid unterminated strings */
+ hdr->cipherName[LUKS_CIPHERNAME_L - 1] = '\0';
+ hdr->cipherMode[LUKS_CIPHERMODE_L - 1] = '\0';
+ hdr->uuid[UUID_STRING_L - 1] = '\0';
+
+ if (repair) {
+ if (!strncmp(hdr->cipherMode, "ecb-", 4)) {
+ log_err(ctx, _("LUKS cipher mode %s is invalid."), hdr->cipherMode);
+ r = -EINVAL;
+ }
+
+ if (_is_not_lower(hdr->hashSpec, LUKS_HASHSPEC_L)) {
+ log_err(ctx, _("LUKS hash %s is invalid."), hdr->hashSpec);
+ r = -EINVAL;
+ }
+
+ if (r == -EINVAL)
+ r = _keyslot_repair(hdr, ctx);
+ else
+ log_verbose(ctx, _("No known problems detected for LUKS header."));
+ }
+
+ return r;
+}
+
+int LUKS_read_phdr_backup(const char *backup_file,
+ struct luks_phdr *hdr,
+ int require_luks_device,
+ struct crypt_device *ctx)
+{
+ ssize_t hdr_size = sizeof(struct luks_phdr);
+ int devfd = 0, r = 0;
+
+ log_dbg(ctx, "Reading LUKS header of size %d from backup file %s",
+ (int)hdr_size, backup_file);
+
+ devfd = open(backup_file, O_RDONLY);
+ if (devfd == -1) {
+ log_err(ctx, _("Cannot open header backup file %s."), backup_file);
+ return -ENOENT;
+ }
+
+ if (read_buffer(devfd, hdr, hdr_size) < hdr_size)
+ r = -EIO;
+ else
+ r = _check_and_convert_hdr(backup_file, hdr,
+ require_luks_device, 0, ctx);
+
+ close(devfd);
+ return r;
+}
+
+int LUKS_read_phdr(struct luks_phdr *hdr,
+ int require_luks_device,
+ int repair,
+ struct crypt_device *ctx)
+{
+ int devfd, r = 0;
+ struct device *device = crypt_metadata_device(ctx);
+ ssize_t hdr_size = sizeof(struct luks_phdr);
+
+ /* LUKS header starts at offset 0, first keyslot on LUKS_ALIGN_KEYSLOTS */
+ assert(sizeof(struct luks_phdr) <= LUKS_ALIGN_KEYSLOTS);
+
+ /* Stripes count cannot be changed without additional code fixes yet */
+ assert(LUKS_STRIPES == 4000);
+
+ if (repair && !require_luks_device)
+ return -EINVAL;
+
+ log_dbg(ctx, "Reading LUKS header of size %zu from device %s",
+ hdr_size, device_path(device));
+
+ devfd = device_open(ctx, device, O_RDONLY);
+ if (devfd < 0) {
+ log_err(ctx, _("Cannot open device %s."), device_path(device));
+ return -EINVAL;
+ }
+
+ if (read_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
+ hdr, hdr_size, 0) < hdr_size)
+ r = -EIO;
+ else
+ r = _check_and_convert_hdr(device_path(device), hdr, require_luks_device,
+ repair, ctx);
+
+ if (!r)
+ r = LUKS_check_device_size(ctx, hdr, 0);
+
+ /*
+ * Cryptsetup 1.0.0 did not align keyslots to 4k (very rare version).
+ * Disable direct-io to avoid possible IO errors if underlying device
+ * has bigger sector size.
+ */
+ if (!r && hdr->keyblock[0].keyMaterialOffset * SECTOR_SIZE < LUKS_ALIGN_KEYSLOTS) {
+ log_dbg(ctx, "Old unaligned LUKS keyslot detected, disabling direct-io.");
+ device_disable_direct_io(device);
+ }
+
+ return r;
+}
+
+int LUKS_write_phdr(struct luks_phdr *hdr,
+ struct crypt_device *ctx)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ ssize_t hdr_size = sizeof(struct luks_phdr);
+ int devfd = 0;
+ unsigned int i;
+ struct luks_phdr convHdr;
+ int r;
+
+ log_dbg(ctx, "Updating LUKS header of size %zu on device %s",
+ sizeof(struct luks_phdr), device_path(device));
+
+ r = LUKS_check_device_size(ctx, hdr, 1);
+ if (r)
+ return r;
+
+ devfd = device_open(ctx, device, O_RDWR);
+ if (devfd < 0) {
+ if (errno == EACCES)
+ log_err(ctx, _("Cannot write to device %s, permission denied."),
+ device_path(device));
+ else
+ log_err(ctx, _("Cannot open device %s."), device_path(device));
+ return -EINVAL;
+ }
+
+ memcpy(&convHdr, hdr, hdr_size);
+ memset(&convHdr._padding, 0, sizeof(convHdr._padding));
+
+ /* Convert every uint16/32_t item to network byte order */
+ convHdr.version = cpu_to_be16(hdr->version);
+ convHdr.payloadOffset = cpu_to_be32(hdr->payloadOffset);
+ convHdr.keyBytes = cpu_to_be32(hdr->keyBytes);
+ convHdr.mkDigestIterations = cpu_to_be32(hdr->mkDigestIterations);
+ for(i = 0; i < LUKS_NUMKEYS; ++i) {
+ convHdr.keyblock[i].active = cpu_to_be32(hdr->keyblock[i].active);
+ convHdr.keyblock[i].passwordIterations = cpu_to_be32(hdr->keyblock[i].passwordIterations);
+ convHdr.keyblock[i].keyMaterialOffset = cpu_to_be32(hdr->keyblock[i].keyMaterialOffset);
+ convHdr.keyblock[i].stripes = cpu_to_be32(hdr->keyblock[i].stripes);
+ }
+
+ r = write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
+ &convHdr, hdr_size, 0) < hdr_size ? -EIO : 0;
+ if (r)
+ log_err(ctx, _("Error during update of LUKS header on device %s."), device_path(device));
+
+ device_sync(ctx, device);
+
+ /* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
+ if (!r) {
+ r = LUKS_read_phdr(hdr, 1, 0, ctx);
+ if (r)
+ log_err(ctx, _("Error re-reading LUKS header after update on device %s."),
+ device_path(device));
+ }
+
+ return r;
+}
+
+/* Check that kernel supports requested cipher by decryption of one sector */
+int LUKS_check_cipher(struct crypt_device *ctx, size_t keylength, const char *cipher, const char *cipher_mode)
+{
+ int r;
+ struct volume_key *empty_key;
+ char buf[SECTOR_SIZE];
+
+ log_dbg(ctx, "Checking if cipher %s-%s is usable.", cipher, cipher_mode);
+
+ empty_key = crypt_alloc_volume_key(keylength, NULL);
+ if (!empty_key)
+ return -ENOMEM;
+
+ /* No need to get KEY quality random but it must avoid known weak keys. */
+ r = crypt_random_get(ctx, empty_key->key, empty_key->keylength, CRYPT_RND_NORMAL);
+ if (!r)
+ r = LUKS_decrypt_from_storage(buf, sizeof(buf), cipher, cipher_mode, empty_key, 0, ctx);
+
+ crypt_free_volume_key(empty_key);
+ crypt_safe_memzero(buf, sizeof(buf));
+ return r;
+}
+
+int LUKS_generate_phdr(struct luks_phdr *header,
+ const struct volume_key *vk,
+ const char *cipherName,
+ const char *cipherMode,
+ const char *hashSpec,
+ const char *uuid,
+ uint64_t data_offset, /* in bytes */
+ uint64_t align_offset, /* in bytes */
+ uint64_t required_alignment, /* in bytes */
+ struct crypt_device *ctx)
+{
+ int i, r;
+ size_t keyslot_sectors, header_sectors;
+ uuid_t partitionUuid;
+ struct crypt_pbkdf_type *pbkdf;
+ double PBKDF2_temp;
+ char luksMagic[] = LUKS_MAGIC;
+
+ if (data_offset % SECTOR_SIZE || align_offset % SECTOR_SIZE ||
+ required_alignment % SECTOR_SIZE)
+ return -EINVAL;
+
+ memset(header, 0, sizeof(struct luks_phdr));
+
+ keyslot_sectors = AF_split_sectors(vk->keylength, LUKS_STRIPES);
+ header_sectors = LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE;
+
+ for (i = 0; i < LUKS_NUMKEYS; i++) {
+ header->keyblock[i].active = LUKS_KEY_DISABLED;
+ header->keyblock[i].keyMaterialOffset = header_sectors;
+ header->keyblock[i].stripes = LUKS_STRIPES;
+ header_sectors = size_round_up(header_sectors + keyslot_sectors,
+ LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
+ }
+ /* In sector is now size of all keyslot material space */
+
+ /* Data offset has priority */
+ if (data_offset)
+ header->payloadOffset = data_offset / SECTOR_SIZE;
+ else if (required_alignment) {
+ header->payloadOffset = size_round_up(header_sectors, (required_alignment / SECTOR_SIZE));
+ header->payloadOffset += (align_offset / SECTOR_SIZE);
+ } else
+ header->payloadOffset = 0;
+
+ if (header->payloadOffset && header->payloadOffset < header_sectors) {
+ log_err(ctx, _("Data offset for LUKS header must be "
+ "either 0 or higher than header size."));
+ return -EINVAL;
+ }
+
+ if (crypt_hmac_size(hashSpec) < LUKS_DIGESTSIZE) {
+ log_err(ctx, _("Requested LUKS hash %s is not supported."), hashSpec);
+ return -EINVAL;
+ }
+
+ if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
+ log_err(ctx, _("Wrong LUKS UUID format provided."));
+ return -EINVAL;
+ }
+ if (!uuid)
+ uuid_generate(partitionUuid);
+
+ /* Set Magic */
+ memcpy(header->magic,luksMagic,LUKS_MAGIC_L);
+ header->version=1;
+ strncpy(header->cipherName,cipherName,LUKS_CIPHERNAME_L-1);
+ strncpy(header->cipherMode,cipherMode,LUKS_CIPHERMODE_L-1);
+ strncpy(header->hashSpec,hashSpec,LUKS_HASHSPEC_L-1);
+ _to_lower(header->hashSpec, LUKS_HASHSPEC_L);
+
+ header->keyBytes=vk->keylength;
+
+ log_dbg(ctx, "Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes",
+ header->version, header->hashSpec ,header->cipherName, header->cipherMode,
+ header->keyBytes);
+
+ r = crypt_random_get(ctx, header->mkDigestSalt, LUKS_SALTSIZE, CRYPT_RND_SALT);
+ if(r < 0) {
+ log_err(ctx, _("Cannot create LUKS header: reading random salt failed."));
+ return r;
+ }
+
+ /* Compute volume key digest */
+ pbkdf = crypt_get_pbkdf(ctx);
+ r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength);
+ if (r < 0)
+ return r;
+ assert(pbkdf->iterations);
+
+ if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK && pbkdf->time_ms == 0)
+ PBKDF2_temp = LUKS_MKD_ITERATIONS_MIN;
+ else /* iterations per ms * LUKS_MKD_ITERATIONS_MS */
+ PBKDF2_temp = (double)pbkdf->iterations * LUKS_MKD_ITERATIONS_MS / pbkdf->time_ms;
+
+ if (PBKDF2_temp > (double)UINT32_MAX)
+ return -EINVAL;
+ header->mkDigestIterations = AT_LEAST((uint32_t)PBKDF2_temp, LUKS_MKD_ITERATIONS_MIN);
+ assert(header->mkDigestIterations);
+
+ r = crypt_pbkdf(CRYPT_KDF_PBKDF2, header->hashSpec, vk->key,vk->keylength,
+ header->mkDigestSalt, LUKS_SALTSIZE,
+ header->mkDigest,LUKS_DIGESTSIZE,
+ header->mkDigestIterations, 0, 0);
+ if (r < 0) {
+ log_err(ctx, _("Cannot create LUKS header: header digest failed (using hash %s)."),
+ header->hashSpec);
+ return r;
+ }
+
+ uuid_unparse(partitionUuid, header->uuid);
+
+ log_dbg(ctx, "Data offset %d, UUID %s, digest iterations %" PRIu32,
+ header->payloadOffset, header->uuid, header->mkDigestIterations);
+
+ return 0;
+}
+
+int LUKS_hdr_uuid_set(
+ struct luks_phdr *hdr,
+ const char *uuid,
+ struct crypt_device *ctx)
+{
+ uuid_t partitionUuid;
+
+ if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
+ log_err(ctx, _("Wrong LUKS UUID format provided."));
+ return -EINVAL;
+ }
+ if (!uuid)
+ uuid_generate(partitionUuid);
+
+ uuid_unparse(partitionUuid, hdr->uuid);
+
+ return LUKS_write_phdr(hdr, ctx);
+}
+
+int LUKS_set_key(unsigned int keyIndex,
+ const char *password, size_t passwordLen,
+ struct luks_phdr *hdr, struct volume_key *vk,
+ struct crypt_device *ctx)
+{
+ struct volume_key *derived_key;
+ char *AfKey = NULL;
+ size_t AFEKSize;
+ struct crypt_pbkdf_type *pbkdf;
+ int r;
+
+ if(hdr->keyblock[keyIndex].active != LUKS_KEY_DISABLED) {
+ log_err(ctx, _("Key slot %d active, purge first."), keyIndex);
+ return -EINVAL;
+ }
+
+ /* LUKS keyslot has always at least 4000 stripes according to specification */
+ if(hdr->keyblock[keyIndex].stripes < 4000) {
+ log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?"),
+ keyIndex);
+ return -EINVAL;
+ }
+
+ log_dbg(ctx, "Calculating data for key slot %d", keyIndex);
+ pbkdf = crypt_get_pbkdf(ctx);
+ r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength);
+ if (r < 0)
+ return r;
+ assert(pbkdf->iterations);
+
+ /*
+ * Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
+ */
+ hdr->keyblock[keyIndex].passwordIterations =
+ AT_LEAST(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN);
+ log_dbg(ctx, "Key slot %d use %" PRIu32 " password iterations.", keyIndex,
+ hdr->keyblock[keyIndex].passwordIterations);
+
+ derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
+ if (!derived_key)
+ return -ENOMEM;
+
+ r = crypt_random_get(ctx, hdr->keyblock[keyIndex].passwordSalt,
+ LUKS_SALTSIZE, CRYPT_RND_SALT);
+ if (r < 0)
+ goto out;
+
+ r = crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, password, passwordLen,
+ hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
+ derived_key->key, hdr->keyBytes,
+ hdr->keyblock[keyIndex].passwordIterations, 0, 0);
+ if (r < 0) {
+ if ((crypt_backend_flags() & CRYPT_BACKEND_PBKDF2_INT) &&
+ hdr->keyblock[keyIndex].passwordIterations > INT_MAX)
+ log_err(ctx, _("PBKDF2 iteration value overflow."));
+ goto out;
+ }
+
+ /*
+ * AF splitting, the volume key stored in vk->key is split to AfKey
+ */
+ assert(vk->keylength == hdr->keyBytes);
+ AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
+ AfKey = crypt_safe_alloc(AFEKSize);
+ if (!AfKey) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ log_dbg(ctx, "Using hash %s for AF in key slot %d, %d stripes",
+ hdr->hashSpec, keyIndex, hdr->keyblock[keyIndex].stripes);
+ r = AF_split(ctx, vk->key, AfKey, vk->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
+ if (r < 0)
+ goto out;
+
+ log_dbg(ctx, "Updating key slot %d [0x%04x] area.", keyIndex,
+ hdr->keyblock[keyIndex].keyMaterialOffset << 9);
+ /* Encryption via dm */
+ r = LUKS_encrypt_to_storage(AfKey,
+ AFEKSize,
+ hdr->cipherName, hdr->cipherMode,
+ derived_key,
+ hdr->keyblock[keyIndex].keyMaterialOffset,
+ ctx);
+ if (r < 0)
+ goto out;
+
+ /* Mark the key as active in phdr */
+ r = LUKS_keyslot_set(hdr, (int)keyIndex, 1, ctx);
+ if (r < 0)
+ goto out;
+
+ r = LUKS_write_phdr(hdr, ctx);
+ if (r < 0)
+ goto out;
+
+ r = 0;
+out:
+ crypt_safe_free(AfKey);
+ crypt_free_volume_key(derived_key);
+ return r;
+}
+
+/* Check whether a volume key is invalid. */
+int LUKS_verify_volume_key(const struct luks_phdr *hdr,
+ const struct volume_key *vk)
+{
+ char checkHashBuf[LUKS_DIGESTSIZE];
+
+ if (crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, vk->key, vk->keylength,
+ hdr->mkDigestSalt, LUKS_SALTSIZE,
+ checkHashBuf, LUKS_DIGESTSIZE,
+ hdr->mkDigestIterations, 0, 0) < 0)
+ return -EINVAL;
+
+ if (crypt_backend_memeq(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE))
+ return -EPERM;
+
+ return 0;
+}
+
+/* Try to open a particular key slot */
+static int LUKS_open_key(unsigned int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct volume_key **vk,
+ struct crypt_device *ctx)
+{
+ crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
+ struct volume_key *derived_key;
+ char *AfKey = NULL;
+ size_t AFEKSize;
+ int r;
+
+ log_dbg(ctx, "Trying to open key slot %d [%s].", keyIndex,
+ dbg_slot_state(ki));
+
+ if (ki < CRYPT_SLOT_ACTIVE)
+ return -ENOENT;
+
+ derived_key = crypt_alloc_volume_key(hdr->keyBytes, NULL);
+ if (!derived_key)
+ return -ENOMEM;
+
+ *vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
+ if (!*vk) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ AFEKSize = AF_split_sectors(hdr->keyBytes, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
+ AfKey = crypt_safe_alloc(AFEKSize);
+ if (!AfKey) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = crypt_pbkdf(CRYPT_KDF_PBKDF2, hdr->hashSpec, password, passwordLen,
+ hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
+ derived_key->key, hdr->keyBytes,
+ hdr->keyblock[keyIndex].passwordIterations, 0, 0);
+ if (r < 0) {
+ log_err(ctx, _("Cannot open keyslot (using hash %s)."), hdr->hashSpec);
+ goto out;
+ }
+
+ log_dbg(ctx, "Reading key slot %d area.", keyIndex);
+ r = LUKS_decrypt_from_storage(AfKey,
+ AFEKSize,
+ hdr->cipherName, hdr->cipherMode,
+ derived_key,
+ hdr->keyblock[keyIndex].keyMaterialOffset,
+ ctx);
+ if (r < 0)
+ goto out;
+
+ r = AF_merge(AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
+ if (r < 0)
+ goto out;
+
+ r = LUKS_verify_volume_key(hdr, *vk);
+
+ /* Allow only empty passphrase with null cipher */
+ if (!r && crypt_is_cipher_null(hdr->cipherName) && passwordLen)
+ r = -EPERM;
+out:
+ if (r < 0) {
+ crypt_free_volume_key(*vk);
+ *vk = NULL;
+ }
+ crypt_safe_free(AfKey);
+ crypt_free_volume_key(derived_key);
+ return r;
+}
+
+int LUKS_open_key_with_hdr(int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct volume_key **vk,
+ struct crypt_device *ctx)
+{
+ unsigned int i, tried = 0;
+ int r;
+
+ if (keyIndex >= 0) {
+ r = LUKS_open_key(keyIndex, password, passwordLen, hdr, vk, ctx);
+ return (r < 0) ? r : keyIndex;
+ }
+
+ for (i = 0; i < LUKS_NUMKEYS; i++) {
+ r = LUKS_open_key(i, password, passwordLen, hdr, vk, ctx);
+ if (r == 0)
+ return i;
+
+ /* Do not retry for errors that are no -EPERM or -ENOENT,
+ former meaning password wrong, latter key slot inactive */
+ if ((r != -EPERM) && (r != -ENOENT))
+ return r;
+ if (r == -EPERM)
+ tried++;
+ }
+ /* Warning, early returns above */
+ return tried ? -EPERM : -ENOENT;
+}
+
+int LUKS_del_key(unsigned int keyIndex,
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx)
+{
+ struct device *device = crypt_metadata_device(ctx);
+ unsigned int startOffset, endOffset;
+ int r;
+
+ r = LUKS_read_phdr(hdr, 1, 0, ctx);
+ if (r)
+ return r;
+
+ r = LUKS_keyslot_set(hdr, keyIndex, 0, ctx);
+ if (r) {
+ log_err(ctx, _("Key slot %d is invalid, please select keyslot between 0 and %d."),
+ keyIndex, LUKS_NUMKEYS - 1);
+ return r;
+ }
+
+ /* secure deletion of key material */
+ startOffset = hdr->keyblock[keyIndex].keyMaterialOffset;
+ endOffset = startOffset + AF_split_sectors(hdr->keyBytes, hdr->keyblock[keyIndex].stripes);
+
+ r = crypt_wipe_device(ctx, device, CRYPT_WIPE_SPECIAL, startOffset * SECTOR_SIZE,
+ (endOffset - startOffset) * SECTOR_SIZE,
+ (endOffset - startOffset) * SECTOR_SIZE, NULL, NULL);
+ if (r) {
+ if (r == -EACCES) {
+ log_err(ctx, _("Cannot write to device %s, permission denied."),
+ device_path(device));
+ r = -EINVAL;
+ } else
+ log_err(ctx, _("Cannot wipe device %s."),
+ device_path(device));
+ return r;
+ }
+
+ /* Wipe keyslot info */
+ memset(&hdr->keyblock[keyIndex].passwordSalt, 0, LUKS_SALTSIZE);
+ hdr->keyblock[keyIndex].passwordIterations = 0;
+
+ r = LUKS_write_phdr(hdr, ctx);
+
+ return r;
+}
+
+crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot)
+{
+ int i;
+
+ if(keyslot >= LUKS_NUMKEYS || keyslot < 0)
+ return CRYPT_SLOT_INVALID;
+
+ if (hdr->keyblock[keyslot].active == LUKS_KEY_DISABLED)
+ return CRYPT_SLOT_INACTIVE;
+
+ if (hdr->keyblock[keyslot].active != LUKS_KEY_ENABLED)
+ return CRYPT_SLOT_INVALID;
+
+ for(i = 0; i < LUKS_NUMKEYS; i++)
+ if(i != keyslot && hdr->keyblock[i].active == LUKS_KEY_ENABLED)
+ return CRYPT_SLOT_ACTIVE;
+
+ return CRYPT_SLOT_ACTIVE_LAST;
+}
+
+int LUKS_keyslot_find_empty(struct luks_phdr *hdr)
+{
+ int i;
+
+ for (i = 0; i < LUKS_NUMKEYS; i++)
+ if(hdr->keyblock[i].active == LUKS_KEY_DISABLED)
+ break;
+
+ if (i == LUKS_NUMKEYS)
+ return -EINVAL;
+
+ return i;
+}
+
+int LUKS_keyslot_active_count(struct luks_phdr *hdr)
+{
+ int i, num = 0;
+
+ for (i = 0; i < LUKS_NUMKEYS; i++)
+ if(hdr->keyblock[i].active == LUKS_KEY_ENABLED)
+ num++;
+
+ return num;
+}
+
+int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable, struct crypt_device *ctx)
+{
+ crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyslot);
+
+ if (ki == CRYPT_SLOT_INVALID)
+ return -EINVAL;
+
+ hdr->keyblock[keyslot].active = enable ? LUKS_KEY_ENABLED : LUKS_KEY_DISABLED;
+ log_dbg(ctx, "Key slot %d was %s in LUKS header.", keyslot, enable ? "enabled" : "disabled");
+ return 0;
+}
+
+int LUKS1_activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vk,
+ uint32_t flags)
+{
+ int r;
+ struct crypt_dm_active_device dmd = {
+ .flags = flags,
+ .uuid = crypt_get_uuid(cd),
+ };
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
+ vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd),
+ crypt_get_data_offset(cd), crypt_get_integrity(cd),
+ crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
+ if (!r)
+ r = create_or_reload_device(cd, name, CRYPT_LUKS1, &dmd);
+
+ dm_targets_free(cd, &dmd);
+
+ return r;
+}
+
+int LUKS_wipe_header_areas(struct luks_phdr *hdr,
+ struct crypt_device *ctx)
+{
+ int i, r;
+ uint64_t offset, length;
+ size_t wipe_block;
+
+ r = LUKS_check_device_size(ctx, hdr, 1);
+ if (r)
+ return r;
+
+ /* Wipe complete header, keyslots and padding areas with zeroes. */
+ offset = 0;
+ length = (uint64_t)hdr->payloadOffset * SECTOR_SIZE;
+ wipe_block = 1024 * 1024;
+
+ /* On detached header or bogus header, wipe at least the first 4k */
+ if (length == 0 || length > (LUKS_MAX_KEYSLOT_SIZE * LUKS_NUMKEYS)) {
+ length = 4096;
+ wipe_block = 4096;
+ }
+
+ log_dbg(ctx, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
+ offset, length + offset);
+
+ r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_ZERO,
+ offset, length, wipe_block, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ /* Wipe keyslots areas */
+ wipe_block = 1024 * 1024;
+ for (i = 0; i < LUKS_NUMKEYS; i++) {
+ r = LUKS_keyslot_area(hdr, i, &offset, &length);
+ if (r < 0)
+ return r;
+
+ /* Ignore too big LUKS1 keyslots here */
+ if (length > LUKS_MAX_KEYSLOT_SIZE ||
+ offset > (LUKS_MAX_KEYSLOT_SIZE - length))
+ continue;
+
+ if (length == 0 || offset < 4096)
+ return -EINVAL;
+
+ log_dbg(ctx, "Wiping keyslot %i area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
+ i, offset, length + offset);
+
+ r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_RANDOM,
+ offset, length, wipe_block, NULL, NULL);
+ if (r < 0)
+ return r;
+ }
+
+ return r;
+}
+
+int LUKS_keyslot_pbkdf(struct luks_phdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf)
+{
+ if (LUKS_keyslot_info(hdr, keyslot) < CRYPT_SLOT_ACTIVE)
+ return -EINVAL;
+
+ pbkdf->type = CRYPT_KDF_PBKDF2;
+ pbkdf->hash = hdr->hashSpec;
+ pbkdf->iterations = hdr->keyblock[keyslot].passwordIterations;
+ pbkdf->max_memory_kb = 0;
+ pbkdf->parallel_threads = 0;
+ pbkdf->time_ms = 0;
+ pbkdf->flags = 0;
+ return 0;
+}
diff --git a/lib/luks1/luks.h b/lib/luks1/luks.h
new file mode 100644
index 0000000..9c3f386
--- /dev/null
+++ b/lib/luks1/luks.h
@@ -0,0 +1,194 @@
+/*
+ * LUKS - Linux Unified Key Setup
+ *
+ * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_CRYPTSETUP_LUKS_LUKS_H
+#define INCLUDED_CRYPTSETUP_LUKS_LUKS_H
+
+/*
+ * LUKS partition header
+ */
+
+#include "libcryptsetup.h"
+
+#define LUKS_CIPHERNAME_L 32
+#define LUKS_CIPHERMODE_L 32
+#define LUKS_HASHSPEC_L 32
+#define LUKS_DIGESTSIZE 20 // since SHA1
+#define LUKS_HMACSIZE 32
+#define LUKS_SALTSIZE 32
+#define LUKS_NUMKEYS 8
+
+// Minimal number of iterations
+#define LUKS_MKD_ITERATIONS_MIN 1000
+#define LUKS_SLOT_ITERATIONS_MIN 1000
+
+// Iteration time for digest in ms
+#define LUKS_MKD_ITERATIONS_MS 125
+
+#define LUKS_KEY_DISABLED_OLD 0
+#define LUKS_KEY_ENABLED_OLD 0xCAFE
+
+#define LUKS_KEY_DISABLED 0x0000DEAD
+#define LUKS_KEY_ENABLED 0x00AC71F3
+
+#define LUKS_STRIPES 4000
+
+// partition header starts with magic
+#define LUKS_MAGIC {'L','U','K','S', 0xba, 0xbe};
+#define LUKS_MAGIC_L 6
+
+/* Actually we need only 37, but we don't want struct autoaligning to kick in */
+#define UUID_STRING_L 40
+
+/* Offset to keyslot area [in bytes] */
+#define LUKS_ALIGN_KEYSLOTS 4096
+
+/* Maximal LUKS header size, for wipe [in bytes] */
+#define LUKS_MAX_KEYSLOT_SIZE 0x1000000 /* 16 MB, up to 32768 bits key */
+
+/* Any integer values are stored in network byte order on disk and must be
+converted */
+
+struct volume_key;
+struct device_backend;
+
+struct luks_phdr {
+ char magic[LUKS_MAGIC_L];
+ uint16_t version;
+ char cipherName[LUKS_CIPHERNAME_L];
+ char cipherMode[LUKS_CIPHERMODE_L];
+ char hashSpec[LUKS_HASHSPEC_L];
+ uint32_t payloadOffset;
+ uint32_t keyBytes;
+ char mkDigest[LUKS_DIGESTSIZE];
+ char mkDigestSalt[LUKS_SALTSIZE];
+ uint32_t mkDigestIterations;
+ char uuid[UUID_STRING_L];
+
+ struct {
+ uint32_t active;
+
+ /* parameters used for password processing */
+ uint32_t passwordIterations;
+ char passwordSalt[LUKS_SALTSIZE];
+
+ /* parameters used for AF store/load */
+ uint32_t keyMaterialOffset;
+ uint32_t stripes;
+ } keyblock[LUKS_NUMKEYS];
+
+ /* Align it to 512 sector size */
+ char _padding[432];
+};
+
+int LUKS_verify_volume_key(const struct luks_phdr *hdr,
+ const struct volume_key *vk);
+
+int LUKS_check_cipher(struct crypt_device *ctx,
+ size_t keylength,
+ const char *cipher,
+ const char *cipher_mode);
+
+int LUKS_generate_phdr(struct luks_phdr *header,
+ const struct volume_key *vk,
+ const char *cipherName,
+ const char *cipherMode,
+ const char *hashSpec,
+ const char *uuid,
+ uint64_t data_offset,
+ uint64_t align_offset,
+ uint64_t required_alignment,
+ struct crypt_device *ctx);
+
+int LUKS_read_phdr(
+ struct luks_phdr *hdr,
+ int require_luks_device,
+ int repair,
+ struct crypt_device *ctx);
+
+int LUKS_read_phdr_backup(
+ const char *backup_file,
+ struct luks_phdr *hdr,
+ int require_luks_device,
+ struct crypt_device *ctx);
+
+int LUKS_hdr_uuid_set(
+ struct luks_phdr *hdr,
+ const char *uuid,
+ struct crypt_device *ctx);
+
+int LUKS_hdr_backup(
+ const char *backup_file,
+ struct crypt_device *ctx);
+
+int LUKS_hdr_restore(
+ const char *backup_file,
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx);
+
+int LUKS_write_phdr(
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx);
+
+int LUKS_set_key(
+ unsigned int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct volume_key *vk,
+ struct crypt_device *ctx);
+
+int LUKS_open_key_with_hdr(
+ int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct volume_key **vk,
+ struct crypt_device *ctx);
+
+int LUKS_del_key(
+ unsigned int keyIndex,
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx);
+
+int LUKS_wipe_header_areas(struct luks_phdr *hdr,
+ struct crypt_device *ctx);
+
+crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot);
+int LUKS_keyslot_find_empty(struct luks_phdr *hdr);
+int LUKS_keyslot_active_count(struct luks_phdr *hdr);
+int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable,
+ struct crypt_device *ctx);
+int LUKS_keyslot_area(const struct luks_phdr *hdr,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length);
+size_t LUKS_device_sectors(const struct luks_phdr *hdr);
+size_t LUKS_keyslots_offset(const struct luks_phdr *hdr);
+int LUKS_keyslot_pbkdf(struct luks_phdr *hdr, int keyslot,
+ struct crypt_pbkdf_type *pbkdf);
+
+int LUKS1_activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vk,
+ uint32_t flags);
+
+#endif
diff --git a/lib/luks2/luks2.h b/lib/luks2/luks2.h
new file mode 100644
index 0000000..dfccf02
--- /dev/null
+++ b/lib/luks2/luks2.h
@@ -0,0 +1,497 @@
+/*
+ * LUKS - Linux Unified Key Setup v2
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_LUKS2_ONDISK_H
+#define _CRYPTSETUP_LUKS2_ONDISK_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "libcryptsetup.h"
+
+#define LUKS2_MAGIC_1ST "LUKS\xba\xbe"
+#define LUKS2_MAGIC_2ND "SKUL\xba\xbe"
+#define LUKS2_MAGIC_L 6
+#define LUKS2_UUID_L 40
+#define LUKS2_LABEL_L 48
+#define LUKS2_SALT_L 64
+#define LUKS2_CHECKSUM_ALG_L 32
+#define LUKS2_CHECKSUM_L 64
+
+#define LUKS2_KEYSLOTS_MAX 32
+#define LUKS2_TOKENS_MAX 32
+#define LUKS2_SEGMENT_MAX 32
+
+#define LUKS2_BUILTIN_TOKEN_PREFIX "luks2-"
+#define LUKS2_BUILTIN_TOKEN_PREFIX_LEN 6
+
+#define LUKS2_TOKEN_NAME_MAX 64
+
+#define LUKS2_TOKEN_KEYRING LUKS2_BUILTIN_TOKEN_PREFIX "keyring"
+
+#define LUKS2_DIGEST_MAX 8
+
+#define CRYPT_ANY_SEGMENT -1
+#define CRYPT_DEFAULT_SEGMENT -2
+#define CRYPT_ONE_SEGMENT -3
+
+#define CRYPT_ANY_DIGEST -1
+
+/* 20 MiBs */
+#define LUKS2_DEFAULT_NONE_REENCRYPTION_LENGTH 0x1400000
+
+/* 1 GiB */
+#define LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH 0x40000000
+
+/* supported reencryption requirement versions */
+#define LUKS2_REENCRYPT_REQ_VERSION UINT8_C(2)
+#define LUKS2_DECRYPT_DATASHIFT_REQ_VERSION UINT8_C(3)
+
+/* see reencrypt_assembly_verification_data() in luks2_reencrypt_digest.c */
+/* LUKS2_REENCRYPT_MAX_VERSION UINT8_C(207) */
+
+struct device;
+struct luks2_reencrypt;
+struct reenc_protection;
+struct crypt_lock_handle;
+struct crypt_dm_active_device;
+struct luks_phdr; /* LUKS1 for conversion */
+
+/*
+ * LUKS2 header on-disk.
+ *
+ * Binary header is followed by JSON area.
+ * JSON area is followed by keyslot area and data area,
+ * these are described in JSON metadata.
+ *
+ * Note: uuid, csum_alg are intentionally on the same offset as LUKS1
+ * (checksum alg replaces hash in LUKS1)
+ *
+ * String (char) should be zero terminated.
+ * Padding should be wiped.
+ * Checksum is calculated with csum zeroed (+ full JSON area).
+ */
+struct luks2_hdr_disk {
+ char magic[LUKS2_MAGIC_L];
+ uint16_t version; /* Version 2 */
+ uint64_t hdr_size; /* in bytes, including JSON area */
+ uint64_t seqid; /* increased on every update */
+ char label[LUKS2_LABEL_L];
+ char checksum_alg[LUKS2_CHECKSUM_ALG_L];
+ uint8_t salt[LUKS2_SALT_L]; /* unique for every header/offset */
+ char uuid[LUKS2_UUID_L];
+ char subsystem[LUKS2_LABEL_L]; /* owner subsystem label */
+ uint64_t hdr_offset; /* offset from device start in bytes */
+ char _padding[184];
+ uint8_t csum[LUKS2_CHECKSUM_L];
+ char _padding4096[7*512];
+ /* JSON area starts here */
+} __attribute__ ((packed));
+
+/*
+ * LUKS2 header in-memory.
+ */
+struct luks2_hdr {
+ size_t hdr_size;
+ uint64_t seqid;
+ unsigned int version;
+ char label[LUKS2_LABEL_L];
+ char subsystem[LUKS2_LABEL_L];
+ char checksum_alg[LUKS2_CHECKSUM_ALG_L];
+ uint8_t salt1[LUKS2_SALT_L];
+ uint8_t salt2[LUKS2_SALT_L];
+ char uuid[LUKS2_UUID_L];
+ void *jobj;
+ void *jobj_rollback;
+};
+
+struct luks2_keyslot_params {
+ enum { LUKS2_KEYSLOT_AF_LUKS1 = 0 } af_type;
+ enum { LUKS2_KEYSLOT_AREA_RAW = 0 } area_type;
+
+ union {
+ struct {
+ char hash[LUKS2_CHECKSUM_ALG_L]; // or include luks.h
+ unsigned int stripes;
+ } luks1;
+ } af;
+
+ union {
+ struct {
+ char encryption[65]; // or include utils_crypt.h
+ size_t key_size;
+ } raw;
+ } area;
+};
+
+/*
+ * Supportable header sizes (hdr_disk + JSON area)
+ * Also used as offset for the 2nd header.
+ */
+#define LUKS2_HDR_16K_LEN 0x4000
+
+#define LUKS2_HDR_BIN_LEN sizeof(struct luks2_hdr_disk)
+
+//#define LUKS2_DEFAULT_HDR_SIZE 0x400000 /* 4 MiB */
+#define LUKS2_DEFAULT_HDR_SIZE 0x1000000 /* 16 MiB */
+
+#define LUKS2_MAX_KEYSLOTS_SIZE 0x8000000 /* 128 MiB */
+
+#define LUKS2_HDR_OFFSET_MAX 0x400000 /* 4 MiB */
+
+/* Offsets for secondary header (for scan if primary header is corrupted). */
+#define LUKS2_HDR2_OFFSETS { 0x04000, 0x008000, 0x010000, 0x020000, \
+ 0x40000, 0x080000, 0x100000, 0x200000, LUKS2_HDR_OFFSET_MAX }
+
+int LUKS2_hdr_version_unlocked(struct crypt_device *cd,
+ const char *backup_file);
+
+int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair);
+int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr);
+int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr);
+int LUKS2_hdr_rollback(struct crypt_device *cd, struct luks2_hdr *hdr);
+int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr);
+int LUKS2_hdr_dump_json(struct crypt_device *cd, struct luks2_hdr *hdr, const char **json);
+
+int LUKS2_hdr_uuid(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const char *uuid);
+
+int LUKS2_hdr_labels(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const char *label,
+ const char *subsystem,
+ int commit);
+
+void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr);
+
+int LUKS2_hdr_backup(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const char *backup_file);
+int LUKS2_hdr_restore(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const char *backup_file);
+
+uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr);
+uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr);
+uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr);
+
+int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *cipher_spec);
+
+/*
+ * Generic LUKS2 keyslot
+ */
+int LUKS2_keyslot_open(struct crypt_device *cd,
+ int keyslot,
+ int segment,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vk);
+
+int LUKS2_keyslot_open_all_segments(struct crypt_device *cd,
+ int keyslot_old,
+ int keyslot_new,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vks);
+
+int LUKS2_keyslot_store(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const char *password,
+ size_t password_len,
+ const struct volume_key *vk,
+ const struct luks2_keyslot_params *params);
+
+int LUKS2_keyslot_wipe(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int wipe_area_only);
+
+crypt_keyslot_priority LUKS2_keyslot_priority_get(struct luks2_hdr *hdr, int keyslot);
+
+int LUKS2_keyslot_priority_set(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ crypt_keyslot_priority priority,
+ int commit);
+
+int LUKS2_keyslot_swap(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int keyslot2);
+
+/*
+ * Generic LUKS2 token
+ */
+int LUKS2_token_json_get(struct luks2_hdr *hdr,
+ int token,
+ const char **json);
+
+int LUKS2_token_assign(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int token,
+ int assign,
+ int commit);
+
+int LUKS2_token_is_assigned(struct luks2_hdr *hdr,
+ int keyslot,
+ int token);
+
+int LUKS2_token_assignment_copy(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot_from,
+ int keyslot_to,
+ int commit);
+
+int LUKS2_token_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *json,
+ int commit);
+
+crypt_token_info LUKS2_token_status(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char **type);
+
+int LUKS2_token_open_and_activate(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *name,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ uint32_t flags,
+ void *usrptr);
+
+int LUKS2_token_unlock_key(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ int segment,
+ void *usrptr,
+ struct volume_key **vk);
+
+int LUKS2_token_keyring_get(struct luks2_hdr *hdr,
+ int token,
+ struct crypt_token_params_luks2_keyring *keyring_params);
+
+int LUKS2_token_keyring_json(char *buffer, size_t buffer_size,
+ const struct crypt_token_params_luks2_keyring *keyring_params);
+
+int LUKS2_token_unlock_passphrase(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr,
+ char **passphrase,
+ size_t *passphrase_size);
+
+void crypt_token_unload_external_all(struct crypt_device *cd);
+
+/*
+ * Generic LUKS2 digest
+ */
+int LUKS2_digest_any_matching(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk);
+
+int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int segment,
+ const struct volume_key *vk);
+
+int LUKS2_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk,
+ int keyslot);
+
+int LUKS2_digest_assign(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int digest,
+ int assign,
+ int commit);
+
+int LUKS2_digest_segment_assign(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int segment,
+ int digest,
+ int assign,
+ int commit);
+
+int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot);
+
+int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment);
+
+int LUKS2_digest_create(struct crypt_device *cd,
+ const char *type,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk);
+
+/*
+ * LUKS2 generic
+ */
+int LUKS2_activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vk,
+ uint32_t flags);
+
+int LUKS2_activate_multi(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vks,
+ uint64_t device_size,
+ uint32_t flags);
+
+int LUKS2_deactivate(struct crypt_device *cd,
+ const char *name,
+ struct luks2_hdr *hdr,
+ struct crypt_dm_active_device *dmd,
+ uint32_t flags);
+
+int LUKS2_generate_hdr(
+ struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk,
+ const char *cipherName,
+ const char *cipherMode,
+ const char *integrity,
+ const char *uuid,
+ unsigned int sector_size,
+ uint64_t data_offset,
+ uint64_t align_offset,
+ uint64_t required_alignment,
+ uint64_t metadata_size,
+ uint64_t keyslots_size);
+
+int LUKS2_check_metadata_area_size(uint64_t metadata_size);
+int LUKS2_check_keyslots_area_size(uint64_t keyslots_size);
+
+int LUKS2_wipe_header_areas(struct crypt_device *cd,
+ struct luks2_hdr *hdr, bool detached_header);
+
+uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr);
+int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic);
+uint32_t LUKS2_get_sector_size(struct luks2_hdr *hdr);
+const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment);
+const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment);
+int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct luks2_keyslot_params *params);
+int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment);
+int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot);
+const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size);
+int LUKS2_keyslot_find_empty(struct crypt_device *cd, struct luks2_hdr *hdr, size_t keylength);
+int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment);
+crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot);
+int LUKS2_keyslot_area(struct luks2_hdr *hdr,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length);
+int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf);
+
+/*
+ * Permanent activation flags stored in header
+ */
+int LUKS2_config_get_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *flags);
+int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t flags);
+
+/*
+ * Requirements for device activation or header modification
+ */
+int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs);
+int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit);
+int LUKS2_config_set_requirement_version(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id, uint8_t req_version, bool commit);
+
+int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint8_t *version);
+
+bool LUKS2_reencrypt_requirement_candidate(struct luks2_hdr *hdr);
+
+int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet);
+
+int LUKS2_key_description_by_segment(struct crypt_device *cd,
+ struct luks2_hdr *hdr, struct volume_key *vk, int segment);
+int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd,
+ struct luks2_hdr *hdr, struct volume_key *vk, int keyslot);
+int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd,
+ struct volume_key *vk, int digest);
+
+int LUKS2_luks1_to_luks2(struct crypt_device *cd,
+ struct luks_phdr *hdr1,
+ struct luks2_hdr *hdr2);
+int LUKS2_luks2_to_luks1(struct crypt_device *cd,
+ struct luks2_hdr *hdr2,
+ struct luks_phdr *hdr1);
+
+/*
+ * LUKS2 reencryption
+ */
+int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size,
+ struct volume_key **vks);
+
+void LUKS2_reencrypt_free(struct crypt_device *cd,
+ struct luks2_reencrypt *rh);
+
+crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr);
+
+crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
+ struct crypt_params_reencrypt *params);
+
+int LUKS2_reencrypt_lock(struct crypt_device *cd,
+ struct crypt_lock_handle **reencrypt_lock);
+
+int LUKS2_reencrypt_lock_by_dm_uuid(struct crypt_device *cd,
+ const char *dm_uuid,
+ struct crypt_lock_handle **reencrypt_lock);
+
+void LUKS2_reencrypt_unlock(struct crypt_device *cd,
+ struct crypt_lock_handle *reencrypt_lock);
+
+int LUKS2_reencrypt_check_device_size(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint64_t check_size,
+ uint64_t *dev_size,
+ bool activation,
+ bool dynamic);
+
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks);
+
+int LUKS2_reencrypt_max_hotzone_size(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct reenc_protection *rp,
+ int reencrypt_keyslot,
+ uint64_t *r_length);
+
+void LUKS2_reencrypt_protection_erase(struct reenc_protection *rp);
+
+#endif
diff --git a/lib/luks2/luks2_digest.c b/lib/luks2/luks2_digest.c
new file mode 100644
index 0000000..933b059
--- /dev/null
+++ b/lib/luks2/luks2_digest.c
@@ -0,0 +1,455 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, digest handling
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+extern const digest_handler PBKDF2_digest;
+
+static const digest_handler *digest_handlers[LUKS2_DIGEST_MAX] = {
+ &PBKDF2_digest,
+ NULL
+};
+
+static const digest_handler *LUKS2_digest_handler_type(const char *type)
+{
+ int i;
+
+ for (i = 0; i < LUKS2_DIGEST_MAX && digest_handlers[i]; i++) {
+ if (!strcmp(digest_handlers[i]->name, type))
+ return digest_handlers[i];
+ }
+
+ return NULL;
+}
+
+static const digest_handler *LUKS2_digest_handler(struct crypt_device *cd, int digest)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj1, *jobj2;
+
+ if (digest < 0)
+ return NULL;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return NULL;
+
+ if (!(jobj1 = LUKS2_get_digest_jobj(hdr, digest)))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj1, "type", &jobj2))
+ return NULL;
+
+ return LUKS2_digest_handler_type(json_object_get_string(jobj2));
+}
+
+static int LUKS2_digest_find_free(struct luks2_hdr *hdr)
+{
+ int digest = 0;
+
+ while (LUKS2_get_digest_jobj(hdr, digest) && digest < LUKS2_DIGEST_MAX)
+ digest++;
+
+ return digest < LUKS2_DIGEST_MAX ? digest : -1;
+}
+
+int LUKS2_digest_create(struct crypt_device *cd,
+ const char *type,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk)
+{
+ int digest;
+ const digest_handler *dh;
+
+ dh = LUKS2_digest_handler_type(type);
+ if (!dh)
+ return -EINVAL;
+
+ digest = LUKS2_digest_find_free(hdr);
+ if (digest < 0)
+ return -EINVAL;
+
+ log_dbg(cd, "Creating new digest %d (%s).", digest, type);
+
+ return dh->store(cd, digest, vk->key, vk->keylength) ?: digest;
+}
+
+int LUKS2_digest_by_keyslot(struct luks2_hdr *hdr, int keyslot)
+{
+ char keyslot_name[16];
+ json_object *jobj_digests, *jobj_digest_keyslots;
+
+ if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1)
+ return -ENOMEM;
+
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ json_object_object_get_ex(val, "keyslots", &jobj_digest_keyslots);
+ if (LUKS2_array_jobj(jobj_digest_keyslots, keyslot_name))
+ return atoi(key);
+ }
+
+ return -ENOENT;
+}
+
+int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
+ int digest,
+ const struct volume_key *vk)
+{
+ const digest_handler *h;
+ int r;
+
+ h = LUKS2_digest_handler(cd, digest);
+ if (!h)
+ return -EINVAL;
+
+ r = h->verify(cd, digest, vk->key, vk->keylength);
+ if (r < 0) {
+ log_dbg(cd, "Digest %d (%s) verify failed with %d.", digest, h->name, r);
+ return r;
+ }
+
+ return digest;
+}
+
+int LUKS2_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk,
+ int keyslot)
+{
+ int digest;
+
+ digest = LUKS2_digest_by_keyslot(hdr, keyslot);
+ if (digest < 0)
+ return digest;
+
+ log_dbg(cd, "Verifying key from keyslot %d, digest %d.", keyslot, digest);
+
+ return LUKS2_digest_verify_by_digest(cd, digest, vk);
+}
+
+int LUKS2_digest_dump(struct crypt_device *cd, int digest)
+{
+ const digest_handler *h;
+
+ if (!(h = LUKS2_digest_handler(cd, digest)))
+ return -EINVAL;
+
+ return h->dump(cd, digest);
+}
+
+int LUKS2_digest_any_matching(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk)
+{
+ int digest;
+
+ for (digest = 0; digest < LUKS2_DIGEST_MAX; digest++)
+ if (LUKS2_digest_verify_by_digest(cd, digest, vk) == digest)
+ return digest;
+
+ return -ENOENT;
+}
+
+int LUKS2_digest_verify_by_segment(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int segment,
+ const struct volume_key *vk)
+{
+ return LUKS2_digest_verify_by_digest(cd, LUKS2_digest_by_segment(hdr, segment), vk);
+}
+
+/* FIXME: segment can have more digests */
+int LUKS2_digest_by_segment(struct luks2_hdr *hdr, int segment)
+{
+ char segment_name[16];
+ json_object *jobj_digests, *jobj_digest_segments;
+
+ if (segment == CRYPT_DEFAULT_SEGMENT)
+ segment = LUKS2_get_default_segment(hdr);
+
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+
+ if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1)
+ return -EINVAL;
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ json_object_object_get_ex(val, "segments", &jobj_digest_segments);
+ if (!LUKS2_array_jobj(jobj_digest_segments, segment_name))
+ continue;
+
+ return atoi(key);
+ }
+
+ return -ENOENT;
+}
+
+static int assign_one_digest(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, int digest, int assign)
+{
+ json_object *jobj1, *jobj_digest, *jobj_digest_keyslots;
+ char num[16];
+
+ log_dbg(cd, "Keyslot %i %s digest %i.", keyslot, assign ? "assigned to" : "unassigned from", digest);
+
+ jobj_digest = LUKS2_get_digest_jobj(hdr, digest);
+ if (!jobj_digest)
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_digest, "keyslots", &jobj_digest_keyslots);
+ if (!jobj_digest_keyslots)
+ return -EINVAL;
+
+ if (snprintf(num, sizeof(num), "%d", keyslot) < 0)
+ return -EINVAL;
+
+ if (assign) {
+ jobj1 = LUKS2_array_jobj(jobj_digest_keyslots, num);
+ if (!jobj1)
+ json_object_array_add(jobj_digest_keyslots, json_object_new_string(num));
+ } else {
+ jobj1 = LUKS2_array_remove(jobj_digest_keyslots, num);
+ if (jobj1)
+ json_object_object_add(jobj_digest, "keyslots", jobj1);
+ }
+
+ return 0;
+}
+
+int LUKS2_digest_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, int digest, int assign, int commit)
+{
+ json_object *jobj_digests;
+ int r = 0;
+
+ if (digest == CRYPT_ANY_DIGEST) {
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ UNUSED(val);
+ r = assign_one_digest(cd, hdr, keyslot, atoi(key), assign);
+ if (r < 0)
+ break;
+ }
+ } else
+ r = assign_one_digest(cd, hdr, keyslot, digest, assign);
+
+ if (r < 0)
+ return r;
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+static int assign_all_segments(struct luks2_hdr *hdr, int digest, int assign)
+{
+ json_object *jobj1, *jobj_digest, *jobj_digest_segments;
+
+ jobj_digest = LUKS2_get_digest_jobj(hdr, digest);
+ if (!jobj_digest)
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_digest, "segments", &jobj_digest_segments);
+ if (!jobj_digest_segments)
+ return -EINVAL;
+
+ if (assign) {
+ json_object_object_foreach(LUKS2_get_segments_jobj(hdr), key, value) {
+ UNUSED(value);
+ jobj1 = LUKS2_array_jobj(jobj_digest_segments, key);
+ if (!jobj1)
+ json_object_array_add(jobj_digest_segments, json_object_new_string(key));
+ }
+ } else {
+ jobj1 = json_object_new_array();
+ if (!jobj1)
+ return -ENOMEM;
+ json_object_object_add(jobj_digest, "segments", jobj1);
+ }
+
+ return 0;
+}
+
+static int assign_one_segment(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int segment, int digest, int assign)
+{
+ json_object *jobj1, *jobj_digest, *jobj_digest_segments;
+ char num[16];
+
+ log_dbg(cd, "Segment %i %s digest %i.", segment, assign ? "assigned to" : "unassigned from", digest);
+
+ jobj_digest = LUKS2_get_digest_jobj(hdr, digest);
+ if (!jobj_digest)
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_digest, "segments", &jobj_digest_segments);
+ if (!jobj_digest_segments)
+ return -EINVAL;
+
+ if (snprintf(num, sizeof(num), "%d", segment) < 0)
+ return -EINVAL;
+
+ if (assign) {
+ jobj1 = LUKS2_array_jobj(jobj_digest_segments, num);
+ if (!jobj1)
+ json_object_array_add(jobj_digest_segments, json_object_new_string(num));
+ } else {
+ jobj1 = LUKS2_array_remove(jobj_digest_segments, num);
+ if (jobj1)
+ json_object_object_add(jobj_digest, "segments", jobj1);
+ }
+
+ return 0;
+}
+
+int LUKS2_digest_segment_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int segment, int digest, int assign, int commit)
+{
+ json_object *jobj_digests;
+ int r = 0;
+
+ if (segment == CRYPT_DEFAULT_SEGMENT)
+ segment = LUKS2_get_default_segment(hdr);
+
+ if (digest == CRYPT_ANY_DIGEST) {
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ UNUSED(val);
+ if (segment == CRYPT_ANY_SEGMENT)
+ r = assign_all_segments(hdr, atoi(key), assign);
+ else
+ r = assign_one_segment(cd, hdr, segment, atoi(key), assign);
+ if (r < 0)
+ break;
+ }
+ } else {
+ if (segment == CRYPT_ANY_SEGMENT)
+ r = assign_all_segments(hdr, digest, assign);
+ else
+ r = assign_one_segment(cd, hdr, segment, digest, assign);
+ }
+
+ if (r < 0)
+ return r;
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+static int digest_unused(json_object *jobj_digest)
+{
+ json_object *jobj;
+
+ json_object_object_get_ex(jobj_digest, "segments", &jobj);
+ if (!jobj || !json_object_is_type(jobj, json_type_array) || json_object_array_length(jobj) > 0)
+ return 0;
+
+ json_object_object_get_ex(jobj_digest, "keyslots", &jobj);
+ if (!jobj || !json_object_is_type(jobj, json_type_array))
+ return 0;
+
+ return json_object_array_length(jobj) > 0 ? 0 : 1;
+}
+
+void LUKS2_digests_erase_unused(struct crypt_device *cd,
+ struct luks2_hdr *hdr)
+{
+ json_object *jobj_digests;
+
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+ if (!jobj_digests || !json_object_is_type(jobj_digests, json_type_object))
+ return;
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ if (digest_unused(val)) {
+ log_dbg(cd, "Erasing unused digest %d.", atoi(key));
+ json_object_object_del(jobj_digests, key);
+ }
+ }
+}
+
+/* Key description helpers */
+static char *get_key_description_by_digest(struct crypt_device *cd, int digest)
+{
+ char *desc, digest_str[3];
+ int r;
+ size_t len;
+
+ if (!crypt_get_uuid(cd))
+ return NULL;
+
+ r = snprintf(digest_str, sizeof(digest_str), "d%u", digest);
+ if (r < 0 || (size_t)r >= sizeof(digest_str))
+ return NULL;
+
+ /* "cryptsetup:<uuid>-<digest_str>" + \0 */
+ len = strlen(crypt_get_uuid(cd)) + strlen(digest_str) + 13;
+
+ desc = malloc(len);
+ if (!desc)
+ return NULL;
+
+ r = snprintf(desc, len, "%s:%s-%s", "cryptsetup", crypt_get_uuid(cd), digest_str);
+ if (r < 0 || (size_t)r >= len) {
+ free(desc);
+ return NULL;
+ }
+
+ return desc;
+}
+
+int LUKS2_key_description_by_segment(struct crypt_device *cd,
+ struct luks2_hdr *hdr, struct volume_key *vk, int segment)
+{
+ char *desc = get_key_description_by_digest(cd, LUKS2_digest_by_segment(hdr, segment));
+ int r;
+
+ r = crypt_volume_key_set_description(vk, desc);
+ free(desc);
+ return r;
+}
+
+int LUKS2_volume_key_load_in_keyring_by_keyslot(struct crypt_device *cd,
+ struct luks2_hdr *hdr, struct volume_key *vk, int keyslot)
+{
+ char *desc = get_key_description_by_digest(cd, LUKS2_digest_by_keyslot(hdr, keyslot));
+ int r;
+
+ r = crypt_volume_key_set_description(vk, desc);
+ if (!r)
+ r = crypt_volume_key_load_in_keyring(cd, vk);
+
+ free(desc);
+ return r;
+}
+
+int LUKS2_volume_key_load_in_keyring_by_digest(struct crypt_device *cd,
+ struct volume_key *vk, int digest)
+{
+ char *desc = get_key_description_by_digest(cd, digest);
+ int r;
+
+ r = crypt_volume_key_set_description(vk, desc);
+ if (!r)
+ r = crypt_volume_key_load_in_keyring(cd, vk);
+
+ free(desc);
+ return r;
+}
diff --git a/lib/luks2/luks2_digest_pbkdf2.c b/lib/luks2/luks2_digest_pbkdf2.c
new file mode 100644
index 0000000..1009cfb
--- /dev/null
+++ b/lib/luks2/luks2_digest_pbkdf2.c
@@ -0,0 +1,210 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, PBKDF2 digest handler (LUKS1 compatible)
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+#define LUKS_DIGESTSIZE 20 // since SHA1
+#define LUKS_SALTSIZE 32
+#define LUKS_MKD_ITERATIONS_MS 125
+
+static int PBKDF2_digest_verify(struct crypt_device *cd,
+ int digest,
+ const char *volume_key,
+ size_t volume_key_len)
+{
+ char checkHashBuf[64];
+ json_object *jobj_digest, *jobj1;
+ const char *hashSpec;
+ char *mkDigest = NULL, *mkDigestSalt = NULL;
+ unsigned int mkDigestIterations;
+ size_t len;
+ int r = -EINVAL;
+
+ /* This can be done only for internally linked digests */
+ jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest);
+ if (!jobj_digest)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_digest, "hash", &jobj1))
+ return -EINVAL;
+ hashSpec = json_object_get_string(jobj1);
+
+ if (!json_object_object_get_ex(jobj_digest, "iterations", &jobj1))
+ return -EINVAL;
+ mkDigestIterations = json_object_get_int64(jobj1);
+
+ if (!json_object_object_get_ex(jobj_digest, "salt", &jobj1))
+ return -EINVAL;
+ r = crypt_base64_decode(&mkDigestSalt, &len, json_object_get_string(jobj1),
+ json_object_get_string_len(jobj1));
+ if (r < 0)
+ goto out;
+ if (len != LUKS_SALTSIZE)
+ goto out;
+
+ if (!json_object_object_get_ex(jobj_digest, "digest", &jobj1))
+ goto out;
+ r = crypt_base64_decode(&mkDigest, &len, json_object_get_string(jobj1),
+ json_object_get_string_len(jobj1));
+ if (r < 0)
+ goto out;
+ if (len < LUKS_DIGESTSIZE ||
+ len > sizeof(checkHashBuf) ||
+ (len != LUKS_DIGESTSIZE && len != (size_t)crypt_hash_size(hashSpec)))
+ goto out;
+
+ r = -EPERM;
+ if (crypt_pbkdf(CRYPT_KDF_PBKDF2, hashSpec, volume_key, volume_key_len,
+ mkDigestSalt, LUKS_SALTSIZE,
+ checkHashBuf, len,
+ mkDigestIterations, 0, 0) < 0) {
+ r = -EINVAL;
+ } else {
+ if (crypt_backend_memeq(checkHashBuf, mkDigest, len) == 0)
+ r = 0;
+ }
+out:
+ free(mkDigest);
+ free(mkDigestSalt);
+ return r;
+}
+
+static int PBKDF2_digest_store(struct crypt_device *cd,
+ int digest,
+ const char *volume_key,
+ size_t volume_key_len)
+{
+ json_object *jobj_digest, *jobj_digests;
+ char salt[LUKS_SALTSIZE], digest_raw[128];
+ int hmac_size, r;
+ char *base64_str;
+ struct luks2_hdr *hdr;
+ struct crypt_pbkdf_limits pbkdf_limits;
+ const struct crypt_pbkdf_type *pbkdf_cd;
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_PBKDF2,
+ .time_ms = LUKS_MKD_ITERATIONS_MS,
+ };
+
+ /* Inherit hash from PBKDF setting */
+ pbkdf_cd = crypt_get_pbkdf_type(cd);
+ if (pbkdf_cd)
+ pbkdf.hash = pbkdf_cd->hash;
+ if (!pbkdf.hash)
+ pbkdf.hash = DEFAULT_LUKS1_HASH;
+
+ log_dbg(cd, "Setting PBKDF2 type key digest %d.", digest);
+
+ r = crypt_random_get(cd, salt, LUKS_SALTSIZE, CRYPT_RND_SALT);
+ if (r < 0)
+ return r;
+
+ r = crypt_pbkdf_get_limits(CRYPT_KDF_PBKDF2, &pbkdf_limits);
+ if (r < 0)
+ return r;
+
+ if (crypt_get_pbkdf(cd)->flags & CRYPT_PBKDF_NO_BENCHMARK)
+ pbkdf.iterations = pbkdf_limits.min_iterations;
+ else {
+ r = crypt_benchmark_pbkdf_internal(cd, &pbkdf, volume_key_len);
+ if (r < 0)
+ return r;
+ }
+
+ hmac_size = crypt_hmac_size(pbkdf.hash);
+ if (hmac_size < 0 || hmac_size > (int)sizeof(digest_raw))
+ return -EINVAL;
+
+ r = crypt_pbkdf(CRYPT_KDF_PBKDF2, pbkdf.hash, volume_key, volume_key_len,
+ salt, LUKS_SALTSIZE, digest_raw, hmac_size,
+ pbkdf.iterations, 0, 0);
+ if (r < 0)
+ return r;
+
+ jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest);
+ jobj_digests = NULL;
+ if (!jobj_digest) {
+ hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ jobj_digest = json_object_new_object();
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+ }
+
+ json_object_object_add(jobj_digest, "type", json_object_new_string("pbkdf2"));
+ json_object_object_add(jobj_digest, "keyslots", json_object_new_array());
+ json_object_object_add(jobj_digest, "segments", json_object_new_array());
+ json_object_object_add(jobj_digest, "hash", json_object_new_string(pbkdf.hash));
+ json_object_object_add(jobj_digest, "iterations", json_object_new_int(pbkdf.iterations));
+
+ r = crypt_base64_encode(&base64_str, NULL, salt, LUKS_SALTSIZE);
+ if (r < 0) {
+ json_object_put(jobj_digest);
+ return r;
+ }
+ json_object_object_add(jobj_digest, "salt", json_object_new_string(base64_str));
+ free(base64_str);
+
+ r = crypt_base64_encode(&base64_str, NULL, digest_raw, hmac_size);
+ if (r < 0) {
+ json_object_put(jobj_digest);
+ return r;
+ }
+ json_object_object_add(jobj_digest, "digest", json_object_new_string(base64_str));
+ free(base64_str);
+
+ if (jobj_digests)
+ json_object_object_add_by_uint(jobj_digests, digest, jobj_digest);
+
+ JSON_DBG(cd, jobj_digest, "Digest JSON:");
+ return 0;
+}
+
+static int PBKDF2_digest_dump(struct crypt_device *cd, int digest)
+{
+ json_object *jobj_digest, *jobj1;
+
+ /* This can be done only for internally linked digests */
+ jobj_digest = LUKS2_get_digest_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), digest);
+ if (!jobj_digest)
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_digest, "hash", &jobj1);
+ log_std(cd, "\tHash: %s\n", json_object_get_string(jobj1));
+
+ json_object_object_get_ex(jobj_digest, "iterations", &jobj1);
+ log_std(cd, "\tIterations: %" PRIu64 "\n", json_object_get_int64(jobj1));
+
+ json_object_object_get_ex(jobj_digest, "salt", &jobj1);
+ log_std(cd, "\tSalt: ");
+ hexprint_base64(cd, jobj1, " ", " ");
+
+ json_object_object_get_ex(jobj_digest, "digest", &jobj1);
+ log_std(cd, "\tDigest: ");
+ hexprint_base64(cd, jobj1, " ", " ");
+
+ return 0;
+}
+
+const digest_handler PBKDF2_digest = {
+ .name = "pbkdf2",
+ .verify = PBKDF2_digest_verify,
+ .store = PBKDF2_digest_store,
+ .dump = PBKDF2_digest_dump,
+};
diff --git a/lib/luks2/luks2_disk_metadata.c b/lib/luks2/luks2_disk_metadata.c
new file mode 100644
index 0000000..e995959
--- /dev/null
+++ b/lib/luks2/luks2_disk_metadata.c
@@ -0,0 +1,811 @@
+/*
+ * LUKS - Linux Unified Key Setup v2
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+/*
+ * Helper functions
+ */
+static json_object *parse_json_len(struct crypt_device *cd, const char *json_area,
+ uint64_t max_length, int *json_len)
+{
+ json_object *jobj;
+ struct json_tokener *jtok;
+
+ /* INT32_MAX is internal (json-c) json_tokener_parse_ex() limit */
+ if (!json_area || max_length > INT32_MAX)
+ return NULL;
+
+ jtok = json_tokener_new();
+ if (!jtok) {
+ log_dbg(cd, "ERROR: Failed to init json tokener");
+ return NULL;
+ }
+
+ jobj = json_tokener_parse_ex(jtok, json_area, max_length);
+ if (!jobj)
+ log_dbg(cd, "ERROR: Failed to parse json data (%d): %s",
+ json_tokener_get_error(jtok),
+ json_tokener_error_desc(json_tokener_get_error(jtok)));
+ else
+ *json_len = jtok->char_offset;
+
+ json_tokener_free(jtok);
+
+ return jobj;
+}
+
+static void log_dbg_checksum(struct crypt_device *cd,
+ const uint8_t *csum, const char *csum_alg, const char *info)
+{
+ char csum_txt[2*LUKS2_CHECKSUM_L+1];
+ int i;
+
+ for (i = 0; i < crypt_hash_size(csum_alg); i++)
+ if (snprintf(&csum_txt[i*2], 3, "%02hhx", (const char)csum[i]) != 2)
+ return;
+
+ log_dbg(cd, "Checksum:%s (%s)", &csum_txt[0], info);
+}
+
+/*
+ * Calculate hash (checksum) of |LUKS2_bin|LUKS2_JSON_area| from in-memory structs.
+ * LUKS2 on-disk header contains uniques salt both for primary and secondary header.
+ * Checksum is always calculated with zeroed checksum field in binary header.
+ */
+static int hdr_checksum_calculate(const char *alg, struct luks2_hdr_disk *hdr_disk,
+ const char *json_area, size_t json_len)
+{
+ struct crypt_hash *hd = NULL;
+ int hash_size, r;
+
+ hash_size = crypt_hash_size(alg);
+ if (hash_size <= 0 || crypt_hash_init(&hd, alg))
+ return -EINVAL;
+
+ /* Binary header, csum zeroed. */
+ r = crypt_hash_write(hd, (char*)hdr_disk, LUKS2_HDR_BIN_LEN);
+
+ /* JSON area (including unused space) */
+ if (!r)
+ r = crypt_hash_write(hd, json_area, json_len);
+
+ if (!r)
+ r = crypt_hash_final(hd, (char*)hdr_disk->csum, (size_t)hash_size);
+
+ crypt_hash_destroy(hd);
+ return r;
+}
+
+/*
+ * Compare hash (checksum) of on-disk and in-memory header.
+ */
+static int hdr_checksum_check(struct crypt_device *cd,
+ const char *alg, struct luks2_hdr_disk *hdr_disk,
+ const char *json_area, size_t json_len)
+{
+ struct luks2_hdr_disk hdr_tmp;
+ int hash_size, r;
+
+ hash_size = crypt_hash_size(alg);
+ if (hash_size <= 0)
+ return -EINVAL;
+
+ /* Copy header and zero checksum. */
+ memcpy(&hdr_tmp, hdr_disk, LUKS2_HDR_BIN_LEN);
+ memset(&hdr_tmp.csum, 0, sizeof(hdr_tmp.csum));
+
+ r = hdr_checksum_calculate(alg, &hdr_tmp, json_area, json_len);
+ if (r < 0)
+ return r;
+
+ log_dbg_checksum(cd, hdr_disk->csum, alg, "on-disk");
+ log_dbg_checksum(cd, hdr_tmp.csum, alg, "in-memory");
+
+ if (memcmp(hdr_tmp.csum, hdr_disk->csum, (size_t)hash_size))
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Convert header from on-disk format to in-memory struct
+ */
+static void hdr_from_disk(struct luks2_hdr_disk *hdr_disk1,
+ struct luks2_hdr_disk *hdr_disk2,
+ struct luks2_hdr *hdr,
+ int secondary)
+{
+ hdr->version = be16_to_cpu(hdr_disk1->version);
+ hdr->hdr_size = be64_to_cpu(hdr_disk1->hdr_size);
+ hdr->seqid = be64_to_cpu(hdr_disk1->seqid);
+
+ memcpy(hdr->label, hdr_disk1->label, LUKS2_LABEL_L);
+ hdr->label[LUKS2_LABEL_L - 1] = '\0';
+ memcpy(hdr->subsystem, hdr_disk1->subsystem, LUKS2_LABEL_L);
+ hdr->subsystem[LUKS2_LABEL_L - 1] = '\0';
+ memcpy(hdr->checksum_alg, hdr_disk1->checksum_alg, LUKS2_CHECKSUM_ALG_L);
+ hdr->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
+ memcpy(hdr->uuid, hdr_disk1->uuid, LUKS2_UUID_L);
+ hdr->uuid[LUKS2_UUID_L - 1] = '\0';
+
+ if (secondary) {
+ memcpy(hdr->salt1, hdr_disk2->salt, LUKS2_SALT_L);
+ memcpy(hdr->salt2, hdr_disk1->salt, LUKS2_SALT_L);
+ } else {
+ memcpy(hdr->salt1, hdr_disk1->salt, LUKS2_SALT_L);
+ memcpy(hdr->salt2, hdr_disk2->salt, LUKS2_SALT_L);
+ }
+}
+
+/*
+ * Convert header from in-memory struct to on-disk format
+ */
+static void hdr_to_disk(struct luks2_hdr *hdr,
+ struct luks2_hdr_disk *hdr_disk,
+ int secondary, uint64_t offset)
+{
+ assert(((char*)&(hdr_disk->_padding4096) - (char*)&(hdr_disk->magic)) == 512);
+
+ memset(hdr_disk, 0, LUKS2_HDR_BIN_LEN);
+
+ memcpy(&hdr_disk->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L);
+ hdr_disk->version = cpu_to_be16(hdr->version);
+ hdr_disk->hdr_size = cpu_to_be64(hdr->hdr_size);
+ hdr_disk->hdr_offset = cpu_to_be64(offset);
+ hdr_disk->seqid = cpu_to_be64(hdr->seqid);
+
+ memcpy(hdr_disk->label, hdr->label, MIN(strlen(hdr->label), LUKS2_LABEL_L));
+ hdr_disk->label[LUKS2_LABEL_L - 1] = '\0';
+ memcpy(hdr_disk->subsystem, hdr->subsystem, MIN(strlen(hdr->subsystem), LUKS2_LABEL_L));
+ hdr_disk->subsystem[LUKS2_LABEL_L - 1] = '\0';
+ memcpy(hdr_disk->checksum_alg, hdr->checksum_alg, MIN(strlen(hdr->checksum_alg), LUKS2_CHECKSUM_ALG_L));
+ hdr_disk->checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
+ memcpy(hdr_disk->uuid, hdr->uuid, MIN(strlen(hdr->uuid), LUKS2_UUID_L));
+ hdr_disk->uuid[LUKS2_UUID_L - 1] = '\0';
+
+ memcpy(hdr_disk->salt, secondary ? hdr->salt2 : hdr->salt1, LUKS2_SALT_L);
+}
+
+/*
+ * Sanity checks before checksum is validated
+ */
+static int hdr_disk_sanity_check_pre(struct crypt_device *cd,
+ struct luks2_hdr_disk *hdr,
+ size_t *hdr_json_size, int secondary,
+ uint64_t offset)
+{
+ uint64_t hdr_size;
+
+ if (memcmp(hdr->magic, secondary ? LUKS2_MAGIC_2ND : LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
+ return -EINVAL;
+
+ if (be16_to_cpu(hdr->version) != 2) {
+ log_dbg(cd, "Unsupported LUKS2 header version %u.", be16_to_cpu(hdr->version));
+ return -EINVAL;
+ }
+
+ if (offset != be64_to_cpu(hdr->hdr_offset)) {
+ log_dbg(cd, "LUKS2 offset 0x%04" PRIx64 " on device differs to expected offset 0x%04" PRIx64 ".",
+ be64_to_cpu(hdr->hdr_offset), offset);
+ return -EINVAL;
+ }
+
+ hdr_size = be64_to_cpu(hdr->hdr_size);
+
+ if (hdr_size < LUKS2_HDR_16K_LEN || hdr_size > LUKS2_HDR_OFFSET_MAX) {
+ log_dbg(cd, "LUKS2 header has bogus size 0x%04" PRIx64 ".", hdr_size);
+ return -EINVAL;
+ }
+
+ if (secondary && (offset != hdr_size)) {
+ log_dbg(cd, "LUKS2 offset 0x%04" PRIx64 " in secondary header does not match size 0x%04" PRIx64 ".",
+ offset, hdr_size);
+ return -EINVAL;
+ }
+
+ /* FIXME: sanity check checksum alg. */
+
+ log_dbg(cd, "LUKS2 header version %u of size %" PRIu64 " bytes, checksum %s.",
+ be16_to_cpu(hdr->version), hdr_size,
+ hdr->checksum_alg);
+
+ *hdr_json_size = hdr_size - LUKS2_HDR_BIN_LEN;
+ return 0;
+}
+
+/*
+ * Read LUKS2 header from disk at specific offset.
+ */
+static int hdr_read_disk(struct crypt_device *cd,
+ struct device *device, struct luks2_hdr_disk *hdr_disk,
+ char **json_area, uint64_t offset, int secondary)
+{
+ size_t hdr_json_size = 0;
+ int devfd, r;
+
+ log_dbg(cd, "Trying to read %s LUKS2 header at offset 0x%" PRIx64 ".",
+ secondary ? "secondary" : "primary", offset);
+
+ devfd = device_open_locked(cd, device, O_RDONLY);
+ if (devfd < 0)
+ return devfd == -1 ? -EIO : devfd;
+
+ /*
+ * Read binary header and run sanity check before reading
+ * JSON area and validating checksum.
+ */
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr_disk,
+ LUKS2_HDR_BIN_LEN, offset) != LUKS2_HDR_BIN_LEN) {
+ return -EIO;
+ }
+
+ /*
+ * hdr_json_size is validated if this call succeeds
+ */
+ r = hdr_disk_sanity_check_pre(cd, hdr_disk, &hdr_json_size, secondary, offset);
+ if (r < 0)
+ return r;
+
+ /*
+ * Allocate and read JSON area. Always the whole area must be read.
+ */
+ *json_area = malloc(hdr_json_size);
+ if (!*json_area)
+ return -ENOMEM;
+
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), *json_area, hdr_json_size,
+ offset + LUKS2_HDR_BIN_LEN) != (ssize_t)hdr_json_size) {
+ free(*json_area);
+ *json_area = NULL;
+ return -EIO;
+ }
+
+ /*
+ * Calculate and validate checksum and zero it afterwards.
+ */
+ if (hdr_checksum_check(cd, hdr_disk->checksum_alg, hdr_disk,
+ *json_area, hdr_json_size)) {
+ log_dbg(cd, "LUKS2 header checksum error (offset %" PRIu64 ").", offset);
+ free(*json_area);
+ *json_area = NULL;
+ r = -EINVAL;
+ }
+ memset(hdr_disk->csum, 0, LUKS2_CHECKSUM_L);
+
+ return r;
+}
+
+/*
+ * Write LUKS2 header to disk at specific offset.
+ */
+static int hdr_write_disk(struct crypt_device *cd,
+ struct device *device, struct luks2_hdr *hdr,
+ const char *json_area, int secondary)
+{
+ struct luks2_hdr_disk hdr_disk;
+ uint64_t offset = secondary ? hdr->hdr_size : 0;
+ size_t hdr_json_len;
+ int devfd, r;
+
+ log_dbg(cd, "Trying to write LUKS2 header (%zu bytes) at offset %" PRIu64 ".",
+ hdr->hdr_size, offset);
+
+ devfd = device_open_locked(cd, device, O_RDWR);
+ if (devfd < 0)
+ return devfd == -1 ? -EINVAL : devfd;
+
+ hdr_json_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN;
+
+ hdr_to_disk(hdr, &hdr_disk, secondary, offset);
+
+ /*
+ * Write header without checksum but with proper seqid.
+ */
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), (char *)&hdr_disk,
+ LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN) {
+ return -EIO;
+ }
+
+ /*
+ * Write json area.
+ */
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device),
+ CONST_CAST(char*)json_area, hdr_json_len,
+ LUKS2_HDR_BIN_LEN + offset) < (ssize_t)hdr_json_len) {
+ return -EIO;
+ }
+
+ /*
+ * Calculate checksum and write header with checksum.
+ */
+ r = hdr_checksum_calculate(hdr_disk.checksum_alg, &hdr_disk,
+ json_area, hdr_json_len);
+ if (r < 0) {
+ return r;
+ }
+ log_dbg_checksum(cd, hdr_disk.csum, hdr_disk.checksum_alg, "in-memory");
+
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), (char *)&hdr_disk,
+ LUKS2_HDR_BIN_LEN, offset) < (ssize_t)LUKS2_HDR_BIN_LEN)
+ r = -EIO;
+
+ device_sync(cd, device);
+ return r;
+}
+
+static int LUKS2_check_sequence_id(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device)
+{
+ int devfd;
+ struct luks2_hdr_disk dhdr;
+
+ if (!hdr)
+ return -EINVAL;
+
+ devfd = device_open_locked(cd, device, O_RDONLY);
+ if (devfd < 0)
+ return devfd == -1 ? -EINVAL : devfd;
+
+ /* we need only first 512 bytes, see luks2_hdr_disk structure */
+ if ((read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), &dhdr, 512, 0) != 512))
+ return -EIO;
+
+ /* there's nothing to check if there's no LUKS2 header */
+ if ((be16_to_cpu(dhdr.version) != 2) ||
+ memcmp(dhdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L) ||
+ strcmp(dhdr.uuid, hdr->uuid))
+ return 0;
+
+ return hdr->seqid != be64_to_cpu(dhdr.seqid);
+}
+
+int LUKS2_device_write_lock(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device)
+{
+ int r = device_write_lock(cd, device);
+
+ if (r < 0) {
+ log_err(cd, _("Failed to acquire write lock on device %s."), device_path(device));
+ return r;
+ }
+
+ /* run sequence id check only on first write lock (r == 1) and w/o LUKS2 reencryption in-progress */
+ if (r == 1 && !crypt_get_luks2_reencrypt(cd)) {
+ log_dbg(cd, "Checking context sequence id matches value stored on disk.");
+ if (LUKS2_check_sequence_id(cd, hdr, device)) {
+ device_write_unlock(cd, device);
+ log_err(cd, _("Detected attempt for concurrent LUKS2 metadata update. Aborting operation."));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Convert in-memory LUKS2 header and write it to disk.
+ * This will increase sequence id, write both header copies and calculate checksum.
+ */
+int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr, struct device *device, bool seqid_check)
+{
+ char *json_area;
+ const char *json_text;
+ size_t json_area_len;
+ int r;
+
+ if (hdr->version != 2) {
+ log_dbg(cd, "Unsupported LUKS2 header version (%u).", hdr->version);
+ return -EINVAL;
+ }
+
+ r = device_check_size(cd, crypt_metadata_device(cd), LUKS2_hdr_and_areas_size(hdr), 1);
+ if (r)
+ return r;
+
+ /*
+ * Allocate and zero JSON area (of proper header size).
+ */
+ json_area_len = hdr->hdr_size - LUKS2_HDR_BIN_LEN;
+ json_area = crypt_zalloc(json_area_len);
+ if (!json_area)
+ return -ENOMEM;
+
+ /*
+ * Generate text space-efficient JSON representation to json area.
+ */
+ json_text = json_object_to_json_string_ext(hdr->jobj,
+ JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
+ if (!json_text || !*json_text) {
+ log_dbg(cd, "Cannot parse JSON object to text representation.");
+ free(json_area);
+ return -ENOMEM;
+ }
+ if (strlen(json_text) > (json_area_len - 1)) {
+ log_dbg(cd, "JSON is too large (%zu > %zu).", strlen(json_text), json_area_len);
+ free(json_area);
+ return -EINVAL;
+ }
+ strncpy(json_area, json_text, json_area_len);
+
+ if (seqid_check)
+ r = LUKS2_device_write_lock(cd, hdr, device);
+ else
+ r = device_write_lock(cd, device);
+ if (r < 0) {
+ free(json_area);
+ return r;
+ }
+
+ /* Increase sequence id before writing it to disk. */
+ hdr->seqid++;
+
+ /* Write primary and secondary header */
+ r = hdr_write_disk(cd, device, hdr, json_area, 0);
+ if (!r)
+ r = hdr_write_disk(cd, device, hdr, json_area, 1);
+
+ if (r)
+ log_dbg(cd, "LUKS2 header write failed (%d).", r);
+
+ device_write_unlock(cd, device);
+
+ free(json_area);
+ return r;
+}
+static int validate_json_area(struct crypt_device *cd, const char *json_area,
+ uint64_t json_len, uint64_t max_length)
+{
+ char c;
+
+ /* Enforce there are no needless opening bytes */
+ if (*json_area != '{') {
+ log_dbg(cd, "ERROR: Opening character must be left curly bracket: '{'.");
+ return -EINVAL;
+ }
+
+ if (json_len >= max_length) {
+ log_dbg(cd, "ERROR: Missing trailing null byte beyond parsed json data string.");
+ return -EINVAL;
+ }
+
+ /*
+ * TODO:
+ * validate there are legal json format characters between
+ * 'json_area' and 'json_area + json_len'
+ */
+
+ do {
+ c = *(json_area + json_len);
+ if (c != '\0') {
+ log_dbg(cd, "ERROR: Forbidden ascii code 0x%02hhx found beyond json data string at offset %" PRIu64,
+ c, json_len);
+ return -EINVAL;
+ }
+ } while (++json_len < max_length);
+
+ return 0;
+}
+
+static int validate_luks2_json_object(struct crypt_device *cd, json_object *jobj_hdr, uint64_t length)
+{
+ int r;
+
+ /* we require top level object to be of json_type_object */
+ r = !json_object_is_type(jobj_hdr, json_type_object);
+ if (r) {
+ log_dbg(cd, "ERROR: Resulting object is not a json object type");
+ return r;
+ }
+
+ r = LUKS2_hdr_validate(cd, jobj_hdr, length);
+ if (r) {
+ log_dbg(cd, "Repairing JSON metadata.");
+ /* try to correct known glitches */
+ LUKS2_hdr_repair(cd, jobj_hdr);
+
+ /* run validation again */
+ r = LUKS2_hdr_validate(cd, jobj_hdr, length);
+ }
+
+ if (r)
+ log_dbg(cd, "ERROR: LUKS2 validation failed");
+
+ return r;
+}
+
+static json_object *parse_and_validate_json(struct crypt_device *cd,
+ const char *json_area, uint64_t max_length)
+{
+ int json_len, r;
+ json_object *jobj = parse_json_len(cd, json_area, max_length, &json_len);
+
+ if (!jobj)
+ return NULL;
+
+ /* successful parse_json_len must not return offset <= 0 */
+ assert(json_len > 0);
+
+ r = validate_json_area(cd, json_area, json_len, max_length);
+ if (!r)
+ r = validate_luks2_json_object(cd, jobj, max_length);
+
+ if (r) {
+ json_object_put(jobj);
+ jobj = NULL;
+ }
+
+ return jobj;
+}
+
+static int detect_device_signatures(struct crypt_device *cd, const char *path)
+{
+ blk_probe_status prb_state;
+ int r;
+ struct blkid_handle *h;
+
+ if (!blk_supported()) {
+ log_dbg(cd, "Blkid probing of device signatures disabled.");
+ return 0;
+ }
+
+ if ((r = blk_init_by_path(&h, path))) {
+ log_dbg(cd, "Failed to initialize blkid_handle by path.");
+ return -EINVAL;
+ }
+
+ /* We don't care about details. Be fast. */
+ blk_set_chains_for_fast_detection(h);
+
+ /* Filter out crypto_LUKS. we don't care now */
+ blk_superblocks_filter_luks(h);
+
+ prb_state = blk_safeprobe(h);
+
+ switch (prb_state) {
+ case PRB_AMBIGUOUS:
+ log_dbg(cd, "Blkid probe couldn't decide device type unambiguously.");
+ /* fall through */
+ case PRB_FAIL:
+ log_dbg(cd, "Blkid probe failed.");
+ r = -EINVAL;
+ break;
+ case PRB_OK: /* crypto_LUKS type is filtered out */
+ r = -EINVAL;
+
+ if (blk_is_partition(h))
+ log_dbg(cd, "Blkid probe detected partition type '%s'", blk_get_partition_type(h));
+ else if (blk_is_superblock(h))
+ log_dbg(cd, "blkid probe detected superblock type '%s'", blk_get_superblock_type(h));
+ break;
+ case PRB_EMPTY:
+ log_dbg(cd, "Blkid probe detected no foreign device signature.");
+ }
+ blk_free(h);
+ return r;
+}
+
+/*
+ * Read and convert on-disk LUKS2 header to in-memory representation..
+ * Try to do recovery if on-disk state is not consistent.
+ */
+int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct device *device, int do_recovery, int do_blkprobe)
+{
+ enum { HDR_OK, HDR_OBSOLETE, HDR_FAIL, HDR_FAIL_IO } state_hdr1, state_hdr2;
+ struct luks2_hdr_disk hdr_disk1, hdr_disk2;
+ char *json_area1 = NULL, *json_area2 = NULL;
+ json_object *jobj_hdr1 = NULL, *jobj_hdr2 = NULL;
+ unsigned int i;
+ int r;
+ uint64_t hdr_size;
+ uint64_t hdr2_offsets[] = LUKS2_HDR2_OFFSETS;
+
+ /* Skip auto-recovery if locks are disabled and we're not doing LUKS2 explicit repair */
+ if (do_recovery && do_blkprobe && !crypt_metadata_locking_enabled()) {
+ do_recovery = 0;
+ log_dbg(cd, "Disabling header auto-recovery due to locking being disabled.");
+ }
+
+ /*
+ * Read primary LUKS2 header (offset 0).
+ */
+ state_hdr1 = HDR_FAIL;
+ r = hdr_read_disk(cd, device, &hdr_disk1, &json_area1, 0, 0);
+ if (r == 0) {
+ jobj_hdr1 = parse_and_validate_json(cd, json_area1, be64_to_cpu(hdr_disk1.hdr_size) - LUKS2_HDR_BIN_LEN);
+ state_hdr1 = jobj_hdr1 ? HDR_OK : HDR_OBSOLETE;
+ } else if (r == -EIO)
+ state_hdr1 = HDR_FAIL_IO;
+
+ /*
+ * Read secondary LUKS2 header (follows primary).
+ */
+ state_hdr2 = HDR_FAIL;
+ if (state_hdr1 != HDR_FAIL && state_hdr1 != HDR_FAIL_IO) {
+ r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, be64_to_cpu(hdr_disk1.hdr_size), 1);
+ if (r == 0) {
+ jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN);
+ state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE;
+ } else if (r == -EIO)
+ state_hdr2 = HDR_FAIL_IO;
+ } else {
+ /*
+ * No header size, check all known offsets.
+ */
+ for (r = -EINVAL,i = 0; r < 0 && i < ARRAY_SIZE(hdr2_offsets); i++)
+ r = hdr_read_disk(cd, device, &hdr_disk2, &json_area2, hdr2_offsets[i], 1);
+
+ if (r == 0) {
+ jobj_hdr2 = parse_and_validate_json(cd, json_area2, be64_to_cpu(hdr_disk2.hdr_size) - LUKS2_HDR_BIN_LEN);
+ state_hdr2 = jobj_hdr2 ? HDR_OK : HDR_OBSOLETE;
+ } else if (r == -EIO)
+ state_hdr2 = HDR_FAIL_IO;
+ }
+
+ /*
+ * Check sequence id if both headers are read correctly.
+ */
+ if (state_hdr1 == HDR_OK && state_hdr2 == HDR_OK) {
+ if (be64_to_cpu(hdr_disk1.seqid) > be64_to_cpu(hdr_disk2.seqid))
+ state_hdr2 = HDR_OBSOLETE;
+ else if (be64_to_cpu(hdr_disk1.seqid) < be64_to_cpu(hdr_disk2.seqid))
+ state_hdr1 = HDR_OBSOLETE;
+ }
+
+ /* check header with keyslots to fit the device */
+ if (state_hdr1 == HDR_OK)
+ hdr_size = LUKS2_hdr_and_areas_size_jobj(jobj_hdr1);
+ else if (state_hdr2 == HDR_OK)
+ hdr_size = LUKS2_hdr_and_areas_size_jobj(jobj_hdr2);
+ else {
+ r = (state_hdr1 == HDR_FAIL_IO && state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
+ goto err;
+ }
+
+ r = device_check_size(cd, device, hdr_size, 0);
+ if (r)
+ goto err;
+
+ /*
+ * Try to rewrite (recover) bad header. Always regenerate salt for bad header.
+ */
+ if (state_hdr1 == HDR_OK && state_hdr2 != HDR_OK) {
+ log_dbg(cd, "Secondary LUKS2 header requires recovery.");
+
+ if (do_blkprobe && (r = detect_device_signatures(cd, device_path(device)))) {
+ log_err(cd, _("Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+ "Please run \"cryptsetup repair\" for recovery."));
+ goto err;
+ }
+
+ if (do_recovery) {
+ memcpy(&hdr_disk2, &hdr_disk1, LUKS2_HDR_BIN_LEN);
+ r = crypt_random_get(cd, (char*)hdr_disk2.salt, sizeof(hdr_disk2.salt), CRYPT_RND_SALT);
+ if (r)
+ log_dbg(cd, "Cannot generate header salt.");
+ else {
+ hdr_from_disk(&hdr_disk1, &hdr_disk2, hdr, 0);
+ r = hdr_write_disk(cd, device, hdr, json_area1, 1);
+ }
+ if (r)
+ log_dbg(cd, "Secondary LUKS2 header recovery failed.");
+ }
+ } else if (state_hdr1 != HDR_OK && state_hdr2 == HDR_OK) {
+ log_dbg(cd, "Primary LUKS2 header requires recovery.");
+
+ if (do_blkprobe && (r = detect_device_signatures(cd, device_path(device)))) {
+ log_err(cd, _("Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+ "Please run \"cryptsetup repair\" for recovery."));
+ goto err;
+ }
+
+ if (do_recovery) {
+ memcpy(&hdr_disk1, &hdr_disk2, LUKS2_HDR_BIN_LEN);
+ r = crypt_random_get(cd, (char*)hdr_disk1.salt, sizeof(hdr_disk1.salt), CRYPT_RND_SALT);
+ if (r)
+ log_dbg(cd, "Cannot generate header salt.");
+ else {
+ hdr_from_disk(&hdr_disk2, &hdr_disk1, hdr, 1);
+ r = hdr_write_disk(cd, device, hdr, json_area2, 0);
+ }
+ if (r)
+ log_dbg(cd, "Primary LUKS2 header recovery failed.");
+ }
+ }
+
+ free(json_area1);
+ json_area1 = NULL;
+ free(json_area2);
+ json_area2 = NULL;
+
+ /* wrong lock for write mode during recovery attempt */
+ if (r == -EAGAIN)
+ goto err;
+
+ /*
+ * Even if status is failed, the second header includes salt.
+ */
+ if (state_hdr1 == HDR_OK) {
+ hdr_from_disk(&hdr_disk1, &hdr_disk2, hdr, 0);
+ hdr->jobj = jobj_hdr1;
+ json_object_put(jobj_hdr2);
+ } else if (state_hdr2 == HDR_OK) {
+ hdr_from_disk(&hdr_disk2, &hdr_disk1, hdr, 1);
+ hdr->jobj = jobj_hdr2;
+ json_object_put(jobj_hdr1);
+ }
+
+ /*
+ * FIXME: should this fail? At least one header was read correctly.
+ * r = (state_hdr1 == HDR_FAIL_IO || state_hdr2 == HDR_FAIL_IO) ? -EIO : -EINVAL;
+ */
+ return 0;
+err:
+ log_dbg(cd, "LUKS2 header read failed (%d).", r);
+
+ free(json_area1);
+ free(json_area2);
+ json_object_put(jobj_hdr1);
+ json_object_put(jobj_hdr2);
+ hdr->jobj = NULL;
+ return r;
+}
+
+int LUKS2_hdr_version_unlocked(struct crypt_device *cd, const char *backup_file)
+{
+ struct {
+ char magic[LUKS2_MAGIC_L];
+ uint16_t version;
+ } __attribute__ ((packed)) hdr;
+ struct device *device = NULL;
+ int r = 0, devfd = -1, flags;
+
+ if (!backup_file)
+ device = crypt_metadata_device(cd);
+ else if (device_alloc(cd, &device, backup_file) < 0)
+ return 0;
+
+ if (!device)
+ return 0;
+
+ flags = O_RDONLY;
+ if (device_direct_io(device))
+ flags |= O_DIRECT;
+
+ devfd = open(device_path(device), flags);
+ if (devfd != -1 && (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), &hdr, sizeof(hdr), 0) == sizeof(hdr)) &&
+ !memcmp(hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L))
+ r = (int)be16_to_cpu(hdr.version);
+
+ if (devfd != -1)
+ close(devfd);
+
+ if (backup_file)
+ device_free(cd, device);
+
+ return r;
+}
diff --git a/lib/luks2/luks2_internal.h b/lib/luks2/luks2_internal.h
new file mode 100644
index 0000000..b564a48
--- /dev/null
+++ b/lib/luks2/luks2_internal.h
@@ -0,0 +1,388 @@
+/*
+ * LUKS - Linux Unified Key Setup v2
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_LUKS2_INTERNAL_H
+#define _CRYPTSETUP_LUKS2_INTERNAL_H
+
+#include <stdio.h>
+#include <errno.h>
+#include <json-c/json.h>
+
+#include "internal.h"
+#include "luks2.h"
+
+/* override useless forward slash escape when supported by json-c */
+#ifndef JSON_C_TO_STRING_NOSLASHESCAPE
+#define JSON_C_TO_STRING_NOSLASHESCAPE 0
+#endif
+
+/*
+ * On-disk access function prototypes
+ */
+int LUKS2_disk_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct device *device, int do_recovery, int do_blkprobe);
+int LUKS2_disk_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct device *device, bool seqid_check);
+int LUKS2_device_write_lock(struct crypt_device *cd,
+ struct luks2_hdr *hdr, struct device *device);
+
+/*
+ * JSON struct access helpers
+ */
+json_object *LUKS2_get_keyslot_jobj(struct luks2_hdr *hdr, int keyslot);
+json_object *LUKS2_get_token_jobj(struct luks2_hdr *hdr, int token);
+json_object *LUKS2_get_digest_jobj(struct luks2_hdr *hdr, int digest);
+json_object *LUKS2_get_segment_jobj(struct luks2_hdr *hdr, int segment);
+json_object *LUKS2_get_tokens_jobj(struct luks2_hdr *hdr);
+json_object *LUKS2_get_segments_jobj(struct luks2_hdr *hdr);
+
+void hexprint_base64(struct crypt_device *cd, json_object *jobj,
+ const char *sep, const char *line_sep);
+
+uint64_t crypt_jobj_get_uint64(json_object *jobj);
+uint32_t crypt_jobj_get_uint32(json_object *jobj);
+json_object *crypt_jobj_new_uint64(uint64_t value);
+
+int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object *jobj_val);
+void json_object_object_del_by_uint(json_object *jobj, unsigned key);
+int json_object_copy(json_object *jobj_src, json_object **jobj_dst);
+
+void JSON_DBG(struct crypt_device *cd, json_object *jobj, const char *desc);
+
+/*
+ * LUKS2 JSON validation
+ */
+
+/* validation helper */
+bool validate_json_uint32(json_object *jobj);
+json_object *json_contains(struct crypt_device *cd, json_object *jobj, const char *name,
+ const char *section, const char *key, json_type type);
+json_object *json_contains_string(struct crypt_device *cd, json_object *jobj,
+ const char *name, const char *section, const char *key);
+
+int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size);
+int LUKS2_check_json_size(struct crypt_device *cd, const struct luks2_hdr *hdr);
+int LUKS2_token_validate(struct crypt_device *cd, json_object *hdr_jobj,
+ json_object *jobj_token, const char *key);
+void LUKS2_token_dump(struct crypt_device *cd, int token);
+
+/*
+ * LUKS2 JSON repair for known glitches
+ */
+void LUKS2_hdr_repair(struct crypt_device *cd, json_object *jobj_hdr);
+void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_hdr);
+
+/*
+ * JSON array helpers
+ */
+json_object *LUKS2_array_jobj(json_object *array, const char *num);
+json_object *LUKS2_array_remove(json_object *array, const char *num);
+
+/*
+ * Plugins API
+ */
+
+/**
+ * LUKS2 keyslots handlers (EXPERIMENTAL)
+ */
+typedef int (*keyslot_alloc_func)(struct crypt_device *cd, int keyslot,
+ size_t volume_key_len,
+ const struct luks2_keyslot_params *params);
+typedef int (*keyslot_update_func)(struct crypt_device *cd, int keyslot,
+ const struct luks2_keyslot_params *params);
+typedef int (*keyslot_open_func) (struct crypt_device *cd, int keyslot,
+ const char *password, size_t password_len,
+ char *volume_key, size_t volume_key_len);
+typedef int (*keyslot_store_func)(struct crypt_device *cd, int keyslot,
+ const char *password, size_t password_len,
+ const char *volume_key, size_t volume_key_len);
+typedef int (*keyslot_wipe_func) (struct crypt_device *cd, int keyslot);
+typedef int (*keyslot_dump_func) (struct crypt_device *cd, int keyslot);
+typedef int (*keyslot_validate_func) (struct crypt_device *cd, json_object *jobj_keyslot);
+typedef void(*keyslot_repair_func) (json_object *jobj_keyslot);
+
+/* see LUKS2_luks2_to_luks1 */
+int placeholder_keyslot_alloc(struct crypt_device *cd,
+ int keyslot,
+ uint64_t area_offset,
+ uint64_t area_length);
+
+/* validate all keyslot implementations in hdr json */
+int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj);
+
+typedef struct {
+ const char *name;
+ keyslot_alloc_func alloc;
+ keyslot_update_func update;
+ keyslot_open_func open;
+ keyslot_store_func store;
+ keyslot_wipe_func wipe;
+ keyslot_dump_func dump;
+ keyslot_validate_func validate;
+ keyslot_repair_func repair;
+} keyslot_handler;
+
+struct reenc_protection {
+ enum { REENC_PROTECTION_NOT_SET = 0,
+ REENC_PROTECTION_NONE,
+ REENC_PROTECTION_CHECKSUM,
+ REENC_PROTECTION_JOURNAL,
+ REENC_PROTECTION_DATASHIFT } type;
+
+ union {
+ struct {
+ char hash[LUKS2_CHECKSUM_ALG_L];
+ struct crypt_hash *ch;
+ size_t hash_size;
+ /* buffer for checksums */
+ void *checksums;
+ size_t checksums_len;
+ size_t block_size;
+ } csum;
+ struct {
+ uint64_t data_shift;
+ } ds;
+ } p;
+};
+
+/**
+ * LUKS2 digest handlers (EXPERIMENTAL)
+ */
+typedef int (*digest_verify_func)(struct crypt_device *cd, int digest,
+ const char *volume_key, size_t volume_key_len);
+typedef int (*digest_store_func) (struct crypt_device *cd, int digest,
+ const char *volume_key, size_t volume_key_len);
+typedef int (*digest_dump_func) (struct crypt_device *cd, int digest);
+
+typedef struct {
+ const char *name;
+ digest_verify_func verify;
+ digest_store_func store;
+ digest_dump_func dump;
+} digest_handler;
+
+int keyring_open(struct crypt_device *cd,
+ int token,
+ char **buffer,
+ size_t *buffer_len,
+ void *usrptr);
+
+void keyring_dump(struct crypt_device *cd, const char *json);
+
+int keyring_validate(struct crypt_device *cd, const char *json);
+
+void keyring_buffer_free(void *buffer, size_t buffer_size);
+
+struct crypt_token_handler_v2 {
+ const char *name;
+ crypt_token_open_func open;
+ crypt_token_buffer_free_func buffer_free;
+ crypt_token_validate_func validate;
+ crypt_token_dump_func dump;
+
+ /* here ends v1. Do not touch anything above */
+
+ crypt_token_open_pin_func open_pin;
+ crypt_token_version_func version;
+
+ void *dlhandle;
+};
+
+/*
+ * Initial sequence of structure members in union 'u' must be always
+ * identical. Version 4 must fully contain version 3 which must
+ * subsequently fully contain version 2, etc.
+ *
+ * See C standard, section 6.5.2.3, item 5.
+ */
+struct crypt_token_handler_internal {
+ uint32_t version;
+ union {
+ crypt_token_handler v1; /* deprecated public structure */
+ struct crypt_token_handler_v2 v2; /* internal helper v2 structure */
+ } u;
+};
+
+int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
+ size_t keylength, uint64_t *area_offset, uint64_t *area_length);
+int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
+ uint64_t *area_offset, uint64_t *area_length);
+
+uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj);
+
+int LUKS2_check_cipher(struct crypt_device *cd,
+ size_t keylength,
+ const char *cipher,
+ const char *cipher_mode);
+
+static inline const char *crypt_reencrypt_mode_to_str(crypt_reencrypt_mode_info mi)
+{
+ if (mi == CRYPT_REENCRYPT_REENCRYPT)
+ return "reencrypt";
+ if (mi == CRYPT_REENCRYPT_ENCRYPT)
+ return "encrypt";
+ if (mi == CRYPT_REENCRYPT_DECRYPT)
+ return "decrypt";
+ return "<unknown>";
+}
+
+/*
+ * Generic LUKS2 keyslot
+ */
+int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const void *buffer,
+ size_t buffer_length);
+
+int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment);
+
+int LUKS2_keyslot_reencrypt_update_needed(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment);
+
+int LUKS2_keyslot_reencrypt_update(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment,
+ struct volume_key *vks);
+
+int LUKS2_keyslot_reencrypt_load(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ struct reenc_protection *rp,
+ bool primary);
+
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint8_t version,
+ struct volume_key *vks);
+
+int LUKS2_keyslot_dump(struct crypt_device *cd,
+ int keyslot);
+
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length);
+
+/* JSON helpers */
+uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise);
+const char *json_segment_type(json_object *jobj_segment);
+uint64_t json_segment_get_iv_offset(json_object *jobj_segment);
+uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise);
+const char *json_segment_get_cipher(json_object *jobj_segment);
+uint32_t json_segment_get_sector_size(json_object *jobj_segment);
+bool json_segment_is_backup(json_object *jobj_segment);
+json_object *json_segments_get_segment(json_object *jobj_segments, int segment);
+unsigned json_segments_count(json_object *jobj_segments);
+void json_segment_remove_flag(json_object *jobj_segment, const char *flag);
+uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise);
+json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
+json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length, const char *cipher, uint32_t sector_size, unsigned reencryption);
+int json_segments_segment_in_reencrypt(json_object *jobj_segments);
+bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2);
+bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len);
+
+int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks,
+ json_object *jobj_segments,
+ struct crypt_dm_active_device *dmd);
+
+/*
+ * Generic LUKS2 segment
+ */
+int LUKS2_segments_count(struct luks2_hdr *hdr);
+
+int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr);
+
+int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag);
+
+json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag);
+
+int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag);
+
+int LUKS2_segments_set(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ json_object *jobj_segments,
+ int commit);
+
+uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr,
+ int segment,
+ unsigned blockwise);
+
+uint64_t LUKS2_segment_size(struct luks2_hdr *hdr,
+ int segment,
+ unsigned blockwise);
+
+int LUKS2_segment_is_type(struct luks2_hdr *hdr,
+ int segment,
+ const char *type);
+
+int LUKS2_segment_by_type(struct luks2_hdr *hdr,
+ const char *type);
+
+int LUKS2_last_segment_by_type(struct luks2_hdr *hdr,
+ const char *type);
+
+int LUKS2_get_default_segment(struct luks2_hdr *hdr);
+
+int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr);
+int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr);
+int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise);
+
+/*
+ * Generic LUKS2 digest
+ */
+int LUKS2_digest_verify_by_digest(struct crypt_device *cd,
+ int digest,
+ const struct volume_key *vk);
+
+void LUKS2_digests_erase_unused(struct crypt_device *cd,
+ struct luks2_hdr *hdr);
+
+int LUKS2_digest_dump(struct crypt_device *cd,
+ int digest);
+
+/*
+ * Generic LUKS2 token
+ */
+int LUKS2_tokens_count(struct luks2_hdr *hdr);
+
+/*
+ * LUKS2 generic
+ */
+int LUKS2_reload(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vks,
+ uint64_t device_size,
+ uint32_t flags);
+
+int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment);
+int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type);
+int LUKS2_set_keyslots_size(struct luks2_hdr *hdr, uint64_t data_offset);
+
+#endif
diff --git a/lib/luks2/luks2_json_format.c b/lib/luks2/luks2_json_format.c
new file mode 100644
index 0000000..4456358
--- /dev/null
+++ b/lib/luks2/luks2_json_format.c
@@ -0,0 +1,411 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, LUKS2 header format code
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+#include <uuid/uuid.h>
+
+struct area {
+ uint64_t offset;
+ uint64_t length;
+};
+
+static size_t get_area_size(size_t keylength)
+{
+ /* for now it is AF_split_sectors */
+ return size_round_up(keylength * 4000, 4096);
+}
+
+static size_t get_min_offset(struct luks2_hdr *hdr)
+{
+ return 2 * hdr->hdr_size;
+}
+
+static size_t get_max_offset(struct luks2_hdr *hdr)
+{
+ return LUKS2_hdr_and_areas_size(hdr);
+}
+
+int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
+ uint64_t *area_offset, uint64_t *area_length)
+{
+ struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX+1] = {};
+ int i, j, k, area_i;
+ size_t valid_offset, offset, length;
+
+ /* fill area offset + length table */
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
+ continue;
+ areas[i].length = 0;
+ areas[i].offset = 0;
+ }
+
+ /* sort table */
+ k = 0; /* index in sorted table */
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ offset = get_max_offset(hdr) ?: UINT64_MAX;
+ area_i = -1;
+ /* search for the smallest offset in table */
+ for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
+ if (areas[j].offset && areas[j].offset <= offset) {
+ area_i = j;
+ offset = areas[j].offset;
+ }
+
+ if (area_i >= 0) {
+ sorted_areas[k].length = areas[area_i].length;
+ sorted_areas[k].offset = areas[area_i].offset;
+ areas[area_i].length = 0;
+ areas[area_i].offset = 0;
+ k++;
+ }
+ }
+
+ sorted_areas[LUKS2_KEYSLOTS_MAX].offset = get_max_offset(hdr);
+ sorted_areas[LUKS2_KEYSLOTS_MAX].length = 1;
+
+ /* search for the gap we can use */
+ length = valid_offset = 0;
+ offset = get_min_offset(hdr);
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX+1; i++) {
+ /* skip empty */
+ if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
+ continue;
+
+ /* found bigger gap than the last one */
+ if ((offset < sorted_areas[i].offset) && (sorted_areas[i].offset - offset) > length) {
+ length = sorted_areas[i].offset - offset;
+ valid_offset = offset;
+ }
+
+ /* move beyond allocated area */
+ offset = sorted_areas[i].offset + sorted_areas[i].length;
+ }
+
+ /* this search 'algorithm' does not work with unaligned areas */
+ assert(length == size_round_up(length, 4096));
+ assert(valid_offset == size_round_up(valid_offset, 4096));
+
+ if (!length) {
+ log_dbg(cd, "Not enough space in header keyslot area.");
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Found largest free area %zu -> %zu", valid_offset, length + valid_offset);
+
+ *area_offset = valid_offset;
+ *area_length = length;
+
+ return 0;
+}
+
+int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
+ size_t keylength, uint64_t *area_offset, uint64_t *area_length)
+{
+ struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX] = {};
+ int i, j, k, area_i;
+ size_t offset, length;
+
+ /* fill area offset + length table */
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
+ continue;
+ areas[i].length = 0;
+ areas[i].offset = 0;
+ }
+
+ /* sort table */
+ k = 0; /* index in sorted table */
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ offset = get_max_offset(hdr) ?: UINT64_MAX;
+ area_i = -1;
+ /* search for the smallest offset in table */
+ for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
+ if (areas[j].offset && areas[j].offset <= offset) {
+ area_i = j;
+ offset = areas[j].offset;
+ }
+
+ if (area_i >= 0) {
+ sorted_areas[k].length = areas[area_i].length;
+ sorted_areas[k].offset = areas[area_i].offset;
+ areas[area_i].length = 0;
+ areas[area_i].offset = 0;
+ k++;
+ }
+ }
+
+ /* search for the gap we can use */
+ offset = get_min_offset(hdr);
+ length = get_area_size(keylength);
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ /* skip empty */
+ if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
+ continue;
+
+ /* enough space before the used area */
+ if ((offset < sorted_areas[i].offset) && ((offset + length) <= sorted_areas[i].offset))
+ break;
+
+ /* both offset and length are already aligned to 4096 bytes */
+ offset = sorted_areas[i].offset + sorted_areas[i].length;
+ }
+
+ if ((offset + length) > get_max_offset(hdr)) {
+ log_dbg(cd, "Not enough space in header keyslot area.");
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Found area %zu -> %zu", offset, length + offset);
+
+ if (area_offset)
+ *area_offset = offset;
+ if (area_length)
+ *area_length = length;
+
+ return 0;
+}
+
+int LUKS2_check_metadata_area_size(uint64_t metadata_size)
+{
+ /* see LUKS2_HDR2_OFFSETS */
+ return (metadata_size != 0x004000 &&
+ metadata_size != 0x008000 && metadata_size != 0x010000 &&
+ metadata_size != 0x020000 && metadata_size != 0x040000 &&
+ metadata_size != 0x080000 && metadata_size != 0x100000 &&
+ metadata_size != 0x200000 && metadata_size != 0x400000);
+}
+
+int LUKS2_check_keyslots_area_size(uint64_t keyslots_size)
+{
+ return (MISALIGNED_4K(keyslots_size) ||
+ keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE);
+}
+
+int LUKS2_generate_hdr(
+ struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct volume_key *vk,
+ const char *cipherName,
+ const char *cipherMode,
+ const char *integrity,
+ const char *uuid,
+ unsigned int sector_size, /* in bytes */
+ uint64_t data_offset, /* in bytes */
+ uint64_t align_offset, /* in bytes */
+ uint64_t required_alignment,
+ uint64_t metadata_size,
+ uint64_t keyslots_size)
+{
+ struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
+ char cipher[128];
+ uuid_t partitionUuid;
+ int r, digest;
+ uint64_t mdev_size;
+
+ if (!metadata_size)
+ metadata_size = LUKS2_HDR_16K_LEN;
+ hdr->hdr_size = metadata_size;
+
+ if (data_offset && data_offset < get_min_offset(hdr)) {
+ log_err(cd, _("Requested data offset is too small."));
+ return -EINVAL;
+ }
+
+ /* Increase keyslot size according to data offset */
+ if (!keyslots_size && data_offset)
+ keyslots_size = data_offset - get_min_offset(hdr);
+
+ /* keyslots size has to be 4 KiB aligned */
+ keyslots_size -= (keyslots_size % 4096);
+
+ if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
+ keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
+
+ if (!keyslots_size) {
+ assert(LUKS2_DEFAULT_HDR_SIZE > 2 * LUKS2_HDR_OFFSET_MAX);
+ keyslots_size = LUKS2_DEFAULT_HDR_SIZE - get_min_offset(hdr);
+ /* Decrease keyslots_size due to metadata device being too small */
+ if (!device_size(crypt_metadata_device(cd), &mdev_size) &&
+ ((keyslots_size + get_min_offset(hdr)) > mdev_size) &&
+ device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)) &&
+ (get_min_offset(hdr) <= mdev_size))
+ keyslots_size = mdev_size - get_min_offset(hdr);
+ }
+
+ /* Decrease keyslots_size if we have smaller data_offset */
+ if (data_offset && (keyslots_size + get_min_offset(hdr)) > data_offset) {
+ keyslots_size = data_offset - get_min_offset(hdr);
+ log_dbg(cd, "Decreasing keyslot area size to %" PRIu64
+ " bytes due to the requested data offset %"
+ PRIu64 " bytes.", keyslots_size, data_offset);
+ }
+
+ /* Data offset has priority */
+ if (!data_offset && required_alignment) {
+ data_offset = size_round_up(get_min_offset(hdr) + keyslots_size,
+ (size_t)required_alignment);
+ data_offset += align_offset;
+ }
+
+ log_dbg(cd, "Formatting LUKS2 with JSON metadata area %" PRIu64
+ " bytes and keyslots area %" PRIu64 " bytes.",
+ metadata_size - LUKS2_HDR_BIN_LEN, keyslots_size);
+
+ if (keyslots_size < (LUKS2_HDR_OFFSET_MAX - 2*LUKS2_HDR_16K_LEN))
+ log_std(cd, _("WARNING: keyslots area (%" PRIu64 " bytes) is very small,"
+ " available LUKS2 keyslot count is very limited.\n"),
+ keyslots_size);
+
+ hdr->seqid = 1;
+ hdr->version = 2;
+ memset(hdr->label, 0, LUKS2_LABEL_L);
+ strcpy(hdr->checksum_alg, "sha256");
+ crypt_random_get(cd, (char*)hdr->salt1, LUKS2_SALT_L, CRYPT_RND_SALT);
+ crypt_random_get(cd, (char*)hdr->salt2, LUKS2_SALT_L, CRYPT_RND_SALT);
+
+ if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
+ log_err(cd, _("Wrong LUKS UUID format provided."));
+ return -EINVAL;
+ }
+ if (!uuid)
+ uuid_generate(partitionUuid);
+
+ uuid_unparse(partitionUuid, hdr->uuid);
+
+ if (*cipherMode != '\0')
+ r = snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
+ else
+ r = snprintf(cipher, sizeof(cipher), "%s", cipherName);
+ if (r < 0 || (size_t)r >= sizeof(cipher))
+ return -EINVAL;
+
+ hdr->jobj = json_object_new_object();
+
+ jobj_keyslots = json_object_new_object();
+ json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots);
+ json_object_object_add(hdr->jobj, "tokens", json_object_new_object());
+ jobj_segments = json_object_new_object();
+ json_object_object_add(hdr->jobj, "segments", jobj_segments);
+ json_object_object_add(hdr->jobj, "digests", json_object_new_object());
+ jobj_config = json_object_new_object();
+ json_object_object_add(hdr->jobj, "config", jobj_config);
+
+ digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk);
+ if (digest < 0)
+ goto err;
+
+ if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0)
+ goto err;
+
+ jobj_segment = json_segment_create_crypt(data_offset, 0, NULL, cipher, sector_size, 0);
+ if (!jobj_segment)
+ goto err;
+
+ if (integrity) {
+ jobj_integrity = json_object_new_object();
+ json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
+ json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
+ json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
+ json_object_object_add(jobj_segment, "integrity", jobj_integrity);
+ }
+
+ json_object_object_add_by_uint(jobj_segments, 0, jobj_segment);
+
+ json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size - LUKS2_HDR_BIN_LEN));
+ json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
+
+ JSON_DBG(cd, hdr->jobj, "Header JSON:");
+ return 0;
+err:
+ json_object_put(hdr->jobj);
+ hdr->jobj = NULL;
+ return -EINVAL;
+}
+
+int LUKS2_wipe_header_areas(struct crypt_device *cd,
+ struct luks2_hdr *hdr, bool detached_header)
+{
+ int r;
+ uint64_t offset, length;
+ size_t wipe_block;
+
+ /* Wipe complete header, keyslots and padding areas with zeroes. */
+ offset = 0;
+ length = LUKS2_get_data_offset(hdr) * SECTOR_SIZE;
+ wipe_block = 1024 * 1024;
+
+ if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
+ return -EINVAL;
+
+ /* On detached header wipe at least the first 4k */
+ if (detached_header) {
+ length = 4096;
+ wipe_block = 4096;
+ }
+
+ r = device_check_size(cd, crypt_metadata_device(cd), length, 1);
+ if (r)
+ return r;
+
+ log_dbg(cd, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
+ offset, length + offset);
+
+ r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO,
+ offset, length, wipe_block, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ /* Wipe keyslot area */
+ wipe_block = 1024 * 1024;
+ offset = get_min_offset(hdr);
+ length = LUKS2_keyslots_size(hdr);
+
+ log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
+ offset, length + offset);
+
+ return crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_RANDOM,
+ offset, length, wipe_block, NULL, NULL);
+}
+
+int LUKS2_set_keyslots_size(struct luks2_hdr *hdr, uint64_t data_offset)
+{
+ json_object *jobj_config;
+ uint64_t keyslots_size;
+
+ if (data_offset < get_min_offset(hdr))
+ return 1;
+
+ keyslots_size = data_offset - get_min_offset(hdr);
+
+ /* keep keyslots_size reasonable for custom data alignments */
+ if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
+ keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
+
+ /* keyslots size has to be 4 KiB aligned */
+ keyslots_size -= (keyslots_size % 4096);
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return 1;
+
+ json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
+ return 0;
+}
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
new file mode 100644
index 0000000..4771f04
--- /dev/null
+++ b/lib/luks2/luks2_json_metadata.c
@@ -0,0 +1,2874 @@
+/*
+ * LUKS - Linux Unified Key Setup v2
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ * Copyright (C) 2015-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+#include "../integrity/integrity.h"
+#include <ctype.h>
+#include <uuid/uuid.h>
+
+#define LUKS_STRIPES 4000
+
+struct interval {
+ uint64_t offset;
+ uint64_t length;
+};
+
+void hexprint_base64(struct crypt_device *cd, json_object *jobj,
+ const char *sep, const char *line_sep)
+{
+ char *buf = NULL;
+ size_t buf_len;
+ unsigned int i;
+
+ if (crypt_base64_decode(&buf, &buf_len, json_object_get_string(jobj),
+ json_object_get_string_len(jobj)))
+ return;
+
+ for (i = 0; i < buf_len; i++) {
+ if (i && !(i % 16))
+ log_std(cd, "\n\t%s", line_sep);
+ log_std(cd, "%02hhx%s", buf[i], sep);
+ }
+ log_std(cd, "\n");
+ free(buf);
+}
+
+void JSON_DBG(struct crypt_device *cd, json_object *jobj, const char *desc)
+{
+ if (desc)
+ crypt_log(cd, CRYPT_LOG_DEBUG_JSON, desc);
+ crypt_log(cd, CRYPT_LOG_DEBUG_JSON, json_object_to_json_string_ext(jobj,
+ JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE));
+}
+
+/*
+ * JSON array helpers
+ */
+struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num)
+{
+ struct json_object *jobj1;
+ int i;
+
+ for (i = 0; i < (int) json_object_array_length(array); i++) {
+ jobj1 = json_object_array_get_idx(array, i);
+ if (!strcmp(num, json_object_get_string(jobj1)))
+ return jobj1;
+ }
+
+ return NULL;
+}
+
+struct json_object *LUKS2_array_remove(struct json_object *array, const char *num)
+{
+ struct json_object *jobj1, *jobj_removing = NULL, *array_new;
+ int i;
+
+ jobj_removing = LUKS2_array_jobj(array, num);
+ if (!jobj_removing)
+ return NULL;
+
+ /* Create new array without jobj_removing. */
+ array_new = json_object_new_array();
+ for (i = 0; i < (int) json_object_array_length(array); i++) {
+ jobj1 = json_object_array_get_idx(array, i);
+ if (jobj1 != jobj_removing)
+ json_object_array_add(array_new, json_object_get(jobj1));
+ }
+
+ return array_new;
+}
+
+/*
+ * JSON struct access helpers
+ */
+json_object *LUKS2_get_keyslot_jobj(struct luks2_hdr *hdr, int keyslot)
+{
+ json_object *jobj1, *jobj2;
+ char keyslot_name[16];
+
+ if (!hdr || keyslot < 0)
+ return NULL;
+
+ if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1)
+ return NULL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj1))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj1, keyslot_name, &jobj2))
+ return NULL;
+
+ return jobj2;
+}
+
+json_object *LUKS2_get_tokens_jobj(struct luks2_hdr *hdr)
+{
+ json_object *jobj_tokens;
+
+ if (!hdr || !json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens))
+ return NULL;
+
+ return jobj_tokens;
+}
+
+json_object *LUKS2_get_token_jobj(struct luks2_hdr *hdr, int token)
+{
+ json_object *jobj1, *jobj2;
+ char token_name[16];
+
+ if (!hdr || token < 0)
+ return NULL;
+
+ jobj1 = LUKS2_get_tokens_jobj(hdr);
+ if (!jobj1)
+ return NULL;
+
+ if (snprintf(token_name, sizeof(token_name), "%u", token) < 1)
+ return NULL;
+
+ json_object_object_get_ex(jobj1, token_name, &jobj2);
+ return jobj2;
+}
+
+json_object *LUKS2_get_digest_jobj(struct luks2_hdr *hdr, int digest)
+{
+ json_object *jobj1, *jobj2;
+ char digest_name[16];
+
+ if (!hdr || digest < 0)
+ return NULL;
+
+ if (snprintf(digest_name, sizeof(digest_name), "%u", digest) < 1)
+ return NULL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "digests", &jobj1))
+ return NULL;
+
+ json_object_object_get_ex(jobj1, digest_name, &jobj2);
+ return jobj2;
+}
+
+static json_object *json_get_segments_jobj(json_object *hdr_jobj)
+{
+ json_object *jobj_segments;
+
+ if (!hdr_jobj || !json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments))
+ return NULL;
+
+ return jobj_segments;
+}
+
+json_object *LUKS2_get_segment_jobj(struct luks2_hdr *hdr, int segment)
+{
+ if (!hdr)
+ return NULL;
+
+ if (segment == CRYPT_DEFAULT_SEGMENT)
+ segment = LUKS2_get_default_segment(hdr);
+
+ return json_segments_get_segment(json_get_segments_jobj(hdr->jobj), segment);
+}
+
+json_object *LUKS2_get_segments_jobj(struct luks2_hdr *hdr)
+{
+ return hdr ? json_get_segments_jobj(hdr->jobj) : NULL;
+}
+
+int LUKS2_segments_count(struct luks2_hdr *hdr)
+{
+ if (!hdr)
+ return -EINVAL;
+
+ return json_segments_count(LUKS2_get_segments_jobj(hdr));
+}
+
+int LUKS2_get_default_segment(struct luks2_hdr *hdr)
+{
+ int s = LUKS2_get_segment_id_by_flag(hdr, "backup-final");
+ if (s >= 0)
+ return s;
+
+ if (LUKS2_segments_count(hdr) >= 1)
+ return 0;
+
+ return -EINVAL;
+}
+
+/*
+ * json_type_int needs to be validated first.
+ * See validate_json_uint32()
+ */
+uint32_t crypt_jobj_get_uint32(json_object *jobj)
+{
+ return json_object_get_int64(jobj);
+}
+
+/* jobj has to be json_type_string and numbered */
+static bool json_str_to_uint64(json_object *jobj, uint64_t *value)
+{
+ char *endptr;
+ unsigned long long tmp;
+
+ errno = 0;
+ tmp = strtoull(json_object_get_string(jobj), &endptr, 10);
+ if (*endptr || errno) {
+ *value = 0;
+ return false;
+ }
+
+ *value = tmp;
+ return true;
+}
+
+uint64_t crypt_jobj_get_uint64(json_object *jobj)
+{
+ uint64_t r;
+ json_str_to_uint64(jobj, &r);
+ return r;
+}
+
+json_object *crypt_jobj_new_uint64(uint64_t value)
+{
+ /* 18446744073709551615 */
+ char num[21];
+ int r;
+ json_object *jobj;
+
+ r = snprintf(num, sizeof(num), "%" PRIu64, value);
+ if (r < 0 || (size_t)r >= sizeof(num))
+ return NULL;
+
+ jobj = json_object_new_string(num);
+ return jobj;
+}
+
+/*
+ * Validate helpers
+ */
+static bool numbered(struct crypt_device *cd, const char *name, const char *key)
+{
+ int i;
+
+ for (i = 0; key[i]; i++)
+ if (!isdigit(key[i])) {
+ log_dbg(cd, "%s \"%s\" is not in numbered form.", name, key);
+ return false;
+ }
+ return true;
+}
+
+json_object *json_contains(struct crypt_device *cd, json_object *jobj, const char *name,
+ const char *section, const char *key, json_type type)
+{
+ json_object *sobj;
+
+ if (!json_object_object_get_ex(jobj, key, &sobj) ||
+ !json_object_is_type(sobj, type)) {
+ log_dbg(cd, "%s \"%s\" is missing \"%s\" (%s) specification.",
+ section, name, key, json_type_to_name(type));
+ return NULL;
+ }
+
+ return sobj;
+}
+
+json_object *json_contains_string(struct crypt_device *cd, json_object *jobj,
+ const char *name, const char *section, const char *key)
+{
+ json_object *sobj = json_contains(cd, jobj, name, section, key, json_type_string);
+
+ if (!sobj)
+ return NULL;
+
+ if (strlen(json_object_get_string(sobj)) < 1)
+ return NULL;
+
+ return sobj;
+}
+
+bool validate_json_uint32(json_object *jobj)
+{
+ int64_t tmp;
+
+ errno = 0;
+ tmp = json_object_get_int64(jobj);
+
+ return (errno || tmp < 0 || tmp > UINT32_MAX) ? false : true;
+}
+
+static bool validate_keyslots_array(struct crypt_device *cd, json_object *jarr, json_object *jobj_keys)
+{
+ json_object *jobj;
+ int i = 0, length = (int) json_object_array_length(jarr);
+
+ while (i < length) {
+ jobj = json_object_array_get_idx(jarr, i);
+ if (!json_object_is_type(jobj, json_type_string)) {
+ log_dbg(cd, "Illegal value type in keyslots array at index %d.", i);
+ return false;
+ }
+
+ if (!json_contains(cd, jobj_keys, "", "Keyslots section",
+ json_object_get_string(jobj), json_type_object))
+ return false;
+
+ i++;
+ }
+
+ return true;
+}
+
+static bool validate_segments_array(struct crypt_device *cd, json_object *jarr, json_object *jobj_segments)
+{
+ json_object *jobj;
+ int i = 0, length = (int) json_object_array_length(jarr);
+
+ while (i < length) {
+ jobj = json_object_array_get_idx(jarr, i);
+ if (!json_object_is_type(jobj, json_type_string)) {
+ log_dbg(cd, "Illegal value type in segments array at index %d.", i);
+ return false;
+ }
+
+ if (!json_contains(cd, jobj_segments, "", "Segments section",
+ json_object_get_string(jobj), json_type_object))
+ return false;
+
+ i++;
+ }
+
+ return true;
+}
+
+static bool segment_has_digest(const char *segment_name, json_object *jobj_digests)
+{
+ json_object *jobj_segments;
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ UNUSED(key);
+ json_object_object_get_ex(val, "segments", &jobj_segments);
+ if (LUKS2_array_jobj(jobj_segments, segment_name))
+ return true;
+ }
+
+ return false;
+}
+
+
+static bool validate_intervals(struct crypt_device *cd,
+ int length, const struct interval *ix,
+ uint64_t metadata_size, uint64_t keyslots_area_end)
+{
+ int j, i = 0;
+
+ while (i < length) {
+ /* Offset cannot be inside primary or secondary JSON area */
+ if (ix[i].offset < 2 * metadata_size) {
+ log_dbg(cd, "Illegal area offset: %" PRIu64 ".", ix[i].offset);
+ return false;
+ }
+
+ if (!ix[i].length) {
+ log_dbg(cd, "Area length must be greater than zero.");
+ return false;
+ }
+
+ if (ix[i].offset > (UINT64_MAX - ix[i].length)) {
+ log_dbg(cd, "Interval offset+length overflow.");
+ return false;
+ }
+
+ if ((ix[i].offset + ix[i].length) > keyslots_area_end) {
+ log_dbg(cd, "Area [%" PRIu64 ", %" PRIu64 "] overflows binary keyslots area (ends at offset: %" PRIu64 ").",
+ ix[i].offset, ix[i].offset + ix[i].length, keyslots_area_end);
+ return false;
+ }
+
+ for (j = 0; j < length; j++) {
+ if (i == j)
+ continue;
+
+ if (ix[j].offset > (UINT64_MAX - ix[j].length)) {
+ log_dbg(cd, "Interval offset+length overflow.");
+ return false;
+ }
+
+ if ((ix[i].offset >= ix[j].offset) && (ix[i].offset < (ix[j].offset + ix[j].length))) {
+ log_dbg(cd, "Overlapping areas [%" PRIu64 ",%" PRIu64 "] and [%" PRIu64 ",%" PRIu64 "].",
+ ix[i].offset, ix[i].offset + ix[i].length,
+ ix[j].offset, ix[j].offset + ix[j].length);
+ return false;
+ }
+ }
+
+ i++;
+ }
+
+ return true;
+}
+
+static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_keyslot, const char *key)
+{
+ json_object *jobj_key_size;
+
+ if (!json_contains_string(cd, hdr_keyslot, key, "Keyslot", "type"))
+ return 1;
+ if (!(jobj_key_size = json_contains(cd, hdr_keyslot, key, "Keyslot", "key_size", json_type_int)))
+ return 1;
+
+ /* enforce uint32_t type */
+ if (!validate_json_uint32(jobj_key_size)) {
+ log_dbg(cd, "Illegal field \"key_size\":%s.",
+ json_object_get_string(jobj_key_size));
+ return 1;
+ }
+
+ return 0;
+}
+
+int LUKS2_token_validate(struct crypt_device *cd,
+ json_object *hdr_jobj, json_object *jobj_token, const char *key)
+{
+ json_object *jarr, *jobj_keyslots;
+
+ /* keyslots are not yet validated, but we need to know token doesn't reference missing keyslot */
+ if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
+ return 1;
+
+ if (!json_contains_string(cd, jobj_token, key, "Token", "type"))
+ return 1;
+
+ jarr = json_contains(cd, jobj_token, key, "Token", "keyslots", json_type_array);
+ if (!jarr)
+ return 1;
+
+ if (!validate_keyslots_array(cd, jarr, jobj_keyslots))
+ return 1;
+
+ return 0;
+}
+
+static int hdr_validate_json_size(struct crypt_device *cd, json_object *hdr_jobj, uint64_t hdr_json_size)
+{
+ json_object *jobj, *jobj1;
+ const char *json;
+ uint64_t json_area_size, json_size;
+
+ json_object_object_get_ex(hdr_jobj, "config", &jobj);
+ json_object_object_get_ex(jobj, "json_size", &jobj1);
+
+ json = json_object_to_json_string_ext(hdr_jobj,
+ JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
+ json_area_size = crypt_jobj_get_uint64(jobj1);
+ json_size = (uint64_t)strlen(json);
+
+ if (hdr_json_size != json_area_size) {
+ log_dbg(cd, "JSON area size does not match value in binary header.");
+ return 1;
+ }
+
+ if (json_size > json_area_size) {
+ log_dbg(cd, "JSON does not fit in the designated area.");
+ return 1;
+ }
+
+ return 0;
+}
+
+int LUKS2_check_json_size(struct crypt_device *cd, const struct luks2_hdr *hdr)
+{
+ return hdr_validate_json_size(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN);
+}
+
+static int hdr_validate_keyslots(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ json_object *jobj;
+
+ if (!(jobj = json_contains(cd, hdr_jobj, "", "JSON area", "keyslots", json_type_object)))
+ return 1;
+
+ json_object_object_foreach(jobj, key, val) {
+ if (!numbered(cd, "Keyslot", key))
+ return 1;
+ if (LUKS2_keyslot_validate(cd, val, key))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int hdr_validate_tokens(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ json_object *jobj;
+
+ if (!(jobj = json_contains(cd, hdr_jobj, "", "JSON area", "tokens", json_type_object)))
+ return 1;
+
+ json_object_object_foreach(jobj, key, val) {
+ if (!numbered(cd, "Token", key))
+ return 1;
+ if (LUKS2_token_validate(cd, hdr_jobj, val, key))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int hdr_validate_crypt_segment(struct crypt_device *cd, json_object *jobj,
+ const char *key, json_object *jobj_digests,
+ uint64_t size)
+{
+ int r;
+ json_object *jobj_ivoffset, *jobj_sector_size, *jobj_integrity;
+ uint32_t sector_size;
+ uint64_t ivoffset;
+
+ if (!(jobj_ivoffset = json_contains_string(cd, jobj, key, "Segment", "iv_tweak")) ||
+ !json_contains_string(cd, jobj, key, "Segment", "encryption") ||
+ !(jobj_sector_size = json_contains(cd, jobj, key, "Segment", "sector_size", json_type_int)))
+ return 1;
+
+ /* integrity */
+ if (json_object_object_get_ex(jobj, "integrity", &jobj_integrity)) {
+ if (!json_contains(cd, jobj, key, "Segment", "integrity", json_type_object) ||
+ !json_contains_string(cd, jobj_integrity, key, "Segment integrity", "type") ||
+ !json_contains_string(cd, jobj_integrity, key, "Segment integrity", "journal_encryption") ||
+ !json_contains_string(cd, jobj_integrity, key, "Segment integrity", "journal_integrity"))
+ return 1;
+ }
+
+ /* enforce uint32_t type */
+ if (!validate_json_uint32(jobj_sector_size)) {
+ log_dbg(cd, "Illegal field \"sector_size\":%s.",
+ json_object_get_string(jobj_sector_size));
+ return 1;
+ }
+
+ sector_size = crypt_jobj_get_uint32(jobj_sector_size);
+ if (!sector_size || MISALIGNED_512(sector_size)) {
+ log_dbg(cd, "Illegal sector size: %" PRIu32, sector_size);
+ return 1;
+ }
+
+ if (!numbered(cd, "iv_tweak", json_object_get_string(jobj_ivoffset)) ||
+ !json_str_to_uint64(jobj_ivoffset, &ivoffset)) {
+ log_dbg(cd, "Illegal iv_tweak value.");
+ return 1;
+ }
+
+ if (size % sector_size) {
+ log_dbg(cd, "Size field has to be aligned to sector size: %" PRIu32, sector_size);
+ return 1;
+ }
+
+ r = segment_has_digest(key, jobj_digests);
+
+ if (!r)
+ log_dbg(cd, "Crypt segment %s not assigned to key digest.", key);
+
+ return !r;
+}
+
+static bool validate_segment_intervals(struct crypt_device *cd,
+ int length, const struct interval *ix)
+{
+ int j, i = 0;
+
+ while (i < length) {
+ if (ix[i].length == UINT64_MAX && (i != (length - 1))) {
+ log_dbg(cd, "Only last regular segment is allowed to have 'dynamic' size.");
+ return false;
+ }
+
+ for (j = 0; j < length; j++) {
+ if (i == j)
+ continue;
+
+ if (ix[j].length != UINT64_MAX && ix[j].offset > (UINT64_MAX - ix[j].length)) {
+ log_dbg(cd, "Interval offset+length overflow.");
+ return false;
+ }
+
+ if ((ix[i].offset >= ix[j].offset) && (ix[j].length == UINT64_MAX || (ix[i].offset < (ix[j].offset + ix[j].length)))) {
+ log_dbg(cd, "Overlapping segments [%" PRIu64 ",%" PRIu64 "]%s and [%" PRIu64 ",%" PRIu64 "]%s.",
+ ix[i].offset, ix[i].offset + ix[i].length, ix[i].length == UINT64_MAX ? "(dynamic)" : "",
+ ix[j].offset, ix[j].offset + ix[j].length, ix[j].length == UINT64_MAX ? "(dynamic)" : "");
+ return false;
+ }
+ }
+
+ i++;
+ }
+
+ return true;
+}
+
+static int reqs_unknown(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_UNKNOWN;
+}
+
+static int reqs_reencrypt(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
+}
+
+static int reqs_reencrypt_online(uint32_t reqs)
+{
+ return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
+}
+
+/*
+ * Config section requirements object must be valid.
+ * Also general segments section must be validated first.
+ */
+static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr_jobj, json_object *jobj_segments, int first_backup, int segments_count)
+{
+ json_object *jobj, *jobj_backup_previous = NULL, *jobj_backup_final = NULL;
+ uint32_t reqs;
+ int i, r;
+ struct luks2_hdr dummy = {
+ .jobj = hdr_jobj
+ };
+
+ r = LUKS2_config_get_requirements(cd, &dummy, &reqs);
+ if (r)
+ return 1;
+
+ if (reqs_reencrypt_online(reqs)) {
+ for (i = first_backup; i < segments_count; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj)
+ return 1;
+ if (json_segment_contains_flag(jobj, "backup-final", 0))
+ jobj_backup_final = jobj;
+ else if (json_segment_contains_flag(jobj, "backup-previous", 0))
+ jobj_backup_previous = jobj;
+ }
+
+ if (!jobj_backup_final || !jobj_backup_previous) {
+ log_dbg(cd, "Backup segment is missing.");
+ return 1;
+ }
+
+ for (i = 0; i < first_backup; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj)
+ return 1;
+
+ if (json_segment_contains_flag(jobj, "in-reencryption", 0)) {
+ if (!json_segment_cmp(jobj, jobj_backup_final)) {
+ log_dbg(cd, "Segment in reencryption does not match backup final segment.");
+ return 1;
+ }
+ continue;
+ }
+
+ if (!json_segment_cmp(jobj, jobj_backup_final) &&
+ !json_segment_cmp(jobj, jobj_backup_previous)) {
+ log_dbg(cd, "Segment does not match neither backup final or backup previous segment.");
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *jobj_type, *jobj_flags, *jobj;
+ uint64_t offset, size;
+ int i, r, count, first_backup = -1;
+ struct interval *intervals = NULL;
+
+ if (!(jobj_segments = json_contains(cd, hdr_jobj, "", "JSON area", "segments", json_type_object)))
+ return 1;
+
+ count = json_object_object_length(jobj_segments);
+ if (count < 1) {
+ log_dbg(cd, "Empty segments section.");
+ return 1;
+ }
+
+ /* digests should already be validated */
+ if (!json_object_object_get_ex(hdr_jobj, "digests", &jobj_digests))
+ return 1;
+
+ json_object_object_foreach(jobj_segments, key, val) {
+ if (!numbered(cd, "Segment", key))
+ return 1;
+
+ /* those fields are mandatory for all segment types */
+ if (!(jobj_type = json_contains_string(cd, val, key, "Segment", "type")) ||
+ !(jobj_offset = json_contains_string(cd, val, key, "Segment", "offset")) ||
+ !(jobj_size = json_contains_string(cd, val, key, "Segment", "size")))
+ return 1;
+
+ if (!numbered(cd, "offset", json_object_get_string(jobj_offset)))
+ return 1;
+
+ if (!json_str_to_uint64(jobj_offset, &offset)) {
+ log_dbg(cd, "Illegal segment offset value.");
+ return 1;
+ }
+
+ /* size "dynamic" means whole device starting at 'offset' */
+ if (strcmp(json_object_get_string(jobj_size), "dynamic")) {
+ if (!numbered(cd, "size", json_object_get_string(jobj_size)))
+ return 1;
+ if (!json_str_to_uint64(jobj_size, &size) || !size) {
+ log_dbg(cd, "Illegal segment size value.");
+ return 1;
+ }
+ } else
+ size = 0;
+
+ /* all device-mapper devices are aligned to 512 sector size */
+ if (MISALIGNED_512(offset)) {
+ log_dbg(cd, "Offset field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE);
+ return 1;
+ }
+ if (MISALIGNED_512(size)) {
+ log_dbg(cd, "Size field has to be aligned to sector size: %" PRIu32, SECTOR_SIZE);
+ return 1;
+ }
+
+ /* flags array is optional and must contain strings */
+ if (json_object_object_get_ex(val, "flags", NULL)) {
+ if (!(jobj_flags = json_contains(cd, val, key, "Segment", "flags", json_type_array)))
+ return 1;
+ for (i = 0; i < (int) json_object_array_length(jobj_flags); i++)
+ if (!json_object_is_type(json_object_array_get_idx(jobj_flags, i), json_type_string))
+ return 1;
+ }
+
+ i = atoi(key);
+ if (json_segment_is_backup(val)) {
+ if (first_backup < 0 || i < first_backup)
+ first_backup = i;
+ } else {
+ if ((first_backup >= 0) && i >= first_backup) {
+ log_dbg(cd, "Regular segment at %d is behind backup segment at %d", i, first_backup);
+ return 1;
+ }
+ }
+
+ /* crypt */
+ if (!strcmp(json_object_get_string(jobj_type), "crypt") &&
+ hdr_validate_crypt_segment(cd, val, key, jobj_digests, size))
+ return 1;
+ }
+
+ if (first_backup == 0) {
+ log_dbg(cd, "No regular segment.");
+ return 1;
+ }
+
+ /* avoid needlessly large allocation when first backup segment is invalid */
+ if (first_backup >= count) {
+ log_dbg(cd, "Gap between last regular segment and backup segment at key %d.", first_backup);
+ return 1;
+ }
+
+ if (first_backup < 0)
+ first_backup = count;
+
+ if ((size_t)first_backup < SIZE_MAX / sizeof(*intervals))
+ intervals = malloc(first_backup * sizeof(*intervals));
+
+ if (!intervals) {
+ log_dbg(cd, "Not enough memory.");
+ return 1;
+ }
+
+ for (i = 0; i < first_backup; i++) {
+ jobj = json_segments_get_segment(jobj_segments, i);
+ if (!jobj) {
+ log_dbg(cd, "Gap at key %d in segments object.", i);
+ free(intervals);
+ return 1;
+ }
+ intervals[i].offset = json_segment_get_offset(jobj, 0);
+ intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
+ }
+
+ r = !validate_segment_intervals(cd, first_backup, intervals);
+ free(intervals);
+
+ if (r)
+ return 1;
+
+ for (; i < count; i++) {
+ if (!json_segments_get_segment(jobj_segments, i)) {
+ log_dbg(cd, "Gap at key %d in segments object.", i);
+ return 1;
+ }
+ }
+
+ return validate_reencrypt_segments(cd, hdr_jobj, jobj_segments, first_backup, count);
+}
+
+static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
+{
+ json_object *jobj1, *jobj2;
+ uint64_t json_size;
+
+ json_object_object_get_ex(jobj, "config", &jobj1);
+ json_object_object_get_ex(jobj1, "json_size", &jobj2);
+ json_str_to_uint64(jobj2, &json_size);
+
+ return json_size + LUKS2_HDR_BIN_LEN;
+}
+
+uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr)
+{
+ return LUKS2_metadata_size_jobj(hdr->jobj);
+}
+
+static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ struct interval *intervals;
+ json_object *jobj_keyslots, *jobj_offset, *jobj_length, *jobj_segments, *jobj_area;
+ int length, ret, i = 0;
+ uint64_t metadata_size;
+
+ if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
+ return 1;
+
+ /* segments are already validated */
+ if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments))
+ return 1;
+
+ /* config is already validated */
+ metadata_size = LUKS2_metadata_size_jobj(hdr_jobj);
+
+ length = json_object_object_length(jobj_keyslots);
+
+ /* Empty section */
+ if (length == 0)
+ return 0;
+
+ if (length < 0) {
+ log_dbg(cd, "Invalid keyslot areas specification.");
+ return 1;
+ }
+
+ intervals = malloc(length * sizeof(*intervals));
+ if (!intervals) {
+ log_dbg(cd, "Not enough memory.");
+ return -ENOMEM;
+ }
+
+ json_object_object_foreach(jobj_keyslots, key, val) {
+
+ if (!(jobj_area = json_contains(cd, val, key, "Keyslot", "area", json_type_object)) ||
+ !json_contains_string(cd, jobj_area, key, "Keyslot area", "type") ||
+ !(jobj_offset = json_contains_string(cd, jobj_area, key, "Keyslot", "offset")) ||
+ !(jobj_length = json_contains_string(cd, jobj_area, key, "Keyslot", "size")) ||
+ !numbered(cd, "offset", json_object_get_string(jobj_offset)) ||
+ !numbered(cd, "size", json_object_get_string(jobj_length))) {
+ free(intervals);
+ return 1;
+ }
+
+ /* rule out values > UINT64_MAX */
+ if (!json_str_to_uint64(jobj_offset, &intervals[i].offset) ||
+ !json_str_to_uint64(jobj_length, &intervals[i].length)) {
+ log_dbg(cd, "Illegal keyslot area values.");
+ free(intervals);
+ return 1;
+ }
+
+ i++;
+ }
+
+ if (length != i) {
+ free(intervals);
+ return 1;
+ }
+
+ ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_and_areas_size_jobj(hdr_jobj)) ? 0 : 1;
+
+ free(intervals);
+
+ return ret;
+}
+
+static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ json_object *jarr_keys, *jarr_segs, *jobj, *jobj_keyslots, *jobj_segments;
+
+ if (!(jobj = json_contains(cd, hdr_jobj, "", "JSON area", "digests", json_type_object)))
+ return 1;
+
+ /* keyslots are not yet validated, but we need to know digest doesn't reference missing keyslot */
+ if (!(jobj_keyslots = json_contains(cd, hdr_jobj, "", "JSON area", "keyslots", json_type_object)))
+ return 1;
+
+ /* segments are not yet validated, but we need to know digest doesn't reference missing segment */
+ if (!(jobj_segments = json_contains(cd, hdr_jobj, "", "JSON area", "segments", json_type_object)))
+ return 1;
+
+ json_object_object_foreach(jobj, key, val) {
+ if (!numbered(cd, "Digest", key))
+ return 1;
+
+ if (!json_contains_string(cd, val, key, "Digest", "type") ||
+ !(jarr_keys = json_contains(cd, val, key, "Digest", "keyslots", json_type_array)) ||
+ !(jarr_segs = json_contains(cd, val, key, "Digest", "segments", json_type_array)))
+ return 1;
+
+ if (!validate_keyslots_array(cd, jarr_keys, jobj_keyslots))
+ return 1;
+ if (!validate_segments_array(cd, jarr_segs, jobj_segments))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* requirements being validated in stand-alone routine */
+static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ json_object *jobj_config, *jobj;
+ int i;
+ uint64_t keyslots_size, metadata_size, segment_offset;
+
+ if (!(jobj_config = json_contains(cd, hdr_jobj, "", "JSON area", "config", json_type_object)))
+ return 1;
+
+ if (!(jobj = json_contains_string(cd, jobj_config, "section", "Config", "json_size")))
+ return 1;
+ if (!json_str_to_uint64(jobj, &metadata_size)) {
+ log_dbg(cd, "Illegal config json_size value.");
+ return 1;
+ }
+
+ /* single metadata instance is assembled from json area size plus
+ * binary header size */
+ metadata_size += LUKS2_HDR_BIN_LEN;
+
+ if (!(jobj = json_contains_string(cd, jobj_config, "section", "Config", "keyslots_size")))
+ return 1;
+ if(!json_str_to_uint64(jobj, &keyslots_size)) {
+ log_dbg(cd, "Illegal config keyslot_size value.");
+ return 1;
+ }
+
+ if (LUKS2_check_metadata_area_size(metadata_size)) {
+ log_dbg(cd, "Unsupported LUKS2 header size (%" PRIu64 ").", metadata_size);
+ return 1;
+ }
+
+ if (LUKS2_check_keyslots_area_size(keyslots_size)) {
+ log_dbg(cd, "Unsupported LUKS2 keyslots size (%" PRIu64 ").", keyslots_size);
+ return 1;
+ }
+
+ /*
+ * validate keyslots_size fits in between (2 * metadata_size) and first
+ * segment_offset (except detached header)
+ */
+ segment_offset = json_segments_get_minimal_offset(json_get_segments_jobj(hdr_jobj), 0);
+ if (segment_offset &&
+ (segment_offset < keyslots_size ||
+ (segment_offset - keyslots_size) < (2 * metadata_size))) {
+ log_dbg(cd, "keyslots_size is too large %" PRIu64 " (bytes). Data offset: %" PRIu64
+ ", keyslots offset: %" PRIu64, keyslots_size, segment_offset, 2 * metadata_size);
+ return 1;
+ }
+
+ /* Flags array is optional */
+ if (json_object_object_get_ex(jobj_config, "flags", &jobj)) {
+ if (!json_contains(cd, jobj_config, "section", "Config", "flags", json_type_array))
+ return 1;
+
+ /* All array members must be strings */
+ for (i = 0; i < (int) json_object_array_length(jobj); i++)
+ if (!json_object_is_type(json_object_array_get_idx(jobj, i), json_type_string))
+ return 1;
+ }
+
+ return 0;
+}
+
+static bool reencrypt_candidate_flag(const char *flag)
+{
+ const char *ptr;
+
+ assert(flag);
+
+ if (!strcmp(flag, "online-reencrypt"))
+ return true;
+
+ if (strncmp(flag, "online-reencrypt-v", 18))
+ return false;
+
+ ptr = flag + 18;
+ if (!*ptr)
+ return false;
+
+ while (*ptr) {
+ if (!isdigit(*ptr))
+ return false;
+ ptr++;
+ }
+
+ return true;
+}
+
+static int hdr_validate_requirements(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ int i;
+ json_object *jobj_config, *jobj, *jobj1;
+ unsigned online_reencrypt_flag = 0;
+
+ if (!(jobj_config = json_contains(cd, hdr_jobj, "", "JSON area", "config", json_type_object)))
+ return 1;
+
+ /* Requirements object is optional */
+ if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) {
+ if (!json_contains(cd, jobj_config, "section", "Config", "requirements", json_type_object))
+ return 1;
+
+ /* Mandatory array is optional */
+ if (json_object_object_get_ex(jobj, "mandatory", &jobj1)) {
+ if (!json_contains(cd, jobj, "section", "Requirements", "mandatory", json_type_array))
+ return 1;
+
+ /* All array members must be strings */
+ for (i = 0; i < (int) json_object_array_length(jobj1); i++) {
+ if (!json_object_is_type(json_object_array_get_idx(jobj1, i), json_type_string))
+ return 1;
+
+ if (reencrypt_candidate_flag(json_object_get_string(json_object_array_get_idx(jobj1, i))))
+ online_reencrypt_flag++;
+
+ }
+ }
+ }
+
+ if (online_reencrypt_flag > 1) {
+ log_dbg(cd, "Multiple online reencryption requirement flags detected.");
+ return 1;
+ }
+
+ return 0;
+}
+
+int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size)
+{
+ struct {
+ int (*validate)(struct crypt_device *, json_object *);
+ } checks[] = {
+ { hdr_validate_requirements },
+ { hdr_validate_tokens },
+ { hdr_validate_digests },
+ { hdr_validate_segments },
+ { hdr_validate_keyslots },
+ { hdr_validate_config },
+ { hdr_validate_areas },
+ { NULL }
+ };
+ int i;
+
+ if (!hdr_jobj)
+ return 1;
+
+ for (i = 0; checks[i].validate; i++)
+ if (checks[i].validate && checks[i].validate(cd, hdr_jobj))
+ return 1;
+
+ if (hdr_validate_json_size(cd, hdr_jobj, json_size))
+ return 1;
+
+ /* validate keyslot implementations */
+ if (LUKS2_keyslots_validate(cd, hdr_jobj))
+ return 1;
+
+ return 0;
+}
+
+static bool hdr_json_free(json_object **jobj)
+{
+ assert(jobj);
+
+ if (json_object_put(*jobj))
+ *jobj = NULL;
+
+ return (*jobj == NULL);
+}
+
+static int hdr_update_copy_for_rollback(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ json_object **jobj_copy;
+
+ assert(hdr);
+ assert(hdr->jobj);
+
+ jobj_copy = (json_object **)&hdr->jobj_rollback;
+
+ if (!hdr_json_free(jobj_copy)) {
+ log_dbg(cd, "LUKS2 rollback metadata copy still in use");
+ return -EINVAL;
+ }
+
+ return json_object_copy(hdr->jobj, jobj_copy) ? -ENOMEM : 0;
+}
+
+/* FIXME: should we expose do_recovery parameter explicitly? */
+int LUKS2_hdr_read(struct crypt_device *cd, struct luks2_hdr *hdr, int repair)
+{
+ int r;
+
+ r = device_read_lock(cd, crypt_metadata_device(cd));
+ if (r) {
+ log_err(cd, _("Failed to acquire read lock on device %s."),
+ device_path(crypt_metadata_device(cd)));
+ return r;
+ }
+
+ r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1, !repair);
+ if (r == -EAGAIN) {
+ /* unlikely: auto-recovery is required and failed due to read lock being held */
+ device_read_unlock(cd, crypt_metadata_device(cd));
+
+ /* Do not use LUKS2_device_write lock. Recovery. */
+ r = device_write_lock(cd, crypt_metadata_device(cd));
+ if (r < 0) {
+ log_err(cd, _("Failed to acquire write lock on device %s."),
+ device_path(crypt_metadata_device(cd)));
+ return r;
+ }
+
+ r = LUKS2_disk_hdr_read(cd, hdr, crypt_metadata_device(cd), 1, !repair);
+
+ device_write_unlock(cd, crypt_metadata_device(cd));
+ } else
+ device_read_unlock(cd, crypt_metadata_device(cd));
+
+ if (!r && (r = hdr_update_copy_for_rollback(cd, hdr)))
+ log_dbg(cd, "Failed to update rollback LUKS2 metadata.");
+
+ return r;
+}
+
+static int hdr_cleanup_and_validate(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ LUKS2_digests_erase_unused(cd, hdr);
+
+ return LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN);
+}
+
+int LUKS2_hdr_write_force(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ int r;
+
+ if (hdr_cleanup_and_validate(cd, hdr))
+ return -EINVAL;
+
+ r = LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), false);
+
+ if (!r && (r = hdr_update_copy_for_rollback(cd, hdr)))
+ log_dbg(cd, "Failed to update rollback LUKS2 metadata.");
+
+ return r;
+}
+
+int LUKS2_hdr_write(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ int r;
+
+ if (hdr_cleanup_and_validate(cd, hdr))
+ return -EINVAL;
+
+ r = LUKS2_disk_hdr_write(cd, hdr, crypt_metadata_device(cd), true);
+
+ if (!r && (r = hdr_update_copy_for_rollback(cd, hdr)))
+ log_dbg(cd, "Failed to update rollback LUKS2 metadata.");
+
+ return r;
+}
+
+int LUKS2_hdr_rollback(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ json_object **jobj_copy;
+
+ assert(hdr->jobj_rollback);
+
+ log_dbg(cd, "Rolling back in-memory LUKS2 json metadata.");
+
+ jobj_copy = (json_object **)&hdr->jobj;
+
+ if (!hdr_json_free(jobj_copy)) {
+ log_dbg(cd, "LUKS2 header still in use");
+ return -EINVAL;
+ }
+
+ return json_object_copy(hdr->jobj_rollback, jobj_copy) ? -ENOMEM : 0;
+}
+
+int LUKS2_hdr_uuid(struct crypt_device *cd, struct luks2_hdr *hdr, const char *uuid)
+{
+ uuid_t partitionUuid;
+
+ if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
+ log_err(cd, _("Wrong LUKS UUID format provided."));
+ return -EINVAL;
+ }
+ if (!uuid)
+ uuid_generate(partitionUuid);
+
+ uuid_unparse(partitionUuid, hdr->uuid);
+
+ return LUKS2_hdr_write(cd, hdr);
+}
+
+int LUKS2_hdr_labels(struct crypt_device *cd, struct luks2_hdr *hdr,
+ const char *label, const char *subsystem, int commit)
+{
+ //FIXME: check if the labels are the same and skip this.
+
+ memset(hdr->label, 0, LUKS2_LABEL_L);
+ if (label)
+ strncpy(hdr->label, label, LUKS2_LABEL_L-1);
+
+ memset(hdr->subsystem, 0, LUKS2_LABEL_L);
+ if (subsystem)
+ strncpy(hdr->subsystem, subsystem, LUKS2_LABEL_L-1);
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ json_object **jobj;
+
+ assert(hdr);
+
+ jobj = (json_object **)&hdr->jobj;
+
+ if (!hdr_json_free(jobj))
+ log_dbg(cd, "LUKS2 header still in use");
+
+ jobj = (json_object **)&hdr->jobj_rollback;
+
+ if (!hdr_json_free(jobj))
+ log_dbg(cd, "LUKS2 rollback metadata copy still in use");
+}
+
+static uint64_t LUKS2_keyslots_size_jobj(json_object *jobj)
+{
+ json_object *jobj1, *jobj2;
+ uint64_t keyslots_size;
+
+ json_object_object_get_ex(jobj, "config", &jobj1);
+ json_object_object_get_ex(jobj1, "keyslots_size", &jobj2);
+ json_str_to_uint64(jobj2, &keyslots_size);
+
+ return keyslots_size;
+}
+
+uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr)
+{
+ return LUKS2_keyslots_size_jobj(hdr->jobj);
+}
+
+uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj)
+{
+ return 2 * LUKS2_metadata_size_jobj(jobj) + LUKS2_keyslots_size_jobj(jobj);
+}
+
+uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr)
+{
+ return LUKS2_hdr_and_areas_size_jobj(hdr->jobj);
+}
+
+int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
+ const char *backup_file)
+{
+ struct device *device = crypt_metadata_device(cd);
+ int fd, devfd, r = 0;
+ ssize_t hdr_size;
+ ssize_t ret, buffer_size;
+ char *buffer = NULL;
+
+ hdr_size = LUKS2_hdr_and_areas_size(hdr);
+ buffer_size = size_round_up(hdr_size, crypt_getpagesize());
+
+ buffer = malloc(buffer_size);
+ if (!buffer)
+ return -ENOMEM;
+
+ log_dbg(cd, "Storing backup of header (%zu bytes).", hdr_size);
+ log_dbg(cd, "Output backup file size: %zu bytes.", buffer_size);
+
+ r = device_read_lock(cd, device);
+ if (r) {
+ log_err(cd, _("Failed to acquire read lock on device %s."),
+ device_path(crypt_metadata_device(cd)));
+ goto out;
+ }
+
+ devfd = device_open_locked(cd, device, O_RDONLY);
+ if (devfd < 0) {
+ device_read_unlock(cd, device);
+ log_err(cd, _("Device %s is not a valid LUKS device."), device_path(device));
+ r = (devfd == -1) ? -EINVAL : devfd;
+ goto out;
+ }
+
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), buffer, hdr_size, 0) < hdr_size) {
+ device_read_unlock(cd, device);
+ r = -EIO;
+ goto out;
+ }
+
+ device_read_unlock(cd, device);
+
+ fd = open(backup_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
+ if (fd == -1) {
+ if (errno == EEXIST)
+ log_err(cd, _("Requested header backup file %s already exists."), backup_file);
+ else
+ log_err(cd, _("Cannot create header backup file %s."), backup_file);
+ r = -EINVAL;
+ goto out;
+ }
+ ret = write_buffer(fd, buffer, buffer_size);
+ close(fd);
+ if (ret < buffer_size) {
+ log_err(cd, _("Cannot write header backup file %s."), backup_file);
+ r = -EIO;
+ } else
+ r = 0;
+out:
+ crypt_safe_memzero(buffer, buffer_size);
+ free(buffer);
+ return r;
+}
+
+int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
+ const char *backup_file)
+{
+ struct device *backup_device, *device = crypt_metadata_device(cd);
+ int r, fd, devfd = -1, diff_uuid = 0;
+ ssize_t ret, buffer_size = 0;
+ char *buffer = NULL, msg[1024];
+ struct luks2_hdr hdr_file = {}, tmp_hdr = {};
+ uint32_t reqs = 0;
+
+ r = device_alloc(cd, &backup_device, backup_file);
+ if (r < 0)
+ return r;
+
+ r = device_read_lock(cd, backup_device);
+ if (r) {
+ log_err(cd, _("Failed to acquire read lock on device %s."),
+ device_path(backup_device));
+ device_free(cd, backup_device);
+ return r;
+ }
+
+ r = LUKS2_disk_hdr_read(cd, &hdr_file, backup_device, 0, 0);
+ device_read_unlock(cd, backup_device);
+ device_free(cd, backup_device);
+
+ if (r < 0) {
+ log_err(cd, _("Backup file does not contain valid LUKS header."));
+ goto out;
+ }
+
+ /* do not allow header restore from backup with unmet requirements */
+ if (LUKS2_unmet_requirements(cd, &hdr_file, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1)) {
+ log_err(cd, _("Forbidden LUKS2 requirements detected in backup %s."),
+ backup_file);
+ r = -ETXTBSY;
+ goto out;
+ }
+
+ buffer_size = LUKS2_hdr_and_areas_size(&hdr_file);
+ buffer = malloc(buffer_size);
+ if (!buffer) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ fd = open(backup_file, O_RDONLY);
+ if (fd == -1) {
+ log_err(cd, _("Cannot open header backup file %s."), backup_file);
+ r = -EINVAL;
+ goto out;
+ }
+
+ ret = read_buffer(fd, buffer, buffer_size);
+ close(fd);
+ if (ret < buffer_size) {
+ log_err(cd, _("Cannot read header backup file %s."), backup_file);
+ r = -EIO;
+ goto out;
+ }
+
+ r = LUKS2_hdr_read(cd, &tmp_hdr, 0);
+ if (r == 0) {
+ log_dbg(cd, "Device %s already contains LUKS2 header, checking UUID and requirements.", device_path(device));
+ r = LUKS2_config_get_requirements(cd, &tmp_hdr, &reqs);
+ if (r)
+ goto out;
+
+ if (memcmp(tmp_hdr.uuid, hdr_file.uuid, LUKS2_UUID_L))
+ diff_uuid = 1;
+
+ if (!reqs_reencrypt(reqs)) {
+ log_dbg(cd, "Checking LUKS2 header size and offsets.");
+ if (LUKS2_get_data_offset(&tmp_hdr) != LUKS2_get_data_offset(&hdr_file)) {
+ log_err(cd, _("Data offset differ on device and backup, restore failed."));
+ r = -EINVAL;
+ goto out;
+ }
+ /* FIXME: what could go wrong? Erase if we're fine with consequences */
+ if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(&tmp_hdr)) {
+ log_err(cd, _("Binary header with keyslot areas size differ on device and backup, restore failed."));
+ r = -EINVAL;
+ goto out;
+ }
+ }
+ }
+
+ r = snprintf(msg, sizeof(msg), _("Device %s %s%s%s%s"), device_path(device),
+ r ? _("does not contain LUKS2 header. Replacing header can destroy data on that device.") :
+ _("already contains LUKS2 header. Replacing header will destroy existing keyslots."),
+ diff_uuid ? _("\nWARNING: real device header has different UUID than backup!") : "",
+ reqs_unknown(reqs) ? _("\nWARNING: unknown LUKS2 requirements detected in real device header!"
+ "\nReplacing header with backup may corrupt the data on that device!") : "",
+ reqs_reencrypt(reqs) ? _("\nWARNING: Unfinished offline reencryption detected on the device!"
+ "\nReplacing header with backup may corrupt data.") : "");
+ if (r < 0 || (size_t) r >= sizeof(msg)) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (!crypt_confirm(cd, msg)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ log_dbg(cd, "Storing backup of header (%zu bytes) to device %s.", buffer_size, device_path(device));
+
+ /* Do not use LUKS2_device_write lock for checking sequence id on restore */
+ r = device_write_lock(cd, device);
+ if (r < 0) {
+ log_err(cd, _("Failed to acquire write lock on device %s."),
+ device_path(device));
+ goto out;
+ }
+
+ devfd = device_open_locked(cd, device, O_RDWR);
+ if (devfd < 0) {
+ if (errno == EACCES)
+ log_err(cd, _("Cannot write to device %s, permission denied."),
+ device_path(device));
+ else
+ log_err(cd, _("Cannot open device %s."), device_path(device));
+ device_write_unlock(cd, device);
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), buffer, buffer_size, 0) < buffer_size)
+ r = -EIO;
+ else
+ r = 0;
+
+ device_write_unlock(cd, device);
+out:
+ LUKS2_hdr_free(cd, hdr);
+ LUKS2_hdr_free(cd, &hdr_file);
+ LUKS2_hdr_free(cd, &tmp_hdr);
+ crypt_safe_memzero(&hdr_file, sizeof(hdr_file));
+ crypt_safe_memzero(&tmp_hdr, sizeof(tmp_hdr));
+ crypt_safe_memzero(buffer, buffer_size);
+ free(buffer);
+ device_sync(cd, device);
+ return r;
+}
+
+/*
+ * Persistent config flags
+ */
+static const struct {
+ uint32_t flag;
+ const char *description;
+} persistent_flags[] = {
+ { CRYPT_ACTIVATE_ALLOW_DISCARDS, "allow-discards" },
+ { CRYPT_ACTIVATE_SAME_CPU_CRYPT, "same-cpu-crypt" },
+ { CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS, "submit-from-crypt-cpus" },
+ { CRYPT_ACTIVATE_NO_JOURNAL, "no-journal" },
+ { CRYPT_ACTIVATE_NO_READ_WORKQUEUE, "no-read-workqueue" },
+ { CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE, "no-write-workqueue" },
+ { 0, NULL }
+};
+
+int LUKS2_config_get_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *flags)
+{
+ json_object *jobj1, *jobj_config, *jobj_flags;
+ int i, j, found;
+
+ if (!hdr || !flags)
+ return -EINVAL;
+
+ *flags = 0;
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_config, "flags", &jobj_flags))
+ return 0;
+
+ for (i = 0; i < (int) json_object_array_length(jobj_flags); i++) {
+ jobj1 = json_object_array_get_idx(jobj_flags, i);
+ found = 0;
+ for (j = 0; persistent_flags[j].description && !found; j++)
+ if (!strcmp(persistent_flags[j].description,
+ json_object_get_string(jobj1))) {
+ *flags |= persistent_flags[j].flag;
+ log_dbg(cd, "Using persistent flag %s.",
+ json_object_get_string(jobj1));
+ found = 1;
+ }
+ if (!found)
+ log_verbose(cd, _("Ignored unknown flag %s."),
+ json_object_get_string(jobj1));
+ }
+
+ return 0;
+}
+
+int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t flags)
+{
+ json_object *jobj_config, *jobj_flags;
+ int i;
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return 0;
+
+ jobj_flags = json_object_new_array();
+
+ for (i = 0; persistent_flags[i].description; i++) {
+ if (flags & persistent_flags[i].flag) {
+ log_dbg(cd, "Setting persistent flag: %s.", persistent_flags[i].description);
+ json_object_array_add(jobj_flags,
+ json_object_new_string(persistent_flags[i].description));
+ }
+ }
+
+ /* Replace or add new flags array */
+ json_object_object_add(jobj_config, "flags", jobj_flags);
+
+ return LUKS2_hdr_write(cd, hdr);
+}
+
+/*
+ * json format example (mandatory array must not be ignored,
+ * all other future fields may be added later)
+ *
+ * "requirements": {
+ * mandatory : [],
+ * optional0 : [],
+ * optional1 : "lala"
+ * }
+ */
+
+/* LUKS2 library requirements */
+struct requirement_flag {
+ uint32_t flag;
+ uint8_t version;
+ const char *description;
+};
+
+static const struct requirement_flag unknown_requirement_flag = { CRYPT_REQUIREMENT_UNKNOWN, 0, NULL };
+
+static const struct requirement_flag requirements_flags[] = {
+ { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT,1, "offline-reencrypt" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 3, "online-reencrypt-v3" },
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
+ { 0, 0, NULL }
+};
+
+static const struct requirement_flag *get_requirement_by_name(const char *requirement)
+{
+ int i;
+
+ for (i = 0; requirements_flags[i].description; i++)
+ if (!strcmp(requirement, requirements_flags[i].description))
+ return requirements_flags + i;
+
+ return &unknown_requirement_flag;
+}
+
+static json_object *mandatory_requirements_jobj(struct luks2_hdr *hdr)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory;
+
+ assert(hdr);
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
+ return NULL;
+
+ return jobj_mandatory;
+}
+
+bool LUKS2_reencrypt_requirement_candidate(struct luks2_hdr *hdr)
+{
+ json_object *jobj_mandatory;
+ int i, len;
+
+ assert(hdr);
+
+ jobj_mandatory = mandatory_requirements_jobj(hdr);
+ if (!jobj_mandatory)
+ return false;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return false;
+
+ for (i = 0; i < len; i++) {
+ if (reencrypt_candidate_flag(json_object_get_string(json_object_array_get_idx(jobj_mandatory, i))))
+ return true;
+ }
+
+ return false;
+}
+
+int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint8_t *version)
+{
+ json_object *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr);
+ assert(version);
+
+ jobj_mandatory = mandatory_requirements_jobj(hdr);
+ if (!jobj_mandatory)
+ return -ENOENT;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return -ENOENT;
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+
+ /* search for requirements prefixed with "online-reencrypt" */
+ if (strncmp(json_object_get_string(jobj), "online-reencrypt", 16))
+ continue;
+
+ /* check current library is aware of the requirement */
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == CRYPT_REQUIREMENT_UNKNOWN)
+ continue;
+
+ *version = req->version;
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
+{
+ json_object *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr);
+
+ jobj_mandatory = mandatory_requirements_jobj(hdr);
+ if (!jobj_mandatory)
+ return NULL;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return NULL;
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == req_id)
+ return req;
+ }
+
+ return NULL;
+}
+
+/*
+ * returns count of requirements (past cryptsetup 2.0 release)
+ */
+int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t *reqs)
+{
+ json_object *jobj_mandatory, *jobj;
+ int i, len;
+ const struct requirement_flag *req;
+
+ assert(hdr);
+ assert(reqs);
+
+ *reqs = 0;
+
+ jobj_mandatory = mandatory_requirements_jobj(hdr);
+ if (!jobj_mandatory)
+ return 0;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+ if (len <= 0)
+ return 0;
+
+ log_dbg(cd, "LUKS2 requirements detected:");
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ log_dbg(cd, "%s - %sknown", json_object_get_string(jobj),
+ reqs_unknown(req->flag) ? "un" : "");
+ *reqs |= req->flag;
+ }
+
+ return 0;
+}
+
+int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs, bool commit)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
+ int i, r = -EINVAL;
+ const struct requirement_flag *req;
+ uint32_t req_id;
+
+ if (!hdr)
+ return -EINVAL;
+
+ jobj_mandatory = json_object_new_array();
+ if (!jobj_mandatory)
+ return -ENOMEM;
+
+ for (i = 0; requirements_flags[i].description; i++) {
+ req_id = reqs & requirements_flags[i].flag;
+ if (req_id) {
+ /* retain already stored version of requirement flag */
+ req = stored_requirement_name_by_id(cd, hdr, req_id);
+ if (req)
+ jobj = json_object_new_string(req->description);
+ else
+ jobj = json_object_new_string(requirements_flags[i].description);
+ if (!jobj) {
+ r = -ENOMEM;
+ goto err;
+ }
+ json_object_array_add(jobj_mandatory, jobj);
+ /* erase processed flag from input set */
+ reqs &= ~(requirements_flags[i].flag);
+ }
+ }
+
+ /* any remaining bit in requirements is unknown therefore illegal */
+ if (reqs) {
+ log_dbg(cd, "Illegal requirement flag(s) requested");
+ goto err;
+ }
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ goto err;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements)) {
+ jobj_requirements = json_object_new_object();
+ if (!jobj_requirements) {
+ r = -ENOMEM;
+ goto err;
+ }
+ json_object_object_add(jobj_config, "requirements", jobj_requirements);
+ }
+
+ if (json_object_array_length(jobj_mandatory) > 0) {
+ /* replace mandatory field with new values */
+ json_object_object_add(jobj_requirements, "mandatory", jobj_mandatory);
+ } else {
+ /* new mandatory field was empty, delete old one */
+ json_object_object_del(jobj_requirements, "mandatory");
+ json_object_put(jobj_mandatory);
+ }
+
+ /* remove empty requirements object */
+ if (!json_object_object_length(jobj_requirements))
+ json_object_object_del(jobj_config, "requirements");
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+err:
+ json_object_put(jobj_mandatory);
+ return r;
+}
+
+static json_object *LUKS2_get_mandatory_requirements_filtered_jobj(struct luks2_hdr *hdr,
+ uint32_t filter_req_ids)
+{
+ int i, len;
+ const struct requirement_flag *req;
+ json_object *jobj_mandatory, *jobj_mandatory_filtered, *jobj;
+
+ jobj_mandatory_filtered = json_object_new_array();
+ if (!jobj_mandatory_filtered)
+ return NULL;
+
+ jobj_mandatory = mandatory_requirements_jobj(hdr);
+ if (!jobj_mandatory)
+ return jobj_mandatory_filtered;
+
+ len = (int) json_object_array_length(jobj_mandatory);
+
+ for (i = 0; i < len; i++) {
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
+ req = get_requirement_by_name(json_object_get_string(jobj));
+ if (req->flag == CRYPT_REQUIREMENT_UNKNOWN || req->flag & filter_req_ids)
+ continue;
+ json_object_array_add(jobj_mandatory_filtered,
+ json_object_new_string(req->description));
+ }
+
+ return jobj_mandatory_filtered;
+}
+
+/*
+ * The function looks for specific version of requirement id.
+ * If it can't be fulfilled function fails.
+ */
+int LUKS2_config_set_requirement_version(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint32_t req_id,
+ uint8_t req_version,
+ bool commit)
+{
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory;
+ const struct requirement_flag *req;
+ int r = -EINVAL;
+
+ if (!hdr || req_id == CRYPT_REQUIREMENT_UNKNOWN)
+ return -EINVAL;
+
+ req = requirements_flags;
+
+ while (req->description) {
+ /* we have a match */
+ if (req->flag == req_id && req->version == req_version)
+ break;
+ req++;
+ }
+
+ if (!req->description)
+ return -EINVAL;
+
+ /*
+ * Creates copy of mandatory requirements set without specific requirement
+ * (no matter the version) we want to set.
+ */
+ jobj_mandatory = LUKS2_get_mandatory_requirements_filtered_jobj(hdr, req_id);
+ if (!jobj_mandatory)
+ return -ENOMEM;
+
+ json_object_array_add(jobj_mandatory, json_object_new_string(req->description));
+
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
+ goto err;
+
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements)) {
+ jobj_requirements = json_object_new_object();
+ if (!jobj_requirements) {
+ r = -ENOMEM;
+ goto err;
+ }
+ json_object_object_add(jobj_config, "requirements", jobj_requirements);
+ }
+
+ json_object_object_add(jobj_requirements, "mandatory", jobj_mandatory);
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+err:
+ json_object_put(jobj_mandatory);
+ return r;
+}
+
+/*
+ * Header dump
+ */
+static void hdr_dump_config(struct crypt_device *cd, json_object *hdr_jobj)
+{
+
+ json_object *jobj1, *jobj_config, *jobj_flags, *jobj_requirements, *jobj_mandatory;
+ int i = 0, flags = 0, reqs = 0;
+
+ log_std(cd, "Flags: \t");
+
+ if (json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) {
+ if (json_object_object_get_ex(jobj_config, "flags", &jobj_flags))
+ flags = (int) json_object_array_length(jobj_flags);
+ if (json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements) &&
+ json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
+ reqs = (int) json_object_array_length(jobj_mandatory);
+ }
+
+ for (i = 0; i < flags; i++) {
+ jobj1 = json_object_array_get_idx(jobj_flags, i);
+ log_std(cd, "%s ", json_object_get_string(jobj1));
+ }
+
+ log_std(cd, "%s\n%s", flags > 0 ? "" : "(no flags)", reqs > 0 ? "" : "\n");
+
+ if (reqs > 0) {
+ log_std(cd, "Requirements:\t");
+ for (i = 0; i < reqs; i++) {
+ jobj1 = json_object_array_get_idx(jobj_mandatory, i);
+ log_std(cd, "%s ", json_object_get_string(jobj1));
+ }
+ log_std(cd, "\n\n");
+ }
+}
+
+static const char *get_priority_desc(json_object *jobj)
+{
+ crypt_keyslot_priority priority;
+ json_object *jobj_priority;
+ const char *text;
+
+ if (json_object_object_get_ex(jobj, "priority", &jobj_priority))
+ priority = (crypt_keyslot_priority)(int)json_object_get_int(jobj_priority);
+ else
+ priority = CRYPT_SLOT_PRIORITY_NORMAL;
+
+ switch (priority) {
+ case CRYPT_SLOT_PRIORITY_IGNORE: text = "ignored"; break;
+ case CRYPT_SLOT_PRIORITY_PREFER: text = "preferred"; break;
+ case CRYPT_SLOT_PRIORITY_NORMAL: text = "normal"; break;
+ default: text = "invalid";
+ }
+
+ return text;
+}
+
+static void hdr_dump_keyslots(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ char slot[16];
+ json_object *keyslots_jobj, *digests_jobj, *jobj2, *jobj3, *val;
+ const char *tmps;
+ int i, j, r;
+
+ log_std(cd, "Keyslots:\n");
+ json_object_object_get_ex(hdr_jobj, "keyslots", &keyslots_jobj);
+
+ for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++) {
+ if (snprintf(slot, sizeof(slot), "%i", j) < 0)
+ slot[0] = '\0';
+ json_object_object_get_ex(keyslots_jobj, slot, &val);
+ if (!val)
+ continue;
+
+ json_object_object_get_ex(val, "type", &jobj2);
+ tmps = json_object_get_string(jobj2);
+
+ r = LUKS2_keyslot_for_segment(crypt_get_hdr(cd, CRYPT_LUKS2), j, CRYPT_ONE_SEGMENT);
+ log_std(cd, " %s: %s%s\n", slot, tmps, r == -ENOENT ? " (unbound)" : "");
+
+ if (json_object_object_get_ex(val, "key_size", &jobj2))
+ log_std(cd, "\tKey: %u bits\n", crypt_jobj_get_uint32(jobj2) * 8);
+
+ log_std(cd, "\tPriority: %s\n", get_priority_desc(val));
+
+ LUKS2_keyslot_dump(cd, j);
+
+ json_object_object_get_ex(hdr_jobj, "digests", &digests_jobj);
+ json_object_object_foreach(digests_jobj, key2, val2) {
+ json_object_object_get_ex(val2, "keyslots", &jobj2);
+ for (i = 0; i < (int) json_object_array_length(jobj2); i++) {
+ jobj3 = json_object_array_get_idx(jobj2, i);
+ if (!strcmp(slot, json_object_get_string(jobj3))) {
+ log_std(cd, "\tDigest ID: %s\n", key2);
+ }
+ }
+ }
+ }
+}
+
+static void hdr_dump_tokens(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ char token[16];
+ json_object *tokens_jobj, *jobj2, *jobj3, *val;
+ const char *tmps;
+ int i, j;
+
+ log_std(cd, "Tokens:\n");
+ json_object_object_get_ex(hdr_jobj, "tokens", &tokens_jobj);
+
+ for (j = 0; j < LUKS2_TOKENS_MAX; j++) {
+ if (snprintf(token, sizeof(token), "%i", j) < 0)
+ token[0] = '\0';
+ json_object_object_get_ex(tokens_jobj, token, &val);
+ if (!val)
+ continue;
+
+ json_object_object_get_ex(val, "type", &jobj2);
+ tmps = json_object_get_string(jobj2);
+ log_std(cd, " %s: %s\n", token, tmps);
+
+ LUKS2_token_dump(cd, j);
+
+ json_object_object_get_ex(val, "keyslots", &jobj2);
+ for (i = 0; i < (int) json_object_array_length(jobj2); i++) {
+ jobj3 = json_object_array_get_idx(jobj2, i);
+ log_std(cd, "\tKeyslot: %s\n", json_object_get_string(jobj3));
+ }
+ }
+}
+
+static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ char segment[16];
+ json_object *jobj_segments, *jobj_segment, *jobj1, *jobj2;
+ int i, j, flags;
+ uint64_t value;
+
+ log_std(cd, "Data segments:\n");
+ json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments);
+
+ for (i = 0; i < LUKS2_SEGMENT_MAX; i++) {
+ if (snprintf(segment, sizeof(segment), "%i", i) < 0)
+ segment[0] = '\0';
+ if (!json_object_object_get_ex(jobj_segments, segment, &jobj_segment))
+ continue;
+
+ json_object_object_get_ex(jobj_segment, "type", &jobj1);
+ log_std(cd, " %s: %s\n", segment, json_object_get_string(jobj1));
+
+ json_object_object_get_ex(jobj_segment, "offset", &jobj1);
+ json_str_to_uint64(jobj1, &value);
+ log_std(cd, "\toffset: %" PRIu64 " [bytes]\n", value);
+
+ json_object_object_get_ex(jobj_segment, "size", &jobj1);
+ if (!(strcmp(json_object_get_string(jobj1), "dynamic")))
+ log_std(cd, "\tlength: (whole device)\n");
+ else {
+ json_str_to_uint64(jobj1, &value);
+ log_std(cd, "\tlength: %" PRIu64 " [bytes]\n", value);
+ }
+
+ if (json_object_object_get_ex(jobj_segment, "encryption", &jobj1))
+ log_std(cd, "\tcipher: %s\n", json_object_get_string(jobj1));
+
+ if (json_object_object_get_ex(jobj_segment, "sector_size", &jobj1))
+ log_std(cd, "\tsector: %" PRIu32 " [bytes]\n", crypt_jobj_get_uint32(jobj1));
+
+ if (json_object_object_get_ex(jobj_segment, "integrity", &jobj1) &&
+ json_object_object_get_ex(jobj1, "type", &jobj2))
+ log_std(cd, "\tintegrity: %s\n", json_object_get_string(jobj2));
+
+ if (json_object_object_get_ex(jobj_segment, "flags", &jobj1) &&
+ (flags = (int)json_object_array_length(jobj1)) > 0) {
+ jobj2 = json_object_array_get_idx(jobj1, 0);
+ log_std(cd, "\tflags : %s", json_object_get_string(jobj2));
+ for (j = 1; j < flags; j++) {
+ jobj2 = json_object_array_get_idx(jobj1, j);
+ log_std(cd, ", %s", json_object_get_string(jobj2));
+ }
+ log_std(cd, "\n");
+ }
+
+ log_std(cd, "\n");
+ }
+}
+
+static void hdr_dump_digests(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ char key[16];
+ json_object *jobj1, *jobj2, *val;
+ const char *tmps;
+ int i;
+
+ log_std(cd, "Digests:\n");
+ json_object_object_get_ex(hdr_jobj, "digests", &jobj1);
+
+ for (i = 0; i < LUKS2_DIGEST_MAX; i++) {
+ if (snprintf(key, sizeof(key), "%i", i) < 0)
+ key[0] = '\0';
+ json_object_object_get_ex(jobj1, key, &val);
+ if (!val)
+ continue;
+
+ json_object_object_get_ex(val, "type", &jobj2);
+ tmps = json_object_get_string(jobj2);
+ log_std(cd, " %s: %s\n", key, tmps);
+
+ LUKS2_digest_dump(cd, i);
+ }
+}
+
+int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr)
+{
+ if (!hdr->jobj)
+ return -EINVAL;
+
+ JSON_DBG(cd, hdr->jobj, NULL);
+
+ log_std(cd, "LUKS header information\n");
+ log_std(cd, "Version: \t%u\n", hdr->version);
+ log_std(cd, "Epoch: \t%" PRIu64 "\n", hdr->seqid);
+ log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size(hdr));
+ log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size(hdr));
+ log_std(cd, "UUID: \t%s\n", *hdr->uuid ? hdr->uuid : "(no UUID)");
+ log_std(cd, "Label: \t%s\n", *hdr->label ? hdr->label : "(no label)");
+ log_std(cd, "Subsystem: \t%s\n", *hdr->subsystem ? hdr->subsystem : "(no subsystem)");
+
+ hdr_dump_config(cd, hdr->jobj);
+ hdr_dump_segments(cd, hdr->jobj);
+ hdr_dump_keyslots(cd, hdr->jobj);
+ hdr_dump_tokens(cd, hdr->jobj);
+ hdr_dump_digests(cd, hdr->jobj);
+
+ return 0;
+}
+
+int LUKS2_hdr_dump_json(struct crypt_device *cd, struct luks2_hdr *hdr, const char **json)
+{
+ const char *json_buf;
+
+ json_buf = json_object_to_json_string_ext(hdr->jobj,
+ JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
+
+ if (!json_buf)
+ return -EINVAL;
+
+ if (json)
+ *json = json_buf;
+ else
+ crypt_log(cd, CRYPT_LOG_NORMAL, json_buf);
+
+ return 0;
+}
+
+int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic)
+{
+ int i, len, sector_size;
+ json_object *jobj_segments, *jobj_segment, *jobj_size;
+ uint64_t tmp = 0;
+
+ if (!size || !json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
+ return -EINVAL;
+
+ len = json_object_object_length(jobj_segments);
+
+ for (i = 0; i < len; i++) {
+ if (!(jobj_segment = json_segments_get_segment(jobj_segments, i)))
+ return -EINVAL;
+
+ if (json_segment_is_backup(jobj_segment))
+ break;
+
+ json_object_object_get_ex(jobj_segment, "size", &jobj_size);
+ if (!strcmp(json_object_get_string(jobj_size), "dynamic")) {
+ sector_size = json_segment_get_sector_size(jobj_segment);
+ /* last dynamic segment must have at least one sector in size */
+ if (tmp)
+ *size = tmp + (sector_size > 0 ? sector_size : SECTOR_SIZE);
+ else
+ *size = 0;
+ if (dynamic)
+ *dynamic = true;
+ return 0;
+ }
+
+ tmp += crypt_jobj_get_uint64(jobj_size);
+ }
+
+ /* impossible, real device size must not be zero */
+ if (!tmp)
+ return -EINVAL;
+
+ *size = tmp;
+ if (dynamic)
+ *dynamic = false;
+ return 0;
+}
+
+uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr)
+{
+ crypt_reencrypt_info ri;
+ json_object *jobj;
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_CLEAN || ri == CRYPT_REENCRYPT_CRASH) {
+ jobj = LUKS2_get_segment_by_flag(hdr, "backup-final");
+ if (jobj)
+ return json_segment_get_offset(jobj, 1);
+ }
+
+ return json_segments_get_minimal_offset(LUKS2_get_segments_jobj(hdr), 1);
+}
+
+const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment)
+{
+ json_object *jobj_segment;
+
+ if (!hdr)
+ return NULL;
+
+ if (segment == CRYPT_DEFAULT_SEGMENT)
+ segment = LUKS2_get_default_segment(hdr);
+
+ jobj_segment = json_segments_get_segment(json_get_segments_jobj(hdr->jobj), segment);
+ if (!jobj_segment)
+ return NULL;
+
+ /* FIXME: default encryption (for other segment types) must be string here. */
+ return json_segment_get_cipher(jobj_segment) ?: "null";
+}
+
+crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr)
+{
+ uint32_t reqs;
+
+ /*
+ * Any unknown requirement or offline reencryption should abort
+ * anything related to online-reencryption handling
+ */
+ if (LUKS2_config_get_requirements(NULL, hdr, &reqs))
+ return CRYPT_REENCRYPT_INVALID;
+
+ if (!reqs_reencrypt_online(reqs))
+ return CRYPT_REENCRYPT_NONE;
+
+ if (json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr)) < 0)
+ return CRYPT_REENCRYPT_CLEAN;
+
+ return CRYPT_REENCRYPT_CRASH;
+}
+
+const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj1;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return NULL;
+
+ /* currently we only support raw length preserving area encryption */
+ json_object_object_get_ex(jobj_area, "type", &jobj1);
+ if (strcmp(json_object_get_string(jobj1), "raw"))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_area, "key_size", &jobj1))
+ return NULL;
+ *key_size = json_object_get_int(jobj1);
+
+ if (!json_object_object_get_ex(jobj_area, "encryption", &jobj1))
+ return NULL;
+
+ return json_object_get_string(jobj1);
+}
+
+const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment)
+{
+ json_object *jobj1, *jobj2, *jobj3;
+
+ jobj1 = LUKS2_get_segment_jobj(hdr, segment);
+ if (!jobj1)
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj1, "integrity", &jobj2))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj2, "type", &jobj3))
+ return NULL;
+
+ return json_object_get_string(jobj3);
+}
+
+/* FIXME: this only ensures that once we have journal encryption, it is not ignored. */
+/* implement segment count and type restrictions (crypt and only single crypt) */
+static int LUKS2_integrity_compatible(struct luks2_hdr *hdr)
+{
+ json_object *jobj1, *jobj2, *jobj3, *jobj4;
+ const char *str;
+
+ if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj1))
+ return 0;
+
+ if (!(jobj2 = LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT)))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj2, "integrity", &jobj3))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj3, "journal_encryption", &jobj4) ||
+ !(str = json_object_get_string(jobj4)) ||
+ strcmp(str, "none"))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj3, "journal_integrity", &jobj4) ||
+ !(str = json_object_get_string(jobj4)) ||
+ strcmp(str, "none"))
+ return 0;
+
+ return 1;
+}
+
+static int LUKS2_keyslot_get_volume_key_size(struct luks2_hdr *hdr, const char *keyslot)
+{
+ json_object *jobj1, *jobj2, *jobj3;
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj1))
+ return -1;
+
+ if (!json_object_object_get_ex(jobj1, keyslot, &jobj2))
+ return -1;
+
+ if (!json_object_object_get_ex(jobj2, "key_size", &jobj3))
+ return -1;
+
+ return json_object_get_int(jobj3);
+}
+
+/* Key size used for encryption of keyslot */
+int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot)
+{
+ char keyslot_name[16];
+
+ if (snprintf(keyslot_name, sizeof(keyslot_name), "%u", keyslot) < 1)
+ return -1;
+
+ return LUKS2_keyslot_get_volume_key_size(hdr, keyslot_name);
+}
+
+int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment)
+{
+ json_object *jobj_digests, *jobj_digest_segments, *jobj_digest_keyslots, *jobj1;
+ char buf[16];
+
+ if (segment == CRYPT_DEFAULT_SEGMENT)
+ segment = LUKS2_get_default_segment(hdr);
+
+ if (snprintf(buf, sizeof(buf), "%u", segment) < 1)
+ return -1;
+
+ json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ UNUSED(key);
+ json_object_object_get_ex(val, "segments", &jobj_digest_segments);
+ json_object_object_get_ex(val, "keyslots", &jobj_digest_keyslots);
+
+ if (!LUKS2_array_jobj(jobj_digest_segments, buf))
+ continue;
+ if (json_object_array_length(jobj_digest_keyslots) <= 0)
+ continue;
+
+ jobj1 = json_object_array_get_idx(jobj_digest_keyslots, 0);
+
+ return LUKS2_keyslot_get_volume_key_size(hdr, json_object_get_string(jobj1));
+ }
+
+ return -1;
+}
+
+uint32_t LUKS2_get_sector_size(struct luks2_hdr *hdr)
+{
+ return json_segment_get_sector_size(LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT));
+}
+
+int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks,
+ json_object *jobj_segments,
+ struct crypt_dm_active_device *dmd)
+{
+ struct volume_key *vk;
+ json_object *jobj;
+ enum devcheck device_check;
+ int r;
+ unsigned s = 0;
+ uint64_t data_offset, segment_size, segment_offset, segment_start = 0;
+ struct dm_target *t = &dmd->segment;
+
+ if (dmd->flags & CRYPT_ACTIVATE_SHARED)
+ device_check = DEV_OK;
+ else
+ device_check = DEV_EXCL;
+
+ data_offset = LUKS2_reencrypt_data_offset(hdr, true);
+
+ r = device_block_adjust(cd, crypt_data_device(cd), device_check,
+ data_offset, &dmd->size, &dmd->flags);
+ if (r)
+ return r;
+
+ r = dm_targets_allocate(&dmd->segment, json_segments_count(jobj_segments));
+ if (r)
+ goto err;
+
+ r = -EINVAL;
+
+ while (t) {
+ jobj = json_segments_get_segment(jobj_segments, s);
+ if (!jobj) {
+ log_dbg(cd, "Internal error. Segment %u is null.", s);
+ r = -EINVAL;
+ goto err;
+ }
+
+ segment_offset = json_segment_get_offset(jobj, 1);
+ segment_size = json_segment_get_size(jobj, 1);
+ /* 'dynamic' length allowed in last segment only */
+ if (!segment_size && !t->next)
+ segment_size = dmd->size - segment_start;
+ if (!segment_size) {
+ log_dbg(cd, "Internal error. Wrong segment size %u", s);
+ r = -EINVAL;
+ goto err;
+ }
+
+ if (!strcmp(json_segment_type(jobj), "crypt")) {
+ vk = crypt_volume_key_by_id(vks, LUKS2_digest_by_segment(hdr, s));
+ if (!vk) {
+ log_err(cd, _("Missing key for dm-crypt segment %u"), s);
+ r = -EINVAL;
+ goto err;
+ }
+
+ r = dm_crypt_target_set(t, segment_start, segment_size,
+ crypt_data_device(cd), vk,
+ json_segment_get_cipher(jobj),
+ json_segment_get_iv_offset(jobj),
+ segment_offset, "none", 0,
+ json_segment_get_sector_size(jobj));
+ if (r) {
+ log_err(cd, _("Failed to set dm-crypt segment."));
+ goto err;
+ }
+ } else if (!strcmp(json_segment_type(jobj), "linear")) {
+ r = dm_linear_target_set(t, segment_start, segment_size, crypt_data_device(cd), segment_offset);
+ if (r) {
+ log_err(cd, _("Failed to set dm-linear segment."));
+ goto err;
+ }
+ } else {
+ r = -EINVAL;
+ goto err;
+ }
+
+ segment_start += segment_size;
+ t = t->next;
+ s++;
+ }
+
+ return r;
+err:
+ dm_targets_free(cd, dmd);
+ return r;
+}
+
+/* FIXME: This shares almost all code with activate_multi_custom */
+static int _reload_custom_multi(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vks,
+ json_object *jobj_segments,
+ uint64_t device_size,
+ uint32_t flags)
+{
+ int r;
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ struct crypt_dm_active_device dmd = {
+ .uuid = crypt_get_uuid(cd),
+ .size = device_size >> SECTOR_SHIFT
+ };
+
+ /* do not allow activation when particular requirements detected */
+ if ((r = LUKS2_unmet_requirements(cd, hdr, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0)))
+ return r;
+
+ /* Add persistent activation flags */
+ if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT))
+ LUKS2_config_get_flags(cd, hdr, &dmd.flags);
+
+ dmd.flags |= (flags | CRYPT_ACTIVATE_SHARED);
+
+ r = LUKS2_assembly_multisegment_dmd(cd, hdr, vks, jobj_segments, &dmd);
+ if (!r)
+ r = dm_reload_device(cd, name, &dmd, 0, 0);
+
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int LUKS2_reload(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vks,
+ uint64_t device_size,
+ uint32_t flags)
+{
+ if (crypt_get_integrity_tag_size(cd))
+ return -ENOTSUP;
+
+ return _reload_custom_multi(cd, name, vks,
+ LUKS2_get_segments_jobj(crypt_get_hdr(cd, CRYPT_LUKS2)), device_size, flags);
+}
+
+int LUKS2_activate_multi(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vks,
+ uint64_t device_size,
+ uint32_t flags)
+{
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ json_object *jobj_segments = LUKS2_get_segments_jobj(hdr);
+ int r;
+ struct crypt_dm_active_device dmd = {
+ .size = device_size,
+ .uuid = crypt_get_uuid(cd)
+ };
+
+ /* do not allow activation when particular requirements detected */
+ if ((r = LUKS2_unmet_requirements(cd, hdr, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0)))
+ return r;
+
+ /* Add persistent activation flags */
+ if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT))
+ LUKS2_config_get_flags(cd, hdr, &dmd.flags);
+
+ dmd.flags |= flags;
+
+ r = LUKS2_assembly_multisegment_dmd(cd, hdr, vks, jobj_segments, &dmd);
+ if (!r)
+ r = dm_create_device(cd, name, CRYPT_LUKS2, &dmd);
+
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int LUKS2_activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vk,
+ uint32_t flags)
+{
+ int r;
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ struct crypt_dm_active_device dmdi = {}, dmd = {
+ .uuid = crypt_get_uuid(cd)
+ };
+
+ /* do not allow activation when particular requirements detected */
+ if ((r = LUKS2_unmet_requirements(cd, hdr, 0, 0)))
+ return r;
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
+ vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd),
+ crypt_get_data_offset(cd), crypt_get_integrity(cd) ?: "none",
+ crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
+ if (r < 0)
+ return r;
+
+ /* Add persistent activation flags */
+ if (!(flags & CRYPT_ACTIVATE_IGNORE_PERSISTENT))
+ LUKS2_config_get_flags(cd, hdr, &dmd.flags);
+
+ dmd.flags |= flags;
+
+ if (crypt_get_integrity_tag_size(cd)) {
+ if (!LUKS2_integrity_compatible(hdr)) {
+ log_err(cd, _("Unsupported device integrity configuration."));
+ return -EINVAL;
+ }
+
+ if (dmd.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
+ log_err(cd, _("Discard/TRIM is not supported."));
+ return -EINVAL;
+ }
+
+ r = INTEGRITY_create_dmd_device(cd, NULL, NULL, NULL, NULL, &dmdi, dmd.flags, 0);
+ if (r)
+ return r;
+
+ dmdi.flags |= CRYPT_ACTIVATE_PRIVATE;
+ dmdi.uuid = dmd.uuid;
+ dmd.segment.u.crypt.offset = 0;
+ dmd.segment.size = dmdi.segment.size;
+
+ r = create_or_reload_device_with_integrity(cd, name, CRYPT_LUKS2, &dmd, &dmdi);
+ } else
+ r = create_or_reload_device(cd, name, CRYPT_LUKS2, &dmd);
+
+ dm_targets_free(cd, &dmd);
+ dm_targets_free(cd, &dmdi);
+
+ return r;
+}
+
+static bool is_reencryption_helper(const char *name)
+{
+ size_t len;
+
+ if (!name)
+ return false;
+
+ len = strlen(name);
+ return (len >= 9 && (!strncmp(name + len - 8, "-hotzone-", 9) ||
+ !strcmp(name + len - 8, "-overlay")));
+
+}
+
+static bool contains_reencryption_helper(char **names)
+{
+ while (*names) {
+ if (is_reencryption_helper(*names++))
+ return true;
+ }
+
+ return false;
+}
+
+int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr *hdr, struct crypt_dm_active_device *dmd, uint32_t flags)
+{
+ int r, ret;
+ struct dm_target *tgt;
+ crypt_status_info ci;
+ struct crypt_dm_active_device dmdc;
+ char **dep, deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = { 0 };
+ const char *namei = NULL;
+ struct crypt_lock_handle *reencrypt_lock = NULL;
+
+ if (!dmd || !dmd->uuid || strncmp(CRYPT_LUKS2, dmd->uuid, sizeof(CRYPT_LUKS2)-1))
+ return -EINVAL;
+
+ /* uuid mismatch with metadata (if available) */
+ if (hdr && crypt_uuid_cmp(dmd->uuid, hdr->uuid))
+ return -EINVAL;
+
+ r = snprintf(deps_uuid_prefix, sizeof(deps_uuid_prefix), CRYPT_SUBDEV "-%.32s", dmd->uuid + 6);
+ if (r < 0 || (size_t)r != (sizeof(deps_uuid_prefix) - 1))
+ return -EINVAL;
+
+ tgt = &dmd->segment;
+
+ /* TODO: We have LUKS2 dependencies now */
+ if (single_segment(dmd) && tgt->type == DM_CRYPT && tgt->u.crypt.tag_size)
+ namei = device_dm_name(tgt->data_device);
+
+ r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps));
+ if (r < 0)
+ goto out;
+
+ if (contains_reencryption_helper(deps)) {
+ r = LUKS2_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_lock);
+ if (r) {
+ if (r == -EBUSY)
+ log_err(cd, _("Reencryption in-progress. Cannot deactivate device."));
+ else
+ log_err(cd, _("Failed to get reencryption lock."));
+ goto out;
+ }
+ }
+
+ dep = deps;
+ while (*dep) {
+ if (is_reencryption_helper(*dep) && (dm_status_suspended(cd, *dep) > 0)) {
+ if (dm_error_device(cd, *dep))
+ log_err(cd, _("Failed to replace suspended device %s with dm-error target."), *dep);
+ }
+ dep++;
+ }
+
+ r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE, &dmdc);
+ if (r < 0) {
+ memset(&dmdc, 0, sizeof(dmdc));
+ dmdc.segment.type = DM_UNKNOWN;
+ }
+
+ /* Remove top level device first */
+ r = dm_remove_device(cd, name, flags);
+ if (!r) {
+ tgt = &dmdc.segment;
+ while (tgt) {
+ if (tgt->type == DM_CRYPT)
+ crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY);
+ tgt = tgt->next;
+ }
+ }
+ dm_targets_free(cd, &dmdc);
+
+ /* TODO: We have LUKS2 dependencies now */
+ if (r >= 0 && namei) {
+ log_dbg(cd, "Deactivating integrity device %s.", namei);
+ r = dm_remove_device(cd, namei, 0);
+ }
+
+ if (!r) {
+ ret = 0;
+ dep = deps;
+ while (*dep) {
+ log_dbg(cd, "Deactivating LUKS2 dependent device %s.", *dep);
+ r = dm_query_device(cd, *dep, DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE, &dmdc);
+ if (r < 0) {
+ memset(&dmdc, 0, sizeof(dmdc));
+ dmdc.segment.type = DM_UNKNOWN;
+ }
+
+ r = dm_remove_device(cd, *dep, flags);
+ if (r < 0) {
+ ci = crypt_status(cd, *dep);
+ if (ci == CRYPT_BUSY)
+ log_err(cd, _("Device %s is still in use."), *dep);
+ if (ci == CRYPT_INACTIVE)
+ r = 0;
+ }
+ if (!r) {
+ tgt = &dmdc.segment;
+ while (tgt) {
+ if (tgt->type == DM_CRYPT)
+ crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY);
+ tgt = tgt->next;
+ }
+ }
+ dm_targets_free(cd, &dmdc);
+ if (r && !ret)
+ ret = r;
+ dep++;
+ }
+ r = ret;
+ }
+
+out:
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ dep = deps;
+ while (*dep)
+ free(*dep++);
+
+ return r;
+}
+
+int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t reqs_mask, int quiet)
+{
+ uint32_t reqs;
+ int r = LUKS2_config_get_requirements(cd, hdr, &reqs);
+
+ if (r) {
+ if (!quiet)
+ log_err(cd, _("Failed to read LUKS2 requirements."));
+ return r;
+ }
+
+ /* do not mask unknown requirements check */
+ if (reqs_unknown(reqs)) {
+ if (!quiet)
+ log_err(cd, _("Unmet LUKS2 requirements detected."));
+ return -ETXTBSY;
+ }
+
+ /* mask out permitted requirements */
+ reqs &= ~reqs_mask;
+
+ if (reqs_reencrypt(reqs) && !quiet)
+ log_err(cd, _("Operation incompatible with device marked for legacy reencryption. Aborting."));
+ if (reqs_reencrypt_online(reqs) && !quiet)
+ log_err(cd, _("Operation incompatible with device marked for LUKS2 reencryption. Aborting."));
+
+ /* any remaining unmasked requirement fails the check */
+ return reqs ? -EINVAL : 0;
+}
+
+/*
+ * NOTE: this routine is called on json object that failed validation.
+ * Proceed with caution :)
+ *
+ * known glitches so far:
+ *
+ * any version < 2.0.3:
+ * - luks2 keyslot pbkdf params change via crypt_keyslot_change_by_passphrase()
+ * could leave previous type parameters behind. Correct this by purging
+ * all params not needed by current type.
+ */
+void LUKS2_hdr_repair(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ json_object *jobj_keyslots;
+
+ if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
+ return;
+ if (!json_object_is_type(jobj_keyslots, json_type_object))
+ return;
+
+ LUKS2_keyslots_repair(cd, jobj_keyslots);
+}
+
+void json_object_object_del_by_uint(json_object *jobj, unsigned key)
+{
+ char key_name[16];
+
+ if (snprintf(key_name, sizeof(key_name), "%u", key) < 1)
+ return;
+ json_object_object_del(jobj, key_name);
+}
+
+int json_object_object_add_by_uint(json_object *jobj, unsigned key, json_object *jobj_val)
+{
+ char key_name[16];
+
+ if (snprintf(key_name, sizeof(key_name), "%u", key) < 1)
+ return -EINVAL;
+
+#if HAVE_DECL_JSON_OBJECT_OBJECT_ADD_EX
+ return json_object_object_add_ex(jobj, key_name, jobj_val, 0) ? -ENOMEM : 0;
+#else
+ json_object_object_add(jobj, key_name, jobj_val);
+ return 0;
+#endif
+}
+
+/* jobj_dst must contain pointer initialized to NULL (see json-c json_object_deep_copy API) */
+int json_object_copy(json_object *jobj_src, json_object **jobj_dst)
+{
+ if (!jobj_src || !jobj_dst || *jobj_dst)
+ return -1;
+
+#if HAVE_DECL_JSON_OBJECT_DEEP_COPY
+ return json_object_deep_copy(jobj_src, jobj_dst, NULL);
+#else
+ *jobj_dst = json_tokener_parse(json_object_get_string(jobj_src));
+ return *jobj_dst ? 0 : -1;
+#endif
+}
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
new file mode 100644
index 0000000..5cf4b83
--- /dev/null
+++ b/lib/luks2/luks2_keyslot.c
@@ -0,0 +1,977 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, keyslot handling
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+/* Internal implementations */
+extern const keyslot_handler luks2_keyslot;
+extern const keyslot_handler reenc_keyslot;
+
+static const keyslot_handler *keyslot_handlers[LUKS2_KEYSLOTS_MAX] = {
+ &luks2_keyslot,
+#if USE_LUKS2_REENCRYPTION
+ &reenc_keyslot,
+#endif
+ NULL
+};
+
+static const keyslot_handler
+*LUKS2_keyslot_handler_type(const char *type)
+{
+ int i;
+
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX && keyslot_handlers[i]; i++) {
+ if (!strcmp(keyslot_handlers[i]->name, type))
+ return keyslot_handlers[i];
+ }
+
+ return NULL;
+}
+
+static const keyslot_handler
+*LUKS2_keyslot_handler(struct crypt_device *cd, int keyslot)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj1, *jobj2;
+
+ if (keyslot < 0)
+ return NULL;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return NULL;
+
+ if (!(jobj1 = LUKS2_get_keyslot_jobj(hdr, keyslot)))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj1, "type", &jobj2))
+ return NULL;
+
+ return LUKS2_keyslot_handler_type(json_object_get_string(jobj2));
+}
+
+int LUKS2_keyslot_find_empty(struct crypt_device *cd, struct luks2_hdr *hdr, size_t keylength)
+{
+ int i;
+
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
+ if (!LUKS2_get_keyslot_jobj(hdr, i))
+ break;
+
+ if (i == LUKS2_KEYSLOTS_MAX)
+ return -EINVAL;
+
+ /* Check also there is a space for the key in keyslots area */
+ if (keylength && LUKS2_find_area_gap(cd, hdr, keylength, NULL, NULL) < 0)
+ return -ENOSPC;
+
+ return i;
+}
+
+/* Check if a keyslot is assigned to specific segment */
+static int _keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment)
+{
+ int keyslot_digest, count = 0;
+ unsigned s;
+
+ keyslot_digest = LUKS2_digest_by_keyslot(hdr, keyslot);
+ if (keyslot_digest < 0)
+ return keyslot_digest;
+
+ if (segment >= 0)
+ return keyslot_digest == LUKS2_digest_by_segment(hdr, segment);
+
+ for (s = 0; s < json_segments_count(LUKS2_get_segments_jobj(hdr)); s++) {
+ if (keyslot_digest == LUKS2_digest_by_segment(hdr, s))
+ count++;
+ }
+
+ return count;
+}
+
+static int _keyslot_for_digest(struct luks2_hdr *hdr, int keyslot, int digest)
+{
+ int r = -EINVAL;
+
+ r = LUKS2_digest_by_keyslot(hdr, keyslot);
+ if (r < 0)
+ return r;
+ return r == digest ? 0 : -ENOENT;
+}
+
+int LUKS2_keyslot_for_segment(struct luks2_hdr *hdr, int keyslot, int segment)
+{
+ int r = -EINVAL;
+
+ /* no need to check anything */
+ if (segment == CRYPT_ANY_SEGMENT)
+ return 0; /* ok */
+ if (segment == CRYPT_DEFAULT_SEGMENT) {
+ segment = LUKS2_get_default_segment(hdr);
+ if (segment < 0)
+ return segment;
+ }
+
+ r = _keyslot_for_segment(hdr, keyslot, segment);
+ if (r < 0)
+ return r;
+
+ return r >= 1 ? 0 : -ENOENT;
+}
+
+/* Number of keyslots assigned to a segment or all keyslots for CRYPT_ANY_SEGMENT */
+int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment)
+{
+ int num = 0;
+ json_object *jobj_keyslots;
+
+ json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots);
+
+ json_object_object_foreach(jobj_keyslots, slot, val) {
+ UNUSED(val);
+ if (!LUKS2_keyslot_for_segment(hdr, atoi(slot), segment))
+ num++;
+ }
+
+ return num;
+}
+
+int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd, const char *cipher_spec)
+{
+ char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+
+ if (!cipher_spec || crypt_is_cipher_null(cipher_spec))
+ return 1;
+
+ if (crypt_parse_name_and_mode(cipher_spec, cipher, NULL, cipher_mode) < 0)
+ return 1;
+
+ /* Keyslot is already authenticated; we cannot use integrity tags here */
+ if (crypt_get_integrity_tag_size(cd))
+ return 1;
+
+ /* Wrapped key schemes cannot be used for keyslot encryption */
+ if (crypt_cipher_wrapped_key(cipher, cipher_mode))
+ return 1;
+
+ /* Check if crypto backend can use the cipher */
+ if (crypt_cipher_ivsize(cipher, cipher_mode) < 0)
+ return 1;
+
+ return 0;
+}
+
+int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct luks2_keyslot_params *params)
+{
+ const struct crypt_pbkdf_type *pbkdf = crypt_get_pbkdf_type(cd);
+ const char *cipher_spec;
+ size_t key_size;
+ int r;
+
+ if (!hdr || !pbkdf || !params)
+ return -EINVAL;
+
+ /*
+ * set keyslot area encryption parameters
+ */
+ params->area_type = LUKS2_KEYSLOT_AREA_RAW;
+ cipher_spec = crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size);
+ if (!cipher_spec || !key_size)
+ return -EINVAL;
+
+ params->area.raw.key_size = key_size;
+ r = snprintf(params->area.raw.encryption, sizeof(params->area.raw.encryption), "%s", cipher_spec);
+ if (r < 0 || (size_t)r >= sizeof(params->area.raw.encryption))
+ return -EINVAL;
+
+ /*
+ * set keyslot AF parameters
+ */
+ params->af_type = LUKS2_KEYSLOT_AF_LUKS1;
+ /* currently we use hash for AF from pbkdf settings */
+ r = snprintf(params->af.luks1.hash, sizeof(params->af.luks1.hash), "%s", pbkdf->hash ?: DEFAULT_LUKS1_HASH);
+ if (r < 0 || (size_t)r >= sizeof(params->af.luks1.hash))
+ return -EINVAL;
+ params->af.luks1.stripes = 4000;
+
+ return 0;
+}
+
+int LUKS2_keyslot_pbkdf(struct luks2_hdr *hdr, int keyslot, struct crypt_pbkdf_type *pbkdf)
+{
+ json_object *jobj_keyslot, *jobj_kdf, *jobj;
+
+ if (!hdr || !pbkdf)
+ return -EINVAL;
+
+ if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -ENOENT;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_kdf, "type", &jobj))
+ return -EINVAL;
+
+ memset(pbkdf, 0, sizeof(*pbkdf));
+
+ pbkdf->type = json_object_get_string(jobj);
+ if (json_object_object_get_ex(jobj_kdf, "hash", &jobj))
+ pbkdf->hash = json_object_get_string(jobj);
+ if (json_object_object_get_ex(jobj_kdf, "iterations", &jobj))
+ pbkdf->iterations = json_object_get_int(jobj);
+ if (json_object_object_get_ex(jobj_kdf, "time", &jobj))
+ pbkdf->iterations = json_object_get_int(jobj);
+ if (json_object_object_get_ex(jobj_kdf, "memory", &jobj))
+ pbkdf->max_memory_kb = json_object_get_int(jobj);
+ if (json_object_object_get_ex(jobj_kdf, "cpus", &jobj))
+ pbkdf->parallel_threads = json_object_get_int(jobj);
+
+ return 0;
+}
+
+static int LUKS2_keyslot_unbound(struct luks2_hdr *hdr, int keyslot)
+{
+ json_object *jobj_digest, *jobj_segments;
+ int digest = LUKS2_digest_by_keyslot(hdr, keyslot);
+
+ if (digest < 0)
+ return 0;
+
+ if (!(jobj_digest = LUKS2_get_digest_jobj(hdr, digest)))
+ return 0;
+
+ json_object_object_get_ex(jobj_digest, "segments", &jobj_segments);
+ if (!jobj_segments || !json_object_is_type(jobj_segments, json_type_array) ||
+ json_object_array_length(jobj_segments) == 0)
+ return 1;
+
+ return 0;
+}
+
+crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot)
+{
+ if(keyslot >= LUKS2_KEYSLOTS_MAX || keyslot < 0)
+ return CRYPT_SLOT_INVALID;
+
+ if (!LUKS2_get_keyslot_jobj(hdr, keyslot))
+ return CRYPT_SLOT_INACTIVE;
+
+ if (LUKS2_digest_by_keyslot(hdr, keyslot) < 0 ||
+ LUKS2_keyslot_unbound(hdr, keyslot))
+ return CRYPT_SLOT_UNBOUND;
+
+ if (LUKS2_keyslot_active_count(hdr, CRYPT_DEFAULT_SEGMENT) == 1 &&
+ !LUKS2_keyslot_for_segment(hdr, keyslot, CRYPT_DEFAULT_SEGMENT))
+ return CRYPT_SLOT_ACTIVE_LAST;
+
+ return CRYPT_SLOT_ACTIVE;
+}
+
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length)
+{
+ json_object *jobj_area, *jobj;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_area, "offset", &jobj))
+ return -EINVAL;
+ *offset = crypt_jobj_get_uint64(jobj);
+
+ if (!json_object_object_get_ex(jobj_area, "size", &jobj))
+ return -EINVAL;
+ *length = crypt_jobj_get_uint64(jobj);
+
+ return 0;
+}
+
+int LUKS2_keyslot_area(struct luks2_hdr *hdr,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length)
+{
+ json_object *jobj_keyslot;
+
+ if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -ENOENT;
+
+ return LUKS2_keyslot_jobj_area(jobj_keyslot, offset, length);
+}
+
+static int _open_and_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const keyslot_handler *h,
+ int keyslot,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vk)
+{
+ int r, key_size = LUKS2_get_keyslot_stored_key_size(hdr, keyslot);
+
+ if (key_size < 0)
+ return -EINVAL;
+
+ *vk = crypt_alloc_volume_key(key_size, NULL);
+ if (!*vk)
+ return -ENOMEM;
+
+ r = h->open(cd, keyslot, password, password_len, (*vk)->key, (*vk)->keylength);
+ if (r < 0)
+ log_dbg(cd, "Keyslot %d (%s) open failed with %d.", keyslot, h->name, r);
+ else
+ r = LUKS2_digest_verify(cd, hdr, *vk, keyslot);
+
+ if (r < 0) {
+ crypt_free_volume_key(*vk);
+ *vk = NULL;
+ }
+
+ crypt_volume_key_set_id(*vk, r);
+
+ return r < 0 ? r : keyslot;
+}
+
+static int LUKS2_open_and_verify_by_digest(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int digest,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vk)
+{
+ const keyslot_handler *h;
+ int r;
+
+ if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
+ return -ENOENT;
+
+ r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
+ if (r) {
+ log_dbg(cd, "Keyslot %d validation failed.", keyslot);
+ return r;
+ }
+
+ r = _keyslot_for_digest(hdr, keyslot, digest);
+ if (r) {
+ if (r == -ENOENT)
+ log_dbg(cd, "Keyslot %d unusable for digest %d.", keyslot, digest);
+ return r;
+ }
+
+ return _open_and_verify(cd, hdr, h, keyslot, password, password_len, vk);
+}
+
+static int LUKS2_open_and_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int segment,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vk)
+{
+ const keyslot_handler *h;
+ int r;
+
+ if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
+ return -ENOENT;
+
+ r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
+ if (r) {
+ log_dbg(cd, "Keyslot %d validation failed.", keyslot);
+ return r;
+ }
+
+ r = LUKS2_keyslot_for_segment(hdr, keyslot, segment);
+ if (r) {
+ if (r == -ENOENT)
+ log_dbg(cd, "Keyslot %d unusable for segment %d.", keyslot, segment);
+ return r;
+ }
+
+ return _open_and_verify(cd, hdr, h, keyslot, password, password_len, vk);
+}
+
+static int LUKS2_keyslot_open_priority_digest(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ crypt_keyslot_priority priority,
+ const char *password,
+ size_t password_len,
+ int digest,
+ struct volume_key **vk)
+{
+ json_object *jobj_keyslots, *jobj;
+ crypt_keyslot_priority slot_priority;
+ int keyslot, r = -ENOENT;
+
+ json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots);
+
+ json_object_object_foreach(jobj_keyslots, slot, val) {
+ if (!json_object_object_get_ex(val, "priority", &jobj))
+ slot_priority = CRYPT_SLOT_PRIORITY_NORMAL;
+ else
+ slot_priority = json_object_get_int(jobj);
+
+ keyslot = atoi(slot);
+ if (slot_priority != priority) {
+ log_dbg(cd, "Keyslot %d priority %d != %d (required), skipped.",
+ keyslot, slot_priority, priority);
+ continue;
+ }
+
+ r = LUKS2_open_and_verify_by_digest(cd, hdr, keyslot, digest, password, password_len, vk);
+
+ /* Do not retry for errors that are no -EPERM or -ENOENT,
+ former meaning password wrong, latter key slot unusable for segment */
+ if ((r != -EPERM) && (r != -ENOENT))
+ break;
+ }
+
+ return r;
+}
+
+static int LUKS2_keyslot_open_priority(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ crypt_keyslot_priority priority,
+ const char *password,
+ size_t password_len,
+ int segment,
+ struct volume_key **vk)
+{
+ json_object *jobj_keyslots, *jobj;
+ crypt_keyslot_priority slot_priority;
+ int keyslot, r = -ENOENT;
+
+ json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots);
+
+ json_object_object_foreach(jobj_keyslots, slot, val) {
+ if (!json_object_object_get_ex(val, "priority", &jobj))
+ slot_priority = CRYPT_SLOT_PRIORITY_NORMAL;
+ else
+ slot_priority = json_object_get_int(jobj);
+
+ keyslot = atoi(slot);
+ if (slot_priority != priority) {
+ log_dbg(cd, "Keyslot %d priority %d != %d (required), skipped.",
+ keyslot, slot_priority, priority);
+ continue;
+ }
+
+ r = LUKS2_open_and_verify(cd, hdr, keyslot, segment, password, password_len, vk);
+
+ /* Do not retry for errors that are no -EPERM or -ENOENT,
+ former meaning password wrong, latter key slot unusable for segment */
+ if ((r != -EPERM) && (r != -ENOENT))
+ break;
+ }
+
+ return r;
+}
+
+static int LUKS2_keyslot_open_by_digest(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int digest,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vk)
+{
+ int r_prio, r = -EINVAL;
+
+ if (digest < 0)
+ return r;
+
+ if (keyslot == CRYPT_ANY_SLOT) {
+ r_prio = LUKS2_keyslot_open_priority_digest(cd, hdr, CRYPT_SLOT_PRIORITY_PREFER,
+ password, password_len, digest, vk);
+ if (r_prio >= 0)
+ r = r_prio;
+ else if (r_prio != -EPERM && r_prio != -ENOENT)
+ r = r_prio;
+ else
+ r = LUKS2_keyslot_open_priority_digest(cd, hdr, CRYPT_SLOT_PRIORITY_NORMAL,
+ password, password_len, digest, vk);
+ /* Prefer password wrong to no entry from priority slot */
+ if (r_prio == -EPERM && r == -ENOENT)
+ r = r_prio;
+ } else
+ r = LUKS2_open_and_verify_by_digest(cd, hdr, keyslot, digest, password, password_len, vk);
+
+ return r;
+}
+
+int LUKS2_keyslot_open_all_segments(struct crypt_device *cd,
+ int keyslot_old,
+ int keyslot_new,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vks)
+{
+ struct volume_key *vk = NULL;
+ int digest_old, digest_new, r = -EINVAL;
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ digest_old = LUKS2_reencrypt_digest_old(hdr);
+ if (digest_old >= 0) {
+ log_dbg(cd, "Trying to unlock volume key (digest: %d) using keyslot %d.", digest_old, keyslot_old);
+ r = LUKS2_keyslot_open_by_digest(cd, hdr, keyslot_old, digest_old, password, password_len, &vk);
+ if (r < 0)
+ goto out;
+ crypt_volume_key_add_next(vks, vk);
+ }
+
+ digest_new = LUKS2_reencrypt_digest_new(hdr);
+ if (digest_new >= 0 && digest_old != digest_new) {
+ log_dbg(cd, "Trying to unlock volume key (digest: %d) using keyslot %d.", digest_new, keyslot_new);
+ r = LUKS2_keyslot_open_by_digest(cd, hdr, keyslot_new, digest_new, password, password_len, &vk);
+ if (r < 0)
+ goto out;
+ crypt_volume_key_add_next(vks, vk);
+ }
+out:
+ if (r < 0) {
+ crypt_free_volume_key(*vks);
+ *vks = NULL;
+
+ if (r == -ENOMEM)
+ log_err(cd, _("Not enough available memory to open a keyslot."));
+ else if (r != -EPERM && r != -ENOENT)
+ log_err(cd, _("Keyslot open failed."));
+ }
+ return r;
+}
+
+int LUKS2_keyslot_open(struct crypt_device *cd,
+ int keyslot,
+ int segment,
+ const char *password,
+ size_t password_len,
+ struct volume_key **vk)
+{
+ struct luks2_hdr *hdr;
+ int r_prio, r = -EINVAL;
+
+ hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ if (keyslot == CRYPT_ANY_SLOT) {
+ r_prio = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_PREFER,
+ password, password_len, segment, vk);
+ if (r_prio >= 0)
+ r = r_prio;
+ else if (r_prio != -EPERM && r_prio != -ENOENT)
+ r = r_prio;
+ else
+ r = LUKS2_keyslot_open_priority(cd, hdr, CRYPT_SLOT_PRIORITY_NORMAL,
+ password, password_len, segment, vk);
+ /* Prefer password wrong to no entry from priority slot */
+ if (r_prio == -EPERM && r == -ENOENT)
+ r = r_prio;
+ } else
+ r = LUKS2_open_and_verify(cd, hdr, keyslot, segment, password, password_len, vk);
+
+ if (r < 0) {
+ if (r == -ENOMEM)
+ log_err(cd, _("Not enough available memory to open a keyslot."));
+ else if (r != -EPERM && r != -ENOENT)
+ log_err(cd, _("Keyslot open failed."));
+ }
+
+ return r;
+}
+
+int LUKS2_keyslot_reencrypt_store(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const void *buffer,
+ size_t buffer_length)
+{
+ const keyslot_handler *h;
+ int r;
+
+ if (!(h = LUKS2_keyslot_handler(cd, keyslot)) || strcmp(h->name, "reencrypt"))
+ return -EINVAL;
+
+ r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
+ if (r) {
+ log_dbg(cd, "Keyslot validation failed.");
+ return r;
+ }
+
+ return h->store(cd, keyslot, NULL, 0,
+ buffer, buffer_length);
+}
+
+int LUKS2_keyslot_store(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const char *password,
+ size_t password_len,
+ const struct volume_key *vk,
+ const struct luks2_keyslot_params *params)
+{
+ const keyslot_handler *h;
+ int r;
+
+ if (keyslot == CRYPT_ANY_SLOT)
+ return -EINVAL;
+
+ if (!LUKS2_get_keyslot_jobj(hdr, keyslot)) {
+ /* Try to allocate default and empty keyslot type */
+ h = LUKS2_keyslot_handler_type("luks2");
+ if (!h)
+ return -EINVAL;
+
+ r = h->alloc(cd, keyslot, vk->keylength, params);
+ if (r)
+ return r;
+ } else {
+ if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
+ return -EINVAL;
+
+ r = h->update(cd, keyslot, params);
+ if (r) {
+ log_dbg(cd, "Failed to update keyslot %d json.", keyslot);
+ return r;
+ }
+ }
+
+ r = h->validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
+ if (r) {
+ log_dbg(cd, "Keyslot validation failed.");
+ return r;
+ }
+
+ if (LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
+ return -EINVAL;
+
+ return h->store(cd, keyslot, password, password_len,
+ vk->key, vk->keylength);
+}
+
+int LUKS2_keyslot_wipe(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ int wipe_area_only)
+{
+ struct device *device = crypt_metadata_device(cd);
+ uint64_t area_offset, area_length;
+ int r;
+ json_object *jobj_keyslot, *jobj_keyslots;
+ const keyslot_handler *h;
+
+ h = LUKS2_keyslot_handler(cd, keyslot);
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -ENOENT;
+
+ if (wipe_area_only)
+ log_dbg(cd, "Wiping keyslot %d area only.", keyslot);
+
+ r = LUKS2_device_write_lock(cd, hdr, device);
+ if (r)
+ return r;
+
+ /* secure deletion of possible key material in keyslot area */
+ r = crypt_keyslot_area(cd, keyslot, &area_offset, &area_length);
+ if (r && r != -ENOENT)
+ goto out;
+
+ if (!r) {
+ r = crypt_wipe_device(cd, device, CRYPT_WIPE_SPECIAL, area_offset,
+ area_length, area_length, NULL, NULL);
+ if (r) {
+ if (r == -EACCES) {
+ log_err(cd, _("Cannot write to device %s, permission denied."),
+ device_path(device));
+ r = -EINVAL;
+ } else
+ log_err(cd, _("Cannot wipe device %s."), device_path(device));
+ goto out;
+ }
+ }
+
+ if (wipe_area_only)
+ goto out;
+
+ /* Slot specific wipe */
+ if (h) {
+ r = h->wipe(cd, keyslot);
+ if (r < 0)
+ goto out;
+ } else
+ log_dbg(cd, "Wiping keyslot %d without specific-slot handler loaded.", keyslot);
+
+ json_object_object_del_by_uint(jobj_keyslots, keyslot);
+
+ r = LUKS2_hdr_write(cd, hdr);
+out:
+ device_write_unlock(cd, crypt_metadata_device(cd));
+ return r;
+}
+
+int LUKS2_keyslot_dump(struct crypt_device *cd, int keyslot)
+{
+ const keyslot_handler *h;
+
+ if (!(h = LUKS2_keyslot_handler(cd, keyslot)))
+ return -EINVAL;
+
+ return h->dump(cd, keyslot);
+}
+
+crypt_keyslot_priority LUKS2_keyslot_priority_get(struct luks2_hdr *hdr, int keyslot)
+{
+ json_object *jobj_keyslot, *jobj_priority;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return CRYPT_SLOT_PRIORITY_INVALID;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "priority", &jobj_priority))
+ return CRYPT_SLOT_PRIORITY_NORMAL;
+
+ return json_object_get_int(jobj_priority);
+}
+
+int LUKS2_keyslot_priority_set(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, crypt_keyslot_priority priority, int commit)
+{
+ json_object *jobj_keyslot;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ if (priority == CRYPT_SLOT_PRIORITY_NORMAL)
+ json_object_object_del(jobj_keyslot, "priority");
+ else
+ json_object_object_add(jobj_keyslot, "priority", json_object_new_int(priority));
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+int placeholder_keyslot_alloc(struct crypt_device *cd,
+ int keyslot,
+ uint64_t area_offset,
+ uint64_t area_length)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj_keyslots, *jobj_keyslot, *jobj_area;
+
+ log_dbg(cd, "Allocating placeholder keyslot %d for LUKS1 down conversion.", keyslot);
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX)
+ return -EINVAL;
+
+ if (LUKS2_get_keyslot_jobj(hdr, keyslot))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ jobj_keyslot = json_object_new_object();
+ json_object_object_add(jobj_keyslot, "type", json_object_new_string("placeholder"));
+ /*
+ * key_size = -1 makes placeholder keyslot impossible to pass validation.
+ * It's a safeguard against accidentally storing temporary conversion
+ * LUKS2 header.
+ */
+ json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(-1));
+
+ /* Area object */
+ jobj_area = json_object_new_object();
+ json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
+ json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
+ json_object_object_add(jobj_keyslot, "area", jobj_area);
+
+ json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
+
+ return 0;
+}
+
+static unsigned LUKS2_get_keyslot_digests_count(json_object *hdr_jobj, int keyslot)
+{
+ char num[16];
+ json_object *jobj_digests, *jobj_keyslots;
+ unsigned count = 0;
+
+ if (!json_object_object_get_ex(hdr_jobj, "digests", &jobj_digests))
+ return 0;
+
+ if (snprintf(num, sizeof(num), "%u", keyslot) < 0)
+ return 0;
+
+ json_object_object_foreach(jobj_digests, key, val) {
+ UNUSED(key);
+ json_object_object_get_ex(val, "keyslots", &jobj_keyslots);
+ if (LUKS2_array_jobj(jobj_keyslots, num))
+ count++;
+ }
+
+ return count;
+}
+
+/* run only on header that passed basic format validation */
+int LUKS2_keyslots_validate(struct crypt_device *cd, json_object *hdr_jobj)
+{
+ const keyslot_handler *h;
+ int keyslot;
+ json_object *jobj_keyslots, *jobj_type;
+ uint32_t reqs, reencrypt_count = 0;
+ struct luks2_hdr dummy = {
+ .jobj = hdr_jobj
+ };
+
+ if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ if (LUKS2_config_get_requirements(cd, &dummy, &reqs))
+ return -EINVAL;
+
+ json_object_object_foreach(jobj_keyslots, slot, val) {
+ keyslot = atoi(slot);
+ json_object_object_get_ex(val, "type", &jobj_type);
+ h = LUKS2_keyslot_handler_type(json_object_get_string(jobj_type));
+ if (!h)
+ continue;
+ if (h->validate && h->validate(cd, val)) {
+ log_dbg(cd, "Keyslot type %s validation failed on keyslot %d.", h->name, keyslot);
+ return -EINVAL;
+ }
+
+ if (!strcmp(h->name, "luks2") && LUKS2_get_keyslot_digests_count(hdr_jobj, keyslot) != 1) {
+ log_dbg(cd, "Keyslot %d is not assigned to exactly 1 digest.", keyslot);
+ return -EINVAL;
+ }
+
+ if (!strcmp(h->name, "reencrypt"))
+ reencrypt_count++;
+ }
+
+ if ((reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT) && reencrypt_count == 0) {
+ log_dbg(cd, "Missing reencryption keyslot.");
+ return -EINVAL;
+ }
+
+ if (reencrypt_count && !LUKS2_reencrypt_requirement_candidate(&dummy)) {
+ log_dbg(cd, "Missing reencryption requirement flag.");
+ return -EINVAL;
+ }
+
+ if (reencrypt_count > 1) {
+ log_dbg(cd, "Too many reencryption keyslots.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void LUKS2_keyslots_repair(struct crypt_device *cd, json_object *jobj_keyslots)
+{
+ const keyslot_handler *h;
+ json_object *jobj_type;
+
+ json_object_object_foreach(jobj_keyslots, slot, val) {
+ UNUSED(slot);
+ if (!json_object_is_type(val, json_type_object) ||
+ !json_object_object_get_ex(val, "type", &jobj_type) ||
+ !json_object_is_type(jobj_type, json_type_string))
+ continue;
+
+ h = LUKS2_keyslot_handler_type(json_object_get_string(jobj_type));
+ if (h && h->repair)
+ h->repair(val);
+ }
+}
+
+/* assumes valid header */
+int LUKS2_find_keyslot(struct luks2_hdr *hdr, const char *type)
+{
+ int i;
+ json_object *jobj_keyslot, *jobj_type;
+
+ if (!type)
+ return -EINVAL;
+
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, i);
+ if (!jobj_keyslot)
+ continue;
+
+ json_object_object_get_ex(jobj_keyslot, "type", &jobj_type);
+ if (!strcmp(json_object_get_string(jobj_type), type))
+ return i;
+ }
+
+ return -ENOENT;
+}
+
+/* assumes valid header, it does not move references in tokens/digests etc! */
+int LUKS2_keyslot_swap(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, int keyslot2)
+{
+ json_object *jobj_keyslots, *jobj_keyslot, *jobj_keyslot2;
+ int r;
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ jobj_keyslot2 = LUKS2_get_keyslot_jobj(hdr, keyslot2);
+ if (!jobj_keyslot2)
+ return -EINVAL;
+
+ /* This transfer owner of object, no need for json_object_put */
+ json_object_get(jobj_keyslot);
+ json_object_get(jobj_keyslot2);
+
+ json_object_object_del_by_uint(jobj_keyslots, keyslot);
+ r = json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot2);
+ if (r < 0) {
+ log_dbg(cd, "Failed to swap keyslot %d.", keyslot);
+ return r;
+ }
+
+ json_object_object_del_by_uint(jobj_keyslots, keyslot2);
+ r = json_object_object_add_by_uint(jobj_keyslots, keyslot2, jobj_keyslot);
+ if (r < 0)
+ log_dbg(cd, "Failed to swap keyslot2 %d.", keyslot2);
+
+ return r;
+}
diff --git a/lib/luks2/luks2_keyslot_luks2.c b/lib/luks2/luks2_keyslot_luks2.c
new file mode 100644
index 0000000..491dcad
--- /dev/null
+++ b/lib/luks2/luks2_keyslot_luks2.c
@@ -0,0 +1,821 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, LUKS2 type keyslot handler
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <limits.h>
+#include "luks2_internal.h"
+
+/* FIXME: move keyslot encryption to crypto backend */
+#include "../luks1/af.h"
+
+#define LUKS_SALTSIZE 32
+#define LUKS_SLOT_ITERATIONS_MIN 1000
+#define LUKS_STRIPES 4000
+
+/* Serialize memory-hard keyslot access: optional workaround for parallel processing */
+#define MIN_MEMORY_FOR_SERIALIZE_LOCK_KB 32*1024 /* 32MB */
+
+/* coverity[ -taint_source : arg-0 ] */
+static int luks2_encrypt_to_storage(char *src, size_t srcLength,
+ const char *cipher, const char *cipher_mode,
+ struct volume_key *vk, unsigned int sector,
+ struct crypt_device *cd)
+{
+#ifndef ENABLE_AF_ALG /* Support for old kernel without Crypto API */
+ return LUKS_encrypt_to_storage(src, srcLength, cipher, cipher_mode, vk, sector, cd);
+#else
+ struct crypt_storage *s;
+ int devfd, r;
+ struct device *device = crypt_metadata_device(cd);
+
+ /* Only whole sector writes supported */
+ if (MISALIGNED_512(srcLength))
+ return -EINVAL;
+
+ /* Encrypt buffer */
+ r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
+ if (r) {
+ log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
+ return r;
+ }
+
+ r = crypt_storage_encrypt(s, 0, srcLength, src);
+ crypt_storage_destroy(s);
+ if (r) {
+ log_err(cd, _("IO error while encrypting keyslot."));
+ return r;
+ }
+
+ devfd = device_open_locked(cd, device, O_RDWR);
+ if (devfd >= 0) {
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), src,
+ srcLength, sector * SECTOR_SIZE) < 0)
+ r = -EIO;
+ else
+ r = 0;
+
+ device_sync(cd, device);
+ } else
+ r = -EIO;
+
+ if (r)
+ log_err(cd, _("IO error while encrypting keyslot."));
+
+ return r;
+#endif
+}
+
+static int luks2_decrypt_from_storage(char *dst, size_t dstLength,
+ const char *cipher, const char *cipher_mode, struct volume_key *vk,
+ unsigned int sector, struct crypt_device *cd)
+{
+ struct device *device = crypt_metadata_device(cd);
+#ifndef ENABLE_AF_ALG /* Support for old kernel without Crypto API */
+ int r = device_read_lock(cd, device);
+ if (r) {
+ log_err(cd, _("Failed to acquire read lock on device %s."), device_path(device));
+ return r;
+ }
+ r = LUKS_decrypt_from_storage(dst, dstLength, cipher, cipher_mode, vk, sector, cd);
+ device_read_unlock(cd, crypt_metadata_device(cd));
+ return r;
+#else
+ struct crypt_storage *s;
+ int devfd, r;
+
+ /* Only whole sector writes supported */
+ if (MISALIGNED_512(dstLength))
+ return -EINVAL;
+
+ r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
+ if (r) {
+ log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
+ return r;
+ }
+
+ r = device_read_lock(cd, device);
+ if (r) {
+ log_err(cd, _("Failed to acquire read lock on device %s."),
+ device_path(device));
+ crypt_storage_destroy(s);
+ return r;
+ }
+
+ devfd = device_open_locked(cd, device, O_RDONLY);
+ if (devfd >= 0) {
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), dst,
+ dstLength, sector * SECTOR_SIZE) < 0)
+ r = -EIO;
+ else
+ r = 0;
+ } else
+ r = -EIO;
+
+ device_read_unlock(cd, device);
+
+ /* Decrypt buffer */
+ if (!r)
+ r = crypt_storage_decrypt(s, 0, dstLength, dst);
+ else
+ log_err(cd, _("IO error while decrypting keyslot."));
+
+ crypt_storage_destroy(s);
+ return r;
+#endif
+}
+
+static int luks2_keyslot_get_pbkdf_params(json_object *jobj_keyslot,
+ struct crypt_pbkdf_type *pbkdf, char **salt)
+{
+ json_object *jobj_kdf, *jobj1, *jobj2;
+ size_t salt_len;
+ int r;
+
+ if (!jobj_keyslot || !pbkdf)
+ return -EINVAL;
+
+ memset(pbkdf, 0, sizeof(*pbkdf));
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_kdf, "type", &jobj1))
+ return -EINVAL;
+ pbkdf->type = json_object_get_string(jobj1);
+ if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
+ if (!json_object_object_get_ex(jobj_kdf, "hash", &jobj2))
+ return -EINVAL;
+ pbkdf->hash = json_object_get_string(jobj2);
+ if (!json_object_object_get_ex(jobj_kdf, "iterations", &jobj2))
+ return -EINVAL;
+ pbkdf->iterations = json_object_get_int(jobj2);
+ pbkdf->max_memory_kb = 0;
+ pbkdf->parallel_threads = 0;
+ } else {
+ if (!json_object_object_get_ex(jobj_kdf, "time", &jobj2))
+ return -EINVAL;
+ pbkdf->iterations = json_object_get_int(jobj2);
+ if (!json_object_object_get_ex(jobj_kdf, "memory", &jobj2))
+ return -EINVAL;
+ pbkdf->max_memory_kb = json_object_get_int(jobj2);
+ if (!json_object_object_get_ex(jobj_kdf, "cpus", &jobj2))
+ return -EINVAL;
+ pbkdf->parallel_threads = json_object_get_int(jobj2);
+ }
+
+ if (!json_object_object_get_ex(jobj_kdf, "salt", &jobj2))
+ return -EINVAL;
+
+ r = crypt_base64_decode(salt, &salt_len, json_object_get_string(jobj2),
+ json_object_get_string_len(jobj2));
+ if (r < 0)
+ return r;
+
+ if (salt_len != LUKS_SALTSIZE) {
+ free(*salt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int luks2_keyslot_set_key(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ const char *password, size_t passwordLen,
+ const char *volume_key, size_t volume_key_len)
+{
+ struct volume_key *derived_key;
+ char *salt = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ char *AfKey = NULL;
+ const char *af_hash = NULL;
+ size_t AFEKSize, keyslot_key_len;
+ json_object *jobj2, *jobj_kdf, *jobj_af, *jobj_area;
+ uint64_t area_offset;
+ struct crypt_pbkdf_type pbkdf;
+ int r;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) ||
+ !json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) ||
+ !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+
+ /* prevent accidental volume key size change after allocation */
+ if (!json_object_object_get_ex(jobj_keyslot, "key_size", &jobj2))
+ return -EINVAL;
+ if (json_object_get_int(jobj2) != (int)volume_key_len)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_area, "offset", &jobj2))
+ return -EINVAL;
+ area_offset = crypt_jobj_get_uint64(jobj2);
+
+ if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2))
+ return -EINVAL;
+ r = crypt_parse_name_and_mode(json_object_get_string(jobj2), cipher, NULL, cipher_mode);
+ if (r < 0)
+ return r;
+
+ if (!json_object_object_get_ex(jobj_area, "key_size", &jobj2))
+ return -EINVAL;
+ keyslot_key_len = json_object_get_int(jobj2);
+
+ if (!json_object_object_get_ex(jobj_af, "hash", &jobj2))
+ return -EINVAL;
+ af_hash = json_object_get_string(jobj2);
+
+ r = luks2_keyslot_get_pbkdf_params(jobj_keyslot, &pbkdf, &salt);
+ if (r < 0)
+ return r;
+
+ /*
+ * Allocate derived key storage.
+ */
+ derived_key = crypt_alloc_volume_key(keyslot_key_len, NULL);
+ if (!derived_key) {
+ free(salt);
+ return -ENOMEM;
+ }
+ /*
+ * Calculate keyslot content, split and store it to keyslot area.
+ */
+ log_dbg(cd, "Running keyslot key derivation.");
+ r = crypt_pbkdf(pbkdf.type, pbkdf.hash, password, passwordLen,
+ salt, LUKS_SALTSIZE,
+ derived_key->key, derived_key->keylength,
+ pbkdf.iterations, pbkdf.max_memory_kb,
+ pbkdf.parallel_threads);
+ free(salt);
+ if (r < 0) {
+ if ((crypt_backend_flags() & CRYPT_BACKEND_PBKDF2_INT) &&
+ pbkdf.iterations > INT_MAX)
+ log_err(cd, _("PBKDF2 iteration value overflow."));
+ crypt_free_volume_key(derived_key);
+ return r;
+ }
+
+ // FIXME: verity key_size to AFEKSize
+ AFEKSize = AF_split_sectors(volume_key_len, LUKS_STRIPES) * SECTOR_SIZE;
+ AfKey = crypt_safe_alloc(AFEKSize);
+ if (!AfKey) {
+ crypt_free_volume_key(derived_key);
+ return -ENOMEM;
+ }
+
+ r = crypt_hash_size(af_hash);
+ if (r < 0)
+ log_err(cd, _("Hash algorithm %s is not available."), af_hash);
+ else
+ r = AF_split(cd, volume_key, AfKey, volume_key_len, LUKS_STRIPES, af_hash);
+
+ if (r == 0) {
+ log_dbg(cd, "Updating keyslot area [0x%04" PRIx64 "].", area_offset);
+ /* FIXME: sector_offset should be size_t, fix LUKS_encrypt... accordingly */
+ r = luks2_encrypt_to_storage(AfKey, AFEKSize, cipher, cipher_mode,
+ derived_key, (unsigned)(area_offset / SECTOR_SIZE), cd);
+ }
+
+ crypt_safe_free(AfKey);
+ crypt_free_volume_key(derived_key);
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+static int luks2_keyslot_get_key(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ const char *password, size_t passwordLen,
+ char *volume_key, size_t volume_key_len)
+{
+ struct volume_key *derived_key = NULL;
+ struct crypt_pbkdf_type pbkdf;
+ char *AfKey = NULL;
+ size_t AFEKSize;
+ const char *af_hash = NULL;
+ char *salt = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ json_object *jobj2, *jobj_af, *jobj_area;
+ uint64_t area_offset;
+ size_t keyslot_key_len;
+ bool try_serialize_lock = false;
+ int r;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) ||
+ !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_af, "hash", &jobj2))
+ return -EINVAL;
+ af_hash = json_object_get_string(jobj2);
+
+ if (!json_object_object_get_ex(jobj_area, "offset", &jobj2))
+ return -EINVAL;
+ area_offset = crypt_jobj_get_uint64(jobj2);
+
+ if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2))
+ return -EINVAL;
+ r = crypt_parse_name_and_mode(json_object_get_string(jobj2), cipher, NULL, cipher_mode);
+ if (r < 0)
+ return r;
+
+ if (!json_object_object_get_ex(jobj_area, "key_size", &jobj2))
+ return -EINVAL;
+ keyslot_key_len = json_object_get_int(jobj2);
+
+ r = luks2_keyslot_get_pbkdf_params(jobj_keyslot, &pbkdf, &salt);
+ if (r < 0)
+ return r;
+
+ /*
+ * Allocate derived key storage space.
+ */
+ derived_key = crypt_alloc_volume_key(keyslot_key_len, NULL);
+ if (!derived_key) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ AFEKSize = AF_split_sectors(volume_key_len, LUKS_STRIPES) * SECTOR_SIZE;
+ AfKey = crypt_safe_alloc(AFEKSize);
+ if (!AfKey) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * If requested, serialize unlocking for memory-hard KDF. Usually NOOP.
+ */
+ if (pbkdf.max_memory_kb > MIN_MEMORY_FOR_SERIALIZE_LOCK_KB)
+ try_serialize_lock = true;
+ if (try_serialize_lock && (r = crypt_serialize_lock(cd)))
+ goto out;
+
+ /*
+ * Calculate derived key, decrypt keyslot content and merge it.
+ */
+ log_dbg(cd, "Running keyslot key derivation.");
+ r = crypt_pbkdf(pbkdf.type, pbkdf.hash, password, passwordLen,
+ salt, LUKS_SALTSIZE,
+ derived_key->key, derived_key->keylength,
+ pbkdf.iterations, pbkdf.max_memory_kb,
+ pbkdf.parallel_threads);
+
+ if (try_serialize_lock)
+ crypt_serialize_unlock(cd);
+
+ if (r == 0) {
+ log_dbg(cd, "Reading keyslot area [0x%04" PRIx64 "].", area_offset);
+ /* FIXME: sector_offset should be size_t, fix LUKS_decrypt... accordingly */
+ r = luks2_decrypt_from_storage(AfKey, AFEKSize, cipher, cipher_mode,
+ derived_key, (unsigned)(area_offset / SECTOR_SIZE), cd);
+ }
+
+ if (r == 0) {
+ r = crypt_hash_size(af_hash);
+ if (r < 0)
+ log_err(cd, _("Hash algorithm %s is not available."), af_hash);
+ else
+ r = AF_merge(AfKey, volume_key, volume_key_len, LUKS_STRIPES, af_hash);
+ }
+out:
+ free(salt);
+ crypt_free_volume_key(derived_key);
+ crypt_safe_free(AfKey);
+
+ return r;
+}
+
+/*
+ * currently we support update of only:
+ *
+ * - af hash function
+ * - kdf params
+ */
+static int luks2_keyslot_update_json(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ const struct luks2_keyslot_params *params)
+{
+ const struct crypt_pbkdf_type *pbkdf;
+ json_object *jobj_af, *jobj_area, *jobj_kdf;
+ char salt[LUKS_SALTSIZE], *salt_base64 = NULL;
+ int r;
+
+ /* jobj_keyslot is not yet validated */
+
+ if (!json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) ||
+ !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+
+ /* update area encryption parameters */
+ json_object_object_add(jobj_area, "encryption", json_object_new_string(params->area.raw.encryption));
+ json_object_object_add(jobj_area, "key_size", json_object_new_int(params->area.raw.key_size));
+
+ pbkdf = crypt_get_pbkdf_type(cd);
+ if (!pbkdf)
+ return -EINVAL;
+
+ r = crypt_benchmark_pbkdf_internal(cd, CONST_CAST(struct crypt_pbkdf_type *)pbkdf, params->area.raw.key_size);
+ if (r < 0)
+ return r;
+
+ /* refresh whole 'kdf' object */
+ jobj_kdf = json_object_new_object();
+ if (!jobj_kdf)
+ return -ENOMEM;
+ json_object_object_add(jobj_kdf, "type", json_object_new_string(pbkdf->type));
+ if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
+ json_object_object_add(jobj_kdf, "hash", json_object_new_string(pbkdf->hash));
+ json_object_object_add(jobj_kdf, "iterations", json_object_new_int(pbkdf->iterations));
+ } else {
+ json_object_object_add(jobj_kdf, "time", json_object_new_int(pbkdf->iterations));
+ json_object_object_add(jobj_kdf, "memory", json_object_new_int(pbkdf->max_memory_kb));
+ json_object_object_add(jobj_kdf, "cpus", json_object_new_int(pbkdf->parallel_threads));
+ }
+ json_object_object_add(jobj_keyslot, "kdf", jobj_kdf);
+
+ /*
+ * Regenerate salt and add it in 'kdf' object
+ */
+ r = crypt_random_get(cd, salt, LUKS_SALTSIZE, CRYPT_RND_SALT);
+ if (r < 0)
+ return r;
+ r = crypt_base64_encode(&salt_base64, NULL, salt, LUKS_SALTSIZE);
+ if (r < 0)
+ return r;
+ json_object_object_add(jobj_kdf, "salt", json_object_new_string(salt_base64));
+ free(salt_base64);
+
+ /* update 'af' hash */
+ json_object_object_add(jobj_af, "hash", json_object_new_string(params->af.luks1.hash));
+
+ JSON_DBG(cd, jobj_keyslot, "Keyslot JSON:");
+ return 0;
+}
+
+static int luks2_keyslot_alloc(struct crypt_device *cd,
+ int keyslot,
+ size_t volume_key_len,
+ const struct luks2_keyslot_params *params)
+{
+ struct luks2_hdr *hdr;
+ uint64_t area_offset, area_length;
+ json_object *jobj_keyslots, *jobj_keyslot, *jobj_af, *jobj_area;
+ int r;
+
+ log_dbg(cd, "Trying to allocate LUKS2 keyslot %d.", keyslot);
+
+ if (!params || params->area_type != LUKS2_KEYSLOT_AREA_RAW ||
+ params->af_type != LUKS2_KEYSLOT_AF_LUKS1) {
+ log_dbg(cd, "Invalid LUKS2 keyslot parameters.");
+ return -EINVAL;
+ }
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ if (keyslot == CRYPT_ANY_SLOT)
+ keyslot = LUKS2_keyslot_find_empty(cd, hdr, 0);
+
+ if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX)
+ return -ENOMEM;
+
+ if (LUKS2_get_keyslot_jobj(hdr, keyslot)) {
+ log_dbg(cd, "Cannot modify already active keyslot %d.", keyslot);
+ return -EINVAL;
+ }
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ r = LUKS2_find_area_gap(cd, hdr, volume_key_len, &area_offset, &area_length);
+ if (r < 0) {
+ log_err(cd, _("No space for new keyslot."));
+ return r;
+ }
+
+ jobj_keyslot = json_object_new_object();
+ json_object_object_add(jobj_keyslot, "type", json_object_new_string("luks2"));
+ json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(volume_key_len));
+
+ /* AF object */
+ jobj_af = json_object_new_object();
+ json_object_object_add(jobj_af, "type", json_object_new_string("luks1"));
+ json_object_object_add(jobj_af, "stripes", json_object_new_int(params->af.luks1.stripes));
+ json_object_object_add(jobj_keyslot, "af", jobj_af);
+
+ /* Area object */
+ jobj_area = json_object_new_object();
+ json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
+ json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
+ json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
+ json_object_object_add(jobj_keyslot, "area", jobj_area);
+
+ json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
+
+ r = luks2_keyslot_update_json(cd, jobj_keyslot, params);
+
+ if (!r && LUKS2_check_json_size(cd, hdr)) {
+ log_dbg(cd, "Not enough space in header json area for new keyslot.");
+ r = -ENOSPC;
+ }
+
+ if (r)
+ json_object_object_del_by_uint(jobj_keyslots, keyslot);
+
+ return r;
+}
+
+static int luks2_keyslot_open(struct crypt_device *cd,
+ int keyslot,
+ const char *password,
+ size_t password_len,
+ char *volume_key,
+ size_t volume_key_len)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj_keyslot;
+
+ log_dbg(cd, "Trying to open LUKS2 keyslot %d.", keyslot);
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ return luks2_keyslot_get_key(cd, jobj_keyslot,
+ password, password_len,
+ volume_key, volume_key_len);
+}
+
+/*
+ * This function must not modify json.
+ * It's called after luks2 keyslot validation.
+ */
+static int luks2_keyslot_store(struct crypt_device *cd,
+ int keyslot,
+ const char *password,
+ size_t password_len,
+ const char *volume_key,
+ size_t volume_key_len)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj_keyslot;
+ int r;
+
+ log_dbg(cd, "Calculating attributes for LUKS2 keyslot %d.", keyslot);
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ r = LUKS2_device_write_lock(cd, hdr, crypt_metadata_device(cd));
+ if(r)
+ return r;
+
+ r = luks2_keyslot_set_key(cd, jobj_keyslot,
+ password, password_len,
+ volume_key, volume_key_len);
+ if (!r)
+ r = LUKS2_hdr_write(cd, hdr);
+
+ device_write_unlock(cd, crypt_metadata_device(cd));
+
+ return r < 0 ? r : keyslot;
+}
+
+static int luks2_keyslot_wipe(struct crypt_device *cd, int keyslot)
+{
+ struct luks2_hdr *hdr;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ /* Remove any reference of deleted keyslot from digests and tokens */
+ LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0);
+ LUKS2_token_assign(cd, hdr, keyslot, CRYPT_ANY_TOKEN, 0, 0);
+
+ return 0;
+}
+
+static int luks2_keyslot_dump(struct crypt_device *cd, int keyslot)
+{
+ json_object *jobj_keyslot, *jobj1, *jobj_kdf, *jobj_af, *jobj_area;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) ||
+ !json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) ||
+ !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_area, "encryption", &jobj1);
+ log_std(cd, "\tCipher: %s\n", json_object_get_string(jobj1));
+
+ json_object_object_get_ex(jobj_area, "key_size", &jobj1);
+ log_std(cd, "\tCipher key: %u bits\n", crypt_jobj_get_uint32(jobj1) * 8);
+
+ json_object_object_get_ex(jobj_kdf, "type", &jobj1);
+ log_std(cd, "\tPBKDF: %s\n", json_object_get_string(jobj1));
+
+ if (!strcmp(json_object_get_string(jobj1), CRYPT_KDF_PBKDF2)) {
+ json_object_object_get_ex(jobj_kdf, "hash", &jobj1);
+ log_std(cd, "\tHash: %s\n", json_object_get_string(jobj1));
+
+ json_object_object_get_ex(jobj_kdf, "iterations", &jobj1);
+ log_std(cd, "\tIterations: %" PRIu64 "\n", crypt_jobj_get_uint64(jobj1));
+ } else {
+ json_object_object_get_ex(jobj_kdf, "time", &jobj1);
+ log_std(cd, "\tTime cost: %" PRIu64 "\n", json_object_get_int64(jobj1));
+
+ json_object_object_get_ex(jobj_kdf, "memory", &jobj1);
+ log_std(cd, "\tMemory: %" PRIu64 "\n", json_object_get_int64(jobj1));
+
+ json_object_object_get_ex(jobj_kdf, "cpus", &jobj1);
+ log_std(cd, "\tThreads: %" PRIu64 "\n", json_object_get_int64(jobj1));
+ }
+ json_object_object_get_ex(jobj_kdf, "salt", &jobj1);
+ log_std(cd, "\tSalt: ");
+ hexprint_base64(cd, jobj1, " ", " ");
+
+
+ json_object_object_get_ex(jobj_af, "stripes", &jobj1);
+ log_std(cd, "\tAF stripes: %u\n", json_object_get_int(jobj1));
+
+ json_object_object_get_ex(jobj_af, "hash", &jobj1);
+ log_std(cd, "\tAF hash: %s\n", json_object_get_string(jobj1));
+
+ json_object_object_get_ex(jobj_area, "offset", &jobj1);
+ log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
+
+ json_object_object_get_ex(jobj_area, "size", &jobj1);
+ log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
+
+ return 0;
+}
+
+static int luks2_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot)
+{
+ json_object *jobj_kdf, *jobj_af, *jobj_area, *jobj1;
+ const char *type;
+ int count;
+
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ if (!(jobj_kdf = json_contains(cd, jobj_keyslot, "", "keyslot", "kdf", json_type_object)) ||
+ !(jobj_af = json_contains(cd, jobj_keyslot, "", "keyslot", "af", json_type_object)) ||
+ !(jobj_area = json_contains(cd, jobj_keyslot, "", "keyslot", "area", json_type_object)))
+ return -EINVAL;
+
+ count = json_object_object_length(jobj_kdf);
+
+ jobj1 = json_contains_string(cd, jobj_kdf, "", "kdf section", "type");
+ if (!jobj1)
+ return -EINVAL;
+ type = json_object_get_string(jobj1);
+
+ if (!strcmp(type, CRYPT_KDF_PBKDF2)) {
+ if (count != 4 || /* type, salt, hash, iterations only */
+ !json_contains_string(cd, jobj_kdf, "kdf type", type, "hash") ||
+ !json_contains(cd, jobj_kdf, "kdf type", type, "iterations", json_type_int) ||
+ !json_contains_string(cd, jobj_kdf, "kdf type", type, "salt"))
+ return -EINVAL;
+ } else if (!strcmp(type, CRYPT_KDF_ARGON2I) || !strcmp(type, CRYPT_KDF_ARGON2ID)) {
+ if (count != 5 || /* type, salt, time, memory, cpus only */
+ !json_contains(cd, jobj_kdf, "kdf type", type, "time", json_type_int) ||
+ !json_contains(cd, jobj_kdf, "kdf type", type, "memory", json_type_int) ||
+ !json_contains(cd, jobj_kdf, "kdf type", type, "cpus", json_type_int) ||
+ !json_contains_string(cd, jobj_kdf, "kdf type", type, "salt"))
+ return -EINVAL;
+ }
+
+ jobj1 = json_contains_string(cd, jobj_af, "", "af section", "type");
+ if (!jobj1)
+ return -EINVAL;
+ type = json_object_get_string(jobj1);
+
+ if (!strcmp(type, "luks1")) {
+ if (!json_contains_string(cd, jobj_af, "", "luks1 af", "hash") ||
+ !json_contains(cd, jobj_af, "", "luks1 af", "stripes", json_type_int))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ // FIXME check numbered
+ jobj1 = json_contains_string(cd, jobj_area, "", "area section", "type");
+ if (!jobj1)
+ return -EINVAL;
+ type = json_object_get_string(jobj1);
+
+ if (!strcmp(type, "raw")) {
+ if (!json_contains_string(cd, jobj_area, "area", "raw type", "encryption") ||
+ !json_contains(cd, jobj_area, "area", "raw type", "key_size", json_type_int) ||
+ !json_contains_string(cd, jobj_area, "area", "raw type", "offset") ||
+ !json_contains_string(cd, jobj_area, "area", "raw type", "size"))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int luks2_keyslot_update(struct crypt_device *cd,
+ int keyslot,
+ const struct luks2_keyslot_params *params)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj_keyslot;
+ int r;
+
+ log_dbg(cd, "Updating LUKS2 keyslot %d.", keyslot);
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ r = luks2_keyslot_update_json(cd, jobj_keyslot, params);
+
+ if (!r && LUKS2_check_json_size(cd, hdr)) {
+ log_dbg(cd, "Not enough space in header json area for updated keyslot %d.", keyslot);
+ r = -ENOSPC;
+ }
+
+ return r;
+}
+
+static void luks2_keyslot_repair(json_object *jobj_keyslot)
+{
+ const char *type;
+ json_object *jobj_kdf, *jobj_type;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) ||
+ !json_object_is_type(jobj_kdf, json_type_object))
+ return;
+
+ if (!json_object_object_get_ex(jobj_kdf, "type", &jobj_type) ||
+ !json_object_is_type(jobj_type, json_type_string))
+ return;
+
+ type = json_object_get_string(jobj_type);
+
+ if (!strcmp(type, CRYPT_KDF_PBKDF2)) {
+ /* type, salt, hash, iterations only */
+ json_object_object_foreach(jobj_kdf, key, val) {
+ UNUSED(val);
+ if (!strcmp(key, "type") || !strcmp(key, "salt") ||
+ !strcmp(key, "hash") || !strcmp(key, "iterations"))
+ continue;
+ json_object_object_del(jobj_kdf, key);
+ }
+ } else if (!strcmp(type, CRYPT_KDF_ARGON2I) || !strcmp(type, CRYPT_KDF_ARGON2ID)) {
+ /* type, salt, time, memory, cpus only */
+ json_object_object_foreach(jobj_kdf, key, val) {
+ UNUSED(val);
+ if (!strcmp(key, "type") || !strcmp(key, "salt") ||
+ !strcmp(key, "time") || !strcmp(key, "memory") ||
+ !strcmp(key, "cpus"))
+ continue;
+ json_object_object_del(jobj_kdf, key);
+ }
+ }
+}
+
+const keyslot_handler luks2_keyslot = {
+ .name = "luks2",
+ .alloc = luks2_keyslot_alloc,
+ .update = luks2_keyslot_update,
+ .open = luks2_keyslot_open,
+ .store = luks2_keyslot_store,
+ .wipe = luks2_keyslot_wipe,
+ .dump = luks2_keyslot_dump,
+ .validate = luks2_keyslot_validate,
+ .repair = luks2_keyslot_repair
+};
diff --git a/lib/luks2/luks2_keyslot_reenc.c b/lib/luks2/luks2_keyslot_reenc.c
new file mode 100644
index 0000000..4291d0c
--- /dev/null
+++ b/lib/luks2/luks2_keyslot_reenc.c
@@ -0,0 +1,752 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, reencryption keyslot handler
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+static int reenc_keyslot_open(struct crypt_device *cd __attribute__((unused)),
+ int keyslot __attribute__((unused)),
+ const char *password __attribute__((unused)),
+ size_t password_len __attribute__((unused)),
+ char *volume_key __attribute__((unused)),
+ size_t volume_key_len __attribute__((unused)))
+{
+ return -ENOENT;
+}
+
+static json_object *reencrypt_keyslot_area_jobj(struct crypt_device *cd,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment,
+ uint64_t area_offset,
+ uint64_t area_length)
+{
+ json_object *jobj_area = json_object_new_object();
+
+ if (!jobj_area || !params || !params->resilience)
+ return NULL;
+
+ json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
+ json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
+ json_object_object_add(jobj_area, "type", json_object_new_string(params->resilience));
+
+ if (!strcmp(params->resilience, "checksum")) {
+ log_dbg(cd, "Setting reencrypt keyslot for checksum protection.");
+ json_object_object_add(jobj_area, "hash", json_object_new_string(params->hash));
+ json_object_object_add(jobj_area, "sector_size", json_object_new_int64(alignment));
+ } else if (!strcmp(params->resilience, "journal")) {
+ log_dbg(cd, "Setting reencrypt keyslot for journal protection.");
+ } else if (!strcmp(params->resilience, "none")) {
+ log_dbg(cd, "Setting reencrypt keyslot for none protection.");
+ } else if (!strcmp(params->resilience, "datashift")) {
+ log_dbg(cd, "Setting reencrypt keyslot for datashift protection.");
+ json_object_object_add(jobj_area, "shift_size",
+ crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT));
+ } else if (!strcmp(params->resilience, "datashift-checksum")) {
+ log_dbg(cd, "Setting reencrypt keyslot for datashift and checksum protection.");
+ json_object_object_add(jobj_area, "hash", json_object_new_string(params->hash));
+ json_object_object_add(jobj_area, "sector_size", json_object_new_int64(alignment));
+ json_object_object_add(jobj_area, "shift_size",
+ crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT));
+ } else if (!strcmp(params->resilience, "datashift-journal")) {
+ log_dbg(cd, "Setting reencrypt keyslot for datashift and journal protection.");
+ json_object_object_add(jobj_area, "shift_size",
+ crypt_jobj_new_uint64(params->data_shift << SECTOR_SHIFT));
+ } else {
+ json_object_put(jobj_area);
+ return NULL;
+ }
+
+ return jobj_area;
+}
+
+static json_object *reencrypt_keyslot_area_jobj_update_block_size(struct crypt_device *cd,
+ json_object *jobj_area, size_t alignment)
+{
+ json_object *jobj_type, *jobj_area_new = NULL;
+
+ if (!jobj_area ||
+ !json_object_object_get_ex(jobj_area, "type", &jobj_type) ||
+ (strcmp(json_object_get_string(jobj_type), "checksum") &&
+ strcmp(json_object_get_string(jobj_type), "datashift-checksum")))
+ return NULL;
+
+ if (json_object_copy(jobj_area, &jobj_area_new))
+ return NULL;
+
+ log_dbg(cd, "Updating reencrypt resilience checksum block size.");
+
+ json_object_object_add(jobj_area_new, "sector_size", json_object_new_int64(alignment));
+
+ return jobj_area_new;
+}
+
+static int reenc_keyslot_alloc(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment)
+{
+ int r;
+ json_object *jobj_keyslots, *jobj_keyslot, *jobj_area;
+ uint64_t area_offset, area_length;
+
+ log_dbg(cd, "Allocating reencrypt keyslot %d.", keyslot);
+
+ if (!params || !params->resilience || params->direction > CRYPT_REENCRYPT_BACKWARD)
+ return -EINVAL;
+
+ if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX)
+ return -ENOMEM;
+
+ if (!json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots))
+ return -EINVAL;
+
+ /* only plain datashift resilience mode does not require additional storage */
+ if (!strcmp(params->resilience, "datashift"))
+ r = LUKS2_find_area_gap(cd, hdr, 1, &area_offset, &area_length);
+ else
+ r = LUKS2_find_area_max_gap(cd, hdr, &area_offset, &area_length);
+ if (r < 0)
+ return r;
+
+ jobj_area = reencrypt_keyslot_area_jobj(cd, params, alignment, area_offset, area_length);
+ if (!jobj_area)
+ return -EINVAL;
+
+ jobj_keyslot = json_object_new_object();
+ if (!jobj_keyslot) {
+ json_object_put(jobj_area);
+ return -ENOMEM;
+ }
+ json_object_object_add(jobj_keyslot, "area", jobj_area);
+
+ json_object_object_add(jobj_keyslot, "type", json_object_new_string("reencrypt"));
+ json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(1)); /* useless but mandatory */
+ json_object_object_add(jobj_keyslot, "mode", json_object_new_string(crypt_reencrypt_mode_to_str(params->mode)));
+ if (params->direction == CRYPT_REENCRYPT_FORWARD)
+ json_object_object_add(jobj_keyslot, "direction", json_object_new_string("forward"));
+ else
+ json_object_object_add(jobj_keyslot, "direction", json_object_new_string("backward"));
+
+ json_object_object_add_by_uint(jobj_keyslots, keyslot, jobj_keyslot);
+ if (LUKS2_check_json_size(cd, hdr)) {
+ log_dbg(cd, "New keyslot too large to fit in free metadata space.");
+ json_object_object_del_by_uint(jobj_keyslots, keyslot);
+ return -ENOSPC;
+ }
+
+ JSON_DBG(cd, hdr->jobj, "JSON:");
+
+ return 0;
+}
+
+static int reenc_keyslot_store_data(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ const void *buffer, size_t buffer_len)
+{
+ int devfd, r;
+ json_object *jobj_area, *jobj_offset, *jobj_length;
+ uint64_t area_offset, area_length;
+ struct device *device = crypt_metadata_device(cd);
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) ||
+ !json_object_object_get_ex(jobj_area, "offset", &jobj_offset) ||
+ !json_object_object_get_ex(jobj_area, "size", &jobj_length))
+ return -EINVAL;
+
+ area_offset = crypt_jobj_get_uint64(jobj_offset);
+ area_length = crypt_jobj_get_uint64(jobj_length);
+
+ if (!area_offset || !area_length || ((uint64_t)buffer_len > area_length))
+ return -EINVAL;
+
+ devfd = device_open_locked(cd, device, O_RDWR);
+ if (devfd >= 0) {
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), CONST_CAST(void *)buffer,
+ buffer_len, area_offset) < 0)
+ r = -EIO;
+ else
+ r = 0;
+ } else
+ r = -EINVAL;
+
+ if (r)
+ log_err(cd, _("IO error while encrypting keyslot."));
+
+ return r;
+}
+
+static int reenc_keyslot_store(struct crypt_device *cd,
+ int keyslot,
+ const char *password __attribute__((unused)),
+ size_t password_len __attribute__((unused)),
+ const char *buffer,
+ size_t buffer_len)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj_keyslot;
+ int r = 0;
+
+ if (!cd || !buffer || !buffer_len)
+ return -EINVAL;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ log_dbg(cd, "Reencrypt keyslot %d store.", keyslot);
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ r = LUKS2_device_write_lock(cd, hdr, crypt_metadata_device(cd));
+ if (r)
+ return r;
+
+ r = reenc_keyslot_store_data(cd, jobj_keyslot, buffer, buffer_len);
+ if (r < 0) {
+ device_write_unlock(cd, crypt_metadata_device(cd));
+ return r;
+ }
+
+ r = LUKS2_hdr_write(cd, hdr);
+
+ device_write_unlock(cd, crypt_metadata_device(cd));
+
+ return r < 0 ? r : keyslot;
+}
+
+static int reenc_keyslot_wipe(struct crypt_device *cd,
+ int keyslot)
+{
+ struct luks2_hdr *hdr;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ /* remove reencryption verification data */
+ LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0);
+
+ return 0;
+}
+
+static int reenc_keyslot_dump(struct crypt_device *cd, int keyslot)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_direction, *jobj_mode, *jobj_resilience,
+ *jobj1;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), keyslot);
+ if (!jobj_keyslot)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "direction", &jobj_direction) ||
+ !json_object_object_get_ex(jobj_keyslot, "mode", &jobj_mode) ||
+ !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) ||
+ !json_object_object_get_ex(jobj_area, "type", &jobj_resilience))
+ return -EINVAL;
+
+ log_std(cd, "\t%-12s%s\n", "Mode:", json_object_get_string(jobj_mode));
+ log_std(cd, "\t%-12s%s\n", "Direction:", json_object_get_string(jobj_direction));
+ log_std(cd, "\t%-12s%s\n", "Resilience:", json_object_get_string(jobj_resilience));
+
+ if (!strcmp(json_object_get_string(jobj_resilience), "checksum")) {
+ json_object_object_get_ex(jobj_area, "hash", &jobj1);
+ log_std(cd, "\t%-12s%s\n", "Hash:", json_object_get_string(jobj1));
+ json_object_object_get_ex(jobj_area, "sector_size", &jobj1);
+ log_std(cd, "\t%-12s%d [bytes]\n", "Hash data:", json_object_get_int(jobj1));
+ } else if (!strcmp(json_object_get_string(jobj_resilience), "datashift")) {
+ json_object_object_get_ex(jobj_area, "shift_size", &jobj1);
+ log_std(cd, "\t%-12s%" PRIu64 "[bytes]\n", "Shift size:", crypt_jobj_get_uint64(jobj1));
+ }
+
+ json_object_object_get_ex(jobj_area, "offset", &jobj1);
+ log_std(cd, "\tArea offset:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
+
+ json_object_object_get_ex(jobj_area, "size", &jobj1);
+ log_std(cd, "\tArea length:%" PRIu64 " [bytes]\n", crypt_jobj_get_uint64(jobj1));
+
+ return 0;
+}
+
+static int reenc_keyslot_validate(struct crypt_device *cd, json_object *jobj_keyslot)
+{
+ json_object *jobj_mode, *jobj_area, *jobj_type, *jobj_shift_size, *jobj_hash,
+ *jobj_sector_size, *jobj_direction, *jobj_key_size;
+ const char *mode, *type, *direction;
+ uint32_t sector_size;
+ uint64_t shift_size;
+
+ /* mode (string: encrypt,reencrypt,decrypt)
+ * direction (string:)
+ * area {
+ * type: (string: datashift, journal, checksum, none, datashift-journal, datashift-checksum)
+ * hash: (string: checksum and datashift-checksum types)
+ * sector_size (uint32: checksum and datashift-checksum types)
+ * shift_size (uint64: all datashift based types)
+ * }
+ */
+
+ /* area and area type are validated in general validation code */
+ if (!jobj_keyslot || !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) ||
+ !json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return -EINVAL;
+
+ jobj_key_size = json_contains(cd, jobj_keyslot, "", "reencrypt keyslot", "key_size", json_type_int);
+ jobj_mode = json_contains_string(cd, jobj_keyslot, "", "reencrypt keyslot", "mode");
+ jobj_direction = json_contains_string(cd, jobj_keyslot, "", "reencrypt keyslot", "direction");
+
+ if (!jobj_mode || !jobj_direction || !jobj_key_size)
+ return -EINVAL;
+
+ if (!validate_json_uint32(jobj_key_size) || crypt_jobj_get_uint32(jobj_key_size) != 1) {
+ log_dbg(cd, "Illegal reencrypt key size.");
+ return -EINVAL;
+ }
+
+ mode = json_object_get_string(jobj_mode);
+ type = json_object_get_string(jobj_type);
+ direction = json_object_get_string(jobj_direction);
+
+ if (strcmp(mode, "reencrypt") && strcmp(mode, "encrypt") &&
+ strcmp(mode, "decrypt")) {
+ log_dbg(cd, "Illegal reencrypt mode %s.", mode);
+ return -EINVAL;
+ }
+
+ if (strcmp(direction, "forward") && strcmp(direction, "backward")) {
+ log_dbg(cd, "Illegal reencrypt direction %s.", direction);
+ return -EINVAL;
+ }
+
+ if (!strcmp(type, "checksum") || !strcmp(type, "datashift-checksum")) {
+ jobj_hash = json_contains_string(cd, jobj_area, "type:checksum",
+ "Keyslot area", "hash");
+ jobj_sector_size = json_contains(cd, jobj_area, "type:checksum",
+ "Keyslot area", "sector_size", json_type_int);
+ if (!jobj_hash || !jobj_sector_size)
+ return -EINVAL;
+ if (!validate_json_uint32(jobj_sector_size))
+ return -EINVAL;
+ sector_size = crypt_jobj_get_uint32(jobj_sector_size);
+ if (sector_size < SECTOR_SIZE || NOTPOW2(sector_size)) {
+ log_dbg(cd, "Invalid sector_size (%" PRIu32 ") for checksum resilience mode.",
+ sector_size);
+ return -EINVAL;
+ }
+ } else if (!strcmp(type, "datashift") ||
+ !strcmp(type, "datashift-checksum") ||
+ !strcmp(type, "datashift-journal")) {
+ if (!(jobj_shift_size = json_contains_string(cd, jobj_area, "type:datashift",
+ "Keyslot area", "shift_size")))
+ return -EINVAL;
+
+ shift_size = crypt_jobj_get_uint64(jobj_shift_size);
+ if (!shift_size)
+ return -EINVAL;
+
+ if (MISALIGNED_512(shift_size)) {
+ log_dbg(cd, "Shift size field has to be aligned to 512 bytes.");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int reenc_keyslot_update_needed(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment)
+{
+ const char *type;
+ json_object *jobj_area, *jobj_type, *jobj;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) ||
+ !json_object_object_get_ex(jobj_area, "type", &jobj_type) ||
+ !(type = json_object_get_string(jobj_type)))
+ return -EINVAL;
+
+ /*
+ * If no resilience mode change is requested and effective
+ * resilience mode is 'checksum' then check alignment matches
+ * stored checksum block size.
+ */
+ if (!params || !params->resilience) {
+ if (!strcmp(json_object_get_string(jobj_type), "checksum") ||
+ !strcmp(json_object_get_string(jobj_type), "datashift-checksum"))
+ return (json_object_object_get_ex(jobj_area, "sector_size", &jobj) ||
+ alignment != crypt_jobj_get_uint32(jobj));
+ return 0;
+ }
+
+ if (strcmp(params->resilience, type))
+ return 1;
+
+ if (!strcmp(type, "checksum") ||
+ !strcmp(type, "datashift-checksum")) {
+ if (!params->hash)
+ return -EINVAL;
+ if (!json_object_object_get_ex(jobj_area, "hash", &jobj) ||
+ strcmp(json_object_get_string(jobj), params->hash) ||
+ !json_object_object_get_ex(jobj_area, "sector_size", &jobj) ||
+ crypt_jobj_get_uint32(jobj) != alignment)
+ return 1;
+ }
+
+ if (!strncmp(type, "datashift", 9)) {
+ if (!json_object_object_get_ex(jobj_area, "shift_size", &jobj))
+ return -EINVAL;
+ if ((params->data_shift << SECTOR_SHIFT) != crypt_jobj_get_uint64(jobj))
+ return 1;
+ }
+
+ /* nothing to compare with 'none' and 'journal' */
+ return 0;
+}
+
+static int load_checksum_protection(struct crypt_device *cd,
+ json_object *jobj_area,
+ uint64_t area_length,
+ struct reenc_protection *rp)
+{
+ int r;
+ json_object *jobj_hash, *jobj_block_size;
+
+ if (!jobj_area || !rp ||
+ !json_object_object_get_ex(jobj_area, "hash", &jobj_hash) ||
+ !json_object_object_get_ex(jobj_area, "sector_size", &jobj_block_size))
+ return -EINVAL;
+
+ r = snprintf(rp->p.csum.hash, sizeof(rp->p.csum.hash), "%s", json_object_get_string(jobj_hash));
+ if (r < 0 || (size_t)r >= sizeof(rp->p.csum.hash))
+ return -EINVAL;
+
+ if (crypt_hash_init(&rp->p.csum.ch, rp->p.csum.hash)) {
+ log_err(cd, _("Hash algorithm %s is not available."), rp->p.csum.hash);
+ return -EINVAL;
+ }
+
+ r = crypt_hash_size(rp->p.csum.hash);
+ if (r <= 0) {
+ crypt_hash_destroy(rp->p.csum.ch);
+ rp->p.csum.ch = NULL;
+ log_dbg(cd, "Invalid hash size");
+ return -EINVAL;
+ }
+
+ rp->p.csum.hash_size = r;
+ rp->p.csum.block_size = crypt_jobj_get_uint32(jobj_block_size);
+ rp->p.csum.checksums_len = area_length;
+
+ rp->type = REENC_PROTECTION_CHECKSUM;
+ return 0;
+}
+
+static int reenc_keyslot_load_resilience_primary(struct crypt_device *cd,
+ const char *type,
+ json_object *jobj_area,
+ uint64_t area_length,
+ struct reenc_protection *rp)
+{
+ json_object *jobj;
+
+ if (!strcmp(type, "checksum")) {
+ log_dbg(cd, "Initializing checksum resilience mode.");
+ return load_checksum_protection(cd, jobj_area, area_length, rp);
+ } else if (!strcmp(type, "journal")) {
+ log_dbg(cd, "Initializing journal resilience mode.");
+ rp->type = REENC_PROTECTION_JOURNAL;
+ } else if (!strcmp(type, "none")) {
+ log_dbg(cd, "Initializing none resilience mode.");
+ rp->type = REENC_PROTECTION_NONE;
+ } else if (!strcmp(type, "datashift") ||
+ !strcmp(type, "datashift-checksum") ||
+ !strcmp(type, "datashift-journal")) {
+ log_dbg(cd, "Initializing datashift resilience mode.");
+ if (!json_object_object_get_ex(jobj_area, "shift_size", &jobj))
+ return -EINVAL;
+ rp->type = REENC_PROTECTION_DATASHIFT;
+ rp->p.ds.data_shift = crypt_jobj_get_uint64(jobj);
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int reenc_keyslot_load_resilience_secondary(struct crypt_device *cd,
+ const char *type,
+ json_object *jobj_area,
+ uint64_t area_length,
+ struct reenc_protection *rp)
+{
+ if (!strcmp(type, "datashift-checksum")) {
+ log_dbg(cd, "Initializing checksum resilience mode.");
+ return load_checksum_protection(cd, jobj_area, area_length, rp);
+ } else if (!strcmp(type, "datashift-journal")) {
+ log_dbg(cd, "Initializing journal resilience mode.");
+ rp->type = REENC_PROTECTION_JOURNAL;
+ } else
+ rp->type = REENC_PROTECTION_NOT_SET;
+
+ return 0;
+}
+
+static int reenc_keyslot_load_resilience(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ struct reenc_protection *rp,
+ bool primary)
+{
+ const char *type;
+ int r;
+ json_object *jobj_area, *jobj_type;
+ uint64_t dummy, area_length;
+
+ if (!rp || !json_object_object_get_ex(jobj_keyslot, "area", &jobj_area) ||
+ !json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return -EINVAL;
+
+ r = LUKS2_keyslot_jobj_area(jobj_keyslot, &dummy, &area_length);
+ if (r < 0)
+ return r;
+
+ type = json_object_get_string(jobj_type);
+ if (!type)
+ return -EINVAL;
+
+ if (primary)
+ return reenc_keyslot_load_resilience_primary(cd, type, jobj_area, area_length, rp);
+ else
+ return reenc_keyslot_load_resilience_secondary(cd, type, jobj_area, area_length, rp);
+}
+
+static bool reenc_keyslot_update_is_valid(struct crypt_device *cd,
+ json_object *jobj_area,
+ const struct crypt_params_reencrypt *params)
+{
+ const char *type;
+ json_object *jobj_type, *jobj;
+
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type) ||
+ !(type = json_object_get_string(jobj_type)))
+ return false;
+
+ /* do not allow switch to/away from datashift resilience type */
+ if ((strcmp(params->resilience, "datashift") && !strcmp(type, "datashift")) ||
+ (!strcmp(params->resilience, "datashift") && strcmp(type, "datashift")))
+ return false;
+
+ /* do not allow switch to/away from datashift- resilience subvariants */
+ if ((strncmp(params->resilience, "datashift-", 10) &&
+ !strncmp(type, "datashift-", 10)) ||
+ (!strncmp(params->resilience, "datashift-", 10) &&
+ strncmp(type, "datashift-", 10)))
+ return false;
+
+ /* datashift value is also immutable */
+ if (!strncmp(type, "datashift", 9)) {
+ if (!json_object_object_get_ex(jobj_area, "shift_size", &jobj))
+ return false;
+ return (params->data_shift << SECTOR_SHIFT) == crypt_jobj_get_uint64(jobj);
+ }
+
+ return true;
+}
+
+static int reenc_keyslot_update(struct crypt_device *cd,
+ json_object *jobj_keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment)
+{
+ int r;
+ json_object *jobj_area, *jobj_area_new;
+ uint64_t area_offset, area_length;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+
+ r = LUKS2_keyslot_jobj_area(jobj_keyslot, &area_offset, &area_length);
+ if (r < 0)
+ return r;
+
+ if (!params || !params->resilience)
+ jobj_area_new = reencrypt_keyslot_area_jobj_update_block_size(cd, jobj_area, alignment);
+ else {
+ if (!reenc_keyslot_update_is_valid(cd, jobj_area, params)) {
+ log_err(cd, _("Invalid reencryption resilience mode change requested."));
+ return -EINVAL;
+ }
+
+ jobj_area_new = reencrypt_keyslot_area_jobj(cd, params, alignment,
+ area_offset, area_length);
+ }
+
+ if (!jobj_area_new)
+ return -EINVAL;
+
+ /* increase refcount for validation purposes */
+ json_object_get(jobj_area);
+
+ json_object_object_add(jobj_keyslot, "area", jobj_area_new);
+
+ r = reenc_keyslot_validate(cd, jobj_keyslot);
+ if (r) {
+ /* replace invalid object with previous valid one */
+ json_object_object_add(jobj_keyslot, "area", jobj_area);
+ return -EINVAL;
+ }
+
+ /* previous area object is no longer needed */
+ json_object_put(jobj_area);
+
+ return 0;
+}
+
+int LUKS2_keyslot_reencrypt_allocate(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment)
+{
+ int r;
+
+ if (keyslot == CRYPT_ANY_SLOT)
+ return -EINVAL;
+
+ r = reenc_keyslot_alloc(cd, hdr, keyslot, params, alignment);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_keyslot_priority_set(cd, hdr, keyslot, CRYPT_SLOT_PRIORITY_IGNORE, 0);
+ if (r < 0)
+ return r;
+
+ r = reenc_keyslot_validate(cd, LUKS2_get_keyslot_jobj(hdr, keyslot));
+ if (r) {
+ log_dbg(cd, "Keyslot validation failed.");
+ return r;
+ }
+
+ return 0;
+}
+
+int LUKS2_keyslot_reencrypt_update_needed(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment)
+{
+ int r;
+ json_object *jobj_type, *jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+
+ if (!jobj_keyslot ||
+ !json_object_object_get_ex(jobj_keyslot, "type", &jobj_type) ||
+ strcmp(json_object_get_string(jobj_type), "reencrypt"))
+ return -EINVAL;
+
+ r = reenc_keyslot_update_needed(cd, jobj_keyslot, params, alignment);
+ if (!r)
+ log_dbg(cd, "No update of reencrypt keyslot needed.");
+
+ return r;
+}
+
+int LUKS2_keyslot_reencrypt_update(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const struct crypt_params_reencrypt *params,
+ size_t alignment,
+ struct volume_key *vks)
+{
+ int r;
+ uint8_t version;
+ uint64_t max_size, moved_segment_size;
+ json_object *jobj_type, *jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ struct reenc_protection check_rp = {};
+
+ if (!jobj_keyslot ||
+ !json_object_object_get_ex(jobj_keyslot, "type", &jobj_type) ||
+ strcmp(json_object_get_string(jobj_type), "reencrypt"))
+ return -EINVAL;
+
+ if (LUKS2_config_get_reencrypt_version(hdr, &version))
+ return -EINVAL;
+
+ /* verify existing reencryption metadata before updating */
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ if (r < 0)
+ return r;
+
+ r = reenc_keyslot_update(cd, jobj_keyslot, params, alignment);
+ if (r < 0)
+ return r;
+
+ r = reenc_keyslot_load_resilience(cd, jobj_keyslot, &check_rp, false);
+ if (r < 0)
+ return r;
+
+ if (check_rp.type != REENC_PROTECTION_NOT_SET) {
+ r = LUKS2_reencrypt_max_hotzone_size(cd, hdr, &check_rp, keyslot, &max_size);
+ LUKS2_reencrypt_protection_erase(&check_rp);
+ if (r < 0)
+ return r;
+ moved_segment_size = json_segment_get_size(LUKS2_get_segment_by_flag(hdr, "backup-moved-segment"), 0);
+ if (!moved_segment_size)
+ return -EINVAL;
+ if (moved_segment_size > max_size) {
+ log_err(cd, _("Can not update resilience type. "
+ "New type only provides %" PRIu64 " bytes, "
+ "required space is: %" PRIu64 " bytes."),
+ max_size, moved_segment_size);
+ return -EINVAL;
+ }
+ }
+
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, version, vks);
+ if (r < 0)
+ log_err(cd, _("Failed to refresh reencryption verification digest."));
+
+ return r ?: LUKS2_hdr_write(cd, hdr);
+}
+
+int LUKS2_keyslot_reencrypt_load(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ struct reenc_protection *rp,
+ bool primary)
+{
+ json_object *jobj_type, *jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+
+ if (!jobj_keyslot ||
+ !json_object_object_get_ex(jobj_keyslot, "type", &jobj_type) ||
+ strcmp(json_object_get_string(jobj_type), "reencrypt"))
+ return -EINVAL;
+
+ return reenc_keyslot_load_resilience(cd, jobj_keyslot, rp, primary);
+}
+
+const keyslot_handler reenc_keyslot = {
+ .name = "reencrypt",
+ .open = reenc_keyslot_open,
+ .store = reenc_keyslot_store, /* initialization only or also per every chunk write */
+ .wipe = reenc_keyslot_wipe,
+ .dump = reenc_keyslot_dump,
+ .validate = reenc_keyslot_validate
+};
diff --git a/lib/luks2/luks2_luks1_convert.c b/lib/luks2/luks2_luks1_convert.c
new file mode 100644
index 0000000..6d3fa1e
--- /dev/null
+++ b/lib/luks2/luks2_luks1_convert.c
@@ -0,0 +1,945 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, LUKS1 conversion code
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Ondrej Kozina
+ * Copyright (C) 2015-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+#include "../luks1/luks.h"
+#include "../luks1/af.h"
+
+/* This differs from LUKS_check_cipher() that it does not check dm-crypt fallback. */
+int LUKS2_check_cipher(struct crypt_device *cd,
+ size_t keylength,
+ const char *cipher,
+ const char *cipher_mode)
+{
+ int r;
+ struct crypt_storage *s;
+ char buf[SECTOR_SIZE], *empty_key;
+
+ log_dbg(cd, "Checking if cipher %s-%s is usable (storage wrapper).", cipher, cipher_mode);
+
+ empty_key = crypt_safe_alloc(keylength);
+ if (!empty_key)
+ return -ENOMEM;
+
+ /* No need to get KEY quality random but it must avoid known weak keys. */
+ r = crypt_random_get(cd, empty_key, keylength, CRYPT_RND_NORMAL);
+ if (r < 0)
+ goto out;
+
+ r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, empty_key, keylength, false);
+ if (r < 0)
+ goto out;
+
+ memset(buf, 0, sizeof(buf));
+ r = crypt_storage_decrypt(s, 0, sizeof(buf), buf);
+ crypt_storage_destroy(s);
+out:
+ crypt_safe_free(empty_key);
+ crypt_safe_memzero(buf, sizeof(buf));
+ return r;
+}
+
+static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struct json_object **keyslot_object)
+{
+ char *base64_str, cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L];
+ size_t base64_len;
+ struct json_object *keyslot_obj, *field, *jobj_kdf, *jobj_af, *jobj_area;
+ uint64_t offset, area_size, length;
+ int r;
+
+ keyslot_obj = json_object_new_object();
+ json_object_object_add(keyslot_obj, "type", json_object_new_string("luks2"));
+ json_object_object_add(keyslot_obj, "key_size", json_object_new_int64(hdr_v1->keyBytes));
+
+ /* KDF */
+ jobj_kdf = json_object_new_object();
+ json_object_object_add(jobj_kdf, "type", json_object_new_string(CRYPT_KDF_PBKDF2));
+ json_object_object_add(jobj_kdf, "hash", json_object_new_string(hdr_v1->hashSpec));
+ json_object_object_add(jobj_kdf, "iterations", json_object_new_int64(hdr_v1->keyblock[keyslot].passwordIterations));
+ /* salt field */
+ r = crypt_base64_encode(&base64_str, &base64_len, hdr_v1->keyblock[keyslot].passwordSalt, LUKS_SALTSIZE);
+ if (r < 0) {
+ json_object_put(keyslot_obj);
+ json_object_put(jobj_kdf);
+ return r;
+ }
+ field = json_object_new_string_len(base64_str, base64_len);
+ free(base64_str);
+ json_object_object_add(jobj_kdf, "salt", field);
+ json_object_object_add(keyslot_obj, "kdf", jobj_kdf);
+
+ /* AF */
+ jobj_af = json_object_new_object();
+ json_object_object_add(jobj_af, "type", json_object_new_string("luks1"));
+ json_object_object_add(jobj_af, "hash", json_object_new_string(hdr_v1->hashSpec));
+ /* stripes field ignored, fixed to LUKS_STRIPES (4000) */
+ json_object_object_add(jobj_af, "stripes", json_object_new_int(LUKS_STRIPES));
+ json_object_object_add(keyslot_obj, "af", jobj_af);
+
+ /* Area */
+ jobj_area = json_object_new_object();
+ json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
+
+ /* encryption algorithm field */
+ if (*hdr_v1->cipherMode != '\0') {
+ if (snprintf(cipher, sizeof(cipher), "%s-%s", hdr_v1->cipherName, hdr_v1->cipherMode) < 0) {
+ json_object_put(keyslot_obj);
+ json_object_put(jobj_area);
+ return -EINVAL;
+ }
+ json_object_object_add(jobj_area, "encryption", json_object_new_string(cipher));
+ } else
+ json_object_object_add(jobj_area, "encryption", json_object_new_string(hdr_v1->cipherName));
+
+ /* area */
+ if (LUKS_keyslot_area(hdr_v1, keyslot, &offset, &length)) {
+ json_object_put(keyslot_obj);
+ json_object_put(jobj_area);
+ return -EINVAL;
+ }
+ area_size = size_round_up(length, 4096);
+ json_object_object_add(jobj_area, "key_size", json_object_new_int(hdr_v1->keyBytes));
+ json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(offset));
+ json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_size));
+ json_object_object_add(keyslot_obj, "area", jobj_area);
+
+ *keyslot_object = keyslot_obj;
+ return 0;
+}
+
+static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_object **keyslots_object)
+{
+ int keyslot, r;
+ struct json_object *keyslot_obj, *field;
+
+ keyslot_obj = json_object_new_object();
+ if (!keyslot_obj)
+ return -ENOMEM;
+
+ for (keyslot = 0; keyslot < LUKS_NUMKEYS; keyslot++) {
+ if (hdr_v1->keyblock[keyslot].active != LUKS_KEY_ENABLED)
+ continue;
+ r = json_luks1_keyslot(hdr_v1, keyslot, &field);
+ if (r) {
+ json_object_put(keyslot_obj);
+ return r;
+ }
+ json_object_object_add_by_uint(keyslot_obj, keyslot, field);
+ }
+
+ *keyslots_object = keyslot_obj;
+ return 0;
+}
+
+static int json_luks1_segment(const struct luks_phdr *hdr_v1, struct json_object **segment_object)
+{
+ const char *c;
+ char cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L];
+ struct json_object *segment_obj, *field;
+ uint64_t number;
+
+ segment_obj = json_object_new_object();
+ if (!segment_obj)
+ return -ENOMEM;
+
+ /* type field */
+ field = json_object_new_string("crypt");
+ if (!field) {
+ json_object_put(segment_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(segment_obj, "type", field);
+
+ /* offset field */
+ number = (uint64_t)hdr_v1->payloadOffset * SECTOR_SIZE;
+
+ field = crypt_jobj_new_uint64(number);
+ if (!field) {
+ json_object_put(segment_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(segment_obj, "offset", field);
+
+ /* iv_tweak field */
+ field = json_object_new_string("0");
+ if (!field) {
+ json_object_put(segment_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(segment_obj, "iv_tweak", field);
+
+ /* length field */
+ field = json_object_new_string("dynamic");
+ if (!field) {
+ json_object_put(segment_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(segment_obj, "size", field);
+
+ /* cipher field */
+ if (*hdr_v1->cipherMode != '\0') {
+ if (snprintf(cipher, sizeof(cipher), "%s-%s", hdr_v1->cipherName, hdr_v1->cipherMode) < 0) {
+ json_object_put(segment_obj);
+ return -EINVAL;
+ }
+ c = cipher;
+ } else
+ c = hdr_v1->cipherName;
+
+ field = json_object_new_string(c);
+ if (!field) {
+ json_object_put(segment_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(segment_obj, "encryption", field);
+
+ /* block field */
+ field = json_object_new_int(SECTOR_SIZE);
+ if (!field) {
+ json_object_put(segment_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(segment_obj, "sector_size", field);
+
+ *segment_object = segment_obj;
+ return 0;
+}
+
+static int json_luks1_segments(const struct luks_phdr *hdr_v1, struct json_object **segments_object)
+{
+ int r;
+ struct json_object *segments_obj, *field;
+
+ segments_obj = json_object_new_object();
+ if (!segments_obj)
+ return -ENOMEM;
+
+ r = json_luks1_segment(hdr_v1, &field);
+ if (r) {
+ json_object_put(segments_obj);
+ return r;
+ }
+ json_object_object_add_by_uint(segments_obj, 0, field);
+
+ *segments_object = segments_obj;
+ return 0;
+}
+
+static int json_luks1_digest(const struct luks_phdr *hdr_v1, struct json_object **digest_object)
+{
+ char keyslot_str[16], *base64_str;
+ int r, ks;
+ size_t base64_len;
+ struct json_object *digest_obj, *array, *field;
+
+ digest_obj = json_object_new_object();
+ if (!digest_obj)
+ return -ENOMEM;
+
+ /* type field */
+ field = json_object_new_string("pbkdf2");
+ if (!field) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "type", field);
+
+ /* keyslots array */
+ array = json_object_new_array();
+ if (!array) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "keyslots", json_object_get(array));
+
+ for (ks = 0; ks < LUKS_NUMKEYS; ks++) {
+ if (hdr_v1->keyblock[ks].active != LUKS_KEY_ENABLED)
+ continue;
+ if (snprintf(keyslot_str, sizeof(keyslot_str), "%d", ks) < 0) {
+ json_object_put(field);
+ json_object_put(array);
+ json_object_put(digest_obj);
+ return -EINVAL;
+ }
+
+ field = json_object_new_string(keyslot_str);
+ if (!field || json_object_array_add(array, field) < 0) {
+ json_object_put(field);
+ json_object_put(array);
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ }
+
+ json_object_put(array);
+
+ /* segments array */
+ array = json_object_new_array();
+ if (!array) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "segments", json_object_get(array));
+
+ field = json_object_new_string("0");
+ if (!field || json_object_array_add(array, field) < 0) {
+ json_object_put(field);
+ json_object_put(array);
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+
+ json_object_put(array);
+
+ /* hash field */
+ field = json_object_new_string(hdr_v1->hashSpec);
+ if (!field) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "hash", field);
+
+ /* salt field */
+ r = crypt_base64_encode(&base64_str, &base64_len, hdr_v1->mkDigestSalt, LUKS_SALTSIZE);
+ if (r < 0) {
+ json_object_put(digest_obj);
+ return r;
+ }
+
+ field = json_object_new_string_len(base64_str, base64_len);
+ free(base64_str);
+ if (!field) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "salt", field);
+
+ /* digest field */
+ r = crypt_base64_encode(&base64_str, &base64_len, hdr_v1->mkDigest, LUKS_DIGESTSIZE);
+ if (r < 0) {
+ json_object_put(digest_obj);
+ return r;
+ }
+
+ field = json_object_new_string_len(base64_str, base64_len);
+ free(base64_str);
+ if (!field) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "digest", field);
+
+ /* iterations field */
+ field = json_object_new_int64(hdr_v1->mkDigestIterations);
+ if (!field) {
+ json_object_put(digest_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(digest_obj, "iterations", field);
+
+ *digest_object = digest_obj;
+ return 0;
+}
+
+static int json_luks1_digests(const struct luks_phdr *hdr_v1, struct json_object **digests_object)
+{
+ int r;
+ struct json_object *digests_obj, *field;
+
+ digests_obj = json_object_new_object();
+ if (!digests_obj)
+ return -ENOMEM;
+
+ r = json_luks1_digest(hdr_v1, &field);
+ if (r) {
+ json_object_put(digests_obj);
+ return r;
+ }
+ json_object_object_add(digests_obj, "0", field);
+
+ *digests_object = digests_obj;
+ return 0;
+}
+
+static int json_luks1_object(struct luks_phdr *hdr_v1, struct json_object **luks1_object, uint64_t keyslots_size)
+{
+ int r;
+ struct json_object *luks1_obj, *field;
+ uint64_t json_size;
+
+ luks1_obj = json_object_new_object();
+ if (!luks1_obj)
+ return -ENOMEM;
+
+ /* keyslots field */
+ r = json_luks1_keyslots(hdr_v1, &field);
+ if (r) {
+ json_object_put(luks1_obj);
+ return r;
+ }
+ json_object_object_add(luks1_obj, "keyslots", field);
+
+ /* tokens field */
+ field = json_object_new_object();
+ if (!field) {
+ json_object_put(luks1_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(luks1_obj, "tokens", field);
+
+ /* segments field */
+ r = json_luks1_segments(hdr_v1, &field);
+ if (r) {
+ json_object_put(luks1_obj);
+ return r;
+ }
+ json_object_object_add(luks1_obj, "segments", field);
+
+ /* digests field */
+ r = json_luks1_digests(hdr_v1, &field);
+ if (r) {
+ json_object_put(luks1_obj);
+ return r;
+ }
+ json_object_object_add(luks1_obj, "digests", field);
+
+ /* config field */
+ /* anything else? */
+ field = json_object_new_object();
+ if (!field) {
+ json_object_put(luks1_obj);
+ return -ENOMEM;
+ }
+ json_object_object_add(luks1_obj, "config", field);
+
+ json_size = LUKS2_HDR_16K_LEN - LUKS2_HDR_BIN_LEN;
+ json_object_object_add(field, "json_size", crypt_jobj_new_uint64(json_size));
+ keyslots_size -= (keyslots_size % 4096);
+ json_object_object_add(field, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
+
+ *luks1_object = luks1_obj;
+ return 0;
+}
+
+static void move_keyslot_offset(json_object *jobj, int offset_add)
+{
+ json_object *jobj1, *jobj2, *jobj_area;
+ uint64_t offset = 0;
+
+ json_object_object_get_ex(jobj, "keyslots", &jobj1);
+ json_object_object_foreach(jobj1, key, val) {
+ UNUSED(key);
+ json_object_object_get_ex(val, "area", &jobj_area);
+ json_object_object_get_ex(jobj_area, "offset", &jobj2);
+ offset = crypt_jobj_get_uint64(jobj2) + offset_add;
+ json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(offset));
+ }
+}
+
+static int move_keyslot_areas(struct crypt_device *cd, off_t offset_from,
+ off_t offset_to, size_t buf_size)
+{
+ int devfd, r = -EIO;
+ struct device *device = crypt_metadata_device(cd);
+ void *buf = NULL;
+
+ log_dbg(cd, "Moving keyslot areas of size %zu from %jd to %jd.",
+ buf_size, (intmax_t)offset_from, (intmax_t)offset_to);
+
+ if (posix_memalign(&buf, crypt_getpagesize(), buf_size))
+ return -ENOMEM;
+
+ devfd = device_open(cd, device, O_RDWR);
+ if (devfd < 0) {
+ free(buf);
+ return -EIO;
+ }
+
+ /* This can safely fail (for block devices). It only allocates space if it is possible. */
+ if (posix_fallocate(devfd, offset_to, buf_size))
+ log_dbg(cd, "Preallocation (fallocate) of new keyslot area not available.");
+
+ /* Try to read *new* area to check that area is there (trimmed backup). */
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), buf, buf_size,
+ offset_to)!= (ssize_t)buf_size)
+ goto out;
+
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), buf, buf_size,
+ offset_from)!= (ssize_t)buf_size)
+ goto out;
+
+ if (write_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), buf, buf_size,
+ offset_to) != (ssize_t)buf_size)
+ goto out;
+
+ r = 0;
+out:
+ device_sync(cd, device);
+ crypt_safe_memzero(buf, buf_size);
+ free(buf);
+
+ return r;
+}
+
+static int luks_header_in_use(struct crypt_device *cd)
+{
+ int r;
+
+ r = lookup_dm_dev_by_uuid(cd, crypt_get_uuid(cd), crypt_get_type(cd));
+ if (r < 0)
+ log_err(cd, _("Cannot check status of device with uuid: %s."), crypt_get_uuid(cd));
+
+ return r;
+}
+
+/* Check if there is a luksmeta area (foreign metadata created by the luksmeta package) */
+static int luksmeta_header_present(struct crypt_device *cd, off_t luks1_size)
+{
+ int devfd, r = 0;
+ static const uint8_t LM_MAGIC[] = { 'L', 'U', 'K', 'S', 'M', 'E', 'T', 'A' };
+ struct device *device = crypt_metadata_device(cd);
+ void *buf = NULL;
+
+ if (posix_memalign(&buf, crypt_getpagesize(), sizeof(LM_MAGIC)))
+ return -ENOMEM;
+
+ devfd = device_open(cd, device, O_RDONLY);
+ if (devfd < 0) {
+ free(buf);
+ return -EIO;
+ }
+
+ /* Note: we must not detect failure as problem here, header can be trimmed. */
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device), device_alignment(device),
+ buf, sizeof(LM_MAGIC), luks1_size) == (ssize_t)sizeof(LM_MAGIC) &&
+ !memcmp(LM_MAGIC, buf, sizeof(LM_MAGIC))) {
+ log_err(cd, _("Unable to convert header with LUKSMETA additional metadata."));
+ r = -EBUSY;
+ }
+
+ free(buf);
+ return r;
+}
+
+/* Convert LUKS1 -> LUKS2 */
+int LUKS2_luks1_to_luks2(struct crypt_device *cd, struct luks_phdr *hdr1, struct luks2_hdr *hdr2)
+{
+ int r;
+ json_object *jobj = NULL;
+ size_t buf_size, buf_offset, luks1_size, luks1_shift = 2 * LUKS2_HDR_16K_LEN - LUKS_ALIGN_KEYSLOTS;
+ uint64_t required_size, max_size = crypt_get_data_offset(cd) * SECTOR_SIZE;
+
+ /* for detached headers max size == device size */
+ if (!max_size && (r = device_size(crypt_metadata_device(cd), &max_size)))
+ return r;
+
+ luks1_size = LUKS_device_sectors(hdr1) << SECTOR_SHIFT;
+ luks1_size = size_round_up(luks1_size, LUKS_ALIGN_KEYSLOTS);
+ if (!luks1_size)
+ return -EINVAL;
+
+ if (LUKS_keyslots_offset(hdr1) != (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
+ log_dbg(cd, "Unsupported keyslots material offset: %zu.", LUKS_keyslots_offset(hdr1));
+ return -EINVAL;
+ }
+
+ if (LUKS2_check_cipher(cd, hdr1->keyBytes, hdr1->cipherName, hdr1->cipherMode)) {
+ log_err(cd, _("Unable to use cipher specification %s-%s for LUKS2."),
+ hdr1->cipherName, hdr1->cipherMode);
+ return -EINVAL;
+ }
+
+ if (luksmeta_header_present(cd, luks1_size))
+ return -EINVAL;
+
+ log_dbg(cd, "Max size: %" PRIu64 ", LUKS1 (full) header size %zu , required shift: %zu",
+ max_size, luks1_size, luks1_shift);
+
+ required_size = luks1_size + luks1_shift;
+
+ if ((max_size < required_size) &&
+ device_fallocate(crypt_metadata_device(cd), required_size)) {
+ log_err(cd, _("Unable to move keyslot area. Not enough space."));
+ return -EINVAL;
+ }
+
+ if (max_size < required_size)
+ max_size = required_size;
+
+ r = json_luks1_object(hdr1, &jobj, max_size - 2 * LUKS2_HDR_16K_LEN);
+ if (r < 0)
+ return r;
+
+ move_keyslot_offset(jobj, luks1_shift);
+
+ /* Create and fill LUKS2 hdr */
+ memset(hdr2, 0, sizeof(*hdr2));
+ hdr2->hdr_size = LUKS2_HDR_16K_LEN;
+ hdr2->seqid = 1;
+ hdr2->version = 2;
+ strncpy(hdr2->checksum_alg, "sha256", LUKS2_CHECKSUM_ALG_L);
+ crypt_random_get(cd, (char*)hdr2->salt1, sizeof(hdr2->salt1), CRYPT_RND_SALT);
+ crypt_random_get(cd, (char*)hdr2->salt2, sizeof(hdr2->salt2), CRYPT_RND_SALT);
+ strncpy(hdr2->uuid, crypt_get_uuid(cd), LUKS2_UUID_L-1); /* UUID should be max 36 chars */
+ hdr2->jobj = jobj;
+
+ /*
+ * It duplicates check in LUKS2_hdr_write() but we don't want to move
+ * keyslot areas in case it would fail later
+ */
+ if (max_size < LUKS2_hdr_and_areas_size(hdr2)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* check future LUKS2 metadata before moving keyslots area */
+ if (LUKS2_hdr_validate(cd, hdr2->jobj, hdr2->hdr_size - LUKS2_HDR_BIN_LEN)) {
+ log_err(cd, _("Cannot convert to LUKS2 format - invalid metadata."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if ((r = luks_header_in_use(cd))) {
+ if (r > 0)
+ r = -EBUSY;
+ goto out;
+ }
+
+ /* move keyslots 4k -> 32k offset */
+ buf_offset = 2 * LUKS2_HDR_16K_LEN;
+ buf_size = luks1_size - LUKS_ALIGN_KEYSLOTS;
+
+ /* check future LUKS2 keyslots area is at least as large as LUKS1 keyslots area */
+ if (buf_size > LUKS2_keyslots_size(hdr2)) {
+ log_err(cd, _("Unable to move keyslot area. LUKS2 keyslots area too small."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if ((r = move_keyslot_areas(cd, 8 * SECTOR_SIZE, buf_offset, buf_size)) < 0) {
+ log_err(cd, _("Unable to move keyslot area."));
+ goto out;
+ }
+
+ /* Write new LUKS2 JSON */
+ r = LUKS2_hdr_write(cd, hdr2);
+out:
+ LUKS2_hdr_free(cd, hdr2);
+
+ return r;
+}
+
+static int keyslot_LUKS1_compatible(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, uint32_t key_size, const char *hash)
+{
+ json_object *jobj_keyslot, *jobj, *jobj_kdf, *jobj_af;
+ uint64_t l2_offset, l2_length;
+ size_t ks_key_size;
+ const char *ks_cipher, *data_cipher;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
+ if (!jobj_keyslot)
+ return 1;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "type", &jobj) ||
+ strcmp(json_object_get_string(jobj), "luks2"))
+ return 0;
+
+ /* Using PBKDF2, this implies memory and parallel is not used. */
+ jobj = NULL;
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf) ||
+ !json_object_object_get_ex(jobj_kdf, "type", &jobj) ||
+ strcmp(json_object_get_string(jobj), CRYPT_KDF_PBKDF2) ||
+ !json_object_object_get_ex(jobj_kdf, "hash", &jobj) ||
+ strcmp(json_object_get_string(jobj), hash))
+ return 0;
+
+ jobj = NULL;
+ if (!json_object_object_get_ex(jobj_keyslot, "af", &jobj_af) ||
+ !json_object_object_get_ex(jobj_af, "stripes", &jobj) ||
+ json_object_get_int(jobj) != LUKS_STRIPES)
+ return 0;
+
+ jobj = NULL;
+ if (!json_object_object_get_ex(jobj_af, "hash", &jobj) ||
+ (crypt_hash_size(json_object_get_string(jobj)) < 0) ||
+ strcmp(json_object_get_string(jobj), hash))
+ return 0;
+
+ ks_cipher = LUKS2_get_keyslot_cipher(hdr, keyslot, &ks_key_size);
+ data_cipher = LUKS2_get_cipher(hdr, CRYPT_DEFAULT_SEGMENT);
+ if (!ks_cipher || !data_cipher || key_size != ks_key_size || strcmp(ks_cipher, data_cipher)) {
+ log_dbg(cd, "Cipher in keyslot %d is different from volume key encryption.", keyslot);
+ return 0;
+ }
+
+ if (LUKS2_keyslot_area(hdr, keyslot, &l2_offset, &l2_length))
+ return 0;
+
+ if (l2_length != (size_round_up(AF_split_sectors(key_size, LUKS_STRIPES) * SECTOR_SIZE, 4096))) {
+ log_dbg(cd, "Area length in LUKS2 keyslot (%d) is not compatible with LUKS1", keyslot);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Convert LUKS2 -> LUKS1 */
+int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct luks_phdr *hdr1)
+{
+ size_t buf_size, buf_offset;
+ char cipher[LUKS_CIPHERNAME_L], cipher_mode[LUKS_CIPHERMODE_L];
+ char *digest, *digest_salt;
+ const char *hash;
+ size_t len;
+ json_object *jobj_keyslot, *jobj_digest, *jobj_segment, *jobj_kdf, *jobj_area, *jobj1, *jobj2;
+ uint32_t key_size;
+ int i, r, last_active = 0;
+ uint64_t offset, area_length;
+ char *buf, luksMagic[] = LUKS_MAGIC;
+
+ jobj_digest = LUKS2_get_digest_jobj(hdr2, 0);
+ if (!jobj_digest)
+ return -EINVAL;
+
+ jobj_segment = LUKS2_get_segment_jobj(hdr2, CRYPT_DEFAULT_SEGMENT);
+ if (!jobj_segment)
+ return -EINVAL;
+
+ if (json_segment_get_sector_size(jobj_segment) != SECTOR_SIZE) {
+ log_err(cd, _("Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."));
+ return -EINVAL;
+ }
+
+ json_object_object_get_ex(hdr2->jobj, "digests", &jobj1);
+ if (!json_object_object_get_ex(jobj_digest, "type", &jobj2) ||
+ strcmp(json_object_get_string(jobj2), "pbkdf2") ||
+ json_object_object_length(jobj1) != 1) {
+ log_err(cd, _("Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."));
+ return -EINVAL;
+ }
+ if (!json_object_object_get_ex(jobj_digest, "hash", &jobj2))
+ return -EINVAL;
+ hash = json_object_get_string(jobj2);
+
+ r = crypt_parse_name_and_mode(LUKS2_get_cipher(hdr2, CRYPT_DEFAULT_SEGMENT), cipher, NULL, cipher_mode);
+ if (r < 0)
+ return r;
+
+ if (crypt_cipher_wrapped_key(cipher, cipher_mode)) {
+ log_err(cd, _("Cannot convert to LUKS1 format - device uses wrapped key cipher %s."), cipher);
+ return -EINVAL;
+ }
+
+ if (json_segments_count(LUKS2_get_segments_jobj(hdr2)) != 1) {
+ log_err(cd, _("Cannot convert to LUKS1 format - device uses more segments."));
+ return -EINVAL;
+ }
+
+ r = LUKS2_tokens_count(hdr2);
+ if (r < 0)
+ return r;
+ if (r > 0) {
+ log_err(cd, _("Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."), r);
+ return -EINVAL;
+ }
+
+ r = LUKS2_get_volume_key_size(hdr2, 0);
+ if (r < 0)
+ return -EINVAL;
+ key_size = r;
+
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
+ if (LUKS2_keyslot_info(hdr2, i) == CRYPT_SLOT_INACTIVE)
+ continue;
+
+ if (LUKS2_keyslot_info(hdr2, i) == CRYPT_SLOT_INVALID) {
+ log_err(cd, _("Cannot convert to LUKS1 format - keyslot %u is in invalid state."), i);
+ return -EINVAL;
+ }
+
+ if (i >= LUKS_NUMKEYS) {
+ log_err(cd, _("Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."), i);
+ return -EINVAL;
+ }
+
+ if (!keyslot_LUKS1_compatible(cd, hdr2, i, key_size, hash)) {
+ log_err(cd, _("Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."), i);
+ return -EINVAL;
+ }
+ }
+
+ memset(hdr1, 0, sizeof(*hdr1));
+
+ for (i = 0; i < LUKS_NUMKEYS; i++) {
+ hdr1->keyblock[i].active = LUKS_KEY_DISABLED;
+ hdr1->keyblock[i].stripes = LUKS_STRIPES;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr2, i);
+
+ if (jobj_keyslot) {
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+ if (!json_object_object_get_ex(jobj_area, "offset", &jobj1))
+ return -EINVAL;
+ offset = crypt_jobj_get_uint64(jobj1);
+ } else {
+ if (LUKS2_find_area_gap(cd, hdr2, key_size, &offset, &area_length))
+ return -EINVAL;
+ /*
+ * We have to create placeholder luks2 keyslots in place of all
+ * inactive keyslots. Otherwise we would allocate all
+ * inactive luks1 keyslots over same binary keyslot area.
+ */
+ if (placeholder_keyslot_alloc(cd, i, offset, area_length))
+ return -EINVAL;
+ }
+
+ offset /= SECTOR_SIZE;
+ if (offset > UINT32_MAX)
+ return -EINVAL;
+
+ hdr1->keyblock[i].keyMaterialOffset = offset;
+ hdr1->keyblock[i].keyMaterialOffset -=
+ ((2 * LUKS2_HDR_16K_LEN - LUKS_ALIGN_KEYSLOTS) / SECTOR_SIZE);
+
+ if (!jobj_keyslot)
+ continue;
+
+ hdr1->keyblock[i].active = LUKS_KEY_ENABLED;
+ last_active = i;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf))
+ continue;
+
+ if (!json_object_object_get_ex(jobj_kdf, "iterations", &jobj1))
+ continue;
+ hdr1->keyblock[i].passwordIterations = crypt_jobj_get_uint32(jobj1);
+
+ if (!json_object_object_get_ex(jobj_kdf, "salt", &jobj1))
+ continue;
+
+ if (crypt_base64_decode(&buf, &len, json_object_get_string(jobj1),
+ json_object_get_string_len(jobj1)))
+ continue;
+ if (len > 0 && len != LUKS_SALTSIZE) {
+ free(buf);
+ continue;
+ }
+ memcpy(hdr1->keyblock[i].passwordSalt, buf, LUKS_SALTSIZE);
+ free(buf);
+ }
+
+ if (!jobj_keyslot) {
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr2, last_active);
+ if (!jobj_keyslot)
+ return -EINVAL;
+ }
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return -EINVAL;
+ if (!json_object_object_get_ex(jobj_area, "encryption", &jobj1))
+ return -EINVAL;
+ r = crypt_parse_name_and_mode(json_object_get_string(jobj1), cipher, NULL, cipher_mode);
+ if (r < 0)
+ return r;
+
+ strncpy(hdr1->cipherName, cipher, LUKS_CIPHERNAME_L - 1);
+ hdr1->cipherName[LUKS_CIPHERNAME_L-1] = '\0';
+ strncpy(hdr1->cipherMode, cipher_mode, LUKS_CIPHERMODE_L - 1);
+ hdr1->cipherMode[LUKS_CIPHERMODE_L-1] = '\0';
+
+ if (!json_object_object_get_ex(jobj_keyslot, "kdf", &jobj_kdf))
+ return -EINVAL;
+ if (!json_object_object_get_ex(jobj_kdf, "hash", &jobj1))
+ return -EINVAL;
+ strncpy(hdr1->hashSpec, json_object_get_string(jobj1), sizeof(hdr1->hashSpec) - 1);
+
+ hdr1->keyBytes = key_size;
+
+ if (!json_object_object_get_ex(jobj_digest, "iterations", &jobj1))
+ return -EINVAL;
+ hdr1->mkDigestIterations = crypt_jobj_get_uint32(jobj1);
+
+ if (!json_object_object_get_ex(jobj_digest, "digest", &jobj1))
+ return -EINVAL;
+ r = crypt_base64_decode(&digest, &len, json_object_get_string(jobj1),
+ json_object_get_string_len(jobj1));
+ if (r < 0)
+ return r;
+ /* We can store full digest here, not only sha1 length */
+ if (len < LUKS_DIGESTSIZE) {
+ free(digest);
+ return -EINVAL;
+ }
+ memcpy(hdr1->mkDigest, digest, LUKS_DIGESTSIZE);
+ free(digest);
+
+ if (!json_object_object_get_ex(jobj_digest, "salt", &jobj1))
+ return -EINVAL;
+ r = crypt_base64_decode(&digest_salt, &len, json_object_get_string(jobj1),
+ json_object_get_string_len(jobj1));
+ if (r < 0)
+ return r;
+ if (len != LUKS_SALTSIZE) {
+ free(digest_salt);
+ return -EINVAL;
+ }
+ memcpy(hdr1->mkDigestSalt, digest_salt, LUKS_SALTSIZE);
+ free(digest_salt);
+
+ if (!json_object_object_get_ex(jobj_segment, "offset", &jobj1))
+ return -EINVAL;
+ offset = crypt_jobj_get_uint64(jobj1) / SECTOR_SIZE;
+ if (offset > UINT32_MAX)
+ return -EINVAL;
+ hdr1->payloadOffset = offset;
+
+ strncpy(hdr1->uuid, hdr2->uuid, UUID_STRING_L); /* max 36 chars */
+ hdr1->uuid[UUID_STRING_L-1] = '\0';
+
+ memcpy(hdr1->magic, luksMagic, LUKS_MAGIC_L);
+
+ hdr1->version = 1;
+
+ r = luks_header_in_use(cd);
+ if (r)
+ return r > 0 ? -EBUSY : r;
+
+ /* move keyslots 32k -> 4k offset */
+ buf_offset = 2 * LUKS2_HDR_16K_LEN;
+ buf_size = LUKS2_keyslots_size(hdr2);
+ r = move_keyslot_areas(cd, buf_offset, 8 * SECTOR_SIZE, buf_size);
+ if (r < 0) {
+ log_err(cd, _("Unable to move keyslot area."));
+ return r;
+ }
+
+ crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0,
+ 8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL);
+
+ /* Write new LUKS1 hdr */
+ return LUKS_write_phdr(hdr1, cd);
+}
diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c
new file mode 100644
index 0000000..b0dcd6d
--- /dev/null
+++ b/lib/luks2/luks2_reencrypt.c
@@ -0,0 +1,4375 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, reencryption helpers
+ *
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+#include "utils_device_locking.h"
+
+struct luks2_reencrypt {
+ /* reencryption window attributes */
+ uint64_t offset;
+ uint64_t progress;
+ uint64_t length;
+ uint64_t device_size;
+ bool online;
+ bool fixed_length;
+ crypt_reencrypt_direction_info direction;
+ crypt_reencrypt_mode_info mode;
+
+ char *device_name;
+ char *hotzone_name;
+ char *overlay_name;
+ uint32_t flags;
+
+ /* reencryption window persistence attributes */
+ struct reenc_protection rp;
+ struct reenc_protection rp_moved_segment;
+
+ int reenc_keyslot;
+
+ /* already running reencryption */
+ json_object *jobj_segs_hot;
+ struct json_object *jobj_segs_post;
+
+ /* backup segments */
+ json_object *jobj_segment_new;
+ int digest_new;
+ json_object *jobj_segment_old;
+ int digest_old;
+ json_object *jobj_segment_moved;
+
+ struct volume_key *vks;
+
+ void *reenc_buffer;
+ ssize_t read;
+
+ struct crypt_storage_wrapper *cw1;
+ struct crypt_storage_wrapper *cw2;
+
+ uint32_t wflags1;
+ uint32_t wflags2;
+
+ struct crypt_lock_handle *reenc_lock;
+};
+#if USE_LUKS2_REENCRYPTION
+static uint64_t data_shift_value(struct reenc_protection *rp)
+{
+ return rp->type == REENC_PROTECTION_DATASHIFT ? rp->p.ds.data_shift : 0;
+}
+
+static json_object *reencrypt_segment(struct luks2_hdr *hdr, unsigned new)
+{
+ return LUKS2_get_segment_by_flag(hdr, new ? "backup-final" : "backup-previous");
+}
+
+static json_object *reencrypt_segment_new(struct luks2_hdr *hdr)
+{
+ return reencrypt_segment(hdr, 1);
+}
+
+static json_object *reencrypt_segment_old(struct luks2_hdr *hdr)
+{
+ return reencrypt_segment(hdr, 0);
+}
+
+static json_object *reencrypt_segments_old(struct luks2_hdr *hdr)
+{
+ json_object *jobj_segments, *jobj = NULL;
+
+ if (json_object_copy(reencrypt_segment_old(hdr), &jobj))
+ return NULL;
+
+ json_segment_remove_flag(jobj, "backup-previous");
+
+ jobj_segments = json_object_new_object();
+ if (!jobj_segments) {
+ json_object_put(jobj);
+ return NULL;
+ }
+
+ if (json_object_object_add_by_uint(jobj_segments, 0, jobj)) {
+ json_object_put(jobj);
+ json_object_put(jobj_segments);
+ return NULL;
+ }
+
+ return jobj_segments;
+}
+
+static const char *reencrypt_segment_cipher_new(struct luks2_hdr *hdr)
+{
+ return json_segment_get_cipher(reencrypt_segment(hdr, 1));
+}
+
+static const char *reencrypt_segment_cipher_old(struct luks2_hdr *hdr)
+{
+ return json_segment_get_cipher(reencrypt_segment(hdr, 0));
+}
+
+static uint32_t reencrypt_get_sector_size_new(struct luks2_hdr *hdr)
+{
+ return json_segment_get_sector_size(reencrypt_segment(hdr, 1));
+}
+
+static uint32_t reencrypt_get_sector_size_old(struct luks2_hdr *hdr)
+{
+ return json_segment_get_sector_size(reencrypt_segment(hdr, 0));
+}
+
+static uint64_t reencrypt_data_offset(struct luks2_hdr *hdr, unsigned new)
+{
+ json_object *jobj = reencrypt_segment(hdr, new);
+ if (jobj)
+ return json_segment_get_offset(jobj, 0);
+
+ return LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
+}
+
+static uint64_t LUKS2_reencrypt_get_data_offset_moved(struct luks2_hdr *hdr)
+{
+ json_object *jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
+
+ if (!jobj_segment)
+ return 0;
+
+ return json_segment_get_offset(jobj_segment, 0);
+}
+
+static uint64_t reencrypt_get_data_offset_new(struct luks2_hdr *hdr)
+{
+ return reencrypt_data_offset(hdr, 1);
+}
+
+static uint64_t reencrypt_get_data_offset_old(struct luks2_hdr *hdr)
+{
+ return reencrypt_data_offset(hdr, 0);
+}
+#endif
+static int reencrypt_digest(struct luks2_hdr *hdr, unsigned new)
+{
+ int segment = LUKS2_get_segment_id_by_flag(hdr, new ? "backup-final" : "backup-previous");
+
+ if (segment < 0)
+ return segment;
+
+ return LUKS2_digest_by_segment(hdr, segment);
+}
+
+int LUKS2_reencrypt_digest_new(struct luks2_hdr *hdr)
+{
+ return reencrypt_digest(hdr, 1);
+}
+
+int LUKS2_reencrypt_digest_old(struct luks2_hdr *hdr)
+{
+ return reencrypt_digest(hdr, 0);
+}
+
+/* none, checksums, journal or shift */
+static const char *reencrypt_resilience_type(struct luks2_hdr *hdr)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_type;
+ int ks = LUKS2_find_keyslot(hdr, "reencrypt");
+
+ if (ks < 0)
+ return NULL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks);
+
+ json_object_object_get_ex(jobj_keyslot, "area", &jobj_area);
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return NULL;
+
+ return json_object_get_string(jobj_type);
+}
+
+static const char *reencrypt_resilience_hash(struct luks2_hdr *hdr)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_type, *jobj_hash;
+ int ks = LUKS2_find_keyslot(hdr, "reencrypt");
+
+ if (ks < 0)
+ return NULL;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks);
+
+ json_object_object_get_ex(jobj_keyslot, "area", &jobj_area);
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return NULL;
+ if (strcmp(json_object_get_string(jobj_type), "checksum"))
+ return NULL;
+ if (!json_object_object_get_ex(jobj_area, "hash", &jobj_hash))
+ return NULL;
+
+ return json_object_get_string(jobj_hash);
+}
+#if USE_LUKS2_REENCRYPTION
+static json_object *_enc_create_segments_shift_after(struct luks2_reencrypt *rh, uint64_t data_offset)
+{
+ int reenc_seg, i = 0;
+ json_object *jobj_copy, *jobj_seg_new = NULL, *jobj_segs_post = json_object_new_object();
+ uint64_t tmp;
+
+ if (!rh->jobj_segs_hot || !jobj_segs_post)
+ goto err;
+
+ if (json_segments_count(rh->jobj_segs_hot) == 0)
+ return jobj_segs_post;
+
+ reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
+ if (reenc_seg < 0)
+ goto err;
+
+ while (i < reenc_seg) {
+ jobj_copy = json_segments_get_segment(rh->jobj_segs_hot, i);
+ if (!jobj_copy)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_post, i++, json_object_get(jobj_copy));
+ }
+
+ if (json_object_copy(json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1), &jobj_seg_new)) {
+ if (json_object_copy(json_segments_get_segment(rh->jobj_segs_hot, reenc_seg), &jobj_seg_new))
+ goto err;
+ json_segment_remove_flag(jobj_seg_new, "in-reencryption");
+ tmp = rh->length;
+ } else {
+ json_object_object_add(jobj_seg_new, "offset", crypt_jobj_new_uint64(rh->offset + data_offset));
+ json_object_object_add(jobj_seg_new, "iv_tweak", crypt_jobj_new_uint64(rh->offset >> SECTOR_SHIFT));
+ tmp = json_segment_get_size(jobj_seg_new, 0) + rh->length;
+ }
+
+ /* alter size of new segment, reenc_seg == 0 we're finished */
+ json_object_object_add(jobj_seg_new, "size", reenc_seg > 0 ? crypt_jobj_new_uint64(tmp) : json_object_new_string("dynamic"));
+ json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_seg_new);
+
+ return jobj_segs_post;
+err:
+ json_object_put(jobj_segs_post);
+ return NULL;
+}
+
+static json_object *reencrypt_make_hot_segments_encrypt_shift(struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t data_offset)
+{
+ int sg, crypt_seg, i = 0;
+ uint64_t segment_size;
+ json_object *jobj_seg_shrunk, *jobj_seg_new, *jobj_copy, *jobj_enc_seg = NULL,
+ *jobj_segs_hot = json_object_new_object();
+
+ if (!jobj_segs_hot)
+ return NULL;
+
+ crypt_seg = LUKS2_segment_by_type(hdr, "crypt");
+
+ /* FIXME: This is hack. Find proper way to fix it. */
+ sg = LUKS2_last_segment_by_type(hdr, "linear");
+ if (rh->offset && sg < 0)
+ goto err;
+ if (sg < 0)
+ return jobj_segs_hot;
+
+ jobj_enc_seg = json_segment_create_crypt(data_offset + rh->offset,
+ rh->offset >> SECTOR_SHIFT,
+ &rh->length,
+ reencrypt_segment_cipher_new(hdr),
+ reencrypt_get_sector_size_new(hdr),
+ 1);
+
+ while (i < sg) {
+ jobj_copy = LUKS2_get_segment_jobj(hdr, i);
+ if (!jobj_copy)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, i++, json_object_get(jobj_copy));
+ }
+
+ segment_size = LUKS2_segment_size(hdr, sg, 0);
+ if (segment_size > rh->length) {
+ jobj_seg_shrunk = NULL;
+ if (json_object_copy(LUKS2_get_segment_jobj(hdr, sg), &jobj_seg_shrunk))
+ goto err;
+ json_object_object_add(jobj_seg_shrunk, "size", crypt_jobj_new_uint64(segment_size - rh->length));
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_seg_shrunk);
+ }
+
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_enc_seg);
+ jobj_enc_seg = NULL; /* see err: label */
+
+ /* first crypt segment after encryption ? */
+ if (crypt_seg >= 0) {
+ jobj_seg_new = LUKS2_get_segment_jobj(hdr, crypt_seg);
+ if (!jobj_seg_new)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg, json_object_get(jobj_seg_new));
+ }
+
+ return jobj_segs_hot;
+err:
+ json_object_put(jobj_enc_seg);
+ json_object_put(jobj_segs_hot);
+
+ return NULL;
+}
+
+static json_object *reencrypt_make_segment_new(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct luks2_reencrypt *rh,
+ uint64_t data_offset,
+ uint64_t segment_offset,
+ uint64_t iv_offset,
+ const uint64_t *segment_length)
+{
+ switch (rh->mode) {
+ case CRYPT_REENCRYPT_REENCRYPT:
+ case CRYPT_REENCRYPT_ENCRYPT:
+ return json_segment_create_crypt(data_offset + segment_offset,
+ crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT),
+ segment_length,
+ reencrypt_segment_cipher_new(hdr),
+ reencrypt_get_sector_size_new(hdr), 0);
+ case CRYPT_REENCRYPT_DECRYPT:
+ return json_segment_create_linear(data_offset + segment_offset, segment_length, 0);
+ }
+
+ return NULL;
+}
+
+static json_object *reencrypt_make_post_segments_forward(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t data_offset)
+{
+ int reenc_seg;
+ json_object *jobj_new_seg_after, *jobj_old_seg, *jobj_old_seg_copy = NULL,
+ *jobj_segs_post = json_object_new_object();
+ uint64_t fixed_length = rh->offset + rh->length;
+
+ if (!rh->jobj_segs_hot || !jobj_segs_post)
+ goto err;
+
+ reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
+ if (reenc_seg < 0)
+ return NULL;
+
+ jobj_old_seg = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1);
+
+ /*
+ * if there's no old segment after reencryption, we're done.
+ * Set size to 'dynamic' again.
+ */
+ jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, jobj_old_seg ? &fixed_length : NULL);
+ if (!jobj_new_seg_after)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_post, 0, jobj_new_seg_after);
+
+ if (jobj_old_seg) {
+ if (rh->fixed_length) {
+ if (json_object_copy(jobj_old_seg, &jobj_old_seg_copy))
+ goto err;
+ jobj_old_seg = jobj_old_seg_copy;
+ fixed_length = rh->device_size - fixed_length;
+ json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(fixed_length));
+ } else
+ json_object_get(jobj_old_seg);
+ json_object_object_add_by_uint(jobj_segs_post, 1, jobj_old_seg);
+ }
+
+ return jobj_segs_post;
+err:
+ json_object_put(jobj_segs_post);
+ return NULL;
+}
+
+static json_object *reencrypt_make_post_segments_backward(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t data_offset)
+{
+ int reenc_seg;
+ uint64_t fixed_length;
+
+ json_object *jobj_new_seg_after, *jobj_old_seg,
+ *jobj_segs_post = json_object_new_object();
+
+ if (!rh->jobj_segs_hot || !jobj_segs_post)
+ goto err;
+
+ reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
+ if (reenc_seg < 0)
+ return NULL;
+
+ jobj_old_seg = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg - 1);
+ if (jobj_old_seg)
+ json_object_object_add_by_uint(jobj_segs_post, reenc_seg - 1, json_object_get(jobj_old_seg));
+ if (rh->fixed_length && rh->offset) {
+ fixed_length = rh->device_size - rh->offset;
+ jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset, rh->offset, &fixed_length);
+ } else
+ jobj_new_seg_after = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset, rh->offset, NULL);
+ if (!jobj_new_seg_after)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_post, reenc_seg, jobj_new_seg_after);
+
+ return jobj_segs_post;
+err:
+ json_object_put(jobj_segs_post);
+ return NULL;
+}
+
+static json_object *reencrypt_make_segment_reencrypt(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct luks2_reencrypt *rh,
+ uint64_t data_offset,
+ uint64_t segment_offset,
+ uint64_t iv_offset,
+ const uint64_t *segment_length)
+{
+ switch (rh->mode) {
+ case CRYPT_REENCRYPT_REENCRYPT:
+ case CRYPT_REENCRYPT_ENCRYPT:
+ return json_segment_create_crypt(data_offset + segment_offset,
+ crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT),
+ segment_length,
+ reencrypt_segment_cipher_new(hdr),
+ reencrypt_get_sector_size_new(hdr), 1);
+ case CRYPT_REENCRYPT_DECRYPT:
+ return json_segment_create_linear(data_offset + segment_offset, segment_length, 1);
+ }
+
+ return NULL;
+}
+
+static json_object *reencrypt_make_segment_old(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct luks2_reencrypt *rh,
+ uint64_t data_offset,
+ uint64_t segment_offset,
+ const uint64_t *segment_length)
+{
+ json_object *jobj_old_seg = NULL;
+
+ switch (rh->mode) {
+ case CRYPT_REENCRYPT_REENCRYPT:
+ case CRYPT_REENCRYPT_DECRYPT:
+ jobj_old_seg = json_segment_create_crypt(data_offset + segment_offset,
+ crypt_get_iv_offset(cd) + (segment_offset >> SECTOR_SHIFT),
+ segment_length,
+ reencrypt_segment_cipher_old(hdr),
+ reencrypt_get_sector_size_old(hdr),
+ 0);
+ break;
+ case CRYPT_REENCRYPT_ENCRYPT:
+ jobj_old_seg = json_segment_create_linear(data_offset + segment_offset, segment_length, 0);
+ }
+
+ return jobj_old_seg;
+}
+
+static json_object *reencrypt_make_hot_segments_forward(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t device_size,
+ uint64_t data_offset)
+{
+ json_object *jobj_segs_hot, *jobj_reenc_seg, *jobj_old_seg, *jobj_new_seg;
+ uint64_t fixed_length, tmp = rh->offset + rh->length;
+ unsigned int sg = 0;
+
+ jobj_segs_hot = json_object_new_object();
+ if (!jobj_segs_hot)
+ return NULL;
+
+ if (rh->offset) {
+ jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, &rh->offset);
+ if (!jobj_new_seg)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_new_seg);
+ }
+
+ jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset, rh->offset, rh->offset, &rh->length);
+ if (!jobj_reenc_seg)
+ goto err;
+
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg);
+
+ if (tmp < device_size) {
+ fixed_length = device_size - tmp;
+ jobj_old_seg = reencrypt_make_segment_old(cd, hdr, rh, data_offset + data_shift_value(&rh->rp),
+ rh->offset + rh->length, rh->fixed_length ? &fixed_length : NULL);
+ if (!jobj_old_seg)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_old_seg);
+ }
+
+ return jobj_segs_hot;
+err:
+ json_object_put(jobj_segs_hot);
+ return NULL;
+}
+
+static json_object *reencrypt_make_hot_segments_decrypt_shift(struct crypt_device *cd,
+ struct luks2_hdr *hdr, struct luks2_reencrypt *rh,
+ uint64_t device_size, uint64_t data_offset)
+{
+ json_object *jobj_segs_hot, *jobj_reenc_seg, *jobj_old_seg, *jobj_new_seg;
+ uint64_t fixed_length, tmp = rh->offset + rh->length, linear_length = rh->progress;
+ unsigned int sg = 0;
+
+ jobj_segs_hot = json_object_new_object();
+ if (!jobj_segs_hot)
+ return NULL;
+
+ if (rh->offset) {
+ jobj_new_seg = LUKS2_get_segment_jobj(hdr, 0);
+ if (!jobj_new_seg)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, json_object_get(jobj_new_seg));
+
+ if (linear_length) {
+ jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh,
+ data_offset,
+ json_segment_get_size(jobj_new_seg, 0),
+ 0,
+ &linear_length);
+ if (!jobj_new_seg)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_new_seg);
+ }
+ }
+
+ jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset,
+ rh->offset,
+ rh->offset,
+ &rh->length);
+ if (!jobj_reenc_seg)
+ goto err;
+
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg);
+
+ if (!rh->offset && (jobj_new_seg = LUKS2_get_segment_jobj(hdr, 1)) &&
+ !json_segment_is_backup(jobj_new_seg))
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, json_object_get(jobj_new_seg));
+ else if (tmp < device_size) {
+ fixed_length = device_size - tmp;
+ jobj_old_seg = reencrypt_make_segment_old(cd, hdr, rh,
+ data_offset + data_shift_value(&rh->rp),
+ rh->offset + rh->length,
+ rh->fixed_length ? &fixed_length : NULL);
+ if (!jobj_old_seg)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_old_seg);
+ }
+
+ return jobj_segs_hot;
+err:
+ json_object_put(jobj_segs_hot);
+ return NULL;
+}
+
+static json_object *_dec_create_segments_shift_after(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t data_offset)
+{
+ int reenc_seg, i = 0;
+ json_object *jobj_copy, *jobj_seg_old, *jobj_seg_new,
+ *jobj_segs_post = json_object_new_object();
+ unsigned segs;
+ uint64_t tmp;
+
+ if (!rh->jobj_segs_hot || !jobj_segs_post)
+ goto err;
+
+ segs = json_segments_count(rh->jobj_segs_hot);
+ if (segs == 0)
+ return jobj_segs_post;
+
+ reenc_seg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
+ if (reenc_seg < 0)
+ goto err;
+
+ if (reenc_seg == 0) {
+ jobj_seg_new = reencrypt_make_segment_new(cd, hdr, rh, data_offset, 0, 0, NULL);
+ if (!jobj_seg_new)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_post, 0, jobj_seg_new);
+
+ return jobj_segs_post;
+ }
+
+ jobj_copy = json_segments_get_segment(rh->jobj_segs_hot, 0);
+ if (!jobj_copy)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_post, i++, json_object_get(jobj_copy));
+
+ jobj_seg_old = json_segments_get_segment(rh->jobj_segs_hot, reenc_seg + 1);
+
+ tmp = rh->length + rh->progress;
+ jobj_seg_new = reencrypt_make_segment_new(cd, hdr, rh, data_offset,
+ json_segment_get_size(rh->jobj_segment_moved, 0),
+ data_shift_value(&rh->rp),
+ jobj_seg_old ? &tmp : NULL);
+ json_object_object_add_by_uint(jobj_segs_post, i++, jobj_seg_new);
+
+ if (jobj_seg_old)
+ json_object_object_add_by_uint(jobj_segs_post, i, json_object_get(jobj_seg_old));
+
+ return jobj_segs_post;
+err:
+ json_object_put(jobj_segs_post);
+ return NULL;
+}
+
+static json_object *reencrypt_make_hot_segments_backward(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t device_size,
+ uint64_t data_offset)
+{
+ json_object *jobj_reenc_seg, *jobj_new_seg, *jobj_old_seg = NULL,
+ *jobj_segs_hot = json_object_new_object();
+ int sg = 0;
+ uint64_t fixed_length, tmp = rh->offset + rh->length;
+
+ if (!jobj_segs_hot)
+ return NULL;
+
+ if (rh->offset) {
+ if (json_object_copy(LUKS2_get_segment_jobj(hdr, 0), &jobj_old_seg))
+ goto err;
+ json_object_object_add(jobj_old_seg, "size", crypt_jobj_new_uint64(rh->offset));
+
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_old_seg);
+ }
+
+ jobj_reenc_seg = reencrypt_make_segment_reencrypt(cd, hdr, rh, data_offset, rh->offset, rh->offset, &rh->length);
+ if (!jobj_reenc_seg)
+ goto err;
+
+ json_object_object_add_by_uint(jobj_segs_hot, sg++, jobj_reenc_seg);
+
+ if (tmp < device_size) {
+ fixed_length = device_size - tmp;
+ jobj_new_seg = reencrypt_make_segment_new(cd, hdr, rh, data_offset, rh->offset + rh->length,
+ rh->offset + rh->length, rh->fixed_length ? &fixed_length : NULL);
+ if (!jobj_new_seg)
+ goto err;
+ json_object_object_add_by_uint(jobj_segs_hot, sg, jobj_new_seg);
+ }
+
+ return jobj_segs_hot;
+err:
+ json_object_put(jobj_segs_hot);
+ return NULL;
+}
+
+static int reencrypt_make_hot_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t device_size,
+ uint64_t data_offset)
+{
+ rh->jobj_segs_hot = NULL;
+
+ if (rh->mode == CRYPT_REENCRYPT_ENCRYPT && rh->direction == CRYPT_REENCRYPT_BACKWARD &&
+ rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->jobj_segment_moved) {
+ log_dbg(cd, "Calculating hot segments for encryption with data move.");
+ rh->jobj_segs_hot = reencrypt_make_hot_segments_encrypt_shift(hdr, rh, data_offset);
+ } else if (rh->mode == CRYPT_REENCRYPT_DECRYPT && rh->direction == CRYPT_REENCRYPT_FORWARD &&
+ rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->jobj_segment_moved) {
+ log_dbg(cd, "Calculating hot segments for decryption with data move.");
+ rh->jobj_segs_hot = reencrypt_make_hot_segments_decrypt_shift(cd, hdr, rh, device_size, data_offset);
+ } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) {
+ log_dbg(cd, "Calculating hot segments (forward direction).");
+ rh->jobj_segs_hot = reencrypt_make_hot_segments_forward(cd, hdr, rh, device_size, data_offset);
+ } else if (rh->direction == CRYPT_REENCRYPT_BACKWARD) {
+ log_dbg(cd, "Calculating hot segments (backward direction).");
+ rh->jobj_segs_hot = reencrypt_make_hot_segments_backward(cd, hdr, rh, device_size, data_offset);
+ }
+
+ return rh->jobj_segs_hot ? 0 : -EINVAL;
+}
+
+static int reencrypt_make_post_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t data_offset)
+{
+ rh->jobj_segs_post = NULL;
+
+ if (rh->mode == CRYPT_REENCRYPT_ENCRYPT && rh->direction == CRYPT_REENCRYPT_BACKWARD &&
+ rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->jobj_segment_moved) {
+ log_dbg(cd, "Calculating post segments for encryption with data move.");
+ rh->jobj_segs_post = _enc_create_segments_shift_after(rh, data_offset);
+ } else if (rh->mode == CRYPT_REENCRYPT_DECRYPT && rh->direction == CRYPT_REENCRYPT_FORWARD &&
+ rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->jobj_segment_moved) {
+ log_dbg(cd, "Calculating post segments for decryption with data move.");
+ rh->jobj_segs_post = _dec_create_segments_shift_after(cd, hdr, rh, data_offset);
+ } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) {
+ log_dbg(cd, "Calculating post segments (forward direction).");
+ rh->jobj_segs_post = reencrypt_make_post_segments_forward(cd, hdr, rh, data_offset);
+ } else if (rh->direction == CRYPT_REENCRYPT_BACKWARD) {
+ log_dbg(cd, "Calculating segments (backward direction).");
+ rh->jobj_segs_post = reencrypt_make_post_segments_backward(cd, hdr, rh, data_offset);
+ }
+
+ return rh->jobj_segs_post ? 0 : -EINVAL;
+}
+#endif
+static uint64_t reencrypt_data_shift(struct luks2_hdr *hdr)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_data_shift;
+ int ks = LUKS2_find_keyslot(hdr, "reencrypt");
+
+ if (ks < 0)
+ return 0;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, ks);
+
+ json_object_object_get_ex(jobj_keyslot, "area", &jobj_area);
+ if (!json_object_object_get_ex(jobj_area, "shift_size", &jobj_data_shift))
+ return 0;
+
+ return crypt_jobj_get_uint64(jobj_data_shift);
+}
+
+static crypt_reencrypt_mode_info reencrypt_mode(struct luks2_hdr *hdr)
+{
+ const char *mode;
+ crypt_reencrypt_mode_info mi = CRYPT_REENCRYPT_REENCRYPT;
+ json_object *jobj_keyslot, *jobj_mode;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, LUKS2_find_keyslot(hdr, "reencrypt"));
+ if (!jobj_keyslot)
+ return mi;
+
+ json_object_object_get_ex(jobj_keyslot, "mode", &jobj_mode);
+ mode = json_object_get_string(jobj_mode);
+
+ /* validation enforces allowed values */
+ if (!strcmp(mode, "encrypt"))
+ mi = CRYPT_REENCRYPT_ENCRYPT;
+ else if (!strcmp(mode, "decrypt"))
+ mi = CRYPT_REENCRYPT_DECRYPT;
+
+ return mi;
+}
+
+static crypt_reencrypt_direction_info reencrypt_direction(struct luks2_hdr *hdr)
+{
+ const char *value;
+ json_object *jobj_keyslot, *jobj_mode;
+ crypt_reencrypt_direction_info di = CRYPT_REENCRYPT_FORWARD;
+
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, LUKS2_find_keyslot(hdr, "reencrypt"));
+ if (!jobj_keyslot)
+ return di;
+
+ json_object_object_get_ex(jobj_keyslot, "direction", &jobj_mode);
+ value = json_object_get_string(jobj_mode);
+
+ /* validation enforces allowed values */
+ if (strcmp(value, "forward"))
+ di = CRYPT_REENCRYPT_BACKWARD;
+
+ return di;
+}
+
+typedef enum { REENC_OK = 0, REENC_ERR, REENC_ROLLBACK, REENC_FATAL } reenc_status_t;
+
+void LUKS2_reencrypt_protection_erase(struct reenc_protection *rp)
+{
+ if (!rp || rp->type != REENC_PROTECTION_CHECKSUM)
+ return;
+
+ if (rp->p.csum.ch) {
+ crypt_hash_destroy(rp->p.csum.ch);
+ rp->p.csum.ch = NULL;
+ }
+
+ if (rp->p.csum.checksums) {
+ crypt_safe_memzero(rp->p.csum.checksums, rp->p.csum.checksums_len);
+ free(rp->p.csum.checksums);
+ rp->p.csum.checksums = NULL;
+ }
+}
+
+void LUKS2_reencrypt_free(struct crypt_device *cd, struct luks2_reencrypt *rh)
+{
+ if (!rh)
+ return;
+
+ LUKS2_reencrypt_protection_erase(&rh->rp);
+ LUKS2_reencrypt_protection_erase(&rh->rp_moved_segment);
+
+ json_object_put(rh->jobj_segs_hot);
+ rh->jobj_segs_hot = NULL;
+ json_object_put(rh->jobj_segs_post);
+ rh->jobj_segs_post = NULL;
+ json_object_put(rh->jobj_segment_old);
+ rh->jobj_segment_old = NULL;
+ json_object_put(rh->jobj_segment_new);
+ rh->jobj_segment_new = NULL;
+ json_object_put(rh->jobj_segment_moved);
+ rh->jobj_segment_moved = NULL;
+
+ free(rh->reenc_buffer);
+ rh->reenc_buffer = NULL;
+ crypt_storage_wrapper_destroy(rh->cw1);
+ rh->cw1 = NULL;
+ crypt_storage_wrapper_destroy(rh->cw2);
+ rh->cw2 = NULL;
+
+ free(rh->device_name);
+ free(rh->overlay_name);
+ free(rh->hotzone_name);
+ crypt_drop_keyring_key(cd, rh->vks);
+ crypt_free_volume_key(rh->vks);
+ device_release_excl(cd, crypt_data_device(cd));
+ crypt_unlock_internal(cd, rh->reenc_lock);
+ free(rh);
+}
+
+int LUKS2_reencrypt_max_hotzone_size(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const struct reenc_protection *rp,
+ int reencrypt_keyslot,
+ uint64_t *r_length)
+{
+#if USE_LUKS2_REENCRYPTION
+ int r;
+ uint64_t dummy, area_length;
+
+ assert(hdr);
+ assert(rp);
+ assert(r_length);
+
+ if (rp->type <= REENC_PROTECTION_NONE) {
+ *r_length = LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH;
+ return 0;
+ }
+
+ if (rp->type == REENC_PROTECTION_DATASHIFT) {
+ *r_length = rp->p.ds.data_shift;
+ return 0;
+ }
+
+ r = LUKS2_keyslot_area(hdr, reencrypt_keyslot, &dummy, &area_length);
+ if (r < 0)
+ return -EINVAL;
+
+ if (rp->type == REENC_PROTECTION_JOURNAL) {
+ *r_length = area_length;
+ return 0;
+ }
+
+ if (rp->type == REENC_PROTECTION_CHECKSUM) {
+ *r_length = (area_length / rp->p.csum.hash_size) * rp->p.csum.block_size;
+ return 0;
+ }
+
+ return -EINVAL;
+#else
+ return -ENOTSUP;
+#endif
+}
+#if USE_LUKS2_REENCRYPTION
+static size_t reencrypt_get_alignment(struct crypt_device *cd,
+ struct luks2_hdr *hdr)
+{
+ size_t ss, alignment = device_block_size(cd, crypt_data_device(cd));
+
+ ss = reencrypt_get_sector_size_old(hdr);
+ if (ss > alignment)
+ alignment = ss;
+ ss = reencrypt_get_sector_size_new(hdr);
+ if (ss > alignment)
+ alignment = ss;
+
+ return alignment;
+}
+
+/* returns void because it must not fail on valid LUKS2 header */
+static void _load_backup_segments(struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh)
+{
+ int segment = LUKS2_get_segment_id_by_flag(hdr, "backup-final");
+
+ if (segment >= 0) {
+ rh->jobj_segment_new = json_object_get(LUKS2_get_segment_jobj(hdr, segment));
+ rh->digest_new = LUKS2_digest_by_segment(hdr, segment);
+ } else {
+ rh->jobj_segment_new = NULL;
+ rh->digest_new = -ENOENT;
+ }
+
+ segment = LUKS2_get_segment_id_by_flag(hdr, "backup-previous");
+ if (segment >= 0) {
+ rh->jobj_segment_old = json_object_get(LUKS2_get_segment_jobj(hdr, segment));
+ rh->digest_old = LUKS2_digest_by_segment(hdr, segment);
+ } else {
+ rh->jobj_segment_old = NULL;
+ rh->digest_old = -ENOENT;
+ }
+
+ segment = LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment");
+ if (segment >= 0)
+ rh->jobj_segment_moved = json_object_get(LUKS2_get_segment_jobj(hdr, segment));
+ else
+ rh->jobj_segment_moved = NULL;
+}
+
+static int reencrypt_offset_backward_moved(struct luks2_hdr *hdr, json_object *jobj_segments,
+ uint64_t *reencrypt_length, uint64_t data_shift, uint64_t *offset)
+{
+ uint64_t tmp, linear_length = 0;
+ int sg, segs = json_segments_count(jobj_segments);
+
+ /* find reencrypt offset with data shift */
+ for (sg = 0; sg < segs; sg++)
+ if (LUKS2_segment_is_type(hdr, sg, "linear"))
+ linear_length += LUKS2_segment_size(hdr, sg, 0);
+
+ /* all active linear segments length */
+ if (linear_length && segs > 1) {
+ if (linear_length < data_shift)
+ return -EINVAL;
+ tmp = linear_length - data_shift;
+ if (tmp && tmp < data_shift) {
+ *offset = data_shift;
+ *reencrypt_length = tmp;
+ } else
+ *offset = tmp;
+ return 0;
+ }
+
+ if (segs == 1) {
+ *offset = 0;
+ return 0;
+ }
+
+ /* should be unreachable */
+
+ return -EINVAL;
+}
+
+static int reencrypt_offset_forward_moved(struct luks2_hdr *hdr,
+ json_object *jobj_segments,
+ uint64_t data_shift,
+ uint64_t *offset)
+{
+ int last_crypt = LUKS2_last_segment_by_type(hdr, "crypt");
+
+ /* if last crypt segment exists and it's first one, just return offset = 0 */
+ if (last_crypt <= 0) {
+ *offset = 0;
+ return 0;
+ }
+
+ *offset = LUKS2_segment_offset(hdr, last_crypt, 0) - data_shift;
+ return 0;
+}
+
+static int _offset_forward(json_object *jobj_segments, uint64_t *offset)
+{
+ int segs = json_segments_count(jobj_segments);
+
+ if (segs == 1)
+ *offset = 0;
+ else if (segs == 2) {
+ *offset = json_segment_get_size(json_segments_get_segment(jobj_segments, 0), 0);
+ if (!*offset)
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int _offset_backward(json_object *jobj_segments, uint64_t device_size, uint64_t *length, uint64_t *offset)
+{
+ int segs = json_segments_count(jobj_segments);
+ uint64_t tmp;
+
+ if (segs == 1) {
+ if (device_size < *length)
+ *length = device_size;
+ *offset = device_size - *length;
+ } else if (segs == 2) {
+ tmp = json_segment_get_size(json_segments_get_segment(jobj_segments, 0), 0);
+ if (tmp < *length)
+ *length = tmp;
+ *offset = tmp - *length;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+/* must be always relative to data offset */
+/* the LUKS2 header MUST be valid */
+static int reencrypt_offset(struct luks2_hdr *hdr,
+ crypt_reencrypt_direction_info di,
+ uint64_t device_size,
+ uint64_t *reencrypt_length,
+ uint64_t *offset)
+{
+ int r, sg;
+ json_object *jobj_segments;
+ uint64_t data_shift = reencrypt_data_shift(hdr);
+
+ if (!offset)
+ return -EINVAL;
+
+ /* if there's segment in reencryption return directly offset of it */
+ json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments);
+ sg = json_segments_segment_in_reencrypt(jobj_segments);
+ if (sg >= 0) {
+ *offset = LUKS2_segment_offset(hdr, sg, 0) - (reencrypt_get_data_offset_new(hdr));
+ return 0;
+ }
+
+ if (di == CRYPT_REENCRYPT_FORWARD) {
+ if (reencrypt_mode(hdr) == CRYPT_REENCRYPT_DECRYPT &&
+ LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0) {
+ r = reencrypt_offset_forward_moved(hdr, jobj_segments, data_shift, offset);
+ if (!r && *offset > device_size)
+ *offset = device_size;
+ return r;
+ }
+ return _offset_forward(jobj_segments, offset);
+ } else if (di == CRYPT_REENCRYPT_BACKWARD) {
+ if (reencrypt_mode(hdr) == CRYPT_REENCRYPT_ENCRYPT &&
+ LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0)
+ return reencrypt_offset_backward_moved(hdr, jobj_segments, reencrypt_length, data_shift, offset);
+ return _offset_backward(jobj_segments, device_size, reencrypt_length, offset);
+ }
+
+ return -EINVAL;
+}
+
+static uint64_t reencrypt_length(struct crypt_device *cd,
+ struct reenc_protection *rp,
+ uint64_t keyslot_area_length,
+ uint64_t length_max,
+ size_t alignment)
+{
+ unsigned long dummy, optimal_alignment;
+ uint64_t length, soft_mem_limit;
+
+ if (rp->type == REENC_PROTECTION_NONE)
+ length = length_max ?: LUKS2_DEFAULT_NONE_REENCRYPTION_LENGTH;
+ else if (rp->type == REENC_PROTECTION_CHECKSUM)
+ length = (keyslot_area_length / rp->p.csum.hash_size) * rp->p.csum.block_size;
+ else if (rp->type == REENC_PROTECTION_DATASHIFT)
+ return rp->p.ds.data_shift;
+ else
+ length = keyslot_area_length;
+
+ /* hard limit */
+ if (length > LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH)
+ length = LUKS2_REENCRYPT_MAX_HOTZONE_LENGTH;
+
+ /* soft limit is 1/4 of system memory */
+ soft_mem_limit = crypt_getphysmemory_kb() << 8; /* multiply by (1024/4) */
+
+ if (soft_mem_limit && length > soft_mem_limit)
+ length = soft_mem_limit;
+
+ if (length_max && length > length_max)
+ length = length_max;
+
+ length -= (length % alignment);
+
+ /* Emits error later */
+ if (!length)
+ return length;
+
+ device_topology_alignment(cd, crypt_data_device(cd), &optimal_alignment, &dummy, length);
+
+ /* we have to stick with encryption sector size alignment */
+ if (optimal_alignment % alignment)
+ return length;
+
+ /* align to opt-io size only if remaining size allows it */
+ if (length > optimal_alignment)
+ length -= (length % optimal_alignment);
+
+ return length;
+}
+
+static int reencrypt_context_init(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t device_size,
+ uint64_t max_hotzone_size,
+ uint64_t fixed_device_size)
+{
+ int r;
+ size_t alignment;
+ uint64_t dummy, area_length;
+
+ rh->reenc_keyslot = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (rh->reenc_keyslot < 0)
+ return -EINVAL;
+ if (LUKS2_keyslot_area(hdr, rh->reenc_keyslot, &dummy, &area_length) < 0)
+ return -EINVAL;
+
+ rh->mode = reencrypt_mode(hdr);
+
+ rh->direction = reencrypt_direction(hdr);
+
+ r = LUKS2_keyslot_reencrypt_load(cd, hdr, rh->reenc_keyslot, &rh->rp, true);
+ if (r < 0)
+ return r;
+
+ if (rh->rp.type == REENC_PROTECTION_CHECKSUM)
+ alignment = rh->rp.p.csum.block_size;
+ else
+ alignment = reencrypt_get_alignment(cd, hdr);
+
+ if (!alignment)
+ return -EINVAL;
+
+ if ((max_hotzone_size << SECTOR_SHIFT) % alignment) {
+ log_err(cd, _("Hotzone size must be multiple of calculated zone alignment (%zu bytes)."), alignment);
+ return -EINVAL;
+ }
+
+ if ((fixed_device_size << SECTOR_SHIFT) % alignment) {
+ log_err(cd, _("Device size must be multiple of calculated zone alignment (%zu bytes)."), alignment);
+ return -EINVAL;
+ }
+
+ if (fixed_device_size) {
+ log_dbg(cd, "Switching reencryption to fixed size mode.");
+ device_size = fixed_device_size << SECTOR_SHIFT;
+ rh->fixed_length = true;
+ } else
+ rh->fixed_length = false;
+
+ rh->length = reencrypt_length(cd, &rh->rp, area_length, max_hotzone_size << SECTOR_SHIFT, alignment);
+ if (!rh->length) {
+ log_dbg(cd, "Invalid reencryption length.");
+ return -EINVAL;
+ }
+
+ if (reencrypt_offset(hdr, rh->direction, device_size, &rh->length, &rh->offset)) {
+ log_dbg(cd, "Failed to get reencryption offset.");
+ return -EINVAL;
+ }
+
+ if (rh->offset > device_size)
+ return -EINVAL;
+ if (rh->length > device_size - rh->offset)
+ rh->length = device_size - rh->offset;
+
+ _load_backup_segments(hdr, rh);
+
+ r = LUKS2_keyslot_reencrypt_load(cd, hdr, rh->reenc_keyslot, &rh->rp_moved_segment, false);
+ if (r < 0)
+ return r;
+
+ if (rh->rp_moved_segment.type == REENC_PROTECTION_NOT_SET)
+ log_dbg(cd, "No moved segment resilience configured.");
+
+ if (rh->direction == CRYPT_REENCRYPT_BACKWARD)
+ rh->progress = device_size - rh->offset - rh->length;
+ else if (rh->jobj_segment_moved && rh->direction == CRYPT_REENCRYPT_FORWARD) {
+ if (rh->offset == json_segment_get_offset(LUKS2_get_segment_by_flag(hdr, "backup-moved-segment"), false))
+ rh->progress = device_size - json_segment_get_size(LUKS2_get_segment_by_flag(hdr, "backup-moved-segment"), false);
+ else
+ rh->progress = rh->offset - json_segment_get_size(rh->jobj_segment_moved, 0);
+ } else
+ rh->progress = rh->offset;
+
+ log_dbg(cd, "reencrypt-direction: %s", rh->direction == CRYPT_REENCRYPT_FORWARD ? "forward" : "backward");
+ log_dbg(cd, "backup-previous digest id: %d", rh->digest_old);
+ log_dbg(cd, "backup-final digest id: %d", rh->digest_new);
+ log_dbg(cd, "reencrypt length: %" PRIu64, rh->length);
+ log_dbg(cd, "reencrypt offset: %" PRIu64, rh->offset);
+ log_dbg(cd, "reencrypt shift: %s%" PRIu64,
+ (rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->direction == CRYPT_REENCRYPT_BACKWARD ? "-" : ""),
+ data_shift_value(&rh->rp));
+ log_dbg(cd, "reencrypt alignment: %zu", alignment);
+ log_dbg(cd, "reencrypt progress: %" PRIu64, rh->progress);
+
+ rh->device_size = device_size;
+
+ return rh->length < 512 ? -EINVAL : 0;
+}
+
+static size_t reencrypt_buffer_length(struct luks2_reencrypt *rh)
+{
+ if (rh->rp.type == REENC_PROTECTION_DATASHIFT)
+ return data_shift_value(&rh->rp);
+ return rh->length;
+}
+
+static int reencrypt_load_clean(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint64_t device_size,
+ uint64_t max_hotzone_size,
+ uint64_t fixed_device_size,
+ struct luks2_reencrypt **rh)
+{
+ int r;
+ struct luks2_reencrypt *tmp = crypt_zalloc(sizeof (*tmp));
+
+ if (!tmp)
+ return -ENOMEM;
+
+ log_dbg(cd, "Loading stored reencryption context.");
+
+ r = reencrypt_context_init(cd, hdr, tmp, device_size, max_hotzone_size, fixed_device_size);
+ if (r)
+ goto err;
+
+ if (posix_memalign(&tmp->reenc_buffer, device_alignment(crypt_data_device(cd)),
+ reencrypt_buffer_length(tmp))) {
+ r = -ENOMEM;
+ goto err;
+ }
+
+ *rh = tmp;
+
+ return 0;
+err:
+ LUKS2_reencrypt_free(cd, tmp);
+
+ return r;
+}
+
+static int reencrypt_make_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t device_size)
+{
+ int r;
+ uint64_t data_offset = reencrypt_get_data_offset_new(hdr);
+
+ log_dbg(cd, "Calculating segments.");
+
+ r = reencrypt_make_hot_segments(cd, hdr, rh, device_size, data_offset);
+ if (!r) {
+ r = reencrypt_make_post_segments(cd, hdr, rh, data_offset);
+ if (r)
+ json_object_put(rh->jobj_segs_hot);
+ }
+
+ if (r)
+ log_dbg(cd, "Failed to make reencryption segments.");
+
+ return r;
+}
+
+static int reencrypt_make_segments_crashed(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh)
+{
+ int r;
+ uint64_t data_offset = crypt_get_data_offset(cd) << SECTOR_SHIFT;
+
+ if (!rh)
+ return -EINVAL;
+
+ rh->jobj_segs_hot = json_object_new_object();
+ if (!rh->jobj_segs_hot)
+ return -ENOMEM;
+
+ json_object_object_foreach(LUKS2_get_segments_jobj(hdr), key, val) {
+ if (json_segment_is_backup(val))
+ continue;
+ json_object_object_add(rh->jobj_segs_hot, key, json_object_get(val));
+ }
+
+ r = reencrypt_make_post_segments(cd, hdr, rh, data_offset);
+ if (r) {
+ json_object_put(rh->jobj_segs_hot);
+ rh->jobj_segs_hot = NULL;
+ }
+
+ return r;
+}
+
+static int reencrypt_load_crashed(struct crypt_device *cd,
+ struct luks2_hdr *hdr, uint64_t device_size, struct luks2_reencrypt **rh)
+{
+ bool dynamic;
+ uint64_t required_device_size;
+ int r, reenc_seg;
+
+ if (LUKS2_get_data_size(hdr, &required_device_size, &dynamic))
+ return -EINVAL;
+
+ if (dynamic)
+ required_device_size = 0;
+ else
+ required_device_size >>= SECTOR_SHIFT;
+
+ r = reencrypt_load_clean(cd, hdr, device_size, 0, required_device_size, rh);
+
+ if (!r) {
+ reenc_seg = json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr));
+ if (reenc_seg < 0)
+ r = -EINVAL;
+ else
+ (*rh)->length = LUKS2_segment_size(hdr, reenc_seg, 0);
+ }
+
+ if (!r)
+ r = reencrypt_make_segments_crashed(cd, hdr, *rh);
+
+ if (r) {
+ LUKS2_reencrypt_free(cd, *rh);
+ *rh = NULL;
+ }
+ return r;
+}
+
+static int reencrypt_init_storage_wrappers(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ struct volume_key *vks)
+{
+ int r;
+ struct volume_key *vk;
+ uint32_t wrapper_flags = (getuid() || geteuid()) ? 0 : DISABLE_KCAPI;
+
+ vk = crypt_volume_key_by_id(vks, rh->digest_old);
+ r = crypt_storage_wrapper_init(cd, &rh->cw1, crypt_data_device(cd),
+ reencrypt_get_data_offset_old(hdr),
+ crypt_get_iv_offset(cd),
+ reencrypt_get_sector_size_old(hdr),
+ reencrypt_segment_cipher_old(hdr),
+ vk, wrapper_flags | OPEN_READONLY);
+ if (r) {
+ log_err(cd, _("Failed to initialize old segment storage wrapper."));
+ return r;
+ }
+ rh->wflags1 = wrapper_flags | OPEN_READONLY;
+ log_dbg(cd, "Old cipher storage wrapper type: %d.", crypt_storage_wrapper_get_type(rh->cw1));
+
+ vk = crypt_volume_key_by_id(vks, rh->digest_new);
+ r = crypt_storage_wrapper_init(cd, &rh->cw2, crypt_data_device(cd),
+ reencrypt_get_data_offset_new(hdr),
+ crypt_get_iv_offset(cd),
+ reencrypt_get_sector_size_new(hdr),
+ reencrypt_segment_cipher_new(hdr),
+ vk, wrapper_flags);
+ if (r) {
+ log_err(cd, _("Failed to initialize new segment storage wrapper."));
+ return r;
+ }
+ rh->wflags2 = wrapper_flags;
+ log_dbg(cd, "New cipher storage wrapper type: %d", crypt_storage_wrapper_get_type(rh->cw2));
+
+ return 0;
+}
+
+static int reencrypt_context_set_names(struct luks2_reencrypt *rh, const char *name)
+{
+ if (!rh | !name)
+ return -EINVAL;
+
+ if (*name == '/') {
+ if (!(rh->device_name = dm_device_name(name)))
+ return -EINVAL;
+ } else if (!(rh->device_name = strdup(name)))
+ return -ENOMEM;
+
+ if (asprintf(&rh->hotzone_name, "%s-hotzone-%s", rh->device_name,
+ rh->direction == CRYPT_REENCRYPT_FORWARD ? "forward" : "backward") < 0) {
+ rh->hotzone_name = NULL;
+ return -ENOMEM;
+ }
+ if (asprintf(&rh->overlay_name, "%s-overlay", rh->device_name) < 0) {
+ rh->overlay_name = NULL;
+ return -ENOMEM;
+ }
+
+ rh->online = true;
+ return 0;
+}
+
+static int modify_offset(uint64_t *offset, uint64_t data_shift, crypt_reencrypt_direction_info di)
+{
+ int r = -EINVAL;
+
+ if (!offset)
+ return r;
+
+ if (di == CRYPT_REENCRYPT_FORWARD) {
+ if (*offset >= data_shift) {
+ *offset -= data_shift;
+ r = 0;
+ }
+ } else if (di == CRYPT_REENCRYPT_BACKWARD) {
+ *offset += data_shift;
+ r = 0;
+ }
+
+ return r;
+}
+
+static int reencrypt_update_flag(struct crypt_device *cd, uint8_t version,
+ bool enable, bool commit)
+{
+ uint32_t reqs;
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ if (enable) {
+ log_dbg(cd, "Going to store reencryption requirement flag (version: %u).", version);
+ return LUKS2_config_set_requirement_version(cd, hdr, CRYPT_REQUIREMENT_ONLINE_REENCRYPT, version, commit);
+ }
+
+ if (LUKS2_config_get_requirements(cd, hdr, &reqs))
+ return -EINVAL;
+
+ reqs &= ~CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
+
+ log_dbg(cd, "Going to wipe reencryption requirement flag.");
+
+ return LUKS2_config_set_requirements(cd, hdr, reqs, commit);
+}
+
+static int reencrypt_hotzone_protect_ready(struct crypt_device *cd,
+ struct reenc_protection *rp)
+{
+ assert(rp);
+
+ if (rp->type == REENC_PROTECTION_NOT_SET)
+ return -EINVAL;
+
+ if (rp->type != REENC_PROTECTION_CHECKSUM)
+ return 0;
+
+ if (!rp->p.csum.checksums) {
+ log_dbg(cd, "Allocating buffer for storing resilience checksums.");
+ if (posix_memalign(&rp->p.csum.checksums, device_alignment(crypt_metadata_device(cd)),
+ rp->p.csum.checksums_len))
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int reencrypt_recover_segment(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ struct volume_key *vks)
+{
+ struct volume_key *vk_old, *vk_new;
+ size_t count, s;
+ ssize_t read, w;
+ struct reenc_protection *rp;
+ int devfd, r, new_sector_size, old_sector_size, rseg;
+ uint64_t area_offset, area_length, area_length_read, crash_iv_offset,
+ data_offset = crypt_get_data_offset(cd) << SECTOR_SHIFT;
+ char *checksum_tmp = NULL, *data_buffer = NULL;
+ struct crypt_storage_wrapper *cw1 = NULL, *cw2 = NULL;
+
+ assert(hdr);
+ assert(rh);
+ assert(vks);
+
+ rseg = json_segments_segment_in_reencrypt(rh->jobj_segs_hot);
+ if (rh->offset == 0 && rh->rp_moved_segment.type > REENC_PROTECTION_NOT_SET) {
+ log_dbg(cd, "Recovery using moved segment protection.");
+ rp = &rh->rp_moved_segment;
+ } else
+ rp = &rh->rp;
+
+ if (rseg < 0 || rh->length < 512)
+ return -EINVAL;
+
+ r = reencrypt_hotzone_protect_ready(cd, rp);
+ if (r) {
+ log_err(cd, _("Failed to initialize hotzone protection."));
+ return -EINVAL;
+ }
+
+ vk_new = crypt_volume_key_by_id(vks, rh->digest_new);
+ if (!vk_new && rh->mode != CRYPT_REENCRYPT_DECRYPT)
+ return -EINVAL;
+ vk_old = crypt_volume_key_by_id(vks, rh->digest_old);
+ if (!vk_old && rh->mode != CRYPT_REENCRYPT_ENCRYPT)
+ return -EINVAL;
+ old_sector_size = json_segment_get_sector_size(reencrypt_segment_old(hdr));
+ new_sector_size = json_segment_get_sector_size(reencrypt_segment_new(hdr));
+ if (rh->mode == CRYPT_REENCRYPT_DECRYPT)
+ crash_iv_offset = rh->offset >> SECTOR_SHIFT; /* TODO: + old iv_tweak */
+ else
+ crash_iv_offset = json_segment_get_iv_offset(json_segments_get_segment(rh->jobj_segs_hot, rseg));
+
+ log_dbg(cd, "crash_offset: %" PRIu64 ", crash_length: %" PRIu64 ", crash_iv_offset: %" PRIu64,
+ data_offset + rh->offset, rh->length, crash_iv_offset);
+
+ r = crypt_storage_wrapper_init(cd, &cw2, crypt_data_device(cd),
+ data_offset + rh->offset, crash_iv_offset, new_sector_size,
+ reencrypt_segment_cipher_new(hdr), vk_new, 0);
+ if (r) {
+ log_err(cd, _("Failed to initialize new segment storage wrapper."));
+ return r;
+ }
+
+ if (LUKS2_keyslot_area(hdr, rh->reenc_keyslot, &area_offset, &area_length)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (posix_memalign((void**)&data_buffer, device_alignment(crypt_data_device(cd)), rh->length)) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ switch (rp->type) {
+ case REENC_PROTECTION_CHECKSUM:
+ log_dbg(cd, "Checksums based recovery.");
+
+ r = crypt_storage_wrapper_init(cd, &cw1, crypt_data_device(cd),
+ data_offset + rh->offset, crash_iv_offset, old_sector_size,
+ reencrypt_segment_cipher_old(hdr), vk_old, 0);
+ if (r) {
+ log_err(cd, _("Failed to initialize old segment storage wrapper."));
+ goto out;
+ }
+
+ count = rh->length / rp->p.csum.block_size;
+ area_length_read = count * rp->p.csum.hash_size;
+ if (area_length_read > area_length) {
+ log_dbg(cd, "Internal error in calculated area_length.");
+ r = -EINVAL;
+ goto out;
+ }
+
+ checksum_tmp = malloc(rp->p.csum.hash_size);
+ if (!checksum_tmp) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /* TODO: lock for read */
+ devfd = device_open(cd, crypt_metadata_device(cd), O_RDONLY);
+ if (devfd < 0)
+ goto out;
+
+ /* read old data checksums */
+ read = read_lseek_blockwise(devfd, device_block_size(cd, crypt_metadata_device(cd)),
+ device_alignment(crypt_metadata_device(cd)), rp->p.csum.checksums, area_length_read, area_offset);
+ if (read < 0 || (size_t)read != area_length_read) {
+ log_err(cd, _("Failed to read checksums for current hotzone."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ read = crypt_storage_wrapper_read(cw2, 0, data_buffer, rh->length);
+ if (read < 0 || (size_t)read != rh->length) {
+ log_err(cd, _("Failed to read hotzone area starting at %" PRIu64 "."), rh->offset + data_offset);
+ r = -EINVAL;
+ goto out;
+ }
+
+ for (s = 0; s < count; s++) {
+ if (crypt_hash_write(rp->p.csum.ch, data_buffer + (s * rp->p.csum.block_size), rp->p.csum.block_size)) {
+ log_dbg(cd, "Failed to write hash.");
+ r = EINVAL;
+ goto out;
+ }
+ if (crypt_hash_final(rp->p.csum.ch, checksum_tmp, rp->p.csum.hash_size)) {
+ log_dbg(cd, "Failed to finalize hash.");
+ r = EINVAL;
+ goto out;
+ }
+ if (!memcmp(checksum_tmp, (char *)rp->p.csum.checksums + (s * rp->p.csum.hash_size), rp->p.csum.hash_size)) {
+ log_dbg(cd, "Sector %zu (size %zu, offset %zu) needs recovery", s, rp->p.csum.block_size, s * rp->p.csum.block_size);
+ if (crypt_storage_wrapper_decrypt(cw1, s * rp->p.csum.block_size, data_buffer + (s * rp->p.csum.block_size), rp->p.csum.block_size)) {
+ log_err(cd, _("Failed to decrypt sector %zu."), s);
+ r = -EINVAL;
+ goto out;
+ }
+ w = crypt_storage_wrapper_encrypt_write(cw2, s * rp->p.csum.block_size, data_buffer + (s * rp->p.csum.block_size), rp->p.csum.block_size);
+ if (w < 0 || (size_t)w != rp->p.csum.block_size) {
+ log_err(cd, _("Failed to recover sector %zu."), s);
+ r = -EINVAL;
+ goto out;
+ }
+ }
+ }
+
+ r = 0;
+ break;
+ case REENC_PROTECTION_JOURNAL:
+ log_dbg(cd, "Journal based recovery.");
+
+ /* FIXME: validation candidate */
+ if (rh->length > area_length) {
+ r = -EINVAL;
+ log_dbg(cd, "Invalid journal size.");
+ goto out;
+ }
+
+ /* TODO locking */
+ r = crypt_storage_wrapper_init(cd, &cw1, crypt_metadata_device(cd),
+ area_offset, crash_iv_offset, old_sector_size,
+ reencrypt_segment_cipher_old(hdr), vk_old, 0);
+ if (r) {
+ log_err(cd, _("Failed to initialize old segment storage wrapper."));
+ goto out;
+ }
+ read = crypt_storage_wrapper_read_decrypt(cw1, 0, data_buffer, rh->length);
+ if (read < 0 || (size_t)read != rh->length) {
+ log_dbg(cd, "Failed to read journaled data.");
+ r = -EIO;
+ /* may content plaintext */
+ crypt_safe_memzero(data_buffer, rh->length);
+ goto out;
+ }
+ read = crypt_storage_wrapper_encrypt_write(cw2, 0, data_buffer, rh->length);
+ /* may content plaintext */
+ crypt_safe_memzero(data_buffer, rh->length);
+ if (read < 0 || (size_t)read != rh->length) {
+ log_dbg(cd, "recovery write failed.");
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = 0;
+ break;
+ case REENC_PROTECTION_DATASHIFT:
+ log_dbg(cd, "Data shift based recovery.");
+
+ if (rseg == 0) {
+ r = crypt_storage_wrapper_init(cd, &cw1, crypt_data_device(cd),
+ json_segment_get_offset(rh->jobj_segment_moved, 0), 0,
+ reencrypt_get_sector_size_old(hdr),
+ reencrypt_segment_cipher_old(hdr), vk_old, 0);
+ } else {
+ if (rh->direction == CRYPT_REENCRYPT_FORWARD)
+ data_offset = data_offset + rh->offset + data_shift_value(rp);
+ else
+ data_offset = data_offset + rh->offset - data_shift_value(rp);
+ r = crypt_storage_wrapper_init(cd, &cw1, crypt_data_device(cd),
+ data_offset,
+ crash_iv_offset,
+ reencrypt_get_sector_size_old(hdr),
+ reencrypt_segment_cipher_old(hdr), vk_old, 0);
+ }
+ if (r) {
+ log_err(cd, _("Failed to initialize old segment storage wrapper."));
+ goto out;
+ }
+
+ read = crypt_storage_wrapper_read_decrypt(cw1, 0, data_buffer, rh->length);
+ if (read < 0 || (size_t)read != rh->length) {
+ log_dbg(cd, "Failed to read data.");
+ r = -EIO;
+ /* may content plaintext */
+ crypt_safe_memzero(data_buffer, rh->length);
+ goto out;
+ }
+
+ read = crypt_storage_wrapper_encrypt_write(cw2, 0, data_buffer, rh->length);
+ /* may content plaintext */
+ crypt_safe_memzero(data_buffer, rh->length);
+ if (read < 0 || (size_t)read != rh->length) {
+ log_dbg(cd, "recovery write failed.");
+ r = -EINVAL;
+ goto out;
+ }
+ r = 0;
+ break;
+ default:
+ r = -EINVAL;
+ }
+
+ if (!r)
+ rh->read = rh->length;
+out:
+ free(data_buffer);
+ free(checksum_tmp);
+ crypt_storage_wrapper_destroy(cw1);
+ crypt_storage_wrapper_destroy(cw2);
+
+ return r;
+}
+
+static int reencrypt_add_moved_segment(struct crypt_device *cd, struct luks2_hdr *hdr, struct luks2_reencrypt *rh)
+{
+ int digest = rh->digest_old, s = LUKS2_segment_first_unused_id(hdr);
+
+ if (!rh->jobj_segment_moved)
+ return 0;
+
+ if (s < 0)
+ return s;
+
+ if (json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), s, json_object_get(rh->jobj_segment_moved))) {
+ json_object_put(rh->jobj_segment_moved);
+ return -EINVAL;
+ }
+
+ if (!strcmp(json_segment_type(rh->jobj_segment_moved), "crypt"))
+ return LUKS2_digest_segment_assign(cd, hdr, s, digest, 1, 0);
+
+ return 0;
+}
+
+static int reencrypt_add_backup_segment(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ unsigned final)
+{
+ int digest, s = LUKS2_segment_first_unused_id(hdr);
+ json_object *jobj;
+
+ if (s < 0)
+ return s;
+
+ digest = final ? rh->digest_new : rh->digest_old;
+ jobj = final ? rh->jobj_segment_new : rh->jobj_segment_old;
+
+ if (json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), s, json_object_get(jobj))) {
+ json_object_put(jobj);
+ return -EINVAL;
+ }
+
+ if (strcmp(json_segment_type(jobj), "crypt"))
+ return 0;
+
+ return LUKS2_digest_segment_assign(cd, hdr, s, digest, 1, 0);
+}
+
+static int reencrypt_assign_segments_simple(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ unsigned hot,
+ unsigned commit)
+{
+ int r, sg;
+
+ if (hot && json_segments_count(rh->jobj_segs_hot) > 0) {
+ log_dbg(cd, "Setting 'hot' segments.");
+
+ r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_hot, 0);
+ if (!r)
+ rh->jobj_segs_hot = NULL;
+ } else if (!hot && json_segments_count(rh->jobj_segs_post) > 0) {
+ log_dbg(cd, "Setting 'post' segments.");
+ r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_post, 0);
+ if (!r)
+ rh->jobj_segs_post = NULL;
+ } else {
+ log_dbg(cd, "No segments to set.");
+ return -EINVAL;
+ }
+
+ if (r) {
+ log_dbg(cd, "Failed to assign new enc segments.");
+ return r;
+ }
+
+ r = reencrypt_add_backup_segment(cd, hdr, rh, 0);
+ if (r) {
+ log_dbg(cd, "Failed to assign reencryption previous backup segment.");
+ return r;
+ }
+
+ r = reencrypt_add_backup_segment(cd, hdr, rh, 1);
+ if (r) {
+ log_dbg(cd, "Failed to assign reencryption final backup segment.");
+ return r;
+ }
+
+ r = reencrypt_add_moved_segment(cd, hdr, rh);
+ if (r) {
+ log_dbg(cd, "Failed to assign reencryption moved backup segment.");
+ return r;
+ }
+
+ for (sg = 0; sg < LUKS2_segments_count(hdr); sg++) {
+ if (LUKS2_segment_is_type(hdr, sg, "crypt") &&
+ LUKS2_digest_segment_assign(cd, hdr, sg, rh->mode == CRYPT_REENCRYPT_ENCRYPT ? rh->digest_new : rh->digest_old, 1, 0)) {
+ log_dbg(cd, "Failed to assign digest %u to segment %u.", rh->digest_new, sg);
+ return -EINVAL;
+ }
+ }
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+static int reencrypt_assign_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ unsigned hot,
+ unsigned commit)
+{
+ bool forward;
+ int rseg, scount, r = -EINVAL;
+
+ /* FIXME: validate in reencrypt context load */
+ if (rh->digest_new < 0 && rh->mode != CRYPT_REENCRYPT_DECRYPT)
+ return -EINVAL;
+
+ if (LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, CRYPT_ANY_DIGEST, 0, 0))
+ return -EINVAL;
+
+ if (rh->mode == CRYPT_REENCRYPT_ENCRYPT || rh->mode == CRYPT_REENCRYPT_DECRYPT)
+ return reencrypt_assign_segments_simple(cd, hdr, rh, hot, commit);
+
+ if (hot && rh->jobj_segs_hot) {
+ log_dbg(cd, "Setting 'hot' segments.");
+
+ r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_hot, 0);
+ if (!r)
+ rh->jobj_segs_hot = NULL;
+ } else if (!hot && rh->jobj_segs_post) {
+ log_dbg(cd, "Setting 'post' segments.");
+ r = LUKS2_segments_set(cd, hdr, rh->jobj_segs_post, 0);
+ if (!r)
+ rh->jobj_segs_post = NULL;
+ }
+
+ if (r)
+ return r;
+
+ scount = LUKS2_segments_count(hdr);
+
+ /* segment in reencryption has to hold reference on both digests */
+ rseg = json_segments_segment_in_reencrypt(LUKS2_get_segments_jobj(hdr));
+ if (rseg < 0 && hot)
+ return -EINVAL;
+
+ if (rseg >= 0) {
+ LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_new, 1, 0);
+ LUKS2_digest_segment_assign(cd, hdr, rseg, rh->digest_old, 1, 0);
+ }
+
+ forward = (rh->direction == CRYPT_REENCRYPT_FORWARD);
+ if (hot) {
+ if (rseg > 0)
+ LUKS2_digest_segment_assign(cd, hdr, 0, forward ? rh->digest_new : rh->digest_old, 1, 0);
+ if (scount > rseg + 1)
+ LUKS2_digest_segment_assign(cd, hdr, rseg + 1, forward ? rh->digest_old : rh->digest_new, 1, 0);
+ } else {
+ LUKS2_digest_segment_assign(cd, hdr, 0, forward || scount == 1 ? rh->digest_new : rh->digest_old, 1, 0);
+ if (scount > 1)
+ LUKS2_digest_segment_assign(cd, hdr, 1, forward ? rh->digest_old : rh->digest_new, 1, 0);
+ }
+
+ r = reencrypt_add_backup_segment(cd, hdr, rh, 0);
+ if (r) {
+ log_dbg(cd, "Failed to assign hot reencryption backup segment.");
+ return r;
+ }
+ r = reencrypt_add_backup_segment(cd, hdr, rh, 1);
+ if (r) {
+ log_dbg(cd, "Failed to assign post reencryption backup segment.");
+ return r;
+ }
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+static int reencrypt_set_encrypt_segments(struct crypt_device *cd, struct luks2_hdr *hdr,
+ uint64_t dev_size, uint64_t data_shift, bool move_first_segment,
+ crypt_reencrypt_direction_info di)
+{
+ int r;
+ uint64_t first_segment_offset, first_segment_length,
+ second_segment_offset, second_segment_length,
+ data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT,
+ data_size = dev_size - data_shift;
+ json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *jobj_segments;
+
+ if (dev_size < data_shift)
+ return -EINVAL;
+
+ if (data_shift && (di == CRYPT_REENCRYPT_FORWARD))
+ return -ENOTSUP;
+
+ if (move_first_segment) {
+ /*
+ * future data_device layout:
+ * [future LUKS2 header (data shift size)][second data segment][gap (data shift size)][first data segment (data shift size)]
+ */
+ first_segment_offset = dev_size;
+ if (data_size < data_shift) {
+ first_segment_length = data_size;
+ second_segment_length = second_segment_offset = 0;
+ } else {
+ first_segment_length = data_shift;
+ second_segment_offset = data_shift;
+ second_segment_length = data_size - data_shift;
+ }
+ } else if (data_shift) {
+ first_segment_offset = data_offset;
+ first_segment_length = dev_size;
+ } else {
+ /* future data_device layout with detached header: [first data segment] */
+ first_segment_offset = data_offset;
+ first_segment_length = 0; /* dynamic */
+ }
+
+ jobj_segments = json_object_new_object();
+ if (!jobj_segments)
+ return -ENOMEM;
+
+ r = -EINVAL;
+ if (move_first_segment) {
+ jobj_segment_first = json_segment_create_linear(first_segment_offset, &first_segment_length, 0);
+ if (second_segment_length &&
+ !(jobj_segment_second = json_segment_create_linear(second_segment_offset, &second_segment_length, 0))) {
+ log_dbg(cd, "Failed generate 2nd segment.");
+ return r;
+ }
+ } else
+ jobj_segment_first = json_segment_create_linear(first_segment_offset, first_segment_length ? &first_segment_length : NULL, 0);
+
+ if (!jobj_segment_first) {
+ log_dbg(cd, "Failed generate 1st segment.");
+ return r;
+ }
+
+ json_object_object_add(jobj_segments, "0", jobj_segment_first);
+ if (jobj_segment_second)
+ json_object_object_add(jobj_segments, "1", jobj_segment_second);
+
+ r = LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, CRYPT_ANY_DIGEST, 0, 0);
+
+ return r ?: LUKS2_segments_set(cd, hdr, jobj_segments, 0);
+}
+
+static int reencrypt_set_decrypt_shift_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint64_t dev_size,
+ uint64_t moved_segment_length,
+ crypt_reencrypt_direction_info di)
+{
+ int r;
+ uint64_t first_segment_offset, first_segment_length,
+ second_segment_offset, second_segment_length,
+ data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
+ json_object *jobj_segment_first = NULL, *jobj_segment_second = NULL, *jobj_segments;
+
+ if (di == CRYPT_REENCRYPT_BACKWARD)
+ return -ENOTSUP;
+
+ /*
+ * future data_device layout:
+ * [encrypted first segment (max data shift size)][gap (data shift size)][second encrypted data segment]
+ */
+ first_segment_offset = 0;
+ first_segment_length = moved_segment_length;
+ if (dev_size > moved_segment_length) {
+ second_segment_offset = data_offset + first_segment_length;
+ second_segment_length = 0;
+ }
+
+ jobj_segments = json_object_new_object();
+ if (!jobj_segments)
+ return -ENOMEM;
+
+ r = -EINVAL;
+ jobj_segment_first = json_segment_create_crypt(first_segment_offset,
+ crypt_get_iv_offset(cd), &first_segment_length,
+ crypt_get_cipher_spec(cd), crypt_get_sector_size(cd), 0);
+
+ if (!jobj_segment_first) {
+ log_dbg(cd, "Failed generate 1st segment.");
+ return r;
+ }
+
+ if (dev_size > moved_segment_length) {
+ jobj_segment_second = json_segment_create_crypt(second_segment_offset,
+ crypt_get_iv_offset(cd) + (first_segment_length >> SECTOR_SHIFT),
+ second_segment_length ? &second_segment_length : NULL,
+ crypt_get_cipher_spec(cd),
+ crypt_get_sector_size(cd), 0);
+ if (!jobj_segment_second) {
+ json_object_put(jobj_segment_first);
+ log_dbg(cd, "Failed generate 2nd segment.");
+ return r;
+ }
+ }
+
+ json_object_object_add(jobj_segments, "0", jobj_segment_first);
+ if (jobj_segment_second)
+ json_object_object_add(jobj_segments, "1", jobj_segment_second);
+
+ r = LUKS2_segments_set(cd, hdr, jobj_segments, 0);
+
+ return r ?: LUKS2_digest_segment_assign(cd, hdr, CRYPT_ANY_SEGMENT, 0, 1, 0);
+}
+
+static int reencrypt_make_targets(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct device *hz_device,
+ struct volume_key *vks,
+ struct dm_target *result,
+ uint64_t size)
+{
+ bool reenc_seg;
+ struct volume_key *vk;
+ uint64_t segment_size, segment_offset, segment_start = 0;
+ int r;
+ int s = 0;
+ json_object *jobj, *jobj_segments = LUKS2_get_segments_jobj(hdr);
+
+ while (result) {
+ jobj = json_segments_get_segment(jobj_segments, s);
+ if (!jobj) {
+ log_dbg(cd, "Internal error. Segment %u is null.", s);
+ return -EINVAL;
+ }
+
+ reenc_seg = (s == json_segments_segment_in_reencrypt(jobj_segments));
+
+ segment_offset = json_segment_get_offset(jobj, 1);
+ segment_size = json_segment_get_size(jobj, 1);
+ /* 'dynamic' length allowed in last segment only */
+ if (!segment_size && !result->next)
+ segment_size = (size >> SECTOR_SHIFT) - segment_start;
+ if (!segment_size) {
+ log_dbg(cd, "Internal error. Wrong segment size %u", s);
+ return -EINVAL;
+ }
+
+ if (reenc_seg)
+ segment_offset -= crypt_get_data_offset(cd);
+
+ if (!strcmp(json_segment_type(jobj), "crypt")) {
+ vk = crypt_volume_key_by_id(vks, reenc_seg ? LUKS2_reencrypt_digest_new(hdr) : LUKS2_digest_by_segment(hdr, s));
+ if (!vk) {
+ log_err(cd, _("Missing key for dm-crypt segment %u"), s);
+ return -EINVAL;
+ }
+
+ r = dm_crypt_target_set(result, segment_start, segment_size,
+ reenc_seg ? hz_device : crypt_data_device(cd),
+ vk,
+ json_segment_get_cipher(jobj),
+ json_segment_get_iv_offset(jobj),
+ segment_offset,
+ "none",
+ 0,
+ json_segment_get_sector_size(jobj));
+ if (r) {
+ log_err(cd, _("Failed to set dm-crypt segment."));
+ return r;
+ }
+ } else if (!strcmp(json_segment_type(jobj), "linear")) {
+ r = dm_linear_target_set(result, segment_start, segment_size, reenc_seg ? hz_device : crypt_data_device(cd), segment_offset);
+ if (r) {
+ log_err(cd, _("Failed to set dm-linear segment."));
+ return r;
+ }
+ } else
+ return EINVAL;
+
+ segment_start += segment_size;
+ s++;
+ result = result->next;
+ }
+
+ return s;
+}
+
+/* GLOBAL FIXME: audit function names and parameters names */
+
+/* FIXME:
+ * 1) audit log routines
+ * 2) can't we derive hotzone device name from crypt context? (unlocked name, device uuid, etc?)
+ */
+static int reencrypt_load_overlay_device(struct crypt_device *cd, struct luks2_hdr *hdr,
+ const char *overlay, const char *hotzone, struct volume_key *vks, uint64_t size,
+ uint32_t flags)
+{
+ char hz_path[PATH_MAX];
+ int r;
+
+ struct device *hz_dev = NULL;
+ struct crypt_dm_active_device dmd = {
+ .flags = flags,
+ };
+
+ log_dbg(cd, "Loading new table for overlay device %s.", overlay);
+
+ r = snprintf(hz_path, PATH_MAX, "%s/%s", dm_get_dir(), hotzone);
+ if (r < 0 || r >= PATH_MAX) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = device_alloc(cd, &hz_dev, hz_path);
+ if (r)
+ goto out;
+
+ r = dm_targets_allocate(&dmd.segment, LUKS2_segments_count(hdr));
+ if (r)
+ goto out;
+
+ r = reencrypt_make_targets(cd, hdr, hz_dev, vks, &dmd.segment, size);
+ if (r < 0)
+ goto out;
+
+ r = dm_reload_device(cd, overlay, &dmd, 0, 0);
+
+ /* what else on error here ? */
+out:
+ dm_targets_free(cd, &dmd);
+ device_free(cd, hz_dev);
+
+ return r;
+}
+
+static int reencrypt_replace_device(struct crypt_device *cd, const char *target, const char *source, uint32_t flags)
+{
+ int r, exists = 1;
+ struct crypt_dm_active_device dmd_source, dmd_target = {};
+ uint32_t dmflags = DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH;
+
+ log_dbg(cd, "Replacing table in device %s with table from device %s.", target, source);
+
+ /* check only whether target device exists */
+ r = dm_status_device(cd, target);
+ if (r < 0) {
+ if (r == -ENODEV)
+ exists = 0;
+ else
+ return r;
+ }
+
+ r = dm_query_device(cd, source, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY, &dmd_source);
+
+ if (r < 0)
+ return r;
+
+ if (exists && ((r = dm_query_device(cd, target, 0, &dmd_target)) < 0))
+ goto out;
+
+ dmd_source.flags |= flags;
+ dmd_source.uuid = crypt_get_uuid(cd);
+
+ if (exists) {
+ if (dmd_target.size != dmd_source.size) {
+ log_err(cd, _("Source and target device sizes don't match. Source %" PRIu64 ", target: %" PRIu64 "."),
+ dmd_source.size, dmd_target.size);
+ r = -EINVAL;
+ goto out;
+ }
+ r = dm_reload_device(cd, target, &dmd_source, 0, 0);
+ if (!r) {
+ log_dbg(cd, "Resuming device %s", target);
+ r = dm_resume_device(cd, target, dmflags | act2dmflags(dmd_source.flags));
+ }
+ } else
+ r = dm_create_device(cd, target, CRYPT_SUBDEV, &dmd_source);
+out:
+ dm_targets_free(cd, &dmd_source);
+ dm_targets_free(cd, &dmd_target);
+
+ return r;
+}
+
+static int reencrypt_swap_backing_device(struct crypt_device *cd, const char *name,
+ const char *new_backend_name)
+{
+ int r;
+ struct device *overlay_dev = NULL;
+ char overlay_path[PATH_MAX] = { 0 };
+ struct crypt_dm_active_device dmd = {};
+
+ log_dbg(cd, "Redirecting %s mapping to new backing device: %s.", name, new_backend_name);
+
+ r = snprintf(overlay_path, PATH_MAX, "%s/%s", dm_get_dir(), new_backend_name);
+ if (r < 0 || r >= PATH_MAX) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = device_alloc(cd, &overlay_dev, overlay_path);
+ if (r)
+ goto out;
+
+ r = device_block_adjust(cd, overlay_dev, DEV_OK,
+ 0, &dmd.size, &dmd.flags);
+ if (r)
+ goto out;
+
+ r = dm_linear_target_set(&dmd.segment, 0, dmd.size, overlay_dev, 0);
+ if (r)
+ goto out;
+
+ r = dm_reload_device(cd, name, &dmd, 0, 0);
+ if (!r) {
+ log_dbg(cd, "Resuming device %s", name);
+ r = dm_resume_device(cd, name, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH);
+ }
+
+out:
+ dm_targets_free(cd, &dmd);
+ device_free(cd, overlay_dev);
+
+ return r;
+}
+
+static int reencrypt_activate_hotzone_device(struct crypt_device *cd, const char *name, uint64_t device_size, uint32_t flags)
+{
+ int r;
+ uint64_t new_offset = reencrypt_get_data_offset_new(crypt_get_hdr(cd, CRYPT_LUKS2)) >> SECTOR_SHIFT;
+
+ struct crypt_dm_active_device dmd = {
+ .flags = flags,
+ .uuid = crypt_get_uuid(cd),
+ .size = device_size >> SECTOR_SHIFT
+ };
+
+ log_dbg(cd, "Activating hotzone device %s.", name);
+
+ r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
+ new_offset, &dmd.size, &dmd.flags);
+ if (r)
+ goto out;
+
+ r = dm_linear_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd), new_offset);
+ if (r)
+ goto out;
+
+ r = dm_create_device(cd, name, CRYPT_SUBDEV, &dmd);
+out:
+ dm_targets_free(cd, &dmd);
+
+ return r;
+}
+
+static int reencrypt_init_device_stack(struct crypt_device *cd,
+ const struct luks2_reencrypt *rh)
+{
+ int r;
+
+ /* Activate hotzone device 1:1 linear mapping to data_device */
+ r = reencrypt_activate_hotzone_device(cd, rh->hotzone_name, rh->device_size, CRYPT_ACTIVATE_PRIVATE);
+ if (r) {
+ log_err(cd, _("Failed to activate hotzone device %s."), rh->hotzone_name);
+ return r;
+ }
+
+ /*
+ * Activate overlay device with exactly same table as original 'name' mapping.
+ * Note that within this step the 'name' device may already include a table
+ * constructed from more than single dm-crypt segment. Therefore transfer
+ * mapping as is.
+ *
+ * If we're about to resume reencryption orig mapping has to be already validated for
+ * abrupt shutdown and rchunk_offset has to point on next chunk to reencrypt!
+ *
+ * TODO: in crypt_activate_by*
+ */
+ r = reencrypt_replace_device(cd, rh->overlay_name, rh->device_name, CRYPT_ACTIVATE_PRIVATE);
+ if (r) {
+ log_err(cd, _("Failed to activate overlay device %s with actual origin table."), rh->overlay_name);
+ goto err;
+ }
+
+ /* swap origin mapping to overlay device */
+ r = reencrypt_swap_backing_device(cd, rh->device_name, rh->overlay_name);
+ if (r) {
+ log_err(cd, _("Failed to load new mapping for device %s."), rh->device_name);
+ goto err;
+ }
+
+ /*
+ * Now the 'name' (unlocked luks) device is mapped via dm-linear to an overlay dev.
+ * The overlay device has a original live table of 'name' device in-before the swap.
+ */
+
+ return 0;
+err:
+ /* TODO: force error helper devices on error path */
+ dm_remove_device(cd, rh->overlay_name, 0);
+ dm_remove_device(cd, rh->hotzone_name, 0);
+
+ return r;
+}
+
+/* TODO:
+ * 1) audit error path. any error in this routine is fatal and should be unlikely.
+ * usually it would hint some collision with another userspace process touching
+ * dm devices directly.
+ */
+static int reenc_refresh_helper_devices(struct crypt_device *cd, const char *overlay, const char *hotzone)
+{
+ int r;
+
+ /*
+ * we have to explicitly suspend the overlay device before suspending
+ * the hotzone one. Resuming overlay device (aka switching tables) only
+ * after suspending the hotzone may lead to deadlock.
+ *
+ * In other words: always suspend the stack from top to bottom!
+ */
+ r = dm_suspend_device(cd, overlay, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH);
+ if (r) {
+ log_err(cd, _("Failed to suspend device %s."), overlay);
+ return r;
+ }
+
+ /* suspend HZ device */
+ r = dm_suspend_device(cd, hotzone, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH);
+ if (r) {
+ log_err(cd, _("Failed to suspend device %s."), hotzone);
+ return r;
+ }
+
+ /* resume overlay device: inactive table (with hotozne) -> live */
+ r = dm_resume_device(cd, overlay, DM_RESUME_PRIVATE);
+ if (r)
+ log_err(cd, _("Failed to resume device %s."), overlay);
+
+ return r;
+}
+
+static int reencrypt_refresh_overlay_devices(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ const char *overlay,
+ const char *hotzone,
+ struct volume_key *vks,
+ uint64_t device_size,
+ uint32_t flags)
+{
+ int r = reencrypt_load_overlay_device(cd, hdr, overlay, hotzone, vks, device_size, flags);
+ if (r) {
+ log_err(cd, _("Failed to reload device %s."), overlay);
+ return REENC_ERR;
+ }
+
+ r = reenc_refresh_helper_devices(cd, overlay, hotzone);
+ if (r) {
+ log_err(cd, _("Failed to refresh reencryption devices stack."));
+ return REENC_ROLLBACK;
+ }
+
+ return REENC_OK;
+}
+
+static int reencrypt_move_data(struct crypt_device *cd,
+ int devfd,
+ uint64_t data_shift,
+ crypt_reencrypt_mode_info mode)
+{
+ void *buffer;
+ int r;
+ ssize_t ret;
+ uint64_t buffer_len, offset,
+ read_offset = (mode == CRYPT_REENCRYPT_ENCRYPT ? 0 : data_shift);
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ offset = json_segment_get_offset(LUKS2_get_segment_jobj(hdr, 0), 0);
+ buffer_len = json_segment_get_size(LUKS2_get_segment_jobj(hdr, 0), 0);
+ if (!buffer_len || buffer_len > data_shift)
+ return -EINVAL;
+
+ if (posix_memalign(&buffer, device_alignment(crypt_data_device(cd)), buffer_len))
+ return -ENOMEM;
+
+ ret = read_lseek_blockwise(devfd,
+ device_block_size(cd, crypt_data_device(cd)),
+ device_alignment(crypt_data_device(cd)),
+ buffer, buffer_len, read_offset);
+ if (ret < 0 || (uint64_t)ret != buffer_len) {
+ log_dbg(cd, "Failed to read data at offset %" PRIu64 " (size: %zu)",
+ read_offset, buffer_len);
+ r = -EIO;
+ goto out;
+ }
+
+ log_dbg(cd, "Going to write %" PRIu64 " bytes read at offset %" PRIu64 " to new offset %" PRIu64,
+ buffer_len, read_offset, offset);
+ ret = write_lseek_blockwise(devfd,
+ device_block_size(cd, crypt_data_device(cd)),
+ device_alignment(crypt_data_device(cd)),
+ buffer, buffer_len, offset);
+ if (ret < 0 || (uint64_t)ret != buffer_len) {
+ log_dbg(cd, "Failed to write data at offset %" PRIu64 " (size: %zu)",
+ offset, buffer_len);
+ r = -EIO;
+ goto out;
+ }
+
+ r = 0;
+out:
+ crypt_safe_memzero(buffer, buffer_len);
+ free(buffer);
+ return r;
+}
+
+static int reencrypt_make_backup_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot_new,
+ const char *cipher,
+ uint64_t data_offset,
+ const struct crypt_params_reencrypt *params)
+{
+ int r, segment, moved_segment = -1, digest_old = -1, digest_new = -1;
+ json_object *jobj_tmp, *jobj_segment_new = NULL, *jobj_segment_old = NULL, *jobj_segment_bcp = NULL;
+ uint32_t sector_size = params->luks2 ? params->luks2->sector_size : SECTOR_SIZE;
+ uint64_t segment_offset, tmp, data_shift = params->data_shift << SECTOR_SHIFT,
+ device_size = params->device_size << SECTOR_SHIFT;
+
+ if (params->mode != CRYPT_REENCRYPT_DECRYPT) {
+ digest_new = LUKS2_digest_by_keyslot(hdr, keyslot_new);
+ if (digest_new < 0)
+ return -EINVAL;
+ }
+
+ if (params->mode != CRYPT_REENCRYPT_ENCRYPT) {
+ digest_old = LUKS2_digest_by_segment(hdr, CRYPT_DEFAULT_SEGMENT);
+ if (digest_old < 0)
+ return -EINVAL;
+ }
+
+ segment = LUKS2_segment_first_unused_id(hdr);
+ if (segment < 0)
+ return -EINVAL;
+
+ if (params->flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT) {
+ if (json_object_copy(LUKS2_get_segment_jobj(hdr, 0), &jobj_segment_bcp)) {
+ r = -EINVAL;
+ goto err;
+ }
+ r = LUKS2_segment_set_flag(jobj_segment_bcp, "backup-moved-segment");
+ if (r)
+ goto err;
+ moved_segment = segment++;
+ json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), moved_segment, jobj_segment_bcp);
+ if (!strcmp(json_segment_type(jobj_segment_bcp), "crypt"))
+ LUKS2_digest_segment_assign(cd, hdr, moved_segment, digest_old, 1, 0);
+ }
+
+ /* FIXME: Add detection for case (digest old == digest new && old segment == new segment) */
+ if (digest_old >= 0) {
+ if (params->flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT) {
+ jobj_tmp = LUKS2_get_segment_jobj(hdr, 0);
+ if (!jobj_tmp) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ jobj_segment_old = json_segment_create_crypt(data_offset,
+ json_segment_get_iv_offset(jobj_tmp),
+ device_size ? &device_size : NULL,
+ json_segment_get_cipher(jobj_tmp),
+ json_segment_get_sector_size(jobj_tmp),
+ 0);
+ } else {
+ if (json_object_copy(LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT), &jobj_segment_old)) {
+ r = -EINVAL;
+ goto err;
+ }
+ }
+ } else if (params->mode == CRYPT_REENCRYPT_ENCRYPT) {
+ r = LUKS2_get_data_size(hdr, &tmp, NULL);
+ if (r)
+ goto err;
+
+ if (params->flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT)
+ jobj_segment_old = json_segment_create_linear(0, tmp ? &tmp : NULL, 0);
+ else
+ jobj_segment_old = json_segment_create_linear(data_offset, tmp ? &tmp : NULL, 0);
+ }
+
+ if (!jobj_segment_old) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ r = LUKS2_segment_set_flag(jobj_segment_old, "backup-previous");
+ if (r)
+ goto err;
+ json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), segment, jobj_segment_old);
+ jobj_segment_old = NULL;
+ if (digest_old >= 0)
+ LUKS2_digest_segment_assign(cd, hdr, segment, digest_old, 1, 0);
+ segment++;
+
+ if (digest_new >= 0) {
+ segment_offset = data_offset;
+ if (params->mode != CRYPT_REENCRYPT_ENCRYPT &&
+ modify_offset(&segment_offset, data_shift, params->direction)) {
+ r = -EINVAL;
+ goto err;
+ }
+ jobj_segment_new = json_segment_create_crypt(segment_offset,
+ crypt_get_iv_offset(cd),
+ NULL, cipher, sector_size, 0);
+ } else if (params->mode == CRYPT_REENCRYPT_DECRYPT) {
+ segment_offset = data_offset;
+ if (modify_offset(&segment_offset, data_shift, params->direction)) {
+ r = -EINVAL;
+ goto err;
+ }
+ jobj_segment_new = json_segment_create_linear(segment_offset, NULL, 0);
+ }
+
+ if (!jobj_segment_new) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ r = LUKS2_segment_set_flag(jobj_segment_new, "backup-final");
+ if (r)
+ goto err;
+ json_object_object_add_by_uint(LUKS2_get_segments_jobj(hdr), segment, jobj_segment_new);
+ jobj_segment_new = NULL;
+ if (digest_new >= 0)
+ LUKS2_digest_segment_assign(cd, hdr, segment, digest_new, 1, 0);
+
+ /* FIXME: also check occupied space by keyslot in shrunk area */
+ if (params->direction == CRYPT_REENCRYPT_FORWARD && data_shift &&
+ crypt_metadata_device(cd) == crypt_data_device(cd) &&
+ LUKS2_set_keyslots_size(hdr, json_segment_get_offset(reencrypt_segment_new(hdr), 0))) {
+ log_err(cd, _("Failed to set new keyslots area size."));
+ r = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+err:
+ json_object_put(jobj_segment_new);
+ json_object_put(jobj_segment_old);
+ return r;
+}
+
+static int reencrypt_verify_single_key(struct crypt_device *cd, int digest, struct volume_key *vks)
+{
+ struct volume_key *vk;
+
+ vk = crypt_volume_key_by_id(vks, digest);
+ if (!vk)
+ return -ENOENT;
+
+ if (LUKS2_digest_verify_by_digest(cd, digest, vk) != digest)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int reencrypt_verify_keys(struct crypt_device *cd,
+ int digest_old,
+ int digest_new,
+ struct volume_key *vks)
+{
+ int r;
+
+ if (digest_new >= 0 && (r = reencrypt_verify_single_key(cd, digest_new, vks)))
+ return r;
+
+ if (digest_old >= 0 && (r = reencrypt_verify_single_key(cd, digest_old, vks)))
+ return r;
+
+ return 0;
+}
+
+static int reencrypt_upload_single_key(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int digest,
+ struct volume_key *vks)
+{
+ struct volume_key *vk;
+
+ vk = crypt_volume_key_by_id(vks, digest);
+ if (!vk)
+ return -EINVAL;
+
+ return LUKS2_volume_key_load_in_keyring_by_digest(cd, vk, digest);
+}
+
+static int reencrypt_upload_keys(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int digest_old,
+ int digest_new,
+ struct volume_key *vks)
+{
+ int r;
+
+ if (!crypt_use_keyring_for_vk(cd))
+ return 0;
+
+ if (digest_new >= 0 && !crypt_is_cipher_null(reencrypt_segment_cipher_new(hdr)) &&
+ (r = reencrypt_upload_single_key(cd, hdr, digest_new, vks)))
+ return r;
+
+ if (digest_old >= 0 && !crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr)) &&
+ (r = reencrypt_upload_single_key(cd, hdr, digest_old, vks))) {
+ crypt_drop_keyring_key(cd, vks);
+ return r;
+ }
+
+ return 0;
+}
+
+static int reencrypt_verify_and_upload_keys(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int digest_old,
+ int digest_new,
+ struct volume_key *vks)
+{
+ int r;
+
+ r = reencrypt_verify_keys(cd, digest_old, digest_new, vks);
+ if (r)
+ return r;
+
+ r = reencrypt_upload_keys(cd, hdr, digest_old, digest_new, vks);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+static int reencrypt_verify_checksum_params(struct crypt_device *cd,
+ const struct crypt_params_reencrypt *params)
+{
+ size_t len;
+ struct crypt_hash *ch;
+
+ assert(params);
+
+ if (!params->hash)
+ return -EINVAL;
+
+ len = strlen(params->hash);
+ if (!len || len > (LUKS2_CHECKSUM_ALG_L - 1))
+ return -EINVAL;
+
+ if (crypt_hash_size(params->hash) <= 0)
+ return -EINVAL;
+
+ if (crypt_hash_init(&ch, params->hash)) {
+ log_err(cd, _("Hash algorithm %s is not available."), params->hash);
+ return -EINVAL;
+ }
+ /* We just check for alg availability */
+ crypt_hash_destroy(ch);
+
+ return 0;
+}
+
+static int reencrypt_verify_datashift_params(struct crypt_device *cd,
+ const struct crypt_params_reencrypt *params,
+ uint32_t sector_size)
+{
+ assert(params);
+
+ if (!params->data_shift)
+ return -EINVAL;
+ if (MISALIGNED(params->data_shift, sector_size >> SECTOR_SHIFT)) {
+ log_err(cd, _("Data shift value is not aligned to encryption sector size (%" PRIu32 " bytes)."),
+ sector_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int reencrypt_verify_resilience_params(struct crypt_device *cd,
+ const struct crypt_params_reencrypt *params,
+ uint32_t sector_size, bool move_first_segment)
+{
+ /* no change requested */
+ if (!params || !params->resilience)
+ return 0;
+
+ if (!strcmp(params->resilience, "journal"))
+ return (params->data_shift || move_first_segment) ? -EINVAL : 0;
+ else if (!strcmp(params->resilience, "none"))
+ return (params->data_shift || move_first_segment) ? -EINVAL : 0;
+ else if (!strcmp(params->resilience, "datashift"))
+ return reencrypt_verify_datashift_params(cd, params, sector_size);
+ else if (!strcmp(params->resilience, "checksum")) {
+ if (params->data_shift || move_first_segment)
+ return -EINVAL;
+ return reencrypt_verify_checksum_params(cd, params);
+ } else if (!strcmp(params->resilience, "datashift-checksum")) {
+ if (!move_first_segment ||
+ reencrypt_verify_datashift_params(cd, params, sector_size))
+ return -EINVAL;
+ return reencrypt_verify_checksum_params(cd, params);
+ } else if (!strcmp(params->resilience, "datashift-journal")) {
+ if (!move_first_segment)
+ return -EINVAL;
+ return reencrypt_verify_datashift_params(cd, params, sector_size);
+ }
+
+ log_err(cd, _("Unsupported resilience mode %s"), params->resilience);
+ return -EINVAL;
+}
+
+static int reencrypt_decrypt_with_datashift_init(struct crypt_device *cd,
+ const char *name,
+ struct luks2_hdr *hdr,
+ int reencrypt_keyslot,
+ uint32_t sector_size,
+ uint64_t data_size,
+ uint64_t data_offset,
+ const char *passphrase,
+ size_t passphrase_size,
+ int keyslot_old,
+ const struct crypt_params_reencrypt *params,
+ struct volume_key **vks)
+{
+ bool clear_table = false;
+ int r, devfd = -1;
+ uint64_t data_shift, max_moved_segment_length, moved_segment_length;
+ struct reenc_protection check_rp = {};
+ struct crypt_dm_active_device dmd_target, dmd_source = {
+ .uuid = crypt_get_uuid(cd),
+ .flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */
+ };
+ json_object *jobj_segments_old;
+
+ assert(hdr);
+ assert(params);
+ assert(params->resilience);
+ assert(params->data_shift);
+ assert(vks);
+
+ if (!data_offset)
+ return -EINVAL;
+
+ if (params->max_hotzone_size > params->data_shift) {
+ log_err(cd, _("Moved segment size can not be greater than data shift value."));
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Initializing decryption with datashift.");
+
+ data_shift = params->data_shift << SECTOR_SHIFT;
+
+ /*
+ * In offline mode we must perform data move with exclusively opened data
+ * device in order to exclude LUKS2 decryption process and filesystem mount.
+ */
+ if (name)
+ devfd = device_open(cd, crypt_data_device(cd), O_RDWR);
+ else
+ devfd = device_open_excl(cd, crypt_data_device(cd), O_RDWR);
+ if (devfd < 0)
+ return -EINVAL;
+
+ /* in-memory only */
+ moved_segment_length = params->max_hotzone_size << SECTOR_SHIFT;
+ if (!moved_segment_length)
+ moved_segment_length = data_shift < LUKS2_DEFAULT_NONE_REENCRYPTION_LENGTH ?
+ data_shift : LUKS2_DEFAULT_NONE_REENCRYPTION_LENGTH;
+
+ if (moved_segment_length > data_size)
+ moved_segment_length = data_size;
+
+ r = reencrypt_set_decrypt_shift_segments(cd, hdr, data_size,
+ moved_segment_length,
+ params->direction);
+ if (r)
+ goto out;
+
+ r = reencrypt_make_backup_segments(cd, hdr, CRYPT_ANY_SLOT, NULL, data_offset, params);
+ if (r) {
+ log_dbg(cd, "Failed to create reencryption backup device segments.");
+ goto out;
+ }
+
+ r = reencrypt_verify_resilience_params(cd, params, sector_size, true);
+ if (r < 0) {
+ log_err(cd, _("Invalid reencryption resilience parameters."));
+ goto out;
+ }
+
+ r = LUKS2_keyslot_reencrypt_allocate(cd, hdr, reencrypt_keyslot,
+ params, reencrypt_get_alignment(cd, hdr));
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_reencrypt_load(cd, hdr, reencrypt_keyslot, &check_rp, false);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_reencrypt_max_hotzone_size(cd, hdr, &check_rp,
+ reencrypt_keyslot,
+ &max_moved_segment_length);
+ if (r < 0)
+ goto out;
+
+ LUKS2_reencrypt_protection_erase(&check_rp);
+
+ if (moved_segment_length > max_moved_segment_length) {
+ log_err(cd, _("Moved segment too large. Requested size %" PRIu64 ", available space for: %" PRIu64 "."),
+ moved_segment_length, max_moved_segment_length);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, CRYPT_ANY_SLOT,
+ passphrase, passphrase_size, vks);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, LUKS2_DECRYPT_DATASHIFT_REQ_VERSION, *vks);
+ if (r < 0)
+ goto out;
+
+ if (name) {
+ r = reencrypt_verify_and_upload_keys(cd, hdr,
+ LUKS2_reencrypt_digest_old(hdr),
+ LUKS2_reencrypt_digest_new(hdr),
+ *vks);
+ if (r)
+ goto out;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE |
+ DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY |
+ DM_ACTIVE_CRYPT_CIPHER, &dmd_target);
+ if (r < 0)
+ goto out;
+
+ jobj_segments_old = reencrypt_segments_old(hdr);
+ if (!jobj_segments_old) {
+ r = -EINVAL;
+ goto out;
+ }
+ r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, jobj_segments_old, &dmd_source);
+ if (!r) {
+ r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target);
+ if (r)
+ log_err(cd, _("Mismatching parameters on device %s."), name);
+ }
+ json_object_put(jobj_segments_old);
+
+ dm_targets_free(cd, &dmd_source);
+ dm_targets_free(cd, &dmd_target);
+ free(CONST_CAST(void*)dmd_target.uuid);
+
+ if (r)
+ goto out;
+
+ dmd_source.size = dmd_target.size;
+ r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source);
+ if (!r) {
+ r = dm_reload_device(cd, name, &dmd_source, dmd_target.flags, 0);
+ if (r)
+ log_err(cd, _("Failed to reload device %s."), name);
+ else
+ clear_table = true;
+ }
+
+ dm_targets_free(cd, &dmd_source);
+
+ if (r)
+ goto out;
+ }
+
+ if (name) {
+ r = dm_suspend_device(cd, name, DM_SUSPEND_SKIP_LOCKFS);
+ if (r) {
+ log_err(cd, _("Failed to suspend device %s."), name);
+ goto out;
+ }
+ }
+
+ if (reencrypt_move_data(cd, devfd, data_shift, params->mode)) {
+ r = -EIO;
+ goto out;
+ }
+
+ /* This must be first and only write in LUKS2 metadata during _reencrypt_init */
+ r = reencrypt_update_flag(cd, LUKS2_DECRYPT_DATASHIFT_REQ_VERSION, true, true);
+ if (r) {
+ log_dbg(cd, "Failed to set online-reencryption requirement.");
+ r = -EINVAL;
+ } else
+ r = reencrypt_keyslot;
+out:
+ if (r < 0 && clear_table && dm_clear_device(cd, name))
+ log_err(cd, _("Failed to clear table."));
+ else if (clear_table && dm_resume_device(cd, name, DM_SUSPEND_SKIP_LOCKFS))
+ log_err(cd, _("Failed to resume device %s."), name);
+
+ device_release_excl(cd, crypt_data_device(cd));
+ if (r < 0 && LUKS2_hdr_rollback(cd, hdr) < 0)
+ log_dbg(cd, "Failed to rollback LUKS2 metadata after failure.");
+
+ return r;
+}
+
+/* This function must be called with metadata lock held */
+static int reencrypt_init(struct crypt_device *cd,
+ const char *name,
+ struct luks2_hdr *hdr,
+ const char *passphrase,
+ size_t passphrase_size,
+ int keyslot_old,
+ int keyslot_new,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct crypt_params_reencrypt *params,
+ struct volume_key **vks)
+{
+ bool move_first_segment;
+ char _cipher[128];
+ uint32_t check_sector_size, new_sector_size, old_sector_size;
+ int r, reencrypt_keyslot, devfd = -1;
+ uint64_t data_offset, data_size = 0;
+ struct crypt_dm_active_device dmd_target, dmd_source = {
+ .uuid = crypt_get_uuid(cd),
+ .flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */
+ };
+
+ assert(cd);
+ assert(hdr);
+
+ if (!params || !params->resilience || params->mode > CRYPT_REENCRYPT_DECRYPT)
+ return -EINVAL;
+
+ if (params->mode != CRYPT_REENCRYPT_DECRYPT &&
+ (!params->luks2 || !(cipher && cipher_mode) || keyslot_new < 0))
+ return -EINVAL;
+
+ log_dbg(cd, "Initializing reencryption (mode: %s) in LUKS2 metadata.",
+ crypt_reencrypt_mode_to_str(params->mode));
+
+ move_first_segment = (params->flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT);
+
+ old_sector_size = LUKS2_get_sector_size(hdr);
+
+ /* implicit sector size 512 for decryption */
+ new_sector_size = params->luks2 ? params->luks2->sector_size : SECTOR_SIZE;
+ if (new_sector_size < SECTOR_SIZE || new_sector_size > MAX_SECTOR_SIZE ||
+ NOTPOW2(new_sector_size)) {
+ log_err(cd, _("Unsupported encryption sector size."));
+ return -EINVAL;
+ }
+ /* check the larger encryption sector size only */
+ check_sector_size = new_sector_size > old_sector_size ? new_sector_size : old_sector_size;
+
+ if (!cipher_mode || *cipher_mode == '\0')
+ r = snprintf(_cipher, sizeof(_cipher), "%s", cipher);
+ else
+ r = snprintf(_cipher, sizeof(_cipher), "%s-%s", cipher, cipher_mode);
+ if (r < 0 || (size_t)r >= sizeof(_cipher))
+ return -EINVAL;
+
+ data_offset = LUKS2_get_data_offset(hdr) << SECTOR_SHIFT;
+
+ r = device_check_access(cd, crypt_data_device(cd), DEV_OK);
+ if (r)
+ return r;
+
+ r = device_check_size(cd, crypt_data_device(cd), data_offset, 1);
+ if (r)
+ return r;
+
+ r = device_size(crypt_data_device(cd), &data_size);
+ if (r)
+ return r;
+
+ data_size -= data_offset;
+
+ if (params->device_size) {
+ if ((params->device_size << SECTOR_SHIFT) > data_size) {
+ log_err(cd, _("Reduced data size is larger than real device size."));
+ return -EINVAL;
+ } else
+ data_size = params->device_size << SECTOR_SHIFT;
+ }
+
+ if (MISALIGNED(data_size, check_sector_size)) {
+ log_err(cd, _("Data device is not aligned to encryption sector size (%" PRIu32 " bytes)."), check_sector_size);
+ return -EINVAL;
+ }
+
+ reencrypt_keyslot = LUKS2_keyslot_find_empty(cd, hdr, 0);
+ if (reencrypt_keyslot < 0) {
+ log_err(cd, _("All key slots full."));
+ return -EINVAL;
+ }
+
+ if (params->mode == CRYPT_REENCRYPT_DECRYPT && (params->data_shift > 0) && move_first_segment)
+ return reencrypt_decrypt_with_datashift_init(cd, name, hdr,
+ reencrypt_keyslot,
+ check_sector_size,
+ data_size,
+ data_offset,
+ passphrase,
+ passphrase_size,
+ keyslot_old,
+ params,
+ vks);
+
+
+ /*
+ * We must perform data move with exclusive open data device
+ * to exclude another cryptsetup process to colide with
+ * encryption initialization (or mount)
+ */
+ if (move_first_segment) {
+ if (data_size < (params->data_shift << SECTOR_SHIFT)) {
+ log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd)));
+ return -EINVAL;
+ }
+ if (params->data_shift < LUKS2_get_data_offset(hdr)) {
+ log_err(cd, _("Data shift (%" PRIu64 " sectors) is less than future data offset (%" PRIu64 " sectors)."),
+ params->data_shift, LUKS2_get_data_offset(hdr));
+ return -EINVAL;
+ }
+ devfd = device_open_excl(cd, crypt_data_device(cd), O_RDWR);
+ if (devfd < 0) {
+ if (devfd == -EBUSY)
+ log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."),
+ device_path(crypt_data_device(cd)));
+ return -EINVAL;
+ }
+ }
+
+ if (params->mode == CRYPT_REENCRYPT_ENCRYPT) {
+ /* in-memory only */
+ r = reencrypt_set_encrypt_segments(cd, hdr, data_size,
+ params->data_shift << SECTOR_SHIFT,
+ move_first_segment,
+ params->direction);
+ if (r)
+ goto out;
+ }
+
+ r = reencrypt_make_backup_segments(cd, hdr, keyslot_new, _cipher, data_offset, params);
+ if (r) {
+ log_dbg(cd, "Failed to create reencryption backup device segments.");
+ goto out;
+ }
+
+ r = reencrypt_verify_resilience_params(cd, params, check_sector_size, move_first_segment);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_reencrypt_allocate(cd, hdr, reencrypt_keyslot, params,
+ reencrypt_get_alignment(cd, hdr));
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphrase, passphrase_size, vks);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, LUKS2_REENCRYPT_REQ_VERSION, *vks);
+ if (r < 0)
+ goto out;
+
+ if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) {
+ r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
+ if (r)
+ goto out;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE |
+ DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY |
+ DM_ACTIVE_CRYPT_CIPHER, &dmd_target);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source);
+ if (!r) {
+ r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target);
+ if (r)
+ log_err(cd, _("Mismatching parameters on device %s."), name);
+ }
+
+ dm_targets_free(cd, &dmd_source);
+ dm_targets_free(cd, &dmd_target);
+ free(CONST_CAST(void*)dmd_target.uuid);
+
+ if (r)
+ goto out;
+ }
+
+ if (move_first_segment && reencrypt_move_data(cd, devfd, params->data_shift << SECTOR_SHIFT, params->mode)) {
+ r = -EIO;
+ goto out;
+ }
+
+ /* This must be first and only write in LUKS2 metadata during _reencrypt_init */
+ r = reencrypt_update_flag(cd, LUKS2_REENCRYPT_REQ_VERSION, true, true);
+ if (r) {
+ log_dbg(cd, "Failed to set online-reencryption requirement.");
+ r = -EINVAL;
+ } else
+ r = reencrypt_keyslot;
+out:
+ device_release_excl(cd, crypt_data_device(cd));
+ if (r < 0 && LUKS2_hdr_rollback(cd, hdr) < 0)
+ log_dbg(cd, "Failed to rollback LUKS2 metadata after failure.");
+
+ return r;
+}
+
+static int reencrypt_hotzone_protect_final(struct crypt_device *cd,
+ struct luks2_hdr *hdr, int reencrypt_keyslot,
+ const struct reenc_protection *rp,
+ const void *buffer, size_t buffer_len)
+{
+ const void *pbuffer;
+ size_t data_offset, len;
+ int r;
+
+ assert(hdr);
+ assert(rp);
+
+ if (rp->type == REENC_PROTECTION_NONE)
+ return 0;
+
+ if (rp->type == REENC_PROTECTION_CHECKSUM) {
+ log_dbg(cd, "Checksums hotzone resilience.");
+
+ for (data_offset = 0, len = 0; data_offset < buffer_len; data_offset += rp->p.csum.block_size, len += rp->p.csum.hash_size) {
+ if (crypt_hash_write(rp->p.csum.ch, (const char *)buffer + data_offset, rp->p.csum.block_size)) {
+ log_dbg(cd, "Failed to hash sector at offset %zu.", data_offset);
+ return -EINVAL;
+ }
+ if (crypt_hash_final(rp->p.csum.ch, (char *)rp->p.csum.checksums + len, rp->p.csum.hash_size)) {
+ log_dbg(cd, "Failed to finalize hash.");
+ return -EINVAL;
+ }
+ }
+ pbuffer = rp->p.csum.checksums;
+ } else if (rp->type == REENC_PROTECTION_JOURNAL) {
+ log_dbg(cd, "Journal hotzone resilience.");
+ len = buffer_len;
+ pbuffer = buffer;
+ } else if (rp->type == REENC_PROTECTION_DATASHIFT) {
+ log_dbg(cd, "Data shift hotzone resilience.");
+ return LUKS2_hdr_write(cd, hdr);
+ } else
+ return -EINVAL;
+
+ log_dbg(cd, "Going to store %zu bytes in reencrypt keyslot.", len);
+
+ r = LUKS2_keyslot_reencrypt_store(cd, hdr, reencrypt_keyslot, pbuffer, len);
+
+ return r > 0 ? 0 : r;
+}
+
+static int reencrypt_context_update(struct crypt_device *cd,
+ struct luks2_reencrypt *rh)
+{
+ if (rh->read < 0)
+ return -EINVAL;
+
+ if (rh->direction == CRYPT_REENCRYPT_BACKWARD) {
+ if (rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->mode == CRYPT_REENCRYPT_ENCRYPT) {
+ if (rh->offset)
+ rh->offset -= data_shift_value(&rh->rp);
+ if (rh->offset && (rh->offset < data_shift_value(&rh->rp))) {
+ rh->length = rh->offset;
+ rh->offset = data_shift_value(&rh->rp);
+ }
+ if (!rh->offset)
+ rh->length = data_shift_value(&rh->rp);
+ } else {
+ if (rh->offset < rh->length)
+ rh->length = rh->offset;
+ rh->offset -= rh->length;
+ }
+ } else if (rh->direction == CRYPT_REENCRYPT_FORWARD) {
+ rh->offset += (uint64_t)rh->read;
+ if (rh->device_size == rh->offset &&
+ rh->jobj_segment_moved &&
+ rh->mode == CRYPT_REENCRYPT_DECRYPT &&
+ rh->rp.type == REENC_PROTECTION_DATASHIFT) {
+ rh->offset = 0;
+ rh->length = json_segment_get_size(rh->jobj_segment_moved, 0);
+ }
+ /* it fails in-case of device_size < rh->offset later */
+ else if (rh->device_size - rh->offset < rh->length)
+ rh->length = rh->device_size - rh->offset;
+ } else
+ return -EINVAL;
+
+ if (rh->device_size < rh->offset) {
+ log_dbg(cd, "Calculated reencryption offset %" PRIu64 " is beyond device size %" PRIu64 ".", rh->offset, rh->device_size);
+ return -EINVAL;
+ }
+
+ rh->progress += (uint64_t)rh->read;
+
+ return 0;
+}
+
+static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
+ uint64_t device_size,
+ uint64_t max_hotzone_size,
+ uint64_t required_device_size,
+ struct volume_key *vks,
+ struct luks2_reencrypt **rh)
+{
+ int r;
+ struct luks2_reencrypt *tmp = NULL;
+ crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
+
+ if (ri == CRYPT_REENCRYPT_NONE) {
+ log_err(cd, _("Device not marked for LUKS2 reencryption."));
+ return -EINVAL;
+ } else if (ri == CRYPT_REENCRYPT_INVALID)
+ return -EINVAL;
+
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ if (r < 0)
+ return r;
+
+ if (ri == CRYPT_REENCRYPT_CLEAN)
+ r = reencrypt_load_clean(cd, hdr, device_size, max_hotzone_size, required_device_size, &tmp);
+ else if (ri == CRYPT_REENCRYPT_CRASH)
+ r = reencrypt_load_crashed(cd, hdr, device_size, &tmp);
+ else
+ r = -EINVAL;
+
+ if (r < 0 || !tmp) {
+ log_err(cd, _("Failed to load LUKS2 reencryption context."));
+ return r;
+ }
+
+ *rh = tmp;
+
+ return 0;
+}
+#endif
+static int reencrypt_lock_internal(struct crypt_device *cd, const char *uuid, struct crypt_lock_handle **reencrypt_lock)
+{
+ int r;
+ char *lock_resource;
+
+ if (!crypt_metadata_locking_enabled()) {
+ *reencrypt_lock = NULL;
+ return 0;
+ }
+
+ r = asprintf(&lock_resource, "LUKS2-reencryption-%s", uuid);
+ if (r < 0)
+ return -ENOMEM;
+ if (r < 20) {
+ free(lock_resource);
+ return -EINVAL;
+ }
+
+ r = crypt_write_lock(cd, lock_resource, false, reencrypt_lock);
+
+ free(lock_resource);
+
+ return r;
+}
+
+/* internal only */
+int LUKS2_reencrypt_lock_by_dm_uuid(struct crypt_device *cd, const char *dm_uuid,
+ struct crypt_lock_handle **reencrypt_lock)
+{
+ int r;
+ char hdr_uuid[37];
+ const char *uuid = crypt_get_uuid(cd);
+
+ if (!dm_uuid)
+ return -EINVAL;
+
+ if (!uuid) {
+ r = snprintf(hdr_uuid, sizeof(hdr_uuid), "%.8s-%.4s-%.4s-%.4s-%.12s",
+ dm_uuid + 6, dm_uuid + 14, dm_uuid + 18, dm_uuid + 22, dm_uuid + 26);
+ if (r < 0 || (size_t)r != (sizeof(hdr_uuid) - 1))
+ return -EINVAL;
+ } else if (crypt_uuid_cmp(dm_uuid, uuid))
+ return -EINVAL;
+
+ return reencrypt_lock_internal(cd, uuid, reencrypt_lock);
+}
+
+/* internal only */
+int LUKS2_reencrypt_lock(struct crypt_device *cd, struct crypt_lock_handle **reencrypt_lock)
+{
+ if (!cd || !crypt_get_type(cd) || strcmp(crypt_get_type(cd), CRYPT_LUKS2))
+ return -EINVAL;
+
+ return reencrypt_lock_internal(cd, crypt_get_uuid(cd), reencrypt_lock);
+}
+
+/* internal only */
+void LUKS2_reencrypt_unlock(struct crypt_device *cd, struct crypt_lock_handle *reencrypt_lock)
+{
+ crypt_unlock_internal(cd, reencrypt_lock);
+}
+#if USE_LUKS2_REENCRYPTION
+static int reencrypt_lock_and_verify(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct crypt_lock_handle **reencrypt_lock)
+{
+ int r;
+ crypt_reencrypt_info ri;
+ struct crypt_lock_handle *h;
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID) {
+ log_err(cd, _("Failed to get reencryption state."));
+ return -EINVAL;
+ }
+ if (ri < CRYPT_REENCRYPT_CLEAN) {
+ log_err(cd, _("Device is not in reencryption."));
+ return -EINVAL;
+ }
+
+ r = LUKS2_reencrypt_lock(cd, &h);
+ if (r < 0) {
+ if (r == -EBUSY)
+ log_err(cd, _("Reencryption process is already running."));
+ else
+ log_err(cd, _("Failed to acquire reencryption lock."));
+ return r;
+ }
+
+ /* With reencryption lock held, reload device context and verify metadata state */
+ r = crypt_load(cd, CRYPT_LUKS2, NULL);
+ if (r) {
+ LUKS2_reencrypt_unlock(cd, h);
+ return r;
+ }
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_CLEAN) {
+ *reencrypt_lock = h;
+ return 0;
+ }
+
+ LUKS2_reencrypt_unlock(cd, h);
+ log_err(cd, _("Cannot proceed with reencryption. Run reencryption recovery first."));
+ return -EINVAL;
+}
+
+static int reencrypt_load_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ int keyslot_old,
+ int keyslot_new,
+ struct volume_key **vks,
+ const struct crypt_params_reencrypt *params)
+{
+ int r, reencrypt_slot;
+ struct luks2_hdr *hdr;
+ struct crypt_lock_handle *reencrypt_lock;
+ struct luks2_reencrypt *rh;
+ const struct volume_key *vk;
+ size_t alignment;
+ uint32_t old_sector_size, new_sector_size, sector_size;
+ struct crypt_dm_active_device dmd_target, dmd_source = {
+ .uuid = crypt_get_uuid(cd),
+ .flags = CRYPT_ACTIVATE_SHARED /* turn off exclusive open checks */
+ };
+ uint64_t minimal_size, device_size, mapping_size = 0, required_size = 0,
+ max_hotzone_size = 0;
+ bool dynamic;
+ uint32_t flags = 0;
+
+ assert(cd);
+
+ hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ if (!hdr)
+ return -EINVAL;
+
+ log_dbg(cd, "Loading LUKS2 reencryption context.");
+
+ old_sector_size = reencrypt_get_sector_size_old(hdr);
+ new_sector_size = reencrypt_get_sector_size_new(hdr);
+ sector_size = new_sector_size > old_sector_size ? new_sector_size : old_sector_size;
+
+ r = reencrypt_verify_resilience_params(cd, params, sector_size,
+ LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0);
+ if (r < 0)
+ return r;
+
+ if (params) {
+ required_size = params->device_size;
+ max_hotzone_size = params->max_hotzone_size;
+ }
+
+ rh = crypt_get_luks2_reencrypt(cd);
+ if (rh) {
+ LUKS2_reencrypt_free(cd, rh);
+ crypt_set_luks2_reencrypt(cd, NULL);
+ rh = NULL;
+ }
+
+ r = reencrypt_lock_and_verify(cd, hdr, &reencrypt_lock);
+ if (r)
+ return r;
+
+ reencrypt_slot = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (reencrypt_slot < 0) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ /* From now on we hold reencryption lock */
+
+ if (LUKS2_get_data_size(hdr, &minimal_size, &dynamic)) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ /* some configurations provides fixed device size */
+ r = LUKS2_reencrypt_check_device_size(cd, hdr, minimal_size, &device_size, false, dynamic);
+ if (r) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ minimal_size >>= SECTOR_SHIFT;
+
+ r = reencrypt_verify_keys(cd, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
+ if (r == -ENOENT) {
+ log_dbg(cd, "Keys are not ready. Unlocking all volume keys.");
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphrase, passphrase_size, vks);
+ }
+
+ if (r < 0)
+ goto err;
+
+ if (name) {
+ r = reencrypt_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
+ if (r < 0)
+ goto err;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_UUID | DM_ACTIVE_DEVICE |
+ DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY |
+ DM_ACTIVE_CRYPT_CIPHER, &dmd_target);
+ if (r < 0)
+ goto err;
+ flags = dmd_target.flags;
+
+ /*
+ * By default reencryption code aims to retain flags from existing dm device.
+ * The keyring activation flag can not be inherited if original cipher is null.
+ *
+ * In this case override the flag based on decision made in reencrypt_upload_keys
+ * above. The code checks if new VK is eligible for keyring.
+ */
+ vk = crypt_volume_key_by_id(*vks, LUKS2_reencrypt_digest_new(hdr));
+ if (vk && vk->key_description && crypt_is_cipher_null(reencrypt_segment_cipher_old(hdr))) {
+ flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ dmd_source.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ }
+
+ r = LUKS2_assembly_multisegment_dmd(cd, hdr, *vks, LUKS2_get_segments_jobj(hdr), &dmd_source);
+ if (!r) {
+ r = crypt_compare_dm_devices(cd, &dmd_source, &dmd_target);
+ if (r)
+ log_err(cd, _("Mismatching parameters on device %s."), name);
+ }
+
+ dm_targets_free(cd, &dmd_source);
+ dm_targets_free(cd, &dmd_target);
+ free(CONST_CAST(void*)dmd_target.uuid);
+ if (r)
+ goto err;
+ mapping_size = dmd_target.size;
+ }
+
+ r = -EINVAL;
+ if (required_size && mapping_size && (required_size != mapping_size)) {
+ log_err(cd, _("Active device size and requested reencryption size don't match."));
+ goto err;
+ }
+
+ if (mapping_size)
+ required_size = mapping_size;
+
+ if (required_size) {
+ /* TODO: Add support for changing fixed minimal size in reencryption mda where possible */
+ if ((minimal_size && (required_size < minimal_size)) ||
+ (required_size > (device_size >> SECTOR_SHIFT)) ||
+ (!dynamic && (required_size != minimal_size)) ||
+ (old_sector_size > 0 && MISALIGNED(required_size, old_sector_size >> SECTOR_SHIFT)) ||
+ (new_sector_size > 0 && MISALIGNED(required_size, new_sector_size >> SECTOR_SHIFT))) {
+ log_err(cd, _("Illegal device size requested in reencryption parameters."));
+ goto err;
+ }
+ }
+
+ alignment = reencrypt_get_alignment(cd, hdr);
+
+ r = LUKS2_keyslot_reencrypt_update_needed(cd, hdr, reencrypt_slot, params, alignment);
+ if (r > 0) /* metadata update needed */
+ r = LUKS2_keyslot_reencrypt_update(cd, hdr, reencrypt_slot, params, alignment, *vks);
+ if (r < 0)
+ goto err;
+
+ r = reencrypt_load(cd, hdr, device_size, max_hotzone_size, required_size, *vks, &rh);
+ if (r < 0 || !rh)
+ goto err;
+
+ if (name && (r = reencrypt_context_set_names(rh, name)))
+ goto err;
+
+ /* Reassure device is not mounted and there's no dm mapping active */
+ if (!name && (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0)) {
+ log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd)));
+ r = -EBUSY;
+ goto err;
+ }
+ device_release_excl(cd, crypt_data_device(cd));
+
+ /* There's a race for dm device activation not managed by cryptsetup.
+ *
+ * 1) excl close
+ * 2) rogue dm device activation
+ * 3) one or more dm-crypt based wrapper activation
+ * 4) next excl open gets skipped due to 3) device from 2) remains undetected.
+ */
+ r = reencrypt_init_storage_wrappers(cd, hdr, rh, *vks);
+ if (r)
+ goto err;
+
+ /* If one of wrappers is based on dmcrypt fallback it already blocked mount */
+ if (!name && crypt_storage_wrapper_get_type(rh->cw1) != DMCRYPT &&
+ crypt_storage_wrapper_get_type(rh->cw2) != DMCRYPT) {
+ if (device_open_excl(cd, crypt_data_device(cd), O_RDONLY) < 0) {
+ log_err(cd,_("Failed to open %s in exclusive mode (already mapped or mounted)."), device_path(crypt_data_device(cd)));
+ r = -EBUSY;
+ goto err;
+ }
+ }
+
+ rh->flags = flags;
+
+ MOVE_REF(rh->vks, *vks);
+ MOVE_REF(rh->reenc_lock, reencrypt_lock);
+
+ crypt_set_luks2_reencrypt(cd, rh);
+
+ return 0;
+err:
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ LUKS2_reencrypt_free(cd, rh);
+ return r;
+}
+
+static int reencrypt_recovery_by_passphrase(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ int r;
+ crypt_reencrypt_info ri;
+ struct crypt_lock_handle *reencrypt_lock;
+
+ r = LUKS2_reencrypt_lock(cd, &reencrypt_lock);
+ if (r) {
+ if (r == -EBUSY)
+ log_err(cd, _("Reencryption in-progress. Cannot perform recovery."));
+ else
+ log_err(cd, _("Failed to get reencryption lock."));
+ return r;
+ }
+
+ if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) {
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ return r;
+ }
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID) {
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ return -EINVAL;
+ }
+
+ if (ri == CRYPT_REENCRYPT_CRASH) {
+ r = LUKS2_reencrypt_locked_recovery_by_passphrase(cd, keyslot_old, keyslot_new,
+ passphrase, passphrase_size, NULL);
+ if (r < 0)
+ log_err(cd, _("LUKS2 reencryption recovery failed."));
+ } else {
+ log_dbg(cd, "No LUKS2 reencryption recovery needed.");
+ r = 0;
+ }
+
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ return r;
+}
+
+static int reencrypt_repair_by_passphrase(
+ struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ int r;
+ struct crypt_lock_handle *reencrypt_lock;
+ struct luks2_reencrypt *rh;
+ crypt_reencrypt_info ri;
+ uint8_t requirement_version;
+ const char *resilience;
+ struct volume_key *vks = NULL;
+
+ log_dbg(cd, "Loading LUKS2 reencryption context for metadata repair.");
+
+ rh = crypt_get_luks2_reencrypt(cd);
+ if (rh) {
+ LUKS2_reencrypt_free(cd, rh);
+ crypt_set_luks2_reencrypt(cd, NULL);
+ rh = NULL;
+ }
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID)
+ return -EINVAL;
+
+ if (ri < CRYPT_REENCRYPT_CLEAN) {
+ log_err(cd, _("Device is not in reencryption."));
+ return -EINVAL;
+ }
+
+ r = LUKS2_reencrypt_lock(cd, &reencrypt_lock);
+ if (r < 0) {
+ if (r == -EBUSY)
+ log_err(cd, _("Reencryption process is already running."));
+ else
+ log_err(cd, _("Failed to acquire reencryption lock."));
+ return r;
+ }
+
+ /* With reencryption lock held, reload device context and verify metadata state */
+ r = crypt_load(cd, CRYPT_LUKS2, NULL);
+ if (r)
+ goto out;
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID) {
+ r = -EINVAL;
+ goto out;
+ }
+ if (ri == CRYPT_REENCRYPT_NONE) {
+ r = 0;
+ goto out;
+ }
+
+ resilience = reencrypt_resilience_type(hdr);
+ if (!resilience) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (reencrypt_mode(hdr) == CRYPT_REENCRYPT_DECRYPT &&
+ !strncmp(resilience, "datashift-", 10) &&
+ LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0)
+ requirement_version = LUKS2_DECRYPT_DATASHIFT_REQ_VERSION;
+ else
+ requirement_version = LUKS2_REENCRYPT_REQ_VERSION;
+
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new, passphrase, passphrase_size, &vks);
+ if (r < 0)
+ goto out;
+
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, requirement_version, vks);
+ crypt_free_volume_key(vks);
+ vks = NULL;
+ if (r < 0)
+ goto out;
+
+ /* replaces old online-reencrypt flag with updated version and commits metadata */
+ r = reencrypt_update_flag(cd, requirement_version, true, true);
+out:
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ crypt_free_volume_key(vks);
+ return r;
+
+}
+#endif
+static int reencrypt_init_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ int keyslot_old,
+ int keyslot_new,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct crypt_params_reencrypt *params)
+{
+#if USE_LUKS2_REENCRYPTION
+ int r;
+ crypt_reencrypt_info ri;
+ struct volume_key *vks = NULL;
+ uint32_t flags = params ? params->flags : 0;
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ /* short-circuit in reencryption metadata update and finish immediately. */
+ if (flags & CRYPT_REENCRYPT_REPAIR_NEEDED)
+ return reencrypt_repair_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size);
+
+ /* short-circuit in recovery and finish immediately. */
+ if (flags & CRYPT_REENCRYPT_RECOVERY)
+ return reencrypt_recovery_by_passphrase(cd, hdr, keyslot_old, keyslot_new, passphrase, passphrase_size);
+
+ if (cipher && !crypt_cipher_wrapped_key(cipher, cipher_mode)) {
+ r = crypt_keyslot_get_key_size(cd, keyslot_new);
+ if (r < 0)
+ return r;
+ r = LUKS2_check_cipher(cd, r, cipher, cipher_mode);
+ if (r < 0) {
+ log_err(cd, _("Unable to use cipher specification %s-%s for LUKS2."), cipher, cipher_mode);
+ return r;
+ }
+ }
+
+ r = LUKS2_device_write_lock(cd, hdr, crypt_metadata_device(cd));
+ if (r)
+ return r;
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID) {
+ device_write_unlock(cd, crypt_metadata_device(cd));
+ return -EINVAL;
+ }
+
+ if ((ri > CRYPT_REENCRYPT_NONE) && (flags & CRYPT_REENCRYPT_INITIALIZE_ONLY)) {
+ device_write_unlock(cd, crypt_metadata_device(cd));
+ log_err(cd, _("LUKS2 reencryption already initialized in metadata."));
+ return -EBUSY;
+ }
+
+ if (ri == CRYPT_REENCRYPT_NONE && !(flags & CRYPT_REENCRYPT_RESUME_ONLY)) {
+ r = reencrypt_init(cd, name, hdr, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params, &vks);
+ if (r < 0)
+ log_err(cd, _("Failed to initialize LUKS2 reencryption in metadata."));
+ } else if (ri > CRYPT_REENCRYPT_NONE) {
+ log_dbg(cd, "LUKS2 reencryption already initialized.");
+ r = 0;
+ }
+
+ device_write_unlock(cd, crypt_metadata_device(cd));
+
+ if (r < 0 || (flags & CRYPT_REENCRYPT_INITIALIZE_ONLY))
+ goto out;
+
+ r = reencrypt_load_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, &vks, params);
+out:
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vks);
+ crypt_free_volume_key(vks);
+ return r < 0 ? r : LUKS2_find_keyslot(hdr, "reencrypt");
+#else
+ log_err(cd, _("This operation is not supported for this device type."));
+ return -ENOTSUP;
+#endif
+}
+
+int crypt_reencrypt_init_by_keyring(struct crypt_device *cd,
+ const char *name,
+ const char *passphrase_description,
+ int keyslot_old,
+ int keyslot_new,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct crypt_params_reencrypt *params)
+{
+ int r;
+ char *passphrase;
+ size_t passphrase_size;
+
+ if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase_description)
+ return -EINVAL;
+ if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (params->flags & CRYPT_REENCRYPT_RESUME_ONLY))
+ return -EINVAL;
+
+ r = keyring_get_passphrase(passphrase_description, &passphrase, &passphrase_size);
+ if (r < 0) {
+ log_err(cd, _("Failed to read passphrase from keyring (error %d)."), r);
+ return -EINVAL;
+ }
+
+ r = reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params);
+
+ crypt_safe_memzero(passphrase, passphrase_size);
+ free(passphrase);
+
+ return r;
+}
+
+int crypt_reencrypt_init_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ int keyslot_old,
+ int keyslot_new,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct crypt_params_reencrypt *params)
+{
+ if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT) || !passphrase)
+ return -EINVAL;
+ if (params && (params->flags & CRYPT_REENCRYPT_INITIALIZE_ONLY) && (params->flags & CRYPT_REENCRYPT_RESUME_ONLY))
+ return -EINVAL;
+
+ return reencrypt_init_by_passphrase(cd, name, passphrase, passphrase_size, keyslot_old, keyslot_new, cipher, cipher_mode, params);
+}
+
+#if USE_LUKS2_REENCRYPTION
+static reenc_status_t reencrypt_step(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh,
+ uint64_t device_size,
+ bool online)
+{
+ int r;
+ struct reenc_protection *rp;
+
+ assert(hdr);
+ assert(rh);
+
+ rp = &rh->rp;
+
+ /* in memory only */
+ r = reencrypt_make_segments(cd, hdr, rh, device_size);
+ if (r)
+ return REENC_ERR;
+
+ r = reencrypt_assign_segments(cd, hdr, rh, 1, 0);
+ if (r) {
+ log_err(cd, _("Failed to set device segments for next reencryption hotzone."));
+ return REENC_ERR;
+ }
+
+ log_dbg(cd, "Reencrypting chunk starting at offset: %" PRIu64 ", size :%" PRIu64 ".", rh->offset, rh->length);
+ log_dbg(cd, "data_offset: %" PRIu64, crypt_get_data_offset(cd) << SECTOR_SHIFT);
+
+ if (!rh->offset && rp->type == REENC_PROTECTION_DATASHIFT && rh->jobj_segment_moved) {
+ crypt_storage_wrapper_destroy(rh->cw1);
+ log_dbg(cd, "Reinitializing old segment storage wrapper for moved segment.");
+ r = crypt_storage_wrapper_init(cd, &rh->cw1, crypt_data_device(cd),
+ LUKS2_reencrypt_get_data_offset_moved(hdr),
+ crypt_get_iv_offset(cd),
+ reencrypt_get_sector_size_old(hdr),
+ reencrypt_segment_cipher_old(hdr),
+ crypt_volume_key_by_id(rh->vks, rh->digest_old),
+ rh->wflags1);
+ if (r) {
+ log_err(cd, _("Failed to initialize old segment storage wrapper."));
+ return REENC_ROLLBACK;
+ }
+
+ if (rh->rp_moved_segment.type != REENC_PROTECTION_NOT_SET) {
+ log_dbg(cd, "Switching to moved segment resilience type.");
+ rp = &rh->rp_moved_segment;
+ }
+ }
+
+ r = reencrypt_hotzone_protect_ready(cd, rp);
+ if (r) {
+ log_err(cd, _("Failed to initialize hotzone protection."));
+ return REENC_ROLLBACK;
+ }
+
+ if (online) {
+ r = reencrypt_refresh_overlay_devices(cd, hdr, rh->overlay_name, rh->hotzone_name, rh->vks, rh->device_size, rh->flags);
+ /* Teardown overlay devices with dm-error. None bio shall pass! */
+ if (r != REENC_OK)
+ return r;
+ }
+
+ rh->read = crypt_storage_wrapper_read(rh->cw1, rh->offset, rh->reenc_buffer, rh->length);
+ if (rh->read < 0) {
+ /* severity normal */
+ log_err(cd, _("Failed to read hotzone area starting at %" PRIu64 "."), rh->offset);
+ return REENC_ROLLBACK;
+ }
+
+ /* metadata commit point */
+ r = reencrypt_hotzone_protect_final(cd, hdr, rh->reenc_keyslot, rp, rh->reenc_buffer, rh->read);
+ if (r < 0) {
+ /* severity normal */
+ log_err(cd, _("Failed to write reencryption resilience metadata."));
+ return REENC_ROLLBACK;
+ }
+
+ r = crypt_storage_wrapper_decrypt(rh->cw1, rh->offset, rh->reenc_buffer, rh->read);
+ if (r) {
+ /* severity normal */
+ log_err(cd, _("Decryption failed."));
+ return REENC_ROLLBACK;
+ }
+ if (rh->read != crypt_storage_wrapper_encrypt_write(rh->cw2, rh->offset, rh->reenc_buffer, rh->read)) {
+ /* severity fatal */
+ log_err(cd, _("Failed to write hotzone area starting at %" PRIu64 "."), rh->offset);
+ return REENC_FATAL;
+ }
+
+ if (rp->type != REENC_PROTECTION_NONE && crypt_storage_wrapper_datasync(rh->cw2)) {
+ log_err(cd, _("Failed to sync data."));
+ return REENC_FATAL;
+ }
+
+ /* metadata commit safe point */
+ r = reencrypt_assign_segments(cd, hdr, rh, 0, rp->type != REENC_PROTECTION_NONE);
+ if (r) {
+ /* severity fatal */
+ log_err(cd, _("Failed to update metadata after current reencryption hotzone completed."));
+ return REENC_FATAL;
+ }
+
+ if (online) {
+ /* severity normal */
+ log_dbg(cd, "Resuming device %s", rh->hotzone_name);
+ r = dm_resume_device(cd, rh->hotzone_name, DM_RESUME_PRIVATE);
+ if (r) {
+ log_err(cd, _("Failed to resume device %s."), rh->hotzone_name);
+ return REENC_ERR;
+ }
+ }
+
+ return REENC_OK;
+}
+
+static int reencrypt_erase_backup_segments(struct crypt_device *cd,
+ struct luks2_hdr *hdr)
+{
+ int segment = LUKS2_get_segment_id_by_flag(hdr, "backup-previous");
+ if (segment >= 0) {
+ if (LUKS2_digest_segment_assign(cd, hdr, segment, CRYPT_ANY_DIGEST, 0, 0))
+ return -EINVAL;
+ json_object_object_del_by_uint(LUKS2_get_segments_jobj(hdr), segment);
+ }
+ segment = LUKS2_get_segment_id_by_flag(hdr, "backup-final");
+ if (segment >= 0) {
+ if (LUKS2_digest_segment_assign(cd, hdr, segment, CRYPT_ANY_DIGEST, 0, 0))
+ return -EINVAL;
+ json_object_object_del_by_uint(LUKS2_get_segments_jobj(hdr), segment);
+ }
+ segment = LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment");
+ if (segment >= 0) {
+ if (LUKS2_digest_segment_assign(cd, hdr, segment, CRYPT_ANY_DIGEST, 0, 0))
+ return -EINVAL;
+ json_object_object_del_by_uint(LUKS2_get_segments_jobj(hdr), segment);
+ }
+
+ return 0;
+}
+
+static int reencrypt_wipe_unused_device_area(struct crypt_device *cd, struct luks2_reencrypt *rh)
+{
+ uint64_t offset, length, dev_size;
+ int r = 0;
+
+ assert(cd);
+ assert(rh);
+
+ if (rh->jobj_segment_moved && rh->mode == CRYPT_REENCRYPT_ENCRYPT) {
+ offset = json_segment_get_offset(rh->jobj_segment_moved, 0);
+ length = json_segment_get_size(rh->jobj_segment_moved, 0);
+ log_dbg(cd, "Wiping %" PRIu64 " bytes of backup segment data at offset %" PRIu64,
+ length, offset);
+ r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_RANDOM,
+ offset, length, 1024 * 1024, NULL, NULL);
+ }
+
+ if (r < 0)
+ return r;
+
+ if (rh->rp.type == REENC_PROTECTION_DATASHIFT && rh->direction == CRYPT_REENCRYPT_FORWARD) {
+ r = device_size(crypt_data_device(cd), &dev_size);
+ if (r < 0)
+ return r;
+
+ if (dev_size < data_shift_value(&rh->rp))
+ return -EINVAL;
+
+ offset = dev_size - data_shift_value(&rh->rp);
+ length = data_shift_value(&rh->rp);
+ log_dbg(cd, "Wiping %" PRIu64 " bytes of data at offset %" PRIu64,
+ length, offset);
+ r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_RANDOM,
+ offset, length, 1024 * 1024, NULL, NULL);
+ }
+
+ return r;
+}
+
+static int reencrypt_teardown_ok(struct crypt_device *cd, struct luks2_hdr *hdr, struct luks2_reencrypt *rh)
+{
+ int i, r;
+ uint32_t dmt_flags;
+ bool finished = !(rh->device_size > rh->progress);
+
+ if (rh->rp.type == REENC_PROTECTION_NONE &&
+ LUKS2_hdr_write(cd, hdr)) {
+ log_err(cd, _("Failed to write LUKS2 metadata."));
+ return -EINVAL;
+ }
+
+ if (rh->online) {
+ r = LUKS2_reload(cd, rh->device_name, rh->vks, rh->device_size, rh->flags);
+ if (r)
+ log_err(cd, _("Failed to reload device %s."), rh->device_name);
+ if (!r) {
+ r = dm_resume_device(cd, rh->device_name, DM_SUSPEND_SKIP_LOCKFS | DM_SUSPEND_NOFLUSH);
+ if (r)
+ log_err(cd, _("Failed to resume device %s."), rh->device_name);
+ }
+ dm_remove_device(cd, rh->overlay_name, 0);
+ dm_remove_device(cd, rh->hotzone_name, 0);
+
+ if (!r && finished && rh->mode == CRYPT_REENCRYPT_DECRYPT &&
+ !dm_flags(cd, DM_LINEAR, &dmt_flags) && (dmt_flags & DM_DEFERRED_SUPPORTED))
+ dm_remove_device(cd, rh->device_name, CRYPT_DEACTIVATE_DEFERRED);
+ }
+
+ if (finished) {
+ if (reencrypt_wipe_unused_device_area(cd, rh))
+ log_err(cd, _("Failed to wipe unused data device area."));
+ if (reencrypt_get_data_offset_new(hdr) && LUKS2_set_keyslots_size(hdr, reencrypt_get_data_offset_new(hdr)))
+ log_dbg(cd, "Failed to set new keyslots area size.");
+ if (rh->digest_old >= 0 && rh->digest_new != rh->digest_old)
+ for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++)
+ if (LUKS2_digest_by_keyslot(hdr, i) == rh->digest_old && crypt_keyslot_destroy(cd, i))
+ log_err(cd, _("Failed to remove unused (unbound) keyslot %d."), i);
+
+ if (reencrypt_erase_backup_segments(cd, hdr))
+ log_dbg(cd, "Failed to erase backup segments");
+
+ if (reencrypt_update_flag(cd, 0, false, false))
+ log_dbg(cd, "Failed to disable reencryption requirement flag.");
+
+ /* metadata commit point also removing reencryption flag on-disk */
+ if (crypt_keyslot_destroy(cd, rh->reenc_keyslot)) {
+ log_err(cd, _("Failed to remove reencryption keyslot."));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void reencrypt_teardown_fatal(struct crypt_device *cd, struct luks2_reencrypt *rh)
+{
+ log_err(cd, _("Fatal error while reencrypting chunk starting at %" PRIu64 ", %" PRIu64 " sectors long."),
+ (rh->offset >> SECTOR_SHIFT) + crypt_get_data_offset(cd), rh->length >> SECTOR_SHIFT);
+
+ if (rh->online) {
+ log_err(cd, _("Online reencryption failed."));
+ if (dm_status_suspended(cd, rh->hotzone_name) > 0) {
+ log_dbg(cd, "Hotzone device %s suspended, replacing with dm-error.", rh->hotzone_name);
+ if (dm_error_device(cd, rh->hotzone_name)) {
+ log_err(cd, _("Failed to replace suspended device %s with dm-error target."), rh->hotzone_name);
+ log_err(cd, _("Do not resume the device unless replaced with error target manually."));
+ }
+ }
+ }
+}
+
+static int reencrypt_teardown(struct crypt_device *cd, struct luks2_hdr *hdr,
+ struct luks2_reencrypt *rh, reenc_status_t rs, bool interrupted,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr)
+{
+ int r;
+
+ switch (rs) {
+ case REENC_OK:
+ if (progress && !interrupted)
+ progress(rh->device_size, rh->progress, usrptr);
+ r = reencrypt_teardown_ok(cd, hdr, rh);
+ break;
+ case REENC_FATAL:
+ reencrypt_teardown_fatal(cd, rh);
+ /* fall-through */
+ default:
+ r = -EIO;
+ }
+
+ /* this frees reencryption lock */
+ LUKS2_reencrypt_free(cd, rh);
+ crypt_set_luks2_reencrypt(cd, NULL);
+
+ return r;
+}
+#endif
+
+int crypt_reencrypt_run(
+ struct crypt_device *cd,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr)
+{
+#if USE_LUKS2_REENCRYPTION
+ int r;
+ crypt_reencrypt_info ri;
+ struct luks2_hdr *hdr;
+ struct luks2_reencrypt *rh;
+ reenc_status_t rs;
+ bool quit = false;
+
+ if (onlyLUKS2mask(cd, CRYPT_REQUIREMENT_ONLINE_REENCRYPT))
+ return -EINVAL;
+
+ hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri > CRYPT_REENCRYPT_CLEAN) {
+ log_err(cd, _("Cannot proceed with reencryption. Unexpected reencryption status."));
+ return -EINVAL;
+ }
+
+ rh = crypt_get_luks2_reencrypt(cd);
+ if (!rh || (!rh->reenc_lock && crypt_metadata_locking_enabled())) {
+ log_err(cd, _("Missing or invalid reencrypt context."));
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Resuming LUKS2 reencryption.");
+
+ if (rh->online && reencrypt_init_device_stack(cd, rh)) {
+ log_err(cd, _("Failed to initialize reencryption device stack."));
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->progress, rh->device_size);
+
+ rs = REENC_OK;
+
+ if (progress && progress(rh->device_size, rh->progress, usrptr))
+ quit = true;
+
+ while (!quit && (rh->device_size > rh->progress)) {
+ rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online);
+ if (rs != REENC_OK)
+ break;
+
+ log_dbg(cd, "Progress %" PRIu64 ", device_size %" PRIu64, rh->progress, rh->device_size);
+ if (progress && progress(rh->device_size, rh->progress, usrptr))
+ quit = true;
+
+ r = reencrypt_context_update(cd, rh);
+ if (r) {
+ log_err(cd, _("Failed to update reencryption context."));
+ rs = REENC_ERR;
+ break;
+ }
+
+ log_dbg(cd, "Next reencryption offset will be %" PRIu64 " sectors.", rh->offset);
+ log_dbg(cd, "Next reencryption chunk size will be %" PRIu64 " sectors).", rh->length);
+ }
+
+ r = reencrypt_teardown(cd, hdr, rh, rs, quit, progress, usrptr);
+ return r;
+#else
+ log_err(cd, _("This operation is not supported for this device type."));
+ return -ENOTSUP;
+#endif
+}
+
+int crypt_reencrypt(
+ struct crypt_device *cd,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr))
+{
+ return crypt_reencrypt_run(cd, progress, NULL);
+}
+#if USE_LUKS2_REENCRYPTION
+static int reencrypt_recovery(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint64_t device_size,
+ struct volume_key *vks)
+{
+ int r;
+ struct luks2_reencrypt *rh = NULL;
+
+ r = reencrypt_load(cd, hdr, device_size, 0, 0, vks, &rh);
+ if (r < 0) {
+ log_err(cd, _("Failed to load LUKS2 reencryption context."));
+ return r;
+ }
+
+ r = reencrypt_recover_segment(cd, hdr, rh, vks);
+ if (r < 0)
+ goto out;
+
+ if ((r = reencrypt_assign_segments(cd, hdr, rh, 0, 0)))
+ goto out;
+
+ r = reencrypt_context_update(cd, rh);
+ if (r) {
+ log_err(cd, _("Failed to update reencryption context."));
+ goto out;
+ }
+
+ r = reencrypt_teardown_ok(cd, hdr, rh);
+ if (!r)
+ r = LUKS2_hdr_write(cd, hdr);
+out:
+ LUKS2_reencrypt_free(cd, rh);
+
+ return r;
+}
+#endif
+/*
+ * use only for calculation of minimal data device size.
+ * The real data offset is taken directly from segments!
+ */
+int LUKS2_reencrypt_data_offset(struct luks2_hdr *hdr, bool blockwise)
+{
+ crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
+ uint64_t data_offset = LUKS2_get_data_offset(hdr);
+
+ if (ri == CRYPT_REENCRYPT_CLEAN && reencrypt_direction(hdr) == CRYPT_REENCRYPT_FORWARD)
+ data_offset += reencrypt_data_shift(hdr) >> SECTOR_SHIFT;
+
+ return blockwise ? data_offset : data_offset << SECTOR_SHIFT;
+}
+
+/* internal only */
+int LUKS2_reencrypt_check_device_size(struct crypt_device *cd, struct luks2_hdr *hdr,
+ uint64_t check_size, uint64_t *dev_size, bool activation, bool dynamic)
+{
+ int r;
+ uint64_t data_offset, real_size = 0;
+
+ if (reencrypt_direction(hdr) == CRYPT_REENCRYPT_BACKWARD &&
+ (LUKS2_get_segment_by_flag(hdr, "backup-moved-segment") || dynamic))
+ check_size += reencrypt_data_shift(hdr);
+
+ r = device_check_access(cd, crypt_data_device(cd), activation ? DEV_EXCL : DEV_OK);
+ if (r)
+ return r;
+
+ data_offset = LUKS2_reencrypt_data_offset(hdr, false);
+
+ r = device_check_size(cd, crypt_data_device(cd), data_offset, 1);
+ if (r)
+ return r;
+
+ r = device_size(crypt_data_device(cd), &real_size);
+ if (r)
+ return r;
+
+ log_dbg(cd, "Required minimal device size: %" PRIu64 " (%" PRIu64 " sectors)"
+ ", real device size: %" PRIu64 " (%" PRIu64 " sectors) "
+ "calculated device size: %" PRIu64 " (%" PRIu64 " sectors)",
+ check_size, check_size >> SECTOR_SHIFT, real_size, real_size >> SECTOR_SHIFT,
+ real_size - data_offset, (real_size - data_offset) >> SECTOR_SHIFT);
+
+ if (real_size < data_offset || (check_size && real_size < check_size)) {
+ log_err(cd, _("Device %s is too small."), device_path(crypt_data_device(cd)));
+ return -EINVAL;
+ }
+
+ *dev_size = real_size - data_offset;
+
+ return 0;
+}
+#if USE_LUKS2_REENCRYPTION
+/* returns keyslot number on success (>= 0) or negative errnor otherwise */
+int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size,
+ struct volume_key **vks)
+{
+ uint64_t minimal_size, device_size;
+ int keyslot, r = -EINVAL;
+ struct luks2_hdr *hdr = crypt_get_hdr(cd, CRYPT_LUKS2);
+ struct volume_key *vk = NULL, *_vks = NULL;
+
+ log_dbg(cd, "Entering reencryption crash recovery.");
+
+ if (LUKS2_get_data_size(hdr, &minimal_size, NULL))
+ return r;
+
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot_old, keyslot_new,
+ passphrase, passphrase_size, &_vks);
+ if (r < 0)
+ goto out;
+ keyslot = r;
+
+ if (crypt_use_keyring_for_vk(cd))
+ vk = _vks;
+
+ while (vk) {
+ r = LUKS2_volume_key_load_in_keyring_by_digest(cd, vk, crypt_volume_key_get_id(vk));
+ if (r < 0)
+ goto out;
+ vk = crypt_volume_key_next(vk);
+ }
+
+ if (LUKS2_reencrypt_check_device_size(cd, hdr, minimal_size, &device_size, true, false))
+ goto out;
+
+ r = reencrypt_recovery(cd, hdr, device_size, _vks);
+
+ if (!r && vks)
+ MOVE_REF(*vks, _vks);
+out:
+ if (r < 0)
+ crypt_drop_keyring_key(cd, _vks);
+ crypt_free_volume_key(_vks);
+
+ return r < 0 ? r : keyslot;
+}
+#endif
+crypt_reencrypt_info LUKS2_reencrypt_get_params(struct luks2_hdr *hdr,
+ struct crypt_params_reencrypt *params)
+{
+ crypt_reencrypt_info ri;
+ int digest;
+ uint8_t version;
+
+ if (params)
+ memset(params, 0, sizeof(*params));
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_NONE || ri == CRYPT_REENCRYPT_INVALID || !params)
+ return ri;
+
+ digest = LUKS2_digest_by_keyslot(hdr, LUKS2_find_keyslot(hdr, "reencrypt"));
+ if (digest < 0 && digest != -ENOENT)
+ return CRYPT_REENCRYPT_INVALID;
+
+ /*
+ * In case there's an old "online-reencrypt" requirement or reencryption
+ * keyslot digest is missing inform caller reencryption metadata requires repair.
+ */
+ if (!LUKS2_config_get_reencrypt_version(hdr, &version) &&
+ (version < 2 || digest == -ENOENT)) {
+ params->flags |= CRYPT_REENCRYPT_REPAIR_NEEDED;
+ return ri;
+ }
+
+ params->mode = reencrypt_mode(hdr);
+ params->direction = reencrypt_direction(hdr);
+ params->resilience = reencrypt_resilience_type(hdr);
+ params->hash = reencrypt_resilience_hash(hdr);
+ params->data_shift = reencrypt_data_shift(hdr) >> SECTOR_SHIFT;
+ params->max_hotzone_size = 0;
+ if (LUKS2_get_segment_id_by_flag(hdr, "backup-moved-segment") >= 0)
+ params->flags |= CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT;
+
+ return ri;
+}
diff --git a/lib/luks2/luks2_reencrypt_digest.c b/lib/luks2/luks2_reencrypt_digest.c
new file mode 100644
index 0000000..bc86f54
--- /dev/null
+++ b/lib/luks2/luks2_reencrypt_digest.c
@@ -0,0 +1,410 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, reencryption digest helpers
+ *
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2022-2023 Ondrej Kozina
+ * Copyright (C) 2022-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+#define MAX_STR 64
+
+struct jtype {
+ enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
+ json_object *jobj;
+ const char *id;
+};
+
+static size_t sr(struct jtype *j, uint8_t *ptr)
+{
+ json_object *jobj;
+ size_t len = 0;
+ uint64_t u64;
+ uint32_t u32;
+
+ if (!json_object_is_type(j->jobj, json_type_object))
+ return 0;
+
+ if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
+ return 0;
+
+ switch(j->type) {
+ case JSTR: /* JSON string */
+ if (!json_object_is_type(jobj, json_type_string))
+ return 0;
+ len = strlen(json_object_get_string(jobj));
+ if (len > MAX_STR)
+ return 0;
+ if (ptr)
+ memcpy(ptr, json_object_get_string(jobj), len);
+ break;
+ case JU64: /* Unsigned 64bit integer stored as string */
+ if (!json_object_is_type(jobj, json_type_string))
+ break;
+ len = sizeof(u64);
+ if (ptr) {
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
+ memcpy(ptr, &u64, len);
+ }
+ break;
+ case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
+ if (!json_object_is_type(jobj, json_type_string))
+ break;
+ if (!strcmp(json_object_get_string(jobj), "dynamic")) {
+ len = strlen("dynamic");
+ if (ptr)
+ memcpy(ptr, json_object_get_string(jobj), len);
+ } else {
+ len = sizeof(u64);
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
+ if (ptr)
+ memcpy(ptr, &u64, len);
+ }
+ break;
+ case JU32: /* Unsigned 32bit integer, stored as JSON int */
+ if (!json_object_is_type(jobj, json_type_int))
+ return 0;
+ len = sizeof(u32);
+ if (ptr) {
+ u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
+ memcpy(ptr, &u32, len);
+ }
+ break;
+ case JNONE:
+ return 0;
+ };
+
+ return len;
+}
+
+static size_t srs(struct jtype j[], uint8_t *ptr)
+{
+ size_t l, len = 0;
+
+ while(j->jobj) {
+ l = sr(j, ptr);
+ if (!l)
+ return 0;
+ len += l;
+ if (ptr)
+ ptr += l;
+ j++;
+ }
+ return len;
+}
+
+static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ struct jtype j[] = {
+ { JSTR, jobj_segment, "type" },
+ { JU64, jobj_segment, "offset" },
+ { JX64, jobj_segment, "size" },
+ {}
+ };
+ return srs(j, buffer);
+}
+
+static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ struct jtype j[] = {
+ { JSTR, jobj_segment, "type" },
+ { JU64, jobj_segment, "offset" },
+ { JX64, jobj_segment, "size" },
+ { JU64, jobj_segment, "iv_tweak" },
+ { JSTR, jobj_segment, "encryption" },
+ { JU32, jobj_segment, "sector_size" },
+ {}
+ };
+ return srs(j, buffer);
+}
+
+static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
+{
+ json_object *jobj_type;
+ const char *segment_type;
+
+ if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
+ return 0;
+
+ if (!(segment_type = json_object_get_string(jobj_type)))
+ return 0;
+
+ if (!strcmp(segment_type, "crypt"))
+ return segment_crypt_serialize(jobj_segment, buffer);
+ else if (!strcmp(segment_type, "linear"))
+ return segment_linear_serialize(jobj_segment, buffer);
+
+ return 0;
+}
+
+static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
+{
+ json_object *jobj_segment;
+ size_t l, len = 0;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ if (buffer)
+ buffer += l;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ if (buffer)
+ buffer += l;
+
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
+ if (jobj_segment) {
+ if (!(l = segment_serialize(jobj_segment, buffer)))
+ return 0;
+ len += l;
+ }
+
+ return len;
+}
+
+static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
+{
+ json_object *jobj_keyslot, *jobj_area, *jobj_type;
+ const char *area_type;
+ int keyslot_reencrypt;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return 0;
+
+ if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
+ return 0;
+
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
+ return 0;
+
+ if (!(area_type = json_object_get_string(jobj_type)))
+ return 0;
+
+ struct jtype j[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ {}
+ };
+ struct jtype j_datashift[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JU64, jobj_area, "shift_size" },
+ {}
+ };
+ struct jtype j_checksum[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JSTR, jobj_area, "hash" },
+ { JU32, jobj_area, "sector_size" },
+ {}
+ };
+ struct jtype j_datashift_checksum[] = {
+ { JSTR, jobj_keyslot, "mode" },
+ { JSTR, jobj_keyslot, "direction" },
+ { JSTR, jobj_area, "type" },
+ { JU64, jobj_area, "offset" },
+ { JU64, jobj_area, "size" },
+ { JSTR, jobj_area, "hash" },
+ { JU32, jobj_area, "sector_size" },
+ { JU64, jobj_area, "shift_size" },
+ {}
+ };
+
+ if (!strcmp(area_type, "datashift-checksum"))
+ return srs(j_datashift_checksum, buffer);
+ else if (!strcmp(area_type, "datashift") ||
+ !strcmp(area_type, "datashift-journal"))
+ return srs(j_datashift, buffer);
+ else if (!strcmp(area_type, "checksum"))
+ return srs(j_checksum, buffer);
+
+ return srs(j, buffer);
+}
+
+static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
+{
+ if (buffer)
+ memcpy(buffer, blob, length);
+
+ return length;
+}
+
+static int reencrypt_assembly_verification_data(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks,
+ uint8_t version,
+ struct volume_key **verification_data)
+{
+ uint8_t *ptr;
+ int digest_new, digest_old;
+ struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
+ size_t keyslot_data_len, segments_data_len, data_len = 2;
+
+ /*
+ * This works up to (including) version v207.
+ */
+ assert(version < (UINT8_MAX - 0x2F));
+
+ /* Keys - calculate length */
+ digest_new = LUKS2_reencrypt_digest_new(hdr);
+ digest_old = LUKS2_reencrypt_digest_old(hdr);
+
+ if (digest_old >= 0) {
+ vk_old = crypt_volume_key_by_id(vks, digest_old);
+ if (!vk_old) {
+ log_dbg(cd, "Key (digest id %d) required but not unlocked.", digest_old);
+ return -EINVAL;
+ }
+ data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
+ }
+
+ if (digest_new >= 0 && digest_old != digest_new) {
+ vk_new = crypt_volume_key_by_id(vks, digest_new);
+ if (!vk_new) {
+ log_dbg(cd, "Key (digest id %d) required but not unlocked.", digest_new);
+ return -EINVAL;
+ }
+ data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
+ }
+
+ if (data_len == 2)
+ return -EINVAL;
+
+ /* Metadata - calculate length */
+ if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
+ return -EINVAL;
+ data_len += keyslot_data_len;
+
+ if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
+ return -EINVAL;
+ data_len += segments_data_len;
+
+ /* Alloc and fill serialization data */
+ data = crypt_alloc_volume_key(data_len, NULL);
+ if (!data)
+ return -ENOMEM;
+
+ ptr = (uint8_t*)data->key;
+
+ *ptr++ = 0x76;
+ *ptr++ = 0x30 + version;
+
+ if (vk_old)
+ ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
+
+ if (vk_new)
+ ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
+
+ if (!reenc_keyslot_serialize(hdr, ptr))
+ goto bad;
+ ptr += keyslot_data_len;
+
+ if (!backup_segments_serialize(hdr, ptr))
+ goto bad;
+ ptr += segments_data_len;
+
+ assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
+
+ *verification_data = data;
+
+ return 0;
+bad:
+ crypt_free_volume_key(data);
+ return -EINVAL;
+}
+
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ uint8_t version,
+ struct volume_key *vks)
+{
+ int digest_reencrypt, keyslot_reencrypt, r;
+ struct volume_key *data;
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return keyslot_reencrypt;
+
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, version, &data);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
+ crypt_free_volume_key(data);
+ if (r < 0)
+ return r;
+
+ digest_reencrypt = r;
+
+ r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
+ if (r < 0)
+ return r;
+
+ return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
+}
+
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ struct volume_key *vks)
+{
+ int r, keyslot_reencrypt;
+ struct volume_key *data;
+ uint8_t version;
+
+ log_dbg(cd, "Verifying reencryption metadata.");
+
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
+ if (keyslot_reencrypt < 0)
+ return keyslot_reencrypt;
+
+ if (LUKS2_config_get_reencrypt_version(hdr, &version))
+ return -EINVAL;
+
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, version, &data);
+ if (r < 0)
+ return r;
+
+ r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
+ crypt_free_volume_key(data);
+
+ if (r < 0) {
+ if (r == -ENOENT)
+ log_dbg(cd, "Reencryption digest is missing.");
+ log_err(cd, _("Reencryption metadata is invalid."));
+ } else
+ log_dbg(cd, "Reencryption metadata verified.");
+
+ return r;
+}
diff --git a/lib/luks2/luks2_segment.c b/lib/luks2/luks2_segment.c
new file mode 100644
index 0000000..63e7c14
--- /dev/null
+++ b/lib/luks2/luks2_segment.c
@@ -0,0 +1,426 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, internal segment handling
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+/* use only on already validated 'segments' object */
+uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise)
+{
+ uint64_t tmp, min = blockwise ? UINT64_MAX >> SECTOR_SHIFT : UINT64_MAX;
+
+ if (!jobj_segments)
+ return 0;
+
+ json_object_object_foreach(jobj_segments, key, val) {
+ UNUSED(key);
+
+ if (json_segment_is_backup(val))
+ continue;
+
+ tmp = json_segment_get_offset(val, blockwise);
+
+ if (!tmp)
+ return tmp;
+
+ if (tmp < min)
+ min = tmp;
+ }
+
+ return min;
+}
+
+uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise)
+{
+ json_object *jobj;
+
+ if (!jobj_segment ||
+ !json_object_object_get_ex(jobj_segment, "offset", &jobj))
+ return 0;
+
+ return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
+}
+
+const char *json_segment_type(json_object *jobj_segment)
+{
+ json_object *jobj;
+
+ if (!jobj_segment ||
+ !json_object_object_get_ex(jobj_segment, "type", &jobj))
+ return NULL;
+
+ return json_object_get_string(jobj);
+}
+
+uint64_t json_segment_get_iv_offset(json_object *jobj_segment)
+{
+ json_object *jobj;
+
+ if (!jobj_segment ||
+ !json_object_object_get_ex(jobj_segment, "iv_tweak", &jobj))
+ return 0;
+
+ return crypt_jobj_get_uint64(jobj);
+}
+
+uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise)
+{
+ json_object *jobj;
+
+ if (!jobj_segment ||
+ !json_object_object_get_ex(jobj_segment, "size", &jobj))
+ return 0;
+
+ return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
+}
+
+const char *json_segment_get_cipher(json_object *jobj_segment)
+{
+ json_object *jobj;
+
+ /* FIXME: Pseudo "null" cipher should be handled elsewhere */
+ if (!jobj_segment ||
+ !json_object_object_get_ex(jobj_segment, "encryption", &jobj))
+ return "null";
+
+ return json_object_get_string(jobj);
+}
+
+uint32_t json_segment_get_sector_size(json_object *jobj_segment)
+{
+ json_object *jobj;
+ int i;
+
+ if (!jobj_segment ||
+ !json_object_object_get_ex(jobj_segment, "sector_size", &jobj))
+ return SECTOR_SIZE;
+
+ i = json_object_get_int(jobj);
+ return i < 0 ? SECTOR_SIZE : i;
+}
+
+static json_object *json_segment_get_flags(json_object *jobj_segment)
+{
+ json_object *jobj;
+
+ if (!jobj_segment || !(json_object_object_get_ex(jobj_segment, "flags", &jobj)))
+ return NULL;
+ return jobj;
+}
+
+bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
+{
+ int r, i;
+ json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment);
+
+ if (!jobj_flags)
+ return false;
+
+ for (i = 0; i < (int)json_object_array_length(jobj_flags); i++) {
+ jobj = json_object_array_get_idx(jobj_flags, i);
+ if (len)
+ r = strncmp(json_object_get_string(jobj), flag_str, len);
+ else
+ r = strcmp(json_object_get_string(jobj), flag_str);
+ if (!r)
+ return true;
+ }
+
+ return false;
+}
+
+bool json_segment_is_backup(json_object *jobj_segment)
+{
+ return json_segment_contains_flag(jobj_segment, "backup-", 7);
+}
+
+json_object *json_segments_get_segment(json_object *jobj_segments, int segment)
+{
+ json_object *jobj;
+ char segment_name[16];
+
+ if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1)
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj_segments, segment_name, &jobj))
+ return NULL;
+
+ return jobj;
+}
+
+unsigned json_segments_count(json_object *jobj_segments)
+{
+ unsigned count = 0;
+
+ if (!jobj_segments)
+ return 0;
+
+ json_object_object_foreach(jobj_segments, slot, val) {
+ UNUSED(slot);
+ if (!json_segment_is_backup(val))
+ count++;
+ }
+
+ return count;
+}
+
+static void _get_segment_or_id_by_flag(json_object *jobj_segments, const char *flag, unsigned id, void *retval)
+{
+ json_object *jobj_flags, **jobj_ret = (json_object **)retval;
+ int *ret = (int *)retval;
+
+ if (!flag)
+ return;
+
+ json_object_object_foreach(jobj_segments, key, value) {
+ if (!json_object_object_get_ex(value, "flags", &jobj_flags))
+ continue;
+ if (LUKS2_array_jobj(jobj_flags, flag)) {
+ if (id)
+ *ret = atoi(key);
+ else
+ *jobj_ret = value;
+ return;
+ }
+ }
+}
+
+void json_segment_remove_flag(json_object *jobj_segment, const char *flag)
+{
+ json_object *jobj_flags, *jobj_flags_new;
+
+ if (!jobj_segment)
+ return;
+
+ jobj_flags = json_segment_get_flags(jobj_segment);
+ if (!jobj_flags)
+ return;
+
+ jobj_flags_new = LUKS2_array_remove(jobj_flags, flag);
+ if (!jobj_flags_new)
+ return;
+
+ if (json_object_array_length(jobj_flags_new) <= 0) {
+ json_object_put(jobj_flags_new);
+ json_object_object_del(jobj_segment, "flags");
+ } else
+ json_object_object_add(jobj_segment, "flags", jobj_flags_new);
+}
+
+static json_object *_segment_create_generic(const char *type, uint64_t offset, const uint64_t *length)
+{
+ json_object *jobj = json_object_new_object();
+ if (!jobj)
+ return NULL;
+
+ json_object_object_add(jobj, "type", json_object_new_string(type));
+ json_object_object_add(jobj, "offset", crypt_jobj_new_uint64(offset));
+ json_object_object_add(jobj, "size", length ? crypt_jobj_new_uint64(*length) : json_object_new_string("dynamic"));
+
+ return jobj;
+}
+
+json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption)
+{
+ json_object *jobj = _segment_create_generic("linear", offset, length);
+ if (reencryption)
+ LUKS2_segment_set_flag(jobj, "in-reencryption");
+ return jobj;
+}
+
+json_object *json_segment_create_crypt(uint64_t offset,
+ uint64_t iv_offset, const uint64_t *length,
+ const char *cipher, uint32_t sector_size,
+ unsigned reencryption)
+{
+ json_object *jobj = _segment_create_generic("crypt", offset, length);
+ if (!jobj)
+ return NULL;
+
+ json_object_object_add(jobj, "iv_tweak", crypt_jobj_new_uint64(iv_offset));
+ json_object_object_add(jobj, "encryption", json_object_new_string(cipher));
+ json_object_object_add(jobj, "sector_size", json_object_new_int(sector_size));
+ if (reencryption)
+ LUKS2_segment_set_flag(jobj, "in-reencryption");
+
+ return jobj;
+}
+
+uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, int segment, unsigned blockwise)
+{
+ return json_segment_get_offset(LUKS2_get_segment_jobj(hdr, segment), blockwise);
+}
+
+int json_segments_segment_in_reencrypt(json_object *jobj_segments)
+{
+ json_object *jobj_flags;
+
+ json_object_object_foreach(jobj_segments, slot, val) {
+ if (!json_object_object_get_ex(val, "flags", &jobj_flags) ||
+ !LUKS2_array_jobj(jobj_flags, "in-reencryption"))
+ continue;
+
+ return atoi(slot);
+ }
+
+ return -1;
+}
+
+uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise)
+{
+ return json_segment_get_size(LUKS2_get_segment_jobj(hdr, segment), blockwise);
+}
+
+int LUKS2_segment_is_type(struct luks2_hdr *hdr, int segment, const char *type)
+{
+ return !strcmp(json_segment_type(LUKS2_get_segment_jobj(hdr, segment)) ?: "", type);
+}
+
+int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, const char *type)
+{
+ json_object *jobj_segments;
+ int last_found = -1;
+
+ if (!type)
+ return -1;
+
+ if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
+ return -1;
+
+ json_object_object_foreach(jobj_segments, slot, val) {
+ if (json_segment_is_backup(val))
+ continue;
+ if (strcmp(type, json_segment_type(val) ?: ""))
+ continue;
+
+ if (atoi(slot) > last_found)
+ last_found = atoi(slot);
+ }
+
+ return last_found;
+}
+
+int LUKS2_segment_by_type(struct luks2_hdr *hdr, const char *type)
+{
+ json_object *jobj_segments;
+ int first_found = -1;
+
+ if (!type)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
+ return -EINVAL;
+
+ json_object_object_foreach(jobj_segments, slot, val) {
+ if (json_segment_is_backup(val))
+ continue;
+ if (strcmp(type, json_segment_type(val) ?: ""))
+ continue;
+
+ if (first_found < 0)
+ first_found = atoi(slot);
+ else if (atoi(slot) < first_found)
+ first_found = atoi(slot);
+ }
+
+ return first_found;
+}
+
+int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr)
+{
+ json_object *jobj_segments;
+
+ if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
+ return -EINVAL;
+
+ return json_object_object_length(jobj_segments);
+}
+
+int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag)
+{
+ json_object *jobj_flags;
+
+ if (!jobj_segment || !flag)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_segment, "flags", &jobj_flags)) {
+ jobj_flags = json_object_new_array();
+ if (!jobj_flags)
+ return -ENOMEM;
+ json_object_object_add(jobj_segment, "flags", jobj_flags);
+ }
+
+ if (LUKS2_array_jobj(jobj_flags, flag))
+ return 0;
+
+ json_object_array_add(jobj_flags, json_object_new_string(flag));
+
+ return 0;
+}
+
+int LUKS2_segments_set(struct crypt_device *cd, struct luks2_hdr *hdr,
+ json_object *jobj_segments, int commit)
+{
+ json_object_object_add(hdr->jobj, "segments", jobj_segments);
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag)
+{
+ int ret = -ENOENT;
+ json_object *jobj_segments = LUKS2_get_segments_jobj(hdr);
+
+ if (jobj_segments)
+ _get_segment_or_id_by_flag(jobj_segments, flag, 1, &ret);
+
+ return ret;
+}
+
+json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag)
+{
+ json_object *jobj_segment = NULL,
+ *jobj_segments = LUKS2_get_segments_jobj(hdr);
+
+ if (jobj_segments)
+ _get_segment_or_id_by_flag(jobj_segments, flag, 0, &jobj_segment);
+
+ return jobj_segment;
+}
+
+/* compares key characteristics of both segments */
+bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2)
+{
+ const char *type = json_segment_type(jobj_segment_1);
+ const char *type2 = json_segment_type(jobj_segment_2);
+
+ if (!type || !type2)
+ return false;
+
+ if (strcmp(type, type2))
+ return false;
+
+ if (!strcmp(type, "crypt"))
+ return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) &&
+ !strcmp(json_segment_get_cipher(jobj_segment_1),
+ json_segment_get_cipher(jobj_segment_2)));
+
+ return true;
+}
diff --git a/lib/luks2/luks2_token.c b/lib/luks2/luks2_token.c
new file mode 100644
index 0000000..5f65918
--- /dev/null
+++ b/lib/luks2/luks2_token.c
@@ -0,0 +1,1043 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, token handling
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <ctype.h>
+#include <dlfcn.h>
+
+#include "luks2_internal.h"
+
+#if USE_EXTERNAL_TOKENS
+static bool external_tokens_enabled = true;
+#else
+static bool external_tokens_enabled = false;
+#endif
+
+static struct crypt_token_handler_internal token_handlers[LUKS2_TOKENS_MAX] = {
+ /* keyring builtin token */
+ {
+ .version = 1,
+ .u = {
+ .v1 = { .name = LUKS2_TOKEN_KEYRING,
+ .open = keyring_open,
+ .buffer_free = keyring_buffer_free,
+ .validate = keyring_validate,
+ .dump = keyring_dump }
+ }
+ }
+};
+
+void crypt_token_external_disable(void)
+{
+ external_tokens_enabled = false;
+}
+
+const char *crypt_token_external_path(void)
+{
+ return external_tokens_enabled ? EXTERNAL_LUKS2_TOKENS_PATH : NULL;
+}
+
+#if USE_EXTERNAL_TOKENS
+static void *token_dlvsym(struct crypt_device *cd,
+ void *handle,
+ const char *symbol,
+ const char *version)
+{
+ char *error;
+ void *sym;
+
+#ifdef HAVE_DLVSYM
+ log_dbg(cd, "Loading symbol %s@%s.", symbol, version);
+ sym = dlvsym(handle, symbol, version);
+#else
+ log_dbg(cd, "Loading default version of symbol %s.", symbol);
+ sym = dlsym(handle, symbol);
+#endif
+ error = dlerror();
+
+ if (error)
+ log_dbg(cd, "%s", error);
+
+ return sym;
+}
+#endif
+
+static bool token_validate_v1(struct crypt_device *cd, const crypt_token_handler *h)
+{
+ if (!h)
+ return false;
+
+ if (!h->name) {
+ log_dbg(cd, "Error: token handler does not provide name attribute.");
+ return false;
+ }
+
+ if (!h->open) {
+ log_dbg(cd, "Error: token handler does not provide open function.");
+ return false;
+ }
+
+ return true;
+}
+
+#if USE_EXTERNAL_TOKENS
+static bool token_validate_v2(struct crypt_device *cd, const struct crypt_token_handler_internal *h)
+{
+ if (!h)
+ return false;
+
+ if (!token_validate_v1(cd, &h->u.v1))
+ return false;
+
+ if (!h->u.v2.version) {
+ log_dbg(cd, "Error: token handler does not provide " CRYPT_TOKEN_ABI_VERSION " function.");
+ return false;
+ }
+
+ return true;
+}
+
+static bool external_token_name_valid(const char *name)
+{
+ if (!*name || strlen(name) > LUKS2_TOKEN_NAME_MAX)
+ return false;
+
+ while (*name) {
+ if (!isalnum(*name) && *name != '-' && *name != '_')
+ return false;
+ name++;
+ }
+
+ return true;
+}
+#endif
+
+static int
+crypt_token_load_external(struct crypt_device *cd, const char *name, struct crypt_token_handler_internal *ret)
+{
+#if USE_EXTERNAL_TOKENS
+ struct crypt_token_handler_v2 *token;
+ void *h;
+ char buf[PATH_MAX];
+ int r;
+
+ if (!external_tokens_enabled)
+ return -ENOTSUP;
+
+ if (!ret || !name)
+ return -EINVAL;
+
+ if (!external_token_name_valid(name)) {
+ log_dbg(cd, "External token name (%.*s) invalid.", LUKS2_TOKEN_NAME_MAX, name);
+ return -EINVAL;
+ }
+
+ token = &ret->u.v2;
+
+ r = snprintf(buf, sizeof(buf), "%s/libcryptsetup-token-%s.so", crypt_token_external_path(), name);
+ if (r < 0 || (size_t)r >= sizeof(buf))
+ return -EINVAL;
+
+ assert(*buf == '/');
+
+ log_dbg(cd, "Trying to load %s.", buf);
+
+ h = dlopen(buf, RTLD_LAZY);
+ if (!h) {
+ log_dbg(cd, "%s", dlerror());
+ return -EINVAL;
+ }
+ dlerror();
+
+ token->name = strdup(name);
+ token->open = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN, CRYPT_TOKEN_ABI_VERSION1);
+ token->buffer_free = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_BUFFER_FREE, CRYPT_TOKEN_ABI_VERSION1);
+ token->validate = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_VALIDATE, CRYPT_TOKEN_ABI_VERSION1);
+ token->dump = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_DUMP, CRYPT_TOKEN_ABI_VERSION1);
+ token->open_pin = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_OPEN_PIN, CRYPT_TOKEN_ABI_VERSION1);
+ token->version = token_dlvsym(cd, h, CRYPT_TOKEN_ABI_VERSION, CRYPT_TOKEN_ABI_VERSION1);
+
+ if (!token_validate_v2(cd, ret)) {
+ free(CONST_CAST(void *)token->name);
+ dlclose(h);
+ memset(token, 0, sizeof(*token));
+ return -EINVAL;
+ }
+
+ /* Token loaded, possible error here means only debug message fail and can be ignored */
+ r = snprintf(buf, sizeof(buf), "%s", token->version() ?: "");
+ if (r < 0 || (size_t)r >= sizeof(buf))
+ *buf = '\0';
+
+ log_dbg(cd, "Token handler %s-%s loaded successfully.", token->name, buf);
+
+ token->dlhandle = h;
+ ret->version = 2;
+
+ return 0;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int is_builtin_candidate(const char *type)
+{
+ return !strncmp(type, LUKS2_BUILTIN_TOKEN_PREFIX, LUKS2_BUILTIN_TOKEN_PREFIX_LEN);
+}
+
+static int crypt_token_find_free(struct crypt_device *cd, const char *name, int *index)
+{
+ int i;
+
+ if (is_builtin_candidate(name)) {
+ log_dbg(cd, "'" LUKS2_BUILTIN_TOKEN_PREFIX "' is reserved prefix for builtin tokens.");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++) {
+ if (!strcmp(token_handlers[i].u.v1.name, name)) {
+ log_dbg(cd, "Keyslot handler %s is already registered.", name);
+ return -EINVAL;
+ }
+ }
+
+ if (i == LUKS2_TOKENS_MAX)
+ return -EINVAL;
+
+ if (index)
+ *index = i;
+
+ return 0;
+}
+
+int crypt_token_register(const crypt_token_handler *handler)
+{
+ int i, r;
+
+ if (!token_validate_v1(NULL, handler))
+ return -EINVAL;
+
+ r = crypt_token_find_free(NULL, handler->name, &i);
+ if (r < 0)
+ return r;
+
+ token_handlers[i].version = 1;
+ token_handlers[i].u.v1 = *handler;
+ return 0;
+}
+
+void crypt_token_unload_external_all(struct crypt_device *cd)
+{
+#if USE_EXTERNAL_TOKENS
+ int i;
+
+ for (i = LUKS2_TOKENS_MAX - 1; i >= 0; i--) {
+ if (token_handlers[i].version < 2)
+ continue;
+
+ log_dbg(cd, "Unloading %s token handler.", token_handlers[i].u.v2.name);
+
+ free(CONST_CAST(void *)token_handlers[i].u.v2.name);
+
+ if (dlclose(CONST_CAST(void *)token_handlers[i].u.v2.dlhandle))
+ log_dbg(cd, "%s", dlerror());
+ }
+#endif
+}
+
+static const void
+*LUKS2_token_handler_type(struct crypt_device *cd, const char *type)
+{
+ int i;
+
+ for (i = 0; i < LUKS2_TOKENS_MAX && token_handlers[i].u.v1.name; i++)
+ if (!strcmp(token_handlers[i].u.v1.name, type))
+ return &token_handlers[i].u;
+
+ if (i >= LUKS2_TOKENS_MAX)
+ return NULL;
+
+ if (is_builtin_candidate(type))
+ return NULL;
+
+ if (crypt_token_load_external(cd, type, &token_handlers[i]))
+ return NULL;
+
+ return &token_handlers[i].u;
+}
+
+static const void
+*LUKS2_token_handler(struct crypt_device *cd, int token)
+{
+ struct luks2_hdr *hdr;
+ json_object *jobj1, *jobj2;
+
+ if (token < 0)
+ return NULL;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return NULL;
+
+ if (!(jobj1 = LUKS2_get_token_jobj(hdr, token)))
+ return NULL;
+
+ if (!json_object_object_get_ex(jobj1, "type", &jobj2))
+ return NULL;
+
+ return LUKS2_token_handler_type(cd, json_object_get_string(jobj2));
+}
+
+static int LUKS2_token_find_free(struct luks2_hdr *hdr)
+{
+ int i;
+
+ for (i = 0; i < LUKS2_TOKENS_MAX; i++)
+ if (!LUKS2_get_token_jobj(hdr, i))
+ return i;
+
+ return -EINVAL;
+}
+
+int LUKS2_token_create(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *json,
+ int commit)
+{
+ const crypt_token_handler *h;
+ json_object *jobj_tokens, *jobj_type, *jobj;
+ enum json_tokener_error jerr;
+ char num[16];
+
+ if (token == CRYPT_ANY_TOKEN) {
+ if (!json)
+ return -EINVAL;
+ token = LUKS2_token_find_free(hdr);
+ }
+
+ if (token < 0 || token >= LUKS2_TOKENS_MAX)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens))
+ return -EINVAL;
+
+ if (snprintf(num, sizeof(num), "%d", token) < 0)
+ return -EINVAL;
+
+ /* Remove token */
+ if (!json)
+ json_object_object_del(jobj_tokens, num);
+ else {
+
+ jobj = json_tokener_parse_verbose(json, &jerr);
+ if (!jobj) {
+ log_dbg(cd, "Token JSON parse failed.");
+ return -EINVAL;
+ }
+
+ if (LUKS2_token_validate(cd, hdr->jobj, jobj, num)) {
+ json_object_put(jobj);
+ return -EINVAL;
+ }
+
+ json_object_object_get_ex(jobj, "type", &jobj_type);
+ h = LUKS2_token_handler_type(cd, json_object_get_string(jobj_type));
+
+ if (is_builtin_candidate(json_object_get_string(jobj_type)) && !h) {
+ log_dbg(cd, "%s is builtin token candidate with missing handler",
+ json_object_get_string(jobj_type));
+ json_object_put(jobj);
+ return -EINVAL;
+ }
+
+ if (h && h->validate && h->validate(cd, json)) {
+ json_object_put(jobj);
+ log_dbg(cd, "Token type %s validation failed.", h->name);
+ return -EINVAL;
+ }
+
+ json_object_object_add(jobj_tokens, num, jobj);
+ if (LUKS2_check_json_size(cd, hdr)) {
+ log_dbg(cd, "Not enough space in header json area for new token.");
+ json_object_object_del(jobj_tokens, num);
+ return -ENOSPC;
+ }
+ }
+
+ if (commit)
+ return LUKS2_hdr_write(cd, hdr) ?: token;
+
+ return token;
+}
+
+crypt_token_info LUKS2_token_status(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char **type)
+{
+ const char *tmp;
+ const crypt_token_handler *th;
+ json_object *jobj_type, *jobj_token;
+
+ if (token < 0 || token >= LUKS2_TOKENS_MAX)
+ return CRYPT_TOKEN_INVALID;
+
+ if (!(jobj_token = LUKS2_get_token_jobj(hdr, token)))
+ return CRYPT_TOKEN_INACTIVE;
+
+ json_object_object_get_ex(jobj_token, "type", &jobj_type);
+ tmp = json_object_get_string(jobj_type);
+
+ if ((th = LUKS2_token_handler_type(cd, tmp))) {
+ if (type)
+ *type = th->name;
+ return is_builtin_candidate(tmp) ? CRYPT_TOKEN_INTERNAL : CRYPT_TOKEN_EXTERNAL;
+ }
+
+ if (type)
+ *type = tmp;
+
+ return is_builtin_candidate(tmp) ? CRYPT_TOKEN_INTERNAL_UNKNOWN : CRYPT_TOKEN_EXTERNAL_UNKNOWN;
+}
+
+static const char *token_json_to_string(json_object *jobj_token)
+{
+ return json_object_to_json_string_ext(jobj_token,
+ JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
+}
+
+static int token_is_usable(struct luks2_hdr *hdr, json_object *jobj_token, int segment,
+ crypt_keyslot_priority minimal_priority, bool requires_keyslot)
+{
+ crypt_keyslot_priority keyslot_priority;
+ json_object *jobj_array;
+ int i, keyslot, len, r = -ENOENT;
+
+ if (!jobj_token)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_token, "keyslots", &jobj_array))
+ return -EINVAL;
+
+ if (segment < 0 && segment != CRYPT_ANY_SEGMENT)
+ return -EINVAL;
+
+ /* no assigned keyslot returns -ENOENT even for CRYPT_ANY_SEGMENT */
+ len = json_object_array_length(jobj_array);
+ if (len < 0)
+ return -ENOENT;
+
+ if (!requires_keyslot)
+ return 0;
+
+ if (!len)
+ return -ENOENT;
+
+ for (i = 0; i < len; i++) {
+ keyslot = atoi(json_object_get_string(json_object_array_get_idx(jobj_array, i)));
+
+ keyslot_priority = LUKS2_keyslot_priority_get(hdr, keyslot);
+ if (keyslot_priority == CRYPT_SLOT_PRIORITY_INVALID)
+ return -EINVAL;
+
+ if (keyslot_priority < minimal_priority)
+ continue;
+
+ r = LUKS2_keyslot_for_segment(hdr, keyslot, segment);
+ if (r != -ENOENT)
+ return r;
+ }
+
+ return r;
+}
+
+static int translate_errno(struct crypt_device *cd, int ret_val, const char *type)
+{
+ if ((ret_val > 0 || ret_val == -EINVAL || ret_val == -EPERM) && !is_builtin_candidate(type)) {
+ log_dbg(cd, "%s token handler returned %d. Changing to %d.", type, ret_val, -ENOENT);
+ ret_val = -ENOENT;
+ }
+
+ return ret_val;
+}
+
+static int token_open(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ json_object *jobj_token,
+ const char *type,
+ int segment,
+ crypt_keyslot_priority priority,
+ const char *pin,
+ size_t pin_size,
+ char **buffer,
+ size_t *buffer_len,
+ void *usrptr,
+ bool requires_keyslot)
+{
+ const struct crypt_token_handler_v2 *h;
+ json_object *jobj_type;
+ int r;
+
+ assert(token >= 0);
+ assert(jobj_token);
+ assert(priority >= 0);
+
+ if (type) {
+ if (!json_object_object_get_ex(jobj_token, "type", &jobj_type))
+ return -EINVAL;
+ if (strcmp(type, json_object_get_string(jobj_type)))
+ return -ENOENT;
+ }
+
+ r = token_is_usable(hdr, jobj_token, segment, priority, requires_keyslot);
+ if (r < 0) {
+ if (r == -ENOENT)
+ log_dbg(cd, "Token %d unusable for segment %d with desired keyslot priority %d.",
+ token, segment, priority);
+ return r;
+ }
+
+ if (!(h = LUKS2_token_handler(cd, token)))
+ return -ENOENT;
+
+ if (h->validate && h->validate(cd, token_json_to_string(jobj_token))) {
+ log_dbg(cd, "Token %d (%s) validation failed.", token, h->name);
+ return -ENOENT;
+ }
+
+ if (pin && !h->open_pin)
+ r = -ENOENT;
+ else if (pin)
+ r = translate_errno(cd, h->open_pin(cd, token, pin, pin_size, buffer, buffer_len, usrptr), h->name);
+ else
+ r = translate_errno(cd, h->open(cd, token, buffer, buffer_len, usrptr), h->name);
+ if (r < 0)
+ log_dbg(cd, "Token %d (%s) open failed with %d.", token, h->name, r);
+
+ return r;
+}
+
+static void LUKS2_token_buffer_free(struct crypt_device *cd,
+ int token,
+ void *buffer,
+ size_t buffer_len)
+{
+ const crypt_token_handler *h = LUKS2_token_handler(cd, token);
+
+ if (h && h->buffer_free)
+ h->buffer_free(buffer, buffer_len);
+ else {
+ crypt_safe_memzero(buffer, buffer_len);
+ free(buffer);
+ }
+}
+
+static bool break_loop_retval(int r)
+{
+ if (r == -ENOENT || r == -EPERM || r == -EAGAIN || r == -ENOANO)
+ return false;
+ return true;
+}
+
+static void update_return_errno(int r, int *stored)
+{
+ if (*stored == -ENOANO)
+ return;
+ else if (r == -ENOANO)
+ *stored = r;
+ else if (r == -EAGAIN && *stored != -ENOANO)
+ *stored = r;
+ else if (r == -EPERM && (*stored != -ENOANO && *stored != -EAGAIN))
+ *stored = r;
+}
+
+static int LUKS2_keyslot_open_by_token(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ int segment,
+ crypt_keyslot_priority priority,
+ const char *buffer,
+ size_t buffer_len,
+ struct volume_key **vk)
+{
+ crypt_keyslot_priority keyslot_priority;
+ json_object *jobj_token, *jobj_token_keyslots, *jobj_type, *jobj;
+ unsigned int num = 0;
+ int i, r = -ENOENT, stored_retval = -ENOENT;
+
+ jobj_token = LUKS2_get_token_jobj(hdr, token);
+ if (!jobj_token)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_token, "type", &jobj_type))
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots);
+ if (!jobj_token_keyslots)
+ return -EINVAL;
+
+ /* Try to open keyslot referenced in token */
+ for (i = 0; i < (int) json_object_array_length(jobj_token_keyslots) && r < 0; i++) {
+ jobj = json_object_array_get_idx(jobj_token_keyslots, i);
+ num = atoi(json_object_get_string(jobj));
+ keyslot_priority = LUKS2_keyslot_priority_get(hdr, num);
+ if (keyslot_priority == CRYPT_SLOT_PRIORITY_INVALID)
+ return -EINVAL;
+ if (keyslot_priority < priority)
+ continue;
+ log_dbg(cd, "Trying to open keyslot %u with token %d (type %s).",
+ num, token, json_object_get_string(jobj_type));
+ r = LUKS2_keyslot_open(cd, num, segment, buffer, buffer_len, vk);
+ /* short circuit on fatal error */
+ if (r < 0 && r != -EPERM && r != -ENOENT)
+ return r;
+ /* save -EPERM in case no other keyslot is usable */
+ if (r == -EPERM)
+ stored_retval = r;
+ }
+
+ if (r < 0)
+ return stored_retval;
+
+ return num;
+}
+
+static bool token_is_blocked(int token, uint32_t *block_list)
+{
+ /* it is safe now, but have assert in case LUKS2_TOKENS_MAX grows */
+ assert(token >= 0 && (size_t)token < BITFIELD_SIZE(block_list));
+
+ return (*block_list & (UINT32_C(1) << token));
+}
+
+static void token_block(int token, uint32_t *block_list)
+{
+ /* it is safe now, but have assert in case LUKS2_TOKENS_MAX grows */
+ assert(token >= 0 && (size_t)token < BITFIELD_SIZE(block_list));
+
+ *block_list |= (UINT32_C(1) << token);
+}
+
+static int token_open_priority(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ json_object *jobj_tokens,
+ const char *type,
+ int segment,
+ crypt_keyslot_priority priority,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr,
+ int *stored_retval,
+ uint32_t *block_list,
+ struct volume_key **vk)
+{
+ char *buffer;
+ size_t buffer_size;
+ int token, r;
+
+ assert(stored_retval);
+ assert(block_list);
+
+ json_object_object_foreach(jobj_tokens, slot, val) {
+ token = atoi(slot);
+ if (token_is_blocked(token, block_list))
+ continue;
+ r = token_open(cd, hdr, token, val, type, segment, priority, pin, pin_size, &buffer, &buffer_size, usrptr, true);
+ if (!r) {
+ r = LUKS2_keyslot_open_by_token(cd, hdr, token, segment, priority,
+ buffer, buffer_size, vk);
+ LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
+ }
+
+ if (r == -ENOANO)
+ token_block(token, block_list);
+
+ if (break_loop_retval(r))
+ return r;
+
+ update_return_errno(r, stored_retval);
+ }
+
+ return *stored_retval;
+}
+
+static int token_open_any(struct crypt_device *cd, struct luks2_hdr *hdr, const char *type, int segment,
+ const char *pin, size_t pin_size, void *usrptr, struct volume_key **vk)
+{
+ json_object *jobj_tokens;
+ int r, retval = -ENOENT;
+ uint32_t blocked = 0; /* bitmap with tokens blocked from loop by returning -ENOANO (wrong/missing pin) */
+
+ json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens);
+
+ /* passing usrptr for CRYPT_ANY_TOKEN does not make sense without specific type */
+ if (!type)
+ usrptr = NULL;
+
+ r = token_open_priority(cd, hdr, jobj_tokens, type, segment, CRYPT_SLOT_PRIORITY_PREFER,
+ pin, pin_size, usrptr, &retval, &blocked, vk);
+ if (break_loop_retval(r))
+ return r;
+
+ return token_open_priority(cd, hdr, jobj_tokens, type, segment, CRYPT_SLOT_PRIORITY_NORMAL,
+ pin, pin_size, usrptr, &retval, &blocked, vk);
+}
+
+int LUKS2_token_unlock_key(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ int segment,
+ void *usrptr,
+ struct volume_key **vk)
+{
+ char *buffer;
+ size_t buffer_size;
+ json_object *jobj_token;
+ int r = -ENOENT;
+
+ assert(vk);
+
+ if (segment == CRYPT_DEFAULT_SEGMENT)
+ segment = LUKS2_get_default_segment(hdr);
+
+ if (segment < 0 && segment != CRYPT_ANY_SEGMENT)
+ return -EINVAL;
+
+ if (token >= 0 && token < LUKS2_TOKENS_MAX) {
+ if ((jobj_token = LUKS2_get_token_jobj(hdr, token))) {
+ r = token_open(cd, hdr, token, jobj_token, type, segment, CRYPT_SLOT_PRIORITY_IGNORE,
+ pin, pin_size, &buffer, &buffer_size, usrptr, true);
+ if (!r) {
+ r = LUKS2_keyslot_open_by_token(cd, hdr, token, segment, CRYPT_SLOT_PRIORITY_IGNORE,
+ buffer, buffer_size, vk);
+ LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
+ }
+ }
+ } else if (token == CRYPT_ANY_TOKEN)
+ /*
+ * return priorities (ordered form least to most significant):
+ * ENOENT - unusable for activation (no token handler, invalid token metadata, not assigned to volume segment, etc)
+ * EPERM - usable but token provided passphrase did not unlock any assigned keyslot
+ * EAGAIN - usable but not ready (token HW is missing)
+ * ENOANO - ready, but token pin is wrong or missing
+ *
+ * success (>= 0) or any other negative errno short-circuits token activation loop
+ * immediately
+ */
+ r = token_open_any(cd, hdr, type, segment, pin, pin_size, usrptr, vk);
+ else
+ r = -EINVAL;
+
+ return r;
+}
+
+int LUKS2_token_open_and_activate(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *name,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ uint32_t flags,
+ void *usrptr)
+{
+ bool use_keyring;
+ int keyslot, r, segment;
+ struct volume_key *vk = NULL;
+
+ if (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY)
+ segment = CRYPT_ANY_SEGMENT;
+ else
+ segment = CRYPT_DEFAULT_SEGMENT;
+
+ r = LUKS2_token_unlock_key(cd, hdr, token, type, pin, pin_size, segment, usrptr, &vk);
+ if (r < 0)
+ return r;
+
+ assert(vk);
+
+ keyslot = r;
+
+ if (!crypt_use_keyring_for_vk(cd))
+ use_keyring = false;
+ else
+ use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
+ (flags & CRYPT_ACTIVATE_KEYRING_KEY));
+
+ if (use_keyring) {
+ if (!(r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd, hdr, vk, keyslot)))
+ flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ }
+
+ if (r >= 0 && name)
+ r = LUKS2_activate(cd, name, vk, flags);
+
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vk);
+ crypt_free_volume_key(vk);
+
+ return r < 0 ? r : keyslot;
+}
+
+void LUKS2_token_dump(struct crypt_device *cd, int token)
+{
+ const crypt_token_handler *h;
+ json_object *jobj_token;
+
+ h = LUKS2_token_handler(cd, token);
+ if (h && h->dump) {
+ jobj_token = LUKS2_get_token_jobj(crypt_get_hdr(cd, CRYPT_LUKS2), token);
+ if (jobj_token)
+ h->dump(cd, json_object_to_json_string_ext(jobj_token,
+ JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE));
+ }
+}
+
+int LUKS2_token_json_get(struct luks2_hdr *hdr, int token, const char **json)
+{
+ json_object *jobj_token;
+
+ jobj_token = LUKS2_get_token_jobj(hdr, token);
+ if (!jobj_token)
+ return -EINVAL;
+
+ *json = token_json_to_string(jobj_token);
+ return 0;
+}
+
+static int assign_one_keyslot(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int token, int keyslot, int assign)
+{
+ json_object *jobj1, *jobj_token, *jobj_token_keyslots;
+ char num[16];
+
+ log_dbg(cd, "Keyslot %i %s token %i.", keyslot, assign ? "assigned to" : "unassigned from", token);
+
+ jobj_token = LUKS2_get_token_jobj(hdr, token);
+ if (!jobj_token)
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots);
+ if (!jobj_token_keyslots)
+ return -EINVAL;
+
+ if (snprintf(num, sizeof(num), "%d", keyslot) < 0)
+ return -EINVAL;
+
+ if (assign) {
+ jobj1 = LUKS2_array_jobj(jobj_token_keyslots, num);
+ if (!jobj1)
+ json_object_array_add(jobj_token_keyslots, json_object_new_string(num));
+ } else {
+ jobj1 = LUKS2_array_remove(jobj_token_keyslots, num);
+ if (jobj1)
+ json_object_object_add(jobj_token, "keyslots", jobj1);
+ }
+
+ return 0;
+}
+
+static int assign_one_token(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, int token, int assign)
+{
+ json_object *jobj_keyslots;
+ int r = 0;
+
+ if (!LUKS2_get_token_jobj(hdr, token))
+ return -EINVAL;
+
+ if (keyslot == CRYPT_ANY_SLOT) {
+ json_object_object_get_ex(hdr->jobj, "keyslots", &jobj_keyslots);
+
+ json_object_object_foreach(jobj_keyslots, key, val) {
+ UNUSED(val);
+ r = assign_one_keyslot(cd, hdr, token, atoi(key), assign);
+ if (r < 0)
+ break;
+ }
+ } else
+ r = assign_one_keyslot(cd, hdr, token, keyslot, assign);
+
+ return r;
+}
+
+int LUKS2_token_assign(struct crypt_device *cd, struct luks2_hdr *hdr,
+ int keyslot, int token, int assign, int commit)
+{
+ json_object *jobj_tokens;
+ int r = 0;
+
+ if ((keyslot < 0 && keyslot != CRYPT_ANY_SLOT) || keyslot >= LUKS2_KEYSLOTS_MAX ||
+ (token < 0 && token != CRYPT_ANY_TOKEN) || token >= LUKS2_TOKENS_MAX)
+ return -EINVAL;
+
+ if (token == CRYPT_ANY_TOKEN) {
+ json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens);
+
+ json_object_object_foreach(jobj_tokens, key, val) {
+ UNUSED(val);
+ r = assign_one_token(cd, hdr, keyslot, atoi(key), assign);
+ if (r < 0)
+ break;
+ }
+ } else
+ r = assign_one_token(cd, hdr, keyslot, token, assign);
+
+ if (r < 0)
+ return r;
+
+ if (commit)
+ return LUKS2_hdr_write(cd, hdr) ?: token;
+
+ return token;
+}
+
+static int token_is_assigned(struct luks2_hdr *hdr, int keyslot, int token)
+{
+ int i;
+ json_object *jobj, *jobj_token_keyslots,
+ *jobj_token = LUKS2_get_token_jobj(hdr, token);
+
+ if (!jobj_token)
+ return -ENOENT;
+
+ json_object_object_get_ex(jobj_token, "keyslots", &jobj_token_keyslots);
+
+ for (i = 0; i < (int) json_object_array_length(jobj_token_keyslots); i++) {
+ jobj = json_object_array_get_idx(jobj_token_keyslots, i);
+ if (keyslot == atoi(json_object_get_string(jobj)))
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+int LUKS2_token_is_assigned(struct luks2_hdr *hdr, int keyslot, int token)
+{
+ if (keyslot < 0 || keyslot >= LUKS2_KEYSLOTS_MAX || token < 0 || token >= LUKS2_TOKENS_MAX)
+ return -EINVAL;
+
+ return token_is_assigned(hdr, keyslot, token);
+}
+
+int LUKS2_tokens_count(struct luks2_hdr *hdr)
+{
+ json_object *jobj_tokens = LUKS2_get_tokens_jobj(hdr);
+ if (!jobj_tokens)
+ return -EINVAL;
+
+ return json_object_object_length(jobj_tokens);
+}
+
+int LUKS2_token_assignment_copy(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot_from,
+ int keyslot_to,
+ int commit)
+{
+ int i, r;
+
+ if (keyslot_from < 0 || keyslot_from >= LUKS2_KEYSLOTS_MAX || keyslot_to < 0 || keyslot_to >= LUKS2_KEYSLOTS_MAX)
+ return -EINVAL;
+
+ r = LUKS2_tokens_count(hdr);
+ if (r <= 0)
+ return r;
+
+ for (i = 0; i < LUKS2_TOKENS_MAX; i++) {
+ if (!token_is_assigned(hdr, keyslot_from, i)) {
+ if ((r = assign_one_token(cd, hdr, keyslot_to, i, 1)))
+ return r;
+ }
+ }
+
+ return commit ? LUKS2_hdr_write(cd, hdr) : 0;
+}
+
+int LUKS2_token_unlock_passphrase(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int token,
+ const char *type,
+ const char *pin,
+ size_t pin_size,
+ void *usrptr,
+ char **passphrase,
+ size_t *passphrase_size)
+{
+ char *buffer;
+ size_t buffer_size;
+ json_object *jobj_token, *jobj_tokens;
+ int r = -ENOENT, retval = -ENOENT;
+
+ if (!hdr)
+ return -EINVAL;
+
+ if (token >= 0 && token < LUKS2_TOKENS_MAX) {
+ if ((jobj_token = LUKS2_get_token_jobj(hdr, token)))
+ r = token_open(cd, hdr, token, jobj_token, type, CRYPT_ANY_SEGMENT, CRYPT_SLOT_PRIORITY_IGNORE,
+ pin, pin_size, &buffer, &buffer_size, usrptr, false);
+ } else if (token == CRYPT_ANY_TOKEN) {
+ json_object_object_get_ex(hdr->jobj, "tokens", &jobj_tokens);
+
+ if (!type)
+ usrptr = NULL;
+
+ json_object_object_foreach(jobj_tokens, slot, val) {
+ token = atoi(slot);
+ r = token_open(cd, hdr, token, val, type, CRYPT_ANY_SEGMENT, CRYPT_SLOT_PRIORITY_IGNORE,
+ pin, pin_size, &buffer, &buffer_size, usrptr, false);
+
+ /*
+ * return priorities (ordered form least to most significant):
+ * ENOENT - unusable for activation (no token handler, invalid token metadata, etc)
+ * EAGAIN - usable but not ready (token HW is missing)
+ * ENOANO - ready, but token pin is wrong or missing
+ *
+ * success (>= 0) or any other negative errno short-circuits token activation loop
+ * immediately
+ */
+ if (break_loop_retval(r))
+ goto out;
+
+ update_return_errno(r, &retval);
+ }
+ r = retval;
+ } else
+ r = -EINVAL;
+out:
+ if (!r) {
+ *passphrase = crypt_safe_alloc(buffer_size);
+ if (*passphrase) {
+ memcpy(*passphrase, buffer, buffer_size);
+ *passphrase_size = buffer_size;
+ } else
+ r = -ENOMEM;
+ LUKS2_token_buffer_free(cd, token, buffer, buffer_size);
+ }
+
+ if (!r)
+ return token;
+
+ return r;
+}
diff --git a/lib/luks2/luks2_token_keyring.c b/lib/luks2/luks2_token_keyring.c
new file mode 100644
index 0000000..ad18798
--- /dev/null
+++ b/lib/luks2/luks2_token_keyring.c
@@ -0,0 +1,144 @@
+/*
+ * LUKS - Linux Unified Key Setup v2, kernel keyring token
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "luks2_internal.h"
+
+int keyring_open(struct crypt_device *cd,
+ int token,
+ char **buffer,
+ size_t *buffer_len,
+ void *usrptr __attribute__((unused)))
+{
+ json_object *jobj_token, *jobj_key;
+ struct luks2_hdr *hdr;
+ int r;
+
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
+ return -EINVAL;
+
+ jobj_token = LUKS2_get_token_jobj(hdr, token);
+ if (!jobj_token)
+ return -EINVAL;
+
+ json_object_object_get_ex(jobj_token, "key_description", &jobj_key);
+
+ r = keyring_get_passphrase(json_object_get_string(jobj_key), buffer, buffer_len);
+ if (r == -ENOTSUP) {
+ log_dbg(cd, "Kernel keyring features disabled.");
+ return -ENOENT;
+ } else if (r < 0) {
+ log_dbg(cd, "keyring_get_passphrase failed (error %d)", r);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+int keyring_validate(struct crypt_device *cd __attribute__((unused)),
+ const char *json)
+{
+ enum json_tokener_error jerr;
+ json_object *jobj_token, *jobj_key;
+ int r = 1;
+
+ log_dbg(cd, "Validating keyring token json");
+
+ jobj_token = json_tokener_parse_verbose(json, &jerr);
+ if (!jobj_token) {
+ log_dbg(cd, "Keyring token JSON parse failed.");
+ return r;
+ }
+
+ if (json_object_object_length(jobj_token) != 3) {
+ log_dbg(cd, "Keyring token is expected to have exactly 3 fields.");
+ goto out;
+ }
+
+ if (!json_object_object_get_ex(jobj_token, "key_description", &jobj_key)) {
+ log_dbg(cd, "missing key_description field.");
+ goto out;
+ }
+
+ if (!json_object_is_type(jobj_key, json_type_string)) {
+ log_dbg(cd, "key_description is not a string.");
+ goto out;
+ }
+
+ /* TODO: perhaps check that key description is in '%s:%s'
+ * format where both strings are not empty */
+ r = !strlen(json_object_get_string(jobj_key));
+out:
+ json_object_put(jobj_token);
+ return r;
+}
+
+void keyring_dump(struct crypt_device *cd, const char *json)
+{
+ enum json_tokener_error jerr;
+ json_object *jobj_token, *jobj_key;
+
+ jobj_token = json_tokener_parse_verbose(json, &jerr);
+ if (!jobj_token)
+ return;
+
+ if (!json_object_object_get_ex(jobj_token, "key_description", &jobj_key)) {
+ json_object_put(jobj_token);
+ return;
+ }
+
+ log_std(cd, "\tKey description: %s\n", json_object_get_string(jobj_key));
+
+ json_object_put(jobj_token);
+}
+
+int LUKS2_token_keyring_json(char *buffer, size_t buffer_size,
+ const struct crypt_token_params_luks2_keyring *keyring_params)
+{
+ int r;
+
+ r = snprintf(buffer, buffer_size, "{ \"type\": \"%s\", \"keyslots\":[],\"key_description\":\"%s\"}",
+ LUKS2_TOKEN_KEYRING, keyring_params->key_description);
+ if (r < 0 || (size_t)r >= buffer_size)
+ return -EINVAL;
+
+ return 0;
+}
+
+int LUKS2_token_keyring_get(struct luks2_hdr *hdr,
+ int token, struct crypt_token_params_luks2_keyring *keyring_params)
+{
+ json_object *jobj_token, *jobj;
+
+ jobj_token = LUKS2_get_token_jobj(hdr, token);
+ json_object_object_get_ex(jobj_token, "type", &jobj);
+ assert(!strcmp(json_object_get_string(jobj), LUKS2_TOKEN_KEYRING));
+
+ json_object_object_get_ex(jobj_token, "key_description", &jobj);
+
+ keyring_params->key_description = json_object_get_string(jobj);
+
+ return token;
+}
+
+void keyring_buffer_free(void *buffer, size_t buffer_len __attribute__((unused)))
+{
+ crypt_safe_free(buffer);
+}
diff --git a/lib/nls.h b/lib/nls.h
new file mode 100644
index 0000000..39760b1
--- /dev/null
+++ b/lib/nls.h
@@ -0,0 +1,34 @@
+#ifndef CRYPTSETUP_NLS_H
+#define CRYPTSETUP_NLS_H
+
+#ifndef LOCALEDIR
+#define LOCALEDIR "/usr/share/locale"
+#endif
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#else
+# undef setlocale
+# define setlocale(Category, Locale) /* empty */
+#endif
+
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+# undef bindtextdomain
+# define bindtextdomain(Domain, Directory) /* empty */
+# undef textdomain
+# define textdomain(Domain) /* empty */
+# define _(Text) (Text)
+# define N_(Text) (Text)
+# define ngettext(Singular, Plural, Count) \
+ ( (Count) == 1 ? (Singular) : (Plural) )
+#endif
+
+#endif /* CRYPTSETUP_NLS_H */
diff --git a/lib/random.c b/lib/random.c
new file mode 100644
index 0000000..0dfcff9
--- /dev/null
+++ b/lib/random.c
@@ -0,0 +1,244 @@
+/*
+ * cryptsetup kernel RNG access functions
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/select.h>
+
+#include "libcryptsetup.h"
+#include "internal.h"
+
+static int random_initialised = 0;
+
+#define URANDOM_DEVICE "/dev/urandom"
+static int urandom_fd = -1;
+
+#define RANDOM_DEVICE "/dev/random"
+static int random_fd = -1;
+
+/* Read random chunk - gathered data usually appears with this granularity */
+#define RANDOM_DEVICE_CHUNK 8
+
+/* Timeout to print warning if no random data (entropy) */
+#define RANDOM_DEVICE_TIMEOUT 5
+
+/* URANDOM_DEVICE access */
+static int _get_urandom(char *buf, size_t len)
+{
+ int r;
+ size_t old_len = len;
+ char *old_buf = buf;
+
+ assert(urandom_fd != -1);
+
+ while (len) {
+ r = read(urandom_fd, buf, len);
+ if (r == -1 && errno != EINTR)
+ return -EINVAL;
+ if (r > 0) {
+ len -= r;
+ buf += r;
+ }
+ }
+
+ assert(len == 0);
+ assert((size_t)(buf - old_buf) == old_len);
+
+ return 0;
+}
+
+static void _get_random_progress(struct crypt_device *ctx, int warn,
+ size_t expected_len, size_t read_len)
+{
+ if (warn)
+ log_std(ctx,
+ _("System is out of entropy while generating volume key.\n"
+ "Please move mouse or type some text in another window "
+ "to gather some random events.\n"));
+
+ log_std(ctx, _("Generating key (%d%% done).\n"),
+ (int)((expected_len - read_len) * 100 / expected_len));
+}
+
+/* RANDOM_DEVICE access */
+static int _get_random(struct crypt_device *ctx, char *buf, size_t len)
+{
+ int r, warn_once = 1;
+ size_t n, old_len = len;
+ char *old_buf = buf;
+ fd_set fds;
+ struct timeval tv;
+
+ assert(random_fd != -1);
+
+ while (len) {
+ FD_ZERO(&fds);
+ FD_SET(random_fd, &fds);
+
+ tv.tv_sec = RANDOM_DEVICE_TIMEOUT;
+ tv.tv_usec = 0;
+
+ r = select(random_fd + 1, &fds, NULL, NULL, &tv);
+ if(r == -1)
+ return -EINVAL;
+
+ if(!r) {
+ _get_random_progress(ctx, warn_once, old_len, len);
+ warn_once = 0;
+ continue;
+ }
+
+ do {
+ n = RANDOM_DEVICE_CHUNK;
+ if (len < RANDOM_DEVICE_CHUNK)
+ n = len;
+
+ r = read(random_fd, buf, n);
+
+ if (r == -1 && errno == EINTR) {
+ r = 0;
+ continue;
+ }
+
+ /* bogus read? */
+ if(r > (int)n)
+ return -EINVAL;
+
+ /* random device is opened with O_NONBLOCK, EAGAIN is expected */
+ if (r == -1 && (errno != EAGAIN && errno != EWOULDBLOCK))
+ return -EINVAL;
+
+ if (r > 0) {
+ len -= r;
+ buf += r;
+ }
+ } while (len && r > 0);
+ }
+
+ assert(len == 0);
+ assert((size_t)(buf - old_buf) == old_len);
+
+ if (!warn_once)
+ _get_random_progress(ctx, 0, old_len, len);
+
+ return 0;
+}
+/* Initialisation of both RNG file descriptors is mandatory */
+int crypt_random_init(struct crypt_device *ctx)
+{
+ if (random_initialised)
+ return 0;
+
+ /* Used for CRYPT_RND_NORMAL */
+ if(urandom_fd == -1)
+ urandom_fd = open(URANDOM_DEVICE, O_RDONLY | O_CLOEXEC);
+ if(urandom_fd == -1)
+ goto err;
+
+ /* Used for CRYPT_RND_KEY */
+ if(random_fd == -1)
+ random_fd = open(RANDOM_DEVICE, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if(random_fd == -1)
+ goto err;
+
+ if (crypt_fips_mode())
+ log_verbose(ctx, _("Running in FIPS mode."));
+
+ random_initialised = 1;
+ return 0;
+err:
+ crypt_random_exit();
+ log_err(ctx, _("Fatal error during RNG initialisation."));
+ return -ENOSYS;
+}
+
+/* coverity[ -taint_source : arg-1 ] */
+int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int quality)
+{
+ int status, rng_type;
+
+ switch(quality) {
+ case CRYPT_RND_NORMAL:
+ status = _get_urandom(buf, len);
+ break;
+ case CRYPT_RND_SALT:
+ if (crypt_fips_mode())
+ status = crypt_backend_rng(buf, len, quality, 1);
+ else
+ status = _get_urandom(buf, len);
+ break;
+ case CRYPT_RND_KEY:
+ if (crypt_fips_mode()) {
+ status = crypt_backend_rng(buf, len, quality, 1);
+ break;
+ }
+ rng_type = ctx ? crypt_get_rng_type(ctx) :
+ crypt_random_default_key_rng();
+ switch (rng_type) {
+ case CRYPT_RNG_URANDOM:
+ status = _get_urandom(buf, len);
+ break;
+ case CRYPT_RNG_RANDOM:
+ status = _get_random(ctx, buf, len);
+ break;
+ default:
+ abort();
+ }
+ break;
+ default:
+ log_err(ctx, _("Unknown RNG quality requested."));
+ return -EINVAL;
+ }
+
+ if (status)
+ log_err(ctx, _("Error reading from RNG."));
+
+ return status;
+}
+
+void crypt_random_exit(void)
+{
+ random_initialised = 0;
+
+ if(random_fd != -1) {
+ (void)close(random_fd);
+ random_fd = -1;
+ }
+
+ if(urandom_fd != -1) {
+ (void)close(urandom_fd);
+ urandom_fd = -1;
+ }
+}
+
+int crypt_random_default_key_rng(void)
+{
+ /* coverity[pointless_string_compare] */
+ if (!strcmp(DEFAULT_RNG, RANDOM_DEVICE))
+ return CRYPT_RNG_RANDOM;
+
+ /* coverity[pointless_string_compare] */
+ if (!strcmp(DEFAULT_RNG, URANDOM_DEVICE))
+ return CRYPT_RNG_URANDOM;
+
+ /* RNG misconfiguration is fatal */
+ abort();
+}
diff --git a/lib/setup.c b/lib/setup.c
new file mode 100644
index 0000000..1c9d47d
--- /dev/null
+++ b/lib/setup.c
@@ -0,0 +1,6564 @@
+/*
+ * libcryptsetup - cryptsetup library
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/utsname.h>
+#include <errno.h>
+
+#include "libcryptsetup.h"
+#include "luks1/luks.h"
+#include "luks2/luks2.h"
+#include "loopaes/loopaes.h"
+#include "verity/verity.h"
+#include "tcrypt/tcrypt.h"
+#include "integrity/integrity.h"
+#include "bitlk/bitlk.h"
+#include "fvault2/fvault2.h"
+#include "utils_device_locking.h"
+#include "internal.h"
+#include "keyslot_context.h"
+
+#define CRYPT_CD_UNRESTRICTED (1 << 0)
+#define CRYPT_CD_QUIET (1 << 1)
+
+struct crypt_device {
+ char *type;
+
+ struct device *device;
+ struct device *metadata_device;
+
+ struct volume_key *volume_key;
+ int rng_type;
+ uint32_t compatibility;
+ struct crypt_pbkdf_type pbkdf;
+
+ /* global context scope settings */
+ unsigned key_in_keyring:1;
+
+ uint64_t data_offset;
+ uint64_t metadata_size; /* Used in LUKS2 format */
+ uint64_t keyslots_size; /* Used in LUKS2 format */
+
+ /* Workaround for OOM during parallel activation (like in systemd) */
+ bool memory_hard_pbkdf_lock_enabled;
+ struct crypt_lock_handle *pbkdf_memory_hard_lock;
+
+ union {
+ struct { /* used in CRYPT_LUKS1 */
+ struct luks_phdr hdr;
+ char *cipher_spec;
+ } luks1;
+ struct { /* used in CRYPT_LUKS2 */
+ struct luks2_hdr hdr;
+ char cipher[MAX_CIPHER_LEN]; /* only for compatibility */
+ char cipher_mode[MAX_CIPHER_LEN]; /* only for compatibility */
+ char *keyslot_cipher;
+ unsigned int keyslot_key_size;
+ struct luks2_reencrypt *rh;
+ } luks2;
+ struct { /* used in CRYPT_PLAIN */
+ struct crypt_params_plain hdr;
+ char *cipher_spec;
+ char *cipher;
+ const char *cipher_mode;
+ unsigned int key_size;
+ } plain;
+ struct { /* used in CRYPT_LOOPAES */
+ struct crypt_params_loopaes hdr;
+ char *cipher_spec;
+ char *cipher;
+ const char *cipher_mode;
+ unsigned int key_size;
+ } loopaes;
+ struct { /* used in CRYPT_VERITY */
+ struct crypt_params_verity hdr;
+ const char *root_hash;
+ unsigned int root_hash_size;
+ char *uuid;
+ struct device *fec_device;
+ } verity;
+ struct { /* used in CRYPT_TCRYPT */
+ struct crypt_params_tcrypt params;
+ struct tcrypt_phdr hdr;
+ } tcrypt;
+ struct { /* used in CRYPT_INTEGRITY */
+ struct crypt_params_integrity params;
+ struct volume_key *journal_mac_key;
+ struct volume_key *journal_crypt_key;
+ uint32_t sb_flags;
+ } integrity;
+ struct { /* used in CRYPT_BITLK */
+ struct bitlk_metadata params;
+ char *cipher_spec;
+ } bitlk;
+ struct { /* used in CRYPT_FVAULT2 */
+ struct fvault2_params params;
+ } fvault2;
+ struct { /* used if initialized without header by name */
+ char *active_name;
+ /* buffers, must refresh from kernel on every query */
+ char cipher_spec[MAX_CIPHER_LEN*2+1];
+ char cipher[MAX_CIPHER_LEN];
+ const char *cipher_mode;
+ unsigned int key_size;
+ } none;
+ } u;
+
+ /* callbacks definitions */
+ void (*log)(int level, const char *msg, void *usrptr);
+ void *log_usrptr;
+ int (*confirm)(const char *msg, void *usrptr);
+ void *confirm_usrptr;
+};
+
+/* Just to suppress redundant messages about crypto backend */
+static int _crypto_logged = 0;
+
+/* Log helper */
+static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL;
+static void *_default_log_usrptr = NULL;
+static int _debug_level = 0;
+
+/* Library can do metadata locking */
+static int _metadata_locking = 1;
+
+/* Library scope detection for kernel keyring support */
+static int _kernel_keyring_supported;
+
+/* Library allowed to use kernel keyring for loading VK in kernel crypto layer */
+static int _vk_via_keyring = 1;
+
+void crypt_set_debug_level(int level)
+{
+ _debug_level = level;
+}
+
+int crypt_get_debug_level(void)
+{
+ return _debug_level;
+}
+
+void crypt_log(struct crypt_device *cd, int level, const char *msg)
+{
+ if (!msg)
+ return;
+
+ if (level < _debug_level)
+ return;
+
+ if (cd && cd->log)
+ cd->log(level, msg, cd->log_usrptr);
+ else if (_default_log)
+ _default_log(level, msg, _default_log_usrptr);
+ /* Default to stdout/stderr if there is no callback. */
+ else
+ fprintf(level == CRYPT_LOG_ERROR ? stderr : stdout, "%s", msg);
+}
+
+__attribute__((format(printf, 3, 4)))
+void crypt_logf(struct crypt_device *cd, int level, const char *format, ...)
+{
+ va_list argp;
+ char target[LOG_MAX_LEN + 2];
+ int len;
+
+ va_start(argp, format);
+
+ len = vsnprintf(&target[0], LOG_MAX_LEN, format, argp);
+ if (len > 0 && len < LOG_MAX_LEN) {
+ /* All verbose and error messages in tools end with EOL. */
+ if (level == CRYPT_LOG_VERBOSE || level == CRYPT_LOG_ERROR ||
+ level == CRYPT_LOG_DEBUG || level == CRYPT_LOG_DEBUG_JSON)
+ strncat(target, "\n", LOG_MAX_LEN);
+
+ crypt_log(cd, level, target);
+ }
+
+ va_end(argp);
+}
+
+static const char *mdata_device_path(struct crypt_device *cd)
+{
+ return device_path(cd->metadata_device ?: cd->device);
+}
+
+static const char *data_device_path(struct crypt_device *cd)
+{
+ return device_path(cd->device);
+}
+
+/* internal only */
+struct device *crypt_metadata_device(struct crypt_device *cd)
+{
+ return cd->metadata_device ?: cd->device;
+}
+
+struct device *crypt_data_device(struct crypt_device *cd)
+{
+ return cd->device;
+}
+
+int init_crypto(struct crypt_device *ctx)
+{
+ struct utsname uts;
+ int r;
+
+ r = crypt_random_init(ctx);
+ if (r < 0) {
+ log_err(ctx, _("Cannot initialize crypto RNG backend."));
+ return r;
+ }
+
+ r = crypt_backend_init(crypt_fips_mode());
+ if (r < 0)
+ log_err(ctx, _("Cannot initialize crypto backend."));
+
+ if (!r && !_crypto_logged) {
+ log_dbg(ctx, "Crypto backend (%s) initialized in cryptsetup library version %s.",
+ crypt_backend_version(), PACKAGE_VERSION);
+ if (!uname(&uts))
+ log_dbg(ctx, "Detected kernel %s %s %s.",
+ uts.sysname, uts.release, uts.machine);
+ _crypto_logged = 1;
+ }
+
+ return r;
+}
+
+static int process_key(struct crypt_device *cd, const char *hash_name,
+ size_t key_size, const char *pass, size_t passLen,
+ struct volume_key **vk)
+{
+ int r;
+
+ if (!key_size)
+ return -EINVAL;
+
+ *vk = crypt_alloc_volume_key(key_size, NULL);
+ if (!*vk)
+ return -ENOMEM;
+
+ if (hash_name) {
+ r = crypt_plain_hash(cd, hash_name, (*vk)->key, key_size, pass, passLen);
+ if (r < 0) {
+ if (r == -ENOENT)
+ log_err(cd, _("Hash algorithm %s not supported."),
+ hash_name);
+ else
+ log_err(cd, _("Key processing error (using hash %s)."),
+ hash_name);
+ crypt_free_volume_key(*vk);
+ *vk = NULL;
+ return -EINVAL;
+ }
+ } else if (passLen > key_size) {
+ memcpy((*vk)->key, pass, key_size);
+ } else {
+ memcpy((*vk)->key, pass, passLen);
+ }
+
+ return 0;
+}
+
+static int isPLAIN(const char *type)
+{
+ return (type && !strcmp(CRYPT_PLAIN, type));
+}
+
+static int isLUKS1(const char *type)
+{
+ return (type && !strcmp(CRYPT_LUKS1, type));
+}
+
+static int isLUKS2(const char *type)
+{
+ return (type && !strcmp(CRYPT_LUKS2, type));
+}
+
+static int isLUKS(const char *type)
+{
+ return (isLUKS2(type) || isLUKS1(type));
+}
+
+static int isLOOPAES(const char *type)
+{
+ return (type && !strcmp(CRYPT_LOOPAES, type));
+}
+
+static int isVERITY(const char *type)
+{
+ return (type && !strcmp(CRYPT_VERITY, type));
+}
+
+static int isTCRYPT(const char *type)
+{
+ return (type && !strcmp(CRYPT_TCRYPT, type));
+}
+
+static int isINTEGRITY(const char *type)
+{
+ return (type && !strcmp(CRYPT_INTEGRITY, type));
+}
+
+static int isBITLK(const char *type)
+{
+ return (type && !strcmp(CRYPT_BITLK, type));
+}
+
+static int isFVAULT2(const char *type)
+{
+ return (type && !strcmp(CRYPT_FVAULT2, type));
+}
+
+static int _onlyLUKS(struct crypt_device *cd, uint32_t cdflags)
+{
+ int r = 0;
+
+ if (cd && !cd->type) {
+ if (!(cdflags & CRYPT_CD_QUIET))
+ log_err(cd, _("Cannot determine device type. Incompatible activation of device?"));
+ r = -EINVAL;
+ }
+
+ if (!cd || !isLUKS(cd->type)) {
+ if (!(cdflags & CRYPT_CD_QUIET))
+ log_err(cd, _("This operation is supported only for LUKS device."));
+ r = -EINVAL;
+ }
+
+ if (r || (cdflags & CRYPT_CD_UNRESTRICTED) || isLUKS1(cd->type))
+ return r;
+
+ return LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, cdflags & CRYPT_CD_QUIET);
+}
+
+static int onlyLUKS(struct crypt_device *cd)
+{
+ return _onlyLUKS(cd, 0);
+}
+
+static int _onlyLUKS2(struct crypt_device *cd, uint32_t cdflags, uint32_t mask)
+{
+ int r = 0;
+
+ if (cd && !cd->type) {
+ if (!(cdflags & CRYPT_CD_QUIET))
+ log_err(cd, _("Cannot determine device type. Incompatible activation of device?"));
+ r = -EINVAL;
+ }
+
+ if (!cd || !isLUKS2(cd->type)) {
+ if (!(cdflags & CRYPT_CD_QUIET))
+ log_err(cd, _("This operation is supported only for LUKS2 device."));
+ r = -EINVAL;
+ }
+
+ if (r || (cdflags & CRYPT_CD_UNRESTRICTED))
+ return r;
+
+ return LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, mask, cdflags & CRYPT_CD_QUIET);
+}
+
+/* Internal only */
+int onlyLUKS2(struct crypt_device *cd)
+{
+ return _onlyLUKS2(cd, 0, 0);
+}
+
+/* Internal only */
+int onlyLUKS2mask(struct crypt_device *cd, uint32_t mask)
+{
+ return _onlyLUKS2(cd, 0, mask);
+}
+
+static void crypt_set_null_type(struct crypt_device *cd)
+{
+ free(cd->type);
+ cd->type = NULL;
+ cd->data_offset = 0;
+ cd->metadata_size = 0;
+ cd->keyslots_size = 0;
+ crypt_safe_memzero(&cd->u, sizeof(cd->u));
+}
+
+static void crypt_reset_null_type(struct crypt_device *cd)
+{
+ if (cd->type)
+ return;
+
+ free(cd->u.none.active_name);
+ cd->u.none.active_name = NULL;
+}
+
+/* keyslot helpers */
+static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
+{
+ crypt_keyslot_info ki;
+
+ if (*keyslot == CRYPT_ANY_SLOT) {
+ if (isLUKS1(cd->type))
+ *keyslot = LUKS_keyslot_find_empty(&cd->u.luks1.hdr);
+ else
+ *keyslot = LUKS2_keyslot_find_empty(cd, &cd->u.luks2.hdr, 0);
+ if (*keyslot < 0) {
+ log_err(cd, _("All key slots full."));
+ return -EINVAL;
+ }
+ }
+
+ if (isLUKS1(cd->type))
+ ki = LUKS_keyslot_info(&cd->u.luks1.hdr, *keyslot);
+ else
+ ki = LUKS2_keyslot_info(&cd->u.luks2.hdr, *keyslot);
+ switch (ki) {
+ case CRYPT_SLOT_INVALID:
+ log_err(cd, _("Key slot %d is invalid, please select between 0 and %d."),
+ *keyslot, crypt_keyslot_max(cd->type) - 1);
+ return -EINVAL;
+ case CRYPT_SLOT_INACTIVE:
+ break;
+ default:
+ log_err(cd, _("Key slot %d is full, please select another one."),
+ *keyslot);
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Selected keyslot %d.", *keyslot);
+ return 0;
+}
+
+/*
+ * compares UUIDs returned by device-mapper (striped by cryptsetup) and uuid in header
+ */
+int crypt_uuid_cmp(const char *dm_uuid, const char *hdr_uuid)
+{
+ int i, j;
+ char *str;
+
+ if (!dm_uuid || !hdr_uuid)
+ return -EINVAL;
+
+ str = strchr(dm_uuid, '-');
+ if (!str)
+ return -EINVAL;
+
+ for (i = 0, j = 1; hdr_uuid[i]; i++) {
+ if (hdr_uuid[i] == '-')
+ continue;
+
+ if (!str[j] || str[j] == '-')
+ return -EINVAL;
+
+ if (str[j] != hdr_uuid[i])
+ return -EINVAL;
+ j++;
+ }
+
+ return 0;
+}
+
+/*
+ * compares type of active device to provided string (only if there is no explicit type)
+ */
+static int crypt_uuid_type_cmp(struct crypt_device *cd, const char *type)
+{
+ struct crypt_dm_active_device dmd;
+ size_t len;
+ int r;
+
+ /* Must use header-on-disk if we know the type here */
+ if (cd->type || !cd->u.none.active_name)
+ return -EINVAL;
+
+ log_dbg(cd, "Checking if active device %s without header has UUID type %s.",
+ cd->u.none.active_name, type);
+
+ r = dm_query_device(cd, cd->u.none.active_name, DM_ACTIVE_UUID, &dmd);
+ if (r < 0)
+ return r;
+
+ r = -ENODEV;
+ len = strlen(type);
+ if (dmd.uuid && strlen(dmd.uuid) > len &&
+ !strncmp(dmd.uuid, type, len) && dmd.uuid[len] == '-')
+ r = 0;
+
+ free(CONST_CAST(void*)dmd.uuid);
+ return r;
+}
+
+int PLAIN_activate(struct crypt_device *cd,
+ const char *name,
+ struct volume_key *vk,
+ uint64_t size,
+ uint32_t flags)
+{
+ int r;
+ struct crypt_dm_active_device dmd = {
+ .flags = flags,
+ .size = size,
+ };
+
+ log_dbg(cd, "Trying to activate PLAIN device %s using cipher %s.",
+ name, crypt_get_cipher_spec(cd));
+
+ if (MISALIGNED(size, device_block_size(cd, crypt_data_device(cd)) >> SECTOR_SHIFT)) {
+ log_err(cd, _("Device size is not aligned to device logical block size."));
+ return -EINVAL;
+ }
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
+ vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd),
+ crypt_get_data_offset(cd), crypt_get_integrity(cd),
+ crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
+ if (r < 0)
+ return r;
+
+ r = create_or_reload_device(cd, name, CRYPT_PLAIN, &dmd);
+
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int crypt_confirm(struct crypt_device *cd, const char *msg)
+{
+ if (!cd || !cd->confirm)
+ return 1;
+ else
+ return cd->confirm(msg, cd->confirm_usrptr);
+}
+
+void crypt_set_log_callback(struct crypt_device *cd,
+ void (*log)(int level, const char *msg, void *usrptr),
+ void *usrptr)
+{
+ if (!cd) {
+ _default_log = log;
+ _default_log_usrptr = usrptr;
+ } else {
+ cd->log = log;
+ cd->log_usrptr = usrptr;
+ }
+}
+
+void crypt_set_confirm_callback(struct crypt_device *cd,
+ int (*confirm)(const char *msg, void *usrptr),
+ void *usrptr)
+{
+ if (cd) {
+ cd->confirm = confirm;
+ cd->confirm_usrptr = usrptr;
+ }
+}
+
+const char *crypt_get_dir(void)
+{
+ return dm_get_dir();
+}
+
+int crypt_init(struct crypt_device **cd, const char *device)
+{
+ struct crypt_device *h = NULL;
+ int r;
+
+ if (!cd)
+ return -EINVAL;
+
+ log_dbg(NULL, "Allocating context for crypt device %s.", device ?: "(none)");
+#if !HAVE_DECL_O_CLOEXEC
+ log_dbg(NULL, "Running without O_CLOEXEC.");
+#endif
+
+ if (!(h = malloc(sizeof(struct crypt_device))))
+ return -ENOMEM;
+
+ memset(h, 0, sizeof(*h));
+
+ r = device_alloc(NULL, &h->device, device);
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ dm_backend_init(NULL);
+
+ h->rng_type = crypt_random_default_key_rng();
+
+ *cd = h;
+ return 0;
+}
+
+static int crypt_check_data_device_size(struct crypt_device *cd)
+{
+ int r;
+ uint64_t size, size_min;
+
+ /* Check data device size, require at least header or one sector */
+ size_min = crypt_get_data_offset(cd) << SECTOR_SHIFT ?: SECTOR_SIZE;
+
+ r = device_size(cd->device, &size);
+ if (r < 0)
+ return r;
+
+ if (size < size_min) {
+ log_err(cd, _("Header detected but device %s is too small."),
+ device_path(cd->device));
+ return -EINVAL;
+ }
+
+ return r;
+}
+
+static int _crypt_set_data_device(struct crypt_device *cd, const char *device)
+{
+ struct device *dev = NULL;
+ int r;
+
+ r = device_alloc(cd, &dev, device);
+ if (r < 0)
+ return r;
+
+ if (!cd->metadata_device) {
+ cd->metadata_device = cd->device;
+ } else
+ device_free(cd, cd->device);
+
+ cd->device = dev;
+
+ r = crypt_check_data_device_size(cd);
+ if (!r && isLUKS2(cd->type))
+ device_set_block_size(crypt_data_device(cd), LUKS2_get_sector_size(&cd->u.luks2.hdr));
+
+ return r;
+}
+
+int crypt_set_data_device(struct crypt_device *cd, const char *device)
+{
+ /* metadata device must be set */
+ if (!cd || !cd->device || !device)
+ return -EINVAL;
+
+ log_dbg(cd, "Setting ciphertext data device to %s.", device ?: "(none)");
+
+ if (!isLUKS1(cd->type) && !isLUKS2(cd->type) && !isVERITY(cd->type) &&
+ !isINTEGRITY(cd->type) && !isTCRYPT(cd->type)) {
+ log_err(cd, _("This operation is not supported for this device type."));
+ return -EINVAL;
+ }
+
+ if (isLUKS2(cd->type) && crypt_get_luks2_reencrypt(cd)) {
+ log_err(cd, _("Illegal operation with reencryption in-progress."));
+ return -EINVAL;
+ }
+
+ return _crypt_set_data_device(cd, device);
+}
+
+int crypt_init_data_device(struct crypt_device **cd, const char *device, const char *data_device)
+{
+ int r;
+
+ if (!cd)
+ return -EINVAL;
+
+ r = crypt_init(cd, device);
+ if (r || !data_device || !strcmp(device, data_device))
+ return r;
+
+ log_dbg(NULL, "Setting ciphertext data device to %s.", data_device);
+ r = _crypt_set_data_device(*cd, data_device);
+ if (r) {
+ crypt_free(*cd);
+ *cd = NULL;
+ }
+
+ return r;
+}
+
+static void crypt_free_type(struct crypt_device *cd, const char *force_type)
+{
+ const char *type = force_type ?: cd->type;
+
+ if (isPLAIN(type)) {
+ free(CONST_CAST(void*)cd->u.plain.hdr.hash);
+ free(cd->u.plain.cipher);
+ free(cd->u.plain.cipher_spec);
+ } else if (isLUKS2(type)) {
+ LUKS2_reencrypt_free(cd, cd->u.luks2.rh);
+ LUKS2_hdr_free(cd, &cd->u.luks2.hdr);
+ free(cd->u.luks2.keyslot_cipher);
+ } else if (isLUKS1(type)) {
+ free(cd->u.luks1.cipher_spec);
+ } else if (isLOOPAES(type)) {
+ free(CONST_CAST(void*)cd->u.loopaes.hdr.hash);
+ free(cd->u.loopaes.cipher);
+ free(cd->u.loopaes.cipher_spec);
+ } else if (isVERITY(type)) {
+ free(CONST_CAST(void*)cd->u.verity.hdr.hash_name);
+ free(CONST_CAST(void*)cd->u.verity.hdr.data_device);
+ free(CONST_CAST(void*)cd->u.verity.hdr.hash_device);
+ free(CONST_CAST(void*)cd->u.verity.hdr.fec_device);
+ free(CONST_CAST(void*)cd->u.verity.hdr.salt);
+ free(CONST_CAST(void*)cd->u.verity.root_hash);
+ free(cd->u.verity.uuid);
+ device_free(cd, cd->u.verity.fec_device);
+ } else if (isINTEGRITY(type)) {
+ free(CONST_CAST(void*)cd->u.integrity.params.integrity);
+ free(CONST_CAST(void*)cd->u.integrity.params.journal_integrity);
+ free(CONST_CAST(void*)cd->u.integrity.params.journal_crypt);
+ crypt_free_volume_key(cd->u.integrity.journal_crypt_key);
+ crypt_free_volume_key(cd->u.integrity.journal_mac_key);
+ } else if (isBITLK(type)) {
+ free(cd->u.bitlk.cipher_spec);
+ BITLK_bitlk_metadata_free(&cd->u.bitlk.params);
+ } else if (!type) {
+ free(cd->u.none.active_name);
+ cd->u.none.active_name = NULL;
+ }
+
+ crypt_set_null_type(cd);
+}
+
+/* internal only */
+struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd)
+{
+ return &cd->pbkdf;
+}
+
+/*
+ * crypt_load() helpers
+ */
+static int _crypt_load_luks2(struct crypt_device *cd, int reload, int repair)
+{
+ int r;
+ char *type = NULL;
+ struct luks2_hdr hdr2 = {};
+
+ log_dbg(cd, "%soading LUKS2 header (repair %sabled).", reload ? "Rel" : "L", repair ? "en" : "dis");
+
+ r = LUKS2_hdr_read(cd, &hdr2, repair);
+ if (r)
+ return r;
+
+ if (!reload && !(type = strdup(CRYPT_LUKS2))) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (verify_pbkdf_params(cd, &cd->pbkdf)) {
+ r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2);
+ if (r)
+ goto out;
+ }
+
+ if (reload) {
+ LUKS2_hdr_free(cd, &cd->u.luks2.hdr);
+ free(cd->u.luks2.keyslot_cipher);
+ } else
+ cd->type = type;
+
+ r = 0;
+ memcpy(&cd->u.luks2.hdr, &hdr2, sizeof(hdr2));
+ cd->u.luks2.keyslot_cipher = NULL;
+ cd->u.luks2.rh = NULL;
+
+out:
+ if (r) {
+ free(type);
+ LUKS2_hdr_free(cd, &hdr2);
+ }
+ return r;
+}
+
+static void _luks2_rollback(struct crypt_device *cd)
+{
+ if (!cd || !isLUKS2(cd->type))
+ return;
+
+ if (LUKS2_hdr_rollback(cd, &cd->u.luks2.hdr)) {
+ log_err(cd, _("Failed to rollback LUKS2 metadata in memory."));
+ return;
+ }
+
+ free(cd->u.luks2.keyslot_cipher);
+ cd->u.luks2.keyslot_cipher = NULL;
+}
+
+static int _crypt_load_luks(struct crypt_device *cd, const char *requested_type,
+ bool quiet, bool repair)
+{
+ char *cipher_spec;
+ struct luks_phdr hdr = {};
+ int r, version;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ /* This will return 0 if primary LUKS2 header is damaged */
+ version = LUKS2_hdr_version_unlocked(cd, NULL);
+
+ if ((isLUKS1(requested_type) && version == 2) ||
+ (isLUKS2(requested_type) && version == 1))
+ return -EINVAL;
+
+ if (requested_type)
+ version = 0;
+
+ if (isLUKS1(requested_type) || version == 1) {
+ if (isLUKS2(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+
+ if (verify_pbkdf_params(cd, &cd->pbkdf)) {
+ r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1);
+ if (r)
+ return r;
+ }
+
+ r = LUKS_read_phdr(&hdr, !quiet, repair, cd);
+ if (r)
+ goto out;
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_LUKS1))) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /* Set hash to the same as in the loaded header */
+ if (!cd->pbkdf.hash || strcmp(cd->pbkdf.hash, hdr.hashSpec)) {
+ free(CONST_CAST(void*)cd->pbkdf.hash);
+ cd->pbkdf.hash = strdup(hdr.hashSpec);
+ if (!cd->pbkdf.hash) {
+ r = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (asprintf(&cipher_spec, "%s-%s", hdr.cipherName, hdr.cipherMode) < 0) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ free(cd->u.luks1.cipher_spec);
+ cd->u.luks1.cipher_spec = cipher_spec;
+
+ memcpy(&cd->u.luks1.hdr, &hdr, sizeof(hdr));
+ } else if (isLUKS2(requested_type) || version == 2 || version == 0) {
+ if (isLUKS1(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+
+ /*
+ * Current LUKS2 repair just overrides blkid probes
+ * and perform auto-recovery if possible. This is safe
+ * unless future LUKS2 repair code do something more
+ * sophisticated. In such case we would need to check
+ * for LUKS2 requirements and decide if it's safe to
+ * perform repair.
+ */
+ r = _crypt_load_luks2(cd, cd->type != NULL, repair);
+ if (!r)
+ device_set_block_size(crypt_data_device(cd), LUKS2_get_sector_size(&cd->u.luks2.hdr));
+ else if (!quiet)
+ log_err(cd, _("Device %s is not a valid LUKS device."), mdata_device_path(cd));
+ } else {
+ if (version > 2)
+ log_err(cd, _("Unsupported LUKS version %d."), version);
+ r = -EINVAL;
+ }
+out:
+ crypt_safe_memzero(&hdr, sizeof(hdr));
+
+ return r;
+}
+
+static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcrypt *params)
+{
+ int r;
+
+ if (!params)
+ return -EINVAL;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ memcpy(&cd->u.tcrypt.params, params, sizeof(*params));
+
+ r = TCRYPT_read_phdr(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
+
+ cd->u.tcrypt.params.passphrase = NULL;
+ cd->u.tcrypt.params.passphrase_size = 0;
+ cd->u.tcrypt.params.keyfiles = NULL;
+ cd->u.tcrypt.params.keyfiles_count = 0;
+ cd->u.tcrypt.params.veracrypt_pim = 0;
+
+ if (r < 0)
+ goto out;
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_TCRYPT)))
+ r = -ENOMEM;
+out:
+ if (r < 0)
+ crypt_free_type(cd, CRYPT_TCRYPT);
+ return r;
+}
+
+static int _crypt_load_verity(struct crypt_device *cd, struct crypt_params_verity *params)
+{
+ int r;
+ uint64_t sb_offset = 0;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ if (params && params->flags & CRYPT_VERITY_NO_HEADER)
+ return -EINVAL;
+
+ if (params)
+ sb_offset = params->hash_area_offset;
+
+ r = VERITY_read_sb(cd, sb_offset, &cd->u.verity.uuid, &cd->u.verity.hdr);
+ if (r < 0)
+ goto out;
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_VERITY))) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (params)
+ cd->u.verity.hdr.flags = params->flags;
+
+ /* Hash availability checked in sb load */
+ cd->u.verity.root_hash_size = crypt_hash_size(cd->u.verity.hdr.hash_name);
+ if (cd->u.verity.root_hash_size > 4096) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (params && params->data_device &&
+ (r = crypt_set_data_device(cd, params->data_device)) < 0)
+ goto out;
+
+ if (params && params->fec_device) {
+ r = device_alloc(cd, &cd->u.verity.fec_device, params->fec_device);
+ if (r < 0)
+ goto out;
+ cd->u.verity.hdr.fec_area_offset = params->fec_area_offset;
+ cd->u.verity.hdr.fec_roots = params->fec_roots;
+ }
+out:
+ if (r < 0)
+ crypt_free_type(cd, CRYPT_VERITY);
+ return r;
+}
+
+static int _crypt_load_integrity(struct crypt_device *cd,
+ struct crypt_params_integrity *params)
+{
+ int r;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ r = INTEGRITY_read_sb(cd, &cd->u.integrity.params, &cd->u.integrity.sb_flags);
+ if (r < 0)
+ goto out;
+
+ // FIXME: add checks for fields in integrity sb vs params
+
+ r = -ENOMEM;
+ if (params) {
+ cd->u.integrity.params.journal_watermark = params->journal_watermark;
+ cd->u.integrity.params.journal_commit_time = params->journal_commit_time;
+ cd->u.integrity.params.buffer_sectors = params->buffer_sectors;
+ if (params->integrity &&
+ !(cd->u.integrity.params.integrity = strdup(params->integrity)))
+ goto out;
+ cd->u.integrity.params.integrity_key_size = params->integrity_key_size;
+ if (params->journal_integrity &&
+ !(cd->u.integrity.params.journal_integrity = strdup(params->journal_integrity)))
+ goto out;
+ if (params->journal_crypt &&
+ !(cd->u.integrity.params.journal_crypt = strdup(params->journal_crypt)))
+ goto out;
+
+ if (params->journal_crypt_key) {
+ cd->u.integrity.journal_crypt_key =
+ crypt_alloc_volume_key(params->journal_crypt_key_size,
+ params->journal_crypt_key);
+ if (!cd->u.integrity.journal_crypt_key)
+ goto out;
+ }
+ if (params->journal_integrity_key) {
+ cd->u.integrity.journal_mac_key =
+ crypt_alloc_volume_key(params->journal_integrity_key_size,
+ params->journal_integrity_key);
+ if (!cd->u.integrity.journal_mac_key)
+ goto out;
+ }
+ }
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_INTEGRITY)))
+ goto out;
+ r = 0;
+out:
+ if (r < 0)
+ crypt_free_type(cd, CRYPT_INTEGRITY);
+ return r;
+}
+
+static int _crypt_load_bitlk(struct crypt_device *cd)
+{
+ int r;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ r = BITLK_read_sb(cd, &cd->u.bitlk.params);
+ if (r < 0)
+ goto out;
+
+ if (asprintf(&cd->u.bitlk.cipher_spec, "%s-%s",
+ cd->u.bitlk.params.cipher, cd->u.bitlk.params.cipher_mode) < 0) {
+ cd->u.bitlk.cipher_spec = NULL;
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_BITLK))) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ device_set_block_size(crypt_data_device(cd), cd->u.bitlk.params.sector_size);
+out:
+ if (r < 0)
+ crypt_free_type(cd, CRYPT_BITLK);
+ return r;
+}
+
+static int _crypt_load_fvault2(struct crypt_device *cd)
+{
+ int r;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ r = FVAULT2_read_metadata(cd, &cd->u.fvault2.params);
+ if (r < 0)
+ goto out;
+
+ if (!cd->type && !(cd->type = strdup(CRYPT_FVAULT2)))
+ r = -ENOMEM;
+out:
+ if (r < 0)
+ crypt_free_type(cd, CRYPT_FVAULT2);
+ return r;
+}
+
+int crypt_load(struct crypt_device *cd,
+ const char *requested_type,
+ void *params)
+{
+ int r;
+
+ if (!cd)
+ return -EINVAL;
+
+ log_dbg(cd, "Trying to load %s crypt type from device %s.",
+ requested_type ?: "any", mdata_device_path(cd) ?: "(none)");
+
+ if (!crypt_metadata_device(cd))
+ return -EINVAL;
+
+ crypt_reset_null_type(cd);
+ cd->data_offset = 0;
+ cd->metadata_size = 0;
+ cd->keyslots_size = 0;
+
+ if (!requested_type || isLUKS1(requested_type) || isLUKS2(requested_type)) {
+ if (cd->type && !isLUKS1(cd->type) && !isLUKS2(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+
+ r = _crypt_load_luks(cd, requested_type, true, false);
+ } else if (isVERITY(requested_type)) {
+ if (cd->type && !isVERITY(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+ r = _crypt_load_verity(cd, params);
+ } else if (isTCRYPT(requested_type)) {
+ if (cd->type && !isTCRYPT(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+ r = _crypt_load_tcrypt(cd, params);
+ } else if (isINTEGRITY(requested_type)) {
+ if (cd->type && !isINTEGRITY(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+ r = _crypt_load_integrity(cd, params);
+ } else if (isBITLK(requested_type)) {
+ if (cd->type && !isBITLK(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+ r = _crypt_load_bitlk(cd);
+ } else if (isFVAULT2(requested_type)) {
+ if (cd->type && !isFVAULT2(cd->type)) {
+ log_dbg(cd, "Context is already initialized to type %s", cd->type);
+ return -EINVAL;
+ }
+ r = _crypt_load_fvault2(cd);
+ } else
+ return -EINVAL;
+
+ return r;
+}
+
+/*
+ * crypt_init() helpers
+ */
+static int _init_by_name_crypt_none(struct crypt_device *cd)
+{
+ int r;
+ char _mode[MAX_CIPHER_LEN];
+ struct crypt_dm_active_device dmd;
+ struct dm_target *tgt = &dmd.segment;
+
+ if (cd->type || !cd->u.none.active_name)
+ return -EINVAL;
+
+ r = dm_query_device(cd, cd->u.none.active_name,
+ DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
+ if (r < 0)
+ return r;
+ if (!single_segment(&dmd) || tgt->type != DM_CRYPT)
+ r = -EINVAL;
+ if (r >= 0)
+ r = crypt_parse_name_and_mode(tgt->u.crypt.cipher,
+ cd->u.none.cipher, NULL,
+ _mode);
+
+ if (!r) {
+ r = snprintf(cd->u.none.cipher_spec, sizeof(cd->u.none.cipher_spec),
+ "%s-%s", cd->u.none.cipher, _mode);
+ if (r < 0 || (size_t)r >= sizeof(cd->u.none.cipher_spec))
+ r = -EINVAL;
+ else {
+ cd->u.none.cipher_mode = cd->u.none.cipher_spec + strlen(cd->u.none.cipher) + 1;
+ cd->u.none.key_size = tgt->u.crypt.vk->keylength;
+ r = 0;
+ }
+ }
+
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+static const char *LUKS_UUID(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+ else if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.uuid;
+ else if (isLUKS2(cd->type))
+ return cd->u.luks2.hdr.uuid;
+
+ return NULL;
+}
+
+static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
+{
+ bool found = false;
+ char **dep, *cipher_spec = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ char deps_uuid_prefix[40], *deps[MAX_DM_DEPS+1] = {};
+ const char *dev, *namei;
+ int key_nums, r;
+ struct crypt_dm_active_device dmd, dmdi = {}, dmdep = {};
+ struct dm_target *tgt = &dmd.segment, *tgti = &dmdi.segment;
+
+ r = dm_query_device(cd, name,
+ DM_ACTIVE_DEVICE |
+ DM_ACTIVE_UUID |
+ DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
+ if (r < 0)
+ return r;
+
+ if (tgt->type != DM_CRYPT && tgt->type != DM_LINEAR) {
+ log_dbg(cd, "Unsupported device table detected in %s.", name);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = -EINVAL;
+
+ if (dmd.uuid) {
+ r = snprintf(deps_uuid_prefix, sizeof(deps_uuid_prefix), CRYPT_SUBDEV "-%.32s", dmd.uuid + 6);
+ if (r < 0 || (size_t)r != (sizeof(deps_uuid_prefix) - 1))
+ r = -EINVAL;
+ }
+
+ if (r >= 0) {
+ r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps));
+ if (r)
+ goto out;
+ }
+
+ r = crypt_parse_name_and_mode(tgt->type == DM_LINEAR ? "null" : tgt->u.crypt.cipher, cipher,
+ &key_nums, cipher_mode);
+ if (r < 0) {
+ log_dbg(cd, "Cannot parse cipher and mode from active device.");
+ goto out;
+ }
+
+ dep = deps;
+
+ if (tgt->type == DM_CRYPT && tgt->u.crypt.integrity && (namei = device_dm_name(tgt->data_device))) {
+ r = dm_query_device(cd, namei, DM_ACTIVE_DEVICE, &dmdi);
+ if (r < 0)
+ goto out;
+ if (!single_segment(&dmdi) || tgti->type != DM_INTEGRITY) {
+ log_dbg(cd, "Unsupported device table detected in %s.", namei);
+ r = -EINVAL;
+ goto out;
+ }
+ if (!cd->metadata_device) {
+ device_free(cd, cd->device);
+ MOVE_REF(cd->device, tgti->data_device);
+ }
+ }
+
+ /* do not try to lookup LUKS2 header in detached header mode */
+ if (dmd.uuid && !cd->metadata_device && !found) {
+ while (*dep && !found) {
+ r = dm_query_device(cd, *dep, DM_ACTIVE_DEVICE, &dmdep);
+ if (r < 0)
+ goto out;
+
+ tgt = &dmdep.segment;
+
+ while (tgt && !found) {
+ dev = device_path(tgt->data_device);
+ if (!dev) {
+ tgt = tgt->next;
+ continue;
+ }
+ if (!strstr(dev, dm_get_dir()) ||
+ !crypt_string_in(dev + strlen(dm_get_dir()) + 1, deps, ARRAY_SIZE(deps))) {
+ device_free(cd, cd->device);
+ MOVE_REF(cd->device, tgt->data_device);
+ found = true;
+ }
+ tgt = tgt->next;
+ }
+ dep++;
+ dm_targets_free(cd, &dmdep);
+ }
+ }
+
+ if (asprintf(&cipher_spec, "%s-%s", cipher, cipher_mode) < 0) {
+ cipher_spec = NULL;
+ r = -ENOMEM;
+ goto out;
+ }
+
+ tgt = &dmd.segment;
+ r = 0;
+
+ if (isPLAIN(cd->type) && single_segment(&dmd) && tgt->type == DM_CRYPT) {
+ cd->u.plain.hdr.hash = NULL; /* no way to get this */
+ cd->u.plain.hdr.offset = tgt->u.crypt.offset;
+ cd->u.plain.hdr.skip = tgt->u.crypt.iv_offset;
+ cd->u.plain.hdr.sector_size = tgt->u.crypt.sector_size;
+ cd->u.plain.key_size = tgt->u.crypt.vk->keylength;
+ cd->u.plain.cipher = strdup(cipher);
+ MOVE_REF(cd->u.plain.cipher_spec, cipher_spec);
+ cd->u.plain.cipher_mode = cd->u.plain.cipher_spec + strlen(cipher) + 1;
+ } else if (isLOOPAES(cd->type) && single_segment(&dmd) && tgt->type == DM_CRYPT) {
+ cd->u.loopaes.hdr.offset = tgt->u.crypt.offset;
+ cd->u.loopaes.cipher = strdup(cipher);
+ MOVE_REF(cd->u.loopaes.cipher_spec, cipher_spec);
+ cd->u.loopaes.cipher_mode = cd->u.loopaes.cipher_spec + strlen(cipher) + 1;
+ /* version 3 uses last key for IV */
+ if (tgt->u.crypt.vk->keylength % key_nums)
+ key_nums++;
+ cd->u.loopaes.key_size = tgt->u.crypt.vk->keylength / key_nums;
+ } else if (isLUKS1(cd->type) || isLUKS2(cd->type)) {
+ if (crypt_metadata_device(cd)) {
+ r = _crypt_load_luks(cd, cd->type, true, false);
+ if (r < 0) {
+ log_dbg(cd, "LUKS device header does not match active device.");
+ crypt_set_null_type(cd);
+ device_close(cd, cd->metadata_device);
+ device_close(cd, cd->device);
+ r = 0;
+ goto out;
+ }
+ /* check whether UUIDs match each other */
+ r = crypt_uuid_cmp(dmd.uuid, LUKS_UUID(cd));
+ if (r < 0) {
+ log_dbg(cd, "LUKS device header uuid: %s mismatches DM returned uuid %s",
+ LUKS_UUID(cd), dmd.uuid);
+ crypt_free_type(cd, NULL);
+ r = 0;
+ goto out;
+ }
+ } else {
+ log_dbg(cd, "LUKS device header not available.");
+ crypt_set_null_type(cd);
+ r = 0;
+ }
+ } else if (isTCRYPT(cd->type) && single_segment(&dmd) && tgt->type == DM_CRYPT) {
+ r = TCRYPT_init_by_name(cd, name, dmd.uuid, tgt, &cd->device,
+ &cd->u.tcrypt.params, &cd->u.tcrypt.hdr);
+ } else if (isBITLK(cd->type)) {
+ r = _crypt_load_bitlk(cd);
+ if (r < 0) {
+ log_dbg(cd, "BITLK device header not available.");
+ crypt_set_null_type(cd);
+ r = 0;
+ }
+ } else if (isFVAULT2(cd->type)) {
+ r = _crypt_load_fvault2(cd);
+ if (r < 0) {
+ log_dbg(cd, "FVAULT2 device header not available.");
+ crypt_set_null_type(cd);
+ r = 0;
+ }
+ }
+out:
+ dm_targets_free(cd, &dmd);
+ dm_targets_free(cd, &dmdi);
+ dm_targets_free(cd, &dmdep);
+ free(CONST_CAST(void*)dmd.uuid);
+ free(cipher_spec);
+ dep = deps;
+ while (*dep)
+ free(*dep++);
+ return r;
+}
+
+static int _init_by_name_verity(struct crypt_device *cd, const char *name)
+{
+ struct crypt_dm_active_device dmd;
+ struct dm_target *tgt = &dmd.segment;
+ int r;
+
+ r = dm_query_device(cd, name,
+ DM_ACTIVE_DEVICE |
+ DM_ACTIVE_VERITY_HASH_DEVICE |
+ DM_ACTIVE_VERITY_ROOT_HASH |
+ DM_ACTIVE_VERITY_PARAMS, &dmd);
+ if (r < 0)
+ return r;
+ if (!single_segment(&dmd) || tgt->type != DM_VERITY) {
+ log_dbg(cd, "Unsupported device table detected in %s.", name);
+ r = -EINVAL;
+ goto out;
+ }
+ if (r > 0)
+ r = 0;
+
+ if (isVERITY(cd->type)) {
+ cd->u.verity.uuid = NULL; // FIXME
+ cd->u.verity.hdr.flags = CRYPT_VERITY_NO_HEADER; //FIXME
+ cd->u.verity.hdr.data_size = tgt->u.verity.vp->data_size;
+ cd->u.verity.root_hash_size = tgt->u.verity.root_hash_size;
+ MOVE_REF(cd->u.verity.hdr.hash_name, tgt->u.verity.vp->hash_name);
+ cd->u.verity.hdr.data_device = NULL;
+ cd->u.verity.hdr.hash_device = NULL;
+ cd->u.verity.hdr.data_block_size = tgt->u.verity.vp->data_block_size;
+ cd->u.verity.hdr.hash_block_size = tgt->u.verity.vp->hash_block_size;
+ cd->u.verity.hdr.hash_area_offset = tgt->u.verity.hash_offset;
+ cd->u.verity.hdr.fec_area_offset = tgt->u.verity.fec_offset;
+ cd->u.verity.hdr.hash_type = tgt->u.verity.vp->hash_type;
+ cd->u.verity.hdr.flags = tgt->u.verity.vp->flags;
+ cd->u.verity.hdr.salt_size = tgt->u.verity.vp->salt_size;
+ MOVE_REF(cd->u.verity.hdr.salt, tgt->u.verity.vp->salt);
+ MOVE_REF(cd->u.verity.hdr.fec_device, tgt->u.verity.vp->fec_device);
+ cd->u.verity.hdr.fec_roots = tgt->u.verity.vp->fec_roots;
+ MOVE_REF(cd->u.verity.fec_device, tgt->u.verity.fec_device);
+ MOVE_REF(cd->metadata_device, tgt->u.verity.hash_device);
+ MOVE_REF(cd->u.verity.root_hash, tgt->u.verity.root_hash);
+ }
+out:
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+static int _init_by_name_integrity(struct crypt_device *cd, const char *name)
+{
+ struct crypt_dm_active_device dmd;
+ struct dm_target *tgt = &dmd.segment;
+ int r;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_DEVICE |
+ DM_ACTIVE_CRYPT_KEY |
+ DM_ACTIVE_CRYPT_KEYSIZE |
+ DM_ACTIVE_INTEGRITY_PARAMS, &dmd);
+ if (r < 0)
+ return r;
+ if (!single_segment(&dmd) || tgt->type != DM_INTEGRITY) {
+ log_dbg(cd, "Unsupported device table detected in %s.", name);
+ r = -EINVAL;
+ goto out;
+ }
+ if (r > 0)
+ r = 0;
+
+ if (isINTEGRITY(cd->type)) {
+ cd->u.integrity.params.tag_size = tgt->u.integrity.tag_size;
+ cd->u.integrity.params.sector_size = tgt->u.integrity.sector_size;
+ cd->u.integrity.params.journal_size = tgt->u.integrity.journal_size;
+ cd->u.integrity.params.journal_watermark = tgt->u.integrity.journal_watermark;
+ cd->u.integrity.params.journal_commit_time = tgt->u.integrity.journal_commit_time;
+ cd->u.integrity.params.interleave_sectors = tgt->u.integrity.interleave_sectors;
+ cd->u.integrity.params.buffer_sectors = tgt->u.integrity.buffer_sectors;
+ MOVE_REF(cd->u.integrity.params.integrity, tgt->u.integrity.integrity);
+ MOVE_REF(cd->u.integrity.params.journal_integrity, tgt->u.integrity.journal_integrity);
+ MOVE_REF(cd->u.integrity.params.journal_crypt, tgt->u.integrity.journal_crypt);
+
+ if (tgt->u.integrity.vk)
+ cd->u.integrity.params.integrity_key_size = tgt->u.integrity.vk->keylength;
+ if (tgt->u.integrity.journal_integrity_key)
+ cd->u.integrity.params.journal_integrity_key_size = tgt->u.integrity.journal_integrity_key->keylength;
+ if (tgt->u.integrity.journal_crypt_key)
+ cd->u.integrity.params.integrity_key_size = tgt->u.integrity.journal_crypt_key->keylength;
+ MOVE_REF(cd->metadata_device, tgt->u.integrity.meta_device);
+ }
+out:
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int crypt_init_by_name_and_header(struct crypt_device **cd,
+ const char *name,
+ const char *header_device)
+{
+ crypt_status_info ci;
+ struct crypt_dm_active_device dmd;
+ struct dm_target *tgt = &dmd.segment;
+ int r;
+
+ if (!cd || !name)
+ return -EINVAL;
+
+ log_dbg(NULL, "Allocating crypt device context by device %s.", name);
+
+ ci = crypt_status(NULL, name);
+ if (ci == CRYPT_INVALID)
+ return -ENODEV;
+
+ if (ci < CRYPT_ACTIVE) {
+ log_err(NULL, _("Device %s is not active."), name);
+ return -ENODEV;
+ }
+
+ r = dm_query_device(NULL, name, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &dmd);
+ if (r < 0)
+ return r;
+
+ *cd = NULL;
+
+ if (header_device) {
+ r = crypt_init(cd, header_device);
+ } else {
+ r = crypt_init(cd, device_path(tgt->data_device));
+
+ /* Underlying device disappeared but mapping still active */
+ if (!tgt->data_device || r == -ENOTBLK)
+ log_verbose(NULL, _("Underlying device for crypt device %s disappeared."),
+ name);
+
+ /* Underlying device is not readable but crypt mapping exists */
+ if (r == -ENOTBLK)
+ r = crypt_init(cd, NULL);
+ }
+
+ if (r < 0)
+ goto out;
+
+ if (dmd.uuid) {
+ if (!strncmp(CRYPT_PLAIN, dmd.uuid, sizeof(CRYPT_PLAIN)-1))
+ (*cd)->type = strdup(CRYPT_PLAIN);
+ else if (!strncmp(CRYPT_LOOPAES, dmd.uuid, sizeof(CRYPT_LOOPAES)-1))
+ (*cd)->type = strdup(CRYPT_LOOPAES);
+ else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1))
+ (*cd)->type = strdup(CRYPT_LUKS1);
+ else if (!strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1))
+ (*cd)->type = strdup(CRYPT_LUKS2);
+ else if (!strncmp(CRYPT_VERITY, dmd.uuid, sizeof(CRYPT_VERITY)-1))
+ (*cd)->type = strdup(CRYPT_VERITY);
+ else if (!strncmp(CRYPT_TCRYPT, dmd.uuid, sizeof(CRYPT_TCRYPT)-1))
+ (*cd)->type = strdup(CRYPT_TCRYPT);
+ else if (!strncmp(CRYPT_INTEGRITY, dmd.uuid, sizeof(CRYPT_INTEGRITY)-1))
+ (*cd)->type = strdup(CRYPT_INTEGRITY);
+ else if (!strncmp(CRYPT_BITLK, dmd.uuid, sizeof(CRYPT_BITLK)-1))
+ (*cd)->type = strdup(CRYPT_BITLK);
+ else if (!strncmp(CRYPT_FVAULT2, dmd.uuid, sizeof(CRYPT_FVAULT2)-1))
+ (*cd)->type = strdup(CRYPT_FVAULT2);
+ else
+ log_dbg(NULL, "Unknown UUID set, some parameters are not set.");
+ } else
+ log_dbg(NULL, "Active device has no UUID set, some parameters are not set.");
+
+ if (header_device) {
+ r = crypt_set_data_device(*cd, device_path(tgt->data_device));
+ if (r < 0)
+ goto out;
+ }
+
+ /* Try to initialize basic parameters from active device */
+
+ if (tgt->type == DM_CRYPT || tgt->type == DM_LINEAR)
+ r = _init_by_name_crypt(*cd, name);
+ else if (tgt->type == DM_VERITY)
+ r = _init_by_name_verity(*cd, name);
+ else if (tgt->type == DM_INTEGRITY)
+ r = _init_by_name_integrity(*cd, name);
+out:
+ if (r < 0) {
+ crypt_free(*cd);
+ *cd = NULL;
+ } else if (!(*cd)->type) {
+ /* For anonymous device (no header found) remember initialized name */
+ (*cd)->u.none.active_name = strdup(name);
+ }
+
+ free(CONST_CAST(void*)dmd.uuid);
+ dm_targets_free(NULL, &dmd);
+ return r;
+}
+
+int crypt_init_by_name(struct crypt_device **cd, const char *name)
+{
+ return crypt_init_by_name_and_header(cd, name, NULL);
+}
+
+/*
+ * crypt_format() helpers
+ */
+static int _crypt_format_plain(struct crypt_device *cd,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ size_t volume_key_size,
+ struct crypt_params_plain *params)
+{
+ unsigned int sector_size = params ? params->sector_size : SECTOR_SIZE;
+ uint64_t dev_size;
+
+ if (!cipher || !cipher_mode) {
+ log_err(cd, _("Invalid plain crypt parameters."));
+ return -EINVAL;
+ }
+
+ if (volume_key_size > 1024) {
+ log_err(cd, _("Invalid key size."));
+ return -EINVAL;
+ }
+
+ if (uuid) {
+ log_err(cd, _("UUID is not supported for this crypt type."));
+ return -EINVAL;
+ }
+
+ if (cd->metadata_device) {
+ log_err(cd, _("Detached metadata device is not supported for this crypt type."));
+ return -EINVAL;
+ }
+
+ /* For compatibility with old params structure */
+ if (!sector_size)
+ sector_size = SECTOR_SIZE;
+
+ if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE ||
+ NOTPOW2(sector_size)) {
+ log_err(cd, _("Unsupported encryption sector size."));
+ return -EINVAL;
+ }
+
+ if (sector_size > SECTOR_SIZE && !device_size(cd->device, &dev_size)) {
+ if (params && params->offset)
+ dev_size -= (params->offset * SECTOR_SIZE);
+ if (dev_size % sector_size) {
+ log_err(cd, _("Device size is not aligned to requested sector size."));
+ return -EINVAL;
+ }
+ device_set_block_size(crypt_data_device(cd), sector_size);
+ }
+
+ if (!(cd->type = strdup(CRYPT_PLAIN)))
+ return -ENOMEM;
+
+ cd->u.plain.key_size = volume_key_size;
+ cd->volume_key = crypt_alloc_volume_key(volume_key_size, NULL);
+ if (!cd->volume_key)
+ return -ENOMEM;
+
+ if (asprintf(&cd->u.plain.cipher_spec, "%s-%s", cipher, cipher_mode) < 0) {
+ cd->u.plain.cipher_spec = NULL;
+ return -ENOMEM;
+ }
+ cd->u.plain.cipher = strdup(cipher);
+ cd->u.plain.cipher_mode = cd->u.plain.cipher_spec + strlen(cipher) + 1;
+
+ if (params && params->hash)
+ cd->u.plain.hdr.hash = strdup(params->hash);
+
+ cd->u.plain.hdr.offset = params ? params->offset : 0;
+ cd->u.plain.hdr.skip = params ? params->skip : 0;
+ cd->u.plain.hdr.size = params ? params->size : 0;
+ cd->u.plain.hdr.sector_size = sector_size;
+
+ if (!cd->u.plain.cipher)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int _crypt_format_luks1(struct crypt_device *cd,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ const char *volume_key,
+ size_t volume_key_size,
+ struct crypt_params_luks1 *params)
+{
+ int r;
+ unsigned long required_alignment = DEFAULT_DISK_ALIGNMENT;
+ unsigned long alignment_offset = 0;
+ uint64_t dev_size;
+
+ if (!cipher || !cipher_mode)
+ return -EINVAL;
+
+ if (!crypt_metadata_device(cd)) {
+ log_err(cd, _("Can't format LUKS without device."));
+ return -EINVAL;
+ }
+
+ if (params && cd->data_offset && params->data_alignment &&
+ (cd->data_offset % params->data_alignment)) {
+ log_err(cd, _("Requested data alignment is not compatible with data offset."));
+ return -EINVAL;
+ }
+
+ if (!(cd->type = strdup(CRYPT_LUKS1)))
+ return -ENOMEM;
+
+ if (volume_key)
+ cd->volume_key = crypt_alloc_volume_key(volume_key_size,
+ volume_key);
+ else
+ cd->volume_key = crypt_generate_volume_key(cd, volume_key_size);
+
+ if (!cd->volume_key)
+ return -ENOMEM;
+
+ if (verify_pbkdf_params(cd, &cd->pbkdf)) {
+ r = init_pbkdf_type(cd, NULL, CRYPT_LUKS1);
+ if (r)
+ return r;
+ }
+
+ if (params && params->hash && strcmp(params->hash, cd->pbkdf.hash)) {
+ free(CONST_CAST(void*)cd->pbkdf.hash);
+ cd->pbkdf.hash = strdup(params->hash);
+ if (!cd->pbkdf.hash)
+ return -ENOMEM;
+ }
+
+ if (params && params->data_device) {
+ if (!cd->metadata_device)
+ cd->metadata_device = cd->device;
+ else
+ device_free(cd, cd->device);
+ cd->device = NULL;
+ if (device_alloc(cd, &cd->device, params->data_device) < 0)
+ return -ENOMEM;
+ }
+
+ if (params && cd->metadata_device) {
+ /* For detached header the alignment is used directly as data offset */
+ if (!cd->data_offset)
+ cd->data_offset = params->data_alignment;
+ required_alignment = params->data_alignment * SECTOR_SIZE;
+ } else if (params && params->data_alignment) {
+ required_alignment = params->data_alignment * SECTOR_SIZE;
+ } else
+ device_topology_alignment(cd, cd->device,
+ &required_alignment,
+ &alignment_offset, DEFAULT_DISK_ALIGNMENT);
+
+ r = LUKS_check_cipher(cd, volume_key_size, cipher, cipher_mode);
+ if (r < 0)
+ return r;
+
+ r = LUKS_generate_phdr(&cd->u.luks1.hdr, cd->volume_key, cipher, cipher_mode,
+ cd->pbkdf.hash, uuid,
+ cd->data_offset * SECTOR_SIZE,
+ alignment_offset, required_alignment, cd);
+ if (r < 0)
+ return r;
+
+ r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL);
+ if (r < 0)
+ return r;
+
+
+ if (asprintf(&cd->u.luks1.cipher_spec, "%s-%s", cipher, cipher_mode) < 0) {
+ cd->u.luks1.cipher_spec = NULL;
+ return -ENOMEM;
+ }
+
+ r = LUKS_wipe_header_areas(&cd->u.luks1.hdr, cd);
+ if (r < 0) {
+ free(cd->u.luks1.cipher_spec);
+ log_err(cd, _("Cannot wipe header on device %s."),
+ mdata_device_path(cd));
+ return r;
+ }
+
+ r = LUKS_write_phdr(&cd->u.luks1.hdr, cd);
+ if (r) {
+ free(cd->u.luks1.cipher_spec);
+ return r;
+ }
+
+ if (!device_size(crypt_data_device(cd), &dev_size) &&
+ dev_size <= (crypt_get_data_offset(cd) * SECTOR_SIZE))
+ log_std(cd, _("Device %s is too small for activation, there is no remaining space for data.\n"),
+ device_path(crypt_data_device(cd)));
+
+ return 0;
+}
+
+static int _crypt_format_luks2(struct crypt_device *cd,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ const char *volume_key,
+ size_t volume_key_size,
+ struct crypt_params_luks2 *params,
+ bool sector_size_autodetect)
+{
+ int r, integrity_key_size = 0;
+ unsigned long required_alignment = DEFAULT_DISK_ALIGNMENT;
+ unsigned long alignment_offset = 0;
+ unsigned int sector_size;
+ const char *integrity = params ? params->integrity : NULL;
+ uint64_t dev_size;
+ uint32_t dmc_flags;
+
+ cd->u.luks2.hdr.jobj = NULL;
+ cd->u.luks2.keyslot_cipher = NULL;
+
+ if (!cipher || !cipher_mode)
+ return -EINVAL;
+
+ if (!crypt_metadata_device(cd)) {
+ log_err(cd, _("Can't format LUKS without device."));
+ return -EINVAL;
+ }
+
+ if (params && cd->data_offset && params->data_alignment &&
+ (cd->data_offset % params->data_alignment)) {
+ log_err(cd, _("Requested data alignment is not compatible with data offset."));
+ return -EINVAL;
+ }
+
+ if (params && params->sector_size)
+ sector_size_autodetect = false;
+
+ if (params && params->data_device) {
+ if (!cd->metadata_device)
+ cd->metadata_device = cd->device;
+ else
+ device_free(cd, cd->device);
+ cd->device = NULL;
+ if (device_alloc(cd, &cd->device, params->data_device) < 0)
+ return -ENOMEM;
+ }
+
+ if (sector_size_autodetect) {
+ sector_size = device_optimal_encryption_sector_size(cd, crypt_data_device(cd));
+ log_dbg(cd, "Auto-detected optimal encryption sector size for device %s is %d bytes.",
+ device_path(crypt_data_device(cd)), sector_size);
+ } else
+ sector_size = params ? params->sector_size : SECTOR_SIZE;
+
+ if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE ||
+ NOTPOW2(sector_size)) {
+ log_err(cd, _("Unsupported encryption sector size."));
+ return -EINVAL;
+ }
+ if (sector_size != SECTOR_SIZE && !dm_flags(cd, DM_CRYPT, &dmc_flags) &&
+ !(dmc_flags & DM_SECTOR_SIZE_SUPPORTED)) {
+ if (sector_size_autodetect) {
+ log_dbg(cd, "dm-crypt does not support encryption sector size option. Reverting to 512 bytes.");
+ sector_size = SECTOR_SIZE;
+ } else
+ log_std(cd, _("WARNING: The device activation will fail, dm-crypt is missing "
+ "support for requested encryption sector size.\n"));
+ }
+
+ if (integrity) {
+ if (params->integrity_params) {
+ /* Standalone dm-integrity must not be used */
+ if (params->integrity_params->integrity ||
+ params->integrity_params->integrity_key_size)
+ return -EINVAL;
+ /* FIXME: journal encryption and MAC is here not yet supported */
+ if (params->integrity_params->journal_crypt ||
+ params->integrity_params->journal_integrity)
+ return -ENOTSUP;
+ }
+ if (!INTEGRITY_tag_size(integrity, cipher, cipher_mode)) {
+ if (!strcmp(integrity, "none"))
+ integrity = NULL;
+ else
+ return -EINVAL;
+ }
+ integrity_key_size = INTEGRITY_key_size(integrity);
+ if ((integrity_key_size < 0) || (integrity_key_size >= (int)volume_key_size)) {
+ log_err(cd, _("Volume key is too small for encryption with integrity extensions."));
+ return -EINVAL;
+ }
+ }
+
+ r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL);
+ if (r < 0)
+ return r;
+
+ if (!(cd->type = strdup(CRYPT_LUKS2)))
+ return -ENOMEM;
+
+ if (volume_key)
+ cd->volume_key = crypt_alloc_volume_key(volume_key_size,
+ volume_key);
+ else
+ cd->volume_key = crypt_generate_volume_key(cd, volume_key_size);
+
+ if (!cd->volume_key)
+ return -ENOMEM;
+
+ if (params && params->pbkdf)
+ r = crypt_set_pbkdf_type(cd, params->pbkdf);
+ else if (verify_pbkdf_params(cd, &cd->pbkdf))
+ r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2);
+
+ if (r < 0)
+ return r;
+
+ if (params && cd->metadata_device) {
+ /* For detached header the alignment is used directly as data offset */
+ if (!cd->data_offset)
+ cd->data_offset = params->data_alignment;
+ required_alignment = params->data_alignment * SECTOR_SIZE;
+ } else if (params && params->data_alignment) {
+ required_alignment = params->data_alignment * SECTOR_SIZE;
+ } else
+ device_topology_alignment(cd, cd->device,
+ &required_alignment,
+ &alignment_offset, DEFAULT_DISK_ALIGNMENT);
+
+ r = device_size(crypt_data_device(cd), &dev_size);
+ if (r < 0)
+ goto out;
+
+ if (sector_size_autodetect) {
+ if (cd->data_offset && MISALIGNED(cd->data_offset, sector_size)) {
+ log_dbg(cd, "Data offset not aligned to sector size. Reverting to 512 bytes.");
+ sector_size = SECTOR_SIZE;
+ } else if (MISALIGNED(dev_size - (uint64_t)required_alignment - (uint64_t)alignment_offset, sector_size)) {
+ /* underflow does not affect misalignment checks */
+ log_dbg(cd, "Device size is not aligned to sector size. Reverting to 512 bytes.");
+ sector_size = SECTOR_SIZE;
+ }
+ }
+
+ /* FIXME: allow this later also for normal ciphers (check AF_ALG availability. */
+ if (integrity && !integrity_key_size) {
+ r = crypt_cipher_check_kernel(cipher, cipher_mode, integrity, volume_key_size);
+ if (r < 0) {
+ log_err(cd, _("Cipher %s-%s (key size %zd bits) is not available."),
+ cipher, cipher_mode, volume_key_size * 8);
+ goto out;
+ }
+ }
+
+ if ((!integrity || integrity_key_size) && !crypt_cipher_wrapped_key(cipher, cipher_mode) &&
+ !INTEGRITY_tag_size(NULL, cipher, cipher_mode)) {
+ r = LUKS_check_cipher(cd, volume_key_size - integrity_key_size,
+ cipher, cipher_mode);
+ if (r < 0)
+ goto out;
+ }
+
+ r = LUKS2_generate_hdr(cd, &cd->u.luks2.hdr, cd->volume_key,
+ cipher, cipher_mode,
+ integrity, uuid,
+ sector_size,
+ cd->data_offset * SECTOR_SIZE,
+ alignment_offset,
+ required_alignment,
+ cd->metadata_size, cd->keyslots_size);
+ if (r < 0)
+ goto out;
+
+ if (cd->metadata_size && (cd->metadata_size != LUKS2_metadata_size(&cd->u.luks2.hdr)))
+ log_std(cd, _("WARNING: LUKS2 metadata size changed to %" PRIu64 " bytes.\n"),
+ LUKS2_metadata_size(&cd->u.luks2.hdr));
+
+ if (cd->keyslots_size && (cd->keyslots_size != LUKS2_keyslots_size(&cd->u.luks2.hdr)))
+ log_std(cd, _("WARNING: LUKS2 keyslots area size changed to %" PRIu64 " bytes.\n"),
+ LUKS2_keyslots_size(&cd->u.luks2.hdr));
+
+ if (!integrity && sector_size > SECTOR_SIZE) {
+ dev_size -= (crypt_get_data_offset(cd) * SECTOR_SIZE);
+ if (dev_size % sector_size) {
+ log_err(cd, _("Device size is not aligned to requested sector size."));
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (params && (params->label || params->subsystem)) {
+ r = LUKS2_hdr_labels(cd, &cd->u.luks2.hdr,
+ params->label, params->subsystem, 0);
+ if (r < 0)
+ goto out;
+ }
+
+ device_set_block_size(crypt_data_device(cd), sector_size);
+
+ r = LUKS2_wipe_header_areas(cd, &cd->u.luks2.hdr, cd->metadata_device != NULL);
+ if (r < 0) {
+ log_err(cd, _("Cannot wipe header on device %s."),
+ mdata_device_path(cd));
+ if (dev_size < LUKS2_hdr_and_areas_size(&cd->u.luks2.hdr))
+ log_err(cd, _("Device %s is too small."), device_path(crypt_metadata_device(cd)));
+ goto out;
+ }
+
+ /* Wipe integrity superblock and create integrity superblock */
+ if (crypt_get_integrity_tag_size(cd)) {
+ r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_ZERO,
+ crypt_get_data_offset(cd) * SECTOR_SIZE,
+ 8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL);
+ if (r < 0) {
+ if (r == -EBUSY)
+ log_err(cd, _("Cannot format device %s in use."),
+ data_device_path(cd));
+ else if (r == -EACCES) {
+ log_err(cd, _("Cannot format device %s, permission denied."),
+ data_device_path(cd));
+ r = -EINVAL;
+ } else
+ log_err(cd, _("Cannot wipe header on device %s."),
+ data_device_path(cd));
+
+ goto out;
+ }
+
+ r = INTEGRITY_format(cd, params ? params->integrity_params : NULL, NULL, NULL);
+ if (r)
+ log_err(cd, _("Cannot format integrity for device %s."),
+ data_device_path(cd));
+ }
+
+ if (r < 0)
+ goto out;
+
+ /* override sequence id check with format */
+ r = LUKS2_hdr_write_force(cd, &cd->u.luks2.hdr);
+ if (r < 0) {
+ if (r == -EBUSY)
+ log_err(cd, _("Cannot format device %s in use."),
+ mdata_device_path(cd));
+ else if (r == -EACCES) {
+ log_err(cd, _("Cannot format device %s, permission denied."),
+ mdata_device_path(cd));
+ r = -EINVAL;
+ } else
+ log_err(cd, _("Cannot format device %s."),
+ mdata_device_path(cd));
+ }
+
+out:
+ if (r) {
+ LUKS2_hdr_free(cd, &cd->u.luks2.hdr);
+ return r;
+ }
+
+ /* Device size can be larger now if it is a file container */
+ if (!device_size(crypt_data_device(cd), &dev_size) &&
+ dev_size <= (crypt_get_data_offset(cd) * SECTOR_SIZE))
+ log_std(cd, _("Device %s is too small for activation, there is no remaining space for data.\n"),
+ device_path(crypt_data_device(cd)));
+
+ return 0;
+}
+
+static int _crypt_format_loopaes(struct crypt_device *cd,
+ const char *cipher,
+ const char *uuid,
+ size_t volume_key_size,
+ struct crypt_params_loopaes *params)
+{
+ if (!crypt_metadata_device(cd)) {
+ log_err(cd, _("Can't format LOOPAES without device."));
+ return -EINVAL;
+ }
+
+ if (volume_key_size > 1024) {
+ log_err(cd, _("Invalid key size."));
+ return -EINVAL;
+ }
+
+ if (uuid) {
+ log_err(cd, _("UUID is not supported for this crypt type."));
+ return -EINVAL;
+ }
+
+ if (cd->metadata_device) {
+ log_err(cd, _("Detached metadata device is not supported for this crypt type."));
+ return -EINVAL;
+ }
+
+ if (!(cd->type = strdup(CRYPT_LOOPAES)))
+ return -ENOMEM;
+
+ cd->u.loopaes.key_size = volume_key_size;
+
+ cd->u.loopaes.cipher = strdup(cipher ?: DEFAULT_LOOPAES_CIPHER);
+
+ if (params && params->hash)
+ cd->u.loopaes.hdr.hash = strdup(params->hash);
+
+ cd->u.loopaes.hdr.offset = params ? params->offset : 0;
+ cd->u.loopaes.hdr.skip = params ? params->skip : 0;
+
+ return 0;
+}
+
+static int _crypt_format_verity(struct crypt_device *cd,
+ const char *uuid,
+ struct crypt_params_verity *params)
+{
+ int r = 0, hash_size;
+ uint64_t data_device_size, hash_blocks_size;
+ struct device *fec_device = NULL;
+ char *fec_device_path = NULL, *hash_name = NULL, *root_hash = NULL, *salt = NULL;
+
+ if (!crypt_metadata_device(cd)) {
+ log_err(cd, _("Can't format VERITY without device."));
+ return -EINVAL;
+ }
+
+ if (!params)
+ return -EINVAL;
+
+ if (!params->data_device && !cd->metadata_device)
+ return -EINVAL;
+
+ if (params->hash_type > VERITY_MAX_HASH_TYPE) {
+ log_err(cd, _("Unsupported VERITY hash type %d."), params->hash_type);
+ return -EINVAL;
+ }
+
+ if (VERITY_BLOCK_SIZE_OK(params->data_block_size) ||
+ VERITY_BLOCK_SIZE_OK(params->hash_block_size)) {
+ log_err(cd, _("Unsupported VERITY block size."));
+ return -EINVAL;
+ }
+
+ if (MISALIGNED_512(params->hash_area_offset)) {
+ log_err(cd, _("Unsupported VERITY hash offset."));
+ return -EINVAL;
+ }
+
+ if (MISALIGNED_512(params->fec_area_offset)) {
+ log_err(cd, _("Unsupported VERITY FEC offset."));
+ return -EINVAL;
+ }
+
+ if (!(cd->type = strdup(CRYPT_VERITY)))
+ return -ENOMEM;
+
+ if (params->data_device) {
+ r = crypt_set_data_device(cd, params->data_device);
+ if (r)
+ return r;
+ }
+
+ if (!params->data_size) {
+ r = device_size(cd->device, &data_device_size);
+ if (r < 0)
+ return r;
+
+ cd->u.verity.hdr.data_size = data_device_size / params->data_block_size;
+ } else
+ cd->u.verity.hdr.data_size = params->data_size;
+
+ if (device_is_identical(crypt_metadata_device(cd), crypt_data_device(cd)) > 0 &&
+ (cd->u.verity.hdr.data_size * params->data_block_size) > params->hash_area_offset) {
+ log_err(cd, _("Data area overlaps with hash area."));
+ return -EINVAL;
+ }
+
+ hash_size = crypt_hash_size(params->hash_name);
+ if (hash_size <= 0) {
+ log_err(cd, _("Hash algorithm %s not supported."),
+ params->hash_name);
+ return -EINVAL;
+ }
+ cd->u.verity.root_hash_size = hash_size;
+
+ if (params->fec_device) {
+ fec_device_path = strdup(params->fec_device);
+ if (!fec_device_path)
+ return -ENOMEM;
+ r = device_alloc(cd, &fec_device, params->fec_device);
+ if (r < 0) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ hash_blocks_size = VERITY_hash_blocks(cd, params) * params->hash_block_size;
+ if (device_is_identical(crypt_metadata_device(cd), fec_device) > 0 &&
+ (params->hash_area_offset + hash_blocks_size) > params->fec_area_offset) {
+ log_err(cd, _("Hash area overlaps with FEC area."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (device_is_identical(crypt_data_device(cd), fec_device) > 0 &&
+ (cd->u.verity.hdr.data_size * params->data_block_size) > params->fec_area_offset) {
+ log_err(cd, _("Data area overlaps with FEC area."));
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ root_hash = malloc(cd->u.verity.root_hash_size);
+ hash_name = strdup(params->hash_name);
+ salt = malloc(params->salt_size);
+
+ if (!root_hash || !hash_name || !salt) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ cd->u.verity.hdr.flags = params->flags;
+ cd->u.verity.root_hash = root_hash;
+ cd->u.verity.hdr.hash_name = hash_name;
+ cd->u.verity.hdr.data_device = NULL;
+ cd->u.verity.fec_device = fec_device;
+ cd->u.verity.hdr.fec_device = fec_device_path;
+ cd->u.verity.hdr.fec_roots = params->fec_roots;
+ cd->u.verity.hdr.data_block_size = params->data_block_size;
+ cd->u.verity.hdr.hash_block_size = params->hash_block_size;
+ cd->u.verity.hdr.hash_area_offset = params->hash_area_offset;
+ cd->u.verity.hdr.fec_area_offset = params->fec_area_offset;
+ cd->u.verity.hdr.hash_type = params->hash_type;
+ cd->u.verity.hdr.flags = params->flags;
+ cd->u.verity.hdr.salt_size = params->salt_size;
+ cd->u.verity.hdr.salt = salt;
+
+ if (params->salt)
+ memcpy(salt, params->salt, params->salt_size);
+ else
+ r = crypt_random_get(cd, salt, params->salt_size, CRYPT_RND_SALT);
+ if (r)
+ goto out;
+
+ if (params->flags & CRYPT_VERITY_CREATE_HASH) {
+ r = VERITY_create(cd, &cd->u.verity.hdr,
+ cd->u.verity.root_hash, cd->u.verity.root_hash_size);
+ if (!r && params->fec_device)
+ r = VERITY_FEC_process(cd, &cd->u.verity.hdr, cd->u.verity.fec_device, 0, NULL);
+ if (r)
+ goto out;
+ }
+
+ if (!(params->flags & CRYPT_VERITY_NO_HEADER)) {
+ if (uuid) {
+ if (!(cd->u.verity.uuid = strdup(uuid)))
+ r = -ENOMEM;
+ } else
+ r = VERITY_UUID_generate(&cd->u.verity.uuid);
+
+ if (!r)
+ r = VERITY_write_sb(cd, cd->u.verity.hdr.hash_area_offset,
+ cd->u.verity.uuid,
+ &cd->u.verity.hdr);
+ }
+
+out:
+ if (r) {
+ device_free(cd, fec_device);
+ free(root_hash);
+ free(hash_name);
+ free(fec_device_path);
+ free(salt);
+ }
+
+ return r;
+}
+
+static int _crypt_format_integrity(struct crypt_device *cd,
+ const char *uuid,
+ struct crypt_params_integrity *params)
+{
+ int r;
+ uint32_t integrity_tag_size;
+ char *integrity = NULL, *journal_integrity = NULL, *journal_crypt = NULL;
+ struct volume_key *journal_crypt_key = NULL, *journal_mac_key = NULL;
+
+ if (!params)
+ return -EINVAL;
+
+ if (uuid) {
+ log_err(cd, _("UUID is not supported for this crypt type."));
+ return -EINVAL;
+ }
+
+ r = device_check_access(cd, crypt_metadata_device(cd), DEV_EXCL);
+ if (r < 0)
+ return r;
+
+ /* Wipe first 8 sectors - fs magic numbers etc. */
+ r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0,
+ 8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL);
+ if (r < 0) {
+ log_err(cd, _("Cannot wipe header on device %s."),
+ mdata_device_path(cd));
+ return r;
+ }
+
+ if (!(cd->type = strdup(CRYPT_INTEGRITY)))
+ return -ENOMEM;
+
+ if (params->journal_crypt_key) {
+ journal_crypt_key = crypt_alloc_volume_key(params->journal_crypt_key_size,
+ params->journal_crypt_key);
+ if (!journal_crypt_key)
+ return -ENOMEM;
+ }
+
+ if (params->journal_integrity_key) {
+ journal_mac_key = crypt_alloc_volume_key(params->journal_integrity_key_size,
+ params->journal_integrity_key);
+ if (!journal_mac_key) {
+ r = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (params->integrity && !(integrity = strdup(params->integrity))) {
+ r = -ENOMEM;
+ goto out;
+ }
+ if (params->journal_integrity && !(journal_integrity = strdup(params->journal_integrity))) {
+ r = -ENOMEM;
+ goto out;
+ }
+ if (params->journal_crypt && !(journal_crypt = strdup(params->journal_crypt))) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ integrity_tag_size = INTEGRITY_hash_tag_size(integrity);
+ if (integrity_tag_size > 0 && params->tag_size && integrity_tag_size != params->tag_size)
+ log_std(cd, _("WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"),
+ params->tag_size, integrity, integrity_tag_size);
+
+ if (params->tag_size)
+ integrity_tag_size = params->tag_size;
+
+ cd->u.integrity.journal_crypt_key = journal_crypt_key;
+ cd->u.integrity.journal_mac_key = journal_mac_key;
+ cd->u.integrity.params.journal_size = params->journal_size;
+ cd->u.integrity.params.journal_watermark = params->journal_watermark;
+ cd->u.integrity.params.journal_commit_time = params->journal_commit_time;
+ cd->u.integrity.params.interleave_sectors = params->interleave_sectors;
+ cd->u.integrity.params.buffer_sectors = params->buffer_sectors;
+ cd->u.integrity.params.sector_size = params->sector_size;
+ cd->u.integrity.params.tag_size = integrity_tag_size;
+ cd->u.integrity.params.integrity = integrity;
+ cd->u.integrity.params.journal_integrity = journal_integrity;
+ cd->u.integrity.params.journal_crypt = journal_crypt;
+
+ r = INTEGRITY_format(cd, params, cd->u.integrity.journal_crypt_key, cd->u.integrity.journal_mac_key);
+ if (r)
+ log_err(cd, _("Cannot format integrity for device %s."),
+ mdata_device_path(cd));
+out:
+ if (r) {
+ crypt_free_volume_key(journal_crypt_key);
+ crypt_free_volume_key(journal_mac_key);
+ free(integrity);
+ free(journal_integrity);
+ free(journal_crypt);
+ }
+
+ return r;
+}
+
+static int _crypt_format(struct crypt_device *cd,
+ const char *type,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ const char *volume_key,
+ size_t volume_key_size,
+ void *params,
+ bool sector_size_autodetect)
+{
+ int r;
+
+ if (!cd || !type)
+ return -EINVAL;
+
+ if (cd->type) {
+ log_dbg(cd, "Context already formatted as %s.", cd->type);
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Formatting device %s as type %s.", mdata_device_path(cd) ?: "(none)", type);
+
+ crypt_reset_null_type(cd);
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ if (isPLAIN(type))
+ r = _crypt_format_plain(cd, cipher, cipher_mode,
+ uuid, volume_key_size, params);
+ else if (isLUKS1(type))
+ r = _crypt_format_luks1(cd, cipher, cipher_mode,
+ uuid, volume_key, volume_key_size, params);
+ else if (isLUKS2(type))
+ r = _crypt_format_luks2(cd, cipher, cipher_mode,
+ uuid, volume_key, volume_key_size, params, sector_size_autodetect);
+ else if (isLOOPAES(type))
+ r = _crypt_format_loopaes(cd, cipher, uuid, volume_key_size, params);
+ else if (isVERITY(type))
+ r = _crypt_format_verity(cd, uuid, params);
+ else if (isINTEGRITY(type))
+ r = _crypt_format_integrity(cd, uuid, params);
+ else {
+ log_err(cd, _("Unknown crypt device type %s requested."), type);
+ r = -EINVAL;
+ }
+
+ if (r < 0) {
+ crypt_set_null_type(cd);
+ crypt_free_volume_key(cd->volume_key);
+ cd->volume_key = NULL;
+ }
+
+ return r;
+}
+
+CRYPT_SYMBOL_EXPORT_NEW(int, crypt_format, 2, 4,
+ /* crypt_format parameters follows */
+ struct crypt_device *cd,
+ const char *type,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ const char *volume_key,
+ size_t volume_key_size,
+ void *params)
+{
+ return _crypt_format(cd, type, cipher, cipher_mode, uuid, volume_key, volume_key_size, params, true);
+}
+
+
+CRYPT_SYMBOL_EXPORT_OLD(int, crypt_format, 2, 0,
+ /* crypt_format parameters follows */
+ struct crypt_device *cd,
+ const char *type,
+ const char *cipher,
+ const char *cipher_mode,
+ const char *uuid,
+ const char *volume_key,
+ size_t volume_key_size,
+ void *params)
+{
+ return _crypt_format(cd, type, cipher, cipher_mode, uuid, volume_key, volume_key_size, params, false);
+}
+
+int crypt_repair(struct crypt_device *cd,
+ const char *requested_type,
+ void *params __attribute__((unused)))
+{
+ int r;
+
+ if (!cd)
+ return -EINVAL;
+
+ log_dbg(cd, "Trying to repair %s crypt type from device %s.",
+ requested_type ?: "any", mdata_device_path(cd) ?: "(none)");
+
+ if (!crypt_metadata_device(cd))
+ return -EINVAL;
+
+ if (requested_type && !isLUKS(requested_type))
+ return -EINVAL;
+
+ /* Load with repair */
+ r = _crypt_load_luks(cd, requested_type, false, true);
+ if (r < 0)
+ return r;
+
+ /* cd->type and header must be set in context */
+ r = crypt_check_data_device_size(cd);
+ if (r < 0)
+ crypt_set_null_type(cd);
+
+ return r;
+}
+
+/* compare volume keys */
+static int _compare_volume_keys(struct volume_key *svk, unsigned skeyring_only,
+ struct volume_key *tvk, unsigned tkeyring_only)
+{
+ if (!svk && !tvk)
+ return 0;
+ else if (!svk || !tvk)
+ return 1;
+
+ if (svk->keylength != tvk->keylength)
+ return 1;
+
+ if (!skeyring_only && !tkeyring_only)
+ return crypt_backend_memeq(svk->key, tvk->key, svk->keylength);
+
+ if (svk->key_description && tvk->key_description)
+ return strcmp(svk->key_description, tvk->key_description);
+
+ return 0;
+}
+
+static int _compare_device_types(struct crypt_device *cd,
+ const struct crypt_dm_active_device *src,
+ const struct crypt_dm_active_device *tgt)
+{
+ if (!tgt->uuid) {
+ log_dbg(cd, "Missing device uuid in target device.");
+ return -EINVAL;
+ }
+
+ if (isLUKS2(cd->type) && !strncmp("INTEGRITY-", tgt->uuid, strlen("INTEGRITY-"))) {
+ if (crypt_uuid_cmp(tgt->uuid, src->uuid)) {
+ log_dbg(cd, "LUKS UUID mismatch.");
+ return -EINVAL;
+ }
+ } else if (isLUKS(cd->type)) {
+ if (!src->uuid || strncmp(cd->type, tgt->uuid, strlen(cd->type)) ||
+ crypt_uuid_cmp(tgt->uuid, src->uuid)) {
+ log_dbg(cd, "LUKS UUID mismatch.");
+ return -EINVAL;
+ }
+ } else if (isPLAIN(cd->type) || isLOOPAES(cd->type)) {
+ if (strncmp(cd->type, tgt->uuid, strlen(cd->type))) {
+ log_dbg(cd, "Unexpected uuid prefix %s in target device.", tgt->uuid);
+ return -EINVAL;
+ }
+ } else if (!isINTEGRITY(cd->type)) {
+ log_dbg(cd, "Unsupported device type %s for reload.", cd->type ?: "<empty>");
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+static int _compare_crypt_devices(struct crypt_device *cd,
+ const struct dm_target *src,
+ const struct dm_target *tgt)
+{
+ char *src_cipher = NULL, *src_integrity = NULL;
+ int r = -EINVAL;
+
+ /* for crypt devices keys are mandatory */
+ if (!src->u.crypt.vk || !tgt->u.crypt.vk)
+ return -EINVAL;
+
+ /* CIPHER checks */
+ if (!src->u.crypt.cipher || !tgt->u.crypt.cipher)
+ return -EINVAL;
+
+ /*
+ * dm_query_target converts capi cipher specification to dm-crypt format.
+ * We need to do same for cipher specification requested in source
+ * device.
+ */
+ if (crypt_capi_to_cipher(&src_cipher, &src_integrity, src->u.crypt.cipher, src->u.crypt.integrity))
+ return -EINVAL;
+
+ if (strcmp(src_cipher, tgt->u.crypt.cipher)) {
+ log_dbg(cd, "Cipher specs do not match.");
+ goto out;
+ }
+
+ if (tgt->u.crypt.vk->keylength == 0 && crypt_is_cipher_null(tgt->u.crypt.cipher))
+ log_dbg(cd, "Existing device uses cipher null. Skipping key comparison.");
+ else if (_compare_volume_keys(src->u.crypt.vk, 0, tgt->u.crypt.vk, tgt->u.crypt.vk->key_description != NULL)) {
+ log_dbg(cd, "Keys in context and target device do not match.");
+ goto out;
+ }
+
+ if (crypt_strcmp(src_integrity, tgt->u.crypt.integrity)) {
+ log_dbg(cd, "Integrity parameters do not match.");
+ goto out;
+ }
+
+ if (src->u.crypt.offset != tgt->u.crypt.offset ||
+ src->u.crypt.sector_size != tgt->u.crypt.sector_size ||
+ src->u.crypt.iv_offset != tgt->u.crypt.iv_offset ||
+ src->u.crypt.tag_size != tgt->u.crypt.tag_size) {
+ log_dbg(cd, "Integer parameters do not match.");
+ goto out;
+ }
+
+ if (device_is_identical(src->data_device, tgt->data_device) <= 0)
+ log_dbg(cd, "Data devices do not match.");
+ else
+ r = 0;
+
+out:
+ free(src_cipher);
+ free(src_integrity);
+
+ return r;
+}
+
+static int _compare_integrity_devices(struct crypt_device *cd,
+ const struct dm_target *src,
+ const struct dm_target *tgt)
+{
+ /*
+ * some parameters may be implicit (and set in dm-integrity ctor)
+ *
+ * journal_size
+ * journal_watermark
+ * journal_commit_time
+ * buffer_sectors
+ * interleave_sectors
+ */
+
+ /* check remaining integer values that makes sense */
+ if (src->u.integrity.tag_size != tgt->u.integrity.tag_size ||
+ src->u.integrity.offset != tgt->u.integrity.offset ||
+ src->u.integrity.sector_size != tgt->u.integrity.sector_size) {
+ log_dbg(cd, "Integer parameters do not match.");
+ return -EINVAL;
+ }
+
+ if (crypt_strcmp(src->u.integrity.integrity, tgt->u.integrity.integrity) ||
+ crypt_strcmp(src->u.integrity.journal_integrity, tgt->u.integrity.journal_integrity) ||
+ crypt_strcmp(src->u.integrity.journal_crypt, tgt->u.integrity.journal_crypt)) {
+ log_dbg(cd, "Journal parameters do not match.");
+ return -EINVAL;
+ }
+
+ /* unfortunately dm-integrity doesn't support keyring */
+ if (_compare_volume_keys(src->u.integrity.vk, 0, tgt->u.integrity.vk, 0) ||
+ _compare_volume_keys(src->u.integrity.journal_integrity_key, 0, tgt->u.integrity.journal_integrity_key, 0) ||
+ _compare_volume_keys(src->u.integrity.journal_crypt_key, 0, tgt->u.integrity.journal_crypt_key, 0)) {
+ log_dbg(cd, "Journal keys do not match.");
+ return -EINVAL;
+ }
+
+ if (device_is_identical(src->data_device, tgt->data_device) <= 0) {
+ log_dbg(cd, "Data devices do not match.");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int crypt_compare_dm_devices(struct crypt_device *cd,
+ const struct crypt_dm_active_device *src,
+ const struct crypt_dm_active_device *tgt)
+{
+ int r;
+ const struct dm_target *s, *t;
+
+ if (!src || !tgt)
+ return -EINVAL;
+
+ r = _compare_device_types(cd, src, tgt);
+ if (r)
+ return r;
+
+ s = &src->segment;
+ t = &tgt->segment;
+
+ while (s || t) {
+ if (!s || !t) {
+ log_dbg(cd, "segments count mismatch.");
+ return -EINVAL;
+ }
+ if (s->type != t->type) {
+ log_dbg(cd, "segment type mismatch.");
+ r = -EINVAL;
+ break;
+ }
+
+ switch (s->type) {
+ case DM_CRYPT:
+ r = _compare_crypt_devices(cd, s, t);
+ break;
+ case DM_INTEGRITY:
+ r = _compare_integrity_devices(cd, s, t);
+ break;
+ case DM_LINEAR:
+ r = (s->u.linear.offset == t->u.linear.offset) ? 0 : -EINVAL;
+ break;
+ default:
+ r = -ENOTSUP;
+ }
+
+ if (r)
+ break;
+
+ s = s->next;
+ t = t->next;
+ }
+
+ return r;
+}
+
+static int _reload_device(struct crypt_device *cd, const char *name,
+ struct crypt_dm_active_device *sdmd)
+{
+ int r;
+ struct crypt_dm_active_device tdmd;
+ struct dm_target *src, *tgt = &tdmd.segment;
+
+ if (!cd || !cd->type || !name || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH))
+ return -EINVAL;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE |
+ DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_INTEGRITY_PARAMS |
+ DM_ACTIVE_JOURNAL_CRYPT_KEY | DM_ACTIVE_JOURNAL_MAC_KEY, &tdmd);
+ if (r < 0) {
+ log_err(cd, _("Device %s is not active."), name);
+ return -EINVAL;
+ }
+
+ if (!single_segment(&tdmd) ||
+ (tgt->type != DM_CRYPT && tgt->type != DM_INTEGRITY) ||
+ (tgt->type == DM_CRYPT && tgt->u.crypt.tag_size)) {
+ r = -ENOTSUP;
+ log_err(cd, _("Unsupported parameters on device %s."), name);
+ goto out;
+ }
+
+ r = crypt_compare_dm_devices(cd, sdmd, &tdmd);
+ if (r) {
+ log_err(cd, _("Mismatching parameters on device %s."), name);
+ goto out;
+ }
+
+ src = &sdmd->segment;
+
+ /* Changing read only flag for active device makes no sense */
+ if (tdmd.flags & CRYPT_ACTIVATE_READONLY)
+ sdmd->flags |= CRYPT_ACTIVATE_READONLY;
+ else
+ sdmd->flags &= ~CRYPT_ACTIVATE_READONLY;
+
+ if (tgt->type == DM_CRYPT && sdmd->flags & CRYPT_ACTIVATE_KEYRING_KEY) {
+ r = crypt_volume_key_set_description(tgt->u.crypt.vk, src->u.crypt.vk->key_description);
+ if (r)
+ goto out;
+ } else if (tgt->type == DM_CRYPT) {
+ crypt_free_volume_key(tgt->u.crypt.vk);
+ tgt->u.crypt.vk = crypt_alloc_volume_key(src->u.crypt.vk->keylength, src->u.crypt.vk->key);
+ if (!tgt->u.crypt.vk) {
+ r = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (tgt->type == DM_CRYPT)
+ r = device_block_adjust(cd, src->data_device, DEV_OK,
+ src->u.crypt.offset, &sdmd->size, NULL);
+ else if (tgt->type == DM_INTEGRITY)
+ r = device_block_adjust(cd, src->data_device, DEV_OK,
+ src->u.integrity.offset, &sdmd->size, NULL);
+ else
+ r = -EINVAL;
+
+ if (r)
+ goto out;
+
+ tdmd.flags = sdmd->flags;
+ tgt->size = tdmd.size = sdmd->size;
+
+ r = dm_reload_device(cd, name, &tdmd, 0, 1);
+out:
+ dm_targets_free(cd, &tdmd);
+ free(CONST_CAST(void*)tdmd.uuid);
+
+ return r;
+}
+
+static int _reload_device_with_integrity(struct crypt_device *cd,
+ const char *name,
+ const char *iname,
+ const char *ipath,
+ struct crypt_dm_active_device *sdmd,
+ struct crypt_dm_active_device *sdmdi)
+{
+ int r;
+ struct crypt_dm_active_device tdmd, tdmdi = {};
+ struct dm_target *src, *srci, *tgt = &tdmd.segment, *tgti = &tdmdi.segment;
+ struct device *data_device = NULL;
+ bool clear = false;
+
+ if (!cd || !cd->type || !name || !iname || !(sdmd->flags & CRYPT_ACTIVATE_REFRESH))
+ return -EINVAL;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_DEVICE | DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_UUID | DM_ACTIVE_CRYPT_KEYSIZE |
+ DM_ACTIVE_CRYPT_KEY, &tdmd);
+ if (r < 0) {
+ log_err(cd, _("Device %s is not active."), name);
+ return -EINVAL;
+ }
+
+ if (!single_segment(&tdmd) || tgt->type != DM_CRYPT || !tgt->u.crypt.tag_size) {
+ log_err(cd, _("Unsupported parameters on device %s."), name);
+ r = -ENOTSUP;
+ goto out;
+ }
+
+ r = dm_query_device(cd, iname, DM_ACTIVE_DEVICE | DM_ACTIVE_UUID, &tdmdi);
+ if (r < 0) {
+ log_err(cd, _("Device %s is not active."), iname);
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!single_segment(&tdmdi) || tgti->type != DM_INTEGRITY) {
+ log_err(cd, _("Unsupported parameters on device %s."), iname);
+ r = -ENOTSUP;
+ goto out;
+ }
+
+ r = crypt_compare_dm_devices(cd, sdmdi, &tdmdi);
+ if (r) {
+ log_err(cd, _("Mismatching parameters on device %s."), iname);
+ goto out;
+ }
+
+ /* unsupported underneath dm-crypt with auth. encryption */
+ if (sdmdi->segment.u.integrity.meta_device || tdmdi.segment.u.integrity.meta_device)
+ return -ENOTSUP;
+
+ src = &sdmd->segment;
+ srci = &sdmdi->segment;
+
+ r = device_alloc(cd, &data_device, ipath);
+ if (r < 0)
+ goto out;
+
+ r = device_block_adjust(cd, srci->data_device, DEV_OK,
+ srci->u.integrity.offset, &sdmdi->size, NULL);
+ if (r)
+ goto out;
+
+ src->data_device = data_device;
+
+ r = crypt_compare_dm_devices(cd, sdmd, &tdmd);
+ if (r) {
+ log_err(cd, _("Crypt devices mismatch."));
+ goto out;
+ }
+
+ /* Changing read only flag for active device makes no sense */
+ if (tdmd.flags & CRYPT_ACTIVATE_READONLY)
+ sdmd->flags |= CRYPT_ACTIVATE_READONLY;
+ else
+ sdmd->flags &= ~CRYPT_ACTIVATE_READONLY;
+
+ if (tdmdi.flags & CRYPT_ACTIVATE_READONLY)
+ sdmdi->flags |= CRYPT_ACTIVATE_READONLY;
+ else
+ sdmdi->flags &= ~CRYPT_ACTIVATE_READONLY;
+
+ if (sdmd->flags & CRYPT_ACTIVATE_KEYRING_KEY) {
+ r = crypt_volume_key_set_description(tgt->u.crypt.vk, src->u.crypt.vk->key_description);
+ if (r)
+ goto out;
+ } else {
+ crypt_free_volume_key(tgt->u.crypt.vk);
+ tgt->u.crypt.vk = crypt_alloc_volume_key(src->u.crypt.vk->keylength, src->u.crypt.vk->key);
+ if (!tgt->u.crypt.vk) {
+ r = -ENOMEM;
+ goto out;
+ }
+ }
+
+ r = device_block_adjust(cd, src->data_device, DEV_OK,
+ src->u.crypt.offset, &sdmd->size, NULL);
+ if (r)
+ goto out;
+
+ tdmd.flags = sdmd->flags;
+ tdmd.size = sdmd->size;
+
+ if ((r = dm_reload_device(cd, iname, sdmdi, 0, 0))) {
+ log_err(cd, _("Failed to reload device %s."), iname);
+ goto out;
+ }
+
+ if ((r = dm_reload_device(cd, name, &tdmd, 0, 0))) {
+ log_err(cd, _("Failed to reload device %s."), name);
+ clear = true;
+ goto out;
+ }
+
+ if ((r = dm_suspend_device(cd, name, 0))) {
+ log_err(cd, _("Failed to suspend device %s."), name);
+ clear = true;
+ goto out;
+ }
+
+ if ((r = dm_suspend_device(cd, iname, 0))) {
+ log_err(cd, _("Failed to suspend device %s."), iname);
+ clear = true;
+ goto out;
+ }
+
+ if ((r = dm_resume_device(cd, iname, act2dmflags(sdmdi->flags)))) {
+ log_err(cd, _("Failed to resume device %s."), iname);
+ clear = true;
+ goto out;
+ }
+
+ r = dm_resume_device(cd, name, act2dmflags(tdmd.flags));
+ if (!r)
+ goto out;
+
+ /*
+ * This is worst case scenario. We have active underlying dm-integrity device with
+ * new table but dm-crypt resume failed for some reason. Tear everything down and
+ * burn it for good.
+ */
+
+ log_err(cd, _("Fatal error while reloading device %s (on top of device %s)."), name, iname);
+
+ if (dm_error_device(cd, name))
+ log_err(cd, _("Failed to switch device %s to dm-error."), name);
+ if (dm_error_device(cd, iname))
+ log_err(cd, _("Failed to switch device %s to dm-error."), iname);
+out:
+ if (clear) {
+ dm_clear_device(cd, name);
+ dm_clear_device(cd, iname);
+
+ if (dm_status_suspended(cd, name) > 0)
+ dm_resume_device(cd, name, 0);
+ if (dm_status_suspended(cd, iname) > 0)
+ dm_resume_device(cd, iname, 0);
+ }
+
+ dm_targets_free(cd, &tdmd);
+ dm_targets_free(cd, &tdmdi);
+ free(CONST_CAST(void*)tdmdi.uuid);
+ free(CONST_CAST(void*)tdmd.uuid);
+ device_free(cd, data_device);
+
+ return r;
+}
+
+int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
+{
+ struct crypt_dm_active_device dmdq, dmd = {};
+ struct dm_target *tgt = &dmdq.segment;
+ struct crypt_params_integrity params = {};
+ uint32_t supported_flags = 0;
+ uint64_t old_size;
+ int r;
+
+ /*
+ * FIXME: Also with LUKS2 we must not allow resize when there's
+ * explicit size stored in metadata (length != "dynamic")
+ */
+
+ /* Device context type must be initialized */
+ if (!cd || !cd->type || !name)
+ return -EINVAL;
+
+ if (isTCRYPT(cd->type) || isBITLK(cd->type)) {
+ log_err(cd, _("This operation is not supported for this device type."));
+ return -ENOTSUP;
+ }
+
+ log_dbg(cd, "Resizing device %s to %" PRIu64 " sectors.", name, new_size);
+
+ r = dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEYSIZE | DM_ACTIVE_CRYPT_KEY |
+ DM_ACTIVE_INTEGRITY_PARAMS | DM_ACTIVE_JOURNAL_CRYPT_KEY |
+ DM_ACTIVE_JOURNAL_MAC_KEY, &dmdq);
+ if (r < 0) {
+ log_err(cd, _("Device %s is not active."), name);
+ return -EINVAL;
+ }
+ if (!single_segment(&dmdq) || (tgt->type != DM_CRYPT && tgt->type != DM_INTEGRITY)) {
+ log_dbg(cd, "Unsupported device table detected in %s.", name);
+ r = -EINVAL;
+ goto out;
+ }
+
+ if ((dmdq.flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_key_in_keyring(cd)) {
+ r = -EPERM;
+ goto out;
+ }
+
+ if (crypt_key_in_keyring(cd)) {
+ if (!isLUKS2(cd->type)) {
+ r = -EINVAL;
+ goto out;
+ }
+ r = LUKS2_key_description_by_segment(cd, &cd->u.luks2.hdr,
+ tgt->u.crypt.vk, CRYPT_DEFAULT_SEGMENT);
+ if (r)
+ goto out;
+
+ dmdq.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ }
+
+ if (crypt_loop_device(crypt_get_device_name(cd))) {
+ log_dbg(cd, "Trying to resize underlying loop device %s.",
+ crypt_get_device_name(cd));
+ /* Here we always use default size not new_size */
+ if (crypt_loop_resize(crypt_get_device_name(cd)))
+ log_err(cd, _("Cannot resize loop device."));
+ }
+
+
+ /*
+ * Integrity device metadata are maintained by the kernel. We need to
+ * reload the device (with the same parameters) and let the kernel
+ * calculate the maximum size of integrity device and store it in the
+ * superblock.
+ */
+ if (!new_size && tgt->type == DM_INTEGRITY) {
+ r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
+ crypt_get_data_offset(cd) * SECTOR_SIZE, &old_size);
+ if (r < 0)
+ return r;
+
+ dmd.size = dmdq.size;
+ dmd.flags = dmdq.flags | CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_PRIVATE;
+
+ r = crypt_get_integrity_info(cd, &params);
+ if (r)
+ goto out;
+
+ r = dm_integrity_target_set(cd, &dmd.segment, 0, dmdq.segment.size,
+ crypt_metadata_device(cd), crypt_data_device(cd),
+ crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
+ crypt_get_sector_size(cd), tgt->u.integrity.vk, tgt->u.integrity.journal_crypt_key,
+ tgt->u.integrity.journal_integrity_key, &params);
+ if (r)
+ goto out;
+ r = _reload_device(cd, name, &dmd);
+ if (r)
+ goto out;
+
+ r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
+ crypt_get_data_offset(cd) * SECTOR_SIZE, &new_size);
+ if (r < 0)
+ return r;
+ log_dbg(cd, "Maximum integrity device size from kernel %" PRIu64, new_size);
+
+ if (old_size == new_size && new_size == dmdq.size &&
+ !dm_flags(cd, tgt->type, &supported_flags) &&
+ !(supported_flags & DM_INTEGRITY_RESIZE_SUPPORTED))
+ log_std(cd, _("WARNING: Maximum size already set or kernel doesn't support resize.\n"));
+ }
+
+ r = device_block_adjust(cd, crypt_data_device(cd), DEV_OK,
+ crypt_get_data_offset(cd), &new_size, &dmdq.flags);
+ if (r)
+ goto out;
+
+ if (MISALIGNED(new_size, (tgt->type == DM_CRYPT ? tgt->u.crypt.sector_size : tgt->u.integrity.sector_size) >> SECTOR_SHIFT)) {
+ log_err(cd, _("Device size is not aligned to requested sector size."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (MISALIGNED(new_size, device_block_size(cd, crypt_data_device(cd)) >> SECTOR_SHIFT)) {
+ log_err(cd, _("Device size is not aligned to device logical block size."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ dmd.uuid = crypt_get_uuid(cd);
+ dmd.size = new_size;
+ dmd.flags = dmdq.flags | CRYPT_ACTIVATE_REFRESH;
+
+ if (tgt->type == DM_CRYPT) {
+ r = dm_crypt_target_set(&dmd.segment, 0, new_size, crypt_data_device(cd),
+ tgt->u.crypt.vk, crypt_get_cipher_spec(cd),
+ crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
+ crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd),
+ crypt_get_sector_size(cd));
+ if (r < 0)
+ goto out;
+ } else if (tgt->type == DM_INTEGRITY) {
+ r = crypt_get_integrity_info(cd, &params);
+ if (r)
+ goto out;
+
+ r = dm_integrity_target_set(cd, &dmd.segment, 0, new_size,
+ crypt_metadata_device(cd), crypt_data_device(cd),
+ crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
+ crypt_get_sector_size(cd), tgt->u.integrity.vk, tgt->u.integrity.journal_crypt_key,
+ tgt->u.integrity.journal_integrity_key, &params);
+ if (r)
+ goto out;
+ }
+
+ if (new_size == dmdq.size) {
+ log_dbg(cd, "Device has already requested size %" PRIu64
+ " sectors.", dmdq.size);
+ r = 0;
+ } else {
+ if (isTCRYPT(cd->type))
+ r = -ENOTSUP;
+ else if (isLUKS2(cd->type))
+ r = LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, 0);
+ if (!r)
+ r = _reload_device(cd, name, &dmd);
+
+ if (r && tgt->type == DM_INTEGRITY &&
+ !dm_flags(cd, tgt->type, &supported_flags) &&
+ !(supported_flags & DM_INTEGRITY_RESIZE_SUPPORTED))
+ log_err(cd, _("Resize failed, the kernel doesn't support it."));
+ }
+out:
+ dm_targets_free(cd, &dmd);
+ dm_targets_free(cd, &dmdq);
+
+ return r;
+}
+
+int crypt_set_uuid(struct crypt_device *cd, const char *uuid)
+{
+ const char *active_uuid;
+ int r;
+
+ log_dbg(cd, "%s device uuid.", uuid ? "Setting new" : "Refreshing");
+
+ if ((r = onlyLUKS(cd)))
+ return r;
+
+ active_uuid = crypt_get_uuid(cd);
+
+ if (uuid && active_uuid && !strncmp(uuid, active_uuid, UUID_STRING_L)) {
+ log_dbg(cd, "UUID is the same as requested (%s) for device %s.",
+ uuid, mdata_device_path(cd));
+ return 0;
+ }
+
+ if (uuid)
+ log_dbg(cd, "Requested new UUID change to %s for %s.", uuid, mdata_device_path(cd));
+ else
+ log_dbg(cd, "Requested new UUID refresh for %s.", mdata_device_path(cd));
+
+ if (!crypt_confirm(cd, _("Do you really want to change UUID of device?")))
+ return -EPERM;
+
+ if (isLUKS1(cd->type))
+ return LUKS_hdr_uuid_set(&cd->u.luks1.hdr, uuid, cd);
+ else
+ return LUKS2_hdr_uuid(cd, &cd->u.luks2.hdr, uuid);
+}
+
+int crypt_set_label(struct crypt_device *cd, const char *label, const char *subsystem)
+{
+ int r;
+
+ log_dbg(cd, "Setting new labels.");
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ return LUKS2_hdr_labels(cd, &cd->u.luks2.hdr, label, subsystem, 1);
+}
+
+const char *crypt_get_label(struct crypt_device *cd)
+{
+ if (_onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0))
+ return NULL;
+
+ return cd->u.luks2.hdr.label;
+}
+
+const char *crypt_get_subsystem(struct crypt_device *cd)
+{
+ if (_onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0))
+ return NULL;
+
+ return cd->u.luks2.hdr.subsystem;
+}
+
+int crypt_header_backup(struct crypt_device *cd,
+ const char *requested_type,
+ const char *backup_file)
+{
+ int r;
+
+ if (requested_type && !isLUKS(requested_type))
+ return -EINVAL;
+
+ if (!backup_file)
+ return -EINVAL;
+
+ /* Load with repair */
+ r = _crypt_load_luks(cd, requested_type, false, false);
+ if (r < 0)
+ return r;
+
+ log_dbg(cd, "Requested header backup of device %s (%s) to "
+ "file %s.", mdata_device_path(cd), requested_type ?: "any type", backup_file);
+
+ if (isLUKS1(cd->type) && (!requested_type || isLUKS1(requested_type)))
+ r = LUKS_hdr_backup(backup_file, cd);
+ else if (isLUKS2(cd->type) && (!requested_type || isLUKS2(requested_type)))
+ r = LUKS2_hdr_backup(cd, &cd->u.luks2.hdr, backup_file);
+ else
+ r = -EINVAL;
+
+ return r;
+}
+
+int crypt_header_restore(struct crypt_device *cd,
+ const char *requested_type,
+ const char *backup_file)
+{
+ struct luks_phdr hdr1;
+ struct luks2_hdr hdr2;
+ int r, version;
+
+ if (requested_type && !isLUKS(requested_type))
+ return -EINVAL;
+
+ if (!cd || (cd->type && !isLUKS(cd->type)) || !backup_file)
+ return -EINVAL;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ log_dbg(cd, "Requested header restore to device %s (%s) from "
+ "file %s.", mdata_device_path(cd), requested_type ?: "any type", backup_file);
+
+ version = LUKS2_hdr_version_unlocked(cd, backup_file);
+ if (!version ||
+ (requested_type && version == 1 && !isLUKS1(requested_type)) ||
+ (requested_type && version == 2 && !isLUKS2(requested_type))) {
+ log_err(cd, _("Header backup file does not contain compatible LUKS header."));
+ return -EINVAL;
+ }
+
+ memset(&hdr2, 0, sizeof(hdr2));
+
+ if (!cd->type) {
+ if (version == 1)
+ r = LUKS_hdr_restore(backup_file, &hdr1, cd);
+ else
+ r = LUKS2_hdr_restore(cd, &hdr2, backup_file);
+
+ crypt_safe_memzero(&hdr1, sizeof(hdr1));
+ crypt_safe_memzero(&hdr2, sizeof(hdr2));
+ } else if (isLUKS2(cd->type) && (!requested_type || isLUKS2(requested_type))) {
+ r = LUKS2_hdr_restore(cd, &cd->u.luks2.hdr, backup_file);
+ if (r)
+ (void) _crypt_load_luks2(cd, 1, 0);
+ } else if (isLUKS1(cd->type) && (!requested_type || isLUKS1(requested_type)))
+ r = LUKS_hdr_restore(backup_file, &cd->u.luks1.hdr, cd);
+ else
+ r = -EINVAL;
+
+ if (!r)
+ r = _crypt_load_luks(cd, version == 1 ? CRYPT_LUKS1 : CRYPT_LUKS2, false, true);
+
+ return r;
+}
+
+int crypt_header_is_detached(struct crypt_device *cd)
+{
+ int r;
+
+ if (!cd || (cd->type && !isLUKS(cd->type)))
+ return -EINVAL;
+
+ r = device_is_identical(crypt_data_device(cd), crypt_metadata_device(cd));
+ if (r < 0) {
+ log_dbg(cd, "Failed to compare data and metadata devices path.");
+ return r;
+ }
+
+ return r ? 0 : 1;
+}
+
+void crypt_free(struct crypt_device *cd)
+{
+ if (!cd)
+ return;
+
+ log_dbg(cd, "Releasing crypt device %s context.", mdata_device_path(cd) ?: "empty");
+
+ dm_backend_exit(cd);
+ crypt_free_volume_key(cd->volume_key);
+
+ crypt_free_type(cd, NULL);
+
+ device_free(cd, cd->device);
+ device_free(cd, cd->metadata_device);
+
+ free(CONST_CAST(void*)cd->pbkdf.type);
+ free(CONST_CAST(void*)cd->pbkdf.hash);
+
+ /* Some structures can contain keys (TCRYPT), wipe it */
+ crypt_safe_memzero(cd, sizeof(*cd));
+ free(cd);
+}
+
+static char *crypt_get_device_key_description(struct crypt_device *cd, const char *name)
+{
+ char *desc = NULL;
+ struct crypt_dm_active_device dmd;
+ struct dm_target *tgt = &dmd.segment;
+
+ if (dm_query_device(cd, name, DM_ACTIVE_CRYPT_KEY | DM_ACTIVE_CRYPT_KEYSIZE, &dmd) < 0)
+ return NULL;
+
+ if (single_segment(&dmd) && tgt->type == DM_CRYPT &&
+ (dmd.flags & CRYPT_ACTIVATE_KEYRING_KEY) && tgt->u.crypt.vk->key_description)
+ desc = strdup(tgt->u.crypt.vk->key_description);
+
+ dm_targets_free(cd, &dmd);
+
+ return desc;
+}
+
+int crypt_suspend(struct crypt_device *cd,
+ const char *name)
+{
+ char *key_desc;
+ crypt_status_info ci;
+ int r;
+ uint32_t dmflags = DM_SUSPEND_WIPE_KEY;
+
+ /* FIXME: check context uuid matches the dm-crypt device uuid (onlyLUKS branching) */
+
+ if (!cd || !name)
+ return -EINVAL;
+
+ log_dbg(cd, "Suspending volume %s.", name);
+
+ if (cd->type)
+ r = onlyLUKS(cd);
+ else {
+ r = crypt_uuid_type_cmp(cd, CRYPT_LUKS1);
+ if (r < 0)
+ r = crypt_uuid_type_cmp(cd, CRYPT_LUKS2);
+ if (r < 0)
+ log_err(cd, _("This operation is supported only for LUKS device."));
+ }
+
+ if (r < 0)
+ return r;
+
+ ci = crypt_status(NULL, name);
+ if (ci < CRYPT_ACTIVE) {
+ log_err(cd, _("Volume %s is not active."), name);
+ return -EINVAL;
+ }
+
+ dm_backend_init(cd);
+
+ r = dm_status_suspended(cd, name);
+ if (r < 0)
+ goto out;
+
+ if (r) {
+ log_err(cd, _("Volume %s is already suspended."), name);
+ r = -EINVAL;
+ goto out;
+ }
+
+ key_desc = crypt_get_device_key_description(cd, name);
+
+ /* we can't simply wipe wrapped keys */
+ if (crypt_cipher_wrapped_key(crypt_get_cipher(cd), crypt_get_cipher_mode(cd)))
+ dmflags &= ~DM_SUSPEND_WIPE_KEY;
+
+ r = dm_suspend_device(cd, name, dmflags);
+ if (r == -ENOTSUP)
+ log_err(cd, _("Suspend is not supported for device %s."), name);
+ else if (r)
+ log_err(cd, _("Error during suspending device %s."), name);
+ else
+ crypt_drop_keyring_key_by_description(cd, key_desc, LOGON_KEY);
+ free(key_desc);
+out:
+ dm_backend_exit(cd);
+ return r;
+}
+
+/* key must be properly verified */
+static int resume_by_volume_key(struct crypt_device *cd,
+ struct volume_key *vk,
+ const char *name)
+{
+ int digest, r;
+ struct volume_key *zerokey = NULL;
+
+ if (crypt_is_cipher_null(crypt_get_cipher_spec(cd))) {
+ zerokey = crypt_alloc_volume_key(0, NULL);
+ if (!zerokey)
+ return -ENOMEM;
+ vk = zerokey;
+ } else if (crypt_use_keyring_for_vk(cd)) {
+ /* LUKS2 path only */
+ digest = LUKS2_digest_by_segment(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+ if (digest < 0)
+ return -EINVAL;
+ r = LUKS2_volume_key_load_in_keyring_by_digest(cd, vk, digest);
+ if (r < 0)
+ return r;
+ }
+
+ r = dm_resume_and_reinstate_key(cd, name, vk);
+
+ if (r == -ENOTSUP)
+ log_err(cd, _("Resume is not supported for device %s."), name);
+ else if (r)
+ log_err(cd, _("Error during resuming device %s."), name);
+
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vk);
+
+ crypt_free_volume_key(zerokey);
+
+ return r;
+}
+
+int crypt_resume_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ struct volume_key *vk = NULL;
+ int r;
+
+ /* FIXME: check context uuid matches the dm-crypt device uuid */
+
+ if (!passphrase || !name)
+ return -EINVAL;
+
+ log_dbg(cd, "Resuming volume %s.", name);
+
+ if ((r = onlyLUKS(cd)))
+ return r;
+
+ r = dm_status_suspended(cd, name);
+ if (r < 0)
+ return r;
+
+ if (!r) {
+ log_err(cd, _("Volume %s is not suspended."), name);
+ return -EINVAL;
+ }
+
+ if (isLUKS1(cd->type))
+ r = LUKS_open_key_with_hdr(keyslot, passphrase, passphrase_size,
+ &cd->u.luks1.hdr, &vk, cd);
+ else
+ r = LUKS2_keyslot_open(cd, keyslot, CRYPT_DEFAULT_SEGMENT, passphrase, passphrase_size, &vk);
+
+ if (r < 0)
+ return r;
+
+ keyslot = r;
+
+ r = resume_by_volume_key(cd, vk, name);
+
+ crypt_free_volume_key(vk);
+ return r < 0 ? r : keyslot;
+}
+
+int crypt_resume_by_keyfile_device_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset)
+{
+ struct volume_key *vk = NULL;
+ char *passphrase_read = NULL;
+ size_t passphrase_size_read;
+ int r;
+
+ /* FIXME: check context uuid matches the dm-crypt device uuid */
+
+ if (!name || !keyfile)
+ return -EINVAL;
+
+ log_dbg(cd, "Resuming volume %s.", name);
+
+ if ((r = onlyLUKS(cd)))
+ return r;
+
+ r = dm_status_suspended(cd, name);
+ if (r < 0)
+ return r;
+
+ if (!r) {
+ log_err(cd, _("Volume %s is not suspended."), name);
+ return -EINVAL;
+ }
+
+ r = crypt_keyfile_device_read(cd, keyfile,
+ &passphrase_read, &passphrase_size_read,
+ keyfile_offset, keyfile_size, 0);
+ if (r < 0)
+ return r;
+
+ if (isLUKS1(cd->type))
+ r = LUKS_open_key_with_hdr(keyslot, passphrase_read, passphrase_size_read,
+ &cd->u.luks1.hdr, &vk, cd);
+ else
+ r = LUKS2_keyslot_open(cd, keyslot, CRYPT_DEFAULT_SEGMENT,
+ passphrase_read, passphrase_size_read, &vk);
+
+ crypt_safe_free(passphrase_read);
+ if (r < 0)
+ return r;
+
+ keyslot = r;
+
+ r = resume_by_volume_key(cd, vk, name);
+
+ crypt_free_volume_key(vk);
+ return r < 0 ? r : keyslot;
+}
+
+int crypt_resume_by_keyfile(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size)
+{
+ return crypt_resume_by_keyfile_device_offset(cd, name, keyslot,
+ keyfile, keyfile_size, 0);
+}
+
+int crypt_resume_by_keyfile_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ size_t keyfile_offset)
+{
+ return crypt_resume_by_keyfile_device_offset(cd, name, keyslot,
+ keyfile, keyfile_size, keyfile_offset);
+}
+
+int crypt_resume_by_volume_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size)
+{
+ struct volume_key *vk = NULL;
+ int r;
+
+ if (!name || !volume_key)
+ return -EINVAL;
+
+ log_dbg(cd, "Resuming volume %s by volume key.", name);
+
+ if ((r = onlyLUKS(cd)))
+ return r;
+
+ r = dm_status_suspended(cd, name);
+ if (r < 0)
+ return r;
+
+ if (!r) {
+ log_err(cd, _("Volume %s is not suspended."), name);
+ return -EINVAL;
+ }
+
+ vk = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!vk)
+ return -ENOMEM;
+
+ if (isLUKS1(cd->type))
+ r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
+ else if (isLUKS2(cd->type))
+ r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
+ else
+ r = -EINVAL;
+ if (r == -EPERM || r == -ENOENT)
+ log_err(cd, _("Volume key does not match the volume."));
+
+ if (r >= 0)
+ r = resume_by_volume_key(cd, vk, name);
+
+ crypt_free_volume_key(vk);
+ return r;
+}
+
+int crypt_resume_by_token_pin(struct crypt_device *cd, const char *name,
+ const char *type, int token, const char *pin, size_t pin_size,
+ void *usrptr)
+{
+ struct volume_key *vk = NULL;
+ int r, keyslot;
+
+ if (!name)
+ return -EINVAL;
+
+ log_dbg(cd, "Resuming volume %s by token (%s type) %d.",
+ name, type ?: "any", token);
+
+ if ((r = _onlyLUKS2(cd, CRYPT_CD_QUIET, 0)))
+ return r;
+
+ r = dm_status_suspended(cd, name);
+ if (r < 0)
+ return r;
+
+ if (!r) {
+ log_err(cd, _("Volume %s is not suspended."), name);
+ return -EINVAL;
+ }
+
+ r = LUKS2_token_unlock_key(cd, &cd->u.luks2.hdr, token, type,
+ pin, pin_size, CRYPT_DEFAULT_SEGMENT, usrptr, &vk);
+ keyslot = r;
+ if (r >= 0)
+ r = resume_by_volume_key(cd, vk, name);
+
+ crypt_free_volume_key(vk);
+ return r < 0 ? r : keyslot;
+}
+
+/*
+ * Keyslot manipulation
+ */
+int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
+ int keyslot, // -1 any
+ const char *passphrase,
+ size_t passphrase_size,
+ const char *new_passphrase,
+ size_t new_passphrase_size)
+{
+ int r;
+ struct crypt_keyslot_context kc, new_kc;
+
+ if (!passphrase || !new_passphrase)
+ return -EINVAL;
+
+ crypt_keyslot_unlock_by_passphrase_init_internal(&kc, passphrase, passphrase_size);
+ crypt_keyslot_unlock_by_passphrase_init_internal(&new_kc, new_passphrase, new_passphrase_size);
+
+ r = crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, &kc, keyslot, &new_kc, 0);
+
+ crypt_keyslot_context_destroy_internal(&kc);
+ crypt_keyslot_context_destroy_internal(&new_kc);
+
+ return r;
+}
+
+int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
+ int keyslot_old,
+ int keyslot_new,
+ const char *passphrase,
+ size_t passphrase_size,
+ const char *new_passphrase,
+ size_t new_passphrase_size)
+{
+ int digest = -1, r, keyslot_new_orig = keyslot_new;
+ struct luks2_keyslot_params params;
+ struct volume_key *vk = NULL;
+
+ if (!passphrase || !new_passphrase)
+ return -EINVAL;
+
+ log_dbg(cd, "Changing passphrase from old keyslot %d to new %d.",
+ keyslot_old, keyslot_new);
+
+ if ((r = onlyLUKS(cd)))
+ return r;
+
+ if (isLUKS1(cd->type))
+ r = LUKS_open_key_with_hdr(keyslot_old, passphrase, passphrase_size,
+ &cd->u.luks1.hdr, &vk, cd);
+ else if (isLUKS2(cd->type)) {
+ r = LUKS2_keyslot_open(cd, keyslot_old, CRYPT_ANY_SEGMENT, passphrase, passphrase_size, &vk);
+ /* will fail for keyslots w/o digest. fix if supported in a future */
+ if (r >= 0) {
+ digest = LUKS2_digest_by_keyslot(&cd->u.luks2.hdr, r);
+ if (digest < 0)
+ r = -EINVAL;
+ }
+ } else
+ r = -EINVAL;
+ if (r < 0)
+ goto out;
+
+ if (keyslot_old != CRYPT_ANY_SLOT && keyslot_old != r) {
+ log_dbg(cd, "Keyslot mismatch.");
+ goto out;
+ }
+ keyslot_old = r;
+
+ if (keyslot_new == CRYPT_ANY_SLOT) {
+ if (isLUKS1(cd->type))
+ keyslot_new = LUKS_keyslot_find_empty(&cd->u.luks1.hdr);
+ else if (isLUKS2(cd->type))
+ keyslot_new = LUKS2_keyslot_find_empty(cd, &cd->u.luks2.hdr, vk->keylength);
+ if (keyslot_new < 0)
+ keyslot_new = keyslot_old;
+ }
+ log_dbg(cd, "Key change, old slot %d, new slot %d.", keyslot_old, keyslot_new);
+
+ if (isLUKS1(cd->type)) {
+ if (keyslot_old == keyslot_new) {
+ log_dbg(cd, "Key slot %d is going to be overwritten.", keyslot_old);
+ (void)crypt_keyslot_destroy(cd, keyslot_old);
+ }
+ r = LUKS_set_key(keyslot_new, new_passphrase, new_passphrase_size,
+ &cd->u.luks1.hdr, vk, cd);
+ } else if (isLUKS2(cd->type)) {
+ r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, &params);
+ if (r)
+ goto out;
+
+ if (keyslot_old != keyslot_new) {
+ r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot_new, digest, 1, 0);
+ if (r < 0)
+ goto out;
+ r = LUKS2_token_assignment_copy(cd, &cd->u.luks2.hdr, keyslot_old, keyslot_new, 0);
+ if (r < 0)
+ goto out;
+ } else {
+ log_dbg(cd, "Key slot %d is going to be overwritten.", keyslot_old);
+ /* FIXME: improve return code so that we can detect area is damaged */
+ r = LUKS2_keyslot_wipe(cd, &cd->u.luks2.hdr, keyslot_old, 1);
+ if (r) {
+ /* (void)crypt_keyslot_destroy(cd, keyslot_old); */
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr,
+ keyslot_new, new_passphrase,
+ new_passphrase_size, vk, &params);
+ if (r < 0)
+ goto out;
+
+ /* Swap old & new so the final keyslot number remains */
+ if (keyslot_new_orig == CRYPT_ANY_SLOT && keyslot_old != keyslot_new) {
+ r = LUKS2_keyslot_swap(cd, &cd->u.luks2.hdr, keyslot_old, keyslot_new);
+ if (r < 0)
+ goto out;
+
+ /* Swap slot id */
+ r = keyslot_old;
+ keyslot_old = keyslot_new;
+ keyslot_new = r;
+ }
+ } else
+ r = -EINVAL;
+
+ if (r >= 0 && keyslot_old != keyslot_new)
+ r = crypt_keyslot_destroy(cd, keyslot_old);
+
+ if (r < 0)
+ log_err(cd, _("Failed to swap new key slot."));
+out:
+ crypt_free_volume_key(vk);
+ if (r < 0) {
+ _luks2_rollback(cd);
+ return r;
+ }
+ return keyslot_new;
+}
+
+int crypt_keyslot_add_by_keyfile_device_offset(struct crypt_device *cd,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset,
+ const char *new_keyfile,
+ size_t new_keyfile_size,
+ uint64_t new_keyfile_offset)
+{
+ int r;
+ struct crypt_keyslot_context kc, new_kc;
+
+ if (!keyfile || !new_keyfile)
+ return -EINVAL;
+
+ crypt_keyslot_unlock_by_keyfile_init_internal(&kc, keyfile, keyfile_size, keyfile_offset);
+ crypt_keyslot_unlock_by_keyfile_init_internal(&new_kc, new_keyfile, new_keyfile_size, new_keyfile_offset);
+
+ r = crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, &kc, keyslot, &new_kc, 0);
+
+ crypt_keyslot_context_destroy_internal(&kc);
+ crypt_keyslot_context_destroy_internal(&new_kc);
+
+ return r;
+}
+
+int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ const char *new_keyfile,
+ size_t new_keyfile_size)
+{
+ return crypt_keyslot_add_by_keyfile_device_offset(cd, keyslot,
+ keyfile, keyfile_size, 0,
+ new_keyfile, new_keyfile_size, 0);
+}
+
+int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ size_t keyfile_offset,
+ const char *new_keyfile,
+ size_t new_keyfile_size,
+ size_t new_keyfile_offset)
+{
+ return crypt_keyslot_add_by_keyfile_device_offset(cd, keyslot,
+ keyfile, keyfile_size, keyfile_offset,
+ new_keyfile, new_keyfile_size, new_keyfile_offset);
+}
+
+int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
+ int keyslot,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ int r;
+ struct crypt_keyslot_context kc, new_kc;
+
+ if (!passphrase)
+ return -EINVAL;
+
+ crypt_keyslot_unlock_by_key_init_internal(&kc, volume_key, volume_key_size);
+ crypt_keyslot_unlock_by_passphrase_init_internal(&new_kc, passphrase, passphrase_size);
+
+ r = crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, &kc, keyslot, &new_kc, 0);
+
+ crypt_keyslot_context_destroy_internal(&kc);
+ crypt_keyslot_context_destroy_internal(&new_kc);
+
+ return r;
+}
+
+int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot)
+{
+ crypt_keyslot_info ki;
+ int r;
+
+ log_dbg(cd, "Destroying keyslot %d.", keyslot);
+
+ if ((r = _onlyLUKS(cd, CRYPT_CD_UNRESTRICTED)))
+ return r;
+
+ ki = crypt_keyslot_status(cd, keyslot);
+ if (ki == CRYPT_SLOT_INVALID) {
+ log_err(cd, _("Key slot %d is invalid."), keyslot);
+ return -EINVAL;
+ }
+
+ if (isLUKS1(cd->type)) {
+ if (ki == CRYPT_SLOT_INACTIVE) {
+ log_err(cd, _("Keyslot %d is not active."), keyslot);
+ return -EINVAL;
+ }
+ return LUKS_del_key(keyslot, &cd->u.luks1.hdr, cd);
+ }
+
+ return LUKS2_keyslot_wipe(cd, &cd->u.luks2.hdr, keyslot, 0);
+}
+
+static int _check_header_data_overlap(struct crypt_device *cd, const char *name)
+{
+ if (!name || !isLUKS(cd->type))
+ return 0;
+
+ if (device_is_identical(crypt_data_device(cd), crypt_metadata_device(cd)) <= 0)
+ return 0;
+
+ /* FIXME: check real header size */
+ if (crypt_get_data_offset(cd) == 0) {
+ log_err(cd, _("Device header overlaps with data area."));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int check_devices(struct crypt_device *cd, const char *name, const char *iname, uint32_t *flags)
+{
+ int r;
+
+ if (!flags || !name)
+ return -EINVAL;
+
+ if (iname) {
+ r = dm_status_device(cd, iname);
+ if (r >= 0 && !(*flags & CRYPT_ACTIVATE_REFRESH))
+ return -EBUSY;
+ if (r < 0 && r != -ENODEV)
+ return r;
+ if (r == -ENODEV)
+ *flags &= ~CRYPT_ACTIVATE_REFRESH;
+ }
+
+ r = dm_status_device(cd, name);
+ if (r >= 0 && !(*flags & CRYPT_ACTIVATE_REFRESH))
+ return -EBUSY;
+ if (r < 0 && r != -ENODEV)
+ return r;
+ if (r == -ENODEV)
+ *flags &= ~CRYPT_ACTIVATE_REFRESH;
+
+ return 0;
+}
+
+static int _create_device_with_integrity(struct crypt_device *cd,
+ const char *type, const char *name, const char *iname,
+ const char *ipath, struct crypt_dm_active_device *dmd,
+ struct crypt_dm_active_device *dmdi)
+{
+ int r;
+ enum devcheck device_check;
+ struct dm_target *tgt;
+ struct device *device = NULL;
+
+ if (!single_segment(dmd))
+ return -EINVAL;
+
+ tgt = &dmd->segment;
+ if (tgt->type != DM_CRYPT)
+ return -EINVAL;
+
+ device_check = dmd->flags & CRYPT_ACTIVATE_SHARED ? DEV_OK : DEV_EXCL;
+
+ r = INTEGRITY_activate_dmd_device(cd, iname, CRYPT_INTEGRITY, dmdi, 0);
+ if (r)
+ return r;
+
+ r = device_alloc(cd, &device, ipath);
+ if (r < 0)
+ goto out;
+ tgt->data_device = device;
+
+ r = device_block_adjust(cd, tgt->data_device, device_check,
+ tgt->u.crypt.offset, &dmd->size, &dmd->flags);
+
+ if (!r)
+ r = dm_create_device(cd, name, type, dmd);
+out:
+ if (r < 0)
+ dm_remove_device(cd, iname, 0);
+
+ device_free(cd, device);
+ return r;
+}
+
+static int kernel_keyring_support(void)
+{
+ static unsigned _checked = 0;
+
+ if (!_checked) {
+ _kernel_keyring_supported = keyring_check();
+ _checked = 1;
+ }
+
+ return _kernel_keyring_supported;
+}
+
+static int dmcrypt_keyring_bug(void)
+{
+ uint64_t kversion;
+
+ if (kernel_version(&kversion))
+ return 1;
+ return kversion < compact_version(4,15,0,0);
+}
+
+int create_or_reload_device(struct crypt_device *cd, const char *name,
+ const char *type, struct crypt_dm_active_device *dmd)
+{
+ int r;
+ enum devcheck device_check;
+ struct dm_target *tgt;
+
+ if (!type || !name || !single_segment(dmd))
+ return -EINVAL;
+
+ tgt = &dmd->segment;
+ if (tgt->type != DM_CRYPT && tgt->type != DM_INTEGRITY)
+ return -EINVAL;
+
+ /* drop CRYPT_ACTIVATE_REFRESH flag if any device is inactive */
+ r = check_devices(cd, name, NULL, &dmd->flags);
+ if (r)
+ return r;
+
+ if (dmd->flags & CRYPT_ACTIVATE_REFRESH)
+ r = _reload_device(cd, name, dmd);
+ else {
+ if (tgt->type == DM_CRYPT) {
+ device_check = dmd->flags & CRYPT_ACTIVATE_SHARED ? DEV_OK : DEV_EXCL;
+
+ r = device_block_adjust(cd, tgt->data_device, device_check,
+ tgt->u.crypt.offset, &dmd->size, &dmd->flags);
+ if (!r) {
+ tgt->size = dmd->size;
+ r = dm_create_device(cd, name, type, dmd);
+ }
+ } else if (tgt->type == DM_INTEGRITY) {
+ r = device_block_adjust(cd, tgt->data_device, DEV_EXCL,
+ tgt->u.integrity.offset, NULL, &dmd->flags);
+ if (r)
+ return r;
+
+ if (tgt->u.integrity.meta_device) {
+ r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL);
+ if (r)
+ return r;
+ }
+
+ r = dm_create_device(cd, name, type, dmd);
+ }
+ }
+
+ return r;
+}
+
+int create_or_reload_device_with_integrity(struct crypt_device *cd, const char *name,
+ const char *type, struct crypt_dm_active_device *dmd,
+ struct crypt_dm_active_device *dmdi)
+{
+ int r;
+ const char *iname = NULL;
+ char *ipath = NULL;
+
+ if (!type || !name || !dmd || !dmdi)
+ return -EINVAL;
+
+ if (asprintf(&ipath, "%s/%s_dif", dm_get_dir(), name) < 0)
+ return -ENOMEM;
+ iname = ipath + strlen(dm_get_dir()) + 1;
+
+ /* drop CRYPT_ACTIVATE_REFRESH flag if any device is inactive */
+ r = check_devices(cd, name, iname, &dmd->flags);
+ if (r)
+ goto out;
+
+ if (dmd->flags & CRYPT_ACTIVATE_REFRESH)
+ r = _reload_device_with_integrity(cd, name, iname, ipath, dmd, dmdi);
+ else
+ r = _create_device_with_integrity(cd, type, name, iname, ipath, dmd, dmdi);
+out:
+ free(ipath);
+
+ return r;
+}
+
+static int _open_and_activate(struct crypt_device *cd,
+ int keyslot,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ bool use_keyring;
+ int r;
+ struct volume_key *vk = NULL;
+
+ r = LUKS2_keyslot_open(cd, keyslot,
+ (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ?
+ CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT,
+ passphrase, passphrase_size, &vk);
+ if (r < 0)
+ return r;
+ keyslot = r;
+
+ if (!crypt_use_keyring_for_vk(cd))
+ use_keyring = false;
+ else
+ use_keyring = ((name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
+ (flags & CRYPT_ACTIVATE_KEYRING_KEY));
+
+ if (use_keyring) {
+ r = LUKS2_volume_key_load_in_keyring_by_keyslot(cd,
+ &cd->u.luks2.hdr, vk, keyslot);
+ if (r < 0)
+ goto out;
+ flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ }
+
+ if (name)
+ r = LUKS2_activate(cd, name, vk, flags);
+out:
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vk);
+ crypt_free_volume_key(vk);
+
+ return r < 0 ? r : keyslot;
+}
+
+#if USE_LUKS2_REENCRYPTION
+static int load_all_keys(struct crypt_device *cd, struct luks2_hdr *hdr, struct volume_key *vks)
+{
+ int r;
+ struct volume_key *vk = vks;
+
+ while (vk) {
+ r = LUKS2_volume_key_load_in_keyring_by_digest(cd, vk, crypt_volume_key_get_id(vk));
+ if (r < 0)
+ return r;
+ vk = crypt_volume_key_next(vk);
+ }
+
+ return 0;
+}
+
+static int _open_all_keys(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags,
+ struct volume_key **vks)
+{
+ int r, segment;
+ struct volume_key *_vks = NULL;
+ crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
+
+ segment = (flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) ? CRYPT_ANY_SEGMENT : CRYPT_DEFAULT_SEGMENT;
+
+ switch (ri) {
+ case CRYPT_REENCRYPT_NONE:
+ r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase, passphrase_size, &_vks);
+ break;
+ case CRYPT_REENCRYPT_CLEAN:
+ case CRYPT_REENCRYPT_CRASH:
+ if (segment == CRYPT_ANY_SEGMENT)
+ r = LUKS2_keyslot_open(cd, keyslot, segment, passphrase,
+ passphrase_size, &_vks);
+ else
+ r = LUKS2_keyslot_open_all_segments(cd, keyslot,
+ keyslot, passphrase, passphrase_size,
+ &_vks);
+ break;
+ default:
+ r = -EINVAL;
+ }
+
+ if (keyslot == CRYPT_ANY_SLOT)
+ keyslot = r;
+
+ if (r >= 0 && (flags & CRYPT_ACTIVATE_KEYRING_KEY))
+ r = load_all_keys(cd, hdr, _vks);
+
+ if (r >= 0 && vks)
+ MOVE_REF(*vks, _vks);
+
+ if (r < 0)
+ crypt_drop_keyring_key(cd, _vks);
+ crypt_free_volume_key(_vks);
+
+ return r < 0 ? r : keyslot;
+}
+
+static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
+ struct luks2_hdr *hdr,
+ int keyslot,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ bool dynamic_size;
+ crypt_reencrypt_info ri;
+ uint64_t minimal_size, device_size;
+ struct volume_key *vks = NULL;
+ int r = 0;
+ struct crypt_lock_handle *reencrypt_lock = NULL;
+
+ if (crypt_use_keyring_for_vk(cd))
+ flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+
+ r = LUKS2_reencrypt_lock(cd, &reencrypt_lock);
+ if (r) {
+ if (r == -EBUSY)
+ log_err(cd, _("Reencryption in-progress. Cannot activate device."));
+ else
+ log_err(cd, _("Failed to get reencryption lock."));
+ return r;
+ }
+
+ if ((r = crypt_load(cd, CRYPT_LUKS2, NULL)))
+ goto out;
+
+ ri = LUKS2_reencrypt_status(hdr);
+
+ if (ri == CRYPT_REENCRYPT_CRASH) {
+ r = LUKS2_reencrypt_locked_recovery_by_passphrase(cd, keyslot,
+ keyslot, passphrase, passphrase_size, &vks);
+ if (r < 0) {
+ log_err(cd, _("LUKS2 reencryption recovery failed."));
+ goto out;
+ }
+ keyslot = r;
+
+ ri = LUKS2_reencrypt_status(hdr);
+ }
+
+ /* recovery finished reencryption or it's already finished */
+ if (ri == CRYPT_REENCRYPT_NONE) {
+ crypt_drop_keyring_key(cd, vks);
+ crypt_free_volume_key(vks);
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
+ }
+
+ if (ri > CRYPT_REENCRYPT_CLEAN) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (LUKS2_get_data_size(hdr, &minimal_size, &dynamic_size))
+ goto out;
+
+ if (!vks) {
+ r = _open_all_keys(cd, hdr, keyslot, passphrase, passphrase_size, flags, &vks);
+ if (r >= 0)
+ keyslot = r;
+ }
+
+ if (r >= 0) {
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ if (r < 0)
+ goto out;
+ }
+
+ log_dbg(cd, "Entering clean reencryption state mode.");
+
+ if (r >= 0)
+ r = LUKS2_reencrypt_check_device_size(cd, hdr, minimal_size, &device_size, true, dynamic_size);
+
+ if (r >= 0)
+ r = LUKS2_activate_multi(cd, name, vks, device_size >> SECTOR_SHIFT, flags);
+out:
+ LUKS2_reencrypt_unlock(cd, reencrypt_lock);
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vks);
+ crypt_free_volume_key(vks);
+
+ return r < 0 ? r : keyslot;
+}
+
+/*
+ * Activation/deactivation of a device
+ */
+static int _open_and_activate_luks2(struct crypt_device *cd,
+ int keyslot,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ crypt_reencrypt_info ri;
+ int r, rv;
+ struct luks2_hdr *hdr = &cd->u.luks2.hdr;
+ struct volume_key *vks = NULL;
+
+ ri = LUKS2_reencrypt_status(hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID)
+ return -EINVAL;
+
+ if (ri > CRYPT_REENCRYPT_NONE) {
+ if (name)
+ r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase,
+ passphrase_size, flags);
+ else {
+ r = _open_all_keys(cd, hdr, keyslot, passphrase,
+ passphrase_size, flags, &vks);
+ if (r < 0)
+ return r;
+
+ rv = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
+ crypt_free_volume_key(vks);
+ if (rv < 0)
+ return rv;
+ }
+ } else
+ r = _open_and_activate(cd, keyslot, name, passphrase,
+ passphrase_size, flags);
+
+ return r;
+}
+#else
+static int _open_and_activate_luks2(struct crypt_device *cd,
+ int keyslot,
+ const char *name,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ crypt_reencrypt_info ri;
+
+ ri = LUKS2_reencrypt_status(&cd->u.luks2.hdr);
+ if (ri == CRYPT_REENCRYPT_INVALID)
+ return -EINVAL;
+
+ if (ri > CRYPT_REENCRYPT_NONE) {
+ log_err(cd, _("This operation is not supported for this device type."));
+ return -ENOTSUP;
+ }
+
+ return _open_and_activate(cd, keyslot, name, passphrase, passphrase_size, flags);
+}
+#endif
+
+static int _activate_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ int r;
+ struct volume_key *vk = NULL;
+
+ if ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd))
+ return -EINVAL;
+
+ if ((flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) && name)
+ return -EINVAL;
+
+ r = _check_header_data_overlap(cd, name);
+ if (r < 0)
+ return r;
+
+ if (flags & CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF)
+ cd->memory_hard_pbkdf_lock_enabled = true;
+
+ /* plain, use hashed passphrase */
+ if (isPLAIN(cd->type)) {
+ r = -EINVAL;
+ if (!name)
+ goto out;
+
+ r = process_key(cd, cd->u.plain.hdr.hash,
+ cd->u.plain.key_size,
+ passphrase, passphrase_size, &vk);
+ if (r < 0)
+ goto out;
+
+ r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags);
+ keyslot = 0;
+ } else if (isLUKS1(cd->type)) {
+ r = LUKS_open_key_with_hdr(keyslot, passphrase,
+ passphrase_size, &cd->u.luks1.hdr, &vk, cd);
+ if (r >= 0) {
+ keyslot = r;
+ if (name)
+ r = LUKS1_activate(cd, name, vk, flags);
+ }
+ } else if (isLUKS2(cd->type)) {
+ r = _open_and_activate_luks2(cd, keyslot, name, passphrase, passphrase_size, flags);
+ keyslot = r;
+ } else if (isBITLK(cd->type)) {
+ r = BITLK_activate_by_passphrase(cd, name, passphrase, passphrase_size,
+ &cd->u.bitlk.params, flags);
+ keyslot = 0;
+ } else if (isFVAULT2(cd->type)) {
+ r = FVAULT2_activate_by_passphrase(cd, name, passphrase, passphrase_size,
+ &cd->u.fvault2.params, flags);
+ keyslot = 0;
+ } else {
+ log_err(cd, _("Device type is not properly initialized."));
+ r = -EINVAL;
+ }
+out:
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vk);
+ crypt_free_volume_key(vk);
+
+ cd->memory_hard_pbkdf_lock_enabled = false;
+
+ return r < 0 ? r : keyslot;
+}
+
+static int _activate_loopaes(struct crypt_device *cd,
+ const char *name,
+ char *buffer,
+ size_t buffer_size,
+ uint32_t flags)
+{
+ int r;
+ unsigned int key_count = 0;
+ struct volume_key *vk = NULL;
+
+ r = LOOPAES_parse_keyfile(cd, &vk, cd->u.loopaes.hdr.hash, &key_count,
+ buffer, buffer_size);
+
+ if (!r && name)
+ r = LOOPAES_activate(cd, name, cd->u.loopaes.cipher, key_count,
+ vk, flags);
+
+ crypt_free_volume_key(vk);
+
+ return r;
+}
+
+static int _activate_check_status(struct crypt_device *cd, const char *name, unsigned reload)
+{
+ int r;
+
+ if (!name)
+ return 0;
+
+ r = dm_status_device(cd, name);
+
+ if (r >= 0 && reload)
+ return 0;
+
+ if (r >= 0 || r == -EEXIST) {
+ log_err(cd, _("Device %s already exists."), name);
+ return -EEXIST;
+ }
+
+ if (r == -ENODEV)
+ return 0;
+
+ log_err(cd, _("Cannot use device %s, name is invalid or still in use."), name);
+ return r;
+}
+
+// activation/deactivation of device mapping
+int crypt_activate_by_passphrase(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ int r;
+
+ if (!cd || !passphrase || (!name && (flags & CRYPT_ACTIVATE_REFRESH)))
+ return -EINVAL;
+
+ log_dbg(cd, "%s volume %s [keyslot %d] using passphrase.",
+ name ? "Activating" : "Checking", name ?: "passphrase",
+ keyslot);
+
+ r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
+ if (r < 0)
+ return r;
+
+ return _activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags);
+}
+
+int crypt_activate_by_keyfile_device_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint64_t keyfile_offset,
+ uint32_t flags)
+{
+ char *passphrase_read = NULL;
+ size_t passphrase_size_read;
+ int r;
+
+ if (!cd || !keyfile ||
+ ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd)))
+ return -EINVAL;
+
+ log_dbg(cd, "%s volume %s [keyslot %d] using keyfile %s.",
+ name ? "Activating" : "Checking", name ?: "passphrase", keyslot, keyfile);
+
+ r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
+ if (r < 0)
+ return r;
+
+ r = crypt_keyfile_device_read(cd, keyfile,
+ &passphrase_read, &passphrase_size_read,
+ keyfile_offset, keyfile_size, 0);
+ if (r < 0)
+ goto out;
+
+ if (isLOOPAES(cd->type))
+ r = _activate_loopaes(cd, name, passphrase_read, passphrase_size_read, flags);
+ else
+ r = _activate_by_passphrase(cd, name, keyslot, passphrase_read, passphrase_size_read, flags);
+
+out:
+ crypt_safe_free(passphrase_read);
+ return r;
+}
+
+int crypt_activate_by_keyfile(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ uint32_t flags)
+{
+ return crypt_activate_by_keyfile_device_offset(cd, name, keyslot, keyfile,
+ keyfile_size, 0, flags);
+}
+
+int crypt_activate_by_keyfile_offset(struct crypt_device *cd,
+ const char *name,
+ int keyslot,
+ const char *keyfile,
+ size_t keyfile_size,
+ size_t keyfile_offset,
+ uint32_t flags)
+{
+ return crypt_activate_by_keyfile_device_offset(cd, name, keyslot, keyfile,
+ keyfile_size, keyfile_offset, flags);
+}
+int crypt_activate_by_volume_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size,
+ uint32_t flags)
+{
+ bool use_keyring;
+ struct volume_key *vk = NULL;
+ int r;
+
+ if (!cd ||
+ ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd)))
+ return -EINVAL;
+
+ log_dbg(cd, "%s volume %s by volume key.", name ? "Activating" : "Checking",
+ name ?: "");
+
+ r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
+ if (r < 0)
+ return r;
+
+ r = _check_header_data_overlap(cd, name);
+ if (r < 0)
+ return r;
+
+ /* use key directly, no hash */
+ if (isPLAIN(cd->type)) {
+ if (!name)
+ return -EINVAL;
+
+ if (!volume_key || !volume_key_size || volume_key_size != cd->u.plain.key_size) {
+ log_err(cd, _("Incorrect volume key specified for plain device."));
+ return -EINVAL;
+ }
+
+ vk = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!vk)
+ return -ENOMEM;
+
+ r = PLAIN_activate(cd, name, vk, cd->u.plain.hdr.size, flags);
+ } else if (isLUKS1(cd->type)) {
+ /* If key is not provided, try to use internal key */
+ if (!volume_key) {
+ if (!cd->volume_key) {
+ log_err(cd, _("Volume key does not match the volume."));
+ return -EINVAL;
+ }
+ volume_key_size = cd->volume_key->keylength;
+ volume_key = cd->volume_key->key;
+ }
+
+ vk = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!vk)
+ return -ENOMEM;
+ r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
+
+ if (r == -EPERM)
+ log_err(cd, _("Volume key does not match the volume."));
+
+ if (!r && name)
+ r = LUKS1_activate(cd, name, vk, flags);
+ } else if (isLUKS2(cd->type)) {
+ /* If key is not provided, try to use internal key */
+ if (!volume_key) {
+ if (!cd->volume_key) {
+ log_err(cd, _("Volume key does not match the volume."));
+ return -EINVAL;
+ }
+ volume_key_size = cd->volume_key->keylength;
+ volume_key = cd->volume_key->key;
+ }
+
+ vk = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!vk)
+ return -ENOMEM;
+
+ r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
+ if (r == -EPERM || r == -ENOENT)
+ log_err(cd, _("Volume key does not match the volume."));
+ if (r > 0)
+ r = 0;
+
+ if (!crypt_use_keyring_for_vk(cd))
+ use_keyring = false;
+ else
+ use_keyring = (name && !crypt_is_cipher_null(crypt_get_cipher(cd))) ||
+ (flags & CRYPT_ACTIVATE_KEYRING_KEY);
+
+ if (!r && use_keyring) {
+ r = LUKS2_key_description_by_segment(cd,
+ &cd->u.luks2.hdr, vk, CRYPT_DEFAULT_SEGMENT);
+ if (!r)
+ r = crypt_volume_key_load_in_keyring(cd, vk);
+ if (!r)
+ flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+ }
+
+ if (!r && name)
+ r = LUKS2_activate(cd, name, vk, flags);
+ } else if (isVERITY(cd->type)) {
+ r = crypt_activate_by_signed_key(cd, name, volume_key, volume_key_size, NULL, 0, flags);
+ } else if (isTCRYPT(cd->type)) {
+ if (!name)
+ return 0;
+ r = TCRYPT_activate(cd, name, &cd->u.tcrypt.hdr,
+ &cd->u.tcrypt.params, flags);
+ } else if (isINTEGRITY(cd->type)) {
+ if (!name)
+ return 0;
+ if (volume_key) {
+ vk = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!vk)
+ return -ENOMEM;
+ }
+ r = INTEGRITY_activate(cd, name, &cd->u.integrity.params, vk,
+ cd->u.integrity.journal_crypt_key,
+ cd->u.integrity.journal_mac_key, flags,
+ cd->u.integrity.sb_flags);
+ } else if (isBITLK(cd->type)) {
+ r = BITLK_activate_by_volume_key(cd, name, volume_key, volume_key_size,
+ &cd->u.bitlk.params, flags);
+ } else {
+ log_err(cd, _("Device type is not properly initialized."));
+ r = -EINVAL;
+ }
+
+ if (r < 0)
+ crypt_drop_keyring_key(cd, vk);
+ crypt_free_volume_key(vk);
+
+ return r;
+}
+
+int crypt_activate_by_signed_key(struct crypt_device *cd,
+ const char *name,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *signature,
+ size_t signature_size,
+ uint32_t flags)
+{
+ char description[512];
+ int r;
+
+ if (!cd || !isVERITY(cd->type))
+ return -EINVAL;
+
+ if (!volume_key || !volume_key_size || (!name && signature)) {
+ log_err(cd, _("Incorrect root hash specified for verity device."));
+ return -EINVAL;
+ }
+
+ if (name)
+ log_dbg(cd, "Activating volume %s by %skey.", name, signature ? "signed " : "");
+ else
+ log_dbg(cd, "Checking volume by key.");
+
+ if (cd->u.verity.hdr.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE && !signature) {
+ log_err(cd, _("Root hash signature required."));
+ return -EINVAL;
+ }
+
+ r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
+ if (r < 0)
+ return r;
+
+ if (signature && !kernel_keyring_support()) {
+ log_err(cd, _("Kernel keyring missing: required for passing signature to kernel."));
+ return -EINVAL;
+ }
+
+ /* volume_key == root hash */
+ free(CONST_CAST(void*)cd->u.verity.root_hash);
+ cd->u.verity.root_hash = NULL;
+
+ if (signature) {
+ r = snprintf(description, sizeof(description)-1, "cryptsetup:%s%s%s",
+ crypt_get_uuid(cd) ?: "", crypt_get_uuid(cd) ? "-" : "", name);
+ if (r < 0)
+ return -EINVAL;
+
+ log_dbg(cd, "Adding signature into keyring %s", description);
+ r = keyring_add_key_in_thread_keyring(USER_KEY, description, signature, signature_size);
+ if (r) {
+ log_err(cd, _("Failed to load key in kernel keyring."));
+ return r;
+ }
+ }
+
+ r = VERITY_activate(cd, name, volume_key, volume_key_size,
+ signature ? description : NULL,
+ cd->u.verity.fec_device,
+ &cd->u.verity.hdr, flags | CRYPT_ACTIVATE_READONLY);
+
+ if (!r) {
+ cd->u.verity.root_hash_size = volume_key_size;
+ cd->u.verity.root_hash = malloc(volume_key_size);
+ if (cd->u.verity.root_hash)
+ memcpy(CONST_CAST(void*)cd->u.verity.root_hash, volume_key, volume_key_size);
+ }
+
+ if (signature)
+ crypt_drop_keyring_key_by_description(cd, description, USER_KEY);
+
+ return r;
+}
+
+int crypt_deactivate_by_name(struct crypt_device *cd, const char *name, uint32_t flags)
+{
+ struct crypt_device *fake_cd = NULL;
+ struct luks2_hdr *hdr2 = NULL;
+ struct crypt_dm_active_device dmd = {};
+ int r;
+ uint32_t get_flags = DM_ACTIVE_DEVICE | DM_ACTIVE_UUID | DM_ACTIVE_HOLDERS;
+
+ if (!name)
+ return -EINVAL;
+
+ if ((flags & CRYPT_DEACTIVATE_DEFERRED) && (flags & CRYPT_DEACTIVATE_DEFERRED_CANCEL))
+ return -EINVAL;
+
+ log_dbg(cd, "Deactivating volume %s.", name);
+
+ if (!cd) {
+ r = crypt_init_by_name(&fake_cd, name);
+ if (r < 0)
+ return r;
+ cd = fake_cd;
+ }
+
+ /* skip holders detection and early abort when some flags raised */
+ if (flags & (CRYPT_DEACTIVATE_FORCE | CRYPT_DEACTIVATE_DEFERRED | CRYPT_DEACTIVATE_DEFERRED_CANCEL))
+ get_flags &= ~DM_ACTIVE_HOLDERS;
+
+ switch (crypt_status(cd, name)) {
+ case CRYPT_ACTIVE:
+ case CRYPT_BUSY:
+ if (flags & CRYPT_DEACTIVATE_DEFERRED_CANCEL) {
+ r = dm_cancel_deferred_removal(name);
+ if (r < 0)
+ log_err(cd, _("Could not cancel deferred remove from device %s."), name);
+ break;
+ }
+
+ r = dm_query_device(cd, name, get_flags, &dmd);
+ if (r >= 0) {
+ if (dmd.holders) {
+ log_err(cd, _("Device %s is still in use."), name);
+ r = -EBUSY;
+ break;
+ }
+ }
+
+ if (isLUKS2(cd->type))
+ hdr2 = crypt_get_hdr(cd, CRYPT_LUKS2);
+
+ if ((dmd.uuid && !strncmp(CRYPT_LUKS2, dmd.uuid, sizeof(CRYPT_LUKS2)-1)) || hdr2)
+ r = LUKS2_deactivate(cd, name, hdr2, &dmd, flags);
+ else if (isTCRYPT(cd->type))
+ r = TCRYPT_deactivate(cd, name, flags);
+ else
+ r = dm_remove_device(cd, name, flags);
+ if (r < 0 && crypt_status(cd, name) == CRYPT_BUSY) {
+ log_err(cd, _("Device %s is still in use."), name);
+ r = -EBUSY;
+ }
+ break;
+ case CRYPT_INACTIVE:
+ log_err(cd, _("Device %s is not active."), name);
+ r = -ENODEV;
+ break;
+ default:
+ log_err(cd, _("Invalid device %s."), name);
+ r = -EINVAL;
+ }
+
+ dm_targets_free(cd, &dmd);
+ free(CONST_CAST(void*)dmd.uuid);
+ crypt_free(fake_cd);
+
+ return r;
+}
+
+int crypt_deactivate(struct crypt_device *cd, const char *name)
+{
+ return crypt_deactivate_by_name(cd, name, 0);
+}
+
+int crypt_get_active_device(struct crypt_device *cd, const char *name,
+ struct crypt_active_device *cad)
+{
+ int r;
+ struct crypt_dm_active_device dmd, dmdi = {};
+ const char *namei = NULL;
+ struct dm_target *tgt = &dmd.segment;
+ uint64_t min_offset = UINT64_MAX;
+
+ if (!cd || !name || !cad)
+ return -EINVAL;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_DEVICE, &dmd);
+ if (r < 0)
+ return r;
+
+ /* For LUKS2 with integrity we need flags from underlying dm-integrity */
+ if (isLUKS2(cd->type) && crypt_get_integrity_tag_size(cd) && single_segment(&dmd)) {
+ namei = device_dm_name(tgt->data_device);
+ if (namei && dm_query_device(cd, namei, 0, &dmdi) >= 0)
+ dmd.flags |= dmdi.flags;
+ }
+
+ if (cd && isTCRYPT(cd->type)) {
+ cad->offset = TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
+ cad->iv_offset = TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
+ } else {
+ while (tgt) {
+ if (tgt->type == DM_CRYPT && (min_offset > tgt->u.crypt.offset)) {
+ min_offset = tgt->u.crypt.offset;
+ cad->iv_offset = tgt->u.crypt.iv_offset;
+ } else if (tgt->type == DM_INTEGRITY && (min_offset > tgt->u.integrity.offset)) {
+ min_offset = tgt->u.integrity.offset;
+ cad->iv_offset = 0;
+ } else if (tgt->type == DM_LINEAR && (min_offset > tgt->u.linear.offset)) {
+ min_offset = tgt->u.linear.offset;
+ cad->iv_offset = 0;
+ }
+ tgt = tgt->next;
+ }
+ }
+
+ if (min_offset != UINT64_MAX)
+ cad->offset = min_offset;
+
+ cad->size = dmd.size;
+ cad->flags = dmd.flags;
+
+ r = 0;
+ dm_targets_free(cd, &dmd);
+ dm_targets_free(cd, &dmdi);
+
+ return r;
+}
+
+uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd, const char *name)
+{
+ struct crypt_dm_active_device dmd;
+ uint64_t failures = 0;
+
+ if (!name)
+ return 0;
+
+ /* LUKS2 / dm-crypt does not provide this count. */
+ if (dm_query_device(cd, name, 0, &dmd) < 0)
+ return 0;
+
+ if (single_segment(&dmd) && dmd.segment.type == DM_INTEGRITY)
+ (void)dm_status_integrity_failures(cd, name, &failures);
+
+ dm_targets_free(cd, &dmd);
+
+ return failures;
+}
+
+/*
+ * Volume key handling
+ */
+int crypt_volume_key_get(struct crypt_device *cd,
+ int keyslot,
+ char *volume_key,
+ size_t *volume_key_size,
+ const char *passphrase,
+ size_t passphrase_size)
+{
+ int r;
+ struct crypt_keyslot_context kc;
+
+ if (!passphrase)
+ return crypt_volume_key_get_by_keyslot_context(cd, keyslot, volume_key, volume_key_size, NULL);
+
+ crypt_keyslot_unlock_by_passphrase_init_internal(&kc, passphrase, passphrase_size);
+
+ r = crypt_volume_key_get_by_keyslot_context(cd, keyslot, volume_key, volume_key_size, &kc);
+
+ crypt_keyslot_context_destroy_internal(&kc);
+
+ return r;
+}
+
+int crypt_volume_key_get_by_keyslot_context(struct crypt_device *cd,
+ int keyslot,
+ char *volume_key,
+ size_t *volume_key_size,
+ struct crypt_keyslot_context *kc)
+{
+ size_t passphrase_size;
+ int key_len, r;
+ const char *passphrase = NULL;
+ struct volume_key *vk = NULL;
+
+ if (!cd || !volume_key || !volume_key_size ||
+ (!kc && !isLUKS(cd->type) && !isTCRYPT(cd->type) && !isVERITY(cd->type)))
+ return -EINVAL;
+
+ if (isLUKS2(cd->type) && keyslot != CRYPT_ANY_SLOT)
+ key_len = LUKS2_get_keyslot_stored_key_size(&cd->u.luks2.hdr, keyslot);
+ else
+ key_len = crypt_get_volume_key_size(cd);
+
+ if (key_len < 0)
+ return -EINVAL;
+
+ if (key_len > (int)*volume_key_size) {
+ log_err(cd, _("Volume key buffer too small."));
+ return -ENOMEM;
+ }
+
+ if (kc && (!kc->get_passphrase || kc->type == CRYPT_KC_TYPE_KEY))
+ return -EINVAL;
+
+ if (kc) {
+ r = kc->get_passphrase(cd, kc, &passphrase, &passphrase_size);
+ if (r < 0)
+ return r;
+ }
+
+ r = -EINVAL;
+
+ if (isLUKS2(cd->type)) {
+ if (kc && !kc->get_luks2_key)
+ log_err(cd, _("Cannot retrieve volume key for LUKS2 device."));
+ else if (!kc)
+ r = -ENOENT;
+ else
+ r = kc->get_luks2_key(cd, kc, keyslot,
+ keyslot == CRYPT_ANY_SLOT ? CRYPT_DEFAULT_SEGMENT : CRYPT_ANY_SEGMENT,
+ &vk);
+ } else if (isLUKS1(cd->type)) {
+ if (kc && !kc->get_luks1_volume_key)
+ log_err(cd, _("Cannot retrieve volume key for LUKS1 device."));
+ else if (!kc)
+ r = -ENOENT;
+ else
+ r = kc->get_luks1_volume_key(cd, kc, keyslot, &vk);
+ } else if (isPLAIN(cd->type)) {
+ if (passphrase && cd->u.plain.hdr.hash)
+ r = process_key(cd, cd->u.plain.hdr.hash, key_len,
+ passphrase, passphrase_size, &vk);
+ if (r < 0)
+ log_err(cd, _("Cannot retrieve volume key for plain device."));
+ } else if (isVERITY(cd->type)) {
+ /* volume_key == root hash */
+ if (cd->u.verity.root_hash) {
+ memcpy(volume_key, cd->u.verity.root_hash, cd->u.verity.root_hash_size);
+ *volume_key_size = cd->u.verity.root_hash_size;
+ r = 0;
+ } else
+ log_err(cd, _("Cannot retrieve root hash for verity device."));
+ } else if (isTCRYPT(cd->type)) {
+ r = TCRYPT_get_volume_key(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params, &vk);
+ } else if (isBITLK(cd->type)) {
+ if (passphrase)
+ r = BITLK_get_volume_key(cd, passphrase, passphrase_size, &cd->u.bitlk.params, &vk);
+ if (r < 0)
+ log_err(cd, _("Cannot retrieve volume key for BITLK device."));
+ } else if (isFVAULT2(cd->type)) {
+ if (passphrase)
+ r = FVAULT2_get_volume_key(cd, passphrase, passphrase_size, &cd->u.fvault2.params, &vk);
+ if (r < 0)
+ log_err(cd, _("Cannot retrieve volume key for FVAULT2 device."));
+ } else
+ log_err(cd, _("This operation is not supported for %s crypt device."), cd->type ?: "(none)");
+
+ if (r == -ENOENT && isLUKS(cd->type) && cd->volume_key) {
+ vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key);
+ r = vk ? 0 : -ENOMEM;
+ }
+
+ if (r >= 0 && vk) {
+ memcpy(volume_key, vk->key, vk->keylength);
+ *volume_key_size = vk->keylength;
+ }
+
+ crypt_free_volume_key(vk);
+ return r;
+}
+
+int crypt_volume_key_verify(struct crypt_device *cd,
+ const char *volume_key,
+ size_t volume_key_size)
+{
+ struct volume_key *vk;
+ int r;
+
+ if ((r = _onlyLUKS(cd, CRYPT_CD_UNRESTRICTED)))
+ return r;
+
+ vk = crypt_alloc_volume_key(volume_key_size, volume_key);
+ if (!vk)
+ return -ENOMEM;
+
+ if (isLUKS1(cd->type))
+ r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
+ else if (isLUKS2(cd->type))
+ r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
+ else
+ r = -EINVAL;
+
+ crypt_free_volume_key(vk);
+
+ return r >= 0 ? 0 : r;
+}
+
+/*
+ * RNG and memory locking
+ */
+void crypt_set_rng_type(struct crypt_device *cd, int rng_type)
+{
+ if (!cd)
+ return;
+
+ switch (rng_type) {
+ case CRYPT_RNG_URANDOM:
+ case CRYPT_RNG_RANDOM:
+ log_dbg(cd, "RNG set to %d (%s).", rng_type, rng_type ? "random" : "urandom");
+ cd->rng_type = rng_type;
+ }
+}
+
+int crypt_get_rng_type(struct crypt_device *cd)
+{
+ if (!cd)
+ return -EINVAL;
+
+ return cd->rng_type;
+}
+
+int crypt_memory_lock(struct crypt_device *cd, int lock)
+{
+ return 0;
+}
+
+void crypt_set_compatibility(struct crypt_device *cd, uint32_t flags)
+{
+ if (cd)
+ cd->compatibility = flags;
+}
+
+uint32_t crypt_get_compatibility(struct crypt_device *cd)
+{
+ if (cd)
+ return cd->compatibility;
+
+ return 0;
+}
+
+/*
+ * Reporting
+ */
+crypt_status_info crypt_status(struct crypt_device *cd, const char *name)
+{
+ int r;
+
+ if (!name)
+ return CRYPT_INVALID;
+
+ if (!cd)
+ dm_backend_init(cd);
+
+ r = dm_status_device(cd, name);
+
+ if (!cd)
+ dm_backend_exit(cd);
+
+ if (r < 0 && r != -ENODEV)
+ return CRYPT_INVALID;
+
+ if (r == 0)
+ return CRYPT_ACTIVE;
+
+ if (r > 0)
+ return CRYPT_BUSY;
+
+ return CRYPT_INACTIVE;
+}
+
+static int _luks_dump(struct crypt_device *cd)
+{
+ int i;
+
+ log_std(cd, "LUKS header information for %s\n\n", mdata_device_path(cd));
+ log_std(cd, "Version: \t%" PRIu16 "\n", cd->u.luks1.hdr.version);
+ log_std(cd, "Cipher name: \t%s\n", cd->u.luks1.hdr.cipherName);
+ log_std(cd, "Cipher mode: \t%s\n", cd->u.luks1.hdr.cipherMode);
+ log_std(cd, "Hash spec: \t%s\n", cd->u.luks1.hdr.hashSpec);
+ log_std(cd, "Payload offset:\t%" PRIu32 "\n", cd->u.luks1.hdr.payloadOffset);
+ log_std(cd, "MK bits: \t%" PRIu32 "\n", cd->u.luks1.hdr.keyBytes * 8);
+ log_std(cd, "MK digest: \t");
+ crypt_log_hex(cd, cd->u.luks1.hdr.mkDigest, LUKS_DIGESTSIZE, " ", 0, NULL);
+ log_std(cd, "\n");
+ log_std(cd, "MK salt: \t");
+ crypt_log_hex(cd, cd->u.luks1.hdr.mkDigestSalt, LUKS_SALTSIZE/2, " ", 0, NULL);
+ log_std(cd, "\n \t");
+ crypt_log_hex(cd, cd->u.luks1.hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " ", 0, NULL);
+ log_std(cd, "\n");
+ log_std(cd, "MK iterations: \t%" PRIu32 "\n", cd->u.luks1.hdr.mkDigestIterations);
+ log_std(cd, "UUID: \t%s\n\n", cd->u.luks1.hdr.uuid);
+ for(i = 0; i < LUKS_NUMKEYS; i++) {
+ if(cd->u.luks1.hdr.keyblock[i].active == LUKS_KEY_ENABLED) {
+ log_std(cd, "Key Slot %d: ENABLED\n",i);
+ log_std(cd, "\tIterations: \t%" PRIu32 "\n",
+ cd->u.luks1.hdr.keyblock[i].passwordIterations);
+ log_std(cd, "\tSalt: \t");
+ crypt_log_hex(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt,
+ LUKS_SALTSIZE/2, " ", 0, NULL);
+ log_std(cd, "\n\t \t");
+ crypt_log_hex(cd, cd->u.luks1.hdr.keyblock[i].passwordSalt +
+ LUKS_SALTSIZE/2, LUKS_SALTSIZE/2, " ", 0, NULL);
+ log_std(cd, "\n");
+
+ log_std(cd, "\tKey material offset:\t%" PRIu32 "\n",
+ cd->u.luks1.hdr.keyblock[i].keyMaterialOffset);
+ log_std(cd, "\tAF stripes: \t%" PRIu32 "\n",
+ cd->u.luks1.hdr.keyblock[i].stripes);
+ }
+ else
+ log_std(cd, "Key Slot %d: DISABLED\n", i);
+ }
+ return 0;
+}
+
+int crypt_dump(struct crypt_device *cd)
+{
+ if (!cd)
+ return -EINVAL;
+ if (isLUKS1(cd->type))
+ return _luks_dump(cd);
+ else if (isLUKS2(cd->type))
+ return LUKS2_hdr_dump(cd, &cd->u.luks2.hdr);
+ else if (isVERITY(cd->type))
+ return VERITY_dump(cd, &cd->u.verity.hdr,
+ cd->u.verity.root_hash, cd->u.verity.root_hash_size,
+ cd->u.verity.fec_device);
+ else if (isTCRYPT(cd->type))
+ return TCRYPT_dump(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
+ else if (isINTEGRITY(cd->type))
+ return INTEGRITY_dump(cd, crypt_data_device(cd), 0);
+ else if (isBITLK(cd->type))
+ return BITLK_dump(cd, crypt_data_device(cd), &cd->u.bitlk.params);
+ else if (isFVAULT2(cd->type))
+ return FVAULT2_dump(cd, crypt_data_device(cd), &cd->u.fvault2.params);
+
+ log_err(cd, _("Dump operation is not supported for this device type."));
+ return -EINVAL;
+}
+
+int crypt_dump_json(struct crypt_device *cd, const char **json, uint32_t flags)
+{
+ if (!cd || flags)
+ return -EINVAL;
+ if (isLUKS2(cd->type))
+ return LUKS2_hdr_dump_json(cd, &cd->u.luks2.hdr, json);
+
+ log_err(cd, _("Dump operation is not supported for this device type."));
+ return -EINVAL;
+}
+
+/* internal only */
+const char *crypt_get_cipher_spec(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+ else if (isLUKS2(cd->type))
+ return LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+ else if (isLUKS1(cd->type))
+ return cd->u.luks1.cipher_spec;
+ else if (isPLAIN(cd->type))
+ return cd->u.plain.cipher_spec;
+ else if (isLOOPAES(cd->type))
+ return cd->u.loopaes.cipher_spec;
+ else if (isBITLK(cd->type))
+ return cd->u.bitlk.cipher_spec;
+ else if (!cd->type && !_init_by_name_crypt_none(cd))
+ return cd->u.none.cipher_spec;
+
+ return NULL;
+}
+
+const char *crypt_get_cipher(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+
+ if (isPLAIN(cd->type))
+ return cd->u.plain.cipher;
+
+ if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.cipherName;
+
+ if (isLUKS2(cd->type)) {
+ if (crypt_parse_name_and_mode(LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT),
+ cd->u.luks2.cipher, NULL, cd->u.luks2.cipher_mode))
+ return NULL;
+ return cd->u.luks2.cipher;
+ }
+
+ if (isLOOPAES(cd->type))
+ return cd->u.loopaes.cipher;
+
+ if (isTCRYPT(cd->type))
+ return cd->u.tcrypt.params.cipher;
+
+ if (isBITLK(cd->type))
+ return cd->u.bitlk.params.cipher;
+
+ if (isFVAULT2(cd->type))
+ return cd->u.fvault2.params.cipher;
+
+ if (!cd->type && !_init_by_name_crypt_none(cd))
+ return cd->u.none.cipher;
+
+ return NULL;
+}
+
+const char *crypt_get_cipher_mode(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+
+ if (isPLAIN(cd->type))
+ return cd->u.plain.cipher_mode;
+
+ if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.cipherMode;
+
+ if (isLUKS2(cd->type)) {
+ if (crypt_parse_name_and_mode(LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT),
+ cd->u.luks2.cipher, NULL, cd->u.luks2.cipher_mode))
+ return NULL;
+ return cd->u.luks2.cipher_mode;
+ }
+
+ if (isLOOPAES(cd->type))
+ return cd->u.loopaes.cipher_mode;
+
+ if (isTCRYPT(cd->type))
+ return cd->u.tcrypt.params.mode;
+
+ if (isBITLK(cd->type))
+ return cd->u.bitlk.params.cipher_mode;
+
+ if (isFVAULT2(cd->type))
+ return cd->u.fvault2.params.cipher_mode;
+
+ if (!cd->type && !_init_by_name_crypt_none(cd))
+ return cd->u.none.cipher_mode;
+
+ return NULL;
+}
+
+/* INTERNAL only */
+const char *crypt_get_integrity(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+
+ if (isINTEGRITY(cd->type))
+ return cd->u.integrity.params.integrity;
+
+ if (isLUKS2(cd->type))
+ return LUKS2_get_integrity(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+
+ return NULL;
+}
+
+/* INTERNAL only */
+int crypt_get_integrity_key_size(struct crypt_device *cd)
+{
+ int key_size = 0;
+
+ if (isINTEGRITY(cd->type))
+ key_size = INTEGRITY_key_size(crypt_get_integrity(cd));
+
+ if (isLUKS2(cd->type))
+ key_size = INTEGRITY_key_size(crypt_get_integrity(cd));
+
+ return key_size > 0 ? key_size : 0;
+}
+
+/* INTERNAL only */
+int crypt_get_integrity_tag_size(struct crypt_device *cd)
+{
+ if (isINTEGRITY(cd->type))
+ return cd->u.integrity.params.tag_size;
+
+ if (isLUKS2(cd->type))
+ return INTEGRITY_tag_size(crypt_get_integrity(cd),
+ crypt_get_cipher(cd),
+ crypt_get_cipher_mode(cd));
+ return 0;
+}
+
+int crypt_get_sector_size(struct crypt_device *cd)
+{
+ if (!cd)
+ return SECTOR_SIZE;
+
+ if (isPLAIN(cd->type))
+ return cd->u.plain.hdr.sector_size;
+
+ if (isINTEGRITY(cd->type))
+ return cd->u.integrity.params.sector_size;
+
+ if (isLUKS2(cd->type))
+ return LUKS2_get_sector_size(&cd->u.luks2.hdr);
+
+ return SECTOR_SIZE;
+}
+
+const char *crypt_get_uuid(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+
+ if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.uuid;
+
+ if (isLUKS2(cd->type))
+ return cd->u.luks2.hdr.uuid;
+
+ if (isVERITY(cd->type))
+ return cd->u.verity.uuid;
+
+ if (isBITLK(cd->type))
+ return cd->u.bitlk.params.guid;
+
+ if (isFVAULT2(cd->type))
+ return cd->u.fvault2.params.family_uuid;
+
+ return NULL;
+}
+
+const char *crypt_get_device_name(struct crypt_device *cd)
+{
+ const char *path;
+
+ if (!cd)
+ return NULL;
+
+ path = device_block_path(cd->device);
+ if (!path)
+ path = device_path(cd->device);
+
+ return path;
+}
+
+const char *crypt_get_metadata_device_name(struct crypt_device *cd)
+{
+ const char *path;
+
+ if (!cd || !cd->metadata_device)
+ return NULL;
+
+ path = device_block_path(cd->metadata_device);
+ if (!path)
+ path = device_path(cd->metadata_device);
+
+ return path;
+}
+
+int crypt_get_volume_key_size(struct crypt_device *cd)
+{
+ int r;
+
+ if (!cd)
+ return 0;
+
+ if (isPLAIN(cd->type))
+ return cd->u.plain.key_size;
+
+ if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.keyBytes;
+
+ if (isLUKS2(cd->type)) {
+ r = LUKS2_get_volume_key_size(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+ if (r < 0 && cd->volume_key)
+ r = cd->volume_key->keylength;
+ return r < 0 ? 0 : r;
+ }
+
+ if (isLOOPAES(cd->type))
+ return cd->u.loopaes.key_size;
+
+ if (isVERITY(cd->type))
+ return cd->u.verity.root_hash_size;
+
+ if (isTCRYPT(cd->type))
+ return cd->u.tcrypt.params.key_size;
+
+ if (isBITLK(cd->type))
+ return cd->u.bitlk.params.key_size / 8;
+
+ if (isFVAULT2(cd->type))
+ return cd->u.fvault2.params.key_size;
+
+ if (!cd->type && !_init_by_name_crypt_none(cd))
+ return cd->u.none.key_size;
+
+ return 0;
+}
+
+int crypt_keyslot_get_key_size(struct crypt_device *cd, int keyslot)
+{
+ if (!cd || !isLUKS(cd->type))
+ return -EINVAL;
+
+ if (keyslot < 0 || keyslot >= crypt_keyslot_max(cd->type))
+ return -EINVAL;
+
+ if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.keyBytes;
+
+ if (isLUKS2(cd->type))
+ return LUKS2_get_keyslot_stored_key_size(&cd->u.luks2.hdr, keyslot);
+
+ return -EINVAL;
+}
+
+int crypt_keyslot_set_encryption(struct crypt_device *cd,
+ const char *cipher,
+ size_t key_size)
+{
+ char *tmp;
+
+ if (!cd || !cipher || !key_size || !isLUKS2(cd->type))
+ return -EINVAL;
+
+ if (LUKS2_keyslot_cipher_incompatible(cd, cipher))
+ return -EINVAL;
+
+ if (!(tmp = strdup(cipher)))
+ return -ENOMEM;
+
+ free(cd->u.luks2.keyslot_cipher);
+ cd->u.luks2.keyslot_cipher = tmp;
+ cd->u.luks2.keyslot_key_size = key_size;
+
+ return 0;
+}
+
+const char *crypt_keyslot_get_encryption(struct crypt_device *cd, int keyslot, size_t *key_size)
+{
+ const char *cipher;
+
+ if (!cd || !isLUKS(cd->type) || !key_size)
+ return NULL;
+
+ if (isLUKS1(cd->type)) {
+ if (keyslot != CRYPT_ANY_SLOT &&
+ LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot) < CRYPT_SLOT_ACTIVE)
+ return NULL;
+ *key_size = crypt_get_volume_key_size(cd);
+ return cd->u.luks1.cipher_spec;
+ }
+
+ if (keyslot != CRYPT_ANY_SLOT)
+ return LUKS2_get_keyslot_cipher(&cd->u.luks2.hdr, keyslot, key_size);
+
+ /* Keyslot encryption was set through crypt_keyslot_set_encryption() */
+ if (cd->u.luks2.keyslot_cipher) {
+ *key_size = cd->u.luks2.keyslot_key_size;
+ return cd->u.luks2.keyslot_cipher;
+ }
+
+ /* Try to reuse volume encryption parameters */
+ cipher = LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+ if (!LUKS2_keyslot_cipher_incompatible(cd, cipher)) {
+ *key_size = crypt_get_volume_key_size(cd);
+ if (*key_size)
+ return cipher;
+ }
+
+ /* Fallback to default LUKS2 keyslot encryption */
+ *key_size = DEFAULT_LUKS2_KEYSLOT_KEYBITS / 8;
+ return DEFAULT_LUKS2_KEYSLOT_CIPHER;
+}
+
+int crypt_keyslot_get_pbkdf(struct crypt_device *cd, int keyslot, struct crypt_pbkdf_type *pbkdf)
+{
+ if (!cd || !pbkdf || keyslot == CRYPT_ANY_SLOT)
+ return -EINVAL;
+
+ if (isLUKS1(cd->type))
+ return LUKS_keyslot_pbkdf(&cd->u.luks1.hdr, keyslot, pbkdf);
+ else if (isLUKS2(cd->type))
+ return LUKS2_keyslot_pbkdf(&cd->u.luks2.hdr, keyslot, pbkdf);
+
+ return -EINVAL;
+}
+
+int crypt_set_data_offset(struct crypt_device *cd, uint64_t data_offset)
+{
+ if (!cd)
+ return -EINVAL;
+ if (data_offset % (MAX_SECTOR_SIZE >> SECTOR_SHIFT)) {
+ log_err(cd, _("Data offset is not multiple of %u bytes."), MAX_SECTOR_SIZE);
+ return -EINVAL;
+ }
+
+ cd->data_offset = data_offset;
+ log_dbg(cd, "Data offset set to %" PRIu64 " (512-byte) sectors.", data_offset);
+
+ return 0;
+}
+
+int crypt_set_metadata_size(struct crypt_device *cd,
+ uint64_t metadata_size,
+ uint64_t keyslots_size)
+{
+ if (!cd)
+ return -EINVAL;
+
+ if (cd->type && !isLUKS2(cd->type))
+ return -EINVAL;
+
+ if (metadata_size && LUKS2_check_metadata_area_size(metadata_size))
+ return -EINVAL;
+
+ if (keyslots_size && LUKS2_check_keyslots_area_size(keyslots_size))
+ return -EINVAL;
+
+ cd->metadata_size = metadata_size;
+ cd->keyslots_size = keyslots_size;
+
+ return 0;
+}
+
+int crypt_get_metadata_size(struct crypt_device *cd,
+ uint64_t *metadata_size,
+ uint64_t *keyslots_size)
+{
+ uint64_t msize, ksize;
+
+ if (!cd)
+ return -EINVAL;
+
+ if (!cd->type) {
+ msize = cd->metadata_size;
+ ksize = cd->keyslots_size;
+ } else if (isLUKS1(cd->type)) {
+ msize = LUKS_ALIGN_KEYSLOTS;
+ ksize = LUKS_device_sectors(&cd->u.luks1.hdr) * SECTOR_SIZE - msize;
+ } else if (isLUKS2(cd->type)) {
+ msize = LUKS2_metadata_size(&cd->u.luks2.hdr);
+ ksize = LUKS2_keyslots_size(&cd->u.luks2.hdr);
+ } else
+ return -EINVAL;
+
+ if (metadata_size)
+ *metadata_size = msize;
+ if (keyslots_size)
+ *keyslots_size = ksize;
+
+ return 0;
+}
+
+uint64_t crypt_get_data_offset(struct crypt_device *cd)
+{
+ if (!cd)
+ return 0;
+
+ if (isPLAIN(cd->type))
+ return cd->u.plain.hdr.offset;
+
+ if (isLUKS1(cd->type))
+ return cd->u.luks1.hdr.payloadOffset;
+
+ if (isLUKS2(cd->type))
+ return LUKS2_get_data_offset(&cd->u.luks2.hdr);
+
+ if (isLOOPAES(cd->type))
+ return cd->u.loopaes.hdr.offset;
+
+ if (isTCRYPT(cd->type))
+ return TCRYPT_get_data_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
+
+ if (isBITLK(cd->type))
+ return cd->u.bitlk.params.volume_header_size / SECTOR_SIZE;
+
+ if (isFVAULT2(cd->type))
+ return cd->u.fvault2.params.log_vol_off / SECTOR_SIZE;
+
+ return cd->data_offset;
+}
+
+uint64_t crypt_get_iv_offset(struct crypt_device *cd)
+{
+ if (!cd)
+ return 0;
+
+ if (isPLAIN(cd->type))
+ return cd->u.plain.hdr.skip;
+
+ if (isLOOPAES(cd->type))
+ return cd->u.loopaes.hdr.skip;
+
+ if (isTCRYPT(cd->type))
+ return TCRYPT_get_iv_offset(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params);
+
+ return 0;
+}
+
+crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot)
+{
+ if (_onlyLUKS(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED) < 0)
+ return CRYPT_SLOT_INVALID;
+
+ if (isLUKS1(cd->type))
+ return LUKS_keyslot_info(&cd->u.luks1.hdr, keyslot);
+ else if(isLUKS2(cd->type))
+ return LUKS2_keyslot_info(&cd->u.luks2.hdr, keyslot);
+
+ return CRYPT_SLOT_INVALID;
+}
+
+int crypt_keyslot_max(const char *type)
+{
+ if (isLUKS1(type))
+ return LUKS_NUMKEYS;
+
+ if (isLUKS2(type))
+ return LUKS2_KEYSLOTS_MAX;
+
+ return -EINVAL;
+}
+
+int crypt_keyslot_area(struct crypt_device *cd,
+ int keyslot,
+ uint64_t *offset,
+ uint64_t *length)
+{
+ if (_onlyLUKS(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED) || !offset || !length)
+ return -EINVAL;
+
+ if (isLUKS2(cd->type))
+ return LUKS2_keyslot_area(&cd->u.luks2.hdr, keyslot, offset, length);
+
+ return LUKS_keyslot_area(&cd->u.luks1.hdr, keyslot, offset, length);
+}
+
+crypt_keyslot_priority crypt_keyslot_get_priority(struct crypt_device *cd, int keyslot)
+{
+ if (_onlyLUKS(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED))
+ return CRYPT_SLOT_PRIORITY_INVALID;
+
+ if (keyslot < 0 || keyslot >= crypt_keyslot_max(cd->type))
+ return CRYPT_SLOT_PRIORITY_INVALID;
+
+ if (isLUKS2(cd->type))
+ return LUKS2_keyslot_priority_get(&cd->u.luks2.hdr, keyslot);
+
+ return CRYPT_SLOT_PRIORITY_NORMAL;
+}
+
+int crypt_keyslot_set_priority(struct crypt_device *cd, int keyslot, crypt_keyslot_priority priority)
+{
+ int r;
+
+ log_dbg(cd, "Setting keyslot %d to priority %d.", keyslot, priority);
+
+ if (priority == CRYPT_SLOT_PRIORITY_INVALID)
+ return -EINVAL;
+
+ if (keyslot < 0 || keyslot >= crypt_keyslot_max(cd->type))
+ return -EINVAL;
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ return LUKS2_keyslot_priority_set(cd, &cd->u.luks2.hdr, keyslot, priority, 1);
+}
+
+const char *crypt_get_type(struct crypt_device *cd)
+{
+ return cd ? cd->type : NULL;
+}
+
+const char *crypt_get_default_type(void)
+{
+ return DEFAULT_LUKS_FORMAT;
+}
+
+int crypt_get_verity_info(struct crypt_device *cd,
+ struct crypt_params_verity *vp)
+{
+ if (!cd || !isVERITY(cd->type) || !vp)
+ return -EINVAL;
+
+ vp->data_device = device_path(cd->device);
+ vp->hash_device = mdata_device_path(cd);
+ vp->fec_device = device_path(cd->u.verity.fec_device);
+ vp->fec_area_offset = cd->u.verity.hdr.fec_area_offset;
+ vp->fec_roots = cd->u.verity.hdr.fec_roots;
+ vp->hash_name = cd->u.verity.hdr.hash_name;
+ vp->salt = cd->u.verity.hdr.salt;
+ vp->salt_size = cd->u.verity.hdr.salt_size;
+ vp->data_block_size = cd->u.verity.hdr.data_block_size;
+ vp->hash_block_size = cd->u.verity.hdr.hash_block_size;
+ vp->data_size = cd->u.verity.hdr.data_size;
+ vp->hash_area_offset = cd->u.verity.hdr.hash_area_offset;
+ vp->hash_type = cd->u.verity.hdr.hash_type;
+ vp->flags = cd->u.verity.hdr.flags & (CRYPT_VERITY_NO_HEADER | CRYPT_VERITY_ROOT_HASH_SIGNATURE);
+ return 0;
+}
+
+int crypt_get_integrity_info(struct crypt_device *cd,
+ struct crypt_params_integrity *ip)
+{
+ if (!cd || !ip)
+ return -EINVAL;
+
+ if (isINTEGRITY(cd->type)) {
+ ip->journal_size = cd->u.integrity.params.journal_size;
+ ip->journal_watermark = cd->u.integrity.params.journal_watermark;
+ ip->journal_commit_time = cd->u.integrity.params.journal_commit_time;
+ ip->interleave_sectors = cd->u.integrity.params.interleave_sectors;
+ ip->tag_size = cd->u.integrity.params.tag_size;
+ ip->sector_size = cd->u.integrity.params.sector_size;
+ ip->buffer_sectors = cd->u.integrity.params.buffer_sectors;
+
+ ip->integrity = cd->u.integrity.params.integrity;
+ ip->integrity_key_size = crypt_get_integrity_key_size(cd);
+
+ ip->journal_integrity = cd->u.integrity.params.journal_integrity;
+ ip->journal_integrity_key_size = cd->u.integrity.params.journal_integrity_key_size;
+ ip->journal_integrity_key = NULL;
+
+ ip->journal_crypt = cd->u.integrity.params.journal_crypt;
+ ip->journal_crypt_key_size = cd->u.integrity.params.journal_crypt_key_size;
+ ip->journal_crypt_key = NULL;
+ return 0;
+ } else if (isLUKS2(cd->type)) {
+ ip->journal_size = 0; // FIXME
+ ip->journal_watermark = 0; // FIXME
+ ip->journal_commit_time = 0; // FIXME
+ ip->interleave_sectors = 0; // FIXME
+ ip->sector_size = crypt_get_sector_size(cd);
+ ip->buffer_sectors = 0; // FIXME
+
+ ip->integrity = LUKS2_get_integrity(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+ ip->integrity_key_size = crypt_get_integrity_key_size(cd);
+ ip->tag_size = INTEGRITY_tag_size(ip->integrity, crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
+
+ ip->journal_integrity = NULL;
+ ip->journal_integrity_key_size = 0;
+ ip->journal_integrity_key = NULL;
+
+ ip->journal_crypt = NULL;
+ ip->journal_crypt_key_size = 0;
+ ip->journal_crypt_key = NULL;
+ return 0;
+ }
+
+ return -ENOTSUP;
+}
+
+int crypt_convert(struct crypt_device *cd,
+ const char *type,
+ void *params)
+{
+ struct luks_phdr hdr1;
+ struct luks2_hdr hdr2;
+ int r;
+
+ if (!type)
+ return -EINVAL;
+
+ log_dbg(cd, "Converting LUKS device to type %s", type);
+
+ if ((r = onlyLUKS(cd)))
+ return r;
+
+ if (isLUKS1(cd->type) && isLUKS2(type))
+ r = LUKS2_luks1_to_luks2(cd, &cd->u.luks1.hdr, &hdr2);
+ else if (isLUKS2(cd->type) && isLUKS1(type))
+ r = LUKS2_luks2_to_luks1(cd, &cd->u.luks2.hdr, &hdr1);
+ else
+ return -EINVAL;
+
+ if (r < 0) {
+ /* in-memory header may be invalid after failed conversion */
+ _luks2_rollback(cd);
+ if (r == -EBUSY)
+ log_err(cd, _("Cannot convert device %s which is still in use."), mdata_device_path(cd));
+ return r;
+ }
+
+ crypt_free_type(cd, NULL);
+
+ return crypt_load(cd, type, params);
+}
+
+/* Internal access function to header pointer */
+void *crypt_get_hdr(struct crypt_device *cd, const char *type)
+{
+ /* If requested type differs, ignore it */
+ if (strcmp(cd->type, type))
+ return NULL;
+
+ if (isPLAIN(cd->type))
+ return &cd->u.plain;
+
+ if (isLUKS1(cd->type))
+ return &cd->u.luks1.hdr;
+
+ if (isLUKS2(cd->type))
+ return &cd->u.luks2.hdr;
+
+ if (isLOOPAES(cd->type))
+ return &cd->u.loopaes;
+
+ if (isVERITY(cd->type))
+ return &cd->u.verity;
+
+ if (isTCRYPT(cd->type))
+ return &cd->u.tcrypt;
+
+ return NULL;
+}
+
+/* internal only */
+struct luks2_reencrypt *crypt_get_luks2_reencrypt(struct crypt_device *cd)
+{
+ return cd->u.luks2.rh;
+}
+
+/* internal only */
+void crypt_set_luks2_reencrypt(struct crypt_device *cd, struct luks2_reencrypt *rh)
+{
+ cd->u.luks2.rh = rh;
+}
+
+/*
+ * Token handling
+ */
+int crypt_activate_by_token_pin(struct crypt_device *cd, const char *name,
+ const char *type, int token, const char *pin, size_t pin_size,
+ void *usrptr, uint32_t flags)
+{
+ int r;
+
+ log_dbg(cd, "%s volume %s using token (%s type) %d.",
+ name ? "Activating" : "Checking", name ?: "passphrase",
+ type ?: "any", token);
+
+ if ((r = _onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0)))
+ return r;
+
+ if ((flags & CRYPT_ACTIVATE_KEYRING_KEY) && !crypt_use_keyring_for_vk(cd))
+ return -EINVAL;
+
+ if ((flags & CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY) && name)
+ return -EINVAL;
+
+ r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
+ if (r < 0)
+ return r;
+
+ return LUKS2_token_open_and_activate(cd, &cd->u.luks2.hdr, token, name, type,
+ pin, pin_size, flags, usrptr);
+}
+
+int crypt_activate_by_token(struct crypt_device *cd,
+ const char *name, int token, void *usrptr, uint32_t flags)
+{
+ return crypt_activate_by_token_pin(cd, name, NULL, token, NULL, 0, usrptr, flags);
+}
+
+int crypt_token_json_get(struct crypt_device *cd, int token, const char **json)
+{
+ int r;
+
+ if (!json)
+ return -EINVAL;
+
+ log_dbg(cd, "Requesting JSON for token %d.", token);
+
+ if ((r = _onlyLUKS2(cd, CRYPT_CD_UNRESTRICTED, 0)))
+ return r;
+
+ return LUKS2_token_json_get(&cd->u.luks2.hdr, token, json) ?: token;
+}
+
+int crypt_token_json_set(struct crypt_device *cd, int token, const char *json)
+{
+ int r;
+
+ log_dbg(cd, "Updating JSON for token %d.", token);
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ return LUKS2_token_create(cd, &cd->u.luks2.hdr, token, json, 1);
+}
+
+crypt_token_info crypt_token_status(struct crypt_device *cd, int token, const char **type)
+{
+ if (_onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0))
+ return CRYPT_TOKEN_INVALID;
+
+ return LUKS2_token_status(cd, &cd->u.luks2.hdr, token, type);
+}
+
+int crypt_token_max(const char *type)
+{
+ if (isLUKS2(type))
+ return LUKS2_TOKENS_MAX;
+
+ return -EINVAL;
+}
+
+int crypt_token_luks2_keyring_get(struct crypt_device *cd,
+ int token,
+ struct crypt_token_params_luks2_keyring *params)
+{
+ crypt_token_info token_info;
+ const char *type;
+ int r;
+
+ if (!params)
+ return -EINVAL;
+
+ log_dbg(cd, "Requesting LUKS2 keyring token %d.", token);
+
+ if ((r = _onlyLUKS2(cd, CRYPT_CD_UNRESTRICTED, 0)))
+ return r;
+
+ token_info = LUKS2_token_status(cd, &cd->u.luks2.hdr, token, &type);
+ switch (token_info) {
+ case CRYPT_TOKEN_INVALID:
+ log_dbg(cd, "Token %d is invalid.", token);
+ return -EINVAL;
+ case CRYPT_TOKEN_INACTIVE:
+ log_dbg(cd, "Token %d is inactive.", token);
+ return -EINVAL;
+ case CRYPT_TOKEN_INTERNAL:
+ if (!strcmp(type, LUKS2_TOKEN_KEYRING))
+ break;
+ /* Fall through */
+ case CRYPT_TOKEN_INTERNAL_UNKNOWN:
+ case CRYPT_TOKEN_EXTERNAL:
+ case CRYPT_TOKEN_EXTERNAL_UNKNOWN:
+ log_dbg(cd, "Token %d has unexpected type %s.", token, type);
+ return -EINVAL;
+ }
+
+ return LUKS2_token_keyring_get(&cd->u.luks2.hdr, token, params);
+}
+
+int crypt_token_luks2_keyring_set(struct crypt_device *cd,
+ int token,
+ const struct crypt_token_params_luks2_keyring *params)
+{
+ int r;
+ char json[4096];
+
+ if (!params || !params->key_description)
+ return -EINVAL;
+
+ log_dbg(cd, "Creating new LUKS2 keyring token (%d).", token);
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ r = LUKS2_token_keyring_json(json, sizeof(json), params);
+ if (r < 0)
+ return r;
+
+ return LUKS2_token_create(cd, &cd->u.luks2.hdr, token, json, 1);
+}
+
+int crypt_token_assign_keyslot(struct crypt_device *cd, int token, int keyslot)
+{
+ int r;
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ return LUKS2_token_assign(cd, &cd->u.luks2.hdr, keyslot, token, 1, 1);
+}
+
+int crypt_token_unassign_keyslot(struct crypt_device *cd, int token, int keyslot)
+{
+ int r;
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ return LUKS2_token_assign(cd, &cd->u.luks2.hdr, keyslot, token, 0, 1);
+}
+
+int crypt_token_is_assigned(struct crypt_device *cd, int token, int keyslot)
+{
+ int r;
+
+ if ((r = _onlyLUKS2(cd, CRYPT_CD_QUIET | CRYPT_CD_UNRESTRICTED, 0)))
+ return r;
+
+ return LUKS2_token_is_assigned(&cd->u.luks2.hdr, keyslot, token);
+}
+
+/* Internal only */
+int crypt_metadata_locking_enabled(void)
+{
+ return _metadata_locking;
+}
+
+int crypt_metadata_locking(struct crypt_device *cd __attribute__((unused)), int enable)
+{
+ if (enable && !_metadata_locking)
+ return -EPERM;
+
+ _metadata_locking = enable ? 1 : 0;
+ return 0;
+}
+
+int crypt_persistent_flags_set(struct crypt_device *cd, crypt_flags_type type, uint32_t flags)
+{
+ int r;
+
+ if ((r = onlyLUKS2(cd)))
+ return r;
+
+ if (type == CRYPT_FLAGS_ACTIVATION)
+ return LUKS2_config_set_flags(cd, &cd->u.luks2.hdr, flags);
+
+ if (type == CRYPT_FLAGS_REQUIREMENTS)
+ return LUKS2_config_set_requirements(cd, &cd->u.luks2.hdr, flags, true);
+
+ return -EINVAL;
+}
+
+int crypt_persistent_flags_get(struct crypt_device *cd, crypt_flags_type type, uint32_t *flags)
+{
+ int r;
+
+ if (!flags)
+ return -EINVAL;
+
+ if ((r = _onlyLUKS2(cd, CRYPT_CD_UNRESTRICTED, 0)))
+ return r;
+
+ if (type == CRYPT_FLAGS_ACTIVATION)
+ return LUKS2_config_get_flags(cd, &cd->u.luks2.hdr, flags);
+
+ if (type == CRYPT_FLAGS_REQUIREMENTS)
+ return LUKS2_config_get_requirements(cd, &cd->u.luks2.hdr, flags);
+
+ return -EINVAL;
+}
+
+static int update_volume_key_segment_digest(struct crypt_device *cd, struct luks2_hdr *hdr, int digest, int commit)
+{
+ int r;
+
+ /* Remove any assignments in memory */
+ r = LUKS2_digest_segment_assign(cd, hdr, CRYPT_DEFAULT_SEGMENT, CRYPT_ANY_DIGEST, 0, 0);
+ if (r)
+ return r;
+
+ /* Assign it to the specific digest */
+ return LUKS2_digest_segment_assign(cd, hdr, CRYPT_DEFAULT_SEGMENT, digest, 1, commit);
+}
+
+static int verify_and_update_segment_digest(struct crypt_device *cd,
+ struct luks2_hdr *hdr, int keyslot, struct crypt_keyslot_context *kc)
+{
+ int digest, r;
+ struct volume_key *vk = NULL;
+
+ assert(kc);
+ assert(kc->get_luks2_key);
+ assert(keyslot >= 0);
+
+ r = kc->get_luks2_key(cd, kc, keyslot, CRYPT_ANY_SEGMENT, &vk);
+ if (r < 0)
+ return r;
+
+ /* check volume_key (param) digest matches keyslot digest */
+ r = LUKS2_digest_verify(cd, hdr, vk, keyslot);
+ if (r < 0)
+ goto out;
+ digest = r;
+
+ /* nothing to do, volume key in keyslot is already assigned to default segment */
+ r = LUKS2_digest_verify_by_segment(cd, hdr, CRYPT_DEFAULT_SEGMENT, vk);
+ if (r >= 0)
+ goto out;
+
+ /* FIXME: check new volume key is usable with current default segment */
+
+ r = update_volume_key_segment_digest(cd, &cd->u.luks2.hdr, digest, 1);
+ if (r)
+ log_err(cd, _("Failed to assign keyslot %u as the new volume key."), keyslot);
+out:
+ crypt_free_volume_key(vk);
+
+ return r < 0 ? r : keyslot;
+}
+
+static int luks2_keyslot_add_by_verified_volume_key(struct crypt_device *cd,
+ int keyslot_new,
+ const char *new_passphrase,
+ size_t new_passphrase_size,
+ struct volume_key *vk)
+{
+ int r;
+ struct luks2_keyslot_params params;
+
+ assert(cd);
+ assert(keyslot_new >= 0);
+ assert(new_passphrase);
+ assert(vk);
+ assert(crypt_volume_key_get_id(vk) >= 0);
+
+ r = LUKS2_keyslot_params_default(cd, &cd->u.luks2.hdr, &params);
+ if (r < 0) {
+ log_err(cd, _("Failed to initialize default LUKS2 keyslot parameters."));
+ return r;
+ }
+
+ r = LUKS2_digest_assign(cd, &cd->u.luks2.hdr, keyslot_new, crypt_volume_key_get_id(vk), 1, 0);
+ if (r < 0) {
+ log_err(cd, _("Failed to assign keyslot %d to digest."), keyslot_new);
+ return r;
+ }
+
+ r = LUKS2_keyslot_store(cd, &cd->u.luks2.hdr, keyslot_new,
+ CONST_CAST(char*)new_passphrase,
+ new_passphrase_size, vk, &params);
+
+ return r < 0 ? r : keyslot_new;
+}
+
+static int luks2_keyslot_add_by_volume_key(struct crypt_device *cd,
+ int keyslot_new,
+ const char *new_passphrase,
+ size_t new_passphrase_size,
+ struct volume_key *vk)
+{
+ int r;
+
+ assert(cd);
+ assert(keyslot_new >= 0);
+ assert(new_passphrase);
+ assert(vk);
+
+ r = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
+ if (r >= 0)
+ crypt_volume_key_set_id(vk, r);
+
+ if (r < 0) {
+ log_err(cd, _("Volume key does not match the volume."));
+ return r;
+ }
+
+ return luks2_keyslot_add_by_verified_volume_key(cd, keyslot_new, new_passphrase, new_passphrase_size, vk);
+}
+
+static int luks1_keyslot_add_by_volume_key(struct crypt_device *cd,
+ int keyslot_new,
+ const char *new_passphrase,
+ size_t new_passphrase_size,
+ struct volume_key *vk)
+{
+ int r;
+
+ assert(cd);
+ assert(keyslot_new >= 0);
+ assert(new_passphrase);
+ assert(vk);
+
+ r = LUKS_verify_volume_key(&cd->u.luks1.hdr, vk);
+ if (r < 0) {
+ log_err(cd, _("Volume key does not match the volume."));
+ return r;
+ }
+
+ r = LUKS_set_key(keyslot_new, CONST_CAST(char*)new_passphrase,
+ new_passphrase_size, &cd->u.luks1.hdr, vk, cd);
+
+ return r < 0 ? r : keyslot_new;
+}
+
+static int keyslot_add_by_key(struct crypt_device *cd,
+ bool is_luks1,
+ int keyslot_new,
+ const char *new_passphrase,
+ size_t new_passphrase_size,
+ struct volume_key *vk,
+ uint32_t flags)
+{
+ int r, digest;
+
+ assert(cd);
+ assert(keyslot_new >= 0);
+ assert(new_passphrase);
+ assert(vk);
+
+ if (!flags)
+ return is_luks1 ? luks1_keyslot_add_by_volume_key(cd, keyslot_new, new_passphrase, new_passphrase_size, vk) :
+ luks2_keyslot_add_by_volume_key(cd, keyslot_new, new_passphrase, new_passphrase_size, vk);
+
+ if (is_luks1)
+ return -EINVAL;
+
+ digest = LUKS2_digest_verify_by_segment(cd, &cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT, vk);
+ if (digest >= 0) /* if key matches volume key digest tear down new vk flag */
+ flags &= ~CRYPT_VOLUME_KEY_SET;
+ else {
+ /* if key matches any existing digest, do not create new digest */
+ if ((flags & CRYPT_VOLUME_KEY_DIGEST_REUSE))
+ digest = LUKS2_digest_any_matching(cd, &cd->u.luks2.hdr, vk);
+
+ /* no segment flag or new vk flag requires new key digest */
+ if (flags & (CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_SET)) {
+ if (digest < 0 || !(flags & CRYPT_VOLUME_KEY_DIGEST_REUSE))
+ digest = LUKS2_digest_create(cd, "pbkdf2", &cd->u.luks2.hdr, vk);
+ }
+ }
+
+ r = digest;
+ if (r < 0) {
+ log_err(cd, _("Volume key does not match the volume."));
+ return r;
+ }
+
+ crypt_volume_key_set_id(vk, digest);
+
+ if (flags & CRYPT_VOLUME_KEY_SET) {
+ r = update_volume_key_segment_digest(cd, &cd->u.luks2.hdr, digest, 0);
+ if (r < 0)
+ log_err(cd, _("Failed to assign keyslot %u as the new volume key."), keyslot_new);
+ }
+
+ if (r >= 0)
+ r = luks2_keyslot_add_by_verified_volume_key(cd, keyslot_new, new_passphrase, new_passphrase_size, vk);
+
+ return r < 0 ? r : keyslot_new;
+}
+
+int crypt_keyslot_add_by_key(struct crypt_device *cd,
+ int keyslot,
+ const char *volume_key,
+ size_t volume_key_size,
+ const char *passphrase,
+ size_t passphrase_size,
+ uint32_t flags)
+{
+ int r;
+ struct crypt_keyslot_context kc, new_kc;
+
+ if (!passphrase || ((flags & CRYPT_VOLUME_KEY_NO_SEGMENT) &&
+ (flags & CRYPT_VOLUME_KEY_SET)))
+ return -EINVAL;
+
+ if ((r = onlyLUKS(cd)) < 0)
+ return r;
+
+ if ((flags & CRYPT_VOLUME_KEY_SET) && crypt_keyslot_status(cd, keyslot) > CRYPT_SLOT_INACTIVE &&
+ isLUKS2(cd->type)) {
+ if (volume_key)
+ crypt_keyslot_unlock_by_key_init_internal(&kc, volume_key, volume_key_size);
+ else
+ crypt_keyslot_unlock_by_passphrase_init_internal(&kc, passphrase, passphrase_size);
+
+ r = verify_and_update_segment_digest(cd, &cd->u.luks2.hdr, keyslot, &kc);
+
+ crypt_keyslot_context_destroy_internal(&kc);
+
+ return r;
+ }
+
+ crypt_keyslot_unlock_by_key_init_internal(&kc, volume_key, volume_key_size);
+ crypt_keyslot_unlock_by_passphrase_init_internal(&new_kc, passphrase, passphrase_size);
+
+ r = crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, &kc, keyslot, &new_kc, flags);
+
+ crypt_keyslot_context_destroy_internal(&kc);
+ crypt_keyslot_context_destroy_internal(&new_kc);
+
+ return r;
+}
+
+int crypt_keyslot_add_by_keyslot_context(struct crypt_device *cd,
+ int keyslot_existing,
+ struct crypt_keyslot_context *kc,
+ int keyslot_new,
+ struct crypt_keyslot_context *new_kc,
+ uint32_t flags)
+{
+ bool is_luks1;
+ int active_slots, r;
+ const char *new_passphrase;
+ size_t new_passphrase_size;
+ struct volume_key *vk = NULL;
+
+ if (!kc || ((flags & CRYPT_VOLUME_KEY_NO_SEGMENT) &&
+ (flags & CRYPT_VOLUME_KEY_SET)))
+ return -EINVAL;
+
+ r = flags ? onlyLUKS2(cd) : onlyLUKS(cd);
+ if (r)
+ return r;
+
+ if ((flags & CRYPT_VOLUME_KEY_SET) && crypt_keyslot_status(cd, keyslot_existing) > CRYPT_SLOT_INACTIVE)
+ return verify_and_update_segment_digest(cd, &cd->u.luks2.hdr, keyslot_existing, kc);
+
+ if (!new_kc || !new_kc->get_passphrase)
+ return -EINVAL;
+
+ log_dbg(cd, "Adding new keyslot %d by %s%s, volume key provided by %s (%d).",
+ keyslot_new, keyslot_context_type_string(new_kc),
+ (flags & CRYPT_VOLUME_KEY_NO_SEGMENT) ? " unassigned to a crypt segment" : "",
+ keyslot_context_type_string(kc), keyslot_existing);
+
+ r = keyslot_verify_or_find_empty(cd, &keyslot_new);
+ if (r < 0)
+ return r;
+
+ is_luks1 = isLUKS1(cd->type);
+ if (is_luks1)
+ active_slots = LUKS_keyslot_active_count(&cd->u.luks1.hdr);
+ else
+ active_slots = LUKS2_keyslot_active_count(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT);
+
+ if (active_slots < 0)
+ return -EINVAL;
+
+ if (active_slots == 0 && kc->type != CRYPT_KC_TYPE_KEY)
+ r = -ENOENT;
+ else if (is_luks1 && kc->get_luks1_volume_key)
+ r = kc->get_luks1_volume_key(cd, kc, keyslot_existing, &vk);
+ else if (!is_luks1 && kc->get_luks2_volume_key)
+ r = kc->get_luks2_volume_key(cd, kc, keyslot_existing, &vk);
+ else
+ return -EINVAL;
+
+ if (r == -ENOENT) {
+ if ((flags & CRYPT_VOLUME_KEY_NO_SEGMENT) && kc->type == CRYPT_KC_TYPE_KEY) {
+ if (!(vk = crypt_generate_volume_key(cd, kc->u.k.volume_key_size)))
+ return -ENOMEM;
+ r = 0;
+ } else if (cd->volume_key) {
+ if (!(vk = crypt_alloc_volume_key(cd->volume_key->keylength, cd->volume_key->key)))
+ return -ENOMEM;
+ r = 0;
+ } else if (active_slots == 0) {
+ log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided."));
+ r = -EINVAL;
+ }
+ }
+
+ if (r < 0)
+ return r;
+
+ r = new_kc->get_passphrase(cd, new_kc, &new_passphrase, &new_passphrase_size);
+ /* If new keyslot context is token just assign it to new keyslot */
+ if (r >= 0 && new_kc->type == CRYPT_KC_TYPE_TOKEN && !is_luks1)
+ r = LUKS2_token_assign(cd, &cd->u.luks2.hdr, keyslot_new, new_kc->u.t.id, 1, 0);
+ if (r >= 0)
+ r = keyslot_add_by_key(cd, is_luks1, keyslot_new, new_passphrase, new_passphrase_size, vk, flags);
+
+ crypt_free_volume_key(vk);
+
+ if (r < 0) {
+ _luks2_rollback(cd);
+ return r;
+ }
+
+ return keyslot_new;
+}
+
+/*
+ * Keyring handling
+ */
+int crypt_use_keyring_for_vk(struct crypt_device *cd)
+{
+ uint32_t dmc_flags;
+
+ /* dm backend must be initialized */
+ if (!cd || !isLUKS2(cd->type))
+ return 0;
+
+ if (!_vk_via_keyring || !kernel_keyring_support())
+ return 0;
+
+ if (dm_flags(cd, DM_CRYPT, &dmc_flags))
+ return dmcrypt_keyring_bug() ? 0 : 1;
+
+ return (dmc_flags & DM_KERNEL_KEYRING_SUPPORTED);
+}
+
+int crypt_volume_key_keyring(struct crypt_device *cd __attribute__((unused)), int enable)
+{
+ _vk_via_keyring = enable ? 1 : 0;
+ return 0;
+}
+
+/* internal only */
+int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk)
+{
+ int r;
+ const char *type_name = key_type_name(LOGON_KEY);
+
+ if (!vk || !cd || !type_name)
+ return -EINVAL;
+
+ if (!vk->key_description) {
+ log_dbg(cd, "Invalid key description");
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Loading key (%zu bytes, type %s) in thread keyring.", vk->keylength, type_name);
+
+ r = keyring_add_key_in_thread_keyring(LOGON_KEY, vk->key_description, vk->key, vk->keylength);
+ if (r) {
+ log_dbg(cd, "keyring_add_key_in_thread_keyring failed (error %d)", r);
+ log_err(cd, _("Failed to load key in kernel keyring."));
+ } else
+ crypt_set_key_in_keyring(cd, 1);
+
+ return r;
+}
+
+/* internal only */
+int crypt_key_in_keyring(struct crypt_device *cd)
+{
+ return cd ? cd->key_in_keyring : 0;
+}
+
+/* internal only */
+void crypt_set_key_in_keyring(struct crypt_device *cd, unsigned key_in_keyring)
+{
+ if (!cd)
+ return;
+
+ cd->key_in_keyring = key_in_keyring;
+}
+
+/* internal only */
+void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *key_description, key_type_t ktype)
+{
+ int r;
+ const char *type_name = key_type_name(ktype);
+
+ if (!key_description || !type_name)
+ return;
+
+ log_dbg(cd, "Requesting keyring %s key for revoke and unlink.", type_name);
+
+ r = keyring_revoke_and_unlink_key(ktype, key_description);
+ if (r)
+ log_dbg(cd, "keyring_revoke_and_unlink_key failed (error %d)", r);
+ crypt_set_key_in_keyring(cd, 0);
+}
+
+/* internal only */
+void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks)
+{
+ struct volume_key *vk = vks;
+
+ while (vk) {
+ crypt_drop_keyring_key_by_description(cd, vk->key_description, LOGON_KEY);
+ vk = crypt_volume_key_next(vk);
+ }
+}
+
+int crypt_activate_by_keyring(struct crypt_device *cd,
+ const char *name,
+ const char *key_description,
+ int keyslot,
+ uint32_t flags)
+{
+ char *passphrase;
+ size_t passphrase_size;
+ int r;
+
+ if (!cd || !key_description)
+ return -EINVAL;
+
+ log_dbg(cd, "%s volume %s [keyslot %d] using passphrase in keyring.",
+ name ? "Activating" : "Checking", name ?: "passphrase", keyslot);
+
+ if (!kernel_keyring_support()) {
+ log_err(cd, _("Kernel keyring is not supported by the kernel."));
+ return -EINVAL;
+ }
+
+ r = _activate_check_status(cd, name, flags & CRYPT_ACTIVATE_REFRESH);
+ if (r < 0)
+ return r;
+
+ r = keyring_get_passphrase(key_description, &passphrase, &passphrase_size);
+ if (r < 0) {
+ log_err(cd, _("Failed to read passphrase from keyring (error %d)."), r);
+ return -EINVAL;
+ }
+
+ r = _activate_by_passphrase(cd, name, keyslot, passphrase, passphrase_size, flags);
+
+ crypt_safe_free(passphrase);
+
+ return r;
+}
+
+/*
+ * Workaround for serialization of parallel activation and memory-hard PBKDF
+ * In specific situation (systemd activation) this causes OOM killer activation.
+ * For now, let's provide this ugly way to serialize unlocking of devices.
+ */
+int crypt_serialize_lock(struct crypt_device *cd)
+{
+ if (!cd->memory_hard_pbkdf_lock_enabled)
+ return 0;
+
+ log_dbg(cd, "Taking global memory-hard access serialization lock.");
+ if (crypt_write_lock(cd, "memory-hard-access", true, &cd->pbkdf_memory_hard_lock)) {
+ log_err(cd, _("Failed to acquire global memory-hard access serialization lock."));
+ cd->pbkdf_memory_hard_lock = NULL;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void crypt_serialize_unlock(struct crypt_device *cd)
+{
+ if (!cd->memory_hard_pbkdf_lock_enabled)
+ return;
+
+ crypt_unlock_internal(cd, cd->pbkdf_memory_hard_lock);
+ cd->pbkdf_memory_hard_lock = NULL;
+}
+
+crypt_reencrypt_info crypt_reencrypt_status(struct crypt_device *cd,
+ struct crypt_params_reencrypt *params)
+{
+ if (params)
+ memset(params, 0, sizeof(*params));
+
+ if (!cd || !isLUKS(cd->type))
+ return CRYPT_REENCRYPT_INVALID;
+
+ if (isLUKS1(cd->type))
+ return CRYPT_REENCRYPT_NONE;
+
+ if (_onlyLUKS2(cd, CRYPT_CD_QUIET, CRYPT_REQUIREMENT_ONLINE_REENCRYPT))
+ return CRYPT_REENCRYPT_INVALID;
+
+ return LUKS2_reencrypt_get_params(&cd->u.luks2.hdr, params);
+}
+
+static void __attribute__((destructor)) libcryptsetup_exit(void)
+{
+ crypt_token_unload_external_all(NULL);
+
+ crypt_backend_destroy();
+ crypt_random_exit();
+}
diff --git a/lib/tcrypt/tcrypt.c b/lib/tcrypt/tcrypt.c
new file mode 100644
index 0000000..60e4966
--- /dev/null
+++ b/lib/tcrypt/tcrypt.c
@@ -0,0 +1,1136 @@
+/*
+ * TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libcryptsetup.h"
+#include "tcrypt.h"
+#include "internal.h"
+
+/* TCRYPT PBKDF variants */
+static const struct {
+ unsigned int legacy:1;
+ unsigned int veracrypt:1;
+ const char *name;
+ const char *hash;
+ unsigned int iterations;
+ uint32_t veracrypt_pim_const;
+ uint32_t veracrypt_pim_mult;
+} tcrypt_kdf[] = {
+ { 0, 0, "pbkdf2", "ripemd160", 2000, 0, 0 },
+ { 0, 0, "pbkdf2", "ripemd160", 1000, 0, 0 },
+ { 0, 0, "pbkdf2", "sha512", 1000, 0, 0 },
+ { 0, 0, "pbkdf2", "whirlpool", 1000, 0, 0 },
+ { 1, 0, "pbkdf2", "sha1", 2000, 0, 0 },
+ { 0, 1, "pbkdf2", "sha512", 500000, 15000, 1000 },
+ { 0, 1, "pbkdf2", "whirlpool", 500000, 15000, 1000 },
+ { 0, 1, "pbkdf2", "sha256", 500000, 15000, 1000 }, // VeraCrypt 1.0f
+ { 0, 1, "pbkdf2", "sha256", 200000, 0, 2048 }, // boot only
+ { 0, 1, "pbkdf2", "ripemd160", 655331, 15000, 1000 },
+ { 0, 1, "pbkdf2", "ripemd160", 327661, 0, 2048 }, // boot only
+ { 0, 1, "pbkdf2", "stribog512",500000, 15000, 1000 },
+// { 0, 1, "pbkdf2", "stribog512",200000, 0, 2048 }, // boot only
+ { 0, 0, NULL, NULL, 0, 0, 0 }
+};
+
+struct tcrypt_alg {
+ const char *name;
+ unsigned int key_size;
+ unsigned int iv_size;
+ unsigned int key_offset;
+ unsigned int iv_offset; /* or tweak key offset */
+ unsigned int key_extra_size;
+};
+
+struct tcrypt_algs {
+ unsigned int legacy:1;
+ unsigned int chain_count;
+ unsigned int chain_key_size;
+ const char *long_name;
+ const char *mode;
+ struct tcrypt_alg cipher[3];
+};
+
+/* TCRYPT cipher variants */
+static struct tcrypt_algs tcrypt_cipher[] = {
+/* XTS mode */
+{0,1,64,"aes","xts-plain64",
+ {{"aes", 64,16,0,32,0}}},
+{0,1,64,"serpent","xts-plain64",
+ {{"serpent",64,16,0,32,0}}},
+{0,1,64,"twofish","xts-plain64",
+ {{"twofish",64,16,0,32,0}}},
+{0,2,128,"twofish-aes","xts-plain64",
+ {{"twofish",64,16, 0,64,0},
+ {"aes", 64,16,32,96,0}}},
+{0,3,192,"serpent-twofish-aes","xts-plain64",
+ {{"serpent",64,16, 0, 96,0},
+ {"twofish",64,16,32,128,0},
+ {"aes", 64,16,64,160,0}}},
+{0,2,128,"aes-serpent","xts-plain64",
+ {{"aes", 64,16, 0,64,0},
+ {"serpent",64,16,32,96,0}}},
+{0,3,192,"aes-twofish-serpent","xts-plain64",
+ {{"aes", 64,16, 0, 96,0},
+ {"twofish",64,16,32,128,0},
+ {"serpent",64,16,64,160,0}}},
+{0,2,128,"serpent-twofish","xts-plain64",
+ {{"serpent",64,16, 0,64,0},
+ {"twofish",64,16,32,96,0}}},
+{0,1,64,"camellia","xts-plain64",
+ {{"camellia", 64,16,0,32,0}}},
+{0,1,64,"kuznyechik","xts-plain64",
+ {{"kuznyechik", 64,16,0,32,0}}},
+{0,2,128,"kuznyechik-camellia","xts-plain64",
+ {{"kuznyechik",64,16, 0,64,0},
+ {"camellia", 64,16,32,96,0}}},
+{0,2,128,"twofish-kuznyechik","xts-plain64",
+ {{"twofish", 64,16, 0,64,0},
+ {"kuznyechik",64,16,32,96,0}}},
+{0,2,128,"serpent-camellia","xts-plain64",
+ {{"serpent", 64,16, 0,64,0},
+ {"camellia", 64,16,32,96,0}}},
+{0,2,128,"aes-kuznyechik","xts-plain64",
+ {{"aes", 64,16, 0,64,0},
+ {"kuznyechik",64,16,32,96,0}}},
+{0,3,192,"camellia-serpent-kuznyechik","xts-plain64",
+ {{"camellia", 64,16, 0, 96,0},
+ {"serpent", 64,16,32,128,0},
+ {"kuznyechik",64,16,64,160,0}}},
+
+/* LRW mode */
+{0,1,48,"aes","lrw-benbi",
+ {{"aes", 48,16,32,0,0}}},
+{0,1,48,"serpent","lrw-benbi",
+ {{"serpent",48,16,32,0,0}}},
+{0,1,48,"twofish","lrw-benbi",
+ {{"twofish",48,16,32,0,0}}},
+{0,2,96,"twofish-aes","lrw-benbi",
+ {{"twofish",48,16,32,0,0},
+ {"aes", 48,16,64,0,0}}},
+{0,3,144,"serpent-twofish-aes","lrw-benbi",
+ {{"serpent",48,16,32,0,0},
+ {"twofish",48,16,64,0,0},
+ {"aes", 48,16,96,0,0}}},
+{0,2,96,"aes-serpent","lrw-benbi",
+ {{"aes", 48,16,32,0,0},
+ {"serpent",48,16,64,0,0}}},
+{0,3,144,"aes-twofish-serpent","lrw-benbi",
+ {{"aes", 48,16,32,0,0},
+ {"twofish",48,16,64,0,0},
+ {"serpent",48,16,96,0,0}}},
+{0,2,96,"serpent-twofish", "lrw-benbi",
+ {{"serpent",48,16,32,0,0},
+ {"twofish",48,16,64,0,0}}},
+
+/* Kernel LRW block size is fixed to 16 bytes for GF(2^128)
+ * thus cannot be used with blowfish where block is 8 bytes.
+ * There also no GF(2^64) support.
+{1,1,64,"blowfish_le","lrw-benbi",
+ {{"blowfish_le",64,8,32,0,0}}},
+{1,2,112,"blowfish_le-aes","lrw-benbi",
+ {{"blowfish_le",64, 8,32,0,0},
+ {"aes", 48,16,88,0,0}}},
+{1,3,160,"serpent-blowfish_le-aes","lrw-benbi",
+ {{"serpent", 48,16, 32,0,0},
+ {"blowfish_le",64, 8, 64,0,0},
+ {"aes", 48,16,120,0,0}}},*/
+
+/*
+ * CBC + "outer" CBC (both with whitening)
+ * chain_key_size: alg_keys_bytes + IV_seed_bytes + whitening_bytes
+ */
+{1,1,32+16+16,"aes","cbc-tcw",
+ {{"aes", 32,16,32,0,32}}},
+{1,1,32+16+16,"serpent","cbc-tcw",
+ {{"serpent",32,16,32,0,32}}},
+{1,1,32+16+16,"twofish","cbc-tcw",
+ {{"twofish",32,16,32,0,32}}},
+{1,2,64+16+16,"twofish-aes","cbci-tcrypt",
+ {{"twofish",32,16,32,0,0},
+ {"aes", 32,16,64,0,32}}},
+{1,3,96+16+16,"serpent-twofish-aes","cbci-tcrypt",
+ {{"serpent",32,16,32,0,0},
+ {"twofish",32,16,64,0,0},
+ {"aes", 32,16,96,0,32}}},
+{1,2,64+16+16,"aes-serpent","cbci-tcrypt",
+ {{"aes", 32,16,32,0,0},
+ {"serpent",32,16,64,0,32}}},
+{1,3,96+16+16,"aes-twofish-serpent", "cbci-tcrypt",
+ {{"aes", 32,16,32,0,0},
+ {"twofish",32,16,64,0,0},
+ {"serpent",32,16,96,0,32}}},
+{1,2,64+16+16,"serpent-twofish", "cbci-tcrypt",
+ {{"serpent",32,16,32,0,0},
+ {"twofish",32,16,64,0,32}}},
+{1,1,16+8+16,"cast5","cbc-tcw",
+ {{"cast5", 16,8,32,0,24}}},
+{1,1,24+8+16,"des3_ede","cbc-tcw",
+ {{"des3_ede",24,8,32,0,24}}},
+{1,1,56+8+16,"blowfish_le","cbc-tcrypt",
+ {{"blowfish_le",56,8,32,0,24}}},
+{1,2,88+16+16,"blowfish_le-aes","cbc-tcrypt",
+ {{"blowfish_le",56, 8,32,0,0},
+ {"aes", 32,16,88,0,32}}},
+{1,3,120+16+16,"serpent-blowfish_le-aes","cbc-tcrypt",
+ {{"serpent", 32,16, 32,0,0},
+ {"blowfish_le",56, 8, 64,0,0},
+ {"aes", 32,16,120,0,32}}},
+{}
+};
+
+static int TCRYPT_hdr_from_disk(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params,
+ int kdf_index, int cipher_index)
+{
+ uint32_t crc32;
+ size_t size;
+
+ /* Check CRC32 of header */
+ size = TCRYPT_HDR_LEN - sizeof(hdr->d.keys) - sizeof(hdr->d.header_crc32);
+ crc32 = crypt_crc32(~0, (unsigned char*)&hdr->d, size) ^ ~0;
+ if (be16_to_cpu(hdr->d.version) > 3 &&
+ crc32 != be32_to_cpu(hdr->d.header_crc32)) {
+ log_dbg(cd, "TCRYPT header CRC32 mismatch.");
+ return -EINVAL;
+ }
+
+ /* Check CRC32 of keys */
+ crc32 = crypt_crc32(~0, (unsigned char*)hdr->d.keys, sizeof(hdr->d.keys)) ^ ~0;
+ if (crc32 != be32_to_cpu(hdr->d.keys_crc32)) {
+ log_dbg(cd, "TCRYPT keys CRC32 mismatch.");
+ return -EINVAL;
+ }
+
+ /* Convert header to cpu format */
+ hdr->d.version = be16_to_cpu(hdr->d.version);
+ hdr->d.version_tc = be16_to_cpu(hdr->d.version_tc);
+
+ hdr->d.keys_crc32 = be32_to_cpu(hdr->d.keys_crc32);
+
+ hdr->d.hidden_volume_size = be64_to_cpu(hdr->d.hidden_volume_size);
+ hdr->d.volume_size = be64_to_cpu(hdr->d.volume_size);
+
+ hdr->d.mk_offset = be64_to_cpu(hdr->d.mk_offset);
+ if (!hdr->d.mk_offset)
+ hdr->d.mk_offset = 512;
+
+ hdr->d.mk_size = be64_to_cpu(hdr->d.mk_size);
+
+ hdr->d.flags = be32_to_cpu(hdr->d.flags);
+
+ hdr->d.sector_size = be32_to_cpu(hdr->d.sector_size);
+ if (!hdr->d.sector_size)
+ hdr->d.sector_size = 512;
+
+ hdr->d.header_crc32 = be32_to_cpu(hdr->d.header_crc32);
+
+ /* Set params */
+ params->passphrase = NULL;
+ params->passphrase_size = 0;
+ params->hash_name = tcrypt_kdf[kdf_index].hash;
+ params->key_size = tcrypt_cipher[cipher_index].chain_key_size;
+ params->cipher = tcrypt_cipher[cipher_index].long_name;
+ params->mode = tcrypt_cipher[cipher_index].mode;
+
+ return 0;
+}
+
+/*
+ * Kernel implements just big-endian version of blowfish, hack it here
+ */
+static void TCRYPT_swab_le(char *buf)
+{
+ uint32_t *l = VOIDP_CAST(uint32_t*)&buf[0];
+ uint32_t *r = VOIDP_CAST(uint32_t*)&buf[4];
+ *l = swab32(*l);
+ *r = swab32(*r);
+}
+
+static int decrypt_blowfish_le_cbc(struct tcrypt_alg *alg,
+ const char *key, char *buf)
+{
+ int bs = alg->iv_size;
+ char iv[8], iv_old[8];
+ struct crypt_cipher *cipher = NULL;
+ int i, j, r;
+
+ assert(bs == 8);
+
+ r = crypt_cipher_init(&cipher, "blowfish", "ecb",
+ &key[alg->key_offset], alg->key_size);
+ if (r < 0)
+ return r;
+
+ memcpy(iv, &key[alg->iv_offset], alg->iv_size);
+ for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
+ memcpy(iv_old, &buf[i], bs);
+ TCRYPT_swab_le(&buf[i]);
+ r = crypt_cipher_decrypt(cipher, &buf[i], &buf[i],
+ bs, NULL, 0);
+ TCRYPT_swab_le(&buf[i]);
+ if (r < 0)
+ break;
+ for (j = 0; j < bs; j++)
+ buf[i + j] ^= iv[j];
+ memcpy(iv, iv_old, bs);
+ }
+
+ crypt_cipher_destroy(cipher);
+ crypt_safe_memzero(iv, bs);
+ crypt_safe_memzero(iv_old, bs);
+ return r;
+}
+
+static void TCRYPT_remove_whitening(char *buf, const char *key)
+{
+ int j;
+
+ for (j = 0; j < TCRYPT_HDR_LEN; j++)
+ buf[j] ^= key[j % 8];
+}
+
+static void TCRYPT_copy_key(struct tcrypt_alg *alg, const char *mode,
+ char *out_key, const char *key)
+{
+ int ks2;
+ if (!strncmp(mode, "xts", 3)) {
+ ks2 = alg->key_size / 2;
+ memcpy(out_key, &key[alg->key_offset], ks2);
+ memcpy(&out_key[ks2], &key[alg->iv_offset], ks2);
+ } else if (!strncmp(mode, "lrw", 3)) {
+ ks2 = alg->key_size - TCRYPT_LRW_IKEY_LEN;
+ memcpy(out_key, &key[alg->key_offset], ks2);
+ memcpy(&out_key[ks2], key, TCRYPT_LRW_IKEY_LEN);
+ } else if (!strncmp(mode, "cbc", 3)) {
+ memcpy(out_key, &key[alg->key_offset], alg->key_size);
+ /* IV + whitening */
+ memcpy(&out_key[alg->key_size], &key[alg->iv_offset],
+ alg->key_extra_size);
+ }
+}
+
+static int TCRYPT_decrypt_hdr_one(struct tcrypt_alg *alg, const char *mode,
+ const char *key,struct tcrypt_phdr *hdr)
+{
+ char backend_key[TCRYPT_HDR_KEY_LEN];
+ char iv[TCRYPT_HDR_IV_LEN] = {};
+ char mode_name[MAX_CIPHER_LEN + 1];
+ struct crypt_cipher *cipher;
+ char *c, *buf = (char*)&hdr->e;
+ int r;
+
+ /* Remove IV if present */
+ mode_name[MAX_CIPHER_LEN] = '\0';
+ strncpy(mode_name, mode, MAX_CIPHER_LEN);
+ c = strchr(mode_name, '-');
+ if (c)
+ *c = '\0';
+
+ if (!strncmp(mode, "lrw", 3))
+ iv[alg->iv_size - 1] = 1;
+ else if (!strncmp(mode, "cbc", 3)) {
+ TCRYPT_remove_whitening(buf, &key[8]);
+ if (!strcmp(alg->name, "blowfish_le"))
+ return decrypt_blowfish_le_cbc(alg, key, buf);
+ memcpy(iv, &key[alg->iv_offset], alg->iv_size);
+ }
+
+ TCRYPT_copy_key(alg, mode, backend_key, key);
+ r = crypt_cipher_init(&cipher, alg->name, mode_name,
+ backend_key, alg->key_size);
+ if (!r) {
+ r = crypt_cipher_decrypt(cipher, buf, buf, TCRYPT_HDR_LEN,
+ iv, alg->iv_size);
+ crypt_cipher_destroy(cipher);
+ }
+
+ crypt_safe_memzero(backend_key, sizeof(backend_key));
+ crypt_safe_memzero(iv, TCRYPT_HDR_IV_LEN);
+ return r;
+}
+
+/*
+ * For chained ciphers and CBC mode we need "outer" decryption.
+ * Backend doesn't provide this, so implement it here directly using ECB.
+ */
+static int TCRYPT_decrypt_cbci(struct tcrypt_algs *ciphers,
+ const char *key, struct tcrypt_phdr *hdr)
+{
+ struct crypt_cipher *cipher[3];
+ unsigned int bs = ciphers->cipher[0].iv_size;
+ char *buf = (char*)&hdr->e, iv[16], iv_old[16];
+ unsigned int i, j;
+ int r = -EINVAL;
+
+ assert(ciphers->chain_count <= 3);
+ assert(bs <= 16);
+
+ TCRYPT_remove_whitening(buf, &key[8]);
+
+ memcpy(iv, &key[ciphers->cipher[0].iv_offset], bs);
+
+ /* Initialize all ciphers in chain in ECB mode */
+ for (j = 0; j < ciphers->chain_count; j++)
+ cipher[j] = NULL;
+ for (j = 0; j < ciphers->chain_count; j++) {
+ r = crypt_cipher_init(&cipher[j], ciphers->cipher[j].name, "ecb",
+ &key[ciphers->cipher[j].key_offset],
+ ciphers->cipher[j].key_size);
+ if (r < 0)
+ goto out;
+ }
+
+ /* Implements CBC with chained ciphers in loop inside */
+ for (i = 0; i < TCRYPT_HDR_LEN; i += bs) {
+ memcpy(iv_old, &buf[i], bs);
+ for (j = ciphers->chain_count; j > 0; j--) {
+ r = crypt_cipher_decrypt(cipher[j - 1], &buf[i], &buf[i],
+ bs, NULL, 0);
+ if (r < 0)
+ goto out;
+ }
+ for (j = 0; j < bs; j++)
+ buf[i + j] ^= iv[j];
+ memcpy(iv, iv_old, bs);
+ }
+out:
+ for (j = 0; j < ciphers->chain_count; j++)
+ if (cipher[j])
+ crypt_cipher_destroy(cipher[j]);
+
+ crypt_safe_memzero(iv, bs);
+ crypt_safe_memzero(iv_old, bs);
+ return r;
+}
+
+static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
+ const char *key, struct crypt_params_tcrypt *params)
+{
+ struct tcrypt_phdr hdr2;
+ int i, j, r = -EINVAL;
+
+ for (i = 0; tcrypt_cipher[i].chain_count; i++) {
+ if (params->cipher && !strstr(tcrypt_cipher[i].long_name, params->cipher))
+ continue;
+ if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
+ continue;
+ log_dbg(cd, "TCRYPT: trying cipher %s-%s",
+ tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode);
+
+ memcpy(&hdr2.e, &hdr->e, TCRYPT_HDR_LEN);
+
+ if (!strncmp(tcrypt_cipher[i].mode, "cbci", 4))
+ r = TCRYPT_decrypt_cbci(&tcrypt_cipher[i], key, &hdr2);
+ else for (j = tcrypt_cipher[i].chain_count - 1; j >= 0 ; j--) {
+ if (!tcrypt_cipher[i].cipher[j].name)
+ continue;
+ r = TCRYPT_decrypt_hdr_one(&tcrypt_cipher[i].cipher[j],
+ tcrypt_cipher[i].mode, key, &hdr2);
+ if (r < 0)
+ break;
+ }
+
+ if (r < 0) {
+ log_dbg(cd, "TCRYPT: returned error %d, skipped.", r);
+ if (r == -ENOTSUP)
+ break;
+ r = -ENOENT;
+ continue;
+ }
+
+ if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
+ log_dbg(cd, "TCRYPT: Signature magic detected.");
+ memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
+ r = i;
+ break;
+ }
+ if ((params->flags & CRYPT_TCRYPT_VERA_MODES) &&
+ !strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
+ log_dbg(cd, "TCRYPT: Signature magic detected (Veracrypt).");
+ memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
+ r = i;
+ break;
+ }
+ r = -EPERM;
+ }
+
+ crypt_safe_memzero(&hdr2, sizeof(hdr2));
+ return r;
+}
+
+static int TCRYPT_pool_keyfile(struct crypt_device *cd,
+ unsigned char pool[VCRYPT_KEY_POOL_LEN],
+ const char *keyfile, int keyfiles_pool_length)
+{
+ unsigned char *data;
+ int i, j, fd, data_size, r = -EIO;
+ uint32_t crc;
+
+ log_dbg(cd, "TCRYPT: using keyfile %s.", keyfile);
+
+ data = malloc(TCRYPT_KEYFILE_LEN);
+ if (!data)
+ return -ENOMEM;
+ memset(data, 0, TCRYPT_KEYFILE_LEN);
+
+ fd = open(keyfile, O_RDONLY);
+ if (fd < 0) {
+ log_err(cd, _("Failed to open key file."));
+ goto out;
+ }
+
+ data_size = read_buffer(fd, data, TCRYPT_KEYFILE_LEN);
+ close(fd);
+ if (data_size < 0) {
+ log_err(cd, _("Error reading keyfile %s."), keyfile);
+ goto out;
+ }
+
+ for (i = 0, j = 0, crc = ~0U; i < data_size; i++) {
+ crc = crypt_crc32(crc, &data[i], 1);
+ pool[j++] += (unsigned char)(crc >> 24);
+ pool[j++] += (unsigned char)(crc >> 16);
+ pool[j++] += (unsigned char)(crc >> 8);
+ pool[j++] += (unsigned char)(crc);
+ j %= keyfiles_pool_length;
+ }
+ r = 0;
+out:
+ crypt_safe_memzero(&crc, sizeof(crc));
+ crypt_safe_memzero(data, TCRYPT_KEYFILE_LEN);
+ free(data);
+
+ return r;
+}
+
+static int TCRYPT_init_hdr(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params)
+{
+ unsigned char pwd[VCRYPT_KEY_POOL_LEN] = {};
+ size_t passphrase_size, max_passphrase_size;
+ char *key;
+ unsigned int i, skipped = 0, iterations;
+ int r = -EPERM, keyfiles_pool_length;
+
+ if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
+ return -ENOMEM;
+
+ if (params->flags & CRYPT_TCRYPT_VERA_MODES &&
+ params->passphrase_size > TCRYPT_KEY_POOL_LEN) {
+ /* Really. Keyfile pool length depends on passphrase size in Veracrypt. */
+ max_passphrase_size = VCRYPT_KEY_POOL_LEN;
+ keyfiles_pool_length = VCRYPT_KEY_POOL_LEN;
+ } else {
+ max_passphrase_size = TCRYPT_KEY_POOL_LEN;
+ keyfiles_pool_length = TCRYPT_KEY_POOL_LEN;
+ }
+
+ if (params->keyfiles_count)
+ passphrase_size = max_passphrase_size;
+ else
+ passphrase_size = params->passphrase_size;
+
+ if (params->passphrase_size > max_passphrase_size) {
+ log_err(cd, _("Maximum TCRYPT passphrase length (%zu) exceeded."),
+ max_passphrase_size);
+ goto out;
+ }
+
+ /* Calculate pool content from keyfiles */
+ for (i = 0; i < params->keyfiles_count; i++) {
+ r = TCRYPT_pool_keyfile(cd, pwd, params->keyfiles[i], keyfiles_pool_length);
+ if (r < 0)
+ goto out;
+ }
+
+ /* If provided password, combine it with pool */
+ for (i = 0; i < params->passphrase_size; i++)
+ pwd[i] += params->passphrase[i];
+
+ for (i = 0; tcrypt_kdf[i].name; i++) {
+ if (params->hash_name && strcmp(params->hash_name, tcrypt_kdf[i].hash))
+ continue;
+ if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
+ continue;
+ if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt)
+ continue;
+ if ((params->flags & CRYPT_TCRYPT_VERA_MODES) && params->veracrypt_pim) {
+ /* Do not try TrueCrypt modes if we have PIM value */
+ if (!tcrypt_kdf[i].veracrypt)
+ continue;
+ /* adjust iterations to given PIM cmdline parameter */
+ iterations = tcrypt_kdf[i].veracrypt_pim_const +
+ (tcrypt_kdf[i].veracrypt_pim_mult * params->veracrypt_pim);
+ } else
+ iterations = tcrypt_kdf[i].iterations;
+ /* Derive header key */
+ log_dbg(cd, "TCRYPT: trying KDF: %s-%s-%d%s.",
+ tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations,
+ params->veracrypt_pim && tcrypt_kdf[i].veracrypt ? "-PIM" : "");
+ r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash,
+ (char*)pwd, passphrase_size,
+ hdr->salt, TCRYPT_HDR_SALT_LEN,
+ key, TCRYPT_HDR_KEY_LEN,
+ iterations, 0, 0);
+ if (r < 0) {
+ log_verbose(cd, _("PBKDF2 hash algorithm %s not available, skipping."),
+ tcrypt_kdf[i].hash);
+ skipped++;
+ r = -EPERM;
+ continue;
+ }
+
+ /* Decrypt header */
+ r = TCRYPT_decrypt_hdr(cd, hdr, key, params);
+ if (r == -ENOENT) {
+ skipped++;
+ r = -EPERM;
+ continue;
+ }
+ if (r != -EPERM)
+ break;
+ }
+
+ if ((r < 0 && skipped && skipped == i) || r == -ENOTSUP) {
+ log_err(cd, _("Required kernel crypto interface not available."));
+#ifdef ENABLE_AF_ALG
+ log_err(cd, _("Ensure you have algif_skcipher kernel module loaded."));
+#endif
+ r = -ENOTSUP;
+ }
+ if (r < 0)
+ goto out;
+
+ r = TCRYPT_hdr_from_disk(cd, hdr, params, i, r);
+ if (!r) {
+ log_dbg(cd, "TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d"
+ ", mk_offset %" PRIu64 ", hidden_size %" PRIu64
+ ", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ?
+ VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC,
+ (int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size,
+ hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size);
+ log_dbg(cd, "TCRYPT: Header cipher %s-%s, key size %zu",
+ params->cipher, params->mode, params->key_size);
+ }
+out:
+ crypt_safe_memzero(pwd, TCRYPT_KEY_POOL_LEN);
+ if (key)
+ crypt_safe_memzero(key, TCRYPT_HDR_KEY_LEN);
+ free(key);
+ return r;
+}
+
+int TCRYPT_read_phdr(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params)
+{
+ struct device *base_device = NULL, *device = crypt_metadata_device(cd);
+ ssize_t hdr_size = sizeof(struct tcrypt_phdr);
+ char *base_device_path;
+ int devfd, r;
+
+ assert(sizeof(struct tcrypt_phdr) == 512);
+
+ log_dbg(cd, "Reading TCRYPT header of size %zu bytes from device %s.",
+ hdr_size, device_path(device));
+
+ if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER &&
+ crypt_dev_is_partition(device_path(device))) {
+ base_device_path = crypt_get_base_device(device_path(device));
+
+ log_dbg(cd, "Reading TCRYPT system header from device %s.", base_device_path ?: "?");
+ if (!base_device_path)
+ return -EINVAL;
+
+ r = device_alloc(cd, &base_device, base_device_path);
+ free(base_device_path);
+ if (r < 0)
+ return r;
+ devfd = device_open(cd, base_device, O_RDONLY);
+ } else
+ devfd = device_open(cd, device, O_RDONLY);
+
+ if (devfd < 0) {
+ device_free(cd, base_device);
+ log_err(cd, _("Cannot open device %s."), device_path(device));
+ return -EINVAL;
+ }
+
+ r = -EIO;
+ if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr, hdr_size,
+ TCRYPT_HDR_SYSTEM_OFFSET) == hdr_size) {
+ r = TCRYPT_init_hdr(cd, hdr, params);
+ }
+ } else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
+ if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) {
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr, hdr_size,
+ TCRYPT_HDR_HIDDEN_OFFSET_BCK) == hdr_size)
+ r = TCRYPT_init_hdr(cd, hdr, params);
+ } else {
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr, hdr_size,
+ TCRYPT_HDR_HIDDEN_OFFSET) == hdr_size)
+ r = TCRYPT_init_hdr(cd, hdr, params);
+ if (r && read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr, hdr_size,
+ TCRYPT_HDR_HIDDEN_OFFSET_OLD) == hdr_size)
+ r = TCRYPT_init_hdr(cd, hdr, params);
+ }
+ } else if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) {
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr, hdr_size,
+ TCRYPT_HDR_OFFSET_BCK) == hdr_size)
+ r = TCRYPT_init_hdr(cd, hdr, params);
+ } else if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), hdr, hdr_size, 0) == hdr_size)
+ r = TCRYPT_init_hdr(cd, hdr, params);
+
+ device_free(cd, base_device);
+ if (r < 0)
+ memset(hdr, 0, sizeof (*hdr));
+ return r;
+}
+
+static struct tcrypt_algs *TCRYPT_get_algs(const char *cipher, const char *mode)
+{
+ int i;
+
+ if (!cipher || !mode)
+ return NULL;
+
+ for (i = 0; tcrypt_cipher[i].chain_count; i++)
+ if (!strcmp(tcrypt_cipher[i].long_name, cipher) &&
+ !strcmp(tcrypt_cipher[i].mode, mode))
+ return &tcrypt_cipher[i];
+
+ return NULL;
+}
+
+int TCRYPT_activate(struct crypt_device *cd,
+ const char *name,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params,
+ uint32_t flags)
+{
+ char dm_name[PATH_MAX], dm_dev_name[PATH_MAX], cipher_spec[MAX_CIPHER_LEN*2+1];
+ char *part_path;
+ unsigned int i;
+ int r;
+ uint32_t req_flags, dmc_flags;
+ struct tcrypt_algs *algs;
+ enum devcheck device_check;
+ uint64_t offset = crypt_get_data_offset(cd);
+ struct volume_key *vk = NULL;
+ struct device *ptr_dev = crypt_data_device(cd), *device = NULL, *part_device = NULL;
+ struct crypt_dm_active_device dmd = {
+ .flags = flags
+ };
+
+ if (!hdr->d.version) {
+ log_dbg(cd, "TCRYPT: this function is not supported without encrypted header load.");
+ return -ENOTSUP;
+ }
+
+ if (hdr->d.sector_size % SECTOR_SIZE) {
+ log_err(cd, _("Activation is not supported for %d sector size."),
+ hdr->d.sector_size);
+ return -ENOTSUP;
+ }
+
+ if (strstr(params->mode, "-tcrypt")) {
+ log_err(cd, _("Kernel does not support activation for this TCRYPT legacy mode."));
+ return -ENOTSUP;
+ }
+
+ if (strstr(params->mode, "-tcw"))
+ req_flags = DM_TCW_SUPPORTED;
+ else
+ req_flags = DM_PLAIN64_SUPPORTED;
+
+ algs = TCRYPT_get_algs(params->cipher, params->mode);
+ if (!algs)
+ return -EINVAL;
+
+ if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
+ dmd.size = 0;
+ else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER)
+ dmd.size = hdr->d.hidden_volume_size / SECTOR_SIZE;
+ else
+ dmd.size = hdr->d.volume_size / SECTOR_SIZE;
+
+ if (dmd.flags & CRYPT_ACTIVATE_SHARED)
+ device_check = DEV_OK;
+ else
+ device_check = DEV_EXCL;
+
+ if ((params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) &&
+ !crypt_dev_is_partition(device_path(crypt_data_device(cd)))) {
+ part_path = crypt_get_partition_device(device_path(crypt_data_device(cd)),
+ crypt_get_data_offset(cd), dmd.size);
+ if (part_path) {
+ if (!device_alloc(cd, &part_device, part_path)) {
+ log_verbose(cd, _("Activating TCRYPT system encryption for partition %s."),
+ part_path);
+ ptr_dev = part_device;
+ offset = 0;
+ }
+ free(part_path);
+ } else
+ /*
+ * System encryption use the whole device mapping, there can
+ * be active partitions.
+ */
+ device_check = DEV_OK;
+ }
+
+ r = device_block_adjust(cd, ptr_dev, device_check,
+ offset, &dmd.size, &dmd.flags);
+ if (r)
+ goto out;
+
+ /* From here, key size for every cipher must be the same */
+ vk = crypt_alloc_volume_key(algs->cipher[0].key_size +
+ algs->cipher[0].key_extra_size, NULL);
+ if (!vk) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ for (i = algs->chain_count; i > 0; i--) {
+ if (i == 1) {
+ dm_name[sizeof(dm_name)-1] = '\0';
+ strncpy(dm_name, name, sizeof(dm_name)-1);
+ dmd.flags = flags;
+ } else {
+ if (snprintf(dm_name, sizeof(dm_name), "%s_%d", name, i-1) < 0) {
+ r = -EINVAL;
+ break;
+ }
+ dmd.flags = flags | CRYPT_ACTIVATE_PRIVATE;
+ }
+
+ TCRYPT_copy_key(&algs->cipher[i-1], algs->mode,
+ vk->key, hdr->d.keys);
+
+ if (algs->chain_count != i) {
+ if (snprintf(dm_dev_name, sizeof(dm_dev_name), "%s/%s_%d", dm_get_dir(), name, i) < 0) {
+ r = -EINVAL;
+ break;
+ }
+ r = device_alloc(cd, &device, dm_dev_name);
+ if (r)
+ break;
+ ptr_dev = device;
+ offset = 0;
+ }
+
+ r = snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", algs->cipher[i-1].name, algs->mode);
+ if (r < 0 || (size_t)r >= sizeof(cipher_spec)) {
+ r = -ENOMEM;
+ break;
+ }
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, ptr_dev, vk,
+ cipher_spec, crypt_get_iv_offset(cd), offset,
+ crypt_get_integrity(cd),
+ crypt_get_integrity_tag_size(cd),
+ crypt_get_sector_size(cd));
+ if (r)
+ break;
+
+ log_dbg(cd, "Trying to activate TCRYPT device %s using cipher %s.",
+ dm_name, dmd.segment.u.crypt.cipher);
+ r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd);
+
+ dm_targets_free(cd, &dmd);
+ device_free(cd, device);
+ device = NULL;
+
+ if (r)
+ break;
+ }
+
+ if (r < 0 &&
+ (dm_flags(cd, DM_CRYPT, &dmc_flags) || ((dmc_flags & req_flags) != req_flags))) {
+ log_err(cd, _("Kernel does not support TCRYPT compatible mapping."));
+ r = -ENOTSUP;
+ }
+
+out:
+ crypt_free_volume_key(vk);
+ device_free(cd, device);
+ device_free(cd, part_device);
+ return r;
+}
+
+static int TCRYPT_remove_one(struct crypt_device *cd, const char *name,
+ const char *base_uuid, int index, uint32_t flags)
+{
+ struct crypt_dm_active_device dmd;
+ char dm_name[PATH_MAX];
+ int r;
+
+ if (snprintf(dm_name, sizeof(dm_name), "%s_%d", name, index) < 0)
+ return -ENOMEM;
+
+ r = dm_status_device(cd, dm_name);
+ if (r < 0)
+ return r;
+
+ r = dm_query_device(cd, dm_name, DM_ACTIVE_UUID, &dmd);
+ if (!r && !strncmp(dmd.uuid, base_uuid, strlen(base_uuid)))
+ r = dm_remove_device(cd, dm_name, flags);
+
+ free(CONST_CAST(void*)dmd.uuid);
+ return r;
+}
+
+int TCRYPT_deactivate(struct crypt_device *cd, const char *name, uint32_t flags)
+{
+ struct crypt_dm_active_device dmd;
+ int r;
+
+ r = dm_query_device(cd, name, DM_ACTIVE_UUID, &dmd);
+ if (r < 0)
+ return r;
+ if (!dmd.uuid)
+ return -EINVAL;
+
+ r = dm_remove_device(cd, name, flags);
+ if (r < 0)
+ goto out;
+
+ r = TCRYPT_remove_one(cd, name, dmd.uuid, 1, flags);
+ if (r < 0)
+ goto out;
+
+ r = TCRYPT_remove_one(cd, name, dmd.uuid, 2, flags);
+out:
+ free(CONST_CAST(void*)dmd.uuid);
+ return (r == -ENODEV) ? 0 : r;
+}
+
+static int TCRYPT_status_one(struct crypt_device *cd, const char *name,
+ const char *base_uuid, int index,
+ size_t *key_size, char *cipher,
+ struct tcrypt_phdr *tcrypt_hdr,
+ struct device **device)
+{
+ struct crypt_dm_active_device dmd;
+ struct dm_target *tgt = &dmd.segment;
+ char dm_name[PATH_MAX], *c;
+ int r;
+
+ if (snprintf(dm_name, sizeof(dm_name), "%s_%d", name, index) < 0)
+ return -ENOMEM;
+
+ r = dm_status_device(cd, dm_name);
+ if (r < 0)
+ return r;
+
+ r = dm_query_device(cd, dm_name, DM_ACTIVE_DEVICE |
+ DM_ACTIVE_UUID |
+ DM_ACTIVE_CRYPT_CIPHER |
+ DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
+ if (r < 0)
+ return r;
+ if (!single_segment(&dmd) || tgt->type != DM_CRYPT) {
+ r = -ENOTSUP;
+ goto out;
+ }
+
+ r = 0;
+
+ if (!strncmp(dmd.uuid, base_uuid, strlen(base_uuid))) {
+ if ((c = strchr(tgt->u.crypt.cipher, '-')))
+ *c = '\0';
+ strcat(cipher, "-");
+ strncat(cipher, tgt->u.crypt.cipher, MAX_CIPHER_LEN);
+ *key_size += tgt->u.crypt.vk->keylength;
+ tcrypt_hdr->d.mk_offset = tgt->u.crypt.offset * SECTOR_SIZE;
+ device_free(cd, *device);
+ MOVE_REF(*device, tgt->data_device);
+ } else
+ r = -ENODEV;
+out:
+ dm_targets_free(cd, &dmd);
+ free(CONST_CAST(void*)dmd.uuid);
+ return r;
+}
+
+int TCRYPT_init_by_name(struct crypt_device *cd, const char *name,
+ const char *uuid,
+ const struct dm_target *tgt,
+ struct device **device,
+ struct crypt_params_tcrypt *tcrypt_params,
+ struct tcrypt_phdr *tcrypt_hdr)
+{
+ struct tcrypt_algs *algs;
+ char cipher[MAX_CIPHER_LEN * 4], mode[MAX_CIPHER_LEN+1], *tmp;
+ size_t key_size;
+ int r;
+
+ memset(tcrypt_params, 0, sizeof(*tcrypt_params));
+ memset(tcrypt_hdr, 0, sizeof(*tcrypt_hdr));
+ tcrypt_hdr->d.sector_size = SECTOR_SIZE;
+ tcrypt_hdr->d.mk_offset = tgt->u.crypt.offset * SECTOR_SIZE;
+
+ strncpy(cipher, tgt->u.crypt.cipher, MAX_CIPHER_LEN);
+ tmp = strchr(cipher, '-');
+ if (!tmp)
+ return -EINVAL;
+ *tmp = '\0';
+ mode[MAX_CIPHER_LEN] = '\0';
+ strncpy(mode, ++tmp, MAX_CIPHER_LEN);
+
+ key_size = tgt->u.crypt.vk->keylength;
+ r = TCRYPT_status_one(cd, name, uuid, 1, &key_size,
+ cipher, tcrypt_hdr, device);
+ if (!r)
+ r = TCRYPT_status_one(cd, name, uuid, 2, &key_size,
+ cipher, tcrypt_hdr, device);
+
+ if (r < 0 && r != -ENODEV)
+ return r;
+
+ algs = TCRYPT_get_algs(cipher, mode);
+ if (!algs || key_size != algs->chain_key_size)
+ return -EINVAL;
+
+ tcrypt_params->key_size = algs->chain_key_size;
+ tcrypt_params->cipher = algs->long_name;
+ tcrypt_params->mode = algs->mode;
+ return 0;
+}
+
+uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params)
+{
+ uint64_t size;
+
+ if (!hdr->d.version) {
+ /* No real header loaded, initialized by active device, use default mk_offset */
+ } else if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
+ /* Mapping through whole device, not partition! */
+ if (crypt_dev_is_partition(device_path(crypt_data_device(cd))))
+ return 0;
+ } else if (params->mode && !strncmp(params->mode, "xts", 3)) {
+ if (hdr->d.version < 3)
+ return 1;
+
+ if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
+ if (hdr->d.version > 3)
+ return (hdr->d.mk_offset / SECTOR_SIZE);
+ if (device_size(crypt_metadata_device(cd), &size) < 0)
+ return 0;
+ return (size - hdr->d.hidden_volume_size +
+ (TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / SECTOR_SIZE;
+ }
+ } else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
+ if (device_size(crypt_metadata_device(cd), &size) < 0)
+ return 0;
+ return (size - hdr->d.hidden_volume_size +
+ (TCRYPT_HDR_HIDDEN_OFFSET_OLD)) / SECTOR_SIZE;
+ }
+
+ return hdr->d.mk_offset / SECTOR_SIZE;
+}
+
+uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params)
+{
+ uint64_t iv_offset;
+
+ if (params->mode && !strncmp(params->mode, "xts", 3))
+ iv_offset = TCRYPT_get_data_offset(cd, hdr, params);
+ else if (params->mode && !strncmp(params->mode, "lrw", 3))
+ iv_offset = 0;
+ else
+ iv_offset = hdr->d.mk_offset / SECTOR_SIZE;
+
+ if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER)
+ iv_offset += crypt_dev_partition_offset(device_path(crypt_data_device(cd)));
+
+ return iv_offset;
+}
+
+int TCRYPT_get_volume_key(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params,
+ struct volume_key **vk)
+{
+ struct tcrypt_algs *algs;
+ unsigned int i, key_index;
+
+ if (!hdr->d.version) {
+ log_err(cd, _("This function is not supported without TCRYPT header load."));
+ return -ENOTSUP;
+ }
+
+ algs = TCRYPT_get_algs(params->cipher, params->mode);
+ if (!algs)
+ return -EINVAL;
+
+ *vk = crypt_alloc_volume_key(params->key_size, NULL);
+ if (!*vk)
+ return -ENOMEM;
+
+ for (i = 0, key_index = 0; i < algs->chain_count; i++) {
+ TCRYPT_copy_key(&algs->cipher[i], algs->mode,
+ &(*vk)->key[key_index], hdr->d.keys);
+ key_index += algs->cipher[i].key_size;
+ }
+
+ return 0;
+}
+
+int TCRYPT_dump(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params)
+{
+ log_std(cd, "%s header information for %s\n",
+ hdr->d.magic[0] == 'T' ? "TCRYPT" : "VERACRYPT",
+ device_path(crypt_metadata_device(cd)));
+ if (hdr->d.version) {
+ log_std(cd, "Version: \t%d\n", hdr->d.version);
+ log_std(cd, "Driver req.:\t%x.%x\n", hdr->d.version_tc >> 8,
+ hdr->d.version_tc & 0xFF);
+
+ log_std(cd, "Sector size:\t%" PRIu32 "\n", hdr->d.sector_size);
+ log_std(cd, "MK offset:\t%" PRIu64 "\n", hdr->d.mk_offset);
+ log_std(cd, "PBKDF2 hash:\t%s\n", params->hash_name);
+ }
+ log_std(cd, "Cipher chain:\t%s\n", params->cipher);
+ log_std(cd, "Cipher mode:\t%s\n", params->mode);
+ log_std(cd, "MK bits: \t%zu\n", params->key_size * 8);
+ return 0;
+}
diff --git a/lib/tcrypt/tcrypt.h b/lib/tcrypt/tcrypt.h
new file mode 100644
index 0000000..b95d74d
--- /dev/null
+++ b/lib/tcrypt/tcrypt.h
@@ -0,0 +1,120 @@
+/*
+ * TCRYPT (TrueCrypt-compatible) header definition
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_TCRYPT_H
+#define _CRYPTSETUP_TCRYPT_H
+
+#include <stdint.h>
+
+#define TCRYPT_HDR_SALT_LEN 64
+#define TCRYPT_HDR_IV_LEN 16
+#define TCRYPT_HDR_LEN 448
+#define TCRYPT_HDR_KEY_LEN 192
+#define TCRYPT_HDR_MAGIC "TRUE"
+#define VCRYPT_HDR_MAGIC "VERA"
+#define TCRYPT_HDR_MAGIC_LEN 4
+
+#define TCRYPT_HDR_HIDDEN_OFFSET_OLD -1536
+#define TCRYPT_HDR_HIDDEN_OFFSET 65536
+
+#define TCRYPT_HDR_HIDDEN_OFFSET_BCK -65536
+#define TCRYPT_HDR_OFFSET_BCK -131072
+
+#define TCRYPT_HDR_SYSTEM_OFFSET 31744
+
+#define TCRYPT_LRW_IKEY_LEN 16
+#define TCRYPT_KEY_POOL_LEN 64
+#define VCRYPT_KEY_POOL_LEN 128
+#define TCRYPT_KEYFILE_LEN 1048576
+
+#define TCRYPT_HDR_FLAG_SYSTEM (1 << 0)
+#define TCRYPT_HDR_FLAG_NONSYSTEM (1 << 1)
+
+struct tcrypt_phdr {
+ char salt[TCRYPT_HDR_SALT_LEN];
+
+ /* encrypted part, TCRYPT_HDR_LEN bytes */
+ union {
+ struct __attribute__((__packed__)) {
+ char magic[TCRYPT_HDR_MAGIC_LEN];
+ uint16_t version;
+ uint16_t version_tc;
+ uint32_t keys_crc32;
+ uint64_t _reserved1[2]; /* data/header ctime */
+ uint64_t hidden_volume_size;
+ uint64_t volume_size;
+ uint64_t mk_offset;
+ uint64_t mk_size;
+ uint32_t flags;
+ uint32_t sector_size;
+ uint8_t _reserved2[120];
+ uint32_t header_crc32;
+ char keys[256];
+ } d;
+ char e[TCRYPT_HDR_LEN];
+ };
+} __attribute__((__packed__));
+
+struct crypt_device;
+struct crypt_params_tcrypt;
+struct dm_target;
+struct volume_key;
+struct device;
+
+int TCRYPT_read_phdr(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params);
+
+int TCRYPT_init_by_name(struct crypt_device *cd, const char *name,
+ const char *uuid,
+ const struct dm_target *tgt,
+ struct device **device,
+ struct crypt_params_tcrypt *tcrypt_params,
+ struct tcrypt_phdr *tcrypt_hdr);
+
+int TCRYPT_activate(struct crypt_device *cd,
+ const char *name,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params,
+ uint32_t flags);
+
+int TCRYPT_deactivate(struct crypt_device *cd,
+ const char *name,
+ uint32_t flags);
+
+uint64_t TCRYPT_get_data_offset(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params);
+
+uint64_t TCRYPT_get_iv_offset(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params);
+
+int TCRYPT_get_volume_key(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params,
+ struct volume_key **vk);
+
+int TCRYPT_dump(struct crypt_device *cd,
+ struct tcrypt_phdr *hdr,
+ struct crypt_params_tcrypt *params);
+
+#endif
diff --git a/lib/utils.c b/lib/utils.c
new file mode 100644
index 0000000..bfcf60d
--- /dev/null
+++ b/lib/utils.c
@@ -0,0 +1,334 @@
+/*
+ * utils - miscellaneous device utilities for cryptsetup
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+
+#include "internal.h"
+
+size_t crypt_getpagesize(void)
+{
+ long r = sysconf(_SC_PAGESIZE);
+ return r <= 0 ? DEFAULT_MEM_ALIGNMENT : (size_t)r;
+}
+
+unsigned crypt_cpusonline(void)
+{
+ long r = sysconf(_SC_NPROCESSORS_ONLN);
+ return r < 0 ? 1 : r;
+}
+
+uint64_t crypt_getphysmemory_kb(void)
+{
+ long pagesize, phys_pages;
+ uint64_t phys_memory_kb;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ phys_pages = sysconf(_SC_PHYS_PAGES);
+
+ if (pagesize < 0 || phys_pages < 0)
+ return 0;
+
+ phys_memory_kb = pagesize / 1024;
+ phys_memory_kb *= phys_pages;
+
+ return phys_memory_kb;
+}
+
+void crypt_process_priority(struct crypt_device *cd, int *priority, bool raise)
+{
+ int _priority, new_priority;
+
+ if (raise) {
+ _priority = getpriority(PRIO_PROCESS, 0);
+ if (_priority < 0)
+ _priority = 0;
+ if (priority)
+ *priority = _priority;
+
+ /*
+ * Do not bother checking CAP_SYS_NICE as device activation
+ * requires CAP_SYSADMIN later anyway.
+ */
+ if (getuid() || geteuid())
+ new_priority = 0;
+ else
+ new_priority = -18;
+
+ if (setpriority(PRIO_PROCESS, 0, new_priority))
+ log_dbg(cd, "Cannot raise process priority.");
+ } else {
+ _priority = priority ? *priority : 0;
+ if (setpriority(PRIO_PROCESS, 0, _priority))
+ log_dbg(cd, "Cannot reset process priority.");
+ }
+}
+
+/* Keyfile processing */
+
+/*
+ * A simple call to lseek(3) might not be possible for some inputs (e.g.
+ * reading from a pipe), so this function instead reads of up to BUFSIZ bytes
+ * at a time until the specified number of bytes. It returns -1 on read error
+ * or when it reaches EOF before the requested number of bytes have been
+ * discarded.
+ */
+static int keyfile_seek(int fd, uint64_t bytes)
+{
+ char tmp[BUFSIZ];
+ size_t next_read;
+ ssize_t bytes_r;
+ off_t r;
+
+ r = lseek(fd, bytes, SEEK_CUR);
+ if (r > 0)
+ return 0;
+ if (r < 0 && errno != ESPIPE)
+ return -1;
+
+ while (bytes > 0) {
+ /* figure out how much to read */
+ next_read = bytes > sizeof(tmp) ? sizeof(tmp) : (size_t)bytes;
+
+ bytes_r = read(fd, tmp, next_read);
+ if (bytes_r < 0) {
+ if (errno == EINTR)
+ continue;
+
+ crypt_safe_memzero(tmp, sizeof(tmp));
+ /* read error */
+ return -1;
+ }
+
+ if (bytes_r == 0)
+ /* EOF */
+ break;
+
+ bytes -= bytes_r;
+ }
+
+ crypt_safe_memzero(tmp, sizeof(tmp));
+ return bytes == 0 ? 0 : -1;
+}
+
+int crypt_keyfile_device_read(struct crypt_device *cd, const char *keyfile,
+ char **key, size_t *key_size_read,
+ uint64_t keyfile_offset, size_t key_size,
+ uint32_t flags)
+{
+ int fd, regular_file, char_to_read = 0, char_read = 0, unlimited_read = 0;
+ int r = -EINVAL, newline;
+ char *pass = NULL;
+ size_t buflen, i;
+ uint64_t file_read_size;
+ struct stat st;
+
+ if (!key || !key_size_read)
+ return -EINVAL;
+
+ *key = NULL;
+ *key_size_read = 0;
+
+ fd = keyfile ? open(keyfile, O_RDONLY) : STDIN_FILENO;
+ if (fd < 0) {
+ log_err(cd, _("Failed to open key file."));
+ return -EINVAL;
+ }
+
+ if (isatty(fd)) {
+ log_err(cd, _("Cannot read keyfile from a terminal."));
+ goto out;
+ }
+
+ /* If not requested otherwise, we limit input to prevent memory exhaustion */
+ if (key_size == 0) {
+ key_size = DEFAULT_KEYFILE_SIZE_MAXKB * 1024 + 1;
+ unlimited_read = 1;
+ /* use 4k for buffer (page divisor but avoid huge pages) */
+ buflen = 4096 - 16; /* sizeof(struct safe_allocation); */
+ } else
+ buflen = key_size;
+
+ regular_file = 0;
+ if (keyfile) {
+ if (stat(keyfile, &st) < 0) {
+ log_err(cd, _("Failed to stat key file."));
+ goto out;
+ }
+ if (S_ISREG(st.st_mode)) {
+ regular_file = 1;
+ file_read_size = (uint64_t)st.st_size;
+
+ if (keyfile_offset > file_read_size) {
+ log_err(cd, _("Cannot seek to requested keyfile offset."));
+ goto out;
+ }
+ file_read_size -= keyfile_offset;
+
+ /* known keyfile size, alloc it in one step */
+ if (file_read_size >= (uint64_t)key_size)
+ buflen = key_size;
+ else if (file_read_size)
+ buflen = file_read_size;
+ }
+ }
+
+ pass = crypt_safe_alloc(buflen);
+ if (!pass) {
+ log_err(cd, _("Out of memory while reading passphrase."));
+ goto out;
+ }
+
+ /* Discard keyfile_offset bytes on input */
+ if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
+ log_err(cd, _("Cannot seek to requested keyfile offset."));
+ goto out;
+ }
+
+ for (i = 0, newline = 0; i < key_size; i += char_read) {
+ if (i == buflen) {
+ buflen += 4096;
+ pass = crypt_safe_realloc(pass, buflen);
+ if (!pass) {
+ log_err(cd, _("Out of memory while reading passphrase."));
+ r = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (flags & CRYPT_KEYFILE_STOP_EOL) {
+ /* If we should stop on newline, we must read the input
+ * one character at the time. Otherwise we might end up
+ * having read some bytes after the newline, which we
+ * promised not to do.
+ */
+ char_to_read = 1;
+ } else {
+ /* char_to_read = min(key_size - i, buflen - i) */
+ char_to_read = key_size < buflen ?
+ key_size - i : buflen - i;
+ }
+ char_read = read_buffer(fd, &pass[i], char_to_read);
+ if (char_read < 0) {
+ log_err(cd, _("Error reading passphrase."));
+ r = -EPIPE;
+ goto out;
+ }
+
+ if (char_read == 0)
+ break;
+ /* Stop on newline only if not requested read from keyfile */
+ if ((flags & CRYPT_KEYFILE_STOP_EOL) && pass[i] == '\n') {
+ newline = 1;
+ pass[i] = '\0';
+ break;
+ }
+ }
+
+ /* Fail if piped input dies reading nothing */
+ if (!i && !regular_file && !newline) {
+ log_err(cd, _("Nothing to read on input."));
+ r = -EPIPE;
+ goto out;
+ }
+
+ /* Fail if we exceeded internal default (no specified size) */
+ if (unlimited_read && i == key_size) {
+ log_err(cd, _("Maximum keyfile size exceeded."));
+ goto out;
+ }
+
+ if (!unlimited_read && i != key_size) {
+ log_err(cd, _("Cannot read requested amount of data."));
+ goto out;
+ }
+
+ *key = pass;
+ *key_size_read = i;
+ r = 0;
+out:
+ if (fd != STDIN_FILENO)
+ close(fd);
+
+ if (r)
+ crypt_safe_free(pass);
+ return r;
+}
+
+int crypt_keyfile_read(struct crypt_device *cd, const char *keyfile,
+ char **key, size_t *key_size_read,
+ size_t keyfile_offset, size_t keyfile_size_max,
+ uint32_t flags)
+{
+ return crypt_keyfile_device_read(cd, keyfile, key, key_size_read,
+ keyfile_offset, keyfile_size_max, flags);
+}
+
+int kernel_version(uint64_t *kversion)
+{
+ struct utsname uts;
+ uint16_t maj, min, patch, rel;
+ int r = -EINVAL;
+
+ if (uname(&uts) < 0)
+ return r;
+
+ if (sscanf(uts.release, "%" SCNu16 ".%" SCNu16 ".%" SCNu16 "-%" SCNu16,
+ &maj, &min, &patch, &rel) == 4)
+ r = 0;
+ else if (sscanf(uts.release, "%" SCNu16 ".%" SCNu16 ".%" SCNu16,
+ &maj, &min, &patch) == 3) {
+ rel = 0;
+ r = 0;
+ }
+
+ if (!r)
+ *kversion = compact_version(maj, min, patch, rel);
+
+ return r;
+}
+
+bool crypt_string_in(const char *str, char **list, size_t list_size)
+{
+ size_t i;
+
+ for (i = 0; *list && i < list_size; i++, list++)
+ if (!strcmp(str, *list))
+ return true;
+
+ return false;
+}
+
+/* compare two strings (allows NULL values) */
+int crypt_strcmp(const char *a, const char *b)
+{
+ if (!a && !b)
+ return 0;
+ else if (!a || !b)
+ return 1;
+ return strcmp(a, b);
+}
diff --git a/lib/utils_benchmark.c b/lib/utils_benchmark.c
new file mode 100644
index 0000000..728e4df
--- /dev/null
+++ b/lib/utils_benchmark.c
@@ -0,0 +1,218 @@
+/*
+ * libcryptsetup - cryptsetup library, cipher benchmark
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "internal.h"
+
+int crypt_benchmark(struct crypt_device *cd,
+ const char *cipher,
+ const char *cipher_mode,
+ size_t volume_key_size,
+ size_t iv_size,
+ size_t buffer_size,
+ double *encryption_mbs,
+ double *decryption_mbs)
+{
+ void *buffer = NULL;
+ char *iv = NULL, *key = NULL, mode[MAX_CIPHER_LEN], *c;
+ int r;
+
+ if (!cipher || !cipher_mode || !volume_key_size || !encryption_mbs || !decryption_mbs)
+ return -EINVAL;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ r = -ENOMEM;
+ if (posix_memalign(&buffer, crypt_getpagesize(), buffer_size))
+ goto out;
+ memset(buffer, 0, buffer_size);
+
+ r = crypt_cipher_ivsize(cipher, cipher_mode);
+ if (r >= 0 && iv_size != (size_t)r) {
+ log_dbg(cd, "IV length for benchmark adjusted to %i bytes (requested %zu).", r, iv_size);
+ iv_size = r;
+ }
+
+ if (iv_size) {
+ iv = malloc(iv_size);
+ if (!iv)
+ goto out;
+ crypt_random_get(cd, iv, iv_size, CRYPT_RND_NORMAL);
+ }
+
+ key = malloc(volume_key_size);
+ if (!key)
+ goto out;
+
+ crypt_random_get(cd, key, volume_key_size, CRYPT_RND_NORMAL);
+
+ strncpy(mode, cipher_mode, sizeof(mode)-1);
+ /* Ignore IV generator */
+ if ((c = strchr(mode, '-')))
+ *c = '\0';
+
+ r = crypt_cipher_perf_kernel(cipher, cipher_mode, buffer, buffer_size, key, volume_key_size,
+ iv, iv_size, encryption_mbs, decryption_mbs);
+
+ if (r == -ERANGE)
+ log_dbg(cd, "Measured cipher runtime is too low.");
+ else if (r)
+ log_dbg(cd, "Cannot initialize cipher %s, mode %s, key size %zu, IV size %zu.",
+ cipher, cipher_mode, volume_key_size, iv_size);
+out:
+ free(buffer);
+ free(key);
+ free(iv);
+
+ return r;
+}
+
+int crypt_benchmark_pbkdf(struct crypt_device *cd,
+ struct crypt_pbkdf_type *pbkdf,
+ const char *password,
+ size_t password_size,
+ const char *salt,
+ size_t salt_size,
+ size_t volume_key_size,
+ int (*progress)(uint32_t time_ms, void *usrptr),
+ void *usrptr)
+{
+ int r, priority;
+ const char *kdf_opt;
+
+ if (!pbkdf || (!password && password_size))
+ return -EINVAL;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ kdf_opt = !strcmp(pbkdf->type, CRYPT_KDF_PBKDF2) ? pbkdf->hash : "";
+
+ log_dbg(cd, "Running %s(%s) benchmark.", pbkdf->type, kdf_opt);
+
+ crypt_process_priority(cd, &priority, true);
+ r = crypt_pbkdf_perf(pbkdf->type, pbkdf->hash, password, password_size,
+ salt, salt_size, volume_key_size, pbkdf->time_ms,
+ pbkdf->max_memory_kb, pbkdf->parallel_threads,
+ &pbkdf->iterations, &pbkdf->max_memory_kb, progress, usrptr);
+ crypt_process_priority(cd, &priority, false);
+
+ if (!r)
+ log_dbg(cd, "Benchmark returns %s(%s) %u iterations, %u memory, %u threads (for %zu-bits key).",
+ pbkdf->type, kdf_opt, pbkdf->iterations, pbkdf->max_memory_kb,
+ pbkdf->parallel_threads, volume_key_size * 8);
+ return r;
+}
+
+struct benchmark_usrptr {
+ struct crypt_device *cd;
+ struct crypt_pbkdf_type *pbkdf;
+};
+
+static int benchmark_callback(uint32_t time_ms, void *usrptr)
+{
+ struct benchmark_usrptr *u = usrptr;
+
+ log_dbg(u->cd, "PBKDF benchmark: memory cost = %u, iterations = %u, "
+ "threads = %u (took %u ms)", u->pbkdf->max_memory_kb,
+ u->pbkdf->iterations, u->pbkdf->parallel_threads, time_ms);
+
+ return 0;
+}
+
+/*
+ * Used in internal places to benchmark crypt_device context PBKDF.
+ * Once requested parameters are benchmarked, iterations attribute is set,
+ * and the benchmarked values can be reused.
+ * Note that memory cost can be changed after benchmark (if used).
+ * NOTE: You need to check that you are benchmarking for the same key size.
+ */
+int crypt_benchmark_pbkdf_internal(struct crypt_device *cd,
+ struct crypt_pbkdf_type *pbkdf,
+ size_t volume_key_size)
+{
+ struct crypt_pbkdf_limits pbkdf_limits;
+ double PBKDF2_tmp;
+ uint32_t ms_tmp;
+ int r = -EINVAL;
+ struct benchmark_usrptr u = {
+ .cd = cd,
+ .pbkdf = pbkdf
+ };
+
+ r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
+ if (r)
+ return r;
+
+ if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) {
+ if (pbkdf->iterations) {
+ log_dbg(cd, "Reusing PBKDF values (no benchmark flag is set).");
+ return 0;
+ }
+ log_err(cd, _("PBKDF benchmark disabled but iterations not set."));
+ return -EINVAL;
+ }
+
+ /* For PBKDF2 run benchmark always. Also note it depends on volume_key_size! */
+ if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
+ /*
+ * For PBKDF2 it is enough to run benchmark for only 1 second
+ * and interpolate final iterations value from it.
+ */
+ ms_tmp = pbkdf->time_ms;
+ pbkdf->time_ms = 1000;
+ pbkdf->parallel_threads = 0; /* N/A in PBKDF2 */
+ pbkdf->max_memory_kb = 0; /* N/A in PBKDF2 */
+
+ r = crypt_benchmark_pbkdf(cd, pbkdf, "foobarfo", 8, "01234567890abcdef", 16,
+ volume_key_size, &benchmark_callback, &u);
+ pbkdf->time_ms = ms_tmp;
+ if (r < 0) {
+ log_err(cd, _("Not compatible PBKDF2 options (using hash algorithm %s)."),
+ pbkdf->hash);
+ return r;
+ }
+
+ PBKDF2_tmp = ((double)pbkdf->iterations * pbkdf->time_ms / 1000.);
+ if (PBKDF2_tmp > (double)UINT32_MAX)
+ return -EINVAL;
+ pbkdf->iterations = AT_LEAST((uint32_t)PBKDF2_tmp, pbkdf_limits.min_iterations);
+ } else {
+ /* Already benchmarked */
+ if (pbkdf->iterations) {
+ log_dbg(cd, "Reusing PBKDF values.");
+ return 0;
+ }
+
+ r = crypt_benchmark_pbkdf(cd, pbkdf, "foobarfo", 8,
+ "0123456789abcdef0123456789abcdef", 32,
+ volume_key_size, &benchmark_callback, &u);
+ if (r < 0)
+ log_err(cd, _("Not compatible PBKDF options."));
+ }
+
+ return r;
+}
diff --git a/lib/utils_blkid.c b/lib/utils_blkid.c
new file mode 100644
index 0000000..5a848a1
--- /dev/null
+++ b/lib/utils_blkid.c
@@ -0,0 +1,347 @@
+/*
+ * blkid probe utilities
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "utils_blkid.h"
+#include "utils_io.h"
+
+#ifdef HAVE_BLKID
+#include <blkid/blkid.h>
+/* make bad checksums flag optional */
+#ifndef BLKID_SUBLKS_BADCSUM
+#define BLKID_SUBLKS_BADCSUM 0
+#endif
+struct blkid_handle {
+ int fd;
+ blkid_probe pr;
+};
+#ifndef HAVE_BLKID_WIPE
+static size_t crypt_getpagesize(void)
+{
+ long r = sysconf(_SC_PAGESIZE);
+ return r <= 0 ? 4096 : (size_t)r;
+}
+#endif
+#endif
+
+void blk_set_chains_for_wipes(struct blkid_handle *h)
+{
+#ifdef HAVE_BLKID
+ blkid_probe_enable_partitions(h->pr, 1);
+ blkid_probe_set_partitions_flags(h->pr, 0
+#ifdef HAVE_BLKID_WIPE
+ | BLKID_PARTS_MAGIC
+#endif
+ );
+
+ blkid_probe_enable_superblocks(h->pr, 1);
+ blkid_probe_set_superblocks_flags(h->pr, BLKID_SUBLKS_LABEL |
+ BLKID_SUBLKS_UUID |
+ BLKID_SUBLKS_TYPE |
+ BLKID_SUBLKS_USAGE |
+ BLKID_SUBLKS_VERSION |
+ BLKID_SUBLKS_MAGIC |
+ BLKID_SUBLKS_BADCSUM);
+#endif
+}
+
+void blk_set_chains_for_full_print(struct blkid_handle *h)
+{
+ blk_set_chains_for_wipes(h);
+}
+
+void blk_set_chains_for_superblocks(struct blkid_handle *h)
+{
+#ifdef HAVE_BLKID
+ blkid_probe_enable_superblocks(h->pr, 1);
+ blkid_probe_set_superblocks_flags(h->pr, BLKID_SUBLKS_TYPE);
+#endif
+}
+
+void blk_set_chains_for_fast_detection(struct blkid_handle *h)
+{
+#ifdef HAVE_BLKID
+ blkid_probe_enable_partitions(h->pr, 1);
+ blkid_probe_set_partitions_flags(h->pr, 0);
+ blk_set_chains_for_superblocks(h);
+#endif
+}
+
+int blk_init_by_path(struct blkid_handle **h, const char *path)
+{
+ int r = -ENOTSUP;
+#ifdef HAVE_BLKID
+ struct blkid_handle *tmp = malloc(sizeof(*tmp));
+ if (!tmp)
+ return -ENOMEM;
+
+ tmp->fd = -1;
+
+ tmp->pr = blkid_new_probe_from_filename(path);
+ if (!tmp->pr) {
+ free(tmp);
+ return -EINVAL;
+ }
+
+ *h = tmp;
+
+ r = 0;
+#endif
+ return r;
+}
+
+int blk_init_by_fd(struct blkid_handle **h, int fd)
+{
+ int r = -ENOTSUP;
+#ifdef HAVE_BLKID
+ struct blkid_handle *tmp = malloc(sizeof(*tmp));
+ if (!tmp)
+ return -ENOMEM;
+
+ tmp->pr = blkid_new_probe();
+ if (!tmp->pr) {
+ free(tmp);
+ return -EINVAL;
+ }
+
+ if (blkid_probe_set_device(tmp->pr, fd, 0, 0)) {
+ blkid_free_probe(tmp->pr);
+ free(tmp);
+ return -EINVAL;
+ }
+
+ tmp->fd = fd;
+
+ *h = tmp;
+
+ r = 0;
+#endif
+ return r;
+}
+
+#ifdef HAVE_BLKID
+static int blk_superblocks_luks(struct blkid_handle *h, bool enable)
+{
+ char luks[] = "crypto_LUKS";
+ char *luks_filter[] = {
+ luks,
+ NULL
+ };
+ return blkid_probe_filter_superblocks_type(h->pr,
+ enable ? BLKID_FLTR_ONLYIN : BLKID_FLTR_NOTIN,
+ luks_filter);
+}
+#endif
+
+int blk_superblocks_filter_luks(struct blkid_handle *h)
+{
+ int r = -ENOTSUP;
+#ifdef HAVE_BLKID
+ r = blk_superblocks_luks(h, false);
+#endif
+ return r;
+}
+
+int blk_superblocks_only_luks(struct blkid_handle *h)
+{
+ int r = -ENOTSUP;
+#ifdef HAVE_BLKID
+ r = blk_superblocks_luks(h, true);
+#endif
+ return r;
+}
+
+blk_probe_status blk_probe(struct blkid_handle *h)
+{
+ blk_probe_status pr = PRB_FAIL;
+#ifdef HAVE_BLKID
+ int r = blkid_do_probe(h->pr);
+
+ if (r == 0)
+ pr = PRB_OK;
+ else if (r == 1)
+ pr = PRB_EMPTY;
+#endif
+ return pr;
+}
+
+blk_probe_status blk_safeprobe(struct blkid_handle *h)
+{
+ int r = -1;
+#ifdef HAVE_BLKID
+ r = blkid_do_safeprobe(h->pr);
+#endif
+ switch (r) {
+ case -2:
+ return PRB_AMBIGUOUS;
+ case 1:
+ return PRB_EMPTY;
+ case 0:
+ return PRB_OK;
+ default:
+ return PRB_FAIL;
+ }
+}
+
+int blk_is_partition(struct blkid_handle *h)
+{
+ int r = 0;
+#ifdef HAVE_BLKID
+ r = blkid_probe_has_value(h->pr, "PTTYPE");
+#endif
+ return r;
+}
+
+int blk_is_superblock(struct blkid_handle *h)
+{
+ int r = 0;
+#ifdef HAVE_BLKID
+ r = blkid_probe_has_value(h->pr, "TYPE");
+#endif
+ return r;
+}
+
+const char *blk_get_partition_type(struct blkid_handle *h)
+{
+ const char *value = NULL;
+#ifdef HAVE_BLKID
+ (void) blkid_probe_lookup_value(h->pr, "PTTYPE", &value, NULL);
+#endif
+ return value;
+}
+
+const char *blk_get_superblock_type(struct blkid_handle *h)
+{
+ const char *value = NULL;
+#ifdef HAVE_BLKID
+ (void) blkid_probe_lookup_value(h->pr, "TYPE", &value, NULL);
+#endif
+ return value;
+}
+
+void blk_free(struct blkid_handle *h)
+{
+#ifdef HAVE_BLKID
+ if (!h)
+ return;
+
+ if (h->pr)
+ blkid_free_probe(h->pr);
+
+ free(h);
+#endif
+}
+
+#ifdef HAVE_BLKID
+#ifndef HAVE_BLKID_WIPE
+static int blk_step_back(struct blkid_handle *h)
+{
+#ifdef HAVE_BLKID_STEP_BACK
+ return blkid_probe_step_back(h->pr);
+#else
+ blkid_reset_probe(h->pr);
+ blkid_probe_set_device(h->pr, h->fd, 0, 0);
+ return 0;
+#endif
+}
+#endif /* not HAVE_BLKID_WIPE */
+#endif /* HAVE_BLKID */
+
+int blk_do_wipe(struct blkid_handle *h)
+{
+#ifdef HAVE_BLKID
+#ifdef HAVE_BLKID_WIPE
+ return blkid_do_wipe(h->pr, 0);
+#else
+ const char *offset;
+ off_t offset_val;
+ void *buf;
+ ssize_t ret;
+ size_t alignment, len, bsize = blkid_probe_get_sectorsize(h->pr);
+
+ if (h->fd < 0 || !bsize)
+ return -EINVAL;
+
+ if (blk_is_partition(h)) {
+ if (blkid_probe_lookup_value(h->pr, "PTMAGIC_OFFSET", &offset, NULL))
+ return -EINVAL;
+ if (blkid_probe_lookup_value(h->pr, "PTMAGIC", NULL, &len))
+ return -EINVAL;
+ } else if (blk_is_superblock(h)) {
+ if (blkid_probe_lookup_value(h->pr, "SBMAGIC_OFFSET", &offset, NULL))
+ return -EINVAL;
+ if (blkid_probe_lookup_value(h->pr, "SBMAGIC", NULL, &len))
+ return -EINVAL;
+ } else
+ return 0;
+
+ alignment = crypt_getpagesize();
+
+ if (posix_memalign(&buf, alignment, len))
+ return -EINVAL;
+ memset(buf, 0, len);
+
+ offset_val = strtoll(offset, NULL, 10);
+
+ /* TODO: missing crypt_wipe_fd() */
+ ret = write_lseek_blockwise(h->fd, bsize, alignment, buf, len, offset_val);
+ free(buf);
+ if (ret < 0)
+ return -EIO;
+
+ if ((size_t)ret == len) {
+ blk_step_back(h);
+ return 0;
+ }
+
+ return -EIO;
+#endif
+#else /* HAVE_BLKID */
+ return -ENOTSUP;
+#endif
+}
+
+int blk_supported(void)
+{
+ int r = 0;
+#ifdef HAVE_BLKID
+ r = 1;
+#endif
+ return r;
+}
+
+unsigned blk_get_block_size(struct blkid_handle *h)
+{
+ unsigned block_size = 0;
+#ifdef HAVE_BLKID
+ const char *data;
+ if (!blk_is_superblock(h) || !blkid_probe_has_value(h->pr, "BLOCK_SIZE") ||
+ blkid_probe_lookup_value(h->pr, "BLOCK_SIZE", &data, NULL) ||
+ sscanf(data, "%u", &block_size) != 1)
+ block_size = 0;
+#endif
+ return block_size;
+}
diff --git a/lib/utils_blkid.h b/lib/utils_blkid.h
new file mode 100644
index 0000000..3ee1434
--- /dev/null
+++ b/lib/utils_blkid.h
@@ -0,0 +1,69 @@
+/*
+ * blkid probe utilities
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _UTILS_BLKID_H
+#define _UTILS_BLKID_H
+
+#include <sys/types.h>
+
+struct blkid_handle;
+
+typedef enum { PRB_OK = 0, PRB_EMPTY, PRB_AMBIGUOUS, PRB_FAIL } blk_probe_status;
+
+int blk_init_by_path(struct blkid_handle **h, const char *path);
+
+void blk_free(struct blkid_handle *h);
+
+/*
+ * WARNING: This will reset file description offset as if
+ * lseek(devfd, 0, SEEK_SET) was called!
+ */
+int blk_init_by_fd(struct blkid_handle **h, int fd);
+
+void blk_set_chains_for_wipes(struct blkid_handle *h);
+
+void blk_set_chains_for_full_print(struct blkid_handle *h);
+
+void blk_set_chains_for_superblocks(struct blkid_handle *h);
+
+void blk_set_chains_for_fast_detection(struct blkid_handle *h);
+
+int blk_superblocks_filter_luks(struct blkid_handle *h);
+int blk_superblocks_only_luks(struct blkid_handle *h);
+
+blk_probe_status blk_safeprobe(struct blkid_handle *h);
+
+blk_probe_status blk_probe(struct blkid_handle *h);
+
+int blk_is_partition(struct blkid_handle *h);
+
+int blk_is_superblock(struct blkid_handle *h);
+
+const char *blk_get_partition_type(struct blkid_handle *h);
+
+const char *blk_get_superblock_type(struct blkid_handle *h);
+
+int blk_do_wipe(struct blkid_handle *h);
+
+int blk_supported(void);
+
+unsigned blk_get_block_size(struct blkid_handle *h);
+
+#endif
diff --git a/lib/utils_crypt.c b/lib/utils_crypt.c
new file mode 100644
index 0000000..0b7dc37
--- /dev/null
+++ b/lib/utils_crypt.c
@@ -0,0 +1,347 @@
+/*
+ * utils_crypt - cipher utilities for cryptsetup
+ *
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "libcryptsetup.h"
+#include "utils_crypt.h"
+
+#define MAX_CAPI_LEN_STR "143" /* for sscanf of crypto API string + 16 + \0 */
+
+int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums,
+ char *cipher_mode)
+{
+ if (!s || !cipher || !cipher_mode)
+ return -EINVAL;
+
+ if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s",
+ cipher, cipher_mode) == 2) {
+ if (!strcmp(cipher_mode, "plain"))
+ strcpy(cipher_mode, "cbc-plain");
+ if (key_nums) {
+ char *tmp = strchr(cipher, ':');
+ *key_nums = tmp ? atoi(++tmp) : 1;
+ if (!*key_nums)
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ /* Short version for "empty" cipher */
+ if (!strcmp(s, "null") || !strcmp(s, "cipher_null")) {
+ strcpy(cipher, "cipher_null");
+ strcpy(cipher_mode, "ecb");
+ if (key_nums)
+ *key_nums = 0;
+ return 0;
+ }
+
+ if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]", cipher) == 1) {
+ strcpy(cipher_mode, "cbc-plain");
+ if (key_nums)
+ *key_nums = 1;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int crypt_parse_hash_integrity_mode(const char *s, char *integrity)
+{
+ char mode[MAX_CIPHER_LEN], hash[MAX_CIPHER_LEN];
+ int r;
+
+ if (!s || !integrity || strchr(s, '(') || strchr(s, ')'))
+ return -EINVAL;
+
+ r = sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s", mode, hash);
+ if (r == 2 && !isdigit(hash[0]))
+ r = snprintf(integrity, MAX_CIPHER_LEN, "%s(%s)", mode, hash);
+ else if (r == 2)
+ r = snprintf(integrity, MAX_CIPHER_LEN, "%s-%s", mode, hash);
+ else if (r == 1)
+ r = snprintf(integrity, MAX_CIPHER_LEN, "%s", mode);
+ else
+ return -EINVAL;
+
+ if (r < 0 || r >= MAX_CIPHER_LEN)
+ return -EINVAL;
+
+ return 0;
+}
+
+int crypt_parse_integrity_mode(const char *s, char *integrity,
+ int *integrity_key_size)
+{
+ int ks = 0, r = 0;
+
+ if (!s || !integrity)
+ return -EINVAL;
+
+ /* AEAD modes */
+ if (!strcmp(s, "aead") ||
+ !strcmp(s, "poly1305") ||
+ !strcmp(s, "none")) {
+ strncpy(integrity, s, MAX_CIPHER_LEN);
+ ks = 0;
+ } else if (!strcmp(s, "hmac-sha1")) {
+ strncpy(integrity, "hmac(sha1)", MAX_CIPHER_LEN);
+ ks = 20;
+ } else if (!strcmp(s, "hmac-sha256")) {
+ strncpy(integrity, "hmac(sha256)", MAX_CIPHER_LEN);
+ ks = 32;
+ } else if (!strcmp(s, "hmac-sha512")) {
+ ks = 64;
+ strncpy(integrity, "hmac(sha512)", MAX_CIPHER_LEN);
+ } else if (!strcmp(s, "cmac-aes")) {
+ ks = 16;
+ strncpy(integrity, "cmac(aes)", MAX_CIPHER_LEN);
+ } else
+ r = -EINVAL;
+
+ if (integrity_key_size)
+ *integrity_key_size = ks;
+
+ return r;
+}
+
+int crypt_parse_pbkdf(const char *s, const char **pbkdf)
+{
+ const char *tmp = NULL;
+
+ if (!s)
+ return -EINVAL;
+
+ if (!strcasecmp(s, CRYPT_KDF_PBKDF2))
+ tmp = CRYPT_KDF_PBKDF2;
+ else if (!strcasecmp(s, CRYPT_KDF_ARGON2I))
+ tmp = CRYPT_KDF_ARGON2I;
+ else if (!strcasecmp(s, CRYPT_KDF_ARGON2ID))
+ tmp = CRYPT_KDF_ARGON2ID;
+
+ if (!tmp)
+ return -EINVAL;
+
+ if (pbkdf)
+ *pbkdf = tmp;
+
+ return 0;
+}
+
+/*
+ * Thanks Mikulas Patocka for these two char converting functions.
+ *
+ * This function is used to load cryptographic keys, so it is coded in such a
+ * way that there are no conditions or memory accesses that depend on data.
+ *
+ * Explanation of the logic:
+ * (ch - '9' - 1) is negative if ch <= '9'
+ * ('0' - 1 - ch) is negative if ch >= '0'
+ * we "and" these two values, so the result is negative if ch is in the range
+ * '0' ... '9'
+ * we are only interested in the sign, so we do a shift ">> 8"; note that right
+ * shift of a negative value is implementation-defined, so we cast the
+ * value to (unsigned) before the shift --- we have 0xffffff if ch is in
+ * the range '0' ... '9', 0 otherwise
+ * we "and" this value with (ch - '0' + 1) --- we have a value 1 ... 10 if ch is
+ * in the range '0' ... '9', 0 otherwise
+ * we add this value to -1 --- we have a value 0 ... 9 if ch is in the range '0'
+ * ... '9', -1 otherwise
+ * the next line is similar to the previous one, but we need to decode both
+ * uppercase and lowercase letters, so we use (ch & 0xdf), which converts
+ * lowercase to uppercase
+ */
+static int hex_to_bin(unsigned char ch)
+{
+ unsigned char cu = ch & 0xdf;
+ return -1 +
+ ((ch - '0' + 1) & (unsigned)((ch - '9' - 1) & ('0' - 1 - ch)) >> 8) +
+ ((cu - 'A' + 11) & (unsigned)((cu - 'F' - 1) & ('A' - 1 - cu)) >> 8);
+}
+
+static char hex2asc(unsigned char c)
+{
+ return c + '0' + ((unsigned)(9 - c) >> 4 & 0x27);
+}
+
+ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc)
+{
+ char *bytes;
+ size_t i, len;
+ int bl, bh;
+
+ if (!hex || !result)
+ return -EINVAL;
+
+ len = strlen(hex);
+ if (len % 2)
+ return -EINVAL;
+ len /= 2;
+
+ bytes = safe_alloc ? crypt_safe_alloc(len) : malloc(len);
+ if (!bytes)
+ return -ENOMEM;
+
+ for (i = 0; i < len; i++) {
+ bh = hex_to_bin(hex[i * 2]);
+ bl = hex_to_bin(hex[i * 2 + 1]);
+ if (bh == -1 || bl == -1) {
+ safe_alloc ? crypt_safe_free(bytes) : free(bytes);
+ return -EINVAL;
+ }
+ bytes[i] = (bh << 4) | bl;
+ }
+ *result = bytes;
+ return i;
+}
+
+char *crypt_bytes_to_hex(size_t size, const char *bytes)
+{
+ unsigned i;
+ char *hex;
+
+ if (size && !bytes)
+ return NULL;
+
+ /* Alloc adds trailing \0 */
+ if (size == 0)
+ hex = crypt_safe_alloc(2);
+ else
+ hex = crypt_safe_alloc(size * 2 + 1);
+ if (!hex)
+ return NULL;
+
+ if (size == 0)
+ hex[0] = '-';
+ else for (i = 0; i < size; i++) {
+ hex[i * 2] = hex2asc((const unsigned char)bytes[i] >> 4);
+ hex[i * 2 + 1] = hex2asc((const unsigned char)bytes[i] & 0xf);
+ }
+
+ return hex;
+}
+
+void crypt_log_hex(struct crypt_device *cd,
+ const char *bytes, size_t size,
+ const char *sep, int numwrap, const char *wrapsep)
+{
+ unsigned i;
+
+ for (i = 0; i < size; i++) {
+ if (wrapsep && numwrap && i && !(i % numwrap))
+ crypt_logf(cd, CRYPT_LOG_NORMAL, wrapsep);
+ crypt_logf(cd, CRYPT_LOG_NORMAL, "%c%c%s",
+ hex2asc((const unsigned char)bytes[i] >> 4),
+ hex2asc((const unsigned char)bytes[i] & 0xf), sep);
+ }
+}
+
+bool crypt_is_cipher_null(const char *cipher_spec)
+{
+ if (!cipher_spec)
+ return false;
+ return (strstr(cipher_spec, "cipher_null") || !strcmp(cipher_spec, "null"));
+}
+
+int crypt_capi_to_cipher(char **org_c, char **org_i, const char *c_dm, const char *i_dm)
+{
+ char cipher[MAX_CAPI_ONE_LEN], mode[MAX_CAPI_ONE_LEN], iv[MAX_CAPI_ONE_LEN],
+ auth[MAX_CAPI_ONE_LEN], tmp[MAX_CAPI_LEN], dmcrypt_tmp[MAX_CAPI_LEN*2],
+ capi[MAX_CAPI_LEN+1];
+ size_t len;
+ int i;
+
+ if (!c_dm)
+ return -EINVAL;
+
+ /* legacy mode */
+ if (strncmp(c_dm, "capi:", 4)) {
+ if (!(*org_c = strdup(c_dm)))
+ return -ENOMEM;
+ if (i_dm) {
+ if (!(*org_i = strdup(i_dm))) {
+ free(*org_c);
+ *org_c = NULL;
+ return -ENOMEM;
+ }
+ } else
+ *org_i = NULL;
+ return 0;
+ }
+
+ /* modes with capi: prefix */
+ i = sscanf(c_dm, "capi:%" MAX_CAPI_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", tmp, iv);
+ if (i != 2)
+ return -EINVAL;
+
+ len = strlen(tmp);
+ if (len < 2)
+ return -EINVAL;
+
+ if (tmp[len-1] == ')')
+ tmp[len-1] = '\0';
+
+ if (sscanf(tmp, "rfc4309(%" MAX_CAPI_LEN_STR "s", capi) == 1) {
+ if (!(*org_i = strdup("aead")))
+ return -ENOMEM;
+ } else if (sscanf(tmp, "rfc7539(%" MAX_CAPI_LEN_STR "[^,],%" MAX_CAPI_ONE_LEN_STR "s", capi, auth) == 2) {
+ if (!(*org_i = strdup(auth)))
+ return -ENOMEM;
+ } else if (sscanf(tmp, "authenc(%" MAX_CAPI_ONE_LEN_STR "[^,],%" MAX_CAPI_LEN_STR "s", auth, capi) == 2) {
+ if (!(*org_i = strdup(auth)))
+ return -ENOMEM;
+ } else {
+ if (i_dm) {
+ if (!(*org_i = strdup(i_dm)))
+ return -ENOMEM;
+ } else
+ *org_i = NULL;
+ memset(capi, 0, sizeof(capi));
+ strncpy(capi, tmp, sizeof(capi)-1);
+ }
+
+ i = sscanf(capi, "%" MAX_CAPI_ONE_LEN_STR "[^(](%" MAX_CAPI_ONE_LEN_STR "[^)])", mode, cipher);
+ if (i == 2)
+ i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv);
+ else
+ i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv);
+ if (i < 0 || (size_t)i >= sizeof(dmcrypt_tmp)) {
+ free(*org_i);
+ *org_i = NULL;
+ return -EINVAL;
+ }
+
+ if (!(*org_c = strdup(dmcrypt_tmp))) {
+ free(*org_i);
+ *org_i = NULL;
+ return -ENOMEM;
+ }
+
+ return 0;
+}
diff --git a/lib/utils_crypt.h b/lib/utils_crypt.h
new file mode 100644
index 0000000..92e0705
--- /dev/null
+++ b/lib/utils_crypt.h
@@ -0,0 +1,54 @@
+/*
+ * utils_crypt - cipher utilities for cryptsetup
+ *
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _UTILS_CRYPT_H
+#define _UTILS_CRYPT_H
+
+#include <stdbool.h>
+
+struct crypt_device;
+
+#define MAX_CIPHER_LEN 32
+#define MAX_CIPHER_LEN_STR "31"
+#define MAX_KEYFILES 32
+#define MAX_CAPI_ONE_LEN 2 * MAX_CIPHER_LEN
+#define MAX_CAPI_ONE_LEN_STR "63" /* for sscanf length + '\0' */
+#define MAX_CAPI_LEN 144 /* should be enough to fit whole capi string */
+
+int crypt_parse_name_and_mode(const char *s, char *cipher,
+ int *key_nums, char *cipher_mode);
+int crypt_parse_hash_integrity_mode(const char *s, char *integrity);
+int crypt_parse_integrity_mode(const char *s, char *integrity,
+ int *integrity_key_size);
+int crypt_parse_pbkdf(const char *s, const char **pbkdf);
+
+ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);
+char *crypt_bytes_to_hex(size_t size, const char *bytes);
+void crypt_log_hex(struct crypt_device *cd,
+ const char *bytes, size_t size,
+ const char *sep, int numwrap, const char *wrapsep);
+
+bool crypt_is_cipher_null(const char *cipher_spec);
+
+int crypt_capi_to_cipher(char **org_c, char **org_i, const char *c_dm, const char *i_dm);
+
+#endif /* _UTILS_CRYPT_H */
diff --git a/lib/utils_device.c b/lib/utils_device.c
new file mode 100644
index 0000000..d80ea62
--- /dev/null
+++ b/lib/utils_device.c
@@ -0,0 +1,1089 @@
+/*
+ * device backend utilities
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+#include "internal.h"
+#include "utils_device_locking.h"
+
+struct device {
+ char *path;
+
+ char *file_path;
+ int loop_fd;
+
+ int ro_dev_fd;
+ int dev_fd;
+ int dev_fd_excl;
+
+ struct crypt_lock_handle *lh;
+
+ unsigned int o_direct:1;
+ unsigned int init_done:1; /* path is bdev or loop already initialized */
+
+ /* cached values */
+ size_t alignment;
+ size_t block_size;
+ size_t loop_block_size;
+};
+
+static size_t device_fs_block_size_fd(int fd)
+{
+ size_t page_size = crypt_getpagesize();
+
+#ifdef HAVE_SYS_STATVFS_H
+ struct statvfs buf;
+
+ /*
+ * NOTE: some filesystems (NFS) returns bogus blocksize (1MB).
+ * Page-size io should always work and avoids increasing IO beyond aligned LUKS header.
+ */
+ if (!fstatvfs(fd, &buf) && buf.f_bsize && buf.f_bsize <= page_size)
+ return (size_t)buf.f_bsize;
+#endif
+ return page_size;
+}
+
+static size_t device_block_size_fd(int fd, size_t *min_size)
+{
+ struct stat st;
+ size_t bsize;
+ int arg;
+
+ if (fstat(fd, &st) < 0)
+ return 0;
+
+ if (S_ISREG(st.st_mode))
+ bsize = device_fs_block_size_fd(fd);
+ else {
+ if (ioctl(fd, BLKSSZGET, &arg) < 0)
+ bsize = crypt_getpagesize();
+ else
+ bsize = (size_t)arg;
+ }
+
+ if (!min_size)
+ return bsize;
+
+ if (S_ISREG(st.st_mode)) {
+ /* file can be empty as well */
+ if (st.st_size > (ssize_t)bsize)
+ *min_size = bsize;
+ else
+ *min_size = st.st_size;
+ } else {
+ /* block device must have at least one block */
+ *min_size = bsize;
+ }
+
+ return bsize;
+}
+
+static size_t device_block_phys_size_fd(int fd)
+{
+ struct stat st;
+ int arg;
+ size_t bsize = SECTOR_SIZE;
+
+ if (fstat(fd, &st) < 0)
+ return bsize;
+
+ if (S_ISREG(st.st_mode))
+ bsize = MAX_SECTOR_SIZE;
+ else if (ioctl(fd, BLKPBSZGET, &arg) >= 0)
+ bsize = (size_t)arg;
+
+ return bsize;
+}
+
+static size_t device_alignment_fd(int devfd)
+{
+ long alignment = DEFAULT_MEM_ALIGNMENT;
+
+#ifdef _PC_REC_XFER_ALIGN
+ alignment = fpathconf(devfd, _PC_REC_XFER_ALIGN);
+ if (alignment < 0)
+ alignment = DEFAULT_MEM_ALIGNMENT;
+#endif
+ return (size_t)alignment;
+}
+
+static int device_read_test(int devfd)
+{
+ char buffer[512];
+ int r = -EIO;
+ size_t minsize = 0, blocksize, alignment;
+
+ blocksize = device_block_size_fd(devfd, &minsize);
+ alignment = device_alignment_fd(devfd);
+
+ if (!blocksize || !alignment)
+ return -EINVAL;
+
+ if (minsize == 0)
+ return 0;
+
+ if (minsize > sizeof(buffer))
+ minsize = sizeof(buffer);
+
+ if (read_blockwise(devfd, blocksize, alignment, buffer, minsize) == (ssize_t)minsize)
+ r = 0;
+
+ crypt_safe_memzero(buffer, sizeof(buffer));
+ return r;
+}
+
+/*
+ * The direct-io is always preferred. The header is usually mapped to the same
+ * device and can be accessed when the rest of device is mapped to data device.
+ * Using direct-io ensures that we do not mess with data in cache.
+ * (But proper alignment should prevent this in the first place.)
+ * The read test is needed to detect broken configurations (seen with remote
+ * block devices) that allow open with direct-io but then fails on read.
+ */
+static int device_ready(struct crypt_device *cd, struct device *device)
+{
+ int devfd = -1, r = 0;
+ struct stat st;
+ size_t tmp_size;
+
+ if (!device)
+ return -EINVAL;
+
+ if (device->o_direct) {
+ log_dbg(cd, "Trying to open and read device %s with direct-io.",
+ device_path(device));
+ device->o_direct = 0;
+ devfd = open(device_path(device), O_RDONLY | O_DIRECT);
+ if (devfd >= 0) {
+ if (device_read_test(devfd) == 0) {
+ device->o_direct = 1;
+ } else {
+ close(devfd);
+ devfd = -1;
+ }
+ }
+ }
+
+ if (devfd < 0) {
+ log_dbg(cd, "Trying to open device %s without direct-io.",
+ device_path(device));
+ devfd = open(device_path(device), O_RDONLY);
+ }
+
+ if (devfd < 0) {
+ log_err(cd, _("Device %s does not exist or access denied."),
+ device_path(device));
+ return -EINVAL;
+ }
+
+ if (fstat(devfd, &st) < 0)
+ r = -EINVAL;
+ else if (!S_ISBLK(st.st_mode))
+ r = S_ISREG(st.st_mode) ? -ENOTBLK : -EINVAL;
+ if (r == -EINVAL) {
+ log_err(cd, _("Device %s is not compatible."),
+ device_path(device));
+ close(devfd);
+ return r;
+ }
+
+ /* Allow only increase (loop device) */
+ tmp_size = device_alignment_fd(devfd);
+ if (tmp_size > device->alignment)
+ device->alignment = tmp_size;
+
+ tmp_size = device_block_size_fd(devfd, NULL);
+ if (tmp_size > device->block_size)
+ device->block_size = tmp_size;
+
+ close(devfd);
+ return r;
+}
+
+static int _open_locked(struct crypt_device *cd, struct device *device, int flags)
+{
+ int fd;
+
+ if (!device)
+ return -EINVAL;
+
+ log_dbg(cd, "Opening locked device %s", device_path(device));
+
+ if ((flags & O_ACCMODE) != O_RDONLY && device_locked_readonly(device->lh)) {
+ log_dbg(cd, "Cannot open locked device %s in write mode. Read lock held.", device_path(device));
+ return -EAGAIN;
+ }
+
+ fd = open(device_path(device), flags);
+ if (fd < 0)
+ return -errno;
+
+ if (device_locked_verify(cd, fd, device->lh)) {
+ /* fd doesn't correspond to a locked resource */
+ close(fd);
+ log_dbg(cd, "Failed to verify lock resource for device %s.", device_path(device));
+ return -EINVAL;
+ }
+
+ return fd;
+}
+
+/*
+ * Common wrapper for device sync.
+ */
+void device_sync(struct crypt_device *cd, struct device *device)
+{
+ if (!device || device->dev_fd < 0)
+ return;
+
+ if (fsync(device->dev_fd) == -1)
+ log_dbg(cd, "Cannot sync device %s.", device_path(device));
+}
+
+/*
+ * in non-locked mode returns always fd or -1
+ *
+ * in locked mode:
+ * opened fd or one of:
+ * -EAGAIN : requested write mode while device being locked in via shared lock
+ * -EINVAL : invalid lock fd state
+ * -1 : all other errors
+ */
+static int device_open_internal(struct crypt_device *cd, struct device *device, int flags)
+{
+ int access, devfd;
+
+ if (device->o_direct)
+ flags |= O_DIRECT;
+
+ access = flags & O_ACCMODE;
+ if (access == O_WRONLY)
+ access = O_RDWR;
+
+ if (access == O_RDONLY && device->ro_dev_fd >= 0) {
+ log_dbg(cd, "Reusing open r%c fd on device %s", 'o', device_path(device));
+ return device->ro_dev_fd;
+ } else if (access == O_RDWR && device->dev_fd >= 0) {
+ log_dbg(cd, "Reusing open r%c fd on device %s", 'w', device_path(device));
+ return device->dev_fd;
+ }
+
+ if (device_locked(device->lh))
+ devfd = _open_locked(cd, device, flags);
+ else
+ devfd = open(device_path(device), flags);
+
+ if (devfd < 0) {
+ log_dbg(cd, "Cannot open device %s%s.",
+ device_path(device),
+ access != O_RDONLY ? " for write" : "");
+ return devfd;
+ }
+
+ if (access == O_RDONLY)
+ device->ro_dev_fd = devfd;
+ else
+ device->dev_fd = devfd;
+
+ return devfd;
+}
+
+int device_open(struct crypt_device *cd, struct device *device, int flags)
+{
+ if (!device)
+ return -EINVAL;
+
+ assert(!device_locked(device->lh));
+ return device_open_internal(cd, device, flags);
+}
+
+int device_open_excl(struct crypt_device *cd, struct device *device, int flags)
+{
+ const char *path;
+ struct stat st;
+
+ if (!device)
+ return -EINVAL;
+
+ assert(!device_locked(device->lh));
+
+ if (device->dev_fd_excl < 0) {
+ path = device_path(device);
+ if (stat(path, &st))
+ return -EINVAL;
+ if (!S_ISBLK(st.st_mode))
+ log_dbg(cd, "%s is not a block device. Can't open in exclusive mode.",
+ path);
+ else {
+ /* open(2) with O_EXCL (w/o O_CREAT) on regular file is undefined behaviour according to man page */
+ /* coverity[toctou] */
+ device->dev_fd_excl = open(path, O_RDONLY | O_EXCL); /* lgtm[cpp/toctou-race-condition] */
+ if (device->dev_fd_excl < 0)
+ return errno == EBUSY ? -EBUSY : device->dev_fd_excl;
+ if (fstat(device->dev_fd_excl, &st) || !S_ISBLK(st.st_mode)) {
+ log_dbg(cd, "%s is not a block device. Can't open in exclusive mode.",
+ path);
+ close(device->dev_fd_excl);
+ device->dev_fd_excl = -1;
+ } else
+ log_dbg(cd, "Device %s is blocked for exclusive open.", path);
+ }
+ }
+
+ return device_open_internal(cd, device, flags);
+}
+
+void device_release_excl(struct crypt_device *cd, struct device *device)
+{
+ if (device && device->dev_fd_excl >= 0) {
+ if (close(device->dev_fd_excl))
+ log_dbg(cd, "Failed to release exclusive handle on device %s.",
+ device_path(device));
+ else
+ log_dbg(cd, "Closed exclusive fd for %s.", device_path(device));
+ device->dev_fd_excl = -1;
+ }
+}
+
+int device_open_locked(struct crypt_device *cd, struct device *device, int flags)
+{
+ if (!device)
+ return -EINVAL;
+
+ assert(!crypt_metadata_locking_enabled() || device_locked(device->lh));
+ return device_open_internal(cd, device, flags);
+}
+
+/* Avoid any read from device, expects direct-io to work. */
+int device_alloc_no_check(struct device **device, const char *path)
+{
+ struct device *dev;
+
+ if (!path) {
+ *device = NULL;
+ return 0;
+ }
+
+ dev = malloc(sizeof(struct device));
+ if (!dev)
+ return -ENOMEM;
+
+ memset(dev, 0, sizeof(struct device));
+ dev->path = strdup(path);
+ if (!dev->path) {
+ free(dev);
+ return -ENOMEM;
+ }
+ dev->loop_fd = -1;
+ dev->ro_dev_fd = -1;
+ dev->dev_fd = -1;
+ dev->dev_fd_excl = -1;
+ dev->o_direct = 1;
+
+ *device = dev;
+ return 0;
+}
+
+int device_alloc(struct crypt_device *cd, struct device **device, const char *path)
+{
+ struct device *dev;
+ int r;
+
+ r = device_alloc_no_check(&dev, path);
+ if (r < 0)
+ return r;
+
+ if (dev) {
+ r = device_ready(cd, dev);
+ if (!r) {
+ dev->init_done = 1;
+ } else if (r == -ENOTBLK) {
+ /* alloc loop later */
+ } else if (r < 0) {
+ free(dev->path);
+ free(dev);
+ return -ENOTBLK;
+ }
+ }
+
+ *device = dev;
+ return 0;
+}
+
+void device_free(struct crypt_device *cd, struct device *device)
+{
+ if (!device)
+ return;
+
+ device_close(cd, device);
+
+ if (device->dev_fd_excl != -1) {
+ log_dbg(cd, "Closed exclusive fd for %s.", device_path(device));
+ close(device->dev_fd_excl);
+ }
+
+ if (device->loop_fd != -1) {
+ log_dbg(cd, "Closed loop %s (%s).", device->path, device->file_path);
+ close(device->loop_fd);
+ }
+
+ assert(!device_locked(device->lh));
+
+ free(device->file_path);
+ free(device->path);
+ free(device);
+}
+
+/* Get block device path */
+const char *device_block_path(const struct device *device)
+{
+ if (!device || !device->init_done)
+ return NULL;
+
+ return device->path;
+}
+
+/* Get device-mapper name of device (if possible) */
+const char *device_dm_name(const struct device *device)
+{
+ const char *dmdir = dm_get_dir();
+ size_t dmdir_len = strlen(dmdir);
+
+ if (!device || !device->init_done)
+ return NULL;
+
+ if (strncmp(device->path, dmdir, dmdir_len))
+ return NULL;
+
+ return &device->path[dmdir_len+1];
+}
+
+/* Get path to device / file */
+const char *device_path(const struct device *device)
+{
+ if (!device)
+ return NULL;
+
+ if (device->file_path)
+ return device->file_path;
+
+ return device->path;
+}
+
+/* block device topology ioctls, introduced in 2.6.32 */
+#ifndef BLKIOMIN
+#define BLKIOMIN _IO(0x12,120)
+#define BLKIOOPT _IO(0x12,121)
+#define BLKALIGNOFF _IO(0x12,122)
+#endif
+
+void device_topology_alignment(struct crypt_device *cd,
+ struct device *device,
+ unsigned long *required_alignment, /* bytes */
+ unsigned long *alignment_offset, /* bytes */
+ unsigned long default_alignment)
+{
+ int dev_alignment_offset = 0;
+ unsigned int min_io_size = 0, opt_io_size = 0;
+ unsigned long temp_alignment = 0;
+ int fd;
+
+ *required_alignment = default_alignment;
+ *alignment_offset = 0;
+
+ if (!device || !device->path) //FIXME
+ return;
+
+ fd = open(device->path, O_RDONLY);
+ if (fd == -1)
+ return;
+
+ /* minimum io size */
+ if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
+ log_dbg(cd, "Topology info for %s not supported, using default offset %lu bytes.",
+ device->path, default_alignment);
+ goto out;
+ }
+
+ /* optimal io size */
+ if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
+ opt_io_size = min_io_size;
+
+ /* alignment offset, bogus -1 means misaligned/unknown */
+ if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
+ dev_alignment_offset = 0;
+ *alignment_offset = (unsigned long)dev_alignment_offset;
+
+ temp_alignment = (unsigned long)min_io_size;
+
+ /*
+ * Ignore bogus opt-io that could break alignment.
+ * Also real opt_io_size should be aligned to minimal page size (4k).
+ * Some bogus USB enclosures reports wrong data here.
+ */
+ if ((temp_alignment < (unsigned long)opt_io_size) &&
+ !((unsigned long)opt_io_size % temp_alignment) && !MISALIGNED_4K(opt_io_size))
+ temp_alignment = (unsigned long)opt_io_size;
+ else if (opt_io_size && (opt_io_size != min_io_size))
+ log_err(cd, _("Ignoring bogus optimal-io size for data device (%u bytes)."), opt_io_size);
+
+ /* If calculated alignment is multiple of default, keep default */
+ if (temp_alignment && (default_alignment % temp_alignment))
+ *required_alignment = temp_alignment;
+
+ log_dbg(cd, "Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
+ min_io_size, opt_io_size, *alignment_offset, *required_alignment);
+out:
+ (void)close(fd);
+}
+
+size_t device_block_size(struct crypt_device *cd, struct device *device)
+{
+ int fd;
+
+ if (!device)
+ return 0;
+
+ if (device->block_size)
+ return device->block_size;
+
+ fd = open(device->file_path ?: device->path, O_RDONLY);
+ if (fd >= 0) {
+ device->block_size = device_block_size_fd(fd, NULL);
+ close(fd);
+ }
+
+ if (!device->block_size)
+ log_dbg(cd, "Cannot get block size for device %s.", device_path(device));
+
+ return device->block_size;
+}
+
+size_t device_optimal_encryption_sector_size(struct crypt_device *cd, struct device *device)
+{
+ int fd;
+ size_t phys_block_size;
+
+ if (!device)
+ return SECTOR_SIZE;
+
+ fd = open(device->file_path ?: device->path, O_RDONLY);
+ if (fd < 0) {
+ log_dbg(cd, "Cannot get optimal encryption sector size for device %s.", device_path(device));
+ return SECTOR_SIZE;
+ }
+
+ /* cache device block size */
+ device->block_size = device_block_size_fd(fd, NULL);
+ if (!device->block_size) {
+ close(fd);
+ log_dbg(cd, "Cannot get block size for device %s.", device_path(device));
+ return SECTOR_SIZE;
+ }
+
+ if (device->block_size >= MAX_SECTOR_SIZE) {
+ close(fd);
+ return MISALIGNED(device->block_size, MAX_SECTOR_SIZE) ? SECTOR_SIZE : MAX_SECTOR_SIZE;
+ }
+
+ phys_block_size = device_block_phys_size_fd(fd);
+ close(fd);
+
+ if (device->block_size >= phys_block_size ||
+ phys_block_size <= SECTOR_SIZE ||
+ phys_block_size > MAX_SECTOR_SIZE ||
+ MISALIGNED(phys_block_size, device->block_size))
+ return device->block_size;
+
+ return phys_block_size;
+}
+
+int device_read_ahead(struct device *device, uint32_t *read_ahead)
+{
+ int fd, r = 0;
+ long read_ahead_long;
+
+ if (!device)
+ return 0;
+
+ if ((fd = open(device->path, O_RDONLY)) < 0)
+ return 0;
+
+ r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
+ close(fd);
+
+ if (r)
+ *read_ahead = (uint32_t) read_ahead_long;
+
+ return r;
+}
+
+/* Get data size in bytes */
+int device_size(struct device *device, uint64_t *size)
+{
+ struct stat st;
+ int devfd, r = -EINVAL;
+
+ if (!device)
+ return -EINVAL;
+
+ devfd = open(device->path, O_RDONLY);
+ if (devfd == -1)
+ return -EINVAL;
+
+ if (fstat(devfd, &st) < 0)
+ goto out;
+
+ if (S_ISREG(st.st_mode)) {
+ *size = (uint64_t)st.st_size;
+ r = 0;
+ } else if (ioctl(devfd, BLKGETSIZE64, size) >= 0)
+ r = 0;
+out:
+ close(devfd);
+ return r;
+}
+
+/* For a file, allocate the required space */
+int device_fallocate(struct device *device, uint64_t size)
+{
+ struct stat st;
+ int devfd, r = -EINVAL;
+
+ if (!device)
+ return -EINVAL;
+
+ devfd = open(device_path(device), O_RDWR);
+ if (devfd == -1)
+ return -EINVAL;
+
+ if (!fstat(devfd, &st) && S_ISREG(st.st_mode) &&
+ ((uint64_t)st.st_size >= size || !posix_fallocate(devfd, 0, size))) {
+ r = 0;
+ if (device->file_path && crypt_loop_resize(device->path))
+ r = -EINVAL;
+ }
+
+ close(devfd);
+ return r;
+}
+
+int device_check_size(struct crypt_device *cd,
+ struct device *device,
+ uint64_t req_offset, int falloc)
+{
+ uint64_t dev_size;
+
+ if (device_size(device, &dev_size)) {
+ log_dbg(cd, "Cannot get device size for device %s.", device_path(device));
+ return -EIO;
+ }
+
+ log_dbg(cd, "Device size %" PRIu64 ", offset %" PRIu64 ".", dev_size, req_offset);
+
+ if (req_offset > dev_size) {
+ /* If it is header file, increase its size */
+ if (falloc && !device_fallocate(device, req_offset))
+ return 0;
+
+ log_err(cd, _("Device %s is too small. Need at least %" PRIu64 " bytes."),
+ device_path(device), req_offset);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int device_info(struct crypt_device *cd,
+ struct device *device,
+ enum devcheck device_check,
+ int *readonly, uint64_t *size)
+{
+ struct stat st;
+ int fd = -1, r, flags = 0, real_readonly;
+ uint64_t real_size;
+
+ if (!device)
+ return -ENOTBLK;
+
+ real_readonly = 0;
+ real_size = 0;
+
+ if (stat(device->path, &st) < 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* never wipe header on mounted device */
+ if (device_check == DEV_EXCL && S_ISBLK(st.st_mode))
+ flags |= O_EXCL;
+
+ /* Try to open read-write to check whether it is a read-only device */
+ /* coverity[toctou] */
+ fd = open(device->path, O_RDWR | flags);
+ if (fd == -1 && errno == EROFS) {
+ real_readonly = 1;
+ fd = open(device->path, O_RDONLY | flags);
+ }
+
+ if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY) {
+ r = -EBUSY;
+ goto out;
+ }
+
+ if (fd == -1) {
+ r = errno ? -errno : -EINVAL;
+ goto out;
+ }
+
+ r = 0;
+ if (S_ISREG(st.st_mode)) {
+ //FIXME: add readonly check
+ real_size = (uint64_t)st.st_size;
+ real_size >>= SECTOR_SHIFT;
+ } else {
+ /* If the device can be opened read-write, i.e. readonly is still 0, then
+ * check whether BKROGET says that it is read-only. E.g. read-only loop
+ * devices may be opened read-write but are read-only according to BLKROGET
+ */
+ if (real_readonly == 0 && (r = ioctl(fd, BLKROGET, &real_readonly)) < 0)
+ goto out;
+
+ r = ioctl(fd, BLKGETSIZE64, &real_size);
+ if (r >= 0) {
+ real_size >>= SECTOR_SHIFT;
+ goto out;
+ }
+ }
+out:
+ if (fd != -1)
+ close(fd);
+
+ switch (r) {
+ case 0:
+ if (readonly)
+ *readonly = real_readonly;
+ if (size)
+ *size = real_size;
+ break;
+ case -EBUSY:
+ log_err(cd, _("Cannot use device %s which is in use "
+ "(already mapped or mounted)."), device_path(device));
+ break;
+ case -EACCES:
+ log_err(cd, _("Cannot use device %s, permission denied."), device_path(device));
+ break;
+ default:
+ log_err(cd, _("Cannot get info about device %s."), device_path(device));
+ r = -EINVAL;
+ }
+
+ return r;
+}
+
+int device_check_access(struct crypt_device *cd,
+ struct device *device,
+ enum devcheck device_check)
+{
+ return device_info(cd, device, device_check, NULL, NULL);
+}
+
+static int device_internal_prepare(struct crypt_device *cd, struct device *device)
+{
+ char *loop_device = NULL, *file_path = NULL;
+ int r, loop_fd, readonly = 0;
+
+ if (device->init_done)
+ return 0;
+
+ if (getuid() || geteuid()) {
+ log_err(cd, _("Cannot use a loopback device, "
+ "running as non-root user."));
+ return -ENOTSUP;
+ }
+
+ log_dbg(cd, "Allocating a free loop device (block size: %zu).",
+ device->loop_block_size ?: SECTOR_SIZE);
+
+ /* Keep the loop open, detached on last close. */
+ loop_fd = crypt_loop_attach(&loop_device, device->path, 0, 1, &readonly, device->loop_block_size);
+ if (loop_fd == -1) {
+ log_err(cd, _("Attaching loopback device failed "
+ "(loop device with autoclear flag is required)."));
+ free(loop_device);
+ return -EINVAL;
+ }
+
+ file_path = device->path;
+ device->path = loop_device;
+
+ r = device_ready(cd, device);
+ if (r < 0) {
+ device->path = file_path;
+ crypt_loop_detach(loop_device);
+ free(loop_device);
+ return r;
+ }
+
+ log_dbg(cd, "Attached loop device block size is %zu bytes.", device_block_size_fd(loop_fd, NULL));
+
+ device->loop_fd = loop_fd;
+ device->file_path = file_path;
+ device->init_done = 1;
+
+ return 0;
+}
+
+int device_block_adjust(struct crypt_device *cd,
+ struct device *device,
+ enum devcheck device_check,
+ uint64_t device_offset,
+ uint64_t *size,
+ uint32_t *flags)
+{
+ int r, real_readonly;
+ uint64_t real_size;
+
+ if (!device)
+ return -ENOTBLK;
+
+ r = device_internal_prepare(cd, device);
+ if (r)
+ return r;
+
+ r = device_info(cd, device, device_check, &real_readonly, &real_size);
+ if (r)
+ return r;
+
+ if (device_offset >= real_size) {
+ log_err(cd, _("Requested offset is beyond real size of device %s."),
+ device_path(device));
+ return -EINVAL;
+ }
+
+ if (size && !*size) {
+ *size = real_size;
+ if (!*size) {
+ log_err(cd, _("Device %s has zero size."), device_path(device));
+ return -ENOTBLK;
+ }
+ *size -= device_offset;
+ }
+
+ /* in case of size is set by parameter */
+ if (size && ((real_size - device_offset) < *size)) {
+ log_dbg(cd, "Device %s: offset = %" PRIu64 " requested size = %" PRIu64
+ ", backing device size = %" PRIu64,
+ device->path, device_offset, *size, real_size);
+ log_err(cd, _("Device %s is too small."), device_path(device));
+ return -EINVAL;
+ }
+
+ if (flags && real_readonly)
+ *flags |= CRYPT_ACTIVATE_READONLY;
+
+ if (size)
+ log_dbg(cd, "Calculated device size is %" PRIu64" sectors (%s), offset %" PRIu64 ".",
+ *size, real_readonly ? "RO" : "RW", device_offset);
+ return 0;
+}
+
+size_t size_round_up(size_t size, size_t block)
+{
+ size_t s = (size + (block - 1)) / block;
+ return s * block;
+}
+
+void device_disable_direct_io(struct device *device)
+{
+ if (device)
+ device->o_direct = 0;
+}
+
+int device_direct_io(const struct device *device)
+{
+ return device ? device->o_direct : 0;
+}
+
+static int device_compare_path(const char *path1, const char *path2)
+{
+ struct stat st_path1, st_path2;
+
+ if (stat(path1, &st_path1 ) < 0 || stat(path2, &st_path2 ) < 0)
+ return -EINVAL;
+
+ if (S_ISBLK(st_path1.st_mode) && S_ISBLK(st_path2.st_mode))
+ return (st_path1.st_rdev == st_path2.st_rdev) ? 1 : 0;
+
+ if (S_ISREG(st_path1.st_mode) && S_ISREG(st_path2.st_mode))
+ return (st_path1.st_ino == st_path2.st_ino &&
+ st_path1.st_dev == st_path2.st_dev) ? 1 : 0;
+
+ return 0;
+}
+
+int device_is_identical(struct device *device1, struct device *device2)
+{
+ if (!device1 || !device2)
+ return 0;
+
+ if (device1 == device2)
+ return 1;
+
+ if (!strcmp(device_path(device1), device_path(device2)))
+ return 1;
+
+ return device_compare_path(device_path(device1), device_path(device2));
+}
+
+int device_is_rotational(struct device *device)
+{
+ struct stat st;
+
+ if (!device)
+ return -EINVAL;
+
+ if (stat(device_path(device), &st) < 0)
+ return -EINVAL;
+
+ if (!S_ISBLK(st.st_mode))
+ return 0;
+
+ return crypt_dev_is_rotational(major(st.st_rdev), minor(st.st_rdev));
+}
+
+size_t device_alignment(struct device *device)
+{
+ int devfd;
+
+ if (!device)
+ return -EINVAL;
+
+ if (!device->alignment) {
+ devfd = open(device_path(device), O_RDONLY);
+ if (devfd != -1) {
+ device->alignment = device_alignment_fd(devfd);
+ close(devfd);
+ }
+ }
+
+ return device->alignment;
+}
+
+void device_set_lock_handle(struct device *device, struct crypt_lock_handle *h)
+{
+ if (device)
+ device->lh = h;
+}
+
+struct crypt_lock_handle *device_get_lock_handle(struct device *device)
+{
+ return device ? device->lh : NULL;
+}
+
+int device_read_lock(struct crypt_device *cd, struct device *device)
+{
+ if (!device || !crypt_metadata_locking_enabled())
+ return 0;
+
+ if (device_read_lock_internal(cd, device))
+ return -EBUSY;
+
+ return 0;
+}
+
+int device_write_lock(struct crypt_device *cd, struct device *device)
+{
+ if (!device || !crypt_metadata_locking_enabled())
+ return 0;
+
+ assert(!device_locked(device->lh) || !device_locked_readonly(device->lh));
+
+ return device_write_lock_internal(cd, device);
+}
+
+void device_read_unlock(struct crypt_device *cd, struct device *device)
+{
+ if (!device || !crypt_metadata_locking_enabled())
+ return;
+
+ assert(device_locked(device->lh));
+
+ device_unlock_internal(cd, device);
+}
+
+void device_write_unlock(struct crypt_device *cd, struct device *device)
+{
+ if (!device || !crypt_metadata_locking_enabled())
+ return;
+
+ assert(device_locked(device->lh) && !device_locked_readonly(device->lh));
+
+ device_unlock_internal(cd, device);
+}
+
+bool device_is_locked(struct device *device)
+{
+ return device ? device_locked(device->lh) : 0;
+}
+
+void device_close(struct crypt_device *cd, struct device *device)
+{
+ if (!device)
+ return;
+
+ if (device->ro_dev_fd != -1) {
+ log_dbg(cd, "Closing read only fd for %s.", device_path(device));
+ if (close(device->ro_dev_fd))
+ log_dbg(cd, "Failed to close read only fd for %s.", device_path(device));
+ device->ro_dev_fd = -1;
+ }
+
+ if (device->dev_fd != -1) {
+ log_dbg(cd, "Closing read write fd for %s.", device_path(device));
+ if (close(device->dev_fd))
+ log_dbg(cd, "Failed to close read write fd for %s.", device_path(device));
+ device->dev_fd = -1;
+ }
+}
+
+void device_set_block_size(struct device *device, size_t size)
+{
+ if (!device)
+ return;
+
+ device->loop_block_size = size;
+}
diff --git a/lib/utils_device_locking.c b/lib/utils_device_locking.c
new file mode 100644
index 0000000..e18ea77
--- /dev/null
+++ b/lib/utils_device_locking.c
@@ -0,0 +1,520 @@
+/*
+ * Metadata on-disk locking for processes serialization
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <linux/limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+#include <libgen.h>
+
+#include "internal.h"
+#include "utils_device_locking.h"
+
+#define same_inode(buf1, buf2) \
+ ((buf1).st_ino == (buf2).st_ino && \
+ (buf1).st_dev == (buf2).st_dev)
+
+enum lock_type {
+ DEV_LOCK_READ = 0,
+ DEV_LOCK_WRITE
+};
+
+enum lock_mode {
+ DEV_LOCK_FILE = 0,
+ DEV_LOCK_BDEV,
+ DEV_LOCK_NAME
+};
+
+struct crypt_lock_handle {
+ unsigned refcnt;
+ int flock_fd;
+ enum lock_type type;
+ enum lock_mode mode;
+ union {
+ struct {
+ dev_t devno;
+ } bdev;
+ struct {
+ char *name;
+ } name;
+ } u;
+};
+
+static int resource_by_name(char *res, size_t res_size, const char *name, bool fullpath)
+{
+ int r;
+
+ if (fullpath)
+ r = snprintf(res, res_size, "%s/LN_%s", DEFAULT_LUKS2_LOCK_PATH, name);
+ else
+ r = snprintf(res, res_size, "LN_%s", name);
+
+ return (r < 0 || (size_t)r >= res_size) ? -EINVAL : 0;
+}
+
+static int resource_by_devno(char *res, size_t res_size, dev_t devno, unsigned fullpath)
+{
+ int r;
+
+ if (fullpath)
+ r = snprintf(res, res_size, "%s/L_%d:%d", DEFAULT_LUKS2_LOCK_PATH, major(devno), minor(devno));
+ else
+ r = snprintf(res, res_size, "L_%d:%d", major(devno), minor(devno));
+
+ return (r < 0 || (size_t)r >= res_size) ? -EINVAL : 0;
+}
+
+static int open_lock_dir(struct crypt_device *cd, const char *dir, const char *base)
+{
+ int dirfd, lockdfd;
+
+ dirfd = open(dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+ if (dirfd < 0) {
+ log_dbg(cd, "Failed to open directory %s: (%d: %s).", dir, errno, strerror(errno));
+ if (errno == ENOTDIR || errno == ENOENT)
+ log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."), dir, base);
+ return -EINVAL;
+ }
+
+ lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
+ if (lockdfd < 0) {
+ if (errno == ENOENT) {
+ log_dbg(cd, "Locking directory %s/%s will be created with default compiled-in permissions.", dir, base);
+
+ /* success or failure w/ errno == EEXIST either way just try to open the 'base' directory again */
+ if (mkdirat(dirfd, base, DEFAULT_LUKS2_LOCK_DIR_PERMS) && errno != EEXIST)
+ log_dbg(cd, "Failed to create directory %s in %s (%d: %s).", base, dir, errno, strerror(errno));
+ else
+ lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
+ } else {
+ log_dbg(cd, "Failed to open directory %s/%s: (%d: %s)", dir, base, errno, strerror(errno));
+ if (errno == ENOTDIR || errno == ELOOP)
+ log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."), dir, base, base);
+ }
+ }
+
+ close(dirfd);
+ return lockdfd >= 0 ? lockdfd : -EINVAL;
+}
+
+static int open_resource(struct crypt_device *cd, const char *res)
+{
+ int err, lockdir_fd, r;
+ char dir[] = DEFAULT_LUKS2_LOCK_PATH,
+ base[] = DEFAULT_LUKS2_LOCK_PATH;
+
+ lockdir_fd = open_lock_dir(cd, dirname(dir), basename(base));
+ if (lockdir_fd < 0)
+ return -EINVAL;
+
+ log_dbg(cd, "Opening lock resource file %s/%s", DEFAULT_LUKS2_LOCK_PATH, res);
+ r = openat(lockdir_fd, res, O_CREAT | O_NOFOLLOW | O_RDWR | O_CLOEXEC, 0777);
+ err = errno;
+
+ close(lockdir_fd);
+
+ return r < 0 ? -err : r;
+}
+
+static int acquire_lock_handle(struct crypt_device *cd, struct device *device, struct crypt_lock_handle *h)
+{
+ char res[PATH_MAX];
+ int dev_fd, fd;
+ struct stat st;
+
+ dev_fd = open(device_path(device), O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (dev_fd < 0)
+ return -EINVAL;
+
+ if (fstat(dev_fd, &st)) {
+ close(dev_fd);
+ return -EINVAL;
+ }
+
+ if (S_ISBLK(st.st_mode)) {
+ if (resource_by_devno(res, sizeof(res), st.st_rdev, 0)) {
+ close(dev_fd);
+ return -EINVAL;
+ }
+
+ fd = open_resource(cd, res);
+ close(dev_fd);
+ if (fd < 0)
+ return fd;
+
+ h->flock_fd = fd;
+ h->u.bdev.devno = st.st_rdev;
+ h->mode = DEV_LOCK_BDEV;
+ } else if (S_ISREG(st.st_mode)) {
+ /* workaround for nfsv4 */
+ fd = open(device_path(device), O_RDWR | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0)
+ h->flock_fd = dev_fd;
+ else {
+ h->flock_fd = fd;
+ close(dev_fd);
+ }
+ h->mode = DEV_LOCK_FILE;
+ } else {
+ /* Wrong device type */
+ close(dev_fd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int acquire_lock_handle_by_name(struct crypt_device *cd, const char *name, struct crypt_lock_handle *h)
+{
+ char res[PATH_MAX];
+ int fd;
+
+ h->u.name.name = strdup(name);
+ if (!h->u.name.name)
+ return -ENOMEM;
+
+ if (resource_by_name(res, sizeof(res), name, false)) {
+ free(h->u.name.name);
+ return -EINVAL;
+ }
+
+ fd = open_resource(cd, res);
+ if (fd < 0) {
+ free(h->u.name.name);
+ return fd;
+ }
+
+ h->flock_fd = fd;
+ h->mode = DEV_LOCK_NAME;
+
+ return 0;
+}
+
+static void release_lock_handle(struct crypt_device *cd, struct crypt_lock_handle *h)
+{
+ char res[PATH_MAX];
+ struct stat buf_a, buf_b;
+
+ if ((h->mode == DEV_LOCK_NAME) && /* was it name lock */
+ !flock(h->flock_fd, LOCK_EX | LOCK_NB) && /* lock to drop the file */
+ !resource_by_name(res, sizeof(res), h->u.name.name, true) && /* acquire lock resource name */
+ !fstat(h->flock_fd, &buf_a) && /* read inode id referred by fd */
+ !stat(res, &buf_b) && /* does path file still exist? */
+ same_inode(buf_a, buf_b)) { /* is it same id as the one referenced by fd? */
+ /* coverity[toctou] */
+ if (unlink(res)) /* yes? unlink the file. lgtm[cpp/toctou-race-condition] */
+ log_dbg(cd, "Failed to unlink resource file: %s", res);
+ }
+
+ if ((h->mode == DEV_LOCK_BDEV) && /* was it block device */
+ !flock(h->flock_fd, LOCK_EX | LOCK_NB) && /* lock to drop the file */
+ !resource_by_devno(res, sizeof(res), h->u.bdev.devno, 1) && /* acquire lock resource name */
+ !fstat(h->flock_fd, &buf_a) && /* read inode id referred by fd */
+ !stat(res, &buf_b) && /* does path file still exist? */
+ same_inode(buf_a, buf_b)) { /* is it same id as the one referenced by fd? */
+ /* coverity[toctou] */
+ if (unlink(res)) /* yes? unlink the file. lgtm[cpp/toctou-race-condition] */
+ log_dbg(cd, "Failed to unlink resource file: %s", res);
+ }
+
+ if (h->mode == DEV_LOCK_NAME)
+ free(h->u.name.name);
+
+ if (close(h->flock_fd))
+ log_dbg(cd, "Failed to close lock resource fd (%d).", h->flock_fd);
+}
+
+int device_locked(struct crypt_lock_handle *h)
+{
+ return (h && (h->type == DEV_LOCK_READ || h->type == DEV_LOCK_WRITE));
+}
+
+int device_locked_readonly(struct crypt_lock_handle *h)
+{
+ return (h && h->type == DEV_LOCK_READ);
+}
+
+static int verify_lock_handle(struct crypt_lock_handle *h)
+{
+ char res[PATH_MAX];
+ struct stat lck_st, res_st;
+
+ /* we locked a regular file, check during device_open() instead. No reason to check now */
+ if (h->mode == DEV_LOCK_FILE)
+ return 0;
+
+ if (h->mode == DEV_LOCK_NAME) {
+ if (resource_by_name(res, sizeof(res), h->u.name.name, true))
+ return -EINVAL;
+ } else if (h->mode == DEV_LOCK_BDEV) {
+ if (resource_by_devno(res, sizeof(res), h->u.bdev.devno, true))
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ if (fstat(h->flock_fd, &lck_st))
+ return -EINVAL;
+
+ return (stat(res, &res_st) || !same_inode(lck_st, res_st)) ? -EAGAIN : 0;
+}
+
+static unsigned device_lock_inc(struct crypt_lock_handle *h)
+{
+ return ++h->refcnt;
+}
+
+static unsigned device_lock_dec(struct crypt_lock_handle *h)
+{
+ assert(h->refcnt);
+
+ return --h->refcnt;
+}
+
+static int acquire_and_verify(struct crypt_device *cd, struct device *device, const char *resource, int flock_op, struct crypt_lock_handle **lock)
+{
+ int r;
+ struct crypt_lock_handle *h;
+
+ if (device && resource)
+ return -EINVAL;
+
+ if (!(h = malloc(sizeof(*h))))
+ return -ENOMEM;
+
+ do {
+ r = device ? acquire_lock_handle(cd, device, h) : acquire_lock_handle_by_name(cd, resource, h);
+ if (r < 0)
+ break;
+
+ if (flock(h->flock_fd, flock_op)) {
+ log_dbg(cd, "Flock on fd %d failed with errno %d.", h->flock_fd, errno);
+ r = (errno == EWOULDBLOCK) ? -EBUSY : -EINVAL;
+ release_lock_handle(cd, h);
+ break;
+ }
+
+ log_dbg(cd, "Verifying lock handle for %s.", device ? device_path(device) : resource);
+
+ /*
+ * check whether another libcryptsetup process removed resource file before this
+ * one managed to flock() it. See release_lock_handle() for details
+ */
+ r = verify_lock_handle(h);
+ if (r < 0) {
+ if (flock(h->flock_fd, LOCK_UN))
+ log_dbg(cd, "flock on fd %d failed.", h->flock_fd);
+ release_lock_handle(cd, h);
+ log_dbg(cd, "Lock handle verification failed.");
+ }
+ } while (r == -EAGAIN);
+
+ if (r < 0) {
+ free(h);
+ return r;
+ }
+
+ *lock = h;
+
+ return 0;
+}
+
+int device_read_lock_internal(struct crypt_device *cd, struct device *device)
+{
+ int r;
+ struct crypt_lock_handle *h;
+
+ if (!device)
+ return -EINVAL;
+
+ h = device_get_lock_handle(device);
+
+ if (device_locked(h)) {
+ device_lock_inc(h);
+ log_dbg(cd, "Device %s READ lock (or higher) already held.", device_path(device));
+ return 0;
+ }
+
+ log_dbg(cd, "Acquiring read lock for device %s.", device_path(device));
+
+ r = acquire_and_verify(cd, device, NULL, LOCK_SH, &h);
+ if (r < 0)
+ return r;
+
+ h->type = DEV_LOCK_READ;
+ h->refcnt = 1;
+ device_set_lock_handle(device, h);
+
+ log_dbg(cd, "Device %s READ lock taken.", device_path(device));
+
+ return 0;
+}
+
+int device_write_lock_internal(struct crypt_device *cd, struct device *device)
+{
+ int r;
+ struct crypt_lock_handle *h;
+
+ if (!device)
+ return -EINVAL;
+
+ h = device_get_lock_handle(device);
+
+ if (device_locked(h)) {
+ log_dbg(cd, "Device %s WRITE lock already held.", device_path(device));
+ return device_lock_inc(h);
+ }
+
+ log_dbg(cd, "Acquiring write lock for device %s.", device_path(device));
+
+ r = acquire_and_verify(cd, device, NULL, LOCK_EX, &h);
+ if (r < 0)
+ return r;
+
+ h->type = DEV_LOCK_WRITE;
+ h->refcnt = 1;
+ device_set_lock_handle(device, h);
+
+ log_dbg(cd, "Device %s WRITE lock taken.", device_path(device));
+
+ return 1;
+}
+
+int crypt_read_lock(struct crypt_device *cd, const char *resource, bool blocking, struct crypt_lock_handle **lock)
+{
+ int r;
+ struct crypt_lock_handle *h;
+
+ if (!resource)
+ return -EINVAL;
+
+ log_dbg(cd, "Acquiring %sblocking read lock for resource %s.", blocking ? "" : "non", resource);
+
+ r = acquire_and_verify(cd, NULL, resource, LOCK_SH | (blocking ? 0 : LOCK_NB), &h);
+ if (r < 0)
+ return r;
+
+ h->type = DEV_LOCK_READ;
+ h->refcnt = 1;
+
+ log_dbg(cd, "READ lock for resource %s taken.", resource);
+
+ *lock = h;
+
+ return 0;
+}
+
+int crypt_write_lock(struct crypt_device *cd, const char *resource, bool blocking, struct crypt_lock_handle **lock)
+{
+ int r;
+ struct crypt_lock_handle *h;
+
+ if (!resource)
+ return -EINVAL;
+
+ log_dbg(cd, "Acquiring %sblocking write lock for resource %s.", blocking ? "" : "non", resource);
+
+ r = acquire_and_verify(cd, NULL, resource, LOCK_EX | (blocking ? 0 : LOCK_NB), &h);
+ if (r < 0)
+ return r;
+
+ h->type = DEV_LOCK_WRITE;
+ h->refcnt = 1;
+
+ log_dbg(cd, "WRITE lock for resource %s taken.", resource);
+
+ *lock = h;
+
+ return 0;
+}
+
+static void unlock_internal(struct crypt_device *cd, struct crypt_lock_handle *h)
+{
+ if (flock(h->flock_fd, LOCK_UN))
+ log_dbg(cd, "flock on fd %d failed.", h->flock_fd);
+ release_lock_handle(cd, h);
+ free(h);
+}
+
+void crypt_unlock_internal(struct crypt_device *cd, struct crypt_lock_handle *h)
+{
+ if (!h)
+ return;
+
+ /* nested locks are illegal */
+ assert(!device_lock_dec(h));
+
+ log_dbg(cd, "Unlocking %s lock for resource %s.",
+ device_locked_readonly(h) ? "READ" : "WRITE", h->u.name.name);
+
+ unlock_internal(cd, h);
+}
+
+void device_unlock_internal(struct crypt_device *cd, struct device *device)
+{
+ bool readonly;
+ struct crypt_lock_handle *h = device_get_lock_handle(device);
+ unsigned u = device_lock_dec(h);
+
+ if (u)
+ return;
+
+ readonly = device_locked_readonly(h);
+
+ unlock_internal(cd, h);
+
+ log_dbg(cd, "Device %s %s lock released.", device_path(device),
+ readonly ? "READ" : "WRITE");
+
+ device_set_lock_handle(device, NULL);
+}
+
+int device_locked_verify(struct crypt_device *cd, int dev_fd, struct crypt_lock_handle *h)
+{
+ char res[PATH_MAX];
+ struct stat dev_st, lck_st, st;
+
+ if (fstat(dev_fd, &dev_st) || fstat(h->flock_fd, &lck_st))
+ return 1;
+
+ /* if device handle is regular file the handle must match the lock handle */
+ if (S_ISREG(dev_st.st_mode)) {
+ log_dbg(cd, "Verifying locked device handle (regular file)");
+ if (!same_inode(dev_st, lck_st))
+ return 1;
+ } else if (S_ISBLK(dev_st.st_mode)) {
+ log_dbg(cd, "Verifying locked device handle (bdev)");
+ if (resource_by_devno(res, sizeof(res), dev_st.st_rdev, 1) ||
+ stat(res, &st) ||
+ !same_inode(lck_st, st))
+ return 1;
+ } else
+ return 1;
+
+ return 0;
+}
diff --git a/lib/utils_device_locking.h b/lib/utils_device_locking.h
new file mode 100644
index 0000000..b73f15d
--- /dev/null
+++ b/lib/utils_device_locking.h
@@ -0,0 +1,49 @@
+/*
+ * Metadata on-disk locking for processes serialization
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_UTILS_LOCKING_H
+#define _CRYPTSETUP_UTILS_LOCKING_H
+
+#include <stdbool.h>
+
+struct crypt_device;
+struct crypt_lock_handle;
+struct device;
+
+int device_locked_readonly(struct crypt_lock_handle *h);
+int device_locked(struct crypt_lock_handle *h);
+
+int device_read_lock_internal(struct crypt_device *cd, struct device *device);
+int device_write_lock_internal(struct crypt_device *cd, struct device *device);
+void device_unlock_internal(struct crypt_device *cd, struct device *device);
+
+int device_locked_verify(struct crypt_device *cd, int fd, struct crypt_lock_handle *h);
+
+int crypt_read_lock(struct crypt_device *cd, const char *name, bool blocking, struct crypt_lock_handle **lock);
+int crypt_write_lock(struct crypt_device *cd, const char *name, bool blocking, struct crypt_lock_handle **lock);
+void crypt_unlock_internal(struct crypt_device *cd, struct crypt_lock_handle *h);
+
+
+/* Used only in device internal allocation */
+void device_set_lock_handle(struct device *device, struct crypt_lock_handle *h);
+struct crypt_lock_handle *device_get_lock_handle(struct device *device);
+
+#endif
diff --git a/lib/utils_devpath.c b/lib/utils_devpath.c
new file mode 100644
index 0000000..dc5a5bb
--- /dev/null
+++ b/lib/utils_devpath.c
@@ -0,0 +1,459 @@
+/*
+ * devname - search for device name
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+#include "internal.h"
+
+static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level)
+{
+ struct dirent *entry;
+ struct stat st;
+ char *ptr;
+ char *result = NULL;
+ DIR *dir;
+ int space;
+
+ /* Ignore strange nested directories */
+ if (dir_level > max_level)
+ return NULL;
+
+ path[PATH_MAX - 1] = '\0';
+ ptr = path + strlen(path);
+ *ptr++ = '/';
+ *ptr = '\0';
+ space = PATH_MAX - (ptr - path);
+
+ dir = opendir(path);
+ if (!dir)
+ return NULL;
+
+ while((entry = readdir(dir))) {
+ if (entry->d_name[0] == '.' ||
+ !strncmp(entry->d_name, "..", 2))
+ continue;
+
+ if (dir_level == 0 &&
+ (!strcmp(entry->d_name, "shm") ||
+ !strcmp(entry->d_name, "fd") ||
+ !strcmp(entry->d_name, "char") ||
+ !strcmp(entry->d_name, "pts")))
+ continue;
+
+ strncpy(ptr, entry->d_name, space);
+ if (stat(path, &st) < 0)
+ continue;
+
+ if (S_ISDIR(st.st_mode)) {
+ result = __lookup_dev(path, dev, dir_level + 1, max_level);
+ if (result)
+ break;
+ } else if (S_ISBLK(st.st_mode)) {
+ /* workaround: ignore dm-X devices, these are internal kernel names */
+ if (dir_level == 0 && dm_is_dm_kernel_name(entry->d_name))
+ continue;
+ if (st.st_rdev == dev) {
+ result = strdup(path);
+ break;
+ }
+ }
+ }
+
+ closedir(dir);
+ return result;
+}
+
+/*
+ * Non-udev systemd need to scan for device here.
+ */
+static char *lookup_dev_old(int major, int minor)
+{
+ dev_t dev;
+ char *result = NULL, buf[PATH_MAX + 1];
+
+ dev = makedev(major, minor);
+ strncpy(buf, "/dev", PATH_MAX);
+ buf[PATH_MAX] = '\0';
+
+ /* First try low level device */
+ if ((result = __lookup_dev(buf, dev, 0, 0)))
+ return result;
+
+ /* If it is dm, try DM dir */
+ if (dm_is_dm_device(major)) {
+ strncpy(buf, dm_get_dir(), PATH_MAX);
+ if ((result = __lookup_dev(buf, dev, 0, 0)))
+ return result;
+ }
+
+ strncpy(buf, "/dev", PATH_MAX);
+ return __lookup_dev(buf, dev, 0, 4);
+}
+
+/*
+ * Returns string pointing to device in /dev according to "major:minor" dev_id
+ */
+char *crypt_lookup_dev(const char *dev_id)
+{
+ int major, minor;
+ char link[PATH_MAX], path[PATH_MAX], *devname, *devpath = NULL;
+ struct stat st;
+ ssize_t len;
+
+ if (sscanf(dev_id, "%d:%d", &major, &minor) != 2)
+ return NULL;
+
+ if (snprintf(path, sizeof(path), "/sys/dev/block/%s", dev_id) < 0)
+ return NULL;
+
+ len = readlink(path, link, sizeof(link) - 1);
+ if (len < 0) {
+ /* Without /sys use old scan */
+ if (stat("/sys/dev/block", &st) < 0)
+ return lookup_dev_old(major, minor);
+ return NULL;
+ }
+
+ link[len] = '\0';
+ devname = strrchr(link, '/');
+ if (!devname)
+ return NULL;
+ devname++;
+
+ if (dm_is_dm_kernel_name(devname))
+ devpath = dm_device_path("/dev/mapper/", major, minor);
+ else if (snprintf(path, sizeof(path), "/dev/%s", devname) > 0)
+ devpath = strdup(path);
+
+ /*
+ * Check that path is correct.
+ */
+ if (devpath && ((stat(devpath, &st) < 0) ||
+ !S_ISBLK(st.st_mode) ||
+ (st.st_rdev != makedev(major, minor)))) {
+ free(devpath);
+ /* Should never happen unless user mangles with dev nodes. */
+ return lookup_dev_old(major, minor);
+ }
+
+ return devpath;
+}
+
+static int _read_uint64(const char *sysfs_path, uint64_t *value)
+{
+ char tmp[64] = {0};
+ int fd, r;
+
+ if ((fd = open(sysfs_path, O_RDONLY)) < 0)
+ return 0;
+ r = read(fd, tmp, sizeof(tmp));
+ close(fd);
+
+ if (r <= 0)
+ return 0;
+
+ if (sscanf(tmp, "%" PRIu64, value) != 1)
+ return 0;
+
+ return 1;
+}
+
+static int _sysfs_get_uint64(int major, int minor, uint64_t *value, const char *attr)
+{
+ char path[PATH_MAX];
+
+ if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/%s",
+ major, minor, attr) < 0)
+ return 0;
+
+ return _read_uint64(path, value);
+}
+
+static int _path_get_uint64(const char *sysfs_path, uint64_t *value, const char *attr)
+{
+ char path[PATH_MAX];
+
+ if (snprintf(path, sizeof(path), "%s/%s",
+ sysfs_path, attr) < 0)
+ return 0;
+
+ return _read_uint64(path, value);
+}
+
+int crypt_dev_is_rotational(int major, int minor)
+{
+ uint64_t val;
+
+ if (!_sysfs_get_uint64(major, minor, &val, "queue/rotational"))
+ return 1; /* if failed, expect rotational disk */
+
+ return val ? 1 : 0;
+}
+
+int crypt_dev_is_partition(const char *dev_path)
+{
+ uint64_t val;
+ struct stat st;
+
+ if (stat(dev_path, &st) < 0)
+ return 0;
+
+ if (!S_ISBLK(st.st_mode))
+ return 0;
+
+ if (!_sysfs_get_uint64(major(st.st_rdev), minor(st.st_rdev),
+ &val, "partition"))
+ return 0;
+
+ return val ? 1 : 0;
+}
+
+uint64_t crypt_dev_partition_offset(const char *dev_path)
+{
+ uint64_t val;
+ struct stat st;
+
+ if (!crypt_dev_is_partition(dev_path))
+ return 0;
+
+ if (stat(dev_path, &st) < 0)
+ return 0;
+
+ if (!_sysfs_get_uint64(major(st.st_rdev), minor(st.st_rdev),
+ &val, "start"))
+ return 0;
+
+ return val;
+}
+
+/* Try to find partition which match offset and size on top level device */
+char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t size)
+{
+ char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
+ char *result = NULL;
+ struct stat st;
+ size_t devname_len;
+ ssize_t len;
+ struct dirent *entry;
+ DIR *dir;
+ uint64_t part_offset, part_size;
+
+ if (stat(dev_path, &st) < 0)
+ return NULL;
+
+ if (!S_ISBLK(st.st_mode))
+ return NULL;
+
+ if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
+ major(st.st_rdev), minor(st.st_rdev)) < 0)
+ return NULL;
+
+ dir = opendir(path);
+ if (!dir)
+ return NULL;
+
+ len = readlink(path, link, sizeof(link) - 1);
+ if (len < 0) {
+ closedir(dir);
+ return NULL;
+ }
+
+ /* Get top level disk name for sysfs search */
+ link[len] = '\0';
+ devname = strrchr(link, '/');
+ if (!devname) {
+ closedir(dir);
+ return NULL;
+ }
+ devname++;
+
+ /* DM devices do not use kernel partitions. */
+ if (dm_is_dm_kernel_name(devname)) {
+ closedir(dir);
+ return NULL;
+ }
+
+ devname_len = strlen(devname);
+ while((entry = readdir(dir))) {
+ if (strncmp(entry->d_name, devname, devname_len))
+ continue;
+
+ if (snprintf(part_path, sizeof(part_path), "%s/%s",
+ path, entry->d_name) < 0)
+ continue;
+
+ if (stat(part_path, &st) < 0)
+ continue;
+
+ if (S_ISDIR(st.st_mode)) {
+ if (!_path_get_uint64(part_path, &part_offset, "start") ||
+ !_path_get_uint64(part_path, &part_size, "size"))
+ continue;
+ if (part_offset == offset && part_size == size &&
+ snprintf(part_path, sizeof(part_path), "/dev/%s",
+ entry->d_name) > 0) {
+ result = strdup(part_path);
+ break;
+ }
+ }
+ }
+ closedir(dir);
+
+ return result;
+}
+
+/* Try to find base device from partition */
+char *crypt_get_base_device(const char *dev_path)
+{
+ char link[PATH_MAX], path[PATH_MAX], part_path[PATH_MAX], *devname;
+ struct stat st;
+ ssize_t len;
+
+ if (!crypt_dev_is_partition(dev_path))
+ return NULL;
+
+ if (stat(dev_path, &st) < 0)
+ return NULL;
+
+ if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d",
+ major(st.st_rdev), minor(st.st_rdev)) < 0)
+ return NULL;
+
+ len = readlink(path, link, sizeof(link) - 1);
+ if (len < 0)
+ return NULL;
+
+ /* Get top level disk name for sysfs search */
+ link[len] = '\0';
+ devname = strrchr(link, '/');
+ if (!devname)
+ return NULL;
+ *devname = '\0';
+ devname = strrchr(link, '/');
+ if (!devname)
+ return NULL;
+ devname++;
+
+ if (dm_is_dm_kernel_name(devname))
+ return NULL;
+
+ if (snprintf(part_path, sizeof(part_path), "/dev/%s", devname) < 0)
+ return NULL;
+
+ return strdup(part_path);
+}
+
+int lookup_by_disk_id(const char *dm_uuid)
+{
+ struct dirent *entry;
+ struct stat st;
+ int r = 0; /* not found */
+ DIR *dir = opendir("/dev/disk/by-id");
+
+ if (!dir)
+ /* map ENOTDIR to ENOENT we'll handle both errors same */
+ return errno == ENOTDIR ? -ENOENT : -errno;
+
+ while ((entry = readdir(dir))) {
+ if (entry->d_name[0] == '.' ||
+ !strncmp(entry->d_name, "..", 2))
+ continue;
+
+ if (fstatat(dirfd(dir), entry->d_name, &st, AT_SYMLINK_NOFOLLOW)) {
+ r = -EINVAL;
+ break;
+ }
+
+ if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
+ continue;
+
+ if (!strncmp(entry->d_name, dm_uuid, strlen(dm_uuid))) {
+ r = 1;
+ break;
+ }
+ }
+
+ closedir(dir);
+
+ return r;
+}
+
+int lookup_by_sysfs_uuid_field(const char *dm_uuid)
+{
+ struct dirent *entry;
+ char subpath[PATH_MAX], uuid[DM_UUID_LEN];
+ ssize_t s;
+ struct stat st;
+ int fd, len, r = 0; /* not found */
+ DIR *dir = opendir("/sys/block/");
+
+ if (!dir)
+ /* map ENOTDIR to ENOENT we'll handle both errors same */
+ return errno == ENOTDIR ? -ENOENT : -errno;
+
+ while (r != 1 && (entry = readdir(dir))) {
+ if (entry->d_name[0] == '.' ||
+ !strncmp(entry->d_name, "..", 2))
+ continue;
+
+ len = snprintf(subpath, PATH_MAX, "%s/%s", entry->d_name, "dm/uuid");
+ if (len < 0 || len >= PATH_MAX) {
+ r = -EINVAL;
+ break;
+ }
+
+ /* looking for dm-X/dm/uuid file, symlinks are fine */
+ fd = openat(dirfd(dir), subpath, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ continue;
+
+ if (fstat(fd, &st) || !S_ISREG(st.st_mode)) {
+ close(fd);
+ continue;
+ }
+
+ /* reads binary data */
+ s = read_buffer(fd, uuid, sizeof(uuid) - 1);
+ if (s > 0) {
+ uuid[s] = '\0';
+ if (!strncmp(uuid, dm_uuid, strlen(dm_uuid)))
+ r = 1;
+ }
+
+ close(fd);
+ }
+
+ closedir(dir);
+
+ return r;
+}
diff --git a/lib/utils_dm.h b/lib/utils_dm.h
new file mode 100644
index 0000000..79212a2
--- /dev/null
+++ b/lib/utils_dm.h
@@ -0,0 +1,246 @@
+/*
+ * libdevmapper - device-mapper backend for cryptsetup
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _UTILS_DM_H
+#define _UTILS_DM_H
+
+/* device-mapper library helpers */
+#include <stddef.h>
+#include <stdint.h>
+
+struct crypt_device;
+struct volume_key;
+struct crypt_params_verity;
+struct device;
+struct crypt_params_integrity;
+
+/* Device mapper internal flags */
+#define DM_RESUME_PRIVATE (1 << 4) /* CRYPT_ACTIVATE_PRIVATE */
+#define DM_SUSPEND_SKIP_LOCKFS (1 << 5)
+#define DM_SUSPEND_WIPE_KEY (1 << 6)
+#define DM_SUSPEND_NOFLUSH (1 << 7)
+
+static inline uint32_t act2dmflags(uint32_t act_flags)
+{
+ return (act_flags & DM_RESUME_PRIVATE);
+}
+
+/* Device mapper backend - kernel support flags */
+#define DM_KEY_WIPE_SUPPORTED (1 << 0) /* key wipe message */
+#define DM_LMK_SUPPORTED (1 << 1) /* lmk mode */
+#define DM_SECURE_SUPPORTED (1 << 2) /* wipe (secure) buffer flag */
+#define DM_PLAIN64_SUPPORTED (1 << 3) /* plain64 IV */
+#define DM_DISCARDS_SUPPORTED (1 << 4) /* discards/TRIM option is supported */
+#define DM_VERITY_SUPPORTED (1 << 5) /* dm-verity target supported */
+#define DM_TCW_SUPPORTED (1 << 6) /* tcw (TCRYPT CBC with whitening) */
+#define DM_SAME_CPU_CRYPT_SUPPORTED (1 << 7) /* same_cpu_crypt */
+#define DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED (1 << 8) /* submit_from_crypt_cpus */
+#define DM_VERITY_ON_CORRUPTION_SUPPORTED (1 << 9) /* ignore/restart_on_corruption, ignore_zero_block */
+#define DM_VERITY_FEC_SUPPORTED (1 << 10) /* Forward Error Correction (FEC) */
+#define DM_KERNEL_KEYRING_SUPPORTED (1 << 11) /* dm-crypt allows loading kernel keyring keys */
+#define DM_INTEGRITY_SUPPORTED (1 << 12) /* dm-integrity target supported */
+#define DM_SECTOR_SIZE_SUPPORTED (1 << 13) /* support for sector size setting in dm-crypt/dm-integrity */
+#define DM_CAPI_STRING_SUPPORTED (1 << 14) /* support for cryptoapi format cipher definition */
+#define DM_DEFERRED_SUPPORTED (1 << 15) /* deferred removal of device */
+#define DM_INTEGRITY_RECALC_SUPPORTED (1 << 16) /* dm-integrity automatic recalculation supported */
+#define DM_INTEGRITY_BITMAP_SUPPORTED (1 << 17) /* dm-integrity bitmap mode supported */
+#define DM_GET_TARGET_VERSION_SUPPORTED (1 << 18) /* dm DM_GET_TARGET version ioctl supported */
+#define DM_INTEGRITY_FIX_PADDING_SUPPORTED (1 << 19) /* supports the parameter fix_padding that fixes a bug that caused excessive padding */
+#define DM_BITLK_EBOIV_SUPPORTED (1 << 20) /* EBOIV for BITLK supported */
+#define DM_BITLK_ELEPHANT_SUPPORTED (1 << 21) /* Elephant diffuser for BITLK supported */
+#define DM_VERITY_SIGNATURE_SUPPORTED (1 << 22) /* Verity option root_hash_sig_key_desc supported */
+#define DM_INTEGRITY_DISCARDS_SUPPORTED (1 << 23) /* dm-integrity discards/TRIM option is supported */
+#define DM_INTEGRITY_RESIZE_SUPPORTED (1 << 23) /* dm-integrity resize of the integrity device supported (introduced in the same version as discards)*/
+#define DM_VERITY_PANIC_CORRUPTION_SUPPORTED (1 << 24) /* dm-verity panic on corruption */
+#define DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt suppot for bypassing workqueues */
+#define DM_INTEGRITY_FIX_HMAC_SUPPORTED (1 << 26) /* hmac covers also superblock */
+#define DM_INTEGRITY_RESET_RECALC_SUPPORTED (1 << 27) /* dm-integrity automatic recalculation supported */
+#define DM_VERITY_TASKLETS_SUPPORTED (1 << 28) /* dm-verity tasklets supported */
+
+typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_ZERO, DM_UNKNOWN } dm_target_type;
+enum tdirection { TARGET_EMPTY = 0, TARGET_SET, TARGET_QUERY };
+
+int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags);
+
+#define DM_ACTIVE_DEVICE (1 << 0)
+#define DM_ACTIVE_UUID (1 << 1)
+#define DM_ACTIVE_HOLDERS (1 << 2)
+
+#define DM_ACTIVE_CRYPT_CIPHER (1 << 3)
+#define DM_ACTIVE_CRYPT_KEYSIZE (1 << 4)
+#define DM_ACTIVE_CRYPT_KEY (1 << 5)
+
+#define DM_ACTIVE_VERITY_ROOT_HASH (1 << 6)
+#define DM_ACTIVE_VERITY_HASH_DEVICE (1 << 7)
+#define DM_ACTIVE_VERITY_PARAMS (1 << 8)
+
+#define DM_ACTIVE_INTEGRITY_PARAMS (1 << 9)
+
+#define DM_ACTIVE_JOURNAL_CRYPT_KEY (1 << 10)
+#define DM_ACTIVE_JOURNAL_CRYPT_KEYSIZE (1 << 11)
+
+#define DM_ACTIVE_JOURNAL_MAC_KEY (1 << 12)
+#define DM_ACTIVE_JOURNAL_MAC_KEYSIZE (1 << 13)
+
+struct dm_target {
+ dm_target_type type;
+ enum tdirection direction;
+ uint64_t offset;
+ uint64_t size;
+ struct device *data_device;
+ union {
+ struct {
+ const char *cipher;
+ const char *integrity;
+
+ /* Active key for device */
+ struct volume_key *vk;
+
+ /* struct crypt_active_device */
+ uint64_t offset; /* offset in sectors */
+ uint64_t iv_offset; /* IV initialisation sector */
+ uint32_t tag_size; /* additional on-disk tag size */
+ uint32_t sector_size; /* encryption sector size */
+ } crypt;
+ struct {
+ struct device *hash_device;
+ struct device *fec_device;
+
+ const char *root_hash;
+ uint32_t root_hash_size;
+ const char *root_hash_sig_key_desc;
+
+ uint64_t hash_offset; /* hash offset in blocks (not header) */
+ uint64_t fec_offset; /* FEC offset in blocks (not header) */
+ uint64_t fec_blocks; /* FEC blocks covering data + hash + padding (foreign metadata)*/
+ struct crypt_params_verity *vp;
+ } verity;
+ struct {
+ uint64_t journal_size;
+ uint32_t journal_watermark;
+ uint32_t journal_commit_time;
+ uint32_t interleave_sectors;
+ uint32_t tag_size;
+ uint64_t offset; /* offset in sectors */
+ uint32_t sector_size; /* integrity sector size */
+ uint32_t buffer_sectors;
+
+ const char *integrity;
+ /* Active key for device */
+ struct volume_key *vk;
+
+ const char *journal_integrity;
+ struct volume_key *journal_integrity_key;
+
+ const char *journal_crypt;
+ struct volume_key *journal_crypt_key;
+
+ struct device *meta_device;
+
+ bool fix_padding;
+ bool fix_hmac;
+ bool legacy_recalc;
+ } integrity;
+ struct {
+ uint64_t offset;
+ } linear;
+ struct {
+ } zero;
+ } u;
+
+ char *params;
+ struct dm_target *next;
+};
+
+struct crypt_dm_active_device {
+ uint64_t size; /* active device size */
+ uint32_t flags; /* activation flags */
+ const char *uuid;
+
+ unsigned holders:1; /* device holders detected (on query only) */
+
+ struct dm_target segment;
+};
+
+static inline bool single_segment(const struct crypt_dm_active_device *dmd)
+{
+ return dmd && !dmd->segment.next;
+}
+
+void dm_backend_init(struct crypt_device *cd);
+void dm_backend_exit(struct crypt_device *cd);
+
+int dm_targets_allocate(struct dm_target *first, unsigned count);
+void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd);
+
+int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *data_device, struct volume_key *vk, const char *cipher,
+ uint64_t iv_offset, uint64_t data_offset, const char *integrity,
+ uint32_t tag_size, uint32_t sector_size);
+int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *data_device, struct device *hash_device, struct device *fec_device,
+ const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
+ uint64_t hash_offset_block, uint64_t fec_blocks, struct crypt_params_verity *vp);
+int dm_integrity_target_set(struct crypt_device *cd,
+ struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *meta_device,
+ struct device *data_device, uint64_t tag_size, uint64_t offset, uint32_t sector_size,
+ struct volume_key *vk,
+ struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key,
+ const struct crypt_params_integrity *ip);
+int dm_linear_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
+ struct device *data_device, uint64_t data_offset);
+int dm_zero_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size);
+
+int dm_remove_device(struct crypt_device *cd, const char *name, uint32_t flags);
+int dm_status_device(struct crypt_device *cd, const char *name);
+int dm_status_suspended(struct crypt_device *cd, const char *name);
+int dm_status_verity_ok(struct crypt_device *cd, const char *name);
+int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count);
+int dm_query_device(struct crypt_device *cd, const char *name,
+ uint32_t get_flags, struct crypt_dm_active_device *dmd);
+int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,
+ char **names, size_t names_length);
+int dm_create_device(struct crypt_device *cd, const char *name,
+ const char *type, struct crypt_dm_active_device *dmd);
+int dm_reload_device(struct crypt_device *cd, const char *name,
+ struct crypt_dm_active_device *dmd, uint32_t dmflags, unsigned resume);
+int dm_suspend_device(struct crypt_device *cd, const char *name, uint32_t dmflags);
+int dm_resume_device(struct crypt_device *cd, const char *name, uint32_t dmflags);
+int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
+ const struct volume_key *vk);
+int dm_error_device(struct crypt_device *cd, const char *name);
+int dm_clear_device(struct crypt_device *cd, const char *name);
+int dm_cancel_deferred_removal(const char *name);
+
+const char *dm_get_dir(void);
+
+int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type);
+
+/* These are DM helpers used only by utils_devpath file */
+int dm_is_dm_device(int major);
+int dm_is_dm_kernel_name(const char *name);
+char *dm_device_path(const char *prefix, int major, int minor);
+char *dm_device_name(const char *path);
+
+#endif /* _UTILS_DM_H */
diff --git a/lib/utils_io.c b/lib/utils_io.c
new file mode 100644
index 0000000..a5bc501
--- /dev/null
+++ b/lib/utils_io.c
@@ -0,0 +1,299 @@
+/*
+ * utils - miscellaneous I/O utilities for cryptsetup
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "utils_io.h"
+
+/* coverity[ -taint_source : arg-1 ] */
+static ssize_t _read_buffer(int fd, void *buf, size_t length, volatile int *quit)
+{
+ size_t read_size = 0;
+ ssize_t r;
+
+ if (fd < 0 || !buf)
+ return -EINVAL;
+
+ do {
+ r = read(fd, buf, length - read_size);
+ if (r == -1 && errno != EINTR)
+ return r;
+ if (r > 0) {
+ read_size += (size_t)r;
+ buf = (uint8_t*)buf + r;
+ }
+ if (r == 0 || (quit && *quit))
+ return (ssize_t)read_size;
+ } while (read_size != length);
+
+ return (ssize_t)length;
+}
+
+ssize_t read_buffer(int fd, void *buf, size_t length)
+{
+ return _read_buffer(fd, buf, length, NULL);
+}
+
+ssize_t read_buffer_intr(int fd, void *buf, size_t length, volatile int *quit)
+{
+ return _read_buffer(fd, buf, length, quit);
+}
+
+static ssize_t _write_buffer(int fd, const void *buf, size_t length, volatile int *quit)
+{
+ size_t write_size = 0;
+ ssize_t w;
+
+ if (fd < 0 || !buf || !length)
+ return -EINVAL;
+
+ do {
+ w = write(fd, buf, length - write_size);
+ if (w < 0 && errno != EINTR)
+ return w;
+ if (w > 0) {
+ write_size += (size_t) w;
+ buf = (const uint8_t*)buf + w;
+ }
+ if (w == 0 || (quit && *quit))
+ return (ssize_t)write_size;
+ } while (write_size != length);
+
+ return (ssize_t)write_size;
+}
+
+ssize_t write_buffer(int fd, const void *buf, size_t length)
+{
+ return _write_buffer(fd, buf, length, NULL);
+}
+
+ssize_t write_buffer_intr(int fd, const void *buf, size_t length, volatile int *quit)
+{
+ return _write_buffer(fd, buf, length, quit);
+}
+
+ssize_t write_blockwise(int fd, size_t bsize, size_t alignment,
+ void *orig_buf, size_t length)
+{
+ void *hangover_buf = NULL, *buf = NULL;
+ size_t hangover, solid;
+ ssize_t r, ret = -1;
+
+ if (fd == -1 || !orig_buf || !bsize || !alignment)
+ return -1;
+
+ hangover = length % bsize;
+ solid = length - hangover;
+
+ if ((size_t)orig_buf & (alignment - 1)) {
+ if (posix_memalign(&buf, alignment, length))
+ return -1;
+ memcpy(buf, orig_buf, length);
+ } else
+ buf = orig_buf;
+
+ if (solid) {
+ r = write_buffer(fd, buf, solid);
+ if (r < 0 || r != (ssize_t)solid)
+ goto out;
+ }
+
+ if (hangover) {
+ if (posix_memalign(&hangover_buf, alignment, bsize))
+ goto out;
+ memset(hangover_buf, 0, bsize);
+
+ r = read_buffer(fd, hangover_buf, bsize);
+ if (r < 0)
+ goto out;
+
+ if (lseek(fd, -(off_t)r, SEEK_CUR) < 0)
+ goto out;
+
+ memcpy(hangover_buf, (char*)buf + solid, hangover);
+
+ r = write_buffer(fd, hangover_buf, bsize);
+ if (r < 0 || r < (ssize_t)hangover)
+ goto out;
+ }
+ ret = length;
+out:
+ free(hangover_buf);
+ if (buf != orig_buf)
+ free(buf);
+ return ret;
+}
+
+ssize_t read_blockwise(int fd, size_t bsize, size_t alignment,
+ void *orig_buf, size_t length)
+{
+ void *hangover_buf = NULL, *buf = NULL;
+ size_t hangover, solid;
+ ssize_t r, ret = -1;
+
+ if (fd == -1 || !orig_buf || !bsize || !alignment)
+ return -1;
+
+ hangover = length % bsize;
+ solid = length - hangover;
+
+ if ((size_t)orig_buf & (alignment - 1)) {
+ if (posix_memalign(&buf, alignment, length))
+ return -1;
+ } else
+ buf = orig_buf;
+
+ r = read_buffer(fd, buf, solid);
+ if (r < 0 || r != (ssize_t)solid)
+ goto out;
+
+ if (hangover) {
+ if (posix_memalign(&hangover_buf, alignment, bsize))
+ goto out;
+ r = read_buffer(fd, hangover_buf, bsize);
+ if (r < 0 || r < (ssize_t)hangover)
+ goto out;
+
+ memcpy((char *)buf + solid, hangover_buf, hangover);
+ }
+ ret = length;
+out:
+ free(hangover_buf);
+ if (buf != orig_buf) {
+ if (ret != -1)
+ memcpy(orig_buf, buf, length);
+ free(buf);
+ }
+ return ret;
+}
+
+/*
+ * Combines llseek with blockwise write. write_blockwise can already deal with short writes
+ * but we also need a function to deal with short writes at the start. But this information
+ * is implicitly included in the read/write offset, which can not be set to non-aligned
+ * boundaries. Hence, we combine llseek with write.
+ */
+ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment,
+ void *buf, size_t length, off_t offset)
+{
+ void *frontPadBuf = NULL;
+ size_t frontHang, innerCount = 0;
+ ssize_t r, ret = -1;
+
+ if (fd == -1 || !buf || !bsize || !alignment)
+ return -1;
+
+ if (offset < 0)
+ offset = lseek(fd, offset, SEEK_END);
+
+ if (offset < 0)
+ return -1;
+
+ frontHang = offset % bsize;
+
+ if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
+ return -1;
+
+ if (frontHang && length) {
+ if (posix_memalign(&frontPadBuf, alignment, bsize))
+ return -1;
+
+ innerCount = bsize - frontHang;
+ if (innerCount > length)
+ innerCount = length;
+
+ r = read_buffer(fd, frontPadBuf, bsize);
+ if (r < 0 || r < (ssize_t)(frontHang + innerCount))
+ goto out;
+
+ memcpy((char*)frontPadBuf + frontHang, buf, innerCount);
+
+ if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
+ goto out;
+
+ r = write_buffer(fd, frontPadBuf, bsize);
+ if (r < 0 || r != (ssize_t)bsize)
+ goto out;
+
+ buf = (char*)buf + innerCount;
+ length -= innerCount;
+ }
+
+ ret = length ? write_blockwise(fd, bsize, alignment, buf, length) : 0;
+ if (ret >= 0)
+ ret += innerCount;
+out:
+ free(frontPadBuf);
+ return ret;
+}
+
+ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment,
+ void *buf, size_t length, off_t offset)
+{
+ void *frontPadBuf = NULL;
+ size_t frontHang, innerCount = 0;
+ ssize_t r, ret = -1;
+
+ if (fd == -1 || !buf || bsize <= 0)
+ return -1;
+
+ if (offset < 0)
+ offset = lseek(fd, offset, SEEK_END);
+
+ if (offset < 0)
+ return -1;
+
+ frontHang = offset % bsize;
+
+ if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
+ return -1;
+
+ if (frontHang && length) {
+ if (posix_memalign(&frontPadBuf, alignment, bsize))
+ return -1;
+
+ innerCount = bsize - frontHang;
+ if (innerCount > length)
+ innerCount = length;
+
+ r = read_buffer(fd, frontPadBuf, bsize);
+ if (r < 0 || r < (ssize_t)(frontHang + innerCount))
+ goto out;
+
+ memcpy(buf, (char*)frontPadBuf + frontHang, innerCount);
+
+ buf = (char*)buf + innerCount;
+ length -= innerCount;
+ }
+
+ ret = read_blockwise(fd, bsize, alignment, buf, length);
+ if (ret >= 0)
+ ret += innerCount;
+out:
+ free(frontPadBuf);
+ return ret;
+}
diff --git a/lib/utils_io.h b/lib/utils_io.h
new file mode 100644
index 0000000..f8b3f00
--- /dev/null
+++ b/lib/utils_io.h
@@ -0,0 +1,43 @@
+/*
+ * utils - miscellaneous I/O utilities for cryptsetup
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _CRYPTSETUP_UTILS_IO_H
+#define _CRYPTSETUP_UTILS_IO_H
+
+#include <stddef.h>
+#include <sys/types.h>
+
+ssize_t read_buffer(int fd, void *buf, size_t length);
+ssize_t read_buffer_intr(int fd, void *buf, size_t length, volatile int *quit);
+ssize_t write_buffer(int fd, const void *buf, size_t length);
+ssize_t write_buffer_intr(int fd, const void *buf, size_t length, volatile int *quit);
+ssize_t write_blockwise(int fd, size_t bsize, size_t alignment,
+ void *orig_buf, size_t length);
+ssize_t read_blockwise(int fd, size_t bsize, size_t alignment,
+ void *orig_buf, size_t length);
+ssize_t write_lseek_blockwise(int fd, size_t bsize, size_t alignment,
+ void *buf, size_t length, off_t offset);
+ssize_t read_lseek_blockwise(int fd, size_t bsize, size_t alignment,
+ void *buf, size_t length, off_t offset);
+
+#endif
diff --git a/lib/utils_keyring.c b/lib/utils_keyring.c
new file mode 100644
index 0000000..a0c4db1
--- /dev/null
+++ b/lib/utils_keyring.c
@@ -0,0 +1,237 @@
+/*
+ * kernel keyring utilities
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#include "libcryptsetup.h"
+#include "libcryptsetup_macros.h"
+#include "utils_keyring.h"
+
+#ifndef HAVE_KEY_SERIAL_T
+#define HAVE_KEY_SERIAL_T
+typedef int32_t key_serial_t;
+#endif
+
+#ifdef KERNEL_KEYRING
+
+static const struct {
+ key_type_t type;
+ const char *type_name;
+} key_types[] = {
+ { LOGON_KEY, "logon" },
+ { USER_KEY, "user" },
+};
+
+#include <linux/keyctl.h>
+
+/* request_key */
+static key_serial_t request_key(const char *type,
+ const char *description,
+ const char *callout_info,
+ key_serial_t keyring)
+{
+ return syscall(__NR_request_key, type, description, callout_info, keyring);
+}
+
+/* add_key */
+static key_serial_t add_key(const char *type,
+ const char *description,
+ const void *payload,
+ size_t plen,
+ key_serial_t keyring)
+{
+ return syscall(__NR_add_key, type, description, payload, plen, keyring);
+}
+
+/* keyctl_read */
+static long keyctl_read(key_serial_t key, char *buffer, size_t buflen)
+{
+ return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen);
+}
+
+/* keyctl_revoke */
+static long keyctl_revoke(key_serial_t key)
+{
+ return syscall(__NR_keyctl, KEYCTL_REVOKE, key);
+}
+
+/* keyctl_unlink */
+static long keyctl_unlink(key_serial_t key, key_serial_t keyring)
+{
+ return syscall(__NR_keyctl, KEYCTL_UNLINK, key, keyring);
+}
+#endif
+
+int keyring_check(void)
+{
+#ifdef KERNEL_KEYRING
+ /* logon type key descriptions must be in format "prefix:description" */
+ return syscall(__NR_request_key, "logon", "dummy", NULL, 0) == -1l && errno != ENOSYS;
+#else
+ return 0;
+#endif
+}
+
+int keyring_add_key_in_thread_keyring(key_type_t ktype, const char *key_desc, const void *key, size_t key_size)
+{
+#ifdef KERNEL_KEYRING
+ key_serial_t kid;
+ const char *type_name = key_type_name(ktype);
+
+ if (!type_name || !key_desc)
+ return -EINVAL;
+
+ kid = add_key(type_name, key_desc, key, key_size, KEY_SPEC_THREAD_KEYRING);
+ if (kid < 0)
+ return -errno;
+
+ return 0;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+/* currently used in client utilities only */
+int keyring_add_key_in_user_keyring(key_type_t ktype, const char *key_desc, const void *key, size_t key_size)
+{
+#ifdef KERNEL_KEYRING
+ const char *type_name = key_type_name(ktype);
+ key_serial_t kid;
+
+ if (!type_name || !key_desc)
+ return -EINVAL;
+
+ kid = add_key(type_name, key_desc, key, key_size, KEY_SPEC_USER_KEYRING);
+ if (kid < 0)
+ return -errno;
+
+ return 0;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+/* alias for the same code */
+int keyring_get_key(const char *key_desc,
+ char **key,
+ size_t *key_size)
+{
+ return keyring_get_passphrase(key_desc, key, key_size);
+}
+
+int keyring_get_passphrase(const char *key_desc,
+ char **passphrase,
+ size_t *passphrase_len)
+{
+#ifdef KERNEL_KEYRING
+ int err;
+ key_serial_t kid;
+ long ret;
+ char *buf = NULL;
+ size_t len = 0;
+
+ do
+ kid = request_key(key_type_name(USER_KEY), key_desc, NULL, 0);
+ while (kid < 0 && errno == EINTR);
+
+ if (kid < 0)
+ return -errno;
+
+ /* just get payload size */
+ ret = keyctl_read(kid, NULL, 0);
+ if (ret > 0) {
+ len = ret;
+ buf = crypt_safe_alloc(len);
+ if (!buf)
+ return -ENOMEM;
+
+ /* retrieve actual payload data */
+ ret = keyctl_read(kid, buf, len);
+ }
+
+ if (ret < 0) {
+ err = errno;
+ crypt_safe_free(buf);
+ return -err;
+ }
+
+ *passphrase = buf;
+ *passphrase_len = len;
+
+ return 0;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static int keyring_revoke_and_unlink_key_type(const char *type_name, const char *key_desc)
+{
+#ifdef KERNEL_KEYRING
+ key_serial_t kid;
+
+ if (!type_name || !key_desc)
+ return -EINVAL;
+
+ do
+ kid = request_key(type_name, key_desc, NULL, 0);
+ while (kid < 0 && errno == EINTR);
+
+ if (kid < 0)
+ return 0;
+
+ if (keyctl_revoke(kid))
+ return -errno;
+
+ /*
+ * best effort only. the key could have been linked
+ * in some other keyring and its payload is now
+ * revoked anyway.
+ */
+ keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING);
+ keyctl_unlink(kid, KEY_SPEC_PROCESS_KEYRING);
+ keyctl_unlink(kid, KEY_SPEC_USER_KEYRING);
+
+ return 0;
+#else
+ return -ENOTSUP;
+#endif
+}
+
+const char *key_type_name(key_type_t type)
+{
+#ifdef KERNEL_KEYRING
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(key_types); i++)
+ if (type == key_types[i].type)
+ return key_types[i].type_name;
+#endif
+ return NULL;
+}
+
+int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc)
+{
+ return keyring_revoke_and_unlink_key_type(key_type_name(ktype), key_desc);
+}
diff --git a/lib/utils_keyring.h b/lib/utils_keyring.h
new file mode 100644
index 0000000..0248862
--- /dev/null
+++ b/lib/utils_keyring.h
@@ -0,0 +1,55 @@
+/*
+ * kernel keyring syscall wrappers
+ *
+ * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _UTILS_KEYRING
+#define _UTILS_KEYRING
+
+#include <stddef.h>
+
+typedef enum { LOGON_KEY = 0, USER_KEY } key_type_t;
+
+const char *key_type_name(key_type_t ktype);
+
+int keyring_check(void);
+
+int keyring_get_key(const char *key_desc,
+ char **key,
+ size_t *key_size);
+
+int keyring_get_passphrase(const char *key_desc,
+ char **passphrase,
+ size_t *passphrase_len);
+
+int keyring_add_key_in_thread_keyring(
+ key_type_t ktype,
+ const char *key_desc,
+ const void *key,
+ size_t key_size);
+
+int keyring_add_key_in_user_keyring(
+ key_type_t ktype,
+ const char *key_desc,
+ const void *key,
+ size_t key_size);
+
+int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc);
+
+#endif
diff --git a/lib/utils_loop.c b/lib/utils_loop.c
new file mode 100644
index 0000000..9b31603
--- /dev/null
+++ b/lib/utils_loop.c
@@ -0,0 +1,331 @@
+/*
+ * loopback block device utilities
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+#include <linux/types.h>
+#include <linux/loop.h>
+
+#include "utils_loop.h"
+#include "libcryptsetup_macros.h"
+
+#define LOOP_DEV_MAJOR 7
+
+#ifndef LO_FLAGS_AUTOCLEAR
+#define LO_FLAGS_AUTOCLEAR 4
+#endif
+
+#ifndef LOOP_CTL_GET_FREE
+#define LOOP_CTL_GET_FREE 0x4C82
+#endif
+
+#ifndef LOOP_SET_CAPACITY
+#define LOOP_SET_CAPACITY 0x4C07
+#endif
+
+#ifndef LOOP_SET_BLOCK_SIZE
+#define LOOP_SET_BLOCK_SIZE 0x4C09
+#endif
+
+#ifndef LOOP_CONFIGURE
+#define LOOP_CONFIGURE 0x4C0A
+struct loop_config {
+ __u32 fd;
+ __u32 block_size;
+ struct loop_info64 info;
+ __u64 __reserved[8];
+};
+#endif
+
+static char *crypt_loop_get_device_old(void)
+{
+ char dev[64];
+ int i, loop_fd;
+ struct loop_info64 lo64 = {0};
+
+ for (i = 0; i < 256; i++) {
+ sprintf(dev, "/dev/loop%d", i);
+
+ loop_fd = open(dev, O_RDONLY);
+ if (loop_fd < 0)
+ return NULL;
+
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) &&
+ errno == ENXIO) {
+ close(loop_fd);
+ return strdup(dev);
+ }
+ close(loop_fd);
+ }
+
+ return NULL;
+}
+
+static char *crypt_loop_get_device(void)
+{
+ char dev[64];
+ int i, loop_fd;
+ struct stat st;
+
+ loop_fd = open("/dev/loop-control", O_RDONLY);
+ if (loop_fd < 0)
+ return crypt_loop_get_device_old();
+
+ i = ioctl(loop_fd, LOOP_CTL_GET_FREE);
+ if (i < 0) {
+ close(loop_fd);
+ return NULL;
+ }
+ close(loop_fd);
+
+ if (sprintf(dev, "/dev/loop%d", i) < 0)
+ return NULL;
+
+ if (stat(dev, &st) || !S_ISBLK(st.st_mode))
+ return NULL;
+
+ return strdup(dev);
+}
+
+int crypt_loop_attach(char **loop, const char *file, int offset,
+ int autoclear, int *readonly, size_t blocksize)
+{
+ struct loop_config config = {0};
+ char *lo_file_name;
+ int loop_fd = -1, file_fd = -1, r = 1;
+ int fallback = 0;
+
+ *loop = NULL;
+
+ file_fd = open(file, (*readonly ? O_RDONLY : O_RDWR) | O_EXCL);
+ if (file_fd < 0 && (errno == EROFS || errno == EACCES) && !*readonly) {
+ *readonly = 1;
+ file_fd = open(file, O_RDONLY | O_EXCL);
+ }
+ if (file_fd < 0)
+ goto out;
+
+ config.fd = file_fd;
+
+ lo_file_name = (char*)config.info.lo_file_name;
+ lo_file_name[LO_NAME_SIZE-1] = '\0';
+ strncpy(lo_file_name, file, LO_NAME_SIZE-1);
+ config.info.lo_offset = offset;
+ if (autoclear)
+ config.info.lo_flags |= LO_FLAGS_AUTOCLEAR;
+ if (blocksize > SECTOR_SIZE)
+ config.block_size = blocksize;
+
+ while (loop_fd < 0) {
+ *loop = crypt_loop_get_device();
+ if (!*loop)
+ goto out;
+
+ loop_fd = open(*loop, *readonly ? O_RDONLY : O_RDWR);
+ if (loop_fd < 0)
+ goto out;
+ if (ioctl(loop_fd, LOOP_CONFIGURE, &config) < 0) {
+ if (errno == EINVAL || errno == ENOTTY) {
+ free(*loop);
+ *loop = NULL;
+
+ close(loop_fd);
+ loop_fd = -1;
+
+ /* kernel doesn't support LOOP_CONFIGURE */
+ fallback = 1;
+ break;
+ }
+ if (errno != EBUSY)
+ goto out;
+ free(*loop);
+ *loop = NULL;
+
+ close(loop_fd);
+ loop_fd = -1;
+ }
+ }
+
+ if (fallback) {
+ while (loop_fd < 0) {
+ *loop = crypt_loop_get_device();
+ if (!*loop)
+ goto out;
+
+ loop_fd = open(*loop, *readonly ? O_RDONLY : O_RDWR);
+ if (loop_fd < 0)
+ goto out;
+ if (ioctl(loop_fd, LOOP_SET_FD, file_fd) < 0) {
+ if (errno != EBUSY)
+ goto out;
+ free(*loop);
+ *loop = NULL;
+
+ close(loop_fd);
+ loop_fd = -1;
+ }
+ }
+
+ if (blocksize > SECTOR_SIZE)
+ (void)ioctl(loop_fd, LOOP_SET_BLOCK_SIZE, (unsigned long)blocksize);
+
+ if (ioctl(loop_fd, LOOP_SET_STATUS64, &config.info) < 0) {
+ (void)ioctl(loop_fd, LOOP_CLR_FD, 0);
+ goto out;
+ }
+ }
+
+ /* Verify that autoclear is really set */
+ if (autoclear) {
+ memset(&config.info, 0, sizeof(config.info));
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &config.info) < 0 ||
+ !(config.info.lo_flags & LO_FLAGS_AUTOCLEAR)) {
+ (void)ioctl(loop_fd, LOOP_CLR_FD, 0);
+ goto out;
+ }
+ }
+
+ r = 0;
+out:
+ if (r && loop_fd >= 0)
+ close(loop_fd);
+ if (file_fd >= 0)
+ close(file_fd);
+ if (r && *loop) {
+ free(*loop);
+ *loop = NULL;
+ }
+ return r ? -1 : loop_fd;
+}
+
+int crypt_loop_detach(const char *loop)
+{
+ int loop_fd = -1, r = 1;
+
+ loop_fd = open(loop, O_RDONLY);
+ if (loop_fd < 0)
+ return 1;
+
+ if (!ioctl(loop_fd, LOOP_CLR_FD, 0))
+ r = 0;
+
+ close(loop_fd);
+ return r;
+}
+
+int crypt_loop_resize(const char *loop)
+{
+ int loop_fd = -1, r = 1;
+
+ loop_fd = open(loop, O_RDONLY);
+ if (loop_fd < 0)
+ return 1;
+
+ if (!ioctl(loop_fd, LOOP_SET_CAPACITY, 0))
+ r = 0;
+
+ close(loop_fd);
+ return r;
+}
+
+static char *_ioctl_backing_file(const char *loop)
+{
+ struct loop_info64 lo64 = {0};
+ int loop_fd;
+
+ loop_fd = open(loop, O_RDONLY);
+ if (loop_fd < 0)
+ return NULL;
+
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) < 0) {
+ close(loop_fd);
+ return NULL;
+ }
+
+ lo64.lo_file_name[LO_NAME_SIZE-2] = '*';
+ lo64.lo_file_name[LO_NAME_SIZE-1] = 0;
+
+ close(loop_fd);
+
+ return strdup((char*)lo64.lo_file_name);
+}
+
+static char *_sysfs_backing_file(const char *loop)
+{
+ struct stat st;
+ char buf[PATH_MAX];
+ size_t len;
+ int fd;
+
+ if (stat(loop, &st) || !S_ISBLK(st.st_mode))
+ return NULL;
+
+ if (snprintf(buf, sizeof(buf), "/sys/dev/block/%d:%d/loop/backing_file",
+ major(st.st_rdev), minor(st.st_rdev)) < 0)
+ return NULL;
+
+ fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ len = read(fd, buf, PATH_MAX);
+ close(fd);
+ if (len < 2)
+ return NULL;
+
+ buf[len - 1] = '\0';
+ return strdup(buf);
+}
+
+char *crypt_loop_backing_file(const char *loop)
+{
+ char *bf;
+
+ if (!crypt_loop_device(loop))
+ return NULL;
+
+ bf = _sysfs_backing_file(loop);
+ return bf ?: _ioctl_backing_file(loop);
+}
+
+int crypt_loop_device(const char *loop)
+{
+ struct stat st;
+
+ if (!loop)
+ return 0;
+
+ if (stat(loop, &st) || !S_ISBLK(st.st_mode) ||
+ major(st.st_rdev) != LOOP_DEV_MAJOR)
+ return 0;
+
+ return 1;
+}
diff --git a/lib/utils_loop.h b/lib/utils_loop.h
new file mode 100644
index 0000000..c1f6356
--- /dev/null
+++ b/lib/utils_loop.h
@@ -0,0 +1,34 @@
+/*
+ * loopback block device utilities
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _UTILS_LOOP_H
+#define _UTILS_LOOP_H
+
+/* loopback device helpers */
+
+char *crypt_loop_backing_file(const char *loop);
+int crypt_loop_device(const char *loop);
+int crypt_loop_attach(char **loop, const char *file, int offset,
+ int autoclear, int *readonly, size_t blocksize);
+int crypt_loop_detach(const char *loop);
+int crypt_loop_resize(const char *loop);
+
+#endif /* _UTILS_LOOP_H */
diff --git a/lib/utils_pbkdf.c b/lib/utils_pbkdf.c
new file mode 100644
index 0000000..4d7e18d
--- /dev/null
+++ b/lib/utils_pbkdf.c
@@ -0,0 +1,333 @@
+/*
+ * utils_pbkdf - PBKDF settings for libcryptsetup
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "internal.h"
+
+const struct crypt_pbkdf_type default_pbkdf2 = {
+ .type = CRYPT_KDF_PBKDF2,
+ .hash = DEFAULT_LUKS1_HASH,
+ .time_ms = DEFAULT_LUKS1_ITER_TIME
+};
+
+const struct crypt_pbkdf_type default_argon2i = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = DEFAULT_LUKS1_HASH,
+ .time_ms = DEFAULT_LUKS2_ITER_TIME,
+ .max_memory_kb = DEFAULT_LUKS2_MEMORY_KB,
+ .parallel_threads = DEFAULT_LUKS2_PARALLEL_THREADS
+};
+
+const struct crypt_pbkdf_type default_argon2id = {
+ .type = CRYPT_KDF_ARGON2ID,
+ .hash = DEFAULT_LUKS1_HASH,
+ .time_ms = DEFAULT_LUKS2_ITER_TIME,
+ .max_memory_kb = DEFAULT_LUKS2_MEMORY_KB,
+ .parallel_threads = DEFAULT_LUKS2_PARALLEL_THREADS
+};
+
+const struct crypt_pbkdf_type *crypt_get_pbkdf_type_params(const char *pbkdf_type)
+{
+ if (!pbkdf_type)
+ return NULL;
+
+ if (!strcmp(pbkdf_type, CRYPT_KDF_PBKDF2))
+ return &default_pbkdf2;
+ else if (!strcmp(pbkdf_type, CRYPT_KDF_ARGON2I))
+ return &default_argon2i;
+ else if (!strcmp(pbkdf_type, CRYPT_KDF_ARGON2ID))
+ return &default_argon2id;
+
+ return NULL;
+}
+
+static uint32_t adjusted_phys_memory(void)
+{
+ uint64_t memory_kb = crypt_getphysmemory_kb();
+
+ /* Ignore bogus value */
+ if (memory_kb < (128 * 1024) || memory_kb > UINT32_MAX)
+ return DEFAULT_LUKS2_MEMORY_KB;
+
+ /*
+ * Never use more than half of physical memory.
+ * OOM killer is too clever...
+ */
+ memory_kb /= 2;
+
+ return memory_kb;
+}
+
+/*
+ * PBKDF configuration interface
+ */
+int verify_pbkdf_params(struct crypt_device *cd,
+ const struct crypt_pbkdf_type *pbkdf)
+{
+ struct crypt_pbkdf_limits pbkdf_limits;
+ const char *pbkdf_type;
+ int r;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ if (!pbkdf || !pbkdf->type ||
+ (!pbkdf->hash && !strcmp(pbkdf->type, "pbkdf2")))
+ return -EINVAL;
+
+ if (!pbkdf->time_ms && !(pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK)) {
+ log_err(cd, _("Requested PBKDF target time cannot be zero."));
+ return -EINVAL;
+ }
+
+ r = crypt_parse_pbkdf(pbkdf->type, &pbkdf_type);
+ if (r < 0) {
+ log_err(cd, _("Unknown PBKDF type %s."), pbkdf->type);
+ return r;
+ }
+
+ if (pbkdf->hash && crypt_hash_size(pbkdf->hash) < 0) {
+ log_err(cd, _("Requested hash %s is not supported."), pbkdf->hash);
+ return -EINVAL;
+ }
+
+ r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
+ if (r < 0)
+ return r;
+
+ if (crypt_get_type(cd) &&
+ !strcmp(crypt_get_type(cd), CRYPT_LUKS1) &&
+ strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) {
+ log_err(cd, _("Requested PBKDF type is not supported for LUKS1."));
+ return -EINVAL;
+ }
+
+ if (!strcmp(pbkdf_type, CRYPT_KDF_PBKDF2)) {
+ if (pbkdf->max_memory_kb || pbkdf->parallel_threads) {
+ log_err(cd, _("PBKDF max memory or parallel threads must not be set with pbkdf2."));
+ return -EINVAL;
+ }
+ if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK &&
+ pbkdf->iterations < pbkdf_limits.min_iterations) {
+ log_err(cd, _("Forced iteration count is too low for %s (minimum is %u)."),
+ pbkdf_type, pbkdf_limits.min_iterations);
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ /* TODO: properly define minimal iterations and also minimal memory values */
+ if (pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK) {
+ if (pbkdf->iterations < pbkdf_limits.min_iterations) {
+ log_err(cd, _("Forced iteration count is too low for %s (minimum is %u)."),
+ pbkdf_type, pbkdf_limits.min_iterations);
+ r = -EINVAL;
+ }
+ if (pbkdf->max_memory_kb < pbkdf_limits.min_memory) {
+ log_err(cd, _("Forced memory cost is too low for %s (minimum is %u kilobytes)."),
+ pbkdf_type, pbkdf_limits.min_memory);
+ r = -EINVAL;
+ }
+ }
+
+ if (pbkdf->max_memory_kb > pbkdf_limits.max_memory) {
+ log_err(cd, _("Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."),
+ pbkdf_limits.max_memory);
+ r = -EINVAL;
+ }
+ if (!pbkdf->max_memory_kb) {
+ log_err(cd, _("Requested maximum PBKDF memory cannot be zero."));
+ r = -EINVAL;
+ }
+ if (!pbkdf->parallel_threads) {
+ log_err(cd, _("Requested PBKDF parallel threads cannot be zero."));
+ r = -EINVAL;
+ }
+
+ return r;
+}
+
+int init_pbkdf_type(struct crypt_device *cd,
+ const struct crypt_pbkdf_type *pbkdf,
+ const char *dev_type)
+{
+ struct crypt_pbkdf_type *cd_pbkdf = crypt_get_pbkdf(cd);
+ struct crypt_pbkdf_limits pbkdf_limits;
+ const char *hash, *type;
+ unsigned cpus;
+ uint32_t old_flags, memory_kb;
+ int r;
+
+ if (crypt_fips_mode()) {
+ if (pbkdf && strcmp(pbkdf->type, CRYPT_KDF_PBKDF2)) {
+ log_err(cd, _("Only PBKDF2 is supported in FIPS mode."));
+ return -EINVAL;
+ }
+ if (!pbkdf)
+ pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2);
+ }
+
+ if (!pbkdf && dev_type && !strcmp(dev_type, CRYPT_LUKS2))
+ pbkdf = crypt_get_pbkdf_type_params(DEFAULT_LUKS2_PBKDF);
+ else if (!pbkdf)
+ pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2);
+
+ r = verify_pbkdf_params(cd, pbkdf);
+ if (r)
+ return r;
+
+ r = crypt_pbkdf_get_limits(pbkdf->type, &pbkdf_limits);
+ if (r < 0)
+ return r;
+
+ type = strdup(pbkdf->type);
+ hash = pbkdf->hash ? strdup(pbkdf->hash) : NULL;
+
+ if (!type || (!hash && pbkdf->hash)) {
+ free(CONST_CAST(void*)type);
+ free(CONST_CAST(void*)hash);
+ return -ENOMEM;
+ }
+
+ free(CONST_CAST(void*)cd_pbkdf->type);
+ free(CONST_CAST(void*)cd_pbkdf->hash);
+ cd_pbkdf->type = type;
+ cd_pbkdf->hash = hash;
+
+ old_flags = cd_pbkdf->flags;
+ cd_pbkdf->flags = pbkdf->flags;
+
+ /* Reset iteration count so benchmark must run again. */
+ if (cd_pbkdf->flags & CRYPT_PBKDF_NO_BENCHMARK)
+ cd_pbkdf->iterations = pbkdf->iterations;
+ else
+ cd_pbkdf->iterations = 0;
+
+ if (old_flags & CRYPT_PBKDF_ITER_TIME_SET)
+ cd_pbkdf->flags |= CRYPT_PBKDF_ITER_TIME_SET;
+ else
+ cd_pbkdf->time_ms = pbkdf->time_ms;
+
+ cd_pbkdf->max_memory_kb = pbkdf->max_memory_kb;
+ cd_pbkdf->parallel_threads = pbkdf->parallel_threads;
+
+ if (cd_pbkdf->parallel_threads > pbkdf_limits.max_parallel) {
+ log_dbg(cd, "Maximum PBKDF threads is %d (requested %d).",
+ pbkdf_limits.max_parallel, cd_pbkdf->parallel_threads);
+ cd_pbkdf->parallel_threads = pbkdf_limits.max_parallel;
+ }
+
+ if (cd_pbkdf->parallel_threads) {
+ cpus = crypt_cpusonline();
+ if (cd_pbkdf->parallel_threads > cpus) {
+ log_dbg(cd, "Only %u active CPUs detected, "
+ "PBKDF threads decreased from %d to %d.",
+ cpus, cd_pbkdf->parallel_threads, cpus);
+ cd_pbkdf->parallel_threads = cpus;
+ }
+ }
+
+ if (cd_pbkdf->max_memory_kb) {
+ memory_kb = adjusted_phys_memory();
+ if (cd_pbkdf->max_memory_kb > memory_kb) {
+ log_dbg(cd, "Not enough physical memory detected, "
+ "PBKDF max memory decreased from %dkB to %dkB.",
+ cd_pbkdf->max_memory_kb, memory_kb);
+ cd_pbkdf->max_memory_kb = memory_kb;
+ }
+ }
+
+ if (!strcmp(pbkdf->type, CRYPT_KDF_PBKDF2))
+ log_dbg(cd, "PBKDF %s-%s, time_ms %u (iterations %u).",
+ cd_pbkdf->type, cd_pbkdf->hash, cd_pbkdf->time_ms, cd_pbkdf->iterations);
+ else
+ log_dbg(cd, "PBKDF %s, time_ms %u (iterations %u), max_memory_kb %u, parallel_threads %u.",
+ cd_pbkdf->type, cd_pbkdf->time_ms, cd_pbkdf->iterations,
+ cd_pbkdf->max_memory_kb, cd_pbkdf->parallel_threads);
+
+ return 0;
+}
+
+/* Libcryptsetup API */
+
+int crypt_set_pbkdf_type(struct crypt_device *cd, const struct crypt_pbkdf_type *pbkdf)
+{
+ if (!cd)
+ return -EINVAL;
+
+ if (!pbkdf)
+ log_dbg(cd, "Resetting pbkdf type to default");
+
+ crypt_get_pbkdf(cd)->flags = 0;
+
+ return init_pbkdf_type(cd, pbkdf, crypt_get_type(cd));
+}
+
+const struct crypt_pbkdf_type *crypt_get_pbkdf_type(struct crypt_device *cd)
+{
+ if (!cd)
+ return NULL;
+
+ return crypt_get_pbkdf(cd)->type ? crypt_get_pbkdf(cd) : NULL;
+}
+
+const struct crypt_pbkdf_type *crypt_get_pbkdf_default(const char *type)
+{
+ if (!type)
+ return NULL;
+
+ if (!strcmp(type, CRYPT_LUKS1) || crypt_fips_mode())
+ return crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2);
+ else if (!strcmp(type, CRYPT_LUKS2))
+ return crypt_get_pbkdf_type_params(DEFAULT_LUKS2_PBKDF);
+
+ return NULL;
+}
+
+void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_ms)
+{
+ struct crypt_pbkdf_type *pbkdf;
+ uint32_t old_time_ms;
+
+ if (!cd || iteration_time_ms > UINT32_MAX)
+ return;
+
+ pbkdf = crypt_get_pbkdf(cd);
+ old_time_ms = pbkdf->time_ms;
+ pbkdf->time_ms = (uint32_t)iteration_time_ms;
+
+ if (pbkdf->type && verify_pbkdf_params(cd, pbkdf)) {
+ pbkdf->time_ms = old_time_ms;
+ log_dbg(cd, "Invalid iteration time.");
+ return;
+ }
+
+ pbkdf->flags |= CRYPT_PBKDF_ITER_TIME_SET;
+
+ /* iterations must be benchmarked now */
+ pbkdf->flags &= ~(CRYPT_PBKDF_NO_BENCHMARK);
+ pbkdf->iterations = 0;
+
+ log_dbg(cd, "Iteration time set to %" PRIu64 " milliseconds.", iteration_time_ms);
+}
diff --git a/lib/utils_safe_memory.c b/lib/utils_safe_memory.c
new file mode 100644
index 0000000..b161369
--- /dev/null
+++ b/lib/utils_safe_memory.c
@@ -0,0 +1,122 @@
+/*
+ * utils_safe_memory - safe memory helpers
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/mman.h>
+#include "libcryptsetup.h"
+
+struct safe_allocation {
+ size_t size;
+ bool locked;
+ char data[0] __attribute__((aligned(8)));
+};
+#define OVERHEAD offsetof(struct safe_allocation, data)
+
+/*
+ * Replacement for memset(s, 0, n) on stack that can be optimized out
+ * Also used in safe allocations for explicit memory wipe.
+ */
+void crypt_safe_memzero(void *data, size_t size)
+{
+ if (!data)
+ return;
+
+#ifdef HAVE_EXPLICIT_BZERO
+ explicit_bzero(data, size);
+#else
+ volatile uint8_t *p = (volatile uint8_t *)data;
+
+ while(size--)
+ *p++ = 0;
+#endif
+}
+
+/* safe allocations */
+void *crypt_safe_alloc(size_t size)
+{
+ struct safe_allocation *alloc;
+
+ if (!size || size > (SIZE_MAX - OVERHEAD))
+ return NULL;
+
+ alloc = malloc(size + OVERHEAD);
+ if (!alloc)
+ return NULL;
+
+ crypt_safe_memzero(alloc, size + OVERHEAD);
+ alloc->size = size;
+
+ /* Ignore failure if it is over limit. */
+ if (!mlock(alloc, size + OVERHEAD))
+ alloc->locked = true;
+
+ /* coverity[leaked_storage] */
+ return &alloc->data;
+}
+
+void crypt_safe_free(void *data)
+{
+ struct safe_allocation *alloc;
+ volatile size_t *s;
+ void *p;
+
+ if (!data)
+ return;
+
+ p = (char *)data - OVERHEAD;
+ alloc = (struct safe_allocation *)p;
+
+ crypt_safe_memzero(data, alloc->size);
+
+ if (alloc->locked) {
+ munlock(alloc, alloc->size + OVERHEAD);
+ alloc->locked = false;
+ }
+
+ s = (volatile size_t *)&alloc->size;
+ *s = 0x55aa55aa;
+ free(alloc);
+}
+
+void *crypt_safe_realloc(void *data, size_t size)
+{
+ struct safe_allocation *alloc;
+ void *new_data;
+ void *p;
+
+ new_data = crypt_safe_alloc(size);
+
+ if (new_data && data) {
+
+ p = (char *)data - OVERHEAD;
+ alloc = (struct safe_allocation *)p;
+
+ if (size > alloc->size)
+ size = alloc->size;
+
+ memcpy(new_data, data, size);
+ }
+
+ crypt_safe_free(data);
+ return new_data;
+}
diff --git a/lib/utils_storage_wrappers.c b/lib/utils_storage_wrappers.c
new file mode 100644
index 0000000..6ff5afa
--- /dev/null
+++ b/lib/utils_storage_wrappers.c
@@ -0,0 +1,394 @@
+/*
+ * Generic wrapper for storage functions
+ * (experimental only)
+ *
+ * Copyright (C) 2018-2023 Ondrej Kozina
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "utils_storage_wrappers.h"
+#include "internal.h"
+
+struct crypt_storage_wrapper {
+ crypt_storage_wrapper_type type;
+ int dev_fd;
+ int block_size;
+ size_t mem_alignment;
+ uint64_t data_offset;
+ union {
+ struct {
+ struct crypt_storage *s;
+ uint64_t iv_start;
+ } cb;
+ struct {
+ int dmcrypt_fd;
+ char name[PATH_MAX];
+ } dm;
+ } u;
+};
+
+static int crypt_storage_backend_init(struct crypt_device *cd,
+ struct crypt_storage_wrapper *w,
+ uint64_t iv_start,
+ int sector_size,
+ const char *cipher,
+ const char *cipher_mode,
+ const struct volume_key *vk,
+ uint32_t flags)
+{
+ int r;
+ struct crypt_storage *s;
+
+ /* iv_start, sector_size */
+ r = crypt_storage_init(&s, sector_size, cipher, cipher_mode, vk->key, vk->keylength, flags & LARGE_IV);
+ if (r)
+ return r;
+
+ if ((flags & DISABLE_KCAPI) && crypt_storage_kernel_only(s)) {
+ log_dbg(cd, "Could not initialize userspace block cipher and kernel fallback is disabled.");
+ crypt_storage_destroy(s);
+ return -ENOTSUP;
+ }
+
+ w->type = USPACE;
+ w->u.cb.s = s;
+ w->u.cb.iv_start = iv_start;
+
+ return 0;
+}
+
+static int crypt_storage_dmcrypt_init(
+ struct crypt_device *cd,
+ struct crypt_storage_wrapper *cw,
+ struct device *device,
+ uint64_t device_offset,
+ uint64_t iv_start,
+ int sector_size,
+ const char *cipher_spec,
+ struct volume_key *vk,
+ int open_flags)
+{
+ static int counter = 0;
+ char path[PATH_MAX];
+ struct crypt_dm_active_device dmd = {
+ .flags = CRYPT_ACTIVATE_PRIVATE,
+ };
+ int mode, r, fd = -1;
+
+ log_dbg(cd, "Using temporary dmcrypt to access data.");
+
+ if (snprintf(cw->u.dm.name, sizeof(cw->u.dm.name), "temporary-cryptsetup-%d-%d", getpid(), counter++) < 0)
+ return -ENOMEM;
+ if (snprintf(path, sizeof(path), "%s/%s", dm_get_dir(), cw->u.dm.name) < 0)
+ return -ENOMEM;
+
+ r = device_block_adjust(cd, device, DEV_OK,
+ device_offset, &dmd.size, &dmd.flags);
+ if (r < 0) {
+ log_err(cd, _("Device %s does not exist or access denied."),
+ device_path(device));
+ return -EIO;
+ }
+
+ mode = open_flags | O_DIRECT;
+ if (dmd.flags & CRYPT_ACTIVATE_READONLY)
+ mode = (open_flags & ~O_ACCMODE) | O_RDONLY;
+
+ if (vk->key_description)
+ dmd.flags |= CRYPT_ACTIVATE_KEYRING_KEY;
+
+ r = dm_crypt_target_set(&dmd.segment, 0, dmd.size,
+ device,
+ vk,
+ cipher_spec,
+ iv_start,
+ device_offset,
+ NULL,
+ 0,
+ sector_size);
+ if (r)
+ return r;
+
+ r = dm_create_device(cd, cw->u.dm.name, "TEMP", &dmd);
+ if (r < 0) {
+ if (r != -EACCES && r != -ENOTSUP)
+ log_dbg(cd, "error hint would be nice");
+ r = -EIO;
+ }
+
+ dm_targets_free(cd, &dmd);
+
+ if (r)
+ return r;
+
+ fd = open(path, mode);
+ if (fd < 0) {
+ log_dbg(cd, "Failed to open %s", path);
+ dm_remove_device(cd, cw->u.dm.name, CRYPT_DEACTIVATE_FORCE);
+ return -EINVAL;
+ }
+
+ cw->type = DMCRYPT;
+ cw->u.dm.dmcrypt_fd = fd;
+
+ return 0;
+}
+
+int crypt_storage_wrapper_init(struct crypt_device *cd,
+ struct crypt_storage_wrapper **cw,
+ struct device *device,
+ uint64_t data_offset,
+ uint64_t iv_start,
+ int sector_size,
+ const char *cipher,
+ struct volume_key *vk,
+ uint32_t flags)
+{
+ int open_flags, r;
+ char _cipher[MAX_CIPHER_LEN], mode[MAX_CIPHER_LEN];
+ struct crypt_storage_wrapper *w;
+
+ /* device-mapper restrictions */
+ if (data_offset & ((1 << SECTOR_SHIFT) - 1))
+ return -EINVAL;
+
+ if (crypt_parse_name_and_mode(cipher, _cipher, NULL, mode))
+ return -EINVAL;
+
+ open_flags = O_CLOEXEC | ((flags & OPEN_READONLY) ? O_RDONLY : O_RDWR);
+
+ w = malloc(sizeof(*w));
+ if (!w)
+ return -ENOMEM;
+
+ memset(w, 0, sizeof(*w));
+ w->data_offset = data_offset;
+ w->mem_alignment = device_alignment(device);
+ w->block_size = device_block_size(cd, device);
+ if (!w->block_size || !w->mem_alignment) {
+ log_dbg(cd, "block size or alignment error.");
+ r = -EINVAL;
+ goto err;
+ }
+
+ w->dev_fd = device_open(cd, device, open_flags);
+ if (w->dev_fd < 0) {
+ r = -EINVAL;
+ goto err;
+ }
+
+ if (crypt_is_cipher_null(_cipher)) {
+ log_dbg(cd, "Requested cipher_null, switching to noop wrapper.");
+ w->type = NONE;
+ *cw = w;
+ return 0;
+ }
+
+ if (!vk) {
+ log_dbg(cd, "no key passed.");
+ r = -EINVAL;
+ goto err;
+ }
+
+ r = crypt_storage_backend_init(cd, w, iv_start, sector_size, _cipher, mode, vk, flags);
+ if (!r) {
+ *cw = w;
+ return 0;
+ }
+
+ log_dbg(cd, "Failed to initialize userspace block cipher.");
+
+ if ((r != -ENOTSUP && r != -ENOENT) || (flags & DISABLE_DMCRYPT))
+ goto err;
+
+ r = crypt_storage_dmcrypt_init(cd, w, device, data_offset >> SECTOR_SHIFT, iv_start,
+ sector_size, cipher, vk, open_flags);
+ if (r) {
+ log_dbg(cd, "Dm-crypt backend failed to initialize.");
+ goto err;
+ }
+ *cw = w;
+ return 0;
+err:
+ crypt_storage_wrapper_destroy(w);
+ /* wrapper destroy */
+ return r;
+}
+
+/* offset is relative to sector_start */
+ssize_t crypt_storage_wrapper_read(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length)
+{
+ return read_lseek_blockwise(cw->dev_fd,
+ cw->block_size,
+ cw->mem_alignment,
+ buffer,
+ buffer_length,
+ cw->data_offset + offset);
+}
+
+ssize_t crypt_storage_wrapper_read_decrypt(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length)
+{
+ int r;
+ ssize_t read;
+
+ if (cw->type == DMCRYPT)
+ return read_lseek_blockwise(cw->u.dm.dmcrypt_fd,
+ cw->block_size,
+ cw->mem_alignment,
+ buffer,
+ buffer_length,
+ offset);
+
+ read = read_lseek_blockwise(cw->dev_fd,
+ cw->block_size,
+ cw->mem_alignment,
+ buffer,
+ buffer_length,
+ cw->data_offset + offset);
+ if (cw->type == NONE || read < 0)
+ return read;
+
+ r = crypt_storage_decrypt(cw->u.cb.s,
+ cw->u.cb.iv_start + (offset >> SECTOR_SHIFT),
+ read,
+ buffer);
+ if (r)
+ return -EINVAL;
+
+ return read;
+}
+
+ssize_t crypt_storage_wrapper_decrypt(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length)
+{
+ int r;
+ ssize_t read;
+
+ if (cw->type == NONE)
+ return 0;
+
+ if (cw->type == DMCRYPT) {
+ /* there's nothing we can do, just read/decrypt via dm-crypt */
+ read = crypt_storage_wrapper_read_decrypt(cw, offset, buffer, buffer_length);
+ if (read < 0 || (size_t)read != buffer_length)
+ return -EINVAL;
+ return 0;
+ }
+
+ r = crypt_storage_decrypt(cw->u.cb.s,
+ cw->u.cb.iv_start + (offset >> SECTOR_SHIFT),
+ buffer_length,
+ buffer);
+ if (r)
+ return r;
+
+ return 0;
+}
+
+ssize_t crypt_storage_wrapper_write(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length)
+{
+ return write_lseek_blockwise(cw->dev_fd,
+ cw->block_size,
+ cw->mem_alignment,
+ buffer,
+ buffer_length,
+ cw->data_offset + offset);
+}
+
+ssize_t crypt_storage_wrapper_encrypt_write(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length)
+{
+ if (cw->type == DMCRYPT)
+ return write_lseek_blockwise(cw->u.dm.dmcrypt_fd,
+ cw->block_size,
+ cw->mem_alignment,
+ buffer,
+ buffer_length,
+ offset);
+
+ if (cw->type == USPACE &&
+ crypt_storage_encrypt(cw->u.cb.s,
+ cw->u.cb.iv_start + (offset >> SECTOR_SHIFT),
+ buffer_length, buffer))
+ return -EINVAL;
+
+ return write_lseek_blockwise(cw->dev_fd,
+ cw->block_size,
+ cw->mem_alignment,
+ buffer,
+ buffer_length,
+ cw->data_offset + offset);
+}
+
+ssize_t crypt_storage_wrapper_encrypt(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length)
+{
+ if (cw->type == NONE)
+ return 0;
+
+ if (cw->type == DMCRYPT)
+ return -ENOTSUP;
+
+ if (crypt_storage_encrypt(cw->u.cb.s,
+ cw->u.cb.iv_start + (offset >> SECTOR_SHIFT),
+ buffer_length,
+ buffer))
+ return -EINVAL;
+
+ return 0;
+}
+
+void crypt_storage_wrapper_destroy(struct crypt_storage_wrapper *cw)
+{
+ if (!cw)
+ return;
+
+ if (cw->type == USPACE)
+ crypt_storage_destroy(cw->u.cb.s);
+ if (cw->type == DMCRYPT) {
+ close(cw->u.dm.dmcrypt_fd);
+ dm_remove_device(NULL, cw->u.dm.name, CRYPT_DEACTIVATE_FORCE);
+ }
+
+ free(cw);
+}
+
+int crypt_storage_wrapper_datasync(const struct crypt_storage_wrapper *cw)
+{
+ if (!cw)
+ return -EINVAL;
+ if (cw->type == DMCRYPT)
+ return fdatasync(cw->u.dm.dmcrypt_fd);
+ else
+ return fdatasync(cw->dev_fd);
+}
+
+crypt_storage_wrapper_type crypt_storage_wrapper_get_type(const struct crypt_storage_wrapper *cw)
+{
+ return cw ? cw->type : NONE;
+}
diff --git a/lib/utils_storage_wrappers.h b/lib/utils_storage_wrappers.h
new file mode 100644
index 0000000..f7781e8
--- /dev/null
+++ b/lib/utils_storage_wrappers.h
@@ -0,0 +1,75 @@
+/*
+ * Generic wrapper for storage functions
+ * (experimental only)
+ *
+ * Copyright (C) 2018-2023 Ondrej Kozina
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _UTILS_STORAGE_WRAPPERS_H
+#define _UTILS_STORAGE_WRAPPERS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+struct crypt_storage_wrapper;
+struct device;
+struct volume_key;
+struct crypt_device;
+
+#define DISABLE_USPACE (1 << 0)
+#define DISABLE_KCAPI (1 << 1)
+#define DISABLE_DMCRYPT (1 << 2)
+#define OPEN_READONLY (1 << 3)
+#define LARGE_IV (1 << 4)
+
+typedef enum {
+ NONE = 0,
+ USPACE,
+ DMCRYPT
+} crypt_storage_wrapper_type;
+
+int crypt_storage_wrapper_init(struct crypt_device *cd,
+ struct crypt_storage_wrapper **cw,
+ struct device *device,
+ uint64_t data_offset,
+ uint64_t iv_start,
+ int sector_size,
+ const char *cipher,
+ struct volume_key *vk,
+ uint32_t flags);
+
+void crypt_storage_wrapper_destroy(struct crypt_storage_wrapper *cw);
+
+/* !!! when doing 'read' or 'write' all offset values are RELATIVE to data_offset !!! */
+ssize_t crypt_storage_wrapper_read(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length);
+ssize_t crypt_storage_wrapper_read_decrypt(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length);
+ssize_t crypt_storage_wrapper_decrypt(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length);
+
+ssize_t crypt_storage_wrapper_write(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length);
+ssize_t crypt_storage_wrapper_encrypt_write(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length);
+ssize_t crypt_storage_wrapper_encrypt(struct crypt_storage_wrapper *cw,
+ off_t offset, void *buffer, size_t buffer_length);
+
+int crypt_storage_wrapper_datasync(const struct crypt_storage_wrapper *cw);
+
+crypt_storage_wrapper_type crypt_storage_wrapper_get_type(const struct crypt_storage_wrapper *cw);
+#endif
diff --git a/lib/utils_wipe.c b/lib/utils_wipe.c
new file mode 100644
index 0000000..1df46c1
--- /dev/null
+++ b/lib/utils_wipe.c
@@ -0,0 +1,311 @@
+/*
+ * utils_wipe - wipe a device
+ *
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <linux/fs.h>
+#include "internal.h"
+
+/* block device zeroout ioctls, introduced in Linux kernel 3.7 */
+#ifndef BLKZEROOUT
+#define BLKZEROOUT _IO(0x12,127)
+#endif
+
+static int wipe_zeroout(struct crypt_device *cd, int devfd,
+ uint64_t offset, uint64_t length)
+{
+ static bool zeroout_available = true;
+ uint64_t range[2] = { offset, length };
+ int r;
+
+ if (!zeroout_available)
+ return -ENOTSUP;
+
+ r = ioctl(devfd, BLKZEROOUT, &range);
+ if (r < 0) {
+ log_dbg(cd, "BLKZEROOUT ioctl not available (error %i), disabling.", r);
+ zeroout_available = false;
+ return -ENOTSUP;
+ }
+
+ return 0;
+}
+
+/*
+ * Wipe using Peter Gutmann method described in
+ * https://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html
+ * Note: used only for rotational device (and even there it is not needed today...)
+ */
+static void wipeSpecial(char *buffer, size_t buffer_size, unsigned int turn)
+{
+ unsigned int i;
+
+ unsigned char write_modes[][3] = {
+ {"\x55\x55\x55"}, {"\xaa\xaa\xaa"}, {"\x92\x49\x24"},
+ {"\x49\x24\x92"}, {"\x24\x92\x49"}, {"\x00\x00\x00"},
+ {"\x11\x11\x11"}, {"\x22\x22\x22"}, {"\x33\x33\x33"},
+ {"\x44\x44\x44"}, {"\x55\x55\x55"}, {"\x66\x66\x66"},
+ {"\x77\x77\x77"}, {"\x88\x88\x88"}, {"\x99\x99\x99"},
+ {"\xaa\xaa\xaa"}, {"\xbb\xbb\xbb"}, {"\xcc\xcc\xcc"},
+ {"\xdd\xdd\xdd"}, {"\xee\xee\xee"}, {"\xff\xff\xff"},
+ {"\x92\x49\x24"}, {"\x49\x24\x92"}, {"\x24\x92\x49"},
+ {"\x6d\xb6\xdb"}, {"\xb6\xdb\x6d"}, {"\xdb\x6d\xb6"}
+ };
+
+ for (i = 0; i < buffer_size / 3; ++i) {
+ memcpy(buffer, write_modes[turn], 3);
+ buffer += 3;
+ }
+}
+
+static int crypt_wipe_special(struct crypt_device *cd, int fd, size_t bsize,
+ size_t alignment, char *buffer,
+ uint64_t offset, size_t size)
+{
+ int r = 0;
+ unsigned int i;
+ ssize_t written;
+
+ for (i = 0; i < 39; ++i) {
+ if (i < 5) {
+ r = crypt_random_get(cd, buffer, size, CRYPT_RND_NORMAL);
+ } else if (i >= 5 && i < 32) {
+ wipeSpecial(buffer, size, i - 5);
+ r = 0;
+ } else if (i >= 32 && i < 38) {
+ r = crypt_random_get(cd, buffer, size, CRYPT_RND_NORMAL);
+ } else if (i >= 38 && i < 39) {
+ memset(buffer, 0xFF, size);
+ r = 0;
+ }
+ if (r < 0)
+ return -EIO;
+
+ written = write_lseek_blockwise(fd, bsize, alignment,
+ buffer, size, offset);
+ if (written < 0 || written != (ssize_t)size)
+ return -EIO;
+ }
+
+ /* Rewrite it finally with random */
+ if (crypt_random_get(cd, buffer, size, CRYPT_RND_NORMAL) < 0)
+ return -EIO;
+
+ written = write_lseek_blockwise(fd, bsize, alignment, buffer, size, offset);
+ if (written < 0 || written != (ssize_t)size)
+ return -EIO;
+
+ return 0;
+}
+
+static int wipe_block(struct crypt_device *cd, int devfd, crypt_wipe_pattern pattern,
+ char *sf, size_t device_block_size, size_t alignment,
+ size_t wipe_block_size, uint64_t offset, bool *need_block_init,
+ bool blockdev)
+{
+ int r;
+
+ if (pattern == CRYPT_WIPE_SPECIAL)
+ return crypt_wipe_special(cd, devfd, device_block_size, alignment,
+ sf, offset, wipe_block_size);
+
+ if (*need_block_init) {
+ if (pattern == CRYPT_WIPE_ZERO) {
+ memset(sf, 0, wipe_block_size);
+ *need_block_init = false;
+ r = 0;
+ } else if (pattern == CRYPT_WIPE_RANDOM ||
+ pattern == CRYPT_WIPE_ENCRYPTED_ZERO) {
+ r = crypt_random_get(cd, sf, wipe_block_size,
+ CRYPT_RND_NORMAL) ? -EIO : 0;
+ *need_block_init = true;
+ } else
+ r = -EINVAL;
+
+ if (r)
+ return r;
+ }
+
+ if (blockdev && pattern == CRYPT_WIPE_ZERO &&
+ !wipe_zeroout(cd, devfd, offset, wipe_block_size)) {
+ /* zeroout ioctl does not move offset */
+ if (lseek(devfd, offset + wipe_block_size, SEEK_SET) < 0) {
+ log_err(cd, _("Cannot seek to device offset."));
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ if (write_blockwise(devfd, device_block_size, alignment, sf,
+ wipe_block_size) == (ssize_t)wipe_block_size)
+ return 0;
+
+ return -EIO;
+}
+
+int crypt_wipe_device(struct crypt_device *cd,
+ struct device *device,
+ crypt_wipe_pattern pattern,
+ uint64_t offset,
+ uint64_t length,
+ size_t wipe_block_size,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr)
+{
+ int r, devfd;
+ struct stat st;
+ size_t bsize, alignment;
+ char *sf = NULL;
+ uint64_t dev_size;
+ bool need_block_init = true;
+
+ /* Note: LUKS1 calls it with wipe_block not aligned to multiple of bsize */
+ bsize = device_block_size(cd, device);
+ alignment = device_alignment(device);
+ if (!bsize || !alignment || !wipe_block_size)
+ return -EINVAL;
+
+ /* if wipe_block_size < bsize, then a wipe is highly ineffective */
+
+ /* Everything must be aligned to SECTOR_SIZE */
+ if (MISALIGNED_512(offset) || MISALIGNED_512(length) || MISALIGNED_512(wipe_block_size))
+ return -EINVAL;
+
+ if (device_is_locked(device))
+ devfd = device_open_locked(cd, device, O_RDWR);
+ else
+ devfd = device_open(cd, device, O_RDWR);
+ if (devfd < 0)
+ return errno ? -errno : -EINVAL;
+
+ if (fstat(devfd, &st) < 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (length)
+ dev_size = offset + length;
+ else {
+ r = device_size(device, &dev_size);
+ if (r)
+ goto out;
+
+ if (dev_size <= offset) {
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ r = posix_memalign((void **)&sf, alignment, wipe_block_size);
+ if (r)
+ goto out;
+
+ if (lseek(devfd, offset, SEEK_SET) < 0) {
+ log_err(cd, _("Cannot seek to device offset."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (progress && progress(dev_size, offset, usrptr)) {
+ r = -EINVAL; /* No change yet, treat this as a parameter error */
+ goto out;
+ }
+
+ if (pattern == CRYPT_WIPE_SPECIAL && !device_is_rotational(device)) {
+ log_dbg(cd, "Non-rotational device, using random data wipe mode.");
+ pattern = CRYPT_WIPE_RANDOM;
+ }
+
+ while (offset < dev_size) {
+ if ((offset + wipe_block_size) > dev_size)
+ wipe_block_size = dev_size - offset;
+
+ r = wipe_block(cd, devfd, pattern, sf, bsize, alignment,
+ wipe_block_size, offset, &need_block_init, S_ISBLK(st.st_mode));
+ if (r) {
+ log_err(cd,_("Device wipe error, offset %" PRIu64 "."), offset);
+ break;
+ }
+
+ offset += wipe_block_size;
+
+ if (progress && progress(dev_size, offset, usrptr)) {
+ r = -EINTR;
+ break;
+ }
+ }
+
+ device_sync(cd, device);
+out:
+ free(sf);
+ return r;
+}
+
+int crypt_wipe(struct crypt_device *cd,
+ const char *dev_path,
+ crypt_wipe_pattern pattern,
+ uint64_t offset,
+ uint64_t length,
+ size_t wipe_block_size,
+ uint32_t flags,
+ int (*progress)(uint64_t size, uint64_t offset, void *usrptr),
+ void *usrptr)
+{
+ struct device *device;
+ int r;
+
+ if (!cd)
+ return -EINVAL;
+
+ r = init_crypto(cd);
+ if (r < 0)
+ return r;
+
+ if (!dev_path)
+ device = crypt_data_device(cd);
+ else {
+ r = device_alloc_no_check(&device, dev_path);
+ if (r < 0)
+ return r;
+
+ if (flags & CRYPT_WIPE_NO_DIRECT_IO)
+ device_disable_direct_io(device);
+ }
+ if (!device)
+ return -EINVAL;
+
+ if (!wipe_block_size)
+ wipe_block_size = 1024*1024;
+
+ log_dbg(cd, "Wipe [%u] device %s, offset %" PRIu64 ", length %" PRIu64 ", block %zu.",
+ (unsigned)pattern, device_path(device), offset, length, wipe_block_size);
+
+ r = crypt_wipe_device(cd, device, pattern, offset, length,
+ wipe_block_size, progress, usrptr);
+
+ if (dev_path)
+ device_free(cd, device);
+
+ return r;
+}
diff --git a/lib/verity/rs.h b/lib/verity/rs.h
new file mode 100644
index 0000000..7638924
--- /dev/null
+++ b/lib/verity/rs.h
@@ -0,0 +1,63 @@
+/*
+ * Reed-Solomon codecs, based on libfec
+ *
+ * Copyright (C) 2004 Phil Karn, KA9Q
+ * libcryptsetup modifications
+ * Copyright (C) 2017-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LIBFEC_RS_H
+#define _LIBFEC_RS_H
+
+/* Special reserved value encoding zero in index form. */
+#define A0 (rs->nn)
+
+#define RS_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef unsigned char data_t;
+
+/* Reed-Solomon codec control block */
+struct rs {
+ int mm; /* Bits per symbol */
+ int nn; /* Symbols per block (= (1<<mm)-1) */
+ data_t *alpha_to;/* log lookup table */
+ data_t *index_of;/* Antilog lookup table */
+ data_t *genpoly; /* Generator polynomial */
+ int nroots; /* Number of generator roots = number of parity symbols */
+ int fcr; /* First consecutive root, index form */
+ int prim; /* Primitive element, index form */
+ int iprim; /* prim-th root of 1, index form */
+ int pad; /* Padding bytes in shortened block */
+};
+
+static inline int modnn(struct rs *rs, int x)
+{
+ while (x >= rs->nn) {
+ x -= rs->nn;
+ x = (x >> rs->mm) + (x & rs->nn);
+ }
+ return x;
+}
+
+struct rs *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad);
+void free_rs_char(struct rs *rs);
+
+/* General purpose RS codec, 8-bit symbols */
+void encode_rs_char(struct rs *rs, data_t *data, data_t *parity);
+int decode_rs_char(struct rs *rs, data_t *data);
+
+#endif
diff --git a/lib/verity/rs_decode_char.c b/lib/verity/rs_decode_char.c
new file mode 100644
index 0000000..4473202
--- /dev/null
+++ b/lib/verity/rs_decode_char.c
@@ -0,0 +1,201 @@
+/*
+ * Reed-Solomon decoder, based on libfec
+ *
+ * Copyright (C) 2002, Phil Karn, KA9Q
+ * libcryptsetup modifications
+ * Copyright (C) 2017-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "rs.h"
+
+#define MAX_NR_BUF 256
+
+int decode_rs_char(struct rs* rs, data_t* data)
+{
+ int deg_lambda, el, deg_omega, syn_error, count;
+ int i, j, r, k;
+ data_t q, tmp, num1, num2, den, discr_r;
+ data_t lambda[MAX_NR_BUF], s[MAX_NR_BUF]; /* Err+Eras Locator poly and syndrome poly */
+ data_t b[MAX_NR_BUF], t[MAX_NR_BUF], omega[MAX_NR_BUF];
+ data_t root[MAX_NR_BUF], reg[MAX_NR_BUF], loc[MAX_NR_BUF];
+
+ if (rs->nroots >= MAX_NR_BUF)
+ return -1;
+
+ memset(s, 0, rs->nroots * sizeof(data_t));
+ memset(b, 0, (rs->nroots + 1) * sizeof(data_t));
+
+ /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */
+ for (i = 0; i < rs->nroots; i++)
+ s[i] = data[0];
+
+ for (j = 1; j < rs->nn - rs->pad; j++) {
+ for (i = 0; i < rs->nroots; i++) {
+ if (s[i] == 0) {
+ s[i] = data[j];
+ } else {
+ s[i] = data[j] ^ rs->alpha_to[modnn(rs, rs->index_of[s[i]] + (rs->fcr + i) * rs->prim)];
+ }
+ }
+ }
+
+ /* Convert syndromes to index form, checking for nonzero condition */
+ syn_error = 0;
+ for (i = 0; i < rs->nroots; i++) {
+ syn_error |= s[i];
+ s[i] = rs->index_of[s[i]];
+ }
+
+ /*
+ * if syndrome is zero, data[] is a codeword and there are no
+ * errors to correct. So return data[] unmodified
+ */
+ if (!syn_error)
+ return 0;
+
+ memset(&lambda[1], 0, rs->nroots * sizeof(lambda[0]));
+ lambda[0] = 1;
+
+ for (i = 0; i < rs->nroots + 1; i++)
+ b[i] = rs->index_of[lambda[i]];
+
+ /*
+ * Begin Berlekamp-Massey algorithm to determine error+erasure
+ * locator polynomial
+ */
+ r = 0;
+ el = 0;
+ while (++r <= rs->nroots) { /* r is the step number */
+ /* Compute discrepancy at the r-th step in poly-form */
+ discr_r = 0;
+ for (i = 0; i < r; i++) {
+ if ((lambda[i] != 0) && (s[r - i - 1] != A0)) {
+ discr_r ^= rs->alpha_to[modnn(rs, rs->index_of[lambda[i]] + s[r - i - 1])];
+ }
+ }
+ discr_r = rs->index_of[discr_r]; /* Index form */
+ if (discr_r == A0) {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ memmove(&b[1], b, rs->nroots * sizeof(b[0]));
+ b[0] = A0;
+ } else {
+ /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
+ t[0] = lambda[0];
+ for (i = 0; i < rs->nroots; i++) {
+ if (b[i] != A0)
+ t[i + 1] = lambda[i + 1] ^ rs->alpha_to[modnn(rs, discr_r + b[i])];
+ else
+ t[i + 1] = lambda[i + 1];
+ }
+ if (2 * el <= r - 1) {
+ el = r - el;
+ /*
+ * 2 lines below: B(x) <-- inv(discr_r) *
+ * lambda(x)
+ */
+ for (i = 0; i <= rs->nroots; i++)
+ b[i] = (lambda[i] == 0) ? A0 : modnn(rs, rs->index_of[lambda[i]] - discr_r + rs->nn);
+ } else {
+ /* 2 lines below: B(x) <-- x*B(x) */
+ memmove(&b[1], b, rs->nroots * sizeof(b[0]));
+ b[0] = A0;
+ }
+ memcpy(lambda, t, (rs->nroots + 1) * sizeof(t[0]));
+ }
+ }
+
+ /* Convert lambda to index form and compute deg(lambda(x)) */
+ deg_lambda = 0;
+ for (i = 0; i < rs->nroots + 1; i++) {
+ lambda[i] = rs->index_of[lambda[i]];
+ if (lambda[i] != A0)
+ deg_lambda = i;
+ }
+ /* Find roots of the error+erasure locator polynomial by Chien search */
+ memcpy(&reg[1], &lambda[1], rs->nroots * sizeof(reg[0]));
+ count = 0; /* Number of roots of lambda(x) */
+ for (i = 1, k = rs->iprim - 1; i <= rs->nn; i++, k = modnn(rs, k + rs->iprim)) {
+ q = 1; /* lambda[0] is always 0 */
+ for (j = deg_lambda; j > 0; j--) {
+ if (reg[j] != A0) {
+ reg[j] = modnn(rs, reg[j] + j);
+ q ^= rs->alpha_to[reg[j]];
+ }
+ }
+ if (q != 0)
+ continue; /* Not a root */
+
+ /* store root (index-form) and error location number */
+ root[count] = i;
+ loc[count] = k;
+ /* If we've already found max possible roots, abort the search to save time */
+ if (++count == deg_lambda)
+ break;
+ }
+
+ /*
+ * deg(lambda) unequal to number of roots => uncorrectable
+ * error detected
+ */
+ if (deg_lambda != count)
+ return -1;
+
+ /*
+ * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
+ * x**rs->nroots). in index form. Also find deg(omega).
+ */
+ deg_omega = deg_lambda - 1;
+ for (i = 0; i <= deg_omega; i++) {
+ tmp = 0;
+ for (j = i; j >= 0; j--) {
+ if ((s[i - j] != A0) && (lambda[j] != A0))
+ tmp ^= rs->alpha_to[modnn(rs, s[i - j] + lambda[j])];
+ }
+ omega[i] = rs->index_of[tmp];
+ }
+
+ /*
+ * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+ * inv(X(l))**(rs->fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form
+ */
+ for (j = count - 1; j >= 0; j--) {
+ num1 = 0;
+ for (i = deg_omega; i >= 0; i--) {
+ if (omega[i] != A0)
+ num1 ^= rs->alpha_to[modnn(rs, omega[i] + i * root[j])];
+ }
+ num2 = rs->alpha_to[modnn(rs, root[j] * (rs->fcr - 1) + rs->nn)];
+ den = 0;
+
+ /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
+ for (i = RS_MIN(deg_lambda, rs->nroots - 1) & ~1; i >= 0; i -= 2) {
+ if (lambda[i + 1] != A0)
+ den ^= rs->alpha_to[modnn(rs, lambda[i + 1] + i * root[j])];
+ }
+
+ /* Apply error to data */
+ if (num1 != 0 && loc[j] >= rs->pad) {
+ data[loc[j] - rs->pad] ^= rs->alpha_to[modnn(rs, rs->index_of[num1] +
+ rs->index_of[num2] + rs->nn - rs->index_of[den])];
+ }
+ }
+
+ return count;
+}
diff --git a/lib/verity/rs_encode_char.c b/lib/verity/rs_encode_char.c
new file mode 100644
index 0000000..55b502a
--- /dev/null
+++ b/lib/verity/rs_encode_char.c
@@ -0,0 +1,173 @@
+/*
+ * Reed-Solomon encoder, based on libfec
+ *
+ * Copyright (C) 2002, Phil Karn, KA9Q
+ * libcryptsetup modifications
+ * Copyright (C) 2017-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "rs.h"
+
+/* Initialize a Reed-Solomon codec
+ * symsize = symbol size, bits
+ * gfpoly = Field generator polynomial coefficients
+ * fcr = first root of RS code generator polynomial, index form
+ * prim = primitive element to generate polynomial roots
+ * nroots = RS code generator polynomial degree (number of roots)
+ * pad = padding bytes at front of shortened block
+ */
+struct rs *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
+{
+ struct rs *rs;
+ int i, j, sr, root, iprim;
+
+ /* Check parameter ranges */
+ if (symsize < 0 || symsize > 8 * (int)sizeof(data_t))
+ return NULL;
+ if (fcr < 0 || fcr >= (1<<symsize))
+ return NULL;
+ if (prim <= 0 || prim >= (1<<symsize))
+ return NULL;
+ if (nroots < 0 || nroots >= (1<<symsize))
+ return NULL; /* Can't have more roots than symbol values! */
+
+ if (pad < 0 || pad >= ((1<<symsize) - 1 - nroots))
+ return NULL; /* Too much padding */
+
+ rs = calloc(1, sizeof(struct rs));
+ if (rs == NULL)
+ return NULL;
+
+ rs->mm = symsize;
+ rs->nn = (1<<symsize) - 1;
+ rs->pad = pad;
+
+ rs->alpha_to = malloc(sizeof(data_t) * (rs->nn + 1));
+ if (rs->alpha_to == NULL) {
+ free(rs);
+ return NULL;
+ }
+ rs->index_of = malloc(sizeof(data_t) * (rs->nn + 1));
+ if (rs->index_of == NULL) {
+ free(rs->alpha_to);
+ free(rs);
+ return NULL;
+ }
+ memset(rs->index_of, 0, sizeof(data_t) * (rs->nn + 1));
+
+ /* Generate Galois field lookup tables */
+ rs->index_of[0] = A0; /* log(zero) = -inf */
+ rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
+ sr = 1;
+ for (i = 0; i < rs->nn; i++) {
+ rs->index_of[sr] = i;
+ rs->alpha_to[i] = sr;
+ sr <<= 1;
+ if(sr & (1<<symsize))
+ sr ^= gfpoly;
+ sr &= rs->nn;
+ }
+ if (sr != 1) {
+ /* field generator polynomial is not primitive! */
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ return NULL;
+ }
+
+ /* Form RS code generator polynomial from its roots */
+ rs->genpoly = malloc(sizeof(data_t) * (nroots + 1));
+ if (rs->genpoly == NULL) {
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ return NULL;
+ }
+
+ rs->fcr = fcr;
+ rs->prim = prim;
+ rs->nroots = nroots;
+
+ /* Find prim-th root of 1, used in decoding */
+ for (iprim = 1; (iprim % prim) != 0; iprim += rs->nn)
+ ;
+ rs->iprim = iprim / prim;
+
+ rs->genpoly[0] = 1;
+ for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) {
+ rs->genpoly[i + 1] = 1;
+
+ /* Multiply rs->genpoly[] by @**(root + x) */
+ for (j = i; j > 0; j--){
+ if (rs->genpoly[j] != 0)
+ rs->genpoly[j] = rs->genpoly[j - 1] ^ rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[j]] + root)];
+ else
+ rs->genpoly[j] = rs->genpoly[j - 1];
+ }
+ /* rs->genpoly[0] can never be zero */
+ rs->genpoly[0] = rs->alpha_to[modnn(rs, rs->index_of[rs->genpoly[0]] + root)];
+ }
+ /* convert rs->genpoly[] to index form for quicker encoding */
+ for (i = 0; i <= nroots; i++)
+ rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
+
+ return rs;
+}
+
+void free_rs_char(struct rs *rs)
+{
+ if (!rs)
+ return;
+
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs->genpoly);
+ free(rs);
+}
+
+void encode_rs_char(struct rs *rs, data_t *data, data_t *parity)
+{
+ int i, j;
+ data_t feedback;
+
+ memset(parity, 0, rs->nroots * sizeof(data_t));
+
+ for (i = 0; i < rs->nn - rs->nroots - rs->pad; i++) {
+ feedback = rs->index_of[data[i] ^ parity[0]];
+ if (feedback != A0) {
+ /* feedback term is non-zero */
+#ifdef UNNORMALIZED
+ /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
+ * always be for the polynomials constructed by init_rs() */
+ feedback = modnn(rs, rs->nn - rs->genpoly[rs->nroots] + feedback);
+#endif
+ for (j = 1; j < rs->nroots; j++)
+ parity[j] ^= rs->alpha_to[modnn(rs, feedback + rs->genpoly[rs->nroots - j])];
+ }
+
+ /* Shift */
+ memmove(&parity[0], &parity[1], sizeof(data_t) * (rs->nroots - 1));
+
+ if (feedback != A0)
+ parity[rs->nroots - 1] = rs->alpha_to[modnn(rs, feedback + rs->genpoly[0])];
+ else
+ parity[rs->nroots - 1] = 0;
+ }
+}
diff --git a/lib/verity/verity.c b/lib/verity/verity.c
new file mode 100644
index 0000000..0d7a8f5
--- /dev/null
+++ b/lib/verity/verity.c
@@ -0,0 +1,416 @@
+/*
+ * dm-verity volume handling
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <uuid/uuid.h>
+
+#include "libcryptsetup.h"
+#include "verity.h"
+#include "internal.h"
+
+#define VERITY_SIGNATURE "verity\0\0"
+
+/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity#verity-superblock-format */
+struct verity_sb {
+ uint8_t signature[8]; /* "verity\0\0" */
+ uint32_t version; /* superblock version */
+ uint32_t hash_type; /* 0 - Chrome OS, 1 - normal */
+ uint8_t uuid[16]; /* UUID of hash device */
+ uint8_t algorithm[32];/* hash algorithm name */
+ uint32_t data_block_size; /* data block in bytes */
+ uint32_t hash_block_size; /* hash block in bytes */
+ uint64_t data_blocks; /* number of data blocks */
+ uint16_t salt_size; /* salt size */
+ uint8_t _pad1[6];
+ uint8_t salt[256]; /* salt */
+ uint8_t _pad2[168];
+} __attribute__((packed));
+
+/* Read verity superblock from disk */
+int VERITY_read_sb(struct crypt_device *cd,
+ uint64_t sb_offset,
+ char **uuid_string,
+ struct crypt_params_verity *params)
+{
+ struct device *device = crypt_metadata_device(cd);
+ struct verity_sb sb = {};
+ ssize_t hdr_size = sizeof(struct verity_sb);
+ int devfd, sb_version;
+
+ log_dbg(cd, "Reading VERITY header of size %zu on device %s, offset %" PRIu64 ".",
+ sizeof(struct verity_sb), device_path(device), sb_offset);
+
+ if (params->flags & CRYPT_VERITY_NO_HEADER) {
+ log_err(cd, _("Verity device %s does not use on-disk header."),
+ device_path(device));
+ return -EINVAL;
+ }
+
+ if (MISALIGNED_512(sb_offset)) {
+ log_err(cd, _("Unsupported VERITY hash offset."));
+ return -EINVAL;
+ }
+
+ devfd = device_open(cd, device, O_RDONLY);
+ if (devfd < 0) {
+ log_err(cd, _("Cannot open device %s."), device_path(device));
+ return -EINVAL;
+ }
+
+ if (read_lseek_blockwise(devfd, device_block_size(cd, device),
+ device_alignment(device), &sb, hdr_size,
+ sb_offset) < hdr_size)
+ return -EIO;
+
+ if (memcmp(sb.signature, VERITY_SIGNATURE, sizeof(sb.signature))) {
+ log_dbg(cd, "No VERITY signature detected.");
+ return -EINVAL;
+ }
+
+ sb_version = le32_to_cpu(sb.version);
+ if (sb_version != 1) {
+ log_err(cd, _("Unsupported VERITY version %d."), sb_version);
+ return -EINVAL;
+ }
+ params->hash_type = le32_to_cpu(sb.hash_type);
+ if (params->hash_type > VERITY_MAX_HASH_TYPE) {
+ log_err(cd, _("Unsupported VERITY hash type %d."), params->hash_type);
+ return -EINVAL;
+ }
+
+ params->data_block_size = le32_to_cpu(sb.data_block_size);
+ params->hash_block_size = le32_to_cpu(sb.hash_block_size);
+ if (VERITY_BLOCK_SIZE_OK(params->data_block_size) ||
+ VERITY_BLOCK_SIZE_OK(params->hash_block_size)) {
+ log_err(cd, _("Unsupported VERITY block size."));
+ return -EINVAL;
+ }
+ params->data_size = le64_to_cpu(sb.data_blocks);
+
+ /* Update block size to be used for loop devices */
+ device_set_block_size(crypt_metadata_device(cd), params->hash_block_size);
+ device_set_block_size(crypt_data_device(cd), params->data_block_size);
+
+ params->hash_name = strndup((const char*)sb.algorithm, sizeof(sb.algorithm));
+ if (!params->hash_name)
+ return -ENOMEM;
+ if (crypt_hash_size(params->hash_name) <= 0) {
+ log_err(cd, _("Hash algorithm %s not supported."),
+ params->hash_name);
+ free(CONST_CAST(char*)params->hash_name);
+ params->hash_name = NULL;
+ return -EINVAL;
+ }
+
+ params->salt_size = le16_to_cpu(sb.salt_size);
+ if (params->salt_size > sizeof(sb.salt)) {
+ log_err(cd, _("VERITY header corrupted."));
+ free(CONST_CAST(char*)params->hash_name);
+ params->hash_name = NULL;
+ return -EINVAL;
+ }
+ params->salt = malloc(params->salt_size);
+ if (!params->salt) {
+ free(CONST_CAST(char*)params->hash_name);
+ params->hash_name = NULL;
+ return -ENOMEM;
+ }
+ memcpy(CONST_CAST(char*)params->salt, sb.salt, params->salt_size);
+
+ if ((*uuid_string = malloc(40)))
+ uuid_unparse(sb.uuid, *uuid_string);
+
+ params->hash_area_offset = sb_offset;
+ return 0;
+}
+
+static void _to_lower(char *str)
+{
+ for(; *str; str++)
+ if (isupper(*str))
+ *str = tolower(*str);
+}
+
+/* Write verity superblock to disk */
+int VERITY_write_sb(struct crypt_device *cd,
+ uint64_t sb_offset,
+ const char *uuid_string,
+ struct crypt_params_verity *params)
+{
+ struct device *device = crypt_metadata_device(cd);
+ struct verity_sb sb = {};
+ ssize_t hdr_size = sizeof(struct verity_sb);
+ size_t block_size;
+ char *algorithm;
+ uuid_t uuid;
+ int r, devfd;
+
+ log_dbg(cd, "Updating VERITY header of size %zu on device %s, offset %" PRIu64 ".",
+ sizeof(struct verity_sb), device_path(device), sb_offset);
+
+ if (!uuid_string || uuid_parse(uuid_string, uuid) == -1) {
+ log_err(cd, _("Wrong VERITY UUID format provided on device %s."),
+ device_path(device));
+ return -EINVAL;
+ }
+
+ if (params->flags & CRYPT_VERITY_NO_HEADER) {
+ log_err(cd, _("Verity device %s does not use on-disk header."),
+ device_path(device));
+ return -EINVAL;
+ }
+
+ /* Avoid possible increasing of image size - FEC could fail later because of it */
+ block_size = device_block_size(cd, device);
+ if (block_size > params->hash_block_size) {
+ device_disable_direct_io(device);
+ block_size = params->hash_block_size;
+ }
+
+ devfd = device_open(cd, device, O_RDWR);
+ if (devfd < 0) {
+ log_err(cd, _("Cannot open device %s."), device_path(device));
+ return -EINVAL;
+ }
+
+ memcpy(&sb.signature, VERITY_SIGNATURE, sizeof(sb.signature));
+ sb.version = cpu_to_le32(1);
+ sb.hash_type = cpu_to_le32(params->hash_type);
+ sb.data_block_size = cpu_to_le32(params->data_block_size);
+ sb.hash_block_size = cpu_to_le32(params->hash_block_size);
+ sb.salt_size = cpu_to_le16(params->salt_size);
+ sb.data_blocks = cpu_to_le64(params->data_size);
+
+ /* Kernel always use lower-case */
+ algorithm = (char *)sb.algorithm;
+ strncpy(algorithm, params->hash_name, sizeof(sb.algorithm)-1);
+ algorithm[sizeof(sb.algorithm)-1] = '\0';
+ _to_lower(algorithm);
+
+ memcpy(sb.salt, params->salt, params->salt_size);
+ memcpy(sb.uuid, uuid, sizeof(sb.uuid));
+
+ r = write_lseek_blockwise(devfd, block_size, device_alignment(device),
+ (char*)&sb, hdr_size, sb_offset) < hdr_size ? -EIO : 0;
+ if (r)
+ log_err(cd, _("Error during update of verity header on device %s."),
+ device_path(device));
+
+ device_sync(cd, device);
+
+ return r;
+}
+
+/* Calculate hash offset in hash blocks */
+uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params)
+{
+ uint64_t hash_offset = params->hash_area_offset;
+
+ if (params->flags & CRYPT_VERITY_NO_HEADER)
+ return hash_offset / params->hash_block_size;
+
+ hash_offset += sizeof(struct verity_sb);
+ hash_offset += params->hash_block_size - 1;
+
+ return hash_offset / params->hash_block_size;
+}
+
+int VERITY_UUID_generate(char **uuid_string)
+{
+ uuid_t uuid;
+
+ *uuid_string = malloc(40);
+ if (!*uuid_string)
+ return -ENOMEM;
+ uuid_generate(uuid);
+ uuid_unparse(uuid, *uuid_string);
+ return 0;
+}
+
+/* Activate verity device in kernel device-mapper */
+int VERITY_activate(struct crypt_device *cd,
+ const char *name,
+ const char *root_hash,
+ size_t root_hash_size,
+ const char *signature_description,
+ struct device *fec_device,
+ struct crypt_params_verity *verity_hdr,
+ uint32_t activation_flags)
+{
+ uint32_t dmv_flags;
+ unsigned int fec_errors = 0;
+ int r, v;
+ struct crypt_dm_active_device dmd = {
+ .size = verity_hdr->data_size * verity_hdr->data_block_size / 512,
+ .flags = activation_flags,
+ .uuid = crypt_get_uuid(cd),
+ };
+
+ log_dbg(cd, "Trying to activate VERITY device %s using hash %s.",
+ name ?: "[none]", verity_hdr->hash_name);
+
+ if (verity_hdr->flags & CRYPT_VERITY_CHECK_HASH) {
+ if (signature_description) {
+ log_err(cd, _("Root hash signature verification is not supported."));
+ return -EINVAL;
+ }
+
+ log_dbg(cd, "Verification of data in userspace required.");
+ r = VERITY_verify(cd, verity_hdr, root_hash, root_hash_size);
+
+ if ((r == -EPERM || r == -EFAULT) && fec_device) {
+ v = r;
+ log_dbg(cd, "Verification failed, trying to repair with FEC device.");
+ r = VERITY_FEC_process(cd, verity_hdr, fec_device, 1, &fec_errors);
+ if (r < 0)
+ log_err(cd, _("Errors cannot be repaired with FEC device."));
+ else if (fec_errors) {
+ log_err(cd, _("Found %u repairable errors with FEC device."),
+ fec_errors);
+ /* If root hash failed, we cannot be sure it was properly repaired */
+ }
+ if (v == -EFAULT)
+ r = -EPERM;
+ }
+
+ if (r < 0)
+ return r;
+ }
+
+ if (!name)
+ return 0;
+
+ r = device_block_adjust(cd, crypt_metadata_device(cd), DEV_OK,
+ 0, NULL, NULL);
+ if (r)
+ return r;
+
+ r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL,
+ 0, &dmd.size, &dmd.flags);
+ if (r)
+ return r;
+
+ if (fec_device) {
+ r = device_block_adjust(cd, fec_device, DEV_OK,
+ 0, NULL, NULL);
+ if (r)
+ return r;
+ }
+
+ r = dm_verity_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
+ crypt_metadata_device(cd), fec_device, root_hash,
+ root_hash_size, signature_description,
+ VERITY_hash_offset_block(verity_hdr),
+ VERITY_FEC_blocks(cd, fec_device, verity_hdr), verity_hdr);
+
+ if (r)
+ return r;
+
+ r = dm_create_device(cd, name, CRYPT_VERITY, &dmd);
+ if (r < 0 && (dm_flags(cd, DM_VERITY, &dmv_flags) || !(dmv_flags & DM_VERITY_SUPPORTED))) {
+ log_err(cd, _("Kernel does not support dm-verity mapping."));
+ r = -ENOTSUP;
+ }
+ if (r < 0 && signature_description && !(dmv_flags & DM_VERITY_SIGNATURE_SUPPORTED)) {
+ log_err(cd, _("Kernel does not support dm-verity signature option."));
+ r = -ENOTSUP;
+ }
+ if (r < 0)
+ goto out;
+
+ r = dm_status_verity_ok(cd, name);
+ if (r < 0)
+ goto out;
+
+ if (!r)
+ log_err(cd, _("Verity device detected corruption after activation."));
+
+ r = 0;
+out:
+ dm_targets_free(cd, &dmd);
+ return r;
+}
+
+int VERITY_dump(struct crypt_device *cd,
+ struct crypt_params_verity *verity_hdr,
+ const char *root_hash,
+ unsigned int root_hash_size,
+ struct device *fec_device)
+{
+ uint64_t hash_blocks, verity_blocks, fec_blocks = 0, rs_blocks = 0;
+ bool fec_on_hash_device = false;
+
+ hash_blocks = VERITY_hash_blocks(cd, verity_hdr);
+ verity_blocks = VERITY_hash_offset_block(verity_hdr) + hash_blocks;
+
+ if (fec_device && verity_hdr->fec_roots) {
+ fec_blocks = VERITY_FEC_blocks(cd, fec_device, verity_hdr);
+ rs_blocks = VERITY_FEC_RS_blocks(fec_blocks, verity_hdr->fec_roots);
+ fec_on_hash_device = device_is_identical(crypt_metadata_device(cd), fec_device) > 0;
+ /*
+ * No way to access fec_area_offset directly.
+ * Assume FEC area starts directly after hash blocks.
+ */
+ if (fec_on_hash_device)
+ verity_blocks += rs_blocks;
+ }
+
+ log_std(cd, "VERITY header information for %s\n", device_path(crypt_metadata_device(cd)));
+ log_std(cd, "UUID: \t%s\n", crypt_get_uuid(cd) ?: "");
+ log_std(cd, "Hash type: \t%u\n", verity_hdr->hash_type);
+ log_std(cd, "Data blocks: \t%" PRIu64 "\n", verity_hdr->data_size);
+ log_std(cd, "Data block size: \t%u\n", verity_hdr->data_block_size);
+ log_std(cd, "Hash blocks: \t%" PRIu64 "\n", hash_blocks);
+ log_std(cd, "Hash block size: \t%u\n", verity_hdr->hash_block_size);
+ log_std(cd, "Hash algorithm: \t%s\n", verity_hdr->hash_name);
+ if (fec_device && fec_blocks) {
+ log_std(cd, "FEC RS roots: \t%" PRIu32 "\n", verity_hdr->fec_roots);
+ log_std(cd, "FEC blocks: \t%" PRIu64 "\n", rs_blocks);
+ }
+
+ log_std(cd, "Salt: \t");
+ if (verity_hdr->salt_size)
+ crypt_log_hex(cd, verity_hdr->salt, verity_hdr->salt_size, "", 0, NULL);
+ else
+ log_std(cd, "-");
+ log_std(cd, "\n");
+
+ if (root_hash) {
+ log_std(cd, "Root hash: \t");
+ crypt_log_hex(cd, root_hash, root_hash_size, "", 0, NULL);
+ log_std(cd, "\n");
+ }
+
+ /* As dump can take only hash device, we have no idea about offsets here. */
+ if (verity_hdr->hash_area_offset == 0)
+ log_std(cd, "Hash device size: \t%" PRIu64 " [bytes]\n", verity_blocks * verity_hdr->hash_block_size);
+
+ if (fec_device && verity_hdr->fec_area_offset == 0 && fec_blocks && !fec_on_hash_device)
+ log_std(cd, "FEC device size: \t%" PRIu64 " [bytes]\n", rs_blocks * verity_hdr->data_block_size);
+
+ return 0;
+}
diff --git a/lib/verity/verity.h b/lib/verity/verity.h
new file mode 100644
index 0000000..afc411e
--- /dev/null
+++ b/lib/verity/verity.h
@@ -0,0 +1,87 @@
+/*
+ * dm-verity volume handling
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _VERITY_H
+#define _VERITY_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define VERITY_MAX_HASH_TYPE 1
+#define VERITY_BLOCK_SIZE_OK(x) ((x) % 512 || (x) < 512 || \
+ (x) > (512 * 1024) || (x) & ((x)-1))
+
+struct crypt_device;
+struct crypt_params_verity;
+struct device;
+
+int VERITY_read_sb(struct crypt_device *cd,
+ uint64_t sb_offset,
+ char **uuid,
+ struct crypt_params_verity *params);
+
+int VERITY_write_sb(struct crypt_device *cd,
+ uint64_t sb_offset,
+ const char *uuid_string,
+ struct crypt_params_verity *params);
+
+int VERITY_activate(struct crypt_device *cd,
+ const char *name,
+ const char *root_hash,
+ size_t root_hash_size,
+ const char *signature_description,
+ struct device *fec_device,
+ struct crypt_params_verity *verity_hdr,
+ uint32_t activation_flags);
+
+int VERITY_verify(struct crypt_device *cd,
+ struct crypt_params_verity *verity_hdr,
+ const char *root_hash,
+ size_t root_hash_size);
+
+int VERITY_create(struct crypt_device *cd,
+ struct crypt_params_verity *verity_hdr,
+ const char *root_hash,
+ size_t root_hash_size);
+
+int VERITY_FEC_process(struct crypt_device *cd,
+ struct crypt_params_verity *params,
+ struct device *fec_device,
+ int check_fec,
+ unsigned int *errors);
+
+uint64_t VERITY_hash_offset_block(struct crypt_params_verity *params);
+
+uint64_t VERITY_hash_blocks(struct crypt_device *cd, struct crypt_params_verity *params);
+
+uint64_t VERITY_FEC_blocks(struct crypt_device *cd,
+ struct device *fec_device,
+ struct crypt_params_verity *params);
+uint64_t VERITY_FEC_RS_blocks(uint64_t blocks, uint32_t roots);
+
+int VERITY_UUID_generate(char **uuid_string);
+
+int VERITY_dump(struct crypt_device *cd,
+ struct crypt_params_verity *verity_hdr,
+ const char *root_hash,
+ unsigned int root_hash_size,
+ struct device *fec_device);
+
+#endif
diff --git a/lib/verity/verity_fec.c b/lib/verity/verity_fec.c
new file mode 100644
index 0000000..2dbf59e
--- /dev/null
+++ b/lib/verity/verity_fec.c
@@ -0,0 +1,336 @@
+/*
+ * dm-verity Forward Error Correction (FEC) support
+ *
+ * Copyright (C) 2015 Google, Inc. All rights reserved.
+ * Copyright (C) 2017-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "verity.h"
+#include "internal.h"
+#include "rs.h"
+
+/* ecc parameters */
+#define FEC_RSM 255
+#define FEC_MIN_RSN 231
+#define FEC_MAX_RSN 253
+
+#define FEC_INPUT_DEVICES 2
+
+/* parameters to init_rs_char */
+#define FEC_PARAMS(roots) \
+ 8, /* symbol size in bits */ \
+ 0x11d, /* field generator polynomial coefficients */ \
+ 0, /* first root of the generator */ \
+ 1, /* primitive element to generate polynomial roots */ \
+ (roots), /* polynomial degree (number of roots) */ \
+ 0 /* padding bytes at the front of shortened block */
+
+struct fec_input_device {
+ struct device *device;
+ int fd;
+ uint64_t start;
+ uint64_t count;
+};
+
+struct fec_context {
+ uint32_t rsn;
+ uint32_t roots;
+ uint64_t size;
+ uint64_t blocks;
+ uint64_t rounds;
+ uint32_t block_size;
+ struct fec_input_device *inputs;
+ size_t ninputs;
+};
+
+/* computes ceil(x / y) */
+static inline uint64_t FEC_div_round_up(uint64_t x, uint64_t y)
+{
+ return (x / y) + (x % y > 0 ? 1 : 0);
+}
+
+/* returns a physical offset for the given RS offset */
+static inline uint64_t FEC_interleave(struct fec_context *ctx, uint64_t offset)
+{
+ return (offset / ctx->rsn) +
+ (offset % ctx->rsn) * ctx->rounds * ctx->block_size;
+}
+
+/* returns data for a byte at the specified RS offset */
+static int FEC_read_interleaved(struct fec_context *ctx, uint64_t i,
+ void *output, size_t count)
+{
+ size_t n;
+ uint64_t offset = FEC_interleave(ctx, i);
+
+ /* offsets outside input area are assumed to contain zeros */
+ if (offset >= ctx->size) {
+ memset(output, 0, count);
+ return 0;
+ }
+
+ /* find the correct input device and read from it */
+ for (n = 0; n < ctx->ninputs; ++n) {
+ if (offset >= ctx->inputs[n].count) {
+ offset -= ctx->inputs[n].count;
+ continue;
+ }
+
+ /* FIXME: read_lseek_blockwise candidate */
+ if (lseek(ctx->inputs[n].fd, ctx->inputs[n].start + offset, SEEK_SET) < 0)
+ return -1;
+ return (read_buffer(ctx->inputs[n].fd, output, count) == (ssize_t)count) ? 0 : -1;
+ }
+
+ /* should never be reached */
+ return -1;
+}
+
+/* encodes/decode inputs to/from fd */
+static int FEC_process_inputs(struct crypt_device *cd,
+ struct crypt_params_verity *params,
+ struct fec_input_device *inputs,
+ size_t ninputs, int fd,
+ int decode, unsigned int *errors)
+{
+ int r = 0;
+ unsigned int i;
+ struct fec_context ctx;
+ uint32_t b;
+ uint64_t n;
+ uint8_t rs_block[FEC_RSM];
+ uint8_t *buf = NULL;
+ void *rs;
+
+ /* initialize parameters */
+ ctx.roots = params->fec_roots;
+ ctx.rsn = FEC_RSM - ctx.roots;
+ ctx.block_size = params->data_block_size;
+ ctx.inputs = inputs;
+ ctx.ninputs = ninputs;
+
+ rs = init_rs_char(FEC_PARAMS(ctx.roots));
+ if (!rs) {
+ log_err(cd, _("Failed to allocate RS context."));
+ return -ENOMEM;
+ }
+
+ /* calculate the total area covered by error correction codes */
+ ctx.size = 0;
+ for (n = 0; n < ctx.ninputs; ++n) {
+ log_dbg(cd, "FEC input %s, offset %" PRIu64 " [bytes], length %" PRIu64 " [bytes]",
+ device_path(ctx.inputs[n].device), ctx.inputs[n].start, ctx.inputs[n].count);
+ ctx.size += ctx.inputs[n].count;
+ }
+
+ /* each byte in a data block is covered by a different code */
+ ctx.blocks = FEC_div_round_up(ctx.size, ctx.block_size);
+ ctx.rounds = FEC_div_round_up(ctx.blocks, ctx.rsn);
+
+ buf = malloc((size_t)ctx.block_size * ctx.rsn);
+ if (!buf) {
+ log_err(cd, _("Failed to allocate buffer."));
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /* encode/decode input */
+ for (n = 0; n < ctx.rounds; ++n) {
+ for (i = 0; i < ctx.rsn; ++i) {
+ if (FEC_read_interleaved(&ctx, n * ctx.rsn * ctx.block_size + i,
+ &buf[i * ctx.block_size], ctx.block_size)) {
+ log_err(cd, _("Failed to read RS block %" PRIu64 " byte %d."), n, i);
+ r = -EIO;
+ goto out;
+ }
+ }
+
+ for (b = 0; b < ctx.block_size; ++b) {
+ for (i = 0; i < ctx.rsn; ++i)
+ rs_block[i] = buf[i * ctx.block_size + b];
+
+ /* decoding from parity device */
+ if (decode) {
+ if (read_buffer(fd, &rs_block[ctx.rsn], ctx.roots) < 0) {
+ log_err(cd, _("Failed to read parity for RS block %" PRIu64 "."), n);
+ r = -EIO;
+ goto out;
+ }
+
+ /* coverity[tainted_data] */
+ r = decode_rs_char(rs, rs_block);
+ if (r < 0) {
+ log_err(cd, _("Failed to repair parity for block %" PRIu64 "."), n);
+ r = -EPERM;
+ goto out;
+ }
+ /* return number of detected errors */
+ if (errors)
+ *errors += r;
+ r = 0;
+ } else {
+ /* encoding and writing parity data to fec device */
+ encode_rs_char(rs, rs_block, &rs_block[ctx.rsn]);
+ if (write_buffer(fd, &rs_block[ctx.rsn], ctx.roots) < 0) {
+ log_err(cd, _("Failed to write parity for RS block %" PRIu64 "."), n);
+ r = -EIO;
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ free_rs_char(rs);
+ free(buf);
+ return r;
+}
+
+static int VERITY_FEC_validate(struct crypt_device *cd, struct crypt_params_verity *params)
+{
+ if (params->data_block_size != params->hash_block_size) {
+ log_err(cd, _("Block sizes must match for FEC."));
+ return -EINVAL;
+ }
+
+ if (params->fec_roots > FEC_RSM - FEC_MIN_RSN ||
+ params->fec_roots < FEC_RSM - FEC_MAX_RSN) {
+ log_err(cd, _("Invalid number of parity bytes."));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int VERITY_FEC_process(struct crypt_device *cd,
+ struct crypt_params_verity *params,
+ struct device *fec_device, int check_fec,
+ unsigned int *errors)
+{
+ int r = -EIO, fd = -1;
+ size_t ninputs = FEC_INPUT_DEVICES;
+ struct fec_input_device inputs[FEC_INPUT_DEVICES] = {
+ {
+ .device = crypt_data_device(cd),
+ .fd = -1,
+ .start = 0,
+ .count = params->data_size * params->data_block_size
+ },{
+ .device = crypt_metadata_device(cd),
+ .fd = -1,
+ .start = VERITY_hash_offset_block(params) * params->data_block_size,
+ .count = (VERITY_FEC_blocks(cd, fec_device, params) - params->data_size) * params->data_block_size
+ }
+ };
+
+ /* validate parameters */
+ r = VERITY_FEC_validate(cd, params);
+ if (r < 0)
+ return r;
+
+ if (!inputs[0].count) {
+ log_err(cd, _("Invalid FEC segment length."));
+ return -EINVAL;
+ }
+ if (!inputs[1].count)
+ ninputs--;
+
+ if (check_fec)
+ fd = open(device_path(fec_device), O_RDONLY);
+ else
+ fd = open(device_path(fec_device), O_RDWR);
+
+ if (fd == -1) {
+ log_err(cd, _("Cannot open device %s."), device_path(fec_device));
+ goto out;
+ }
+
+ if (lseek(fd, params->fec_area_offset, SEEK_SET) < 0) {
+ log_dbg(cd, "Cannot seek to requested position in FEC device.");
+ goto out;
+ }
+
+ /* input devices */
+ inputs[0].fd = open(device_path(inputs[0].device), O_RDONLY);
+ if (inputs[0].fd == -1) {
+ log_err(cd, _("Cannot open device %s."), device_path(inputs[0].device));
+ goto out;
+ }
+ inputs[1].fd = open(device_path(inputs[1].device), O_RDONLY);
+ if (inputs[1].fd == -1) {
+ log_err(cd, _("Cannot open device %s."), device_path(inputs[1].device));
+ goto out;
+ }
+
+ r = FEC_process_inputs(cd, params, inputs, ninputs, fd, check_fec, errors);
+out:
+ if (inputs[0].fd != -1)
+ close(inputs[0].fd);
+ if (inputs[1].fd != -1)
+ close(inputs[1].fd);
+ if (fd != -1)
+ close(fd);
+
+ return r;
+}
+
+/* All blocks that are covered by FEC */
+uint64_t VERITY_FEC_blocks(struct crypt_device *cd,
+ struct device *fec_device,
+ struct crypt_params_verity *params)
+{
+ uint64_t blocks = 0;
+
+ if (!fec_device || VERITY_FEC_validate(cd, params) < 0)
+ return 0;
+
+ /*
+ * FEC covers this data:
+ * | protected data | hash area | padding (optional foreign metadata) |
+ *
+ * If hash device is in a separate image, metadata covers the whole rest of the image after hash area.
+ * If hash and FEC device is in the image, metadata ends on the FEC area offset.
+ */
+ if (device_is_identical(crypt_metadata_device(cd), fec_device) > 0) {
+ log_dbg(cd, "FEC and hash device is the same.");
+ blocks = params->fec_area_offset;
+ } else {
+ /* cover the entire hash device starting from hash_offset */
+ if (device_size(crypt_metadata_device(cd), &blocks)) {
+ log_err(cd, _("Failed to determine size for device %s."),
+ device_path(crypt_metadata_device(cd)));
+ return 0;
+ }
+ }
+
+ blocks /= params->data_block_size;
+ if (blocks)
+ blocks -= VERITY_hash_offset_block(params);
+
+ /* Protected data */
+ blocks += params->data_size;
+
+ return blocks;
+}
+
+/* Blocks needed to store FEC data, blocks must be validated/calculated by VERITY_FEC_blocks() */
+uint64_t VERITY_FEC_RS_blocks(uint64_t blocks, uint32_t roots)
+{
+ return FEC_div_round_up(blocks, FEC_RSM - roots) * roots;
+}
diff --git a/lib/verity/verity_hash.c b/lib/verity/verity_hash.c
new file mode 100644
index 0000000..f33b737
--- /dev/null
+++ b/lib/verity/verity_hash.c
@@ -0,0 +1,444 @@
+/*
+ * dm-verity volume handling
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "verity.h"
+#include "internal.h"
+
+#define VERITY_MAX_LEVELS 63
+#define VERITY_MAX_DIGEST_SIZE 1024
+
+static unsigned get_bits_up(size_t u)
+{
+ unsigned i = 0;
+ while ((1U << i) < u)
+ i++;
+ return i;
+}
+
+static unsigned get_bits_down(size_t u)
+{
+ unsigned i = 0;
+ while ((u >> i) > 1U)
+ i++;
+ return i;
+}
+
+static int verify_zero(struct crypt_device *cd, FILE *wr, size_t bytes)
+{
+ char *block = NULL;
+ size_t i;
+ int r;
+
+ block = malloc(bytes);
+ if (!block)
+ return -ENOMEM;
+
+ if (fread(block, bytes, 1, wr) != 1) {
+ log_dbg(cd, "EIO while reading spare area.");
+ r = -EIO;
+ goto out;
+ }
+ for (i = 0; i < bytes; i++)
+ if (block[i]) {
+ log_err(cd, _("Spare area is not zeroed at position %" PRIu64 "."),
+ ftello(wr) - bytes);
+ r = -EPERM;
+ goto out;
+ }
+ r = 0;
+out:
+ free(block);
+ return r;
+}
+
+static int verify_hash_block(const char *hash_name, int version,
+ char *hash, size_t hash_size,
+ const char *data, size_t data_size,
+ const char *salt, size_t salt_size)
+{
+ struct crypt_hash *ctx = NULL;
+ int r;
+
+ if (crypt_hash_init(&ctx, hash_name))
+ return -EINVAL;
+
+ if (version == 1 && (r = crypt_hash_write(ctx, salt, salt_size)))
+ goto out;
+
+ if ((r = crypt_hash_write(ctx, data, data_size)))
+ goto out;
+
+ if (version == 0 && (r = crypt_hash_write(ctx, salt, salt_size)))
+ goto out;
+
+ r = crypt_hash_final(ctx, hash, hash_size);
+out:
+ crypt_hash_destroy(ctx);
+ return r;
+}
+
+static int hash_levels(size_t hash_block_size, size_t digest_size,
+ uint64_t data_file_blocks, uint64_t *hash_position, int *levels,
+ uint64_t *hash_level_block, uint64_t *hash_level_size)
+{
+ size_t hash_per_block_bits;
+ uint64_t s, s_shift;
+ int i;
+
+ if (!digest_size)
+ return -EINVAL;
+
+ hash_per_block_bits = get_bits_down(hash_block_size / digest_size);
+ if (!hash_per_block_bits)
+ return -EINVAL;
+
+ *levels = 0;
+ while (hash_per_block_bits * *levels < 64 &&
+ (data_file_blocks - 1) >> (hash_per_block_bits * *levels))
+ (*levels)++;
+
+ if (*levels > VERITY_MAX_LEVELS)
+ return -EINVAL;
+
+ for (i = *levels - 1; i >= 0; i--) {
+ if (hash_level_block)
+ hash_level_block[i] = *hash_position;
+ // verity position of block data_file_blocks at level i
+ s_shift = (i + 1) * hash_per_block_bits;
+ if (s_shift > 63)
+ return -EINVAL;
+ s = (data_file_blocks + ((uint64_t)1 << s_shift) - 1) >> ((i + 1) * hash_per_block_bits);
+ if (hash_level_size)
+ hash_level_size[i] = s;
+ if ((*hash_position + s) < *hash_position)
+ return -EINVAL;
+ *hash_position += s;
+ }
+
+ return 0;
+}
+
+static int create_or_verify(struct crypt_device *cd, FILE *rd, FILE *wr,
+ uint64_t data_block, size_t data_block_size,
+ uint64_t hash_block, size_t hash_block_size,
+ uint64_t blocks, int version,
+ const char *hash_name, int verify,
+ char *calculated_digest, size_t digest_size,
+ const char *salt, size_t salt_size)
+{
+ char *left_block, *data_buffer;
+ char read_digest[VERITY_MAX_DIGEST_SIZE];
+ size_t hash_per_block = 1 << get_bits_down(hash_block_size / digest_size);
+ size_t digest_size_full = 1 << get_bits_up(digest_size);
+ uint64_t blocks_to_write = (blocks + hash_per_block - 1) / hash_per_block;
+ uint64_t seek_rd, seek_wr;
+ size_t left_bytes;
+ unsigned i;
+ int r;
+
+ if (digest_size > sizeof(read_digest))
+ return -EINVAL;
+
+ if (uint64_mult_overflow(&seek_rd, data_block, data_block_size) ||
+ uint64_mult_overflow(&seek_wr, hash_block, hash_block_size)) {
+ log_err(cd, _("Device offset overflow."));
+ return -EINVAL;
+ }
+
+ if (fseeko(rd, seek_rd, SEEK_SET)) {
+ log_dbg(cd, "Cannot seek to requested position in data device.");
+ return -EIO;
+ }
+
+ if (wr && fseeko(wr, seek_wr, SEEK_SET)) {
+ log_dbg(cd, "Cannot seek to requested position in hash device.");
+ return -EIO;
+ }
+
+ left_block = malloc(hash_block_size);
+ data_buffer = malloc(data_block_size);
+ if (!left_block || !data_buffer) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ memset(left_block, 0, hash_block_size);
+ while (blocks_to_write--) {
+ left_bytes = hash_block_size;
+ for (i = 0; i < hash_per_block; i++) {
+ if (!blocks)
+ break;
+ blocks--;
+ if (fread(data_buffer, data_block_size, 1, rd) != 1) {
+ log_dbg(cd, "Cannot read data device block.");
+ r = -EIO;
+ goto out;
+ }
+
+ if (verify_hash_block(hash_name, version,
+ calculated_digest, digest_size,
+ data_buffer, data_block_size,
+ salt, salt_size)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!wr)
+ break;
+ if (verify) {
+ if (fread(read_digest, digest_size, 1, wr) != 1) {
+ log_dbg(cd, "Cannot read digest form hash device.");
+ r = -EIO;
+ goto out;
+ }
+ if (crypt_backend_memeq(read_digest, calculated_digest, digest_size)) {
+ log_err(cd, _("Verification failed at position %" PRIu64 "."),
+ ftello(rd) - data_block_size);
+ r = -EPERM;
+ goto out;
+ }
+ } else {
+ if (fwrite(calculated_digest, digest_size, 1, wr) != 1) {
+ log_dbg(cd, "Cannot write digest to hash device.");
+ r = -EIO;
+ goto out;
+ }
+ }
+ if (version == 0) {
+ left_bytes -= digest_size;
+ } else {
+ if (digest_size_full - digest_size) {
+ if (verify) {
+ r = verify_zero(cd, wr, digest_size_full - digest_size);
+ if (r)
+ goto out;
+ } else if (fwrite(left_block, digest_size_full - digest_size, 1, wr) != 1) {
+ log_dbg(cd, "Cannot write spare area to hash device.");
+ r = -EIO;
+ goto out;
+ }
+ }
+ left_bytes -= digest_size_full;
+ }
+ }
+ if (wr && left_bytes) {
+ if (verify) {
+ r = verify_zero(cd , wr, left_bytes);
+ if (r)
+ goto out;
+ } else if (fwrite(left_block, left_bytes, 1, wr) != 1) {
+ log_dbg(cd, "Cannot write remaining spare area to hash device.");
+ r = -EIO;
+ goto out;
+ }
+ }
+ }
+ r = 0;
+out:
+ free(left_block);
+ free(data_buffer);
+ return r;
+}
+
+static int VERITY_create_or_verify_hash(struct crypt_device *cd, bool verify,
+ struct crypt_params_verity *params,
+ char *root_hash, size_t digest_size)
+{
+ char calculated_digest[VERITY_MAX_DIGEST_SIZE];
+ FILE *data_file = NULL;
+ FILE *hash_file = NULL, *hash_file_2;
+ uint64_t hash_level_block[VERITY_MAX_LEVELS];
+ uint64_t hash_level_size[VERITY_MAX_LEVELS];
+ uint64_t data_file_blocks;
+ uint64_t data_device_offset_max = 0, hash_device_offset_max = 0;
+ uint64_t hash_position = VERITY_hash_offset_block(params);
+ uint64_t dev_size;
+ int levels, i, r;
+
+ log_dbg(cd, "Hash %s %s, data device %s, data blocks %" PRIu64
+ ", hash_device %s, offset %" PRIu64 ".",
+ verify ? "verification" : "creation", params->hash_name,
+ device_path(crypt_data_device(cd)), params->data_size,
+ device_path(crypt_metadata_device(cd)), hash_position);
+
+ if (digest_size > sizeof(calculated_digest))
+ return -EINVAL;
+
+ if (!params->data_size) {
+ r = device_size(crypt_data_device(cd), &dev_size);
+ if (r < 0)
+ return r;
+
+ data_file_blocks = dev_size / params->data_block_size;
+ } else
+ data_file_blocks = params->data_size;
+
+ if (uint64_mult_overflow(&data_device_offset_max, params->data_size, params->data_block_size)) {
+ log_err(cd, _("Device offset overflow."));
+ return -EINVAL;
+ }
+ log_dbg(cd, "Data device size required: %" PRIu64 " bytes.", data_device_offset_max);
+
+ if (hash_levels(params->hash_block_size, digest_size, data_file_blocks, &hash_position,
+ &levels, &hash_level_block[0], &hash_level_size[0])) {
+ log_err(cd, _("Hash area overflow."));
+ return -EINVAL;
+ }
+ if (uint64_mult_overflow(&hash_device_offset_max, hash_position, params->hash_block_size)) {
+ log_err(cd, _("Device offset overflow."));
+ return -EINVAL;
+ }
+ log_dbg(cd, "Hash device size required: %" PRIu64 " bytes.",
+ hash_device_offset_max - params->hash_area_offset);
+ log_dbg(cd, "Using %d hash levels.", levels);
+
+ data_file = fopen(device_path(crypt_data_device(cd)), "r");
+ if (!data_file) {
+ log_err(cd, _("Cannot open device %s."),
+ device_path(crypt_data_device(cd))
+ );
+ r = -EIO;
+ goto out;
+ }
+
+ hash_file = fopen(device_path(crypt_metadata_device(cd)), verify ? "r" : "r+");
+ if (!hash_file) {
+ log_err(cd, _("Cannot open device %s."),
+ device_path(crypt_metadata_device(cd)));
+ r = -EIO;
+ goto out;
+ }
+
+ memset(calculated_digest, 0, digest_size);
+
+ for (i = 0; i < levels; i++) {
+ if (!i) {
+ r = create_or_verify(cd, data_file, hash_file,
+ 0, params->data_block_size,
+ hash_level_block[i], params->hash_block_size,
+ data_file_blocks, params->hash_type, params->hash_name, verify,
+ calculated_digest, digest_size, params->salt, params->salt_size);
+ if (r)
+ goto out;
+ } else {
+ hash_file_2 = fopen(device_path(crypt_metadata_device(cd)), "r");
+ if (!hash_file_2) {
+ log_err(cd, _("Cannot open device %s."),
+ device_path(crypt_metadata_device(cd)));
+ r = -EIO;
+ goto out;
+ }
+ r = create_or_verify(cd, hash_file_2, hash_file,
+ hash_level_block[i - 1], params->hash_block_size,
+ hash_level_block[i], params->hash_block_size,
+ hash_level_size[i - 1], params->hash_type, params->hash_name, verify,
+ calculated_digest, digest_size, params->salt, params->salt_size);
+ fclose(hash_file_2);
+ if (r)
+ goto out;
+ }
+ }
+
+ if (levels)
+ r = create_or_verify(cd, hash_file, NULL,
+ hash_level_block[levels - 1], params->hash_block_size,
+ 0, params->hash_block_size,
+ 1, params->hash_type, params->hash_name, verify,
+ calculated_digest, digest_size, params->salt, params->salt_size);
+ else
+ r = create_or_verify(cd, data_file, NULL,
+ 0, params->data_block_size,
+ 0, params->hash_block_size,
+ data_file_blocks, params->hash_type, params->hash_name, verify,
+ calculated_digest, digest_size, params->salt, params->salt_size);
+out:
+ if (verify) {
+ if (r)
+ log_err(cd, _("Verification of data area failed."));
+ else {
+ log_dbg(cd, "Verification of data area succeeded.");
+ r = crypt_backend_memeq(root_hash, calculated_digest, digest_size) ? -EFAULT : 0;
+ if (r)
+ log_err(cd, _("Verification of root hash failed."));
+ else
+ log_dbg(cd, "Verification of root hash succeeded.");
+ }
+ } else {
+ if (r == -EIO)
+ log_err(cd, _("Input/output error while creating hash area."));
+ else if (r)
+ log_err(cd, _("Creation of hash area failed."));
+ else {
+ fsync(fileno(hash_file));
+ memcpy(root_hash, calculated_digest, digest_size);
+ }
+ }
+
+ if (data_file)
+ fclose(data_file);
+ if (hash_file)
+ fclose(hash_file);
+ return r;
+}
+
+/* Verify verity device using userspace crypto backend */
+int VERITY_verify(struct crypt_device *cd,
+ struct crypt_params_verity *verity_hdr,
+ const char *root_hash,
+ size_t root_hash_size)
+{
+ return VERITY_create_or_verify_hash(cd, 1, verity_hdr, CONST_CAST(char*)root_hash, root_hash_size);
+}
+
+/* Create verity hash */
+int VERITY_create(struct crypt_device *cd,
+ struct crypt_params_verity *verity_hdr,
+ const char *root_hash,
+ size_t root_hash_size)
+{
+ unsigned pgsize = (unsigned)crypt_getpagesize();
+
+ if (verity_hdr->salt_size > 256)
+ return -EINVAL;
+
+ if (verity_hdr->data_block_size > pgsize)
+ log_err(cd, _("WARNING: Kernel cannot activate device if data "
+ "block size exceeds page size (%u)."), pgsize);
+
+ return VERITY_create_or_verify_hash(cd, 0, verity_hdr, CONST_CAST(char*)root_hash, root_hash_size);
+}
+
+uint64_t VERITY_hash_blocks(struct crypt_device *cd, struct crypt_params_verity *params)
+{
+ uint64_t hash_position = 0;
+ int levels = 0;
+
+ if (hash_levels(params->hash_block_size, crypt_get_volume_key_size(cd),
+ params->data_size, &hash_position, &levels, NULL, NULL))
+ return 0;
+
+ return (uint64_t)hash_position;
+}
diff --git a/lib/volumekey.c b/lib/volumekey.c
new file mode 100644
index 0000000..00791ac
--- /dev/null
+++ b/lib/volumekey.c
@@ -0,0 +1,147 @@
+/*
+ * cryptsetup volume key implementation
+ *
+ * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "internal.h"
+
+struct volume_key *crypt_alloc_volume_key(size_t keylength, const char *key)
+{
+ struct volume_key *vk;
+
+ if (keylength > (SIZE_MAX - sizeof(*vk)))
+ return NULL;
+
+ vk = malloc(sizeof(*vk) + keylength);
+ if (!vk)
+ return NULL;
+
+ vk->key_description = NULL;
+ vk->keylength = keylength;
+ vk->id = -1;
+ vk->next = NULL;
+
+ /* keylength 0 is valid => no key */
+ if (vk->keylength) {
+ if (key)
+ memcpy(&vk->key, key, keylength);
+ else
+ crypt_safe_memzero(&vk->key, keylength);
+ }
+
+ return vk;
+}
+
+int crypt_volume_key_set_description(struct volume_key *vk, const char *key_description)
+{
+ if (!vk)
+ return -EINVAL;
+
+ free(CONST_CAST(void*)vk->key_description);
+ vk->key_description = NULL;
+ if (key_description && !(vk->key_description = strdup(key_description)))
+ return -ENOMEM;
+
+ return 0;
+}
+
+void crypt_volume_key_set_id(struct volume_key *vk, int id)
+{
+ if (vk && id >= 0)
+ vk->id = id;
+}
+
+int crypt_volume_key_get_id(const struct volume_key *vk)
+{
+ return vk ? vk->id : -1;
+}
+
+struct volume_key *crypt_volume_key_by_id(struct volume_key *vks, int id)
+{
+ struct volume_key *vk = vks;
+
+ if (id < 0)
+ return NULL;
+
+ while (vk && vk->id != id)
+ vk = vk->next;
+
+ return vk;
+}
+
+void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk)
+{
+ struct volume_key *tmp;
+
+ if (!vks)
+ return;
+
+ if (!*vks) {
+ *vks = vk;
+ return;
+ }
+
+ tmp = *vks;
+
+ while (tmp->next)
+ tmp = tmp->next;
+
+ tmp->next = vk;
+}
+
+struct volume_key *crypt_volume_key_next(struct volume_key *vk)
+{
+ return vk ? vk->next : NULL;
+}
+
+void crypt_free_volume_key(struct volume_key *vk)
+{
+ struct volume_key *vk_next;
+
+ while (vk) {
+ crypt_safe_memzero(vk->key, vk->keylength);
+ vk->keylength = 0;
+ free(CONST_CAST(void*)vk->key_description);
+ vk_next = vk->next;
+ free(vk);
+ vk = vk_next;
+ }
+}
+
+struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t keylength)
+{
+ int r;
+ struct volume_key *vk;
+
+ vk = crypt_alloc_volume_key(keylength, NULL);
+ if (!vk)
+ return NULL;
+
+ r = crypt_random_get(cd, vk->key, keylength, CRYPT_RND_KEY);
+ if(r < 0) {
+ crypt_free_volume_key(vk);
+ return NULL;
+ }
+ return vk;
+}
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..bd753b3
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,53 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 6
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_VAR_IF(CACHEVAR,yes,
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/man/Makemodule.am b/man/Makemodule.am
new file mode 100644
index 0000000..41e21da
--- /dev/null
+++ b/man/Makemodule.am
@@ -0,0 +1,145 @@
+ADOCFILES_COMMON = \
+ man/common_options.adoc \
+ man/common_footer.adoc
+
+ADOCFILES = $(ADOCFILES_COMMON) \
+ man/cryptsetup.8.adoc \
+ man/cryptsetup-open.8.adoc \
+ man/cryptsetup-close.8.adoc \
+ man/cryptsetup-reencrypt.8.adoc \
+ man/cryptsetup-status.8.adoc \
+ man/cryptsetup-resize.8.adoc \
+ man/cryptsetup-refresh.8.adoc \
+ man/cryptsetup-luksFormat.8.adoc \
+ man/cryptsetup-luksSuspend.8.adoc \
+ man/cryptsetup-luksResume.8.adoc \
+ man/cryptsetup-luksAddKey.8.adoc \
+ man/cryptsetup-luksRemoveKey.8.adoc \
+ man/cryptsetup-luksConvertKey.8.adoc \
+ man/cryptsetup-luksKillSlot.8.adoc \
+ man/cryptsetup-luksChangeKey.8.adoc \
+ man/cryptsetup-erase.8.adoc \
+ man/cryptsetup-luksUUID.8.adoc \
+ man/cryptsetup-isLuks.8.adoc \
+ man/cryptsetup-luksDump.8.adoc \
+ man/cryptsetup-luksHeaderBackup.8.adoc \
+ man/cryptsetup-luksHeaderRestore.8.adoc \
+ man/cryptsetup-token.8.adoc \
+ man/cryptsetup-convert.8.adoc \
+ man/cryptsetup-config.8.adoc \
+ man/cryptsetup-tcryptDump.8.adoc \
+ man/cryptsetup-bitlkDump.8.adoc \
+ man/cryptsetup-fvault2Dump.8.adoc \
+ man/cryptsetup-repair.8.adoc \
+ man/cryptsetup-benchmark.8.adoc \
+ man/cryptsetup-ssh.8.adoc \
+ man/veritysetup.8.adoc \
+ man/integritysetup.8.adoc
+
+dist_noinst_DATA += $(ADOCFILES)
+
+CRYPTSETUP_MANPAGES = \
+ man/cryptsetup.8 \
+ man/cryptsetup-open.8 \
+ man/cryptsetup-close.8 \
+ man/cryptsetup-reencrypt.8 \
+ man/cryptsetup-status.8 \
+ man/cryptsetup-resize.8 \
+ man/cryptsetup-refresh.8 \
+ man/cryptsetup-luksFormat.8 \
+ man/cryptsetup-luksSuspend.8 \
+ man/cryptsetup-luksResume.8 \
+ man/cryptsetup-luksAddKey.8 \
+ man/cryptsetup-luksRemoveKey.8 \
+ man/cryptsetup-luksConvertKey.8 \
+ man/cryptsetup-luksKillSlot.8 \
+ man/cryptsetup-luksChangeKey.8 \
+ man/cryptsetup-erase.8 \
+ man/cryptsetup-luksUUID.8 \
+ man/cryptsetup-isLuks.8 \
+ man/cryptsetup-luksDump.8 \
+ man/cryptsetup-luksHeaderBackup.8 \
+ man/cryptsetup-luksHeaderRestore.8 \
+ man/cryptsetup-token.8 \
+ man/cryptsetup-convert.8 \
+ man/cryptsetup-config.8 \
+ man/cryptsetup-tcryptDump.8 \
+ man/cryptsetup-bitlkDump.8 \
+ man/cryptsetup-fvault2Dump.8 \
+ man/cryptsetup-repair.8 \
+ man/cryptsetup-benchmark.8
+
+CRYPTSETUP_MANLINKS = \
+ man/cryptsetup-create.8 \
+ man/cryptsetup-plainOpen.8 \
+ man/cryptsetup-luksOpen.8 \
+ man/cryptsetup-loopaesOpen.8 \
+ man/cryptsetup-tcryptOpen.8 \
+ man/cryptsetup-bitlkOpen.8 \
+ man/cryptsetup-fvault2Open.8 \
+ man/cryptsetup-luksErase.8
+
+VERITYSETUP_MANPAGES = man/veritysetup.8
+INTEGRITYSETUP_MANPAGES = man/integritysetup.8
+SSHPLUGIN_MANPAGES = man/cryptsetup-ssh.8
+
+MANPAGES_ALL = \
+ $(CRYPTSETUP_MANPAGES) \
+ $(CRYPTSETUP_MANLINKS) \
+ $(VERITYSETUP_MANPAGES) \
+ $(INTEGRITYSETUP_MANPAGES) \
+ $(SSHPLUGIN_MANPAGES)
+
+MANPAGES =
+MANLINKS =
+
+if CRYPTSETUP
+MANPAGES += $(CRYPTSETUP_MANPAGES)
+MANLINKS += $(CRYPTSETUP_MANLINKS)
+endif
+if VERITYSETUP
+MANPAGES += $(VERITYSETUP_MANPAGES)
+endif
+if INTEGRITYSETUP
+MANPAGES += $(INTEGRITYSETUP_MANPAGES)
+endif
+if SSHPLUGIN_TOKEN
+MANPAGES += $(SSHPLUGIN_MANPAGES)
+endif
+
+if ENABLE_ASCIIDOC
+EXTRA_DIST += $(MANPAGES_ALL)
+man8_MANS += $(MANPAGES) $(MANLINKS)
+
+$(MANPAGES): $(ADOCFILES_COMMON)
+
+SUFFIXES = .8.adoc .8
+.8.adoc.8:
+ $(AM_V_GEN) $(ASCIIDOCTOR) -b manpage \
+ -a 'release-version=$(VERSION)' \
+ --base-dir=$(abs_srcdir) \
+ --destination-dir $(abs_builddir)/man $<
+
+$(MANLINKS): $(MANPAGES)
+gen-man: $(man8_MANS)
+
+gen-man-dist:
+ @list=`find -name *.adoc -not -path "*/man/common_*" | sed -e 's/\.adoc//g'`; \
+ missing=`for p in $$list; do test -f $$p || echo $$p; done`; \
+ if test -n "$$missing"; then \
+ $(MAKE) $(AM_MAKEFLAGS) $$missing; \
+ fi;
+
+# !ENABLE_ASCIIDOC
+else
+
+if HAVE_MANPAGES
+EXTRA_DIST += $(MANPAGES_ALL)
+man8_MANS += $(MANPAGES) $(MANLINKS)
+endif
+
+gen-man:
+gen-man-dist:
+endif
+
+dist-hook: gen-man-dist
diff --git a/man/common_footer.adoc b/man/common_footer.adoc
new file mode 100644
index 0000000..21302eb
--- /dev/null
+++ b/man/common_footer.adoc
@@ -0,0 +1,17 @@
+
+== REPORTING BUGS
+
+Report bugs at mailto:cryptsetup@lists.linux.dev[*cryptsetup mailing list*]
+or in https://gitlab.com/cryptsetup/cryptsetup/-/issues/new[*Issues project section*].
+
+Please attach output of the failed command with --debug option added.
+
+== SEE ALSO
+
+https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions[*Cryptsetup FAQ*]
+
+*cryptsetup*(8), *integritysetup*(8) and *veritysetup*(8)
+
+== CRYPTSETUP
+
+Part of https://gitlab.com/cryptsetup/cryptsetup/[*cryptsetup project*].
diff --git a/man/common_options.adoc b/man/common_options.adoc
new file mode 100644
index 0000000..56a6e29
--- /dev/null
+++ b/man/common_options.adoc
@@ -0,0 +1,1195 @@
+== OPTIONS
+
+ifdef::ACTION_REENCRYPT[]
+*--block-size* _value_ *(LUKS1 only)*::
+Use re-encryption block size of _value_ in MiB.
++
+Values can be between 1 and 64 MiB.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--use-directio (LUKS1 only)*::
+Use direct-io (O_DIRECT) for all read/write data operations related
+to block device undergoing reencryption.
++
+Useful if direct-io operations perform better than normal buffered
+operations (e.g. in virtual environments).
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--use-fsync (LUKS1 only)*::
+Use fsync call after every written block. This applies for reencryption
+log files as well.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--write-log (LUKS1 only)*::
+Update log file after every block write. This can slow down reencryption
+but will minimize data loss in the case of system crash.
+endif::[]
+
+ifdef::ACTION_ISLUKS[]
+*--verbose, -v*::
+Print more information on command execution.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_LUKSRESUME,ACTION_LUKSADDKEY,ACTION_LUKSREMOVEKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSKILLSLOT,ACTION_ISLUKS,ACTION_LUKSDUMP,ACTION_LUKSUUID,ACTION_CONVERT,ACTION_REPAIR,ACTION_REENCRYPT[]
+*--type <device-type>*::
+ifndef::ACTION_REENCRYPT[]
+Specifies required device type, for more info read _BASIC ACTIONS_ section in *cryptsetup*(8).
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+Specifies required (encryption mode) or expected (other modes) LUKS format. Accepts only _luks1_ or _luks2_.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_TCRYPTDUMP,ACTION_BENCHMARK,ACTION_REENCRYPT[]
+*--hash, -h* _<hash-spec>_::
+ifdef::ACTION_OPEN,ACTION_TCRYPTDUMP[]
+Specifies the passphrase hash. Applies to _plain_ and _loopaes_ device types only.
++
+For _tcrypt_ device type, it restricts checked PBKDF2 variants when looking for header.
+endif::[]
+ifdef::ACTION_LUKSFORMAT[]
+Specifies the hash used in the LUKS key setup scheme and volume key
+digest.
+endif::[]
+ifndef::ACTION_REENCRYPT,ACTION_OPEN,ACTION_TCRYPTDUMP[]
+The specified hash is used for PBKDF2 and AF splitter.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+*LUKS1:*
+Specifies the hash used in the LUKS1 key setup scheme and volume key digest.
++
+*NOTE*: if this parameter is not specified, default hash algorithm is always used
+for new LUKS1 device header.
++
+*LUKS2:* Ignored unless new keyslot pbkdf algorithm is set to PBKDF2 (see --pbkdf).
+endif::[]
++
+ifdef::ACTION_LUKSFORMAT[]
+The hash algorithm must provide at least 160 bits of output.
+Do not use a non-crypto hash like *xxhash* as this breaks security.
+Use _cryptsetup --help_ to show the defaults.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_REENCRYPT,ACTION_TCRYPTDUMP,ACTION_BENCHMARK[]
+*--cipher, -c* _<cipher-spec>_::
+ifdef::ACTION_OPEN,ACTION_TCRYPTDUMP[]
+Set the cipher specification string for _plain_ device type.
++
+For _tcrypt_ device type it restricts checked cipher chains when looking for header.
+endif::[]
+ifndef::ACTION_REENCRYPT,ACTION_OPEN,ACTION_TCRYPTDUMP[]
+Set the cipher specification string.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+*LUKS2*:
+Set the cipher specification string for data segment only.
++
+*LUKS1*:
+Set the cipher specification string for data segment and keyslots.
++
+*NOTE*: In encrypt mode, if cipher specification is omitted the default cipher is applied.
+In reencrypt mode, if no new cipher specification is requested, the existing cipher will remain
+in use. Unless the existing cipher was "cipher_null". In that case default cipher would
+be applied as in encrypt mode.
+endif::[]
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
++
+_cryptsetup --help_ shows the compiled-in defaults.
++
+If a hash is part of the cipher specification, then it is used as part
+of the IV generation. For example, ESSIV needs a hash function, while
+"plain64" does not and hence none is specified.
++
+For XTS mode you can optionally set a key size of 512 bits with the -s
+option. Key size for XTS mode is twice that for other modes for the same
+security level.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSFORMAT,ACTION_LUKSRESUME,ACTION_LUKSADDKEY,ACTION_LUKSREMOVEKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_LUKSKILLSLOT,ACTION_REPAIR,ACTION_TCRYPTDUMP,ACTION_REENCRYPT[]
+*--verify-passphrase, -y*::
+When interactively asking for a passphrase, ask for it twice and
+complain if both inputs do not match.
+ifdef::ACTION_OPEN[]
+Advised when creating a _plain_ type mapping for the first time.
+endif::[]
+Ignored on input from file or stdin.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSFORMAT,ACTION_LUKSRESUME,ACTION_LUKSADDKEY,ACTION_LUKSREMOVEKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_LUKSKILLSLOT,ACTION_LUKSDUMP,ACTION_TCRYPTDUMP,ACTION_REENCRYPT,ACTION_REPAIR,ACTION_BITLKDUMP[]
+*--key-file, -d* _name_::
+Read the passphrase from file.
++
+If the name given is "-", then the passphrase will be read from stdin.
+In this case, reading will not stop at newline characters.
++
+ifdef::ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY[]
+The passphrase supplied via --key-file is always the passphrase for existing
+keyslot requested by the command.
++
+If you want to set a new passphrase via key file, you have to use a
+positional argument or parameter --new-keyfile.
++
+endif::[]
+ifdef::ACTION_OPEN[]
+*NOTE:* With _plain_ device type, the passphrase obtained via --key-file option is
+passed directly in dm-crypt. Unlike the interactive mode (stdin)
+where digest (--hash option) of the passphrase is passed in dm-crypt instead.
++
+endif::[]
+ifndef::ACTION_REENCRYPT[]
+See section _NOTES ON PASSPHRASE PROCESSING_ in *cryptsetup*(8) for more information.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+*WARNING:* --key-file option can be used only if there is only one active keyslot,
+or alternatively, also if --key-slot option is specified (then all other keyslots
+will be disabled in new LUKS device).
++
+If this option is not used, cryptsetup will ask for all active keyslot
+passphrases.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSFORMAT,ACTION_LUKSRESUME,ACTION_LUKSADDKEY,ACTION_LUKSREMOVEKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_LUKSKILLSLOT,ACTION_LUKSDUMP,ACTION_REENCRYPT,ACTION_REPAIR,ACTION_BITLKDUMP[]
+*--keyfile-offset* _value_::
+Skip _value_ bytes at the beginning of the key file.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSFORMAT,ACTION_LUKSRESUME,ACTION_LUKSADDKEY,ACTION_LUKSREMOVEKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_LUKSKILLSLOT,ACTION_LUKSDUMP,ACTION_REENCRYPT,ACTION_REPAIR,ACTION_BITLKDUMP[]
+*--keyfile-size, -l* _value_::
+Read a maximum of _value_ bytes from the key file. The default is to
+read the whole file up to the compiled-in maximum that can be queried
+with --help. Supplying more data than the compiled-in maximum aborts
+the operation.
++
+This option is useful to cut trailing newlines, for example. If
+--keyfile-offset is also given, the size count starts after the offset.
+endif::[]
+
+ifdef::ACTION_LUKSADDKEY[]
+*--new-keyfile* _name_::
+Read the passphrase for a new keyslot from file.
++
+If the name given is "-", then the passphrase will be read from stdin.
+In this case, reading will not stop at newline characters.
++
+This is alternative method to positional argument when adding new
+passphrase via kefile.
+endif::[]
+
+ifdef::ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY[]
+*--new-keyfile-offset* _value_::
+Skip _value_ bytes at the start when adding a new passphrase from key
+file.
+endif::[]
+
+ifdef::ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY[]
+*--new-keyfile-size* _value_::
+Read a maximum of _value_ bytes when adding a new passphrase from key
+file. The default is to read the whole file up to
+the compiled-in maximum length that can be queried with --help.
+Supplying more than the compiled in maximum aborts the operation. When
+--new-keyfile-offset is also given, reading starts after the offset.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSDUMP,ACTION_BITLKDUMP,ACTION_REENCRYPT[]
+*--volume-key-file, --master-key-file (OBSOLETE alias)*::
+ifndef::ACTION_REENCRYPT[]
+Use a volume key stored in a file.
+endif::[]
+ifdef::ACTION_FORMAT[]
++
+This allows creating a LUKS header with this specific
+volume key. If the volume key was taken from an existing LUKS header and
+all other parameters are the same, then the new header decrypts the data
+encrypted with the header the volume key was taken from. +
+endif::[]
+ifdef::ACTION_LUKSDUMP,ACTION_BITLKDUMP[]
+The volume key is stored in a file instead of being printed out to standard output. +
+endif::[]
+ifdef::ACTION_LUKSADDKEY[]
+This allows adding a new keyslot without having to know passphrase to existing one.
+It may be also used when no keyslot is active.
++
+endif::[]
+ifdef::ACTION_OPEN[]
+This allows one to open _luks_ and _bitlk_ device types without giving a passphrase. +
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+Use (set) new volume key stored in a file. +
+endif::[]
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_REENCRYPT[]
+*WARNING:* If you create your own volume key, you need to make sure to
+do it right. Otherwise, you can end up with a low-entropy or otherwise
+partially predictable volume key which will compromise security.
+endif::[]
+endif::[]
+
+ifdef::ACTION_LUKSDUMP[]
+*--dump-json-metadata*::
+For _luksDump_ (LUKS2 only) this option prints content of LUKS2 header
+JSON metadata area.
+endif::[]
+
+ifdef::ACTION_LUKSDUMP,ACTION_TCRYPTDUMP,ACTION_BITLKDUMP[]
+*--dump-volume-key, --dump-master-key (OBSOLETE alias)*::
+Print the volume key in the displayed information. Use with care,
+as the volume key can be used to bypass
+the passphrases, see also option --volume-key-file.
+endif::[]
+
+ifdef::ACTION_TOKEN[]
+*--json-file*::
+Read token JSON from a file or write token to it. --json-file=- reads JSON from
+standard input or writes it to standard output respectively.
+endif::[]
+
+ifdef::ACTION_TOKEN[]
+*--token-replace*::
+Replace an existing token when adding or importing a token with the
+--token-id option.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--use-random*::
+*--use-urandom*::
+ifdef::ACTION_REENCRYPT[]
+Define which kernel random number generator will be used to create the volume key.
+endif::[]
+ifndef::ACTION_REENCRYPT[]
+For _luksFormat_ these options define which kernel random number
+generator will be used to create the volume key (which is a long-term
+key).
++
+See *NOTES ON RANDOM NUMBER GENERATORS* in *cryptsetup*(8) for more
+information. Use _cryptsetup --help_ to show the compiled-in default random
+number generator.
++
+*WARNING:* In a low-entropy situation (e.g. in an embedded system) and older
+kernels, both selections are problematic. Using /dev/urandom can lead to weak keys.
+Using /dev/random can block a long time, potentially forever, if not
+enough entropy can be harvested by the kernel.
+endif::[]
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--keep-key*::
+*LUKS2*:
+Do not change effective volume key and change other parameters provided
+it is requested.
++
+*LUKS1*:
+Reencrypt only the LUKS1 header and keyslots. Skips data in-place reencryption.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_LUKSDUMP,ACTION_LUKSRESUME,ACTION_TOKEN,ACTION_CONFIG,ACTION_TOKEN,ACTION_REPAIR,ACTION_REENCRYPT[]
+*--key-slot, -S <0-N>*::
+ifdef::ACTION_LUKSADDKEY[]
+When used together with parameter --new-key-slot this option allows you to specify which
+key slot is selected for unlocking volume key.
++
+*NOTE:* This option is ignored if existing volume key gets unlocked
+via LUKS2 token (--token-id, --token-type or --token-only parameters) or
+when volume key is provided directly via --volume-key-file parameter.
++
+*NOTE:* To maintain backward compatibility, without --new-key-slot parameter,
+this option allows you to specify which key slot is selected for the new key.
+endif::[]
+ifndef::ACTION_OPEN,ACTION_LUKSADDKEY[]
+For LUKS operations that add key material, this option allows you to
+specify which key slot is selected for the new key.
+endif::[]
+ifdef::ACTION_OPEN[]
+This option selects a specific key-slot to
+compare the passphrase against. If the given passphrase would only
+match a different key-slot, the operation fails.
+endif::[]
++
+ifdef::ACTION_REENCRYPT[]
+For reencryption mode it selects specific keyslot (and passphrase) that can be used to unlock new volume key.
+If used all other keyslots get removed after reencryption operation is finished.
++
+endif::[]
+The maximum number of key slots depends on the LUKS version. LUKS1 can have up
+to 8 key slots. LUKS2 can have up to 32 key slots based on key slot area
+size and key size, but a valid key slot ID can always be between 0 and
+31 for LUKS2.
+endif::[]
+
+ifdef::ACTION_LUKSADDKEY[]
+*--new-key-slot <0-N>*::
+This option allows you to specify which key slot is selected for
+the new key.
++
+*NOTE:* When used this option affects --key-slot option.
++
+The maximum number of key slots depends on the LUKS version. LUKS1 can have up
+to 8 key slots. LUKS2 can have up to 32 key slots based on key slot area
+size and key size, but a valid key slot ID can always be between 0 and
+31 for LUKS2.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_REENCRYPT,ACTION_BENCHMARK,ACTION_LUKSADDKEY[]
+*--key-size, -s* _bits_::
+ifndef::ACTION_LUKSADDKEY[]
+Sets key size in _bits_. The argument has to be a multiple of 8. The
+possible key-sizes are limited by the cipher and mode used.
++
+See /proc/crypto for more information. Note that key-size in
+/proc/crypto is stated in bytes.
++
+endif::[]
+ifdef::ACTION_LUKSADDKEY[]
+Provide volume key size in _bits_. The argument has to be a multiple of 8.
++
+This option is required when parameter --volume-key-file is used to provide
+current volume key. Also, it is used when new unbound keyslot is created by
+specifying --unbound parameter.
+endif::[]
+ifdef::ACTION_OPEN[]
+This option can be used for _plain_ device type only.
+endif::[]
+ifndef::ACTION_REENCRYPT,ACTION_OPEN,ACTION_LUKSADDKEY[]
+This option can be used for _open --type plain_ or _luksFormat_. All
+other LUKS actions will use the key-size specified in the LUKS header.
+Use _cryptsetup --help_ to show the compiled-in defaults.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+*LUKS1*:
+If you are increasing key size, there must be enough space in the LUKS header
+for enlarged keyslots (data offset must be large enough) or reencryption
+cannot be performed.
++
+If there is not enough space for keyslots with new key size,
+you can destructively shrink device with --reduce-device-size option.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE[]
+*--size, -b <number of 512 byte sectors>*::
+Set the size of the device in sectors of 512 bytes.
+ifdef::ACTION_OPEN[]
+Usable only with _plain_ device type.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--offset, -o <number of 512 byte sectors>*::
+Start offset in the backend device in 512-byte sectors.
+ifdef::ACTION_OPEN[]
+This option is only relevant with plain or loopaes device types.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+This option is only relevant for the encrypt mode.
+endif::[]
++
+ifndef::ACTION_OPEN[]
+The --offset option sets the data offset (payload) of data
+device and must be aligned to 4096-byte sectors (must be multiple of
+8). This option cannot be combined with --align-payload option.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--skip, -p <number of 512 byte sectors>*::
+Start offset used in IV calculation in 512-byte sectors (how many
+sectors of the encrypted data to skip at the beginning). This option
+is only relevant with plain or loopaes device types.
++
+Hence, if --offset _n_, and --skip _s_, sector _n_ (the first sector of
+the encrypted device) will get a sector number of _s_ for the IV
+calculation.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_REENCRYPT,ACTION_RESIZE[]
+*--device-size* _size[units]_::
+ifndef::ACTION_RESIZE[]
+Instead of real device size, use specified value.
+endif::[]
+ifdef::ACTION_RESIZE[]
+Sets new size of the device. If unset real device size is used.
+endif::[]
+ifdef::ACTION_OPEN[]
+Usable only with _plain_ device type.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+It means that only specified area (from the start of the device
+to the specified size) will be reencrypted.
++
+*WARNING:* This is destructive operation. Data beyond --device-size limit may
+be lost after operation gets finished.
+endif::[]
++
+If no unit suffix is specified, the size is in bytes.
++
+Unit suffix can be S for 512 byte sectors, K/M/G/T (or KiB,MiB,GiB,TiB)
+for units with 1024 base or KB/MB/GB/TB for 1000 base (SI scale).
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--readonly, -r*::
+set up a read-only mapping.
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--shared*::
+Creates an additional mapping for one common ciphertext device.
+Arbitrary mappings are supported. This option is only relevant for the
+_plain_ device type. Use --offset, --size and --skip to specify
+the mapped area.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT,ACTION_BENCHMARK[]
+*--pbkdf <PBKDF spec>*::
+Set Password-Based Key Derivation Function (PBKDF) algorithm for LUKS
+keyslot. The PBKDF can be: _pbkdf2_ (for PBKDF2 according to RFC2898),
+_argon2i_ for Argon2i or _argon2id_ for Argon2id (see
+https://www.cryptolux.org/index.php/Argon2[Argon2] for more info).
++
+For LUKS1, only PBKDF2 is accepted (no need to use this option). The
+default PBKDF for LUKS2 is set during compilation time and is available
+in _cryptsetup --help_ output.
++
+A PBKDF is used for increasing dictionary and brute-force attack cost
+for keyslot passwords. The parameters can be time, memory and parallel
+cost.
++
+For PBKDF2, only time cost (number of iterations) applies. For
+Argon2i/id, there is also memory cost (memory required during the
+process of key derivation) and parallel cost (number of threads that run
+in parallel during the key derivation.
++
+Note that increasing memory cost also increases time, so the final
+parameter values are measured by a benchmark. The benchmark tries to
+find iteration time (_--iter-time_) with required memory cost
+_--pbkdf-memory_. If it is not possible, the memory cost is decreased as
+well. The parallel cost _--pbkdf-parallel_ is constant and is checked
+against available CPU cores.
++
+You can see all PBKDF parameters for particular LUKS2 keyslot with
+*cryptsetup-luksDump*(8) command.
++
+*NOTE:* If you do not want to use benchmark and want to specify all
+parameters directly, use _--pbkdf-force-iterations_ with
+_--pbkdf-memory_ and _--pbkdf-parallel_. This will override the values
+without benchmarking. Note it can cause extremely long unlocking time.
+Use only in specific cases, for example, if you know that the formatted
+device will be used on some small embedded system.
++
+*MINIMAL AND MAXIMAL PBKDF COSTS:* For *PBKDF2*, the minimum iteration
+count is 1000 and maximum is 4294967295 (maximum for 32bit unsigned
+integer). Memory and parallel costs are unused for PBKDF2. For *Argon2i*
+and *Argon2id*, minimum iteration count (CPU cost) is 4 and maximum is
+4294967295 (maximum for 32bit unsigned integer). Minimum memory cost is
+32 KiB and maximum is 4 GiB. (Limited by addressable memory on some CPU
+platforms.) If the memory cost parameter is benchmarked (not specified
+by a parameter) it is always in range from 64 MiB to 1 GiB. The parallel
+cost minimum is 1 and maximum 4 (if enough CPUs cores are available,
+otherwise it is decreased).
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT,ACTION_BENCHMARK[]
+*--iter-time, -i <number of milliseconds>*::
+ifndef::ACTION_REENCRYPT[]
+The number of milliseconds to spend with PBKDF passphrase processing.
+Specifying 0 as parameter selects the compiled-in default.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+The number of milliseconds to spend with PBKDF passphrase processing for the
+new LUKS header.
+endif::[]
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT,ACTION_BENCHMARK[]
+*--pbkdf-memory <number>*::
+Set the memory cost for PBKDF (for Argon2i/id the number represents
+kilobytes). Note that it is maximal value, PBKDF benchmark or
+available physical memory can decrease it. This option is not
+available for PBKDF2.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT,ACTION_BENCHMARK[]
+*--pbkdf-parallel <number>*::
+Set the parallel cost for PBKDF (number of threads, up to 4). Note
+that it is maximal value, it is decreased automatically if CPU online
+count is lower. This option is not available for PBKDF2.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT[]
+*--pbkdf-force-iterations <num>*::
+Avoid PBKDF benchmark and set time cost (iterations) directly. It can
+be used for LUKS/LUKS2 device only. See _--pbkdf_ option for more
+info.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--progress-frequency* _seconds_::
+ifndef::ACTION_REENCRYPT[]
+Print separate line every _seconds_ with wipe progress.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+Print separate line every _seconds_ with reencryption progress.
+endif::[]
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--progress-json*::
+Prints progress data in JSON format suitable mostly for machine
+processing. It prints separate line every half second (or based on
+_--progress-frequency_ value). The JSON output looks as follows during
+progress (except it's compact single line):
++
+....
+{
+ "device":"/dev/sda" // backing device or file
+ "device_bytes":"8192", // bytes of I/O so far
+ "device_size":"44040192", // total bytes of I/O to go
+ "speed":"126877696", // calculated speed in bytes per second (based on progress so far)
+ "eta_ms":"2520012" // estimated time to finish an operation in milliseconds
+ "time_ms":"5561235" // total time spent in IO operation in milliseconds
+}
+....
++
+Note on numbers in JSON output: Due to JSON parsers limitations all
+numbers are represented in a string format due to need of full 64bit
+unsigned integers.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_LUKSREMOVEKEY,ACTION_LUKSKILLSLOT,ACTION_LUKSDUMP,ACTION_REENCRYPT,ACTION_REPAIR,ACTION_LUKSRESUME,ACTION_RESIZE,ACTION_TCRYPTDUMP,ACTION_BITLKDUMP[]
+*--timeout, -t <number of seconds>*::
+The number of seconds to wait before timeout on passphrase input via
+terminal. It is relevant every time a passphrase is asked.
+It has no effect if used in conjunction with --key-file.
++
+This option is useful when the system should not stall if the user
+does not input a passphrase, e.g. during boot. The default is a value
+of 0 seconds, which means to wait forever.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSRESUME,ACTION_REENCRYPT[]
+*--tries, -T*::
+How often the input of the passphrase shall be retried. The default is 3 tries.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--align-payload <number of 512 byte sectors>*::
+Align payload at a boundary of _value_ 512-byte sectors.
++
+If not specified, cryptsetup tries to use the topology info provided by
+the kernel for the underlying device to get the optimal alignment. If
+not available (or the calculated value is a multiple of the default)
+data is by default aligned to a 1MiB boundary (i.e. 2048 512-byte
+sectors).
++
+For a detached LUKS header, this option specifies the offset on the data
+device. See also the --header option.
++
+*WARNING:* This option is DEPRECATED and has often unexpected impact to
+the data offset and keyslot area size (for LUKS2) due to the complex
+rounding. For fixed data device offset use _--offset_ option instead.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSUUID,ACTION_REENCRYPT[]
+*--uuid <UUID>*::
+ifndef::ACTION_REENCRYPT[]
+Use the provided _UUID_ for the _luksFormat_ command instead of
+generating a new one. Changes the existing _UUID_ when used with the
+_luksUUID_ command.
++
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+When used in encryption mode use the provided _UUID_ for the new LUKS header
+instead of generating a new one.
++
+*LUKS1 (only in decryption mode)*:
+To find out what _UUID_ to pass look for temporary files LUKS-_UUID_.[|log|org|new]
+of the interrupted decryption process.
++
+endif::[]
+The _UUID_ must be provided in the standard UUID format, e.g.
+12345678-1234-1234-1234-123456789abc.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_REFRESH[]
+*--allow-discards*::
+Allow the use of discard (TRIM) requests for the device. This is also not
+supported for LUKS2 devices with data integrity protection.
++
+*WARNING:* This command can have a negative security impact because it
+can make filesystem-level operations visible on the physical device. For
+example, information leaking filesystem type, used space, etc. may be
+extractable from the physical device if the discarded blocks can be
+located later. If in doubt, do not use it.
++
+A kernel version of 3.1 or later is needed. For earlier kernels, this
+option is ignored.
+endif::[]
+
+ifdef::ACTION_REFRESH,ACTION_OPEN[]
+*--perf-same_cpu_crypt*::
+Perform encryption using the same cpu that IO was submitted on. The
+default is to use an unbound workqueue so that encryption work is
+automatically balanced between available CPUs.
++
+*NOTE:* This option is available only for low-level dm-crypt performance
+tuning, use only if you need a change to default dm-crypt behaviour.
+Needs kernel 4.0 or later.
+endif::[]
+
+ifdef::ACTION_REFRESH,ACTION_OPEN[]
+*--perf-submit_from_crypt_cpus*::
+Disable offloading writes to a separate thread after encryption. There
+are some situations where offloading write bios from the encryption
+threads to a single thread degrades performance significantly. The
+default is to offload write bios to the same thread.
++
+*NOTE:* This option is available only for low-level dm-crypt performance
+tuning, use only if you need a change to default dm-crypt behaviour.
+Needs kernel 4.0 or later.
+endif::[]
+
+ifdef::ACTION_REFRESH,ACTION_OPEN[]
+*--perf-no_read_workqueue, --perf-no_write_workqueue*::
+Bypass dm-crypt internal workqueue and process read or write requests
+synchronously.
++
+*NOTE:* These options are available only for low-level dm-crypt
+performance tuning, use only if you need a change to default dm-crypt
+behaviour. Needs kernel 5.9 or later.
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--test-passphrase*::
+Do not activate the device, just verify passphrase. The device mapping name is
+not mandatory if this option is used.
+endif::[]
+
+ifndef::ACTION_BENCHMARK,ACTION_BITLKDUMP[]
+*--header <device or file storing the LUKS header>*::
+ifndef::ACTION_OPEN[]
+Use a detached (separated) metadata device or file where the LUKS
+header is stored. This option allows one to store ciphertext and LUKS
+header on different devices.
++
+endif::[]
+ifdef::ACTION_OPEN[]
+Specify detached (separated) metadata device or file where the header is stored.
++
+*WARNING:* There is no check whether the ciphertext device specified
+actually belongs to the header given. In fact, you can specify an
+arbitrary device as the ciphertext device with the --header option.
+Use with care.
+endif::[]
+ifndef::ACTION_REENCRYPT[]
+ifdef::ACTION_LUKSFORMAT[]
+With a file name as the argument to --header, the file
+will be automatically created if it does not exist. See the cryptsetup
+FAQ for header size calculation.
++
+The --align-payload option is taken as absolute sector alignment on ciphertext
+device and can be zero.
+endif::[]
+ifndef::ACTION_LUKSFORMAT,ACTION_OPEN[]
+For commands that change the LUKS header (e.g. _luksAddKey_),
+specify the device or file with the LUKS header directly as the LUKS
+device.
+endif::[]
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+If used with --encrypt/--new option, the header file will be created (or overwritten).
+Use with care.
++
+*LUKS2*:
+For decryption mode the option may be used to export original LUKS2 header
+to a detached file. The passed future file must not exist at the time
+of initializing the decryption operation. This frees space in head of data
+device so that data can be moved at original LUKS2 header location. Later on
+decryption operation continues as if the ordinary detached header was passed.
++
+*WARNING:* Never put exported header file in a filesystem on top of device
+you are about to decrypt! It would cause a deadlock.
+endif::[]
+endif::[]
+
+ifdef::ACTION_LUKSHEADERBACKUP,ACTION_LUKSHEADERRESTORE[]
+*--header-backup-file <file>*::
+Specify file with header backup file.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--force-offline-reencrypt (LUKS2 only)*::
+Bypass active device auto-detection and enforce offline reencryption.
++
+This option is useful especially for reencryption of LUKS2 images put in
+files (auto-detection is not reliable in this scenario).
++
+It may also help in case active device auto-detection on particular
+data device does not work or report errors.
++
+*WARNING:* Use with extreme caution! This may destroy data if the device
+is activated and/or actively used.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT[]
+*--force-password*::
+Do not use password quality checking for new LUKS passwords.
++
+This option is ignored if cryptsetup is built without password
+quality checking support.
++
+For more info about password quality check, see the manual page for
+*pwquality.conf(5)* and *passwdqc.conf(5)*.
+endif::[]
+
+ifdef::ACTION_CLOSE[]
+*--deferred*::
+Defers device removal in _close_ command until the last user closes
+it.
+endif::[]
+
+ifdef::ACTION_CLOSE[]
+*--cancel-deferred*::
+Removes a previously configured deferred device removal in _close_
+command.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSRESUME,ACTION_RESIZE,ACTION_TOKEN[]
+*--disable-external-tokens*::
+Disable loading of plugins for external LUKS2 tokens.
+endif::[]
+
+ifndef::ACTION_BENCHMARK,ACTION_BITLKDUMP,ACTION_TCRYPTDUMP[]
+*--disable-locks*::
+Disable lock protection for metadata on disk. This option is valid
+only for LUKS2 and ignored for other formats.
++
+ifdef::ACTION_REENCRYPT[]
+*NOTE:* With locking disabled LUKS2 images in files can be fully (re)encrypted
+offline without need for super user privileges provided used block ciphers are
+available in crypto backend.
++
+endif::[]
+*WARNING:* Do not use this option unless you run cryptsetup in a
+restricted environment where locking is impossible to perform (where
+/run directory cannot be used).
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_REFRESH,ACTION_LUKSFORMAT,ACTION_LUKSRESUME,ACTION_TOKEN,ACTION_REENCRYPT[]
+*--disable-keyring*::
+Do not load volume key in kernel keyring and store it directly in the
+dm-crypt target instead. This option is supported only for the LUKS2 type.
+endif::[]
+
+ifdef::ACTION_TOKEN[]
+*--key-description <text>*::
+Set key description in keyring for use with _token_ command.
+endif::[]
+
+ifdef::ACTION_CONFIG[]
+*--priority <normal|prefer|ignore>*::
+Set a priority for LUKS2 keyslot. The _prefer_ priority marked slots
+are tried before _normal_ priority. The _ignored_ priority means, that
+slot is never used, if not explicitly requested by _--key-slot_
+option.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSRESUME,ACTION_TOKEN,ACTION_LUKSADDKEY[]
+*--token-id*::
+ifndef::ACTION_TOKEN,ACTION_LUKSADDKEY[]
+Specify what token to use and allow token PIN prompt to take precedence over interative
+keyslot passphrase prompt. If omitted, all available tokens (not protected by PIN)
+will be checked before proceeding further with passphrase prompt.
+endif::[]
+ifdef::ACTION_LUKSADDKEY[]
+Specify what token to use when unlocking existing keyslot to get volume key.
+endif::[]
+ifdef::ACTION_TOKEN[]
+Specify token number. If omitted, first unused token id is used when adding or importing
+new token.
+endif::[]
+endif::[]
+
+ifdef::ACTION_LUKSADDKEY[]
+*--new-token-id*::
+Specify what token to use to get the passphrase for a new keyslot.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSRESUME,ACTION_LUKSADDKEY[]
+*--token-only*::
+ifndef::ACTION_LUKSADDKEY[]
+Do not proceed further with action if token based keyslot unlock failed. Without the
+option, action asks for passphrase to proceed further.
++
+It allows LUKS2 tokens protected by PIN to take precedence over interactive keyslot
+passphrase prompt.
+endif::[]
+ifdef::ACTION_LUKSADDKEY[]
+Use only LUKS2 tokens to unlock existing volume key.
++
+*NOTE*: To create a new keyslot using passphrase provided by a token use --new-token-id parameter.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_RESIZE,ACTION_LUKSRESUME,ACTION_LUKSADDKEY[]
+*--token-type* _type_::
+ifndef::ACTION_LUKSADDKEY[]
+Restrict tokens eligible for operation to specific token _type_.
+Mostly useful when no --token-id is specified.
++
+It allows LUKS2 _type_ tokens protected by PIN to take precedence over interactive keyslot
+passphrase prompt.
+endif::[]
+ifdef::ACTION_LUKSADDKEY[]
+Specify what token type (all _type_ tokens) to use when unlocking existing keyslot to get volume key.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+ifndef::ACTION_REENCRYPT[]
+*--sector-size* _bytes_::
+endif::[]
+ifndef::ACTION_REENCRYPT[]
+ifdef::ACTION_OPEN[]
+Set encryption sector size for use with _plain_ device type. It must be power of two
+and in range 512 - 4096 bytes. The default mode is 512 bytes.
++
+Note that if sector size is higher than underlying device hardware
+sector, using this option can increase risk on incomplete sector writes during a
+power fail.
+endif::[]
+ifdef::ACTION_LUKSFORMAT[]
+Set sector size for use with disk encryption. It must be power of two
+and in range 512 - 4096 bytes. This option is available only with LUKS2
+format.
++
+For LUKS2 devices it's established based on parameters provided by
+underlying data device. For native 4K block devices it's 4096 bytes.
+For 4K/512e (4K physical sector size with 512 bytes emulation) it's
+4096 bytes. For drives reporting only 512 bytes block size it remains
+512 bytes. If data device is regular file put in filesystem it's 4096
+bytes.
++
+Note that if sector size is higher than underlying device hardware
+sector and there is not integrity protection that uses data journal,
+using this option can increase risk on incomplete sector writes during a
+power fail.
++
+If used together with _--integrity_ option and dm-integrity journal, the
+atomicity of writes is guaranteed in all cases (but it cost write
+performance - data has to be written twice).
+endif::[]
++
+Increasing sector size from 512 bytes to 4096 bytes can provide better
+performance on most of the modern storage devices and also with some hw
+encryption accelerators.
+endif::[]
+ifdef::ACTION_REENCRYPT[]
+*--sector-size* _bytes_ *(LUKS2 only)*::
+Reencrypt device with new encryption sector size enforced.
++
+*WARNING:* Increasing encryption sector size may break hosted filesystem. Do not
+run reencryption with --force-offline-reencrypt if unsure what block size
+was filesystem formatted with.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--iv-large-sectors*::
+Count Initialization Vector (IV) in larger sector size (if set)
+instead of 512 bytes sectors. This option can be used only with _plain_
+device type.
++
+*NOTE:* This option does not have any performance or security impact,
+use it only for accessing incompatible existing disk images from other
+systems that require this option.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_REFRESH[]
+*--persistent*::
+If used with LUKS2 devices and activation commands like _open_ or
+_refresh_, the specified activation flags are persistently written
+into metadata and used next time automatically even for normal
+activation. (No need to use cryptab or other system configuration
+files.)
++
+If you need to remove a persistent flag, use _--persistent_ without the
+flag you want to remove (e.g. to disable persistently stored discard
+flag, use _--persistent_ without _--allow-discards_).
++
+Only _--allow-discards_, _--perf-same_cpu_crypt_,
+_--perf-submit_from_crypt_cpus_, _--perf-no_read_workqueue_,
+_--perf-no_write_workqueue_ and _--integrity-no-journal_ can be stored
+persistently.
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--refresh*::
+Refreshes an active device with new set of parameters. See
+*cryptsetup-refresh*(8) for more details.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_CONFIG,ACTION_REENCRYPT[]
+*--label <LABEL> --subsystem <SUBSYSTEM>*::
+Set label and subsystem description for LUKS2 device.
+The label and subsystem are optional fields and can be later used
+in udev scripts for triggering user actions once the device marked
+by these labels is detected.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT[]
+*--integrity <integrity algorithm>*::
+Specify integrity algorithm to be used for authenticated disk
+encryption in LUKS2.
++
+*WARNING: This extension is EXPERIMENTAL* and requires dm-integrity
+kernel target (available since kernel version 4.12). For native AEAD
+modes, also enable "User-space interface for AEAD cipher algorithms" in
+"Cryptographic API" section (CONFIG_CRYPTO_USER_API_AEAD .config
+option).
++
+For more info, see _AUTHENTICATED DISK ENCRYPTION_ section in *cryptsetup*(8).
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT[]
+*--integrity-legacy-padding*::
+Use inefficient legacy padding.
++
+*WARNING*: Do not use this option until you need compatibility with specific
+old kernel.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--luks2-metadata-size <size>*::
+This option can be used to enlarge the LUKS2 metadata (JSON) area. The
+size includes 4096 bytes for binary metadata (usable JSON area is
+smaller of the binary area). According to LUKS2 specification, only
+these values are valid: 16, 32, 64, 128, 256, 512, 1024, 2048 and 4096
+kB The <size> can be specified with unit suffix (for example 128k).
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_REENCRYPT[]
+*--luks2-keyslots-size <size>*::
+This option can be used to set specific size of the LUKS2 binary
+keyslot area (key material is encrypted there). The value must be
+aligned to multiple of 4096 bytes with maximum size 128MB. The <size>
+can be specified with unit suffix (for example 128k).
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT[]
+*--keyslot-cipher <cipher-spec>*::
+This option can be used to set specific cipher encryption for the
+LUKS2 keyslot area.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT,ACTION_LUKSADDKEY,ACTION_LUKSCHANGEKEY,ACTION_LUKSCONVERTKEY,ACTION_REENCRYPT[]
+*--keyslot-key-size <bits>*::
+This option can be used to set specific key size for the LUKS2 keyslot
+area.
+endif::[]
+
+ifdef::ACTION_REFRESH[]
+*--integrity-no-journal*::
+Activate device with integrity protection without using data journal
+(direct write of data and integrity tags). Note that without journal
+power fail can cause non-atomic write and data corruption. Use only if
+journalling is performed on a different storage layer.
+endif::[]
+
+ifdef::ACTION_LUKSFORMAT[]
+*--integrity-no-wipe*::
+Skip wiping of device authentication (integrity) tags. If you skip
+this step, sectors will report invalid integrity tag until an
+application write to the sector.
++
+*NOTE:* Even some writes to the device can fail if the write is not
+aligned to page size and page-cache initiates read of a sector with
+invalid integrity tag.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_LUKSADDKEY,ACTION_LUKSDUMP,ACTION_TOKEN[]
+*--unbound*::
+ifdef::ACTION_LUKSADDKEY[]
+Creates new LUKS2 unbound keyslot.
+endif::[]
+ifdef::ACTION_LUKSDUMP[]
+Dumps existing LUKS2 unbound keyslot.
+endif::[]
+ifdef::ACTION_OPEN[]
+Allowed only together with --test-passphrase parameter, it allows one to test
+passphrase for unbound LUKS2 keyslot. Otherwise, unbound keyslot passphrase
+can be tested only when specific keyslot is selected via --key-slot parameter.
+endif::[]
+ifdef::ACTION_TOKEN[]
+Creates new LUKS2 keyring token assigned to no keyslot. Usable only with _add_ action.
+endif::[]
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_TCRYPTDUMP[]
+*--tcrypt-hidden*::
+*--tcrypt-system*::
+*--tcrypt-backup*::
+Specify which TrueCrypt on-disk
+header will be used to open the device. See _TCRYPT_ section in
+*cryptsetup*(8) for more info.
+endif::[]
+
+ifdef::ACTION_TCRYPTDUMP,ACTION_OPEN[]
+*--veracrypt*::
+This option is ignored as VeraCrypt compatible mode is supported by
+default.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_TCRYPTDUMP[]
+*--disable-veracrypt*::
+This option can be used to disable VeraCrypt compatible mode (only
+TrueCrypt devices are recognized). Only for TCRYPT extension. See
+_TCRYPT_ section in *cryptsetup*(8) for more info.
+endif::[]
+
+ifdef::ACTION_OPEN,ACTION_TCRYPTDUMP[]
+*--veracrypt-pim*::
+*--veracrypt-query-pim*::
+Use a custom Personal Iteration Multiplier (PIM) for
+VeraCrypt device. See _TCRYPT_ section in *cryptsetup*(8) for more info.
+endif::[]
+
+ifdef::ACTION_OPEN[]
+*--serialize-memory-hard-pbkdf*::
+Use a global lock to serialize unlocking of keyslots using memory-hard
+PBKDF.
++
+*NOTE:* This is (ugly) workaround for a specific situation when multiple
+devices are activated in parallel and system instead of reporting out of
+memory starts unconditionally stop processes using out-of-memory killer.
++
+*DO NOT USE* this switch until you are implementing boot environment
+with parallel devices activation!
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--encrypt, --new, -N*::
+Initialize (and run) device in-place encryption mode.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--decrypt*::
+Initialize (and run) device decryption mode.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--init-only (LUKS2 only)*::
+Initialize reencryption (any mode) operation in LUKS2 metadata only
+and exit. If any reencrypt operation is already initialized in
+metadata, the command with --init-only parameter fails.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--resume-only (LUKS2 only)*::
+Resume reencryption (any mode) operation already described in LUKS2
+metadata. If no reencrypt operation is initialized, the command with
+--resume-only parameter fails. Useful for resuming reencrypt operation
+without accidentally triggering new reencryption operation.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--resilience* _mode_ *(LUKS2 only)*::
+Reencryption resilience _mode_ can be one of _checksum_, _journal_ or
+_none_.
++
+_checksum_: default mode, where individual checksums of ciphertext
+hotzone sectors are stored, so the recovery process can detect which
+sectors were already reencrypted. It requires that the device sector
+write is atomic.
++
+_journal_: the hotzone is journaled in the binary area (so the data are
+written twice).
++
+_none_: performance mode. There is no protection and the only way it's
+safe to interrupt the reencryption is similar to old offline
+reencryption utility.
++
+Resilience modes can be changed unless _datashift_ mode is used for
+operation initialization (encryption with --reduce-device-size option)
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--resilience-hash* _hash_ *(LUKS2 only)*::
+The _hash_ algorithm used with "--resilience checksum" only. The default
+hash is sha256. With other resilience modes, the hash parameter is
+ignored.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--hotzone-size* _size_ *(LUKS2 only)*::
+This option can be used to set an upper limit on the size of
+reencryption area (hotzone). The _size_ can be specified with unit
+suffix (for example 50M). Note that actual hotzone size may be less
+than specified <size> due to other limitations (free space in keyslots
+area or available memory).
++
+With decryption mode for devices with LUKS2 header placed in head of data
+device, the option specifies how large is the first data segment moved
+from original data offset pointer.
+endif::[]
+
+ifdef::ACTION_REENCRYPT[]
+*--reduce-device-size* _size_::
+This means that last _size_ sectors on the original device will be lost,
+data will be effectively shifted by specified number of sectors.
++
+It could be useful if you added some space to underlying partition or
+logical volume (so last _size_ sectors contains no data).
++
+For units suffix see --device-size parameter description.
++
+*WARNING:* This is a destructive operation and cannot be reverted. Use
+with extreme care - accidentally overwritten filesystems are usually
+unrecoverable.
++
+*LUKS2*:
+Initialize LUKS2 reencryption with data device size reduction
+(currently only encryption mode is supported).
++
+Recommended minimal size is twice the default LUKS2 header size
+(--reduce-device-size 32M) for encryption mode.
++
+*LUKS1*:
+Enlarge data offset to specified value by shrinking device size.
++
+You cannot shrink device more than by 64 MiB (131072 sectors).
+endif::[]
+
+ifdef::COMMON_OPTIONS[]
+*--batch-mode, -q*::
+Suppresses all confirmation questions. Use with care!
++
+If the --verify-passphrase option is not specified, this option also
+switches off the passphrase verification.
+endif::[]
+
+ifdef::COMMON_OPTIONS[]
+*--debug or --debug-json*::
+Run in debug mode with full diagnostic logs. Debug output lines are
+always prefixed by *#*.
++
+If --debug-json is used, additional LUKS2 JSON data structures are printed.
+endif::[]
+
+ifdef::COMMON_OPTIONS[]
+*--version, -V*::
+Show the program version.
+endif::[]
+
+ifdef::COMMON_OPTIONS[]
+*--usage*::
+Show short option help.
+endif::[]
+
+ifdef::COMMON_OPTIONS[]
+*--help, -?*::
+Show help text and default parameters.
+endif::[]
diff --git a/man/cryptsetup-benchmark.8.adoc b/man/cryptsetup-benchmark.8.adoc
new file mode 100644
index 0000000..caaacba
--- /dev/null
+++ b/man/cryptsetup-benchmark.8.adoc
@@ -0,0 +1,41 @@
+= cryptsetup-benchmark(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_BENCHMARK:
+
+== Name
+
+cryptsetup-benchmark - benchmarks ciphers and KDF
+
+== SYNOPSIS
+
+*cryptsetup _benchmark_ [<options>]*
+
+== DESCRIPTION
+
+Benchmarks ciphers and KDF (key derivation function). Without
+parameters, it tries to measure few common configurations.
+
+To benchmark other ciphers or modes, you need to specify *--cipher* and
+*--key-size* options.
+
+To benchmark PBKDF you need to specify *--pbkdf* or *--hash* with optional
+cost parameters *--iter-time*, *--pbkdf-memory* or *--pbkdf-parallel*.
+
+*NOTE:* This benchmark uses memory only and is only informative. You
+cannot directly predict real storage encryption speed from it.
+
+For testing block ciphers, this benchmark requires kernel userspace
+crypto API to be available (introduced in Linux kernel 2.6.38). If you
+are configuring kernel yourself, enable "User-space interface for
+symmetric key cipher algorithms" in "Cryptographic API" section
+(CRYPTO_USER_API_SKCIPHER .config option).
+
+*<options>* can be [--cipher, --key-size, --hash, --pbkdf, --iter-time,
+--pbkdf-memory, --pbkdf-parallel].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-bitlkDump.8.adoc b/man/cryptsetup-bitlkDump.8.adoc
new file mode 100644
index 0000000..6dc273f
--- /dev/null
+++ b/man/cryptsetup-bitlkDump.8.adoc
@@ -0,0 +1,34 @@
+= cryptsetup-bitlkDump(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_BITLKDUMP:
+
+== Name
+
+cryptsetup-bitlkDump - dump the header information of a BITLK (BitLocker compatible) device
+
+== SYNOPSIS
+
+*cryptsetup _bitlkDump_ [<options>] <device>*
+
+== DESCRIPTION
+
+Dump the header information of a BITLK (BitLocker compatible) device.
+
+If the --dump-volume-key option is used, the BITLK device volume key
+is dumped instead of header information. You have to provide password
+or keyfile to dump volume key.
+
+Beware that the volume key can be used to decrypt the data stored in
+the container without a passphrase.
+This means that if the volume key is compromised, the whole device has
+to be erased to prevent further access. Use this option carefully.
+
+*<options>* can be [--dump-volume-key, --volume-key-file, --key-file,
+--keyfile-offset, --keyfile-size, --timeout].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-close.8.adoc b/man/cryptsetup-close.8.adoc
new file mode 100644
index 0000000..28813d3
--- /dev/null
+++ b/man/cryptsetup-close.8.adoc
@@ -0,0 +1,30 @@
+= cryptsetup-close(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_CLOSE:
+
+== Name
+
+cryptsetup-close - removes the existing mapping <name> (and the associated key)
+
+== SYNOPSIS
+
+*cryptsetup _close_ [<options>] <name>*
+
+== DESCRIPTION
+
+Removes the existing mapping <name> and wipes the key from kernel
+memory.
+
+For backward compatibility, there are *close* command aliases: *remove*,
+*plainClose*, *luksClose*, *loopaesClose*, *tcryptClose*, *bitlkClose*
+(all behave exactly the same, device type is determined automatically
+from the active device).
+
+*<options>* can be [--deferred, --cancel-deferred, --header, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-config.8.adoc b/man/cryptsetup-config.8.adoc
new file mode 100644
index 0000000..c664242
--- /dev/null
+++ b/man/cryptsetup-config.8.adoc
@@ -0,0 +1,30 @@
+= cryptsetup-config(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_CONFIG:
+
+== Name
+
+cryptsetup-config - set permanent configuration options (store to LUKS header)
+
+== SYNOPSIS
+
+*cryptsetup _config_ <options> <device>*
+
+== DESCRIPTION
+
+Set permanent configuration options (store to LUKS header). The _config_
+command is supported only for LUKS2.
+
+The permanent options can be _--priority_ to set priority (normal,
+prefer, ignore) for keyslot (specified by _--key-slot_) or _--label_ and
+_--subsystem_.
+
+*<options>* can be [--priority, --label, --subsystem, --key-slot,
+--header, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-convert.8.adoc b/man/cryptsetup-convert.8.adoc
new file mode 100644
index 0000000..dbb4c23
--- /dev/null
+++ b/man/cryptsetup-convert.8.adoc
@@ -0,0 +1,37 @@
+= cryptsetup-convert(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_CONVERT:
+
+== Name
+
+cryptsetup-convert - converts the device between LUKS1 and LUKS2 format
+
+== SYNOPSIS
+
+*cryptsetup _convert_ --type <format> [<options>] <device>*
+
+== DESCRIPTION
+
+Converts the device between LUKS1 and LUKS2 format (if possible). The
+conversion will not be performed if there is an additional LUKS2 feature
+or LUKS1 has unsupported header size.
+
+Conversion (both directions) must be performed on inactive device. There
+must not be active dm-crypt mapping established for LUKS header
+requested for conversion.
+
+The *--type* option is mandatory with the following accepted values: _luks1_ or
+_luks2_.
+
+*WARNING:* The _convert_ action can destroy the LUKS header in the case
+of a crash during conversion or if a media error occurs. Always create a
+header backup before performing this operation!
+
+*<options>* can be [--header, --type, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-erase.8.adoc b/man/cryptsetup-erase.8.adoc
new file mode 100644
index 0000000..97a13aa
--- /dev/null
+++ b/man/cryptsetup-erase.8.adoc
@@ -0,0 +1,28 @@
+= cryptsetup-erase(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_ERASE:
+
+== Name
+
+cryptsetup-erase, cryptsetup-luksErase - erase all keyslots
+
+== SYNOPSIS
+
+*cryptsetup _erase_ [<options>] <device>* +
+*cryptsetup _luksErase_ [<options>] <device>*
+
+== DESCRIPTION
+
+Erase all keyslots and make the LUKS container permanently inaccessible.
+You do not need to provide any password for this operation.
+
+*WARNING:* This operation is irreversible.
+
+*<options>* can be [--header, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-fvault2Dump.8.adoc b/man/cryptsetup-fvault2Dump.8.adoc
new file mode 100644
index 0000000..0831899
--- /dev/null
+++ b/man/cryptsetup-fvault2Dump.8.adoc
@@ -0,0 +1,34 @@
+= cryptsetup-fvault2Dump(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_BITLKDUMP:
+
+== Name
+
+cryptsetup-fvault2Dump - dump the header information of a FVAULT2 (FileVault2 compatible) device
+
+== SYNOPSIS
+
+*cryptsetup _fvault2Dump_ [<options>] <device>*
+
+== DESCRIPTION
+
+Dump the header information of a FVAULT2 (FileVault2 compatible) device.
+
+If the --dump-volume-key option is used, the FVAULT2 device volume key
+is dumped instead of header information. You have to provide password
+or keyfile to dump volume key.
+
+Beware that the volume key can be used to decrypt the data stored in
+the container without a passphrase.
+This means that if the volume key is compromised, the whole device has
+to be erased to prevent further access. Use this option carefully.
+
+*<options>* can be [--dump-volume-key, --volume-key-file, --key-file,
+--keyfile-offset, --keyfile-size, --timeout].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-isLuks.8.adoc b/man/cryptsetup-isLuks.8.adoc
new file mode 100644
index 0000000..aac559c
--- /dev/null
+++ b/man/cryptsetup-isLuks.8.adoc
@@ -0,0 +1,29 @@
+= cryptsetup-isLuks(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_ISLUKS:
+
+== Name
+
+cryptsetup-isLuks - check if a device is a LUKS device
+
+== SYNOPSIS
+
+*cryptsetup _isLuks_ [<options>] <device>*
+
+== DESCRIPTION
+
+Returns true, if <device> is a LUKS device, false otherwise.
+
+Use option -v to get human-readable feedback.
+'Command successful.' means the device is a LUKS device.
+
+By specifying --type you may query for specific LUKS version.
+
+*<options>* can be [--header, --type, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksAddKey.8.adoc b/man/cryptsetup-luksAddKey.8.adoc
new file mode 100644
index 0000000..9686a1d
--- /dev/null
+++ b/man/cryptsetup-luksAddKey.8.adoc
@@ -0,0 +1,71 @@
+= cryptsetup-luksAddKey(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSADDKEY:
+
+== Name
+
+cryptsetup-luksAddKey - add a new passphrase
+
+== SYNOPSIS
+
+*cryptsetup _luksAddKey_ [<options>] <device> [<key file with new key>]*
+
+== DESCRIPTION
+
+Adds a keyslot protected by a new passphrase. An existing passphrase
+must be supplied interactively, via --key-file or LUKS2 token (plugin).
+Alternatively to existing passphrase user may pass directly volume key
+(via --volume-key-file). The new passphrase to be added can be specified
+interactively, read from the file given as the positional argument (also
+via --new-keyfile parameter) or via LUKS2 token.
+
+*NOTE:* with --unbound option the action creates new unbound LUKS2
+keyslot. The keyslot cannot be used for device activation. If you don't
+pass new key via --volume-key-file option, new random key is generated.
+Existing passphrase for any active keyslot is not required.
+
+*NOTE:* some parameters are effective only if used with LUKS2 format
+that supports per-keyslot parameters. For LUKS1, PBKDF type and hash
+algorithm is always the same for all keyslots.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
+--new-keyfile, --new-keyfile-offset, --new-keyfile-size, --key-slot,
+--new-key-slot, --volume-key-file, --force-password, --hash, --header,
+--disable-locks, --iter-time, --pbkdf, --pbkdf-force-iterations,
+--pbkdf-memory, --pbkdf-parallel, --unbound, --type, --keyslot-cipher,
+--keyslot-key-size, --key-size, --timeout, --token-id, --token-type,
+--token-only, --new-token-id, --verify-passphrase].
+
+include::man/common_options.adoc[]
+
+== EXAMPLES
+
+*NOTE*: When not specified otherwise interactive passphrase prompt is always default method.
+
+Add new keyslot using interactive passphrase prompt for both existing and new passphrase:
+
+*cryptsetup luksAddKey /dev/device*
+
+Add new keyslot using LUKS2 tokens to unlock existing keyslot with interactive passphrase prompt for new passphrase:
+
+*cryptsetup luksAddKey --token-only /dev/device*
+
+Add new keyslot using LUKS2 systemd-tpm2 tokens to unlock existing keyslot with interactive passphrase prompt for new passphrase (systemd-tpm2 token plugin must be available):
+
+*cryptsetup luksAddKey --token-type systemd-tpm2 /dev/device*
+
+Add new keyslot using interactive passphrase prompt for existing keyslot, reading new passphrase from key_file:
+
+*cryptsetup luksAddKey --new-keyfile key_file /dev/device* or
+*cryptsetup luksAddKey /dev/device key_file*
+
+Add new keyslot using volume stored in volume_key_file and LUKS2 token in slot 5 to get new keyslot passphrase (token in slot 5 must exist
+and respective token plugin must be available):
+
+*cryptsetup luksAddKey --volume-key-file volume_key_file --new-token-id 5 /dev/device*
+
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksChangeKey.8.adoc b/man/cryptsetup-luksChangeKey.8.adoc
new file mode 100644
index 0000000..7dd5f3b
--- /dev/null
+++ b/man/cryptsetup-luksChangeKey.8.adoc
@@ -0,0 +1,46 @@
+= cryptsetup-luksChangeKey(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSCHANGEKEY:
+
+== Name
+
+cryptsetup-luksChangeKey - change an existing passphrase
+
+== SYNOPSIS
+
+*cryptsetup _luksChangeKey_ [<options>] <device> [<new key file>]*
+
+== DESCRIPTION
+
+Changes an existing passphrase. The passphrase to be changed must be
+supplied interactively or via --key-file. The new passphrase can be
+supplied interactively or in a file given as the positional argument.
+
+If a key-slot is specified (via --key-slot), the passphrase for that
+key-slot must be given and the new passphrase will overwrite the
+specified key-slot. If no key-slot is specified and there is still a
+free key-slot, then the new passphrase will be put into a free key-slot
+before the key-slot containing the old passphrase is purged. If there is
+no free key-slot, then the key-slot with the old passphrase is
+overwritten directly.
+
+*WARNING:* If a key-slot is overwritten, a media failure during this
+operation can cause the overwrite to fail after the old passphrase has
+been wiped and make the LUKS container inaccessible.
+
+*NOTE:* some parameters are effective only if used with LUKS2 format
+that supports per-keyslot parameters. For LUKS1, PBKDF type and hash
+algorithm is always the same for all keyslots.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
+--new-keyfile-offset, --iter-time, --pbkdf, --pbkdf-force-iterations,
+--pbkdf-memory, --pbkdf-parallel, --new-keyfile-size, --key-slot,
+--force-password, --hash, --header, --disable-locks, --type,
+--keyslot-cipher, --keyslot-key-size, --timeout, --verify-passphrase].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksConvertKey.8.adoc b/man/cryptsetup-luksConvertKey.8.adoc
new file mode 100644
index 0000000..c626542
--- /dev/null
+++ b/man/cryptsetup-luksConvertKey.8.adoc
@@ -0,0 +1,41 @@
+= cryptsetup-luksConvertKey(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSCONVERTKEY:
+
+== Name
+
+cryptsetup-luksConvertKey - converts an existing LUKS2 keyslot to new PBKDF parameters
+
+== SYNOPSIS
+
+*cryptsetup _luksConvertKey_ [<options>] <device>*
+
+== DESCRIPTION
+
+Converts an existing LUKS2 keyslot to new PBKDF parameters. The
+passphrase for keyslot to be converted must be supplied interactively or
+via --key-file. If no --pbkdf parameters are specified LUKS2 default
+PBKDF values will apply.
+
+If a keyslot is specified (via --key-slot), the passphrase for that
+keyslot must be given. If no keyslot is specified and there is still a
+free keyslot, then the new parameters will be put into a free keyslot
+before the keyslot containing the old parameters is purged. If there is
+no free keyslot, then the keyslot with the old parameters is overwritten
+directly.
+
+*WARNING:* If a keyslot is overwritten, a media failure during this
+operation can cause the overwrite to fail after the old parameters have
+been wiped and make the LUKS container inaccessible.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
+--key-slot, --hash, --header, --disable-locks, --iter-time, --pbkdf,
+--pbkdf-force-iterations, --pbkdf-memory, --pbkdf-parallel,
+--keyslot-cipher, --keyslot-key-size, --timeout, --verify-passphrase].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksDump.8.adoc b/man/cryptsetup-luksDump.8.adoc
new file mode 100644
index 0000000..f9f3910
--- /dev/null
+++ b/man/cryptsetup-luksDump.8.adoc
@@ -0,0 +1,50 @@
+= cryptsetup-luksDump(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSDUMP:
+
+== Name
+
+cryptsetup-luksDump - dump the header information of a LUKS device
+
+== SYNOPSIS
+
+*cryptsetup _luksDump_ [<options>] <device>*
+
+== DESCRIPTION
+
+Dump the header information of a LUKS device.
+
+If the --dump-volume-key option is used, the LUKS device volume key is
+dumped instead of the keyslot info. Together with the --volume-key-file
+option, volume key is dumped to a file instead of standard output.
+Beware that the volume key cannot be changed without reencryption and
+can be used to decrypt the data stored in the LUKS container without a
+passphrase and even without the LUKS header. This means that if the
+volume key is compromised, the whole device has to be erased or
+reencrypted to prevent further access. Use this option carefully.
+
+To dump the volume key, a passphrase has to be supplied, either
+interactively or via --key-file.
+
+To dump unbound key (LUKS2 format only), --unbound parameter, specific
+--key-slot id and proper passphrase has to be supplied, either
+interactively or via --key-file. Optional --volume-key-file parameter
+enables unbound keyslot dump to a file.
+
+To dump LUKS2 JSON metadata (without basic header information like UUID)
+use --dump-json-metadata option.
+
+*<options>* can be [--dump-volume-key, --dump-json-metadata, --key-file,
+--keyfile-offset, --keyfile-size, --header, --disable-locks,
+--volume-key-file, --type, --unbound, --key-slot, --timeout].
+
+*WARNING:* If --dump-volume-key is used with --key-file and the argument
+to --key-file is '-', no validation question will be asked and no
+warning given.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksFormat.8.adoc b/man/cryptsetup-luksFormat.8.adoc
new file mode 100644
index 0000000..be241f8
--- /dev/null
+++ b/man/cryptsetup-luksFormat.8.adoc
@@ -0,0 +1,51 @@
+= cryptsetup-luksFormat(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSFORMAT:
+
+== Name
+
+cryptsetup-luksFormat - initialize a LUKS partition and set the initial passphrase
+
+== SYNOPSIS
+
+*cryptsetup _luksFormat_ [<options>] <device> [<key file>]*
+
+== DESCRIPTION
+
+Initializes a LUKS partition and sets the initial passphrase (for
+key-slot 0), either via prompting or via <key file>. Note that if the
+second argument is present, then the passphrase is taken from the file
+given there, without the need to use the --key-file option. Also note
+that for both forms of reading the passphrase from a file you can give
+'-' as file name, which results in the passphrase being read from stdin
+and the safety-question being skipped.
+
+You cannot call luksFormat on a device or filesystem that is mapped or
+in use, e.g., mounted filesystem, used in LVM, active RAID member, etc. The
+device or filesystem has to be un-mounted in order to call luksFormat.
+
+To use specific version of LUKS format, use _--type luks1_ or _type luks2_.
+
+*<options>* can be [--hash, --cipher, --verify-passphrase, --key-size,
+--key-slot, --key-file (takes precedence over optional second argument),
+--keyfile-offset, --keyfile-size, --use-random, --use-urandom, --uuid,
+--volume-key-file, --iter-time, --header, --pbkdf-force-iterations,
+--force-password, --disable-locks, --timeout, --type, --offset,
+--align-payload (deprecated)].
+
+For LUKS2, additional *<options>* can be [--integrity,
+--integrity-no-wipe, --sector-size, --label, --subsystem, --pbkdf,
+--pbkdf-memory, --pbkdf-parallel, --disable-locks, --disable-keyring,
+--luks2-metadata-size, --luks2-keyslots-size, --keyslot-cipher,
+--keyslot-key-size, --integrity-legacy-padding].
+
+*WARNING:* Doing a luksFormat on an existing LUKS container will make
+all data in the old container permanently irretrievable unless you have a
+header backup.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksHeaderBackup.8.adoc b/man/cryptsetup-luksHeaderBackup.8.adoc
new file mode 100644
index 0000000..1f57f25
--- /dev/null
+++ b/man/cryptsetup-luksHeaderBackup.8.adoc
@@ -0,0 +1,35 @@
+= cryptsetup-luksHeaderBackup(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSHEADERBACKUP:
+
+== Name
+
+cryptsetup-luksHeaderBackup - store a binary backup of the LUKS header and keyslot area
+
+== SYNOPSIS
+
+*cryptsetup _luksHeaderBackup_ --header-backup-file <file> [<options>] <device>*
+
+== DESCRIPTION
+
+Stores a binary backup of the LUKS header and keyslot area. +
+*NOTE:* Using '-' as filename writes the header backup to a file named
+'-'.
+
+*<options>* can be [--header, --header-backup-file, --disable-locks].
+
+*WARNING:* This backup file and a passphrase valid at the time of backup
+allows decryption of the LUKS data area, even if the passphrase was
+later changed or removed from the LUKS device. Also note that with a
+header backup you lose the ability to securely wipe the LUKS device by
+just overwriting the header and key-slots. You either need to securely
+erase all header backups in addition or overwrite the encrypted data
+area as well. The second option is less secure, as some sectors can
+survive, e.g., due to defect management.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksHeaderRestore.8.adoc b/man/cryptsetup-luksHeaderRestore.8.adoc
new file mode 100644
index 0000000..e7fa8aa
--- /dev/null
+++ b/man/cryptsetup-luksHeaderRestore.8.adoc
@@ -0,0 +1,34 @@
+= cryptsetup-luksHeaderRestore(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSHEADERRESTORE:
+
+== Name
+
+cryptsetup-luksHeaderRestore - restore a binary backup of the LUKS header and keyslot area
+
+== SYNOPSIS
+
+*cryptsetup _luksHeaderRestore_ --header-backup-file <file> [<options>] <device>*
+
+== DESCRIPTION
+
+Restores a binary backup of the LUKS header and keyslot area from the
+specified file. +
+*NOTE:* Using '-' as filename reads the header backup from a file named '-'.
+
+*<options>* can be [--header, --header-backup-file, --disable-locks].
+
+*WARNING:* Header and keyslots will be replaced, only the passphrases
+from the backup will work afterward.
+
+This command requires that the volume key size and data offset of the
+LUKS header already on the device and of the header backup match.
+Alternatively, if there is no LUKS header on the device, the backup will
+also be written to it.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksKillSlot.8.adoc b/man/cryptsetup-luksKillSlot.8.adoc
new file mode 100644
index 0000000..4575387
--- /dev/null
+++ b/man/cryptsetup-luksKillSlot.8.adoc
@@ -0,0 +1,40 @@
+= cryptsetup-luksKillSlot(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSKILLSLOT:
+
+== Name
+
+cryptsetup-luksKillSlot - wipe a key-slot from the LUKS device
+
+== SYNOPSIS
+
+*cryptsetup _luksKillSlot_ [<options>] <device> <key slot number>*
+
+== DESCRIPTION
+
+Wipe the key-slot number <key slot> from the LUKS device. Except running
+in batch-mode (-q) a remaining passphrase must be supplied, either
+interactively or via --key-file. This command can remove the last
+remaining key-slot, but requires an interactive confirmation when doing
+so. Removing the last passphrase makes a LUKS container permanently
+inaccessible.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
+--header, --disable-locks, --type, --verify-passphrase, --timeout].
+
+*WARNING:* If you read the passphrase from stdin (without further
+argument or with '-' as an argument to --key-file), batch-mode (-q) will
+be implicitly switched on and no warning will be given when you remove
+the last remaining passphrase from a LUKS container. Removing the last
+passphrase makes the LUKS container permanently inaccessible.
+
+*NOTE:* If there is no passphrase provided (on stdin or through
+--key-file argument) and batch-mode (-q) is active, the key-slot is
+removed without any other warning.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksRemoveKey.8.adoc b/man/cryptsetup-luksRemoveKey.8.adoc
new file mode 100644
index 0000000..b414f18
--- /dev/null
+++ b/man/cryptsetup-luksRemoveKey.8.adoc
@@ -0,0 +1,33 @@
+= cryptsetup-luksRemoveKey(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSREMOVEKEY:
+
+== Name
+
+cryptsetup-luksRemoveKey - remove the supplied passphrase from the LUKS device
+
+== SYNOPSIS
+
+*cryptsetup _luksRemoveKey_ [<options>] <device> [<key file with passphrase to be removed>]*
+
+== DESCRIPTION
+
+Removes the supplied passphrase from the LUKS device. The passphrase to
+be removed can be specified interactively, as the positional argument or
+via --key-file.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
+--header, --disable-locks, --type, --timeout, --verify-passphrase].
+
+*WARNING:* If you read the passphrase from stdin (without further
+argument or with '-' as an argument to --key-file), batch-mode (-q) will
+be implicitly switched on and no warning will be given when you remove
+the last remaining passphrase from a LUKS container. Removing the last
+passphrase makes the LUKS container permanently inaccessible.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksResume.8.adoc b/man/cryptsetup-luksResume.8.adoc
new file mode 100644
index 0000000..9d81cbc
--- /dev/null
+++ b/man/cryptsetup-luksResume.8.adoc
@@ -0,0 +1,29 @@
+= cryptsetup-luksResume(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSRESUME:
+
+== Name
+
+cryptsetup-luksResume - resume a suspended device and reinstate the key
+
+== SYNOPSIS
+
+*cryptsetup _luksResume_ [<options>] <name>*
+
+== DESCRIPTION
+
+Resumes a suspended device and reinstates the encryption key. Prompts
+interactively for a passphrase if no token is usable (LUKS2 only) or
+--key-file is not given.
+
+*<options>* can be [--key-file, --keyfile-size, --keyfile-offset,
+--key-slot, --header, --disable-keyring, --disable-locks, --token-id,
+--token-only, --token-type, --disable-external-tokens, --type, --tries,
+--timeout, --verify-passphrase].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksSuspend.8.adoc b/man/cryptsetup-luksSuspend.8.adoc
new file mode 100644
index 0000000..ed20681
--- /dev/null
+++ b/man/cryptsetup-luksSuspend.8.adoc
@@ -0,0 +1,33 @@
+= cryptsetup-luksSuspend(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSSUSPEND:
+
+== Name
+
+cryptsetup-luksSuspend - suspends an active device and wipes the key
+
+== SYNOPSIS
+
+*cryptsetup _luksSuspend_ [<options>] <name>*
+
+== DESCRIPTION
+
+Suspends an active device (all IO operations will block and accesses to
+the device will wait indefinitely) and wipes the encryption key from
+kernel memory. Needs kernel 2.6.19 or later.
+
+After this operation, you have to use _luksResume_ to reinstate the
+encryption key and unblock the device or _close_ to remove the mapped
+device.
+
+*<options>* can be [--header, --disable-locks].
+
+*WARNING:* Never suspend the device on which the cryptsetup binary
+resides.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-luksUUID.8.adoc b/man/cryptsetup-luksUUID.8.adoc
new file mode 100644
index 0000000..8ffe9ff
--- /dev/null
+++ b/man/cryptsetup-luksUUID.8.adoc
@@ -0,0 +1,25 @@
+= cryptsetup-luksUUID(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_LUKSUUID:
+
+== Name
+
+cryptsetup-luksUUID - print or set the UUID of a LUKS device
+
+== SYNOPSIS
+
+*cryptsetup _luksUUID_ [<options>] <device>*
+
+== DESCRIPTION
+
+Print the UUID of a LUKS device. +
+Set new UUID if _--uuid_ option is specified.
+
+*<options>* can be [--header, --uuid, --type, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-open.8.adoc b/man/cryptsetup-open.8.adoc
new file mode 100644
index 0000000..5e8e7a6
--- /dev/null
+++ b/man/cryptsetup-open.8.adoc
@@ -0,0 +1,165 @@
+= cryptsetup-open(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_OPEN:
+
+== Name
+
+cryptsetup-open, cryptsetup-create, cryptsetup-plainOpen, cryptsetup-luksOpen, cryptsetup-loopaesOpen, cryptsetup-tcryptOpen, cryptsetup-bitlkOpen, cryptsetup-fvault2Open - open an encrypted device and create a mapping with a specified name
+
+== SYNOPSIS
+
+*cryptsetup _open_ --type <device_type> [<options>] <device> <name>*
+
+== DESCRIPTION
+Opens (creates a mapping with) <name> backed by device <device>.
+
+Device type can be _plain_, _luks_ (default), _luks1_, _luks2_,
+_loopaes_ or _tcrypt_.
+
+For backward compatibility there are *open* command aliases:
+
+*create* (argument-order <name> <device>): open --type plain +
+*plainOpen*: open --type plain +
+*luksOpen*: open --type luks +
+*loopaesOpen*: open --type loopaes +
+*tcryptOpen*: open --type tcrypt +
+*bitlkOpen*: open --type bitlk
+
+*<options>* are type specific and are described below for individual
+device types. For *create*, the order of the <name> and <device> options
+is inverted for historical reasons, all other aliases use the standard
+*<device> <name>* order.
+
+=== PLAIN
+*open --type plain <device> <name>* +
+plainOpen <device> <name> (*old syntax*) +
+create <name> <device> (*OBSOLETE syntax*)
+
+Opens (creates a mapping with) <name> backed by device <device>.
+
+*<options>* can be [--hash, --cipher, --verify-passphrase, --sector-size,
+--key-file, --keyfile-size, --keyfile-offset, --key-size, --offset,
+--skip, --device-size, --size, --readonly, --shared, --allow-discards,
+--refresh, --timeout, --verify-passphrase, --iv-large-sectors].
+
+Example: 'cryptsetup open --type plain /dev/sda10 e1' maps the raw
+encrypted device /dev/sda10 to the mapped (decrypted) device
+/dev/mapper/e1, which can then be mounted, fsck-ed or have a filesystem
+created on it.
+
+=== LUKS
+*open <device> <name>* +
+open --type <luks1|luks2> <device> <name> (*explicit version request*) +
+luksOpen <device> <name> (*old syntax*)
+
+Opens the LUKS device <device> and sets up a mapping <name> after
+successful verification of the supplied passphrase.
+
+First, the passphrase is searched in LUKS2 tokens unprotected by PIN.
+If such token does not exist (or fails to unlock keyslot) and
+also the passphrase is not supplied via --key-file, the command
+prompts for passphrase interactively.
+
+If there is valid LUKS2 token but it requires PIN to unlock assigned keyslot,
+it is not used unless one of following options is added: --token-only,
+--token-type where type matches desired PIN protected token or --token-id with id
+matching PIN protected token.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
+--readonly, --test-passphrase, --allow-discards, --header, --key-slot,
+--volume-key-file, --token-id, --token-only, --token-type,
+--disable-external-tokens, --disable-keyring, --disable-locks, --type,
+--refresh, --serialize-memory-hard-pbkdf, --unbound, --tries, --timeout,
+--verify-passphrase, --persistent].
+
+=== loopAES
+*open --type loopaes <device> <name> --key-file <keyfile>* +
+loopaesOpen <device> <name> --key-file <keyfile> (*old syntax*)
+
+Opens the loop-AES <device> and sets up a mapping <name>.
+
+If the key file is encrypted with GnuPG, then you have to use
+--key-file=- and decrypt it before use, e.g., like this: +
+gpg --decrypt <keyfile> | cryptsetup loopaesOpen --key-file=- <device>
+<name>
+
+*WARNING:* The loop-AES extension cannot use the direct input of the key
+file on the real terminal because the keys are separated by end-of-line and
+only part of the multi-key file would be read. +
+If you need it in script, just use the pipe redirection: +
+echo $keyfile | cryptsetup loopaesOpen --key-file=- <device> <name>
+
+Use *--keyfile-size* to specify the proper key length if needed.
+
+Use *--offset* to specify device offset. Note that the units need to be
+specified in number of 512 byte sectors.
+
+Use *--skip* to specify the IV offset. If the original device used an
+offset and but did not use it in IV sector calculations, you have to
+explicitly use *--skip 0* in addition to the offset parameter.
+
+Use *--hash* to override the default hash function for passphrase
+hashing (otherwise it is detected according to key size).
+
+*<options>* can be [--cipher, --key-file, --keyfile-size, --keyfile-offset,
+--key-size, --offset, --skip, --hash, --readonly, --allow-discards, --refresh].
+
+=== TrueCrypt and VeraCrypt
+*open --type tcrypt <device> <name>* +
+tcryptOpen <device> <name> (*old syntax*)
+
+Opens the TCRYPT (TrueCrypt and VeraCrypt compatible) <device> and sets
+up a mapping <name>.
+
+*<options>* can be [--key-file, --tcrypt-hidden, --tcrypt-system,
+--tcrypt-backup, --readonly, --test-passphrase, --allow-discards,
+--veracrypt (ignored), --disable-veracrypt, --veracrypt-pim,
+--veracrypt-query-pim, --header,
+--cipher, --hash, --tries, --timeout, --verify-passphrase].
+
+The keyfile parameter allows a combination of file content with the
+passphrase and can be repeated. Note that using keyfiles is compatible
+with TCRYPT and is different from LUKS keyfile logic.
+
+If *--cipher* or *--hash* options are used, only cipher chains or PBKDF2
+variants with the specified hash algorithms are checked. This could
+speed up unlocking the device (but also it reveals some information
+about the container).
+
+If you use *--header* in combination with hidden or system options, the
+header file must contain specific headers on the same positions as the
+original encrypted container.
+
+*WARNING:* Option *--allow-discards* cannot be combined with option
+*--tcrypt-hidden*. For normal mapping, it can cause the *destruction of
+hidden volume* (hidden volume appears as unused space for outer volume
+so this space can be discarded).
+
+=== BitLocker
+*open --type bitlk <device> <name>* +
+bitlkOpen <device> <name> (*old syntax*)
+
+Opens the BITLK (a BitLocker compatible) <device> and sets up a mapping
+<name>.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size, --key-size,
+--readonly, --test-passphrase, --allow-discards --volume-key-file, --tries,
+--timeout, --verify-passphrase].
+
+=== FileVault2
+*open --type fvault2 <device> <name>* +
+fvault2Open <device> <name> (*old syntax*)
+
+Opens the FVAULT2 (a FileVault2 compatible) <device> and sets up a mapping
+<name>.
+
+*<options>* can be [--key-file, --keyfile-offset, --keyfile-size, --key-size,
+--readonly, --test-passphrase, --allow-discards --volume-key-file, --tries,
+--timeout, --verify-passphrase].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-reencrypt.8.adoc b/man/cryptsetup-reencrypt.8.adoc
new file mode 100644
index 0000000..154a469
--- /dev/null
+++ b/man/cryptsetup-reencrypt.8.adoc
@@ -0,0 +1,175 @@
+= cryptsetup-reencrypt(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_REENCRYPT:
+
+== Name
+
+cryptsetup-reencrypt - reencrypt LUKS encrypted volumes in-place
+
+== SYNOPSIS
+
+*cryptsetup _reencrypt_ [<options>] <device> or --active-name <name> [<new_name>]*
+
+== DESCRIPTION
+
+Run LUKS device reencryption.
+
+There are 3 basic modes of operation:
+
+* device reencryption (_reencrypt_)
+* device encryption (_reencrypt_ --encrypt/--new/-N)
+* device decryption (_reencrypt_ --decrypt)
+
+<device> or --active-name <name> (LUKS2 only) is mandatory parameter.
+
+Cryptsetup _reencrypt_ action can be used to change reencryption parameters
+which otherwise require full on-disk data change (re-encryption). The
+_reencrypt_ action reencrypts data on LUKS device in-place.
+
+You can regenerate *volume key* (the real key used in on-disk encryption
+unclocked by passphrase), *cipher*, *cipher mode* or *encryption sector size*
+(LUKS2 only).
+
+Reencryption process may be safely interrupted by a user via SIGINT
+signal (ctrl+c). Same applies to SIGTERM signal (i.e. issued by systemd
+during system shutdown).
+
+For in-place encryption mode, the _reencrypt_ action additionally takes all
+options available for _luksFormat_ action for respective LUKS version (see
+cryptsetup-luksFormat man page for more details). See *cryptsetup-luksFormat*(8).
+
+*NOTE* that for encrypt and decrypt mode, the whole device must be
+treated as unencrypted -- there are no quarantees of confidentiality as
+part of the device contains plaintext.
+
+*ALWAYS BE SURE YOU HAVE RELIABLE BACKUP BEFORE USING THIS ACTION ON LUKS DEVICE.*
+
+*<options>* can be [--batch-mode,
+--block-size,
+--cipher,
+--debug,
+--debug-json,
+--decrypt,
+--device-size,
+--disable-locks,
+--encrypt,
+--force-offline-reencrypt,
+--hash,
+--header,
+--hotzone-size,
+--iter-time,
+--init-only,
+--keep-key,
+--key-file,
+--key-size,
+--key-slot,
+--keyfile-offset,
+--keyfile-size,
+--tries,
+--timeout,
+--pbkdf,
+--pbkdf-force-iterations,
+--pbkdf-memory,
+--pbkdf-parallel,
+--progress-frequency,
+--progress-json,
+--reduce-device-size,
+--resilience,
+--resilience-hash,
+--resume-only,
+--sector-size,
+--use-directio,
+--use-random,
+--use-urandom,
+--use-fsync,
+--uuid,
+--verbose,
+--volume-key-file,
+--write-log].
+
+== LUKS2 REENCRYPTION
+
+With <device> parameter cryptsetup looks up active <device> dm mapping.
+If no active mapping is detected, it starts offline LUKS2 reencryption
+otherwise online reencryption takes place.
+
+To resume already initialized or interrupted reencryption, just run the
+cryptsetup _reencrypt_ command again to continue the reencryption
+operation. Reencryption may be resumed with different --resilience or
+--hotzone-size unless implicit datashift resilience mode is used: either
+encrypt mode with --reduce-device-size option or decrypt mode with
+original LUKS2 header exported in --header file.
+
+If the reencryption process was interrupted abruptly (reencryption
+process crash, system crash, poweroff) it may require recovery. The
+recovery is currently run automatically on next activation (action
+_open_) when needed or explicitly by user (action _repair_).
+
+Optional parameter <new_name> takes effect only with encrypt option
+and it activates device <new_name> immediately after encryption
+initialization gets finished. That's useful when device needs to be
+ready as soon as possible and mounted (used) before full data area
+encryption is completed.
+
+== LUKS1 REENCRYPTION
+
+Current working directory must be writable and temporary files created during
+reencryption must be present. During reencryption process the LUKS1 device is
+marked unavailable and must be offline (no dm-crypt mapping or mounted
+filesystem).
+
+*WARNING*: The LUKS1 reencryption code is not resistant to hardware
+or kernel failures during reencryption (you can lose your data in this case).
+
+include::man/common_options.adoc[]
+
+== EXAMPLES
+
+*NOTE*: You may drop *--type luks2* option as long as LUKS2 format is
+default.
+
+=== LUKS2 ENCRYPTION EXAMPLES
+
+Encrypt LUKS2 device (in-place). Make sure last 32 MiB on _/dev/plaintext_
+is unused (e.g.: does not contain filesystem data):
+
+*cryptsetup reencrypt --encrypt --type luks2 --reduce-device-size 32m /dev/plaintext_device*
+
+Encrypt LUKS2 device (in-place) with detached header put in a file:
+
+*cryptsetup reencrypt --encrypt --type luks2 --header my_luks2_header /dev/plaintext_device*
+
+Initialize LUKS2 in-place encryption operation only and activate the device (not yet encrypted):
+
+*cryptsetup reencrypt --encrypt --type luks2 --init-only --reduce-device-size 32m /dev/plaintext_device my_future_luks_device*
+
+Resume online encryption on device initialized in example above:
+
+*cryptsetup reencrypt --resume-only /dev/plaintext_device* or
+*cryptsetup reencrypt --active-name my_future_luks_device*
+
+=== LUKS2 REENCRYPTION EXAMPLES
+
+Reencrypt LUKS2 device (refresh volume key only):
+
+*cryptsetup reencrypt /dev/encrypted_device*
+
+=== LUKS2 DECRYPTION EXAMPLES
+
+Decrypt LUKS2 device with header put in head of data device (header file does not exist):
+
+*cryptsetup reencrypt --decrypt --header /export/header/to/file /dev/encrypted_device*
+
+Decrypt LUKS2 device with detached header (header file exists):
+
+*cryptsetup reencrypt --decrypt --header detached-luks2-header /dev/encrypted_device*
+
+Resume interrupted LUKS2 decryption:
+
+*cryptsetup reencrypt --resume-only --header luks2-hdr-file /dev/encrypted_device*
+
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-refresh.8.adoc b/man/cryptsetup-refresh.8.adoc
new file mode 100644
index 0000000..b79a80a
--- /dev/null
+++ b/man/cryptsetup-refresh.8.adoc
@@ -0,0 +1,53 @@
+= cryptsetup-refresh(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_REFRESH:
+
+== Name
+
+cryptsetup-refresh - refresh parameters of an active mapping
+
+== SYNOPSIS
+
+*cryptsetup _refresh_ [<options>] <name>*
+
+== DESCRIPTION
+
+Refreshes parameters of active mapping <name>.
+
+Updates parameters of active device <name> without the need to deactivate
+the device (and umount filesystem). Currently, it supports parameters
+refresh on following devices: LUKS1, LUKS2 (including authenticated
+encryption), plain crypt and loop-AES.
+
+Mandatory parameters are identical to those of an open action for
+the respective device type.
+
+You may change following parameters on all devices
+--perf-same_cpu_crypt, --perf-submit_from_crypt_cpus,
+--perf-no_read_workqueue, --perf-no_write_workqueue and
+--allow-discards.
+
+Refreshing the device without any optional parameter will refresh the device
+with default setting (respective to device type).
+
+*LUKS2 only:*
+
+The --integrity-no-journal parameter affects only LUKS2 devices with
+the underlying dm-integrity device.
+
+Adding option --persistent stores any combination of device parameters
+above in LUKS2 metadata (only after successful refresh operation).
+
+The --disable-keyring parameter refreshes a device with volume key passed in
+dm-crypt driver.
+
+*<options>* can be [--allow-discards, --perf-same_cpu_crypt, --perf-submit_from_crypt_cpus,
+--perf-no_read_workqueue, --perf-no_write_workqueue, --header, --disable-keyring,
+--disable-locks, --persistent, --integrity-no-journal].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-repair.8.adoc b/man/cryptsetup-repair.8.adoc
new file mode 100644
index 0000000..22ad9cb
--- /dev/null
+++ b/man/cryptsetup-repair.8.adoc
@@ -0,0 +1,43 @@
+= cryptsetup-repair(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_REPAIR:
+
+== Name
+
+cryptsetup-repair - repair the device metadata
+
+== SYNOPSIS
+
+*cryptsetup _repair_ [<options>] <device>*
+
+== DESCRIPTION
+
+Tries to repair the device metadata if possible. Currently supported
+only for LUKS device type.
+
+This command is useful to fix some known benign LUKS metadata header
+corruptions. Only basic corruptions of unused keyslot are fixable. This
+command will only change the LUKS header, not any key-slot data. You may
+enforce LUKS version by adding --type option.
+
+It also repairs (upgrades) LUKS2 reencryption metadata by adding
+a metadata digest that protects it against malicious changes.
+
+If LUKS2 reencryption was interrupted in the middle of writing
+reencryption segment the repair command can be used to perform
+reencryption recovery so that reencryption can continue later.
+Repairing reencryption requires verification of reencryption
+keyslot so passphrase or keyfile is needed.
+
+*<options>* can be [--timeout, --verify-passphrase, --disable-locks,
+--type, --header, --key-file, --keyfile-size, --keyfile-offset, --key-slot].
+
+*WARNING:* Always create a binary backup of the original header before
+calling this command.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-resize.8.adoc b/man/cryptsetup-resize.8.adoc
new file mode 100644
index 0000000..4cff482
--- /dev/null
+++ b/man/cryptsetup-resize.8.adoc
@@ -0,0 +1,42 @@
+= cryptsetup-resize(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_RESIZE:
+
+== Name
+
+cryptsetup-resize - resize an active mapping
+
+== SYNOPSIS
+
+*cryptsetup _resize_ [<options>] <name>*
+
+== DESCRIPTION
+
+Resizes an active mapping <name>.
+
+If --size (in 512-bytes sectors) or --device-size are not specified, the
+size is computed from the underlying device. For LUKS it is the size of
+the underlying device without the area reserved for LUKS header (see
+data payload offset in *luksDump* command). For plain crypt device, the
+whole device size is used.
+
+Note that this does not change the raw device geometry, it just changes
+how many sectors of the raw device are represented in the mapped device.
+
+If cryptsetup detected volume key for active device loaded in kernel
+keyring service, resize action would first try to retrieve the key using
+a token. Only if it failed, it'd ask for a passphrase to unlock a
+keyslot (LUKS) or to derive a volume key again (plain mode). The kernel
+keyring is used by default for LUKS2 devices.
+
+*<options>* can be [--size, --device-size, --token-id, --token-only,
+--token-type, --key-slot, --key-file, --keyfile-size, --keyfile-offset,
+--timeout, --disable-external-tokens, --disable-locks, --disable-keyring,
+--verify-passphrase, --timeout].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-ssh.8.adoc b/man/cryptsetup-ssh.8.adoc
new file mode 100644
index 0000000..f71f856
--- /dev/null
+++ b/man/cryptsetup-ssh.8.adoc
@@ -0,0 +1,80 @@
+= cryptsetup-ssh(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup-ssh {release-version}
+:man-linkstyle: pass:[blue R < >]
+
+== NAME
+
+cryptsetup-ssh - manage LUKS2 SSH token
+
+== SYNOPSIS
+
+*cryptsetup-ssh <action> [<options>] <action args>*
+
+== DESCRIPTION
+
+Experimental cryptsetup plugin for unlocking LUKS2 devices with token
+connected to an SSH server.
+
+This plugin currently allows only adding a token to an existing key
+slot. See *cryptsetup(8)* for instructions on how to remove, import or
+export the token.
+
+=== Add operation
+
+*add <options> <device>*
+
+Adds the SSH token to *<device>*.
+
+The specified SSH server must contain a key file on the specified path with
+a passphrase for an existing key slot on the device. Provided
+credentials will be used by cryptsetup to get the password when opening
+the device using the token.
+
+Options --ssh-server, --ssh-user, --ssh-keypath and --ssh-path are
+required for this operation.
+
+== OPTIONS
+
+**--key-slot**=_NUM_::
+Keyslot to assign the token to. If not specified, the token will be
+assigned to the first key slot matching provided passphrase.
+
+**--ssh-keypath**=_STRING_::
+Path to the SSH key for connecting to the remote server.
+
+**--ssh-path**=_STRING_::
+Path to the key file on the remote server.
+
+**--ssh-server**=_STRING_::
+IP address/URL of the remote server for this token.
+
+**--ssh-user**=_STRING_::
+Username used for the remote server.
+
+*--debug*::
+Show debug messages
+
+*--debug-json*::
+Show debug messages including JSON metadata
+
+*--verbose, -v*::
+Shows more detailed error messages
+
+*--help, -?*::
+Show help
+
+*--version, -V*::
+Print program version
+
+== NOTES
+
+The information provided when adding the token (SSH server address, user
+and paths) will be stored in the LUKS2 header in plaintext.
+
+== AUTHORS
+
+The cryptsetup-ssh tool is written by Vojtech Trefny.
+
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-status.8.adoc b/man/cryptsetup-status.8.adoc
new file mode 100644
index 0000000..1152f55
--- /dev/null
+++ b/man/cryptsetup-status.8.adoc
@@ -0,0 +1,24 @@
+= cryptsetup-status(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_STATUS:
+
+== Name
+
+cryptsetup-status - report the status for a mapping
+
+== SYNOPSIS
+
+*cryptsetup _status_ [<options>] <name>*
+
+== DESCRIPTION
+
+Reports the status for the mapping <name>.
+
+*<options>* can be [--header, --disable-locks].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-tcryptDump.8.adoc b/man/cryptsetup-tcryptDump.8.adoc
new file mode 100644
index 0000000..51d5041
--- /dev/null
+++ b/man/cryptsetup-tcryptDump.8.adoc
@@ -0,0 +1,37 @@
+= cryptsetup-tcryptDump(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_TCRYPTDUMP:
+
+== Name
+
+cryptsetup-tcryptDump - dump the header information of a TCRYPT (TrueCrypt or VeraCrypt compatible) device
+
+== SYNOPSIS
+
+*cryptsetup _tcryptDump_ [<options>] <device>*
+
+== DESCRIPTION
+
+Dump the header information of a TCRYPT (TrueCrypt or VeraCrypt compatible) device.
+
+If the --dump-volume-key option is used, the TCRYPT device volume key is
+dumped instead of TCRYPT header info. Beware that the volume key (or
+concatenated volume keys if cipher chain is used) can be used to decrypt
+the data stored in the TCRYPT container without a passphrase. This means
+that if the volume key is compromised, the whole device has to be erased
+to prevent further access. Use this option carefully.
+
+*<options>* can be [--dump-volume-key, --key-file, --tcrypt-hidden,
+--tcrypt-system, --tcrypt-backup, --veracrypt (ignored), --disable-veracrypt,
+--veracrypt-pim, --veracrypt-query-pim, --cipher, --hash, --header,
+--verify-passphrase, --timeout].
+
+The keyfile parameter allows a combination of file content with the
+passphrase and can be repeated.
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup-token.8.adoc b/man/cryptsetup-token.8.adoc
new file mode 100644
index 0000000..7a3a069
--- /dev/null
+++ b/man/cryptsetup-token.8.adoc
@@ -0,0 +1,55 @@
+= cryptsetup-token(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+:COMMON_OPTIONS:
+:ACTION_TOKEN:
+
+== Name
+
+cryptsetup-token - manage LUKS2 tokens
+
+== SYNOPSIS
+
+*cryptsetup _token_ <add|remove|import|export|unassign> [<options>] <device>*
+
+== DESCRIPTION
+
+Action _add_ creates a new keyring token to enable auto-activation of the
+device. For the auto-activation, the passphrase must be stored in
+keyring with the specified description. Usually, the passphrase should
+be stored in _user_ or _user-session_ keyring. The _token_ command is
+supported only for LUKS2.
+
+For adding new keyring token, option --key-description is mandatory.
+Also, new token is assigned to key slot specified with --key-slot option
+or to all active key slots in the case --key-slot option is omitted.
+
+To remove existing token, specify the token ID which should be removed
+with --token-id option.
+
+*WARNING:* The action _token remove_ removes any token type, not just
+_keyring_ type from token slot specified by --token-id option.
+
+Action _import_ can store arbitrary valid token json in LUKS2 header. It
+may be passed via standard input or via file passed in --json-file
+option. If you specify --key-slot then successfully imported token is
+also assigned to the key slot.
+
+Action _export_ writes requested token JSON to a file passed with
+--json-file or to standard output.
+
+Action _unassign_ removes token binding to specified keyslot. Both token
+and keyslot must be specified by --token-id and --key-slot parameters.
+
+If --token-id is used with action _add_ or action _import_ and a token
+with that ID already exists, option --token-replace can be used to
+replace the existing token.
+
+*<options>* can be [--header, --token-id, --key-slot, --key-description,
+--disable-external-tokens, --disable-locks, --disable-keyring,
+--json-file, --token-replace, --unbound].
+
+include::man/common_options.adoc[]
+include::man/common_footer.adoc[]
diff --git a/man/cryptsetup.8.adoc b/man/cryptsetup.8.adoc
new file mode 100644
index 0000000..ddd3a12
--- /dev/null
+++ b/man/cryptsetup.8.adoc
@@ -0,0 +1,729 @@
+= cryptsetup(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: cryptsetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+
+== Name
+
+cryptsetup - manage plain dm-crypt, LUKS, and other encrypted volumes
+
+== SYNOPSIS
+
+*cryptsetup <action> [<options>] <action args>*
+
+== DESCRIPTION
+
+cryptsetup is used to conveniently setup dm-crypt managed device-mapper
+mappings. These include plain dm-crypt volumes and LUKS volumes. The
+difference is that LUKS uses a metadata header and can hence offer more
+features than plain dm-crypt. On the other hand, the header is visible
+and vulnerable to damage.
+
+In addition, cryptsetup provides limited support for the use of loop-AES
+volumes, TrueCrypt, VeraCrypt, BitLocker and FileVault2 compatible volumes.
+
+For more information about specific cryptsetup action see
+*cryptsetup-<action>*(8), where *<action>* is the name of the
+cryptsetup action.
+
+== BASIC ACTIONS
+
+The following are valid actions for all supported device types.
+
+=== OPEN
+*open <device> <name> --type <device_type>*
+
+Opens (creates a mapping with) <name> backed by device <device>. +
+See *cryptsetup-open*(8).
+
+=== CLOSE
+*close <name>*
+
+Removes the existing mapping <name> and wipes the key from kernel memory. +
+See *cryptsetup-close*(8).
+
+=== STATUS
+*status <name>*
+
+Reports the status for the mapping <name>. +
+See *cryptsetup-status*(8).
+
+=== RESIZE
+*resize <name>*
+
+Resizes an active mapping <name>. +
+See *cryptsetup-resize*(8).
+
+=== REFRESH
+*refresh <name>*
+
+Refreshes parameters of active mapping <name>. +
+See *cryptsetup-refresh*(8).
+
+=== REENCRYPT
+*reencrypt <device> or --active-name <name> [<new_name>]*
+
+Run LUKS device reencryption. +
+See *cryptsetup-reencrypt*(8).
+
+== PLAIN MODE
+
+Plain dm-crypt encrypts the device sector-by-sector with a single,
+non-salted hash of the passphrase. No checks are performed, no metadata
+is used. There is no formatting operation. When the raw device is mapped
+(opened), the usual device operations can be used on the mapped device,
+including filesystem creation. Mapped devices usually reside in
+/dev/mapper/<name>.
+
+The following are valid plain device type actions:
+
+=== OPEN
+*open --type plain <device> <name>* +
+create <name> <device> (*OBSOLETE syntax*)
+
+Opens (creates a mapping with) <name> backed by device <device>. +
+See *cryptsetup-open*(8).
+
+== LUKS EXTENSION
+
+LUKS, the Linux Unified Key Setup, is a standard for disk encryption. It
+adds a standardized header at the start of the device, a key-slot area
+directly behind the header and the bulk data area behind that. The whole
+set is called a 'LUKS container'. The device that a LUKS container
+resides on is called a 'LUKS device'. For most purposes, both terms can
+be used interchangeably. But note that when the LUKS header is at a
+nonzero offset in a device, then the device is not a LUKS device
+anymore, but has a LUKS container stored in it at an offset.
+
+LUKS can manage multiple passphrases that can be individually revoked or
+changed and that can be securely scrubbed from persistent media due to
+the use of anti-forensic stripes. Passphrases are protected against
+brute-force and dictionary attacks by Password-Based Key Derivation
+Function (PBKDF).
+
+LUKS2 is a new version of header format that allows additional
+extensions like different PBKDF algorithm or authenticated encryption.
+You can format device with LUKS2 header if you specify *--type luks2* in
+*luksFormat* command. For activation, the format is already recognized
+automatically.
+
+Each passphrase, also called a *key* in this document, is associated
+with one of 8 key-slots. Key operations that do not specify a slot
+affect the first slot that matches the supplied passphrase or the first
+empty slot if a new passphrase is added.
+
+The *<device>* parameter can also be specified by a LUKS UUID in the
+format UUID=<uuid>. Translation to real device name uses symlinks in
+/dev/disk/by-uuid directory.
+
+To specify a detached header, the *--header* parameter can be used in
+all LUKS commands and always takes precedence over the positional
+*<device>* parameter.
+
+The following are valid LUKS actions:
+
+=== FORMAT
+*luksFormat <device> [<key file>]*
+
+Initializes a LUKS partition and sets the initial passphrase (for key-slot 0). +
+See *cryptsetup-luksFormat*(8).
+
+=== OPEN
+*open --type luks <device> <name>* +
+luksOpen <device> <name> (*old syntax*)
+
+Opens the LUKS device <device> and sets up a mapping <name> after
+successful verification of the supplied passphrase. +
+See *cryptsetup-open*(8).
+
+=== SUSPEND
+*luksSuspend <name>*
+
+Suspends an active device (all IO operations will block and accesses to
+the device will wait indefinitely) and wipes the encryption key from
+kernel memory. +
+See *cryptsetup-luksSuspend*(8).
+
+=== RESUME
+*luksResume <name>*
+
+Resumes a suspended device and reinstates the encryption key. +
+See *cryptsetup-luksResume*(8).
+
+=== ADD KEY
+*luksAddKey <device> [<key file with new key>]*
+
+Adds a new passphrase using an existing passphrase. +
+See *cryptsetup-luksAddKey*(8).
+
+=== REMOVE KEY
+*luksRemoveKey <device> [<key file with passphrase to be removed>]*
+
+Removes the supplied passphrase from the LUKS device. +
+See *cryptsetup-luksRemoveKey*(8).
+
+=== CHANGE KEY
+*luksChangeKey <device> [<new key file>]*
+
+Changes an existing passphrase. +
+See *cryptsetup-luksChangeKey*(8).
+
+=== CONVERT KEY
+*luksConvertKey <device>*
+
+Converts an existing LUKS2 keyslot to new PBKDF parameters. +
+See *cryptsetup-luksConvertKey*(8).
+
+=== KILL SLOT
+*luksKillSlot <device> <key slot number>*
+
+Wipe the key-slot number <key slot> from the LUKS device. +
+See *cryptsetup-luksKillSlot*(8).
+
+=== ERASE
+*erase <device>* +
+luksErase <device> (*old syntax*)
+
+Erase all keyslots and make the LUKS container permanently inaccessible. +
+See *cryptsetup-erase*(8).
+
+=== UUID
+*luksUUID <device>*
+
+Print or set the UUID of a LUKS device. +
+See *cryptsetup-luksUUID*(8).
+
+=== IS LUKS
+*isLuks <device>*
+
+Returns true, if <device> is a LUKS device, false otherwise. +
+See *cryptsetup-isLuks*(8).
+
+=== DUMP
+*luksDump <device>*
+
+Dump the header information of a LUKS device. +
+See *cryptsetup-luksDump*(8).
+
+=== HEADER BACKUP
+*luksHeaderBackup <device> --header-backup-file <file>*
+
+Stores a binary backup of the LUKS header and keyslot area. +
+See *cryptsetup-luksHeaderBackup*(8).
+
+=== HEADER RESTORE
+*luksHeaderRestore <device> --header-backup-file <file>*
+
+Restores a binary backup of the LUKS header and keyslot area from the
+specified file. +
+See *cryptsetup-luksHeaderRestore*(8).
+
+=== TOKEN
+*token <add|remove|import|export> <device>*
+
+Manipulate token objects used for obtaining passphrases. +
+See *cryptsetup-token*(8).
+
+=== CONVERT
+*convert <device> --type <format>*
+
+Converts the device between LUKS1 and LUKS2 format (if possible). +
+See *cryptsetup-convert*(8).
+
+=== CONFIG
+*config <device>*
+
+Set permanent configuration options (store to LUKS header). +
+See *cryptsetup-config*(8).
+
+== loop-AES EXTENSION
+
+cryptsetup supports mapping loop-AES encrypted partition using a
+compatibility mode.
+
+=== OPEN
+*open --type loopaes <device> <name> --key-file <keyfile>* +
+loopaesOpen <device> <name> --key-file <keyfile> (*old syntax*)
+
+Opens the loop-AES <device> and sets up a mapping <name>. +
+See *cryptsetup-open*(8).
+
+See also section 7 of the FAQ and http://loop-aes.sourceforge.net[loop-AES]
+for more information regarding loop-AES.
+
+== TCRYPT (TrueCrypt and VeraCrypt compatible) EXTENSION
+
+cryptsetup supports mapping of TrueCrypt, tcplay or VeraCrypt encrypted
+partition using a native Linux kernel API. Header formatting and TCRYPT
+header change is not supported, cryptsetup never changes TCRYPT header
+on-device.
+
+TCRYPT extension requires kernel userspace crypto API to be available
+(introduced in Linux kernel 2.6.38). If you are configuring kernel
+yourself, enable "User-space interface for symmetric key cipher
+algorithms" in "Cryptographic API" section
+(CRYPTO_USER_API_SKCIPHER .config option).
+
+Because TCRYPT header is encrypted, you have to always provide valid
+passphrase and keyfiles.
+
+Cryptsetup should recognize all header variants, except legacy cipher
+chains using LRW encryption mode with 64 bits encryption block (namely
+Blowfish in LRW mode is not recognized, this is limitation of kernel
+crypto API).
+
+VeraCrypt is extension of TrueCrypt header with increased iteration
+count so unlocking can take quite a lot of time.
+
+To open a VeraCrypt device with a custom Personal Iteration Multiplier
+(PIM) value, use either the *--veracrypt-pim=<PIM>* option to directly
+specify the PIM on the command- line or use *--veracrypt-query-pim* to
+be prompted for the PIM.
+
+The PIM value affects the number of iterations applied during key
+derivation. Please refer to
+https://www.veracrypt.fr/en/Personal%20Iterations%20Multiplier%20%28PIM%29.html[PIM]
+for more detailed information.
+
+If you need to disable VeraCrypt device support, use
+*--disable-veracrypt* option.
+
+*NOTE:* Activation with *tcryptOpen* is supported only for cipher chains
+using LRW or XTS encryption modes.
+
+The *tcryptDump* command should work for all recognized TCRYPT devices
+and doesn't require superuser privilege.
+
+To map system device (device with boot loader where the whole encrypted
+system resides) use *--tcrypt-system* option. You can use partition
+device as the parameter (parameter must be real partition device, not an
+image in a file), then only this partition is mapped.
+
+If you have the whole TCRYPT device as a file image and you want to map
+multiple partition encrypted with system encryption, please create
+loopback mapping with partitions first (*losetup -P*, see *losetup(8)*
+man page for more info), and use loop partition as the device parameter.
+
+If you use the whole base device as a parameter, one device for the
+whole system encryption is mapped. This mode is available only for
+backward compatibility with older cryptsetup versions which mapped
+TCRYPT system encryption using the whole device.
+
+To use hidden header (and map hidden device, if available), use
+*--tcrypt-hidden* option.
+
+To explicitly use backup (secondary) header, use *--tcrypt-backup*
+option.
+
+*NOTE:* There is no protection for a hidden volume if the outer volume
+is mounted. The reason is that if there were any protection, it would
+require some metadata describing what to protect in the outer volume and
+the hidden volume would become detectable.
+
+=== OPEN
+*open --type tcrypt <device> <name>* +
+tcryptOpen_ <device> <name> (*old syntax*)
+
+Opens the TCRYPT (a TrueCrypt-compatible) <device> and sets up a mapping
+<name>. +
+See *cryptsetup-open*(8).
+
+=== DUMP
+*tcryptDump <device>*
+
+Dump the header information of a TCRYPT device. +
+See *cryptsetup-tcryptDump*(8).
+
+See also https://en.wikipedia.org/wiki/TrueCrypt[*TrueCrypt*] and
+https://en.wikipedia.org/wiki/VeraCrypt[*VeraCrypt*] pages for more information.
+
+Please note that cryptsetup does not use TrueCrypt or VeraCrypt code, please
+report all problems related to this compatibility extension to the cryptsetup
+project.
+
+== BITLK (Windows BitLocker compatible) EXTENSION
+
+cryptsetup supports mapping of BitLocker and BitLocker to Go encrypted
+partition using a native Linux kernel API. Header formatting and BITLK
+header changes are not supported, cryptsetup never changes BITLK header
+on-device.
+
+BITLK extension requires kernel userspace crypto API to be available
+(for details see TCRYPT section).
+
+Cryptsetup should recognize all BITLK header variants, except legacy
+header used in Windows Vista systems and partially decrypted BitLocker
+devices. Activation of legacy devices encrypted in CBC mode requires at
+least Linux kernel version 5.3 and for devices using Elephant diffuser
+kernel 5.6.
+
+The *bitlkDump* command should work for all recognized BITLK devices and
+doesn't require superuser privilege.
+
+For unlocking with the *open* a password or a recovery passphrase or a
+startup key must be provided.
+
+Additionally unlocking using volume key is supported. You must provide
+BitLocker Full Volume Encryption Key (FVEK) using the --volume-key-file
+option. The key must be decrypted and without the header (only
+128/256/512 bits of key data depending on used cipher and mode).
+
+Other unlocking methods (TPM, SmartCard) are not supported.
+
+=== OPEN
+*open --type bitlk <device> <name>* +
+bitlkOpen <device> <name> (*old syntax*)
+
+Opens the BITLK (a BitLocker-compatible) <device> and sets up a mapping
+<name>. +
+See *cryptsetup-open*(8).
+
+=== DUMP
+*bitlkDump <device>*
+
+Dump the header information of a BITLK device. +
+See *cryptsetup-bitlkDump*(8).
+
+Please note that cryptsetup does not use any Windows BitLocker code,
+please report all problems related to this compatibility extension to
+the cryptsetup project.
+
+== FVAULT2 (Apple macOS FileVault2 compatible) EXTENSION
+
+cryptsetup supports the mapping of FileVault2 (FileVault2 full-disk
+encryption) by Apple for the macOS operating system using a native Linux
+kernel API.
+
+*NOTE:* cryptsetup supports only FileVault2 based on Core Storage and HFS+
+filesystem (introduced in MacOS X 10.7 Lion).
+It does NOT support the new version of FileVault based on the APFS
+filesystem used in recent macOS versions.
+
+Header formatting and FVAULT2 header changes are not supported;
+cryptsetup never changes the FVAULT2 header on-device.
+
+FVAULT2 extension requires kernel userspace crypto API to be available
+(for details, see TCRYPT section) and kernel driver for HFS+ (hfsplus)
+filesystem.
+
+Cryptsetup should recognize the basic configuration for portable drives.
+
+The *fvault2Dump* command should work for all recognized FVAULT2 devices
+and doesn't require superuser privilege.
+
+For unlocking with the *open*, a password must be provided.
+Other unlocking methods are not supported.
+
+=== OPEN
+*open --type fvault2 <device> <name>* +
+fvault2Open <device> <name> (*old syntax*)
+
+Opens the FVAULT2 (a FileVault2-compatible) <device> (usually the second
+partition on the device) and sets up a mapping <name>. +
+See *cryptsetup-open*(8).
+
+=== DUMP
+*fvault2Dump <device>*
+
+Dump the header information of an FVAULT2 device. +
+See *cryptsetup-fvault2Dump*(8).
+
+Note that cryptsetup does not use any macOS code or proprietary
+specifications. Please report all problems related to this compatibility
+extension to the cryptsetup project.
+
+== MISCELLANEOUS ACTIONS
+
+=== REPAIR
+*repair <device>*
+
+Tries to repair the device metadata if possible. Currently supported
+only for LUKS device type. +
+See *cryptsetup-repair*(8).
+
+=== BENCHMARK
+*benchmark <options>*
+
+Benchmarks ciphers and KDF (key derivation function). +
+See *cryptsetup-benchmark*(8).
+
+== PLAIN DM-CRYPT OR LUKS?
+
+Unless you understand the cryptographic background well, use LUKS. With
+plain dm-crypt there are a number of possible user errors that massively
+decrease security. While LUKS cannot fix them all, it can lessen the
+impact for many of them.
+
+== WARNINGS
+
+A lot of good information on the risks of using encrypted storage, on
+handling problems and on security aspects can be found in the
+Cryptsetup FAQ. Read it. Nonetheless, some risks deserve to be
+mentioned here.
+
+*Backup:* Storage media die. Encryption has no influence on that. Backup
+is mandatory for encrypted data as well, if the data has any worth. See
+the Cryptsetup FAQ for advice on how to do a backup of an encrypted
+volume.
+
+*Character encoding:* If you enter a passphrase with special symbols,
+the passphrase can change depending on character encoding. Keyboard
+settings can also change, which can make blind input hard or impossible.
+For example, switching from some ASCII 8-bit variant to UTF-8 can lead
+to a different binary encoding and hence different passphrase seen by
+cryptsetup, even if what you see on the terminal is exactly the same. It
+is therefore highly recommended to select passphrase characters only
+from 7-bit ASCII, as the encoding for 7-bit ASCII stays the same for all
+ASCII variants and UTF-8.
+
+*LUKS header:* If the header of a LUKS volume gets damaged, all data is
+permanently lost unless you have a header-backup. If a key-slot is
+damaged, it can only be restored from a header-backup or if another
+active key-slot with known passphrase is undamaged. Damaging the LUKS
+header is something people manage to do with surprising frequency. This
+risk is the result of a trade-off between security and safety, as LUKS
+is designed for fast and secure wiping by just overwriting header and
+key-slot area.
+
+*Previously used partitions:* If a partition was previously used, it is
+a very good idea to wipe filesystem signatures, data, etc. before
+creating a LUKS or plain dm-crypt container on it. For a quick removal
+of filesystem signatures, use *wipefs*(8). Take care though that this may
+not remove everything. In particular, MD RAID signatures at the end of a
+device may survive. It also does not remove data. For a full wipe,
+overwrite the whole partition before container creation. If you do not
+know how to do that, the cryptsetup FAQ describes several options.
+
+== EXAMPLES
+
+Example 1: Create LUKS 2 container on block device /dev/sdX.::
+ sudo cryptsetup --type luks2 luksFormat /dev/sdX
+Example 2: Add an additional passphrase to key slot 5.::
+ sudo cryptsetup luksAddKey --key-slot 5 /dev/sdX
+Example 3: Create LUKS header backup and save it to file.::
+ sudo cryptsetup luksHeaderBackup /dev/sdX --header-backup-file
+ /var/tmp/NameOfBackupFile
+Example 4: Open LUKS container on /dev/sdX and map it to sdX_crypt.::
+ sudo cryptsetup open /dev/sdX sdX_crypt
+*WARNING: The command in example 5 will erase all key slots.*::
+ Your cannot use your LUKS container afterward anymore unless you have
+ a backup to restore.
+Example 5: Erase all key slots on /dev/sdX.::
+ sudo cryptsetup erase /dev/sdX
+Example 6: Restore LUKS header from backup file.::
+ sudo cryptsetup luksHeaderRestore /dev/sdX --header-backup-file
+ /var/tmp/NameOfBackupFile
+
+== RETURN CODES
+
+Cryptsetup returns *0* on success and a non-zero value on error.
+
+Error codes are: *1* wrong parameters, *2* no permission (bad passphrase),
+*3* out of memory, *4* wrong device specified, *5* device already exists
+or device is busy.
+
+== NOTES
+
+=== Passphrase processing for PLAIN mode
+
+Note that no iterated hashing or salting is done in plain mode. If
+hashing is done, it is a single direct hash. This means that low-entropy
+passphrases are easy to attack in plain mode.
+
+*From a terminal*: The passphrase is read until the first newline, i.e.
+'\n'. The input without the newline character is processed with the
+default hash or the hash specified with --hash. The hash result will be
+truncated to the key size of the used cipher, or the size specified with
+-s.
+
+*From stdin*: Reading will continue until a newline (or until the
+maximum input size is reached), with the trailing newline stripped. The
+maximum input size is defined by the same compiled-in default as for the
+maximum key file size and can be overwritten using --keyfile-size
+option.
+
+The data read will be hashed with the default hash or the hash specified
+with --hash. The hash result will be truncated to the key size of the
+used cipher, or the size specified with -s.
+
+Note that if --key-file=- is used for reading the key from stdin,
+trailing newlines are not stripped from the input.
+
+If "plain" is used as argument to --hash, the input data will not be
+hashed. Instead, it will be zero padded (if shorter than the key size)
+or truncated (if longer than the key size) and used directly as the
+binary key. This is useful for directly specifying a binary key. No
+warning will be given if the amount of data read from stdin is less than
+the key size.
+
+*From a key file*: It will be truncated to the key size of the used
+cipher or the size given by -s and directly used as a binary key.
+
+*WARNING*: The --hash argument is being ignored. The --hash option is
+usable only for stdin input in plain mode.
+
+If the key file is shorter than the key, cryptsetup will quit with an
+error. The maximum input size is defined by the same compiled-in default
+as for the maximum key file size and can be overwritten using
+--keyfile-size option.
+
+=== Passphrase processing for LUKS
+
+LUKS uses PBKDF to protect against dictionary attacks and to give some
+protection to low-entropy passphrases (see cryptsetup FAQ).
+
+*From a terminal*: The passphrase is read until the first newline and
+then processed by PBKDF2 without the newline character.
+
+*From stdin*: LUKS will read passphrases from stdin up to the first
+newline character or the compiled-in maximum key file length. If
+--keyfile-size is given, it is ignored.
+
+*From key file*: The complete keyfile is read up to the compiled-in
+maximum size. Newline characters do not terminate the input. The
+--keyfile-size option can be used to limit what is read.
+
+*Passphrase processing*: Whenever a passphrase is added to a LUKS header
+(luksAddKey, luksFormat), the user may specify how much the time the
+passphrase processing should consume. The time is used to determine the
+iteration count for PBKDF2 and higher times will offer better protection
+for low-entropy passphrases, but open will take longer to complete. For
+passphrases that have entropy higher than the used key length, higher
+iteration times will not increase security.
+
+The default setting of one or two seconds is sufficient for most
+practical cases. The only exception is a low-entropy passphrase used on
+a device with a slow CPU, as this will result in a low iteration count.
+On a slow device, it may be advisable to increase the iteration time
+using the --iter-time option in order to obtain a higher iteration
+count. This does slow down all later luksOpen operations accordingly.
+
+=== Incoherent behavior for invalid passphrases/keys
+
+LUKS checks for a valid passphrase when an encrypted partition is
+unlocked. The behavior of plain dm-crypt is different. It will always
+decrypt with the passphrase given. If the given passphrase is wrong, the
+device mapped by plain dm-crypt will essentially still contain encrypted
+data and will be unreadable.
+
+=== Supported ciphers, modes, hashes and key sizes
+
+The available combinations of ciphers, modes, hashes and key sizes
+depend on kernel support. See /proc/crypto for a list of available
+options. You might need to load additional kernel crypto modules in
+order to get more options.
+
+For the --hash option, if the crypto backend is libgcrypt, then all
+algorithms supported by the gcrypt library are available. For other
+crypto backends, some algorithms may be missing.
+
+=== Notes on passphrases
+
+Mathematics can't be bribed. Make sure you keep your passphrases safe.
+There are a few nice tricks for constructing a fallback, when suddenly
+out of the blue, your brain refuses to cooperate. These fallbacks need
+LUKS, as it's only possible with LUKS to have multiple passphrases.
+Still, if your attacker model does not prevent it, storing your
+passphrase in a sealed envelope somewhere may be a good idea as well.
+
+=== Notes on Random Number Generators
+
+Random Number Generators (RNG) used in cryptsetup are always the kernel
+RNGs without any modifications or additions to data stream produced.
+
+There are two types of randomness cryptsetup/LUKS needs. One type (which
+always uses /dev/urandom) is used for salts, the AF splitter and for
+wiping deleted keyslots.
+
+The second type is used for the volume key. You can switch between using
+/dev/random and /dev/urandom here, see *--use-random* and
+*--use-urandom* options. Using /dev/random on a system without enough
+entropy sources can cause *luksFormat* to block until the requested
+amount of random data is gathered. In a low-entropy situation (embedded
+system), this can take a very long time and potentially forever. At the
+same time, using /dev/urandom in a low-entropy situation will produce
+low-quality keys. This is a serious problem, but solving it is out of
+scope for a mere man-page. See *urandom(4)* for more information.
+
+=== Authenticated disk encryption (EXPERIMENTAL)
+
+Since Linux kernel version 4.12 dm-crypt supports authenticated disk
+encryption.
+
+Normal disk encryption modes are length-preserving (plaintext sector is
+of the same size as a ciphertext sector) and can provide only
+confidentiality protection, but not cryptographically sound data
+integrity protection.
+
+Authenticated modes require additional space per-sector for
+authentication tag and use Authenticated Encryption with Additional Data
+(AEAD) algorithms.
+
+If you configure LUKS2 device with data integrity protection, there will
+be an underlying dm-integrity device, which provides additional
+per-sector metadata space and also provide data journal protection to
+ensure atomicity of data and metadata update. Because there must be
+additional space for metadata and journal, the available space for the
+device will be smaller than for length-preserving modes.
+
+The dm-crypt device then resides on top of such a dm-integrity device.
+All activation and deactivation of this device stack is performed by
+cryptsetup, there is no difference in using *luksOpen* for integrity
+protected devices. If you want to format LUKS2 device with data
+integrity protection, use *--integrity* option.
+
+Since dm-integrity doesn't support discards (TRIM), dm-crypt device on
+top of it inherits this, so integrity protection mode doesn't support
+discards either.
+
+Some integrity modes requires two independent keys (key for encryption
+and for authentication). Both these keys are stored in one LUKS keyslot.
+
+*WARNING:* All support for authenticated modes is experimental and there
+are only some modes available for now. Note that there are a very few
+authenticated encryption algorithms that are suitable for disk
+encryption. You also cannot use CRC32 or any other non-cryptographic
+checksums (other than the special integrity mode "none"). If for some
+reason you want to have integrity control without using authentication
+mode, then you should separately configure dm-integrity independently of
+LUKS2.
+
+=== Notes on loopback device use
+
+Cryptsetup is usually used directly on a block device (disk partition or
+LVM volume). However, if the device argument is a file, cryptsetup tries
+to allocate a loopback device and map it into this file. This mode
+requires Linux kernel 2.6.25 or more recent which supports the loop
+autoclear flag (loop device is cleared on the last close automatically).
+Of course, you can always map a file to a loop-device manually. See the
+cryptsetup FAQ for an example.
+
+When device mapping is active, you can see the loop backing file in the
+status command output. Also see losetup(8).
+
+=== LUKS2 header locking
+
+The LUKS2 on-disk metadata is updated in several steps and to achieve
+proper atomic update, there is a locking mechanism. For an image in
+file, code uses *flock(2)* system call. For a block device, lock is
+performed over a special file stored in a locking directory (by default
+*/run/cryptsetup*). The locking directory should be created with the
+proper security context by the distribution during the boot-up phase.
+Only LUKS2 uses locks, other formats do not use this mechanism.
+
+=== LUKS on-disk format specification
+
+For LUKS on-disk metadata specification see
+https://gitlab.com/cryptsetup/cryptsetup/wikis/Specification[*LUKS1*] and
+https://gitlab.com/cryptsetup/LUKS2-docs[*LUKS2*].
+
+== AUTHORS
+
+Cryptsetup is originally written by mailto:jana@saout.de[Jana Saout]. +
+The LUKS extensions and original man page were written by
+mailto:clemens@endorphin.org[Clemens Fruhwirth]. +
+Man page extensions by mailto:gmazyland@gmail.com[Milan Broz]. +
+Man page rewrite and extension by mailto:arno@wagner.name[Arno Wagner].
+
+include::man/common_footer.adoc[]
diff --git a/man/integritysetup.8.adoc b/man/integritysetup.8.adoc
new file mode 100644
index 0000000..2aec1a6
--- /dev/null
+++ b/man/integritysetup.8.adoc
@@ -0,0 +1,334 @@
+= integritysetup(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: integritysetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+
+== NAME
+
+integritysetup - manage dm-integrity (block level integrity) volumes
+
+== SYNOPSIS
+
+*integritysetup <action> [<options>] <action args>*
+
+== DESCRIPTION
+
+Integritysetup is used to configure dm-integrity managed device-mapper
+mappings.
+
+Device-mapper integrity target provides read-write transparent integrity
+checking of block devices. The dm-integrity target emulates an additional
+data integrity field per-sector. You can use this additional field
+directly with integritysetup utility, or indirectly (for authenticated
+encryption) through cryptsetup.
+
+== BASIC ACTIONS
+
+Integritysetup supports these operations:
+
+=== FORMAT
+*format <device>*
+
+Formats <device> (calculates space and dm-integrity superblock and wipes
+the device).
+
+*<options>* can be [--data-device, --batch-mode, --no-wipe,
+--journal-size, --interleave-sectors, --tag-size, --integrity,
+--integrity-key-size, --integrity-key-file, --sector-size,
+--progress-frequency, --progress-json].
+
+=== OPEN
+*open <device> <name>* +
+create <name> <device> (*OBSOLETE syntax*)
+
+Open a mapping with <name> backed by device <device>.
+
+*<options>* can be [--data-device, --batch-mode, --journal-watermark,
+--journal-commit-time, --buffer-sectors, --integrity,
+--integrity-key-size, --integrity-key-file, --integrity-no-journal,
+--integrity-recalculate,
+--integrity-recalculate-reset,--integrity-recovery-mode,
+--allow-discards].
+
+=== CLOSE
+*close <name>* +
+remove <name> (*OBSOLETE syntax*)
+
+Removes existing mapping <name>.
+
+*<options>* can be [--deferred] or [--cancel-deferred]
+
+=== STATUS
+*status <name>*
+
+Reports status for the active integrity mapping <name>.
+
+=== DUMP
+*dump <device>*
+
+Reports parameters from on-disk stored superblock.
+
+=== RESIZE
+*resize <name>*
+
+Resizes an active mapping <name>.
+
+If --size (in 512-bytes sectors) or --device-size are not specified, the
+size is computed from the underlying device. After resize, the
+*recalculating* flag is set. If --wipe flag is set and the size of the
+device is increased, the newly added section will be wiped.
+
+Increasing the size of integrity volumes is available since the Linux
+kernel version 5.7, shrinking should work on older kernels too.
+
+*<options>* can be [--size, --device-size, --wipe].
+
+== OPTIONS
+*--progress-frequency <seconds>*::
+Print separate line every <seconds> with wipe progress.
+
+*--progress-json*::
+Prints wipe progress data in json format suitable mostly for machine
+processing. It prints separate line every half second (or based on
+--progress-frequency value). The JSON output looks as follows during
+wipe progress (except it's compact single line):
++
+....
+{
+ "device":"/dev/sda" // backing device or file
+ "device_bytes":"8192", // bytes wiped so far
+ "device_size":"44040192", // total bytes to wipe
+ "speed":"126877696", // calculated speed in bytes per second (based on progress so far)
+ "eta_ms":"2520012" // estimated time to finish wipe in milliseconds
+ "time_ms":"5561235" // total time spent wiping device in milliseconds
+}
+....
++
+Note on numbers in JSON output: Due to JSON parsers limitations all
+numbers are represented in a string format due to need of full 64bit
+unsigned integers.
+
+*--no-wipe*::
+Do not wipe the device after format. A device that is not initially
+wiped will contain invalid checksums.
+
+*--wipe*::
+Wipe the newly allocated area after resize to bigger size. If this
+flag is not set, checksums will be calculated for the data previously
+stored in the newly allocated area.
+
+*--journal-size, -j BYTES*::
+Size of the journal.
+
+*--interleave-sectors SECTORS*::
+The number of interleaved sectors.
+
+*--integrity-recalculate*::
+Automatically recalculate integrity tags in kernel on activation. The
+device can be used during automatic integrity recalculation but
+becomes fully integrity protected only after the background operation
+is finished. This option is available since the Linux kernel version
+4.19.
+
+*--integrity-recalculate-reset*::
+Restart recalculation from the beginning of the device. It can be used
+to change the integrity checksum function. Note it does not change the
+tag length. This option is available since the Linux kernel version
+5.13.
+
+*--journal-watermark PERCENT*::
+Journal watermark in percents. When the size of the journal exceeds
+this watermark, the journal flush will be started.
+
+*--journal-commit-time MS*::
+Commit time in milliseconds. When this time passes (and no explicit
+flush operation was issued), the journal is written.
+
+*--tag-size, -t BYTES*::
+Size of the integrity tag per-sector (here the integrity function will
+store authentication tag).
++
+*NOTE:* The size can be smaller that output size of the hash function,
+in that case only part of the hash will be stored.
+
+*--data-device <data_device>*::
+Specify a separate data device that contains existing data. The
+<device> then will contain calculated integrity tags and journal for
+data on <data_device>.
++
+*NOTE:* To not wipe the data device after initial format, also specify
+--no-wipe option and activate with --integrity-recalculate to
+automatically recalculate integrity tags.
+
+*--sector-size, -s BYTES*::
+Sector size (power of two: 512, 1024, 2048, 4096).
+
+*--buffer-sectors SECTORS*::
+The number of sectors in one buffer.
++
+The tag area is accessed using buffers, the large buffer size means that
+the I/O size will be larger, but there could be less I/Os issued.
+
+*--integrity, -I ALGORITHM*::
+Use internal integrity calculation (standalone mode). The integrity
+algorithm can be CRC (crc32c/crc32), non-cryptographic hash function
+(xxhash64) or hash function (sha1, sha256).
++
+For HMAC (hmac-sha256) you have also to specify an integrity key and its
+size.
+
+*--integrity-key-size BYTES*::
+The size of the data integrity key. Maximum is 4096 bytes.
+
+*--integrity-key-file FILE*::
+The file with the integrity key.
+
+*--integrity-no-journal, -D*::
+Disable journal for integrity device.
+
+*--integrity-bitmap-mode. -B*::
+Use alternate bitmap mode (available since Linux kernel 5.2) where
+dm-integrity uses bitmap instead of a journal. If a bit in the bitmap
+is 1, the corresponding region's data and integrity tags are not
+synchronized - if the machine crashes, the unsynchronized regions will
+be recalculated. The bitmap mode is faster than the journal mode,
+because we don't have to write the data twice, but it is also less
+reliable, because if data corruption happens when the machine crashes,
+it may not be detected.
+
+*--bitmap-sectors-per-bit SECTORS*::
+Number of 512-byte sectors per bitmap bit, the value must be power of
+two.
+
+*--bitmap-flush-time MS*::
+Bitmap flush time in milliseconds.
++
+*WARNING:*::
+In case of a crash, it is possible that the data and integrity tag
+doesn't match if the journal is disabled.
+
+*--integrity-recovery-mode. -R*::
+Recovery mode (no journal, no tag checking).
+
+*NOTE:* The following options are intended for testing purposes only.:
+Using journal encryption does not make sense without encryption the
+data, these options are internally used in authenticated disk
+encryption with *cryptsetup(8)*.
+
+*--journal-integrity ALGORITHM*::
+Integrity algorithm for journal area. See --integrity option for
+detailed specification.
+
+*--journal-integrity-key-size BYTES*::
+The size of the journal integrity key. Maximum is 4096 bytes.
+
+*--journal-integrity-key-file FILE*::
+The file with the integrity key.
+
+*--journal-crypt ALGORITHM*::
+Encryption algorithm for journal data area. You can use a block cipher
+here such as cbc-aes or a stream cipher, for example, chacha20 or
+ctr-aes.
+
+*--journal-crypt-key-size BYTES*::
+The size of the journal encryption key. Maximum is 4096 bytes.
+
+*--journal-crypt-key-file FILE*::
+The file with the journal encryption key.
+
+*--allow-discards*::
+Allow the use of discard (TRIM) requests for the device. This option
+is available since the Linux kernel version 5.7.
+
+*--deferred*::
+Defers device removal in *close* command until the last user closes
+it.
+
+*--cancel-deferred*::
+Removes a previously configured deferred device removal in *close*
+command.
+
+*--verbose, -v*::
+Print more information on command execution.
+
+*--debug*::
+Run in debug mode with full diagnostic logs. Debug output lines are
+always prefixed by *#*.
+
+*--version, -V*::
+Show the program version.
+
+*--batch-mode, -q*::
+Do not ask for confirmation.
+
+*--usage*::
+Show short option help.
+
+*--help, -?*::
+Show help text and default parameters.
+
+== LEGACY COMPATIBILITY OPTIONS
+
+*WARNING:*::
+Do not use these options until you need compatibility with specific
+old kernel.
+
+*--integrity-legacy-padding*::
+Use inefficient legacy padding.
+
+*--integrity-legacy-hmac*::
+Use old flawed HMAC calculation (also does not protect superblock).
+
+*--integrity-legacy-recalculate*::
+Allow insecure recalculating of volumes with HMAC keys (recalculation
+offset in superblock is not protected).
+
+== RETURN CODES
+
+Integritysetup returns *0* on success and a non-zero value on error.
+
+Error codes are: *1* wrong parameters, *2* no permission, *3* out of memory,
+*4* wrong device specified, *5* device already exists or device is busy.
+
+== NOTES
+The dm-integrity target is available since Linux kernel version 4.12.
+
+Format and activation of an integrity device always require superuser
+privilege because the superblock is calculated and handled in
+dm-integrity kernel target.
+
+== EXAMPLES
+
+Format the device with default standalone mode (CRC32C):
+
+*integritysetup format <device>*
+
+Open the device with default parameters:
+
+*integritysetup open <device> test*
+
+Format the device in standalone mode for use with HMAC(SHA256):
+
+*integritysetup format <device> --tag-size 32 --integrity hmac-sha256
+--integrity-key-file <keyfile> --integrity-key-size <key_bytes>*
+
+Open (activate) the device with HMAC(SHA256) and HMAC key in file:
+
+*integritysetup open <device> test --integrity hmac-sha256
+--integrity-key-file <keyfile> --integrity-key-size <key_bytes>*
+
+Dump dm-integrity superblock information:
+
+*integritysetup dump <device>*
+
+== DM-INTEGRITY ON-DISK FORMAT
+
+The on-disk format specification available at
+https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity[*DMIntegrity*] page.
+
+== AUTHORS
+
+The integritysetup tool is written by mailto:gmazyland@gmail.com[Milan Broz].
+
+include::man/common_footer.adoc[]
diff --git a/man/veritysetup.8.adoc b/man/veritysetup.8.adoc
new file mode 100644
index 0000000..36d1501
--- /dev/null
+++ b/man/veritysetup.8.adoc
@@ -0,0 +1,311 @@
+= veritysetup(8)
+:doctype: manpage
+:manmanual: Maintenance Commands
+:mansource: veritysetup {release-version}
+:man-linkstyle: pass:[blue R < >]
+
+== NAME
+
+veritysetup - manage dm-verity (block level verification) volumes
+
+== SYNOPSIS
+
+*veritysetup <action> [<options>] <action args>*
+
+== DESCRIPTION
+
+Veritysetup is used to configure dm-verity managed device-mapper
+mappings.
+
+Device-mapper verity target provides read-only transparent integrity
+checking of block devices using kernel crypto API.
+
+The dm-verity devices are always read-only.
+
+== BASIC ACTIONS
+
+Veritysetup supports these operations:
+
+=== FORMAT
+*format <data_device> <hash_device>*
+
+Calculates and permanently stores hash verification data for
+data_device. Hash area can be located on the same device after data if
+specified by --hash-offset option.
+
+Note you need to provide root hash string for device verification or
+activation. Root hash must be trusted.
+
+The data or hash device argument can be block device or file image. If
+hash device path doesn't exist, it will be created as file.
+
+*<options>* can be [--hash, --no-superblock, --format,
+--data-block-size, --hash-block-size, --data-blocks, --hash-offset,
+--salt, --uuid, --root-hash-file].
+
+If option --root-hash-file is used, the root hash is stored in
+hex-encoded text format in <path>.
+
+=== OPEN
+*open <data_device> <name> <hash_device> <root_hash>* +
+*open <data_device> <name> <hash_device> --root-hash-file <path>* +
+create <name> <data_device> <hash_device> <root_hash> (*OBSOLETE syntax*)
+
+Creates a mapping with <name> backed by device <data_device> and using
+<hash_device> for in-kernel verification.
+
+The <root_hash> is a hexadecimal string.
+
+*<options>* can be [--hash-offset, --no-superblock, --ignore-corruption
+or --restart-on-corruption, --panic-on-corruption, --ignore-zero-blocks,
+--check-at-most-once, --root-hash-signature, --root-hash-file, --use-tasklets].
+
+If option --root-hash-file is used, the root hash is read from <path>
+instead of from the command line parameter. Expects hex-encoded text,
+without terminating newline.
+
+If option --no-superblock is used, you have to use as the same options
+as in initial format operation.
+
+=== VERIFY
+*verify <data_device> <hash_device> <root_hash>* +
+*verify <data_device> <hash_device> --root-hash-file <path>*
+
+Verifies data on data_device with use of hash blocks stored on
+hash_device.
+
+This command performs userspace verification, no kernel device is
+created.
+
+The <root_hash> is a hexadecimal string.
+
+If option --root-hash-file is used, the root hash is read from <path>
+instead of from the command line parameter. Expects hex-encoded text,
+without terminating newline.
+
+*<options>* can be [--hash-offset, --no-superblock, --root-hash-file].
+
+If option --no-superblock is used, you have to use as the same options
+as in initial format operation.
+
+=== CLOSE
+*close <name>* +
+remove <name> (*OBSOLETE syntax*)
+
+Removes existing mapping <name>.
+
+*<options>* can be [--deferred] or [--cancel-deferred].
+
+=== STATUS
+*status <name>*
+
+Reports status for the active verity mapping <name>.
+
+=== DUMP
+*dump <hash_device>*
+
+Reports parameters of verity device from on-disk stored superblock.
+
+*<options>* can be [--hash-offset].
+
+== OPTIONS
+
+*--no-superblock*::
+Create or use dm-verity without permanent on-disk superblock.
+
+*--format=number*::
+Specifies the hash version type. Format type 0 is original Chrome OS
+version. Format type 1 is current version.
+
+*--data-block-size=bytes*::
+Used block size for the data device. (Note kernel supports only
+page-size as maximum here.)
+
+*--hash-block-size=bytes*::
+Used block size for the hash device. (Note kernel supports only
+page-size as maximum here.)
+
+*--data-blocks=blocks*::
+Size of data device used in verification. If not specified, the whole
+device is used.
+
+*--hash-offset=bytes*::
+Offset of hash area/superblock on hash_device. Value must be aligned
+to disk sector offset.
+
+*--salt=hex string*::
+Salt used for format or verification. Format is a hexadecimal string.
+
+*--uuid=UUID*::
+Use the provided UUID for format command instead of generating new
+one.
++
+The UUID must be provided in standard UUID format, e.g.
+12345678-1234-1234-1234-123456789abc.
+*--ignore-corruption , --restart-on-corruption ,
+--panic-on-corruption*::
+Defines what to do if data integrity problem is detected (data
+corruption).
++
+Without these options kernel fails the IO operation with I/O error. With
+--ignore-corruption option the corruption is only logged. With
+--restart-on-corruption or --panic-on-corruption the kernel is restarted
+(panicked) immediately. (You have to provide way how to avoid restart
+loops.)
++
+*WARNING:* Use these options only for very specific cases. These options
+are available since Linux kernel version 4.1.
+
+*--ignore-zero-blocks*::
+Instruct kernel to not verify blocks that are expected to contain
+zeroes and always directly return zeroes instead.
++
+*WARNING:* Use this option only in very specific cases. This option is
+available since Linux kernel version 4.5.
+
+*--check-at-most-once*::
+Instruct kernel to verify blocks only the first time they are read
+from the data device, rather than every time.
++
+*WARNING:* It provides a reduced level of security because only offline
+tampering of the data device's content will be detected, not online
+tampering. This option is available since Linux kernel version 4.17.
+
+*--hash=hash*::
+Hash algorithm for dm-verity. For default see --help option.
+
+*--fec-device=fec_device*::
+Use forward error correction (FEC) to recover from corruption if hash
+verification fails. Use encoding data from the specified device.
++
+The fec device argument can be block device or file image. For format,
+if fec device path doesn't exist, it will be created as file.
++
+Block sizes for data and hash devices must match. Also, if the verity
+data_device is encrypted the fec_device should be too.
++
+FEC calculation covers data, hash area, and optional foreign metadata
+stored on the same device with the hash tree (additional space after
+hash area). Size of this optional additional area protected by FEC is
+calculated from image sizes, so you must be sure that you use the same
+images for activation.
++
+If the hash device is in a separate image, metadata covers the whole
+rest of the image after the hash area.
++
+If hash and FEC device is in the image, metadata ends on the FEC area
+offset.
+
+*--fec-offset=bytes*::
+This is the offset, in bytes, from the start of the FEC device to the
+beginning of the encoding data.
+
+*--fec-roots=num*::
+Number of generator roots. This equals to the number of parity bytes
+in the encoding data. In RS(M, N) encoding, the number of roots is
+M-N. M is 255 and M-N is between 2 and 24 (including).
+
+*--root-hash-file=FILE*::
+Path to file with stored root hash in hex-encoded text.
+
+*--root-hash-signature=FILE*::
+Path to root hash signature file used to verify the root hash (in
+kernel). This feature requires Linux kernel version 5.4 or more
+recent.
+
+*--use-tasklets*::
+Try to use kernel tasklets in dm-verity driver for performance reasons.
+This option is available since Linux kernel version 6.0.
+
+*--deferred*::
+Defers device removal in *close* command until the last user closes
+it.
+
+*--cancel-deferred*::
+Removes a previously configured deferred device removal in *close*
+command.
+
+*--verbose, -v*::
+Print more information on command execution.
+
+*--debug*::
+Run in debug mode with full diagnostic logs. Debug output lines are
+always prefixed by *#*.
+
+*--version, -V*::
+Show the program version.
+
+*--batch-mode, -q*::
+Do not ask for confirmation.
+
+*--usage*::
+Show short option help.
+
+*--help, -?*::
+Show help text and default parameters.
+
+== RETURN CODES
+
+Veritysetup returns *0* on success and a non-zero value on error.
+
+Error codes are: *1* wrong parameters, *2* no permission, *3* out of memory,
+*4* wrong device specified, *5* device already exists or device is busy.
+
+== EXAMPLES
+
+*veritysetup --data-blocks=256 format <data_device> <hash_device>*
+
+Calculates and stores verification data on hash_device for the first 256
+blocks (of block-size). If hash_device does not exist, it is created (as
+file image).
+
+*veritysetup format --root-hash-file <path> <data_device> <hash_device>*
+
+Calculates and stores verification data on hash_device for the whole
+data_device, and store the root hash as hex-encoded text in <path>.
+
+*veritysetup --data-blocks=256 --hash-offset=1052672 format <device>
+<device>*
+
+Verification data (hashes) is stored on the same device as data
+(starting at hash-offset). Hash-offset must be greater than number of
+blocks in data-area.
+
+*veritysetup --data-blocks=256 --hash-offset=1052672 create test-device
+<device> <device> <root_hash>*
+
+Activates the verity device named test-device. Options --data-blocks and
+--hash-offset are the same as in the format command. The <root_hash> was
+calculated in format command.
+
+*veritysetup --data-blocks=256 --hash-offset=1052672 verify
+<data_device> <hash_device> <root_hash>*
+
+Verifies device without activation (in userspace).
+
+*veritysetup --data-blocks=256 --hash-offset=1052672 --root-hash-file
+<path> verify <data_device> <hash_device>*
+
+Verifies device without activation (in userspace). Root hash passed via
+a file rather than inline.
+
+*veritysetup --fec-device=<fec_device> --fec-roots=10 format
+<data_device> <hash_device>*
+
+Calculates and stores verification and encoding data for data_device.
+
+== DM-VERITY ON-DISK SPECIFICATION
+
+The on-disk format specification is available at
+https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity[*DMVerity*] page.
+
+== AUTHORS
+
+The first implementation of veritysetup was written by Chrome OS
+authors.
+
+This version is based on verification code written by
+mailto:mpatocka@redhat.com[Mikulas Patocka] and rewritten for libcryptsetup
+by mailto:gmazyland@gmail.com[Milan Broz].
+
+include::man/common_footer.adoc[]
diff --git a/misc/11-dm-crypt.rules b/misc/11-dm-crypt.rules
new file mode 100644
index 0000000..dfbb3a0
--- /dev/null
+++ b/misc/11-dm-crypt.rules
@@ -0,0 +1,17 @@
+# Old udev rules historically used in device-mapper.
+# No need to install these until you have some weird configuration.
+# (Code internally set the same flags.)
+
+ACTION!="add|change", GOTO="crypt_end"
+ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="crypt_end"
+
+ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="crypt_disable"
+ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="crypt_disable"
+GOTO="crypt_end"
+
+LABEL="crypt_disable"
+ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
+ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
+
+LABEL="crypt_end"
diff --git a/misc/dict_search/Makefile b/misc/dict_search/Makefile
new file mode 100644
index 0000000..0226c98
--- /dev/null
+++ b/misc/dict_search/Makefile
@@ -0,0 +1,17 @@
+TARGET=crypt_dict
+CFLAGS=-O2 -g -Wall -D_GNU_SOURCE
+LDLIBS=-lcryptsetup
+CC=gcc
+
+SOURCES=$(wildcard *.c)
+OBJECTS=$(SOURCES:.c=.o)
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+ $(CC) -o $@ $^ $(LDLIBS)
+
+clean:
+ rm -f *.o *~ core $(TARGET)
+
+.PHONY: clean
diff --git a/misc/dict_search/README b/misc/dict_search/README
new file mode 100644
index 0000000..fc6aa44
--- /dev/null
+++ b/misc/dict_search/README
@@ -0,0 +1,22 @@
+Simple example how to use libcryptsetup
+for password search.
+
+Run: crypt_dict luks|tcrypt <device|image> <dictionary> [cpus]
+
+luks|tcrypt specified device type (LUKS or TrueCrypt)
+
+<device|image> is LUKS or TrueCrypt device or image
+
+<dictionary> is list of passphrases to try
+(note trailing EOL is stripped)
+
+cpus - number of processes to start in parallel
+
+Format of dictionary file is simple one password per line,
+if first char on line is # it is skipped as comment.
+
+For LUKS, you have it run as root (device-mapper cannot
+create dmcrypt devices as nrmal user. Code need
+to map keyslots as temporary dmcrypt device.)
+
+For TrueCrypt devices root privilege is not required.
diff --git a/misc/dict_search/crypt_dict.c b/misc/dict_search/crypt_dict.c
new file mode 100644
index 0000000..c80d502
--- /dev/null
+++ b/misc/dict_search/crypt_dict.c
@@ -0,0 +1,158 @@
+/*
+ * Example of LUKS/TrueCrypt password dictionary search
+ *
+ * Copyright (C) 2012 Milan Broz <gmazyland@gmail.com>
+ *
+ * Run this (for LUKS as root),
+ * e.g. ./crypt_dict test.img /usr/share/john/password.lst 4
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <libcryptsetup.h>
+
+#define MAX_LEN 512
+
+static enum { LUKS, TCRYPT } device_type;
+
+static void check(struct crypt_device *cd, const char *pwd_file, unsigned my_id, unsigned max_id)
+{
+ FILE *f;
+ int len, r = -1;
+ unsigned long line = 0;
+ char pwd[MAX_LEN];
+
+ if (fork())
+ return;
+
+ /* open password file, now in separate process */
+ f = fopen(pwd_file, "r");
+ if (!f) {
+ printf("Cannot open %s.\n", pwd_file);
+ exit(EXIT_FAILURE);
+ }
+
+ while (fgets(pwd, MAX_LEN, f)) {
+
+ /* every process tries N-th line, skip others */
+ if (line++ % max_id != my_id)
+ continue;
+
+ len = strlen(pwd);
+
+ /* strip EOL - this is like a input from tty */
+ if (len && pwd[len - 1] == '\n') {
+ pwd[len - 1] = '\0';
+ len--;
+ }
+
+ /* lines starting "#!comment" are comments */
+ if (len >= 9 && !strncmp(pwd, "#!comment", 9)) {
+ /* printf("skipping %s\n", pwd); */
+ continue;
+ }
+
+ /* printf("%d: checking %s\n", my_id, pwd); */
+ if (device_type == LUKS)
+ r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, pwd, len, 0);
+ else if (device_type == TCRYPT) {
+ struct crypt_params_tcrypt params = {
+ .flags = CRYPT_TCRYPT_LEGACY_MODES,
+ .passphrase = pwd,
+ .passphrase_size = len,
+ };
+ r = crypt_load(cd, CRYPT_TCRYPT, &params);
+ }
+ if (r >= 0) {
+ printf("Found passphrase for slot %d: \"%s\"\n", r, pwd);
+ break;
+ }
+ }
+
+ fclose(f);
+ crypt_free(cd);
+ exit(r >= 0 ? 2 : EXIT_SUCCESS);
+}
+
+int main(int argc, char *argv[])
+{
+ int i, status, procs = 4;
+ struct crypt_device *cd;
+
+ if (argc < 4 || argc > 5) {
+ printf("Use: %s luks|tcrypt <device|file> <password file> [#processes] %d\n", argv[0], argc);
+ exit(EXIT_FAILURE);
+ }
+
+ if (argc == 5 && (sscanf(argv[4], "%i", &procs) != 1 || procs < 1)) {
+ printf("Wrong number of processes.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!strcmp(argv[1], "luks"))
+ device_type = LUKS;
+ else if (!strcmp(argv[1], "tcrypt"))
+ device_type = TCRYPT;
+ else {
+ printf("Wrong device type %s.\n", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* crypt_set_debug_level(CRYPT_DEBUG_ALL); */
+
+ /*
+ * Need to create temporary keyslot device-mapper devices and allocate loop if needed,
+ * so root is required here.
+ */
+ if (getuid() != 0) {
+ printf("You must be root to run this program.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* signal all children if anything happens */
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+ setpriority(PRIO_PROCESS, 0, -5);
+
+ /* we are not going to modify anything, so common init is ok */
+ if (crypt_init(&cd, argv[2]) ||
+ (device_type == LUKS && crypt_load(cd, CRYPT_LUKS1, NULL))) {
+ printf("Cannot open %s.\n", argv[2]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* run scan in separate processes, it is up to scheduler to assign CPUs inteligently */
+ for (i = 0; i < procs; i++)
+ check(cd, argv[3], i, procs);
+
+ /* wait until at least one finishes with error or status 2 (key found) */
+ while (wait(&status) != -1 && WIFEXITED(status)) {
+ if (WEXITSTATUS(status) == EXIT_SUCCESS)
+ continue;
+ /* kill rest of processes */
+ kill(0, SIGHUP);
+ /* not reached */
+ break;
+ }
+ exit(0);
+}
diff --git a/misc/fedora/cryptsetup.spec b/misc/fedora/cryptsetup.spec
new file mode 100644
index 0000000..d635d45
--- /dev/null
+++ b/misc/fedora/cryptsetup.spec
@@ -0,0 +1,121 @@
+# Simplified version of RPM spec for Fedora
+
+Summary: Utility for setting up encrypted disks
+Name: cryptsetup
+Version: 2.5.0
+Release: 1%{?dist}
+License: GPLv2+ and LGPLv2+
+URL: https://gitlab.com/cryptsetup/cryptsetup
+BuildRequires: autoconf, automake, libtool, gettext-devel,
+BuildRequires: openssl-devel, popt-devel, device-mapper-devel
+BuildRequires: libuuid-devel, gcc, json-c-devel, libargon2-devel
+BuildRequires: libpwquality-devel, libblkid-devel
+BuildRequires: make libssh-devel
+BuildRequires: asciidoctor
+Requires: cryptsetup-libs = %{version}-%{release}
+Requires: libpwquality >= 1.2.0
+Obsoletes: %{name}-reencrypt <= %{version}
+Provides: %{name}-reencrypt = %{version}
+
+%global upstream_version %{version_no_tilde}
+Source0: https://www.kernel.org/pub/linux/utils/cryptsetup/v2.5/cryptsetup-%{upstream_version}.tar.xz
+
+%description
+The cryptsetup package contains a utility for setting up
+disk encryption using dm-crypt kernel module.
+
+%package devel
+Requires: %{name}-libs%{?_isa} = %{version}-%{release}
+Requires: pkgconfig
+Summary: Headers and libraries for using encrypted file systems
+
+%description devel
+The cryptsetup-devel package contains libraries and header files
+used for writing code that makes use of disk encryption.
+
+%package libs
+Summary: Cryptsetup shared library
+
+%description libs
+This package contains the cryptsetup shared library, libcryptsetup.
+
+%package ssh-token
+Summary: Cryptsetup LUKS2 SSH token
+Requires: cryptsetup-libs = %{version}-%{release}
+
+%description ssh-token
+This package contains the LUKS2 SSH token.
+
+%package -n veritysetup
+Summary: A utility for setting up dm-verity volumes
+Requires: cryptsetup-libs = %{version}-%{release}
+
+%description -n veritysetup
+The veritysetup package contains a utility for setting up
+disk verification using dm-verity kernel module.
+
+%package -n integritysetup
+Summary: A utility for setting up dm-integrity volumes
+Requires: cryptsetup-libs = %{version}-%{release}
+
+%description -n integritysetup
+The integritysetup package contains a utility for setting up
+disk integrity protection using dm-integrity kernel module.
+
+%prep
+%autosetup -n cryptsetup-%{upstream_version} -p 1
+
+%build
+# force regeneration of manual pages from AsciiDoc
+rm -f man/*.8
+
+./autogen.sh
+%configure --enable-fips --enable-pwquality --enable-libargon2 --enable-asciidoc
+%make_build
+
+%install
+%make_install
+rm -rf %{buildroot}%{_libdir}/*.la
+rm -rf %{buildroot}%{_libdir}/%{name}/*.la
+
+%find_lang cryptsetup
+
+%ldconfig_scriptlets -n cryptsetup-libs
+
+%files
+%license COPYING
+%doc AUTHORS FAQ.md docs/*ReleaseNotes
+%{_mandir}/man8/cryptsetup.8.gz
+%{_mandir}/man8/cryptsetup-*.8.gz
+%{_sbindir}/cryptsetup
+
+%files -n veritysetup
+%license COPYING
+%{_mandir}/man8/veritysetup.8.gz
+%{_sbindir}/veritysetup
+
+%files -n integritysetup
+%license COPYING
+%{_mandir}/man8/integritysetup.8.gz
+%{_sbindir}/integritysetup
+
+%files devel
+%doc docs/examples/*
+%{_includedir}/libcryptsetup.h
+%{_libdir}/libcryptsetup.so
+%{_libdir}/pkgconfig/libcryptsetup.pc
+
+%files libs -f cryptsetup.lang
+%license COPYING COPYING.LGPL
+%{_libdir}/libcryptsetup.so.*
+%dir %{_libdir}/%{name}/
+%{_tmpfilesdir}/cryptsetup.conf
+%ghost %attr(700, -, -) %dir /run/cryptsetup
+
+%files ssh-token
+%license COPYING COPYING.LGPL
+%{_libdir}/%{name}/libcryptsetup-token-ssh.so
+%{_mandir}/man8/cryptsetup-ssh.8.gz
+%{_sbindir}/cryptsetup-ssh
+
+%changelog
diff --git a/misc/keyslot_checker/Makefile b/misc/keyslot_checker/Makefile
new file mode 100644
index 0000000..3b159fd
--- /dev/null
+++ b/misc/keyslot_checker/Makefile
@@ -0,0 +1,14 @@
+TARGETS=chk_luks_keyslots
+CFLAGS=-O0 -g -Wall -D_GNU_SOURCE
+LDLIBS=-lcryptsetup -lm
+CC=gcc
+
+all: $(TARGETS)
+
+chk_luks_keyslots: chk_luks_keyslots.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+clean:
+ rm -f *.o *~ core $(TARGETS)
+
+.PHONY: clean
diff --git a/misc/keyslot_checker/README b/misc/keyslot_checker/README
new file mode 100644
index 0000000..cd5bf81
--- /dev/null
+++ b/misc/keyslot_checker/README
@@ -0,0 +1,120 @@
+Purpose
+=======
+
+chk_luks_keyslots is a tool that searches the keyslot area of a
+LUKS container for positions where entropy is low and hence
+there is a high probability of damage from overwrites of parts
+of the key-slot with data such as a RAID superblock or a partition
+table.
+
+
+Installation
+============
+
+1. Install the version of cryptsetup the tool came with.
+2. Compile with "make"
+
+Manual compile can be done with
+ gcc -lm -lcryptsetup chk_luks_keyslots.c -o chk_luks_keyslots
+
+Usage
+=====
+
+Call chk_luks_keyslots without arguments for an option summary.
+
+
+Example of a good keyslot area with keys 0 and 2 in use:
+--------------------------------------------------------
+
+root> ./chk_luks_keyslots /dev/loop0
+
+parameters (commandline and LUKS header):
+ sector size: 512
+ threshold: 0.900000
+
+- processing keyslot 0: start: 0x001000 end: 0x020400
+- processing keyslot 1: keyslot not in use
+- processing keyslot 2: start: 0x041000 end: 0x060400
+- processing keyslot 3: keyslot not in use
+- processing keyslot 4: keyslot not in use
+- processing keyslot 5: keyslot not in use
+- processing keyslot 6: keyslot not in use
+- processing keyslot 7: keyslot not in use
+
+
+Same example of a fault in slot 2 at offset 0x50000:
+----------------------------------------------------
+
+root>./chk_luks_keyslots /dev/loop2
+
+parameters (commandline and LUKS header):
+ sector size: 512
+ threshold: 0.900000
+
+- processing keyslot 0: start: 0x001000 end: 0x020400
+- processing keyslot 1: keyslot not in use
+- processing keyslot 2: start: 0x041000 end: 0x060400
+ low entropy at: 0x050000 entropy: 0.549165
+- processing keyslot 3: keyslot not in use
+- processing keyslot 4: keyslot not in use
+- processing keyslot 5: keyslot not in use
+- processing keyslot 6: keyslot not in use
+- processing keyslot 7: keyslot not in use
+
+
+Same as last, but verbose:
+--------------------------
+root>./chk_luks_keyslots -v /dev/loop2
+
+parameters (commandline and LUKS header):
+ sector size: 512
+ threshold: 0.900000
+
+- processing keyslot 0: start: 0x001000 end: 0x020400
+- processing keyslot 1: keyslot not in use
+- processing keyslot 2: start: 0x041000 end: 0x060400
+ low entropy at: 0x050000 entropy: 0.549165
+ Binary dump:
+ 0x050000 54 68 69 73 20 69 73 20 61 20 74 65 73 74 2D 73 This is a test-s
+ 0x050010 65 63 74 6F 72 20 66 6F 72 20 63 68 6B 5F 6C 75 ector for chk_lu
+ 0x050020 6B 73 5F 6B 65 79 73 6C 6F 74 73 20 74 68 65 20 ks_keyslots the
+ 0x050030 71 75 69 63 6B 20 62 72 6F 77 6E 20 66 6F 78 20 quick brown fox
+ 0x050040 6A 75 6D 70 73 20 6F 76 65 72 20 74 68 65 20 6C jumps over the l
+ 0x050050 61 7A 79 20 64 6F 67 20 74 68 65 20 71 75 69 63 azy dog the quic
+ 0x050060 6B 20 62 72 6F 77 6E 20 66 6F 78 20 6A 75 6D 70 k brown fox jump
+ 0x050070 73 20 6F 76 65 72 20 74 68 65 20 6C 61 7A 79 20 s over the lazy
+ 0x050080 64 6F 67 20 74 68 65 20 71 75 69 63 6B 20 62 72 dog the quick br
+ 0x050090 6F 77 6E 20 66 6F 78 20 6A 75 6D 70 73 20 6F 76 own fox jumps ov
+ 0x0500a0 65 72 20 74 68 65 20 6C 61 7A 79 20 64 6F 67 20 er the lazy dog
+ 0x0500b0 74 68 65 20 71 75 69 63 6B 20 62 72 6F 77 6E 20 the quick brown
+ 0x0500c0 66 6F 78 20 6A 75 6D 70 73 20 6F 76 65 72 20 74 fox jumps over t
+ 0x0500d0 68 65 20 6C 61 7A 79 20 64 6F 67 20 74 68 65 20 he lazy dog the
+ 0x0500e0 71 75 69 63 6B 20 62 72 6F 77 6E 20 66 6F 78 20 quick brown fox
+ 0x0500f0 6A 75 6D 70 73 20 6F 76 65 72 20 74 68 65 20 6C jumps over the l
+ 0x050100 61 7A 79 20 64 6F 67 20 74 68 65 20 71 75 69 63 azy dog the quic
+ 0x050110 6B 20 62 72 6F 77 6E 20 66 6F 78 20 6A 75 6D 70 k brown fox jump
+ 0x050120 73 20 6F 76 65 72 20 74 68 65 20 6C 61 7A 79 20 s over the lazy
+ 0x050130 64 6F 67 20 74 68 65 20 71 75 69 63 6B 20 62 72 dog the quick br
+ 0x050140 6F 77 6E 20 66 6F 78 20 6A 75 6D 70 73 20 6F 76 own fox jumps ov
+ 0x050150 65 72 20 74 68 65 20 6C 61 7A 79 20 64 6F 67 20 er the lazy dog
+ 0x050160 74 68 65 20 71 75 69 63 6B 20 62 72 6F 77 6E 20 the quick brown
+ 0x050170 66 6F 78 20 6A 75 6D 70 73 20 6F 76 65 72 20 74 fox jumps over t
+ 0x050180 68 65 20 6C 61 7A 79 20 64 6F 67 20 74 68 65 20 he lazy dog the
+ 0x050190 71 75 69 63 6B 20 62 72 6F 77 6E 20 66 6F 78 20 quick brown fox
+ 0x0501a0 6A 75 6D 70 73 20 6F 76 65 72 20 74 68 65 20 6C jumps over the l
+ 0x0501b0 61 7A 79 20 64 6F 67 20 74 68 65 20 71 75 69 63 azy dog the quic
+ 0x0501c0 6B 20 62 72 6F 77 6E 20 66 6F 78 20 6A 75 6D 70 k brown fox jump
+ 0x0501d0 73 20 6F 76 65 72 20 74 68 65 20 6C 61 7A 79 20 s over the lazy
+ 0x0501e0 64 6F 67 20 74 68 65 20 71 75 69 63 6B 20 62 72 dog the quick br
+ 0x0501f0 6F 77 6E 20 66 6F 78 20 6A 75 6D 70 73 20 6F 76 own fox jumps ov
+
+- processing keyslot 3: keyslot not in use
+- processing keyslot 4: keyslot not in use
+- processing keyslot 5: keyslot not in use
+- processing keyslot 6: keyslot not in use
+- processing keyslot 7: keyslot not in use
+
+----
+Copyright (C) 2012, Arno Wagner <arno@wagner.name>
+This file is free documentation; the author gives
+unlimited permission to copy, distribute and modify it.
diff --git a/misc/keyslot_checker/chk_luks_keyslots.c b/misc/keyslot_checker/chk_luks_keyslots.c
new file mode 100644
index 0000000..308b002
--- /dev/null
+++ b/misc/keyslot_checker/chk_luks_keyslots.c
@@ -0,0 +1,371 @@
+/*
+ * LUKS keyslot entropy tester. Works only for header version 1.
+ *
+ * Functionality: Determines sample entropy (symbols: bytes) for
+ * each (by default) 512B sector in each used keyslot. If it
+ * is lower than a threshold, the sector address is printed
+ * as it is suspected of having non-"random" data in it, indicating
+ * damage by overwriting. This can obviously not find overwriting
+ * with random or random-like data (encrypted, compressed).
+ *
+ * Version history:
+ * v0.1: 09.09.2012 Initial release
+ * v0.2: 08.10.2012 Converted to use libcryptsetup
+ *
+ * Copyright (C) 2012, Arno Wagner <arno@wagner.name>
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <math.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libcryptsetup.h>
+
+const char *help =
+"Version 0.2 [8.10.2012]\n"
+"\n"
+" chk_luks_keyslots [options] luks-device \n"
+"\n"
+"This tool checks all keyslots of a LUKS device for \n"
+"low entropy sections. If any are found, they are reported. \n"
+"This allows one to find areas damaged by things like filesystem \n"
+"creation or RAID superblocks. \n"
+"\n"
+"Options: \n"
+" -t <num> Entropy threshold. Possible values 0.0 ... 1.0 \n"
+" Default: 0.90, which works well for 512B sectors.\n"
+" For 512B sectors, you will get frequent misdetections\n"
+" at thresholds around 0.94\n"
+" Higher value: more sensitive but more false detections.\n"
+" -s <num> Sector size. Must divide keyslot-size.\n"
+" Default: 512 Bytes.\n"
+" Values smaller than 128 are generally not very useful.\n"
+" For values smaller than the default, you need to adjust\n"
+" the threshold down to reduce misdetection. For values\n"
+" larger than the default you need to adjust the threshold\n"
+" up to retain sensitivity.\n"
+" -v Print found suspicious sectors verbosely. \n"
+" -d Print decimal addresses instead of hex ones.\n"
+"\n";
+
+
+/* Config defaults */
+
+static int sector_size = 512;
+static double threshold = 0.90;
+static int print_decimal = 0;
+static int verbose = 0;
+
+/* tools */
+
+/* Calculates and returns sample entropy on byte level for
+ * The argument.
+ */
+static double ent_samp(unsigned char * buf, int len)
+{
+ int freq[256]; /* stores symbol frequencies */
+ int i;
+ double e, f;
+
+ /* 0. Plausibility checks */
+ if (len <= 0)
+ return 0.0;
+
+ /* 1. count all frequencies */
+ for (i = 0; i < 256; i++) {
+ freq[i] = 0.0;
+ }
+
+ for (i = 0; i < len; i ++)
+ freq[buf[i]]++;
+
+ /* 2. calculate sample entropy */
+ e = 0.0;
+ for (i = 0; i < 256; i++) {
+ f = freq[i];
+ if (f > 0) {
+ f = f / (double)len;
+ e += f * log2(f);
+ }
+ }
+
+ if (e != 0.0)
+ e = -1.0 * e;
+
+ e = e / 8.0;
+ return e;
+}
+
+static void print_address(FILE *out, uint64_t value)
+{
+ if (print_decimal) {
+ fprintf(out,"%08" PRIu64 " ", value);
+ } else {
+ fprintf(out,"%#08" PRIx64 " ", value);
+ }
+}
+
+/* uses default "hd" style, i.e. 16 bytes followed by ASCII */
+static void hexdump_line(FILE *out, uint64_t address, unsigned char *buf) {
+ int i;
+ static char tbl[16] = "0123456789ABCDEF";
+
+ fprintf(out," ");
+ print_address(out, address);
+ fprintf(out," ");
+
+ /* hex */
+ for (i = 0; i < 16; i++) {
+ fprintf(out, "%c%c",
+ tbl[(unsigned char)buf[i]>> 4],
+ tbl[(unsigned char)buf[i] & 0x0f]);
+ fprintf(out," ");
+ if (i == 7)
+ fprintf(out," ");
+ }
+
+ fprintf(out," ");
+
+ /* ascii */
+ for (i = 0; i < 16; i++) {
+ if (isprint(buf[i])) {
+ fprintf(out, "%c", buf[i]);
+ } else {
+ fprintf(out, ".");
+ }
+ }
+ fprintf(out, "\n");
+}
+
+static void hexdump_sector(FILE *out, unsigned char *buf, uint64_t address, int len)
+{
+ int done;
+
+ done = 0;
+ while (len - done >= 16) {
+ hexdump_line(out, address + done, buf + done);
+ done += 16;
+ }
+}
+
+static int check_keyslots(FILE *out, struct crypt_device *cd, int f_luks)
+{
+ int i;
+ double ent;
+ off_t ofs;
+ uint64_t start, length, end;
+ crypt_keyslot_info ki;
+ unsigned char buffer[sector_size];
+
+ for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1) ; i++) {
+ fprintf(out, "- processing keyslot %d:", i);
+ ki = crypt_keyslot_status(cd, i);
+ if (ki == CRYPT_SLOT_INACTIVE) {
+ fprintf(out, " keyslot not in use\n");
+ continue;
+ }
+
+ if (ki == CRYPT_SLOT_INVALID) {
+ fprintf(out, "\nError: keyslot invalid.\n");
+ return EXIT_FAILURE;
+ }
+
+ if (crypt_keyslot_area(cd, i, &start, &length) < 0) {
+ fprintf(stderr,"\nError: querying keyslot area failed for slot %d\n", i);
+ perror(NULL);
+ return EXIT_FAILURE;
+ }
+ end = start + length;
+
+ fprintf(out, " start: ");
+ print_address(out, start);
+ fprintf(out, " end: ");
+ print_address(out, end);
+ fprintf(out, "\n");
+
+ /* check whether sector-size divides size */
+ if (length % sector_size != 0) {
+ fprintf(stderr,"\nError: Argument to -s does not divide keyslot size\n");
+ return EXIT_FAILURE;
+ }
+
+ for (ofs = start; (uint64_t)ofs < end; ofs += sector_size) {
+ if (lseek(f_luks, ofs, SEEK_SET) != ofs) {
+ fprintf(stderr,"\nCannot seek to keyslot area.\n");
+ return EXIT_FAILURE;
+ }
+ if (read(f_luks, buffer, sector_size) != sector_size) {
+ fprintf(stderr,"\nCannot read keyslot area.\n");
+ return EXIT_FAILURE;
+ }
+ ent = ent_samp(buffer, sector_size);
+ if (ent < threshold) {
+ fprintf(out, " low entropy at: ");
+ print_address(out, ofs);
+ fprintf(out, " entropy: %f\n", ent);
+ if (verbose) {
+ fprintf(out, " Binary dump:\n");
+ hexdump_sector(out, buffer, (uint64_t)ofs, sector_size);
+ fprintf(out,"\n");
+ }
+ }
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+/* Main */
+int main(int argc, char **argv)
+{
+ /* for option processing */
+ int c, r;
+ char *device;
+
+ /* for use of libcryptsetup */
+ struct crypt_device *cd;
+
+ /* Other vars */
+ int f_luks; /* device file for the luks device */
+ FILE *out;
+
+ /* temporary helper vars */
+ int res;
+
+ /* getopt values */
+ char *s, *end;
+ double tvalue;
+ int svalue;
+
+ /* global initializations */
+ out = stdout;
+
+ /* get commandline parameters */
+ while ((c = getopt (argc, argv, "t:s:vd")) != -1) {
+ switch (c) {
+ case 't':
+ s = optarg;
+ tvalue = strtod(s, &end);
+ if (s == end) {
+ fprintf(stderr, "\nError: Parsing of argument to -t failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (tvalue < 0.0 || tvalue > 1.0) {
+ fprintf(stderr,"\nError: Argument to -t must be in 0.0 ... 1.0\n");
+ exit(EXIT_FAILURE);
+ }
+ threshold = tvalue;
+ break;
+ case 's':
+ s = optarg;
+ svalue = strtol(s, &end, 10);
+ if (s == end) {
+ fprintf(stderr, "\nError: Parsing of argument to -s failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (svalue < 1) {
+ fprintf(stderr,"\nError: Argument to -s must be >= 1 \n");
+ exit(EXIT_FAILURE);
+ }
+ sector_size = svalue;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'd':
+ print_decimal = 1;
+ break;
+ case '?':
+ if (optopt == 't' || optopt == 's')
+ fprintf (stderr,"\nError: Option -%c requires an argument.\n",
+ optopt);
+ else if (isprint (optopt)) {
+ fprintf(stderr,"\nError: Unknown option `-%c'.\n", optopt);
+ fprintf(stderr,"\n\n%s", help);
+ } else {
+ fprintf (stderr, "\nError: Unknown option character `\\x%x'.\n",
+ optopt);
+ fprintf(stderr,"\n\n%s", help);
+ }
+ exit(EXIT_SUCCESS);
+ default:
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* parse non-option stuff. Should be exactly one, the device. */
+ if (optind+1 != argc) {
+ fprintf(stderr,"\nError: exactly one non-option argument expected!\n");
+ fprintf(stderr,"\n\n%s", help);
+ exit(EXIT_FAILURE);
+ }
+ device = argv[optind];
+
+ /* test whether we can open and read device */
+ /* This is needed as we are reading the actual data
+ * in the keyslots directly from the LUKS container.
+ */
+ f_luks = open(device, O_RDONLY);
+ if (f_luks == -1) {
+ fprintf(stderr,"\nError: Opening of device %s failed:\n", device);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+
+ /* now get the parameters we need via libcryptsetup */
+ /* Basically we need all active keyslots and their placement on disk */
+
+ /* first init. This does the following:
+ * - gets us a crypt_device struct with some values filled in
+ * Note: This does some init stuff we do not need, but that
+ * should not cause trouble.
+ */
+
+ res = crypt_init(&cd, device);
+ if (res < 0) {
+ fprintf(stderr, "crypt_init() failed. Maybe not running as root?\n");
+ close(f_luks);
+ exit(EXIT_FAILURE);
+ }
+
+ /* now load LUKS header into the crypt_device
+ * This should also make sure a valid LUKS1 header is on disk
+ * and hence we should be able to skip magic and version checks.
+ */
+ res = crypt_load(cd, CRYPT_LUKS1, NULL);
+ if (res < 0) {
+ fprintf(stderr, "crypt_load() failed. LUKS header too broken/absent?\n");
+ crypt_free(cd);
+ close(f_luks);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(out, "\nparameters (commandline and LUKS header):\n");
+ fprintf(out, " sector size: %d\n", sector_size);
+ fprintf(out, " threshold: %0f\n\n", threshold);
+
+ r = check_keyslots(out, cd, f_luks);
+
+ crypt_free(cd);
+ close(f_luks);
+ return r;
+}
diff --git a/misc/luks-header-from-active b/misc/luks-header-from-active
new file mode 100755
index 0000000..a94ad33
--- /dev/null
+++ b/misc/luks-header-from-active
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+# Try to get LUKS info and master key from active mapping and prepare parameters for cryptsetup.
+#
+# Copyright (C) 2010,2011,2012 Milan Broz <gmazyland@gmail.com>
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+umask 0077
+
+fail() { echo -e $1 ; exit 1 ; }
+field() { echo $(dmsetup table --target crypt --showkeys $DEVICE | sed 's/.*: //' | cut -d' ' -f$1) ; }
+field_uuid() { echo $(dmsetup info $1 --noheadings -c -o uuid) ; }
+field_device() {
+ TEMP=$(readlink /sys/dev/block/$1 | sed -e 's/.*\///')
+ if [ ${TEMP:0:3} = "dm-" -a -e /sys/block/$TEMP/dm/name ] ; then
+ TEMP=/dev/mapper/$(cat /sys/block/$TEMP/dm/name)
+ else
+ TEMP=/dev/$TEMP
+ fi
+ echo $TEMP
+}
+
+which readlink >/dev/null || fail "You need readlink (part of coreutils package)."
+which xxd >/dev/null || fail "You need xxd (part of vim package) installed to convert key."
+
+[ -z "$2" ] && fail "Recover LUKS header from active mapping, use:\n $0 crypt_mapped_device mk_file_name"
+
+DEVICE=$1
+MK_FILE=$2
+
+[ -z "$(field 4)" ] && fail "Mapping $1 not active or it is not crypt target."
+
+CIPHER=$(field 4)
+OFFSET=$(field 8)
+SYS_DEVICE=$(field 7)
+REAL_DEVICE=$(field_device $SYS_DEVICE)
+KEY=$(field 5)
+KEY_SIZE=$(( ${#KEY} / 2 * 8 ))
+SYS_UUID=$(field_uuid $DEVICE)
+UUID="${SYS_UUID:12:8}-${SYS_UUID:20:4}-${SYS_UUID:24:4}-${SYS_UUID:28:4}-${SYS_UUID:32:12}"
+
+#echo "CIPHER=$CIPHER OFFSET=$OFFSET SYS_DEVICE=$SYS_DEVICE REAL_DEVICE=$REAL_DEVICE KEY_SIZE=$KEY_SIZE KEY=$KEY UUID=$UUID SYS_UUID=$SYS_UUID"
+
+[ -z "$CIPHER" -o -z "$OFFSET" -o "$OFFSET" -le 383 -o \
+-z "$KEY" -o -z "$UUID" -o -z "$REAL_DEVICE" -o "${SYS_UUID:0:12}" != "CRYPT-LUKS1-" ] && \
+fail "Incompatible device, sorry."
+
+echo "Generating master key to file $MK_FILE."
+echo -E -n $KEY| xxd -r -p >$MK_FILE
+
+echo "You can now try to reformat LUKS device using:"
+echo " cryptsetup luksFormat -c $CIPHER -s $KEY_SIZE --align-payload=$OFFSET --master-key-file=$MK_FILE --uuid=$UUID $REAL_DEVICE"
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..1ad138e
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,20 @@
+cs
+da
+de
+es
+fi
+fr
+id
+it
+ja
+ka
+nl
+pl
+pt_BR
+ro
+ru
+sr
+sv
+uk
+vi
+zh_CN
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..93d6bbc
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,44 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This option gets passed to msgmerge.
+MSGMERGE_OPTIONS = --no-wrap
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
+# package. (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.) Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright. The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER =
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+# in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+# understood.
+# - Strings which make invalid assumptions about notation of date, time or
+# money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = cryptsetup@lists.linux.dev
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used. It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..ed9ebfe
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,56 @@
+lib/libdevmapper.c
+lib/random.c
+lib/setup.c
+lib/utils.c
+lib/volumekey.c
+lib/crypt_plain.c
+lib/utils_crypt.c
+lib/utils_loop.c
+lib/utils_device.c
+lib/utils_devpath.c
+lib/utils_pbkdf.c
+lib/utils_benchmark.c
+lib/utils_device_locking.c
+lib/utils_wipe.c
+lib/utils_keyring.c
+lib/utils_blkid.c
+lib/utils_io.c
+lib/utils_storage_wrappers.c
+lib/luks1/af.c
+lib/luks1/keyencryption.c
+lib/luks1/keymanage.c
+lib/loopaes/loopaes.c
+lib/tcrypt/tcrypt.c
+lib/bitlk/bitlk.c
+lib/fvault2/fvault2.c
+lib/verity/verity.c
+lib/verity/verity_hash.c
+lib/verity/verity_fec.c
+lib/integrity/integrity.c
+lib/luks2/luks2_digest.c
+lib/luks2/luks2_digest_pbkdf2.c
+lib/luks2/luks2_disk_metadata.c
+lib/luks2/luks2_json_format.c
+lib/luks2/luks2_json_metadata.c
+lib/luks2/luks2_keyslot.c
+lib/luks2/luks2_keyslot_luks2.c
+lib/luks2/luks2_keyslot_reenc.c
+lib/luks2/luks2_luks1_convert.c
+lib/luks2/luks2_reencrypt.c
+lib/luks2/luks2_reencrypt_digest.c
+lib/luks2/luks2_segment.c
+lib/luks2/luks2_token.c
+lib/luks2/luks2_token_keyring.c
+src/cryptsetup.c
+src/veritysetup.c
+src/integritysetup.c
+src/utils_tools.c
+src/utils_progress.c
+src/utils_password.c
+src/utils_luks.c
+src/utils_reencrypt.c
+src/utils_reencrypt_luks1.c
+src/utils_blockdev.c
+src/utils_args.c
+tokens/ssh/cryptsetup-ssh.c
+tokens/ssh/ssh-utils.c
diff --git a/po/cryptsetup.pot b/po/cryptsetup.pot
new file mode 100644
index 0000000..8c1423d
--- /dev/null
+++ b/po/cryptsetup.pot
@@ -0,0 +1,3895 @@
+# SOME DESCRIPTIVE TITLE.
+# This file is put in the public domain.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr ""
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr ""
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr ""
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr ""
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr ""
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random "
+"events.\n"
+msgstr ""
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr ""
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr ""
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr ""
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr ""
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr ""
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr ""
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr ""
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr ""
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr ""
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr ""
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr ""
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr ""
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr ""
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr ""
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr ""
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr ""
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr ""
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr ""
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr ""
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr ""
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr ""
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr ""
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr ""
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr ""
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr ""
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr ""
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr ""
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr ""
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr ""
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr ""
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr ""
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr ""
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr ""
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid ""
+"Device %s is too small for activation, there is no remaining space for "
+"data.\n"
+msgstr ""
+
+#: lib/setup.c:1840
+msgid ""
+"WARNING: The device activation will fail, dm-crypt is missing support for "
+"requested encryption sector size.\n"
+msgstr ""
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr ""
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr ""
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr ""
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr ""
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr ""
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr ""
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr ""
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr ""
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr ""
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr ""
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr ""
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr ""
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr ""
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr ""
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr ""
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr ""
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr ""
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr ""
+
+#: lib/setup.c:2313
+#, c-format
+msgid ""
+"WARNING: Requested tag size %d bytes differs from %s size output (%d "
+"bytes).\n"
+msgstr ""
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr ""
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr ""
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr ""
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr ""
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr ""
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr ""
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr ""
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr ""
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr ""
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr ""
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr ""
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr ""
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr ""
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr ""
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr ""
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr ""
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr ""
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr ""
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr ""
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr ""
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr ""
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr ""
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr ""
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr ""
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr ""
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr ""
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr ""
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr ""
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr ""
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr ""
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr ""
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr ""
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr ""
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr ""
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr ""
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr ""
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr ""
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr ""
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr ""
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr ""
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr ""
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr ""
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr ""
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr ""
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr ""
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr ""
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr ""
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr ""
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr ""
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr ""
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr ""
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr ""
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr ""
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr ""
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr ""
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr ""
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr ""
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr ""
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr ""
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr ""
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr ""
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr ""
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr ""
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr ""
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr ""
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr ""
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr ""
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr ""
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr ""
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr ""
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr ""
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr ""
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr ""
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr ""
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr ""
+
+#: lib/utils_device.c:844
+msgid ""
+"Attaching loopback device failed (loop device with autoclear flag is "
+"required)."
+msgstr ""
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr ""
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr ""
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr ""
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr ""
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr ""
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr ""
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid ""
+"Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr ""
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr ""
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr ""
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr ""
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid ""
+"Locking aborted. The locking path %s/%s is unusable (not a directory or "
+"missing)."
+msgstr ""
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid ""
+"Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr ""
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr ""
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr ""
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr ""
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr ""
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr ""
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr ""
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr ""
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr ""
+
+#: lib/luks1/keymanage.c:348
+msgid ""
+"does not contain LUKS header. Replacing header can destroy data on that "
+"device."
+msgstr ""
+
+#: lib/luks1/keymanage.c:349
+msgid ""
+"already contains LUKS header. Replacing header will destroy existing "
+"keyslots."
+msgstr ""
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr ""
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr ""
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr ""
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr ""
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr ""
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr ""
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr ""
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr ""
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr ""
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr ""
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr ""
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:786
+msgid ""
+"Data offset for LUKS header must be either 0 or higher than header size."
+msgstr ""
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr ""
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr ""
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr ""
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr ""
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr ""
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr ""
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr ""
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr ""
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr ""
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr ""
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid ""
+"Unexpected metadata entry type '%u' found when parsing supported Volume "
+"Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid ""
+"Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid ""
+"Unexpected metadata entry value '%u' found when parsing supported Volume "
+"Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid ""
+"WARNING: BitLocker volume size %<PRIu64> does not match the underlying "
+"device size %<PRIu64>"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1389
+msgid ""
+"Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1393
+msgid ""
+"Cannot activate device, kernel dm-crypt is missing support for BITLK "
+"Elephant diffuser."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1397
+msgid ""
+"Cannot activate device, kernel dm-crypt is missing support for large sector "
+"size."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr ""
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr ""
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr ""
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr ""
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr ""
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr ""
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr ""
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr ""
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr ""
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr ""
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr ""
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr ""
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr ""
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr ""
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr ""
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr ""
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr ""
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr ""
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid ""
+"WARNING: Kernel cannot activate device if data block size exceeds page size "
+"(%u)."
+msgstr ""
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr ""
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr ""
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr ""
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr ""
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr ""
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr ""
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr ""
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr ""
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr ""
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr ""
+
+#: lib/integrity/integrity.c:292
+msgid ""
+"Kernel refuses to activate insecure recalculate option (see legacy "
+"activation options to override)."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid ""
+"Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr ""
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid ""
+"WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 "
+"keyslot count is very limited.\n"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid ""
+"Binary header with keyslot areas size differ on device and backup, restore "
+"failed."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid ""
+"does not contain LUKS2 header. Replacing header can destroy data on that "
+"device."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid ""
+"already contains LUKS2 header. Replacing header will destroy existing "
+"keyslots."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid ""
+"Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid ""
+"Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid ""
+"Can not update resilience type. New type only provides %<PRIu64> bytes, "
+"required space is: %<PRIu64> bytes."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid ""
+"Cannot convert to LUKS1 format - default segment encryption sector size is "
+"not 512 bytes."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid ""
+"Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid ""
+"Cannot convert to LUKS1 format - slot %u (over maximum slots) is still "
+"active."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid ""
+"Source and target device sizes don't match. Source %<PRIu64>, target: "
+"%<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid ""
+"Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid ""
+"Moved segment too large. Requested size %<PRIu64>, available space for: "
+"%<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid ""
+"Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> "
+"sectors)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid ""
+"Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> "
+"sectors long."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr ""
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr ""
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr ""
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr ""
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr ""
+
+#: src/cryptsetup.c:167
+msgid ""
+"WARNING: The --hash parameter is being ignored in plain mode with keyfile "
+"specified.\n"
+msgstr ""
+
+#: src/cryptsetup.c:175
+msgid ""
+"WARNING: The --keyfile-size option is being ignored, the read size is the "
+"same as the encryption key size.\n"
+msgstr ""
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid ""
+"Detected device signature(s) on %s. Proceeding further may damage existing "
+"data."
+msgstr ""
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr ""
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr ""
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr ""
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr ""
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr ""
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr ""
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr ""
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr ""
+
+#: src/cryptsetup.c:464
+msgid ""
+"Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr ""
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr ""
+
+#: src/cryptsetup.c:747
+msgid ""
+"Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr ""
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr ""
+
+#: src/cryptsetup.c:835
+msgid ""
+"Resize of active device requires volume key in keyring but --disable-keyring "
+"option is set."
+msgstr ""
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr ""
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr ""
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr ""
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr ""
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid ""
+"%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit "
+"key (requested %u ms time)\n"
+msgstr ""
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr ""
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr ""
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr ""
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr ""
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr ""
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr ""
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the "
+"reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as "
+"genuine."
+msgstr ""
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr ""
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr ""
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr ""
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr ""
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr ""
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will "
+"contain invalid checksum).\n"
+msgstr ""
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr ""
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr ""
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr ""
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr ""
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr ""
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr ""
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr ""
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr ""
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr ""
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr ""
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid ""
+"LUKS file container %s is too small for activation, there is no remaining "
+"space for data."
+msgstr ""
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid ""
+"Cannot determine volume key size for LUKS without keyslots, please use --key-"
+"size option."
+msgstr ""
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr ""
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr ""
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid ""
+"This is the last keyslot. Device will become unusable after purging this key."
+msgstr ""
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr ""
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr ""
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr ""
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr ""
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr ""
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr ""
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr ""
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr ""
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr ""
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr ""
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr ""
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr ""
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr ""
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr ""
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr ""
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr ""
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr ""
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr ""
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr ""
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr ""
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr ""
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr ""
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr ""
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr ""
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr ""
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr ""
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr ""
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr ""
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr ""
+
+#: src/cryptsetup.c:2983
+msgid ""
+"Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only "
+"for TCRYPT device."
+msgstr ""
+
+#: src/cryptsetup.c:2986
+msgid ""
+"Option --veracrypt or --disable-veracrypt is supported only for TCRYPT "
+"device type."
+msgstr ""
+
+#: src/cryptsetup.c:2989
+msgid ""
+"Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr ""
+
+#: src/cryptsetup.c:2993
+msgid ""
+"Option --veracrypt-query-pim is supported only for VeraCrypt compatible "
+"devices."
+msgstr ""
+
+#: src/cryptsetup.c:2995
+msgid ""
+"The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr ""
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr ""
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr ""
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr ""
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr ""
+
+#: src/cryptsetup.c:3016
+msgid ""
+"Option --offset with open action is only supported for plain and loopaes "
+"devices."
+msgstr ""
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr ""
+
+#: src/cryptsetup.c:3023
+msgid ""
+"Sector size option with open action is supported only for plain devices."
+msgstr ""
+
+#: src/cryptsetup.c:3027
+msgid ""
+"Large IV sectors option is supported only for opening plain type device with "
+"sector size larger than 512 bytes."
+msgstr ""
+
+#: src/cryptsetup.c:3032
+msgid ""
+"Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and "
+"FVAULT2 devices."
+msgstr ""
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr ""
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr ""
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid ""
+"Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr ""
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr ""
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr ""
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3091
+msgid ""
+"Option --integrity-no-wipe can be used only for format action with integrity "
+"extension."
+msgstr ""
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr ""
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr ""
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr ""
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr ""
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr ""
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr ""
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr ""
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr ""
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr ""
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr ""
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr ""
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr ""
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr ""
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr ""
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr ""
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr ""
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr ""
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr ""
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr ""
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr ""
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr ""
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr ""
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr ""
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr ""
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr ""
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr ""
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr ""
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr ""
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr ""
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr ""
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr ""
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr ""
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr ""
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr ""
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr ""
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, "
+"fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, "
+"bitlkClose, fvault2Close\n"
+msgstr ""
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr ""
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr ""
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d "
+"(characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+
+#: src/cryptsetup.c:3250
+msgid ""
+"\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr ""
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr ""
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr ""
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr ""
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr ""
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr ""
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr ""
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr ""
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr ""
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr ""
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr ""
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr ""
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr ""
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr ""
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr ""
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr ""
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr ""
+
+#: src/cryptsetup.c:3557
+msgid ""
+"Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/"
+"argon2id."
+msgstr ""
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr ""
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr ""
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr ""
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr ""
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr ""
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr ""
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr ""
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr ""
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr ""
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr ""
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr ""
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr ""
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr ""
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr ""
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr ""
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr ""
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr ""
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr ""
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr ""
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr ""
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr ""
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr ""
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr ""
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, "
+"Hash format: %u\n"
+msgstr ""
+
+#: src/veritysetup.c:658
+msgid ""
+"Option --ignore-corruption and --restart-on-corruption cannot be used "
+"together."
+msgstr ""
+
+#: src/veritysetup.c:663
+msgid ""
+"Option --panic-on-corruption and --restart-on-corruption cannot be used "
+"together."
+msgstr ""
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --"
+"integrity-recalculate)."
+msgstr ""
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr ""
+
+#: src/integritysetup.c:289
+msgid ""
+"Setting recalculate flag is not supported, you may consider using --wipe "
+"instead."
+msgstr ""
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr ""
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr ""
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr ""
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr ""
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:727
+msgid ""
+"Journal integrity algorithm must be specified if journal integrity key is "
+"used."
+msgstr ""
+
+#: src/integritysetup.c:731
+msgid ""
+"Both journal encryption key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:734
+msgid ""
+"Journal encryption algorithm must be specified if journal encryption key is "
+"used."
+msgstr ""
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr ""
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr ""
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr ""
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr ""
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr ""
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr ""
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr ""
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr ""
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr ""
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr ""
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr ""
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr ""
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr ""
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr ""
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr ""
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr ""
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr ""
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr ""
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr ""
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr ""
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr ""
+
+#: src/utils_tools.c:290
+#, c-format
+msgid ""
+"Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr ""
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr ""
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr ""
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr ""
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr ""
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr ""
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr ""
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr ""
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr ""
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr ""
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr ""
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr ""
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr ""
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr ""
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr ""
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr ""
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr ""
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr ""
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr ""
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr ""
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr ""
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr ""
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr ""
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr ""
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr ""
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr ""
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr ""
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr ""
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr ""
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr ""
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr ""
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr ""
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr ""
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or "
+"not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode "
+"(dangerous!)."
+msgstr ""
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid ""
+"Requested --resilience option cannot be applied to current reencryption "
+"operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr ""
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr ""
+
+#: src/utils_reencrypt.c:215
+msgid ""
+"Device is in reencryption using datashift resilience. Requested --resilience "
+"option cannot be applied."
+msgstr ""
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr ""
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid ""
+"Device %s is already in LUKS2 reencryption. Do you wish to resume previously "
+"initialised operation?"
+msgstr ""
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr ""
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr ""
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid ""
+"Encryption without detached header (--header) is not possible without data "
+"device size reduction (--reduce-device-size)."
+msgstr ""
+
+#: src/utils_reencrypt.c:525
+msgid ""
+"Requested data offset must be less than or equal to half of --reduce-device-"
+"size parameter."
+msgstr ""
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid ""
+"Adjusting --reduce-device-size value to twice the --offset %<PRIu64> "
+"(sectors).\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr ""
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr ""
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr ""
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr ""
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr ""
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid ""
+"Header file %s does not exist. Do you want to initialize LUKS2 decryption of "
+"device %s and export LUKS2 header to file %s?"
+msgstr ""
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr ""
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:873
+msgid ""
+"LUKS2 decryption is supported with detached header device only (with data "
+"offset set to 0)."
+msgstr ""
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr ""
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid ""
+"Key file can be used only with --key-slot or with exactly one key slot "
+"active."
+msgstr ""
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr ""
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr ""
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr ""
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option "
+"(dangerous!)."
+msgstr ""
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr ""
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr ""
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr ""
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr ""
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr ""
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr ""
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid ""
+"No decryption in progress, provided UUID can be used only to resume "
+"suspended decryption process."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ""
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr ""
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr ""
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr ""
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr ""
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr ""
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr ""
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr ""
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr ""
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr ""
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr ""
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token "
+"connected to an SSH server\vThis plugin currently allows only adding a token "
+"to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a "
+"passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when "
+"opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, "
+"user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid ""
+"Keyslot to assign the token to. If not specified, token will be assigned to "
+"the first keyslot matching provided passphrase."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr ""
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr ""
diff --git a/po/cs.po b/po/cs.po
new file mode 100644
index 0000000..ed39d10
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,4782 @@
+# Czech translation for cryptsetup.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Milan Broz <mbroz@redhat.com>, 2010.
+# Petr Pisar <petr.pisar@atlas.cz>, 2010, 2011, 2012, 2013, 2014, 2015, 2016.
+# Petr Pisar <petr.pisar@atlas.cz>, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+#
+# See `LUKS On-Disk Format Specification' document to clarify some terms.
+#
+# backing device → podpůrné zařízení
+# (SSH) credentials → přihlašovací údaje
+# data offset → počátek dat
+# deffered remove → odložené odebrání
+# detached header → oddělená hlavička
+# digest → otisk
+# hash → haš
+# key slot → pozice klíče
+# keyring → klíčenka
+# online mode → (režim) za běhu
+# plain/LUKS1 crypt → šifra plain/LUKS1 („plain“ nepřekládat)
+# (reencryption) recover → obnova (jedná se o činnost před samotným navázáním
+# rozdělaného přešifrování, obvykle po výpadku napájení).
+# refresh → reaktivace
+# resume → probudit, dokončit
+# segment → část
+# signature → značka, vzorec nebo podpis (záleží na kontextu)
+# suspend → uspat
+# token → token
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-02 18:11+01:00\n"
+"Last-Translator: Petr Pisar <petr.pisar@atlas.cz>\n"
+"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Nelze inicializovat device-mapper, nespuštěno superuživatelem."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Nelze inicializovat device-mapper. Je jaderný modul dm_mod zaveden?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Požadovaný příznak odložení není podporován."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID pro zařízení %s bylo zkráceno."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Neznámý druh cíle DM."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Požadované výkonnostní volby dm-cryptu nejsou podporovány."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Požadované volby, jak zacházet s poškozením dat dm-verity, nejsou podporovány."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "Požadovaná volba taskletu dm-cryptu není podporována."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Požadované FEC volby dm-cryptu nejsou podporovány."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Požadované volby integrity dat nejsou podporovány."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "Požadované volby sector_size není podporována."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Požadovaný automatický přepočet značek integrity není podporován."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Zahazování (TRIM) není podporováno."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Požadovaný režim bitmapy integrity DM není podporován."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Dotaz na část dm-%s selhal."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Během vytváření klíče svazku došla systému entropie.\n"
+"Aby bylo možné nasbírat náhodné události, žádáme uživatele, aby pohyboval\n"
+"myší nebo psal text do jiného okna.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Vytváří se klíč (%d %% hotovo).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Režim FIPS zapnut."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "Fatální chyba během přípravy generátoru náhodných čísel."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Požadována neznámá kvalita generátoru náhodných čísel."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Chyba při čtení z generátoru náhodných čísel."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Implementaci šifrovacího generátoru náhodných čísel nelze inicializovat."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Implementaci šifrování nelze inicializovat."
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Hašovací algoritmus %s není podporován."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Chyba zpracování klíče (za použití haše %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Druh zařízení nelze určit. Nekompatibilní aktivace zařízení?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "Tato operace je podporována jen u zařízení LUKS."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Tato operace je podporována jen u zařízení LUKS2."
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Všechny pozice klíčů jsou obsazeny."
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Pozice klíče %d není platná, prosím, vyberte číslo mezi 0 a %d."
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Pozice klíče %d je obsazena, prosím, vyberte jinou."
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "Velikost zařízení není zarovnaná na velikost logického sektoru zařízení."
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Nalezena hlavička, ale zařízení %s je příliš malé."
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Tato operace není na zařízení tohoto typu podporována."
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Zakázaná operace spolu s probíhajícím přešifrování."
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Nahrání původních metadat LUKS2 do paměti selhalo."
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Zařízení %s není platným zařízením LUKS."
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Nepodporovaná verze LUKS %d."
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "Zařízení %s není aktivní."
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Zařízení nižší úrovně pod šifrovaným zařízením %s zmizelo."
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "Neplatné parametry plain šifry."
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "Neplatná velikost klíče."
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID není na šifře tohoto typu podporováno."
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Zařízení s oddělenými metadaty není na šifře tohoto typu podporováno."
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Nepodporovaná velikost šifrovaného sektoru."
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "Velikost zařízení není zarovnaná na požadovanou velikost sektoru."
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "LUKS nelze bez zařízení naformátovat."
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Požadované zarovnání dat není slučitelné s polohou dat."
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Ze zařízení %s nelze odstranit hlavičku."
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Zařízení %s je na aktivaci příliš malé. Nezbývá žádné místo pro data.\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "POZOR: Aktivace zařízení selže, dm-crypt nepodporuje požadovanou velikost šifrovaného sektoru.\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Klíč svazku je příliš malý na šifrovaní s rozšířeními pro integritu."
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Šifra %s-%s (velikost klíče %zd bitů) není dostupná."
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "POZOR: Metadata LUKS2 změnila velikost na %<PRIu64> bajtů.\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "POZOR: Oblast s pozicemi klíčů pro LUKS2 změnila velikost na %<PRIu64> bajtů.\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Zařízení %s je příliš malé."
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Zařízení %s, které se používá, nelze formátovat."
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Zařízení %s nelze formátovat, povolení zamítnuto."
+
+# FIXME "format integrity" is nonsense
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Zařízení %s není možné formátovat integritu."
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Zařízení %s nelze formátovat."
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "LOOPAES nelze bez zařízení naformátovat."
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "VERITY nelze bez zařízení naformátovat."
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Nepodporovaný druh VERITY haše %d."
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Nepodporovaná velikost bloku VERITY."
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Nepodporovaná poloha haše VERITY."
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "Nepodporovaná poloha VERITY FEC."
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "Oblast dat se překrývá s oblastí haše."
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "Oblast FEC se překrývá s oblastí haše."
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "Oblast dat se překrývá s oblastí FEC."
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "POZOR: Požadovaná velikost značky %d bajtů se liší od výstupu velikosti %s (%d bajtů).\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Požadován neznámý typ šifrovaného zařízení %s."
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Nepodporované parametry na zařízení %s."
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Neodpovídající parametry an za zařízení %s."
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Zařízení dmcryptu si neodpovídají."
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Zařízení %s nebylo možné znovu zavést."
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Zařízení %s nebylo možné pozastavit."
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Zařízení %s nebylo možné probudit."
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Nepřekonatelná chyba při zavádění zařízení %s (nad zařízením %s)."
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Zařízení %s nebylo možné přepnout do dm-error."
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "Nelze změnit velikost zařízení zpětné smyčky."
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr ""
+"POZOR: Maximální velikost je již nastavena nebo změna velikosti není jádrem\n"
+"podporována.\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Změna velikosti selhala, jádro ji nepodporuje."
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "Opravdu chcete změnit UUID zařízení?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Soubor se zálohou hlavičky neobsahuje kompatibilní hlavičku LUKS."
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Svazek %s není aktivní."
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Svazek %s je již uspán."
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Uspání není na zařízení %s podporováno."
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Chyba při uspávání zařízení %s."
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Probuzení není na zařízení %s podporováno."
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Chyba při probouzení zařízení %s."
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Svazek %s není uspán."
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Heslo svazku neodpovídá svazku."
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "Záměna novou pozicí klíče se nezdařila."
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Pozice klíče %d je neplatná."
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Pozice klíče %d není aktivní."
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "Hlavička zařízení se překrývá s datovou oblastí."
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Přešifrování již probíhá. Zařízení nelze aktivovat."
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Získání zámku pro přešifrování selhalo."
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Obnova přešifrování LUKS2 selhalo."
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "Typ zařízení není řádně inicializován."
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "Zařízení %s již existuje."
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Zařízení %s nelze použít. Název není platný nebo zařízení se stále používá."
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "Byl zadán neplatný klíč svazku."
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "K zařízení VERITY byl zadán neplatný kořenový haš."
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "Je potřeba podpis kořenového otisku."
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Jaderná klíčenka chybí: je potřeba pro předání podpisu do jádra."
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "Klíč se nepodařilo přidat do jaderné klíčenky."
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Odložené odebrání zařízení %s nebylo možné zrušit."
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Zařízení %s se stále používá."
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "Neplatné zařízení %s."
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "Vyhrazená paměť pro klíč svazku je příliš malá."
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Nelze získat klíč svazku pro zařízení LUKS2."
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Nelze získat klíč svazku pro zařízení LUKS1."
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Nelze získat klíč svazku pro otevřené zařízení."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "K zařízení VERITY nelze získat kořenový otisk."
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Nelze získat klíč svazku pro zařízení BITLK."
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Nelze získat klíč svazku pro zařízení FVAULT2."
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Na šifrovaném zařízení %s není tato operace podporována."
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "Operace výpisu není na zařízení tohoto typu podporována."
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Počátek dat není násobkem %u bajtů."
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Zařízení %s, které se stále používá, nelze konvertovat."
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Přiřazení pozice klíče %u jakožto nového klíče svazku se nezdařilo."
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Inicializace parametrů výchozí pozice klíče LUKS2 selhala."
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Přiřazení pozice klíče %d k otisku se nezdařilo."
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Nelze přidat pozici klíče, všechny pozice jsou zakázány a klíč svazku nebyl poskytnut."
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Jaderná klíčenka není jádrem podporována."
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Čtení hesla z klíčenky selhalo (chyba %d)."
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Získání zámku pro tvrdý přístup do globální paměti selhalo."
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Soubor s klíčem se nepodařilo otevřít."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Soubor s klíčem nelze z terminálu přečíst."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "O souboru s klíčem nebylo možné zjistit údaje."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Nelze se přesunout na požadované místo v souboru s klíčem."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "Při čtení hesla došla paměť."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Chyba při čtení hesla."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Na vstupu není nic k přečtení."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Maximální délka souboru s klíčem překročena."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "Požadované množství dat nelze načíst."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Zařízení %s neexistuje nebo přístup byl zamítnut."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Zařízení %s není kompatibilní."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "U zařízení s daty se ignoruje chybná optimální velikost I/O (%u bajtů)."
+
+# TODO: Pluralize
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Zařízení %s je příliš malé. Je třeba alespoň %<PRIu64> bajtů."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Zařízení %s nelze použít, protože se již používá (již namapováno nebo připojeno)."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Zařízení %s nelze použít, povolení zamítnuto."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "O zařízení %s nelze získat údaje."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Zařízení typu loopback nelze použít, nespuštěno superuživatelem."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Připojení zařízení zpětné smyčky selhalo (požadováno zařízení s příznakem autoclear)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Požadovaná poloha je za hranicí skutečné velikosti zařízení %s."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Zařízení %s má nulovou velikost."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Požadovaný cílový čas PBKDF nemůže být nula."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Neznámý druh PBKDF %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Požadovaný haš %s není podporován."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Požadovaný druh PBKDF není podporován formátem LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Při PBKDF2 nesmí být nastavena maximální paměť pro PBKDF nebo počet souběžných vláken."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Vynucený počet opakování je pro %s příliš nízký (minimum je %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Vynucená cena paměti je pro %s příliš nízká (minimum je %u kilobajtů)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Požadovaná maximální cena PBKDF paměti je příliš vysoká (maximum je %d kilobajtů)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Požadované maximum paměti PBKDF nemůže být nula."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Požadovaný počet souběžných vláken PBKDF nemůže být nula."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "V režimu FIPS je podporován jen PBKDF2."
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Porovnání výkonu PBKDF je zakázáno, ale počet iterací není nastaven."
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Neslučitelné volby PBKDF2 (při použití hašovacího algoritmu %s)."
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "Neslučitelné volby PBKDF."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Zamykání zrušeno. Zamykací cesta %s/%s je nepoužitelná (není adresářem nebo neexistuje)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Zamykání zrušeno. Zamykací cesta %s/%s je nepoužitelná (%s není adresářem)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Nelze se přesunout na požadované místo v zařízení."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Chyba při čištění zařízení na pozici %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Nepodařilo se nastavit mapování klíče v dm-cryptu pro zařízení %s.\n"
+"Zkontrolujte, že jádro podporuje šifru %s (podrobnosti v syslogu)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "V režimu XTS musí být velikost klíče 256 nebo 512 bitů."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Zápis šifry by měl být ve tvaru [šifra]-[režim]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Na zařízení %s nelze zapsat, povolení zamítnuto."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Otevření dočasného zařízení s úložištěm klíče selhalo."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Přístup do dočasného zařízení s úložištěm klíče selhal."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Chyba vstupu/výstupu při šifrování pozice klíče."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Zařízení %s nelze otevřít."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "Chyba vstupu/výstupu při dešifrování pozice klíče."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Zařízení %s je příliš malé. (LUKS1 vyžaduje alespoň %<PRIu64> bajtů.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "Pozice %u klíče LUKS není platná."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Požadovaný soubor se zálohou hlavičky %s již existuje."
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Soubor se zálohou hlavičky %s nelze vytvořit."
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Nelze zapsat soubor %s se zálohou hlavičky."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Záložní soubor neobsahuje platnou hlavičku LUKS."
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Nelze otevřít soubor se zálohou hlavičky %s."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Soubor se zálohou hlavičky %s nelze načíst."
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Počátek dat nebo velikost klíče se liší mezi zařízením a zálohou, obnova se nezdařila."
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Zařízení %s %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "neobsahuje hlavičku LUKS. Nahrazení hlavičky může zničit data na daném zařízení."
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "již obsahuje hlavičku LUKS. Nahrazení hlavičky zničí existující pozice s klíči."
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"POZOR: hlavička ve skutečném zařízení má jiné UUID než záloha!"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "Nestandardní velikost klíče, je třeba ruční opravy."
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Nestandardní zarovnání pozice klíče, je třeba ruční opravy."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Režim šifry opraven (%s → %s)."
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Haš šifry opraven na malý písmena (%s)."
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Požadovaný haš LUKSu %s není podporován."
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "Opravují se pozice klíčů."
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Pozice klíče %i: poloha opravena (%u → %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Pozice klíče %i: proklad opraven (%u → %u)."
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Pozice klíče %i: chybná značka oddílu."
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Pozice klíče %i: sůl vymazána."
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "Hlavička LUKS se zapisuje na disk."
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "Oprava selhala."
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Režim LUKS šifry %s není platný."
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "LUKS haš %s není platný."
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "V hlavičce LUKS nenalezen žádný známý problém."
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Chyba při aktualizaci hlavičky LUKS na zařízení %s."
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Chyba při opakovaném čtení hlavičky LUKS po aktualizaci zařízení %s."
+
+# TODO: Pluralize
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Poloha dat u hlavičky LUKS musí být buď 0 nebo více než velikost hlavičky."
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "Poskytnut UUID LUKSu ve špatném tvaru."
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Hlavičku LUKS nelze vytvořit: čtení náhodné soli selhalo."
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Hlavičku LUKS nelze vytvořit: výpočet otisku hlavičky (haš %s) selhal."
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Pozice klíče %d je aktivní, nejprve ji uvolněte."
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Pozice klíče %d obsahuje příliš málo útržků. Manipulace s hlavičkou?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "Čítač opakování PBKDF2 přetekl."
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Pozici s klíčem nezle otevřít (za použití haše %s)."
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Pozice klíče %d není platná, prosím, vyberte pozici mezi 0 a %d."
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Zařízení %s není možné smazat."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Zjištěn dosud nepodporovaný soubor s klíčem šifrovaný pomocí GPG."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Prosím, použijte gpg --decrypt SOUBOR_S_KLÍČEM | cryptsetup --keyfile=- …\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Zjištěn nekompatibilní soubor s klíčem loop-AES."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Jádro nepodporuje mapování kompatibilní s loop-AES."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Chyba při čtení souboru s klíčem %s"
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Překročena maximální délka hesla TCRYPT (%zu)."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Hašovací algoritmus PBKDF2 %s není podporován, přeskakuje se."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "Požadované kryptografické rozhraní jádra není dostupné."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Ujistěte se, že jaderný modul algif_skcipher je zaveden."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Aktivace nad sektory o velikosti %d není podporována."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Jádro nepodporuje aktivaci v tomto zastaralém režimu TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Aktivuje se systémové šifrování TCRYPT pro oddíl %s."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Jádro nepodporuje mapování kompatibilní s TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Bez dat s hlavičkou TCRYPT není tato funkce podporována."
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Při rozboru podporovaného hlavního klíče svazku byla nalezena položka nečekaného typu „%u“."
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Při rozboru hlavního svazku klíče byl nalezen neplatný řetězec."
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Při rozboru hlavního klíče svazku byl nalezen nečekaný řetězec („%s“)."
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Při rozboru hlavního klíče svazku byl nalezen záznam metadat s nečekanou hodnotou „%u“."
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK verze 1 není v současnosti podporován."
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Neplatná nebo neznámá značka zavaděče zařízení BITLK."
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Nepodporovaná velikost sektoru %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Z %s nebylo možné načíst hlavičku BITLK."
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Z %s nebylo možné přečíst metadata BITLK FVE."
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "Neznámý nebo nepodporovaný druh šifrování."
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Z %s nebylo možné načíst položky metadat BITLK."
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "Převod popisu svazku BITLK se nezdařil"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Při rozboru externího klíče byla v metadatech nalezena položka nečekaného typu „%u“."
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "GUID „%s“ souboru BEK neodpovídá GUID svazku."
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Při rozboru externího klíče byla v metadatech nalezena položka s nečekanou hodnotou „%u“."
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Nepodporovaná metadata BEK verze %<PRIu32>."
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Nečekaná velikost metadat BEK %<PRIu32> neodpovídá délce souboru BEK"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Při rozboru startovacího klíče byla v metadatech nalezena nečekaná položka."
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "Tato operace není podporována."
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "Nečekaná velikost údajů o klíči."
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Toto zařízení BITLK je v nepodporovaném stavu a nelze jej aktivovat."
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Zařízení BITLK s typem „%s“ nelze aktivovat."
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Aktivace částečně dešifrovaného zařízení BITLK není podporována."
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "POZOR: Velikost svazku BitLockeru %<PRIu64> neodpovídá velikosti zařízení ve zpod %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Zařízení nelze aktivovat. Jaderný dm-crypt postrádá podporu inicializačního vektoru BITLK."
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Zařízení nelze aktivovat. Jaderný dm-crypt postrádá podporu difuzéru Elephant BITLK."
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Zařízení nelze aktivovat. Jaderný dm-crypt postrádá podporu velikostí velkých sektorů."
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Zařízení nelze aktivovat. Chybí jaderný modul dm-zero."
+
+# FIXME: Pluralize
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Z hlavičky svazku nebylo možné přečíst %u bajtů."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Nepodporovaná verze FVAULT2 %<PRIu16>."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Zařízení VERITY %s nepoužívá hlavičku uvnitř disku."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Nepodporovaná verze VERITY %d."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "Hlavička VERITY je poškozena."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Na zařízení %s poskytnuto UUID VERITY ve špatném tvaru."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Chyba při aktualizaci hlavičky VERITY na zařízení %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Ověření podpisu kořenového otisku není podporováno."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Chyby v zařízení FEC nelze opravit."
+
+# TODO: Pluralize
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Nalezeno %u opravitelných chyb v zařízení FEC."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Jádro nepodporuje mapování dm-verity."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Jádro nepodporuje volbu pro podpis dm-verity."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Po aktivaci zjistilo zařízení VERITY poškození."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Řídká oblast na pozici %<PRIu64> není vynulována."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Pozice na zařízení přetekla."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Ověření na pozici %<PRIu64> selhalo."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Přetečení oblasti haše."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Ověření datové oblasti selhalo."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Ověření kořenového haše selhalo."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Při vytváření oblasti haší došlo k chybě na vstupu/výstupu."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Oblast haší se nepodařilo vytvořit."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "POZOR: Jádro nemůže aktivovat zařízení, pokud velikost datového bloku přesahuje velikost stránky (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Kontext RS se nepodařilo alokovat."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Vyrovnávací paměť se nepodařilo alokovat."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Čtení bloku RS %<PRIu64> bajtu %d selhalo."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Čtení parity bloku RS %<PRIu64> selhalo."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Oprava parity bloku RS %<PRIu64> selhala."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Zápis parity bloku RS %<PRIu64> selhal."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Velikosti bloků musí odpovídat FEC."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Chybný počet paritních bajtů."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Neplatná délka části FEC."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Velikost zařízení %s se nepodařilo určit."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Neslučitelná metadata jaderného dm-integrity (verze %u) byla nalezena na %s."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Jádro nepodporuje mapování dm-integrity."
+
+# Fixed metadata means fix_padding attribute of dm-integrity target
+# documented as "use a smaller padding".
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Jádro nepodporuje drobné zarovnání metadat dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Jádro odmítá aktivovat volbu nebezpečného přepočtu (pro přebití vizte zastaralé volby aktivace)"
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Získání zámku pro zápis do zařízení %s selhalo."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Zjištěn pokus o současnou aktualizaci metadat LUKS2. Operace se ruší."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Zařízení obsahuje nejednoznačný vzorec. LUKS2 nelze automaticky obnovit.\n"
+"Prosím, spusťte obnovu příkazem „cryptsetup repair“."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Požadovaná poloha dat je příliš nízká."
+
+# TODO: Pluralize
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "POZOR: oblast s pozicemi klíčů (%<PRIu64> bajtů) je příliš malá, dostupný počet pozic klíčů LUKS2 je značně omezen.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Získání zámku pro čtení ze zařízení %s selhalo."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "V záloze %s byly zjištěny zakázané požadavky na LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Počátek dat se liší mezi zařízením a zálohou, obnova se nezdařila."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Velikost binární hlavičky s oblastí pro pozice klíčů se liší mezi zařízením a zálohou, obnova se nezdařila."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Zařízení %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "neobsahuje hlavičku LUKS2. Nahrazení hlavičky může zničit data na daném zařízení."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "již obsahuje hlavičku LUKS2. Nahrazení hlavičky zničí existující pozice s klíči."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"POZOR: Ve skutečné hlavičce zařízení byly objeveny neznámé požadavky na LUKS2!\n"
+"Nahrazení hlavičky zálohou může zničit data na zařízení!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"POZOR: Na zařízení bylo objeveno nedokončené offline přešifrování!\n"
+"Nahrazení hlavičky zálohou může zničit data."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Neznámý příznak %s ignorován."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Chybí klíč pro dm-crypt část %u."
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Nastavení části dm-crypt selhalo."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Nastavení části dm-linear selhalo."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Nepodporovaná konfigurace integrity zařízení."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Probíhá přešifrování. Zařízení nelze deaktivovat."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Výměna pozastaveného zařízení %s za cíl dm-error selhala."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Čtení požadavků na LUKS2 selhalo."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Zjištěny nesplněné požadavky na LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Operace se neslučuje se zařízením označeným pro zastaralé přešifrování. Operace se ruší."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Operace se neslučuje se zařízením označeným pro přešifrování LUKS2. Operace se ruší."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Nedostatek paměti pro otevření pozice s klíčem."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Otevření pozice s klíčem selhalo."
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Šifru %s-%s nelze použít pro pozici s klíčem."
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Hašovací algoritmus %s není dostupný."
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "Pro novou pozicí klíče není místo."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Požadována neplatná změna režimu odolnosti při přešifrování."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Druh odolnosti nelze zaktualizovat. Nový druh poskytuje pouze %<PRIu64> bajtů, požadovaná velikost je %<PRIu64> bajtů."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Ověřovací otisk přešifrování se nepodařilo obnovit."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Nelze zjistit stav zařízení s UUID: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Hlavičky s dodatečnými metadaty LUKSMETA nelze převést."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "LUKS2 neumožňuje použít šifru zadanou jako %s-%s."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Oblast s pozicemi klíčů nelze přesunout. Nedostatek místa."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Nelze převést do formátu LUKS2 – neplatná metadata."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Oblast s pozicemi klíčů nelze přesunout. Oblast s pozicemi klíčů LUKS2 je příliš malá."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Oblast s pozicemi klíčů nelze přesunout."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Nelze převést do formátu LUKS1 – výchozí velikost sektoru šifrování části není 512 bajtů."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Nelze převést do formátu LUKS1 – otisky v pozicích s klíči nejsou slučitelné s LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Nelze převést do formátu LUKS1 – zařízení používá šifru se zabaleným klíčem %s."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Nelze převést do formátu LUKS1 – zařízení používá více částí."
+
+# TODO: Pluralize
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Nelze převést do formátu LUKS1 – hlavička LUKS2 obsahuje %u token(ů)."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Nelze převést do formátu LUKS1 – pozice s klíče %u je v nesprávném stavu."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Nelze převést do formátu LUKS1 – pozice s klíčem %u (nad maximem pozic) je stále aktivní."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Nelze převést do formátu LUKS1 – pozice s klíče %u není slučitelná s LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Velikost horké zóny musí být násobek vypočteného zarovnání zóny (%zu bajtů)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Velikost zařízení musí být násobek vypočteného zarovnání zóny (%zu bajtů)."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Obálku pro starou část úložiště se nepodařilo inicializovat."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Obálku pro novou část úložiště se nepodařilo inicializovat."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Ochranu horké zóny se nepodařilo inicializovat."
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Kontrolní součty pro aktuální horkou zónu se nepodařilo přečíst."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Čtení oblasti s horkou zónou počínaje na %<PRIu64> selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Sektor %zu nebylo možné rozšifrovat."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Sektor %zu nebylo možné obnovit."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Velikosti zdrojového a cílového zařízení se neshodují. Zdroj %<PRIu64>, cíl %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Aktivace zařízení horké zóny %s selhala."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Aktivace překryvného zařízení %s se skutečnou tabulkou původu selhala."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Zavedení nového mapování pro zařízení %s selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Zásobník zařízení k přešifrování se nepodařilo obnovit."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Nastavení velikosti nové oblasti s pozicemi klíčů selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Hodnota posunu dat není zarovnána s velikostí šifrovaného sektoru (%<PRIu32> bajtů)."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Nepodporovaný režim odolnosti %s"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Velikost přesunované oblasti nemůže být větší než hodnota posunu dat."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Neplatné parametry režimu odolnosti při přešifrování."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Přesunovaná oblast je příliš velká. Požadovaná velikost %<PRIu64>, dostupné místo %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Vyprázdnění tabulky selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "Zmenšená velikost dat je větší než velikost skutečného zařízení"
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Zařízení s daty není zarovnáno na velikost šifrovaného sektoru (%<PRIu32> bajtů)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Posun dat (%<PRIu64> sektorů) je menší než budoucí poloha dat (%<PRIu64> sektorů)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Zařízení %s nebylo možné otevřít ve výlučném režimu (již namapováno nebo připojeno)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Zařízení není označeno pro přešifrování LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Načtení kontextu přešifrování LUKS2 selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Stavu přešifrování se nepodařilo zjistit."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Zařízení se nepřešifrovává."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Proces přešifrování již běží."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Získání zámku pro přešifrování selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "V přešifrování nelze pokračovat. Spusťte nejprve obnovu přešifrování."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Aktivní velikost zařízení a velikost požadovaná k přešifrování si neodpovídají."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "V parametrech přešifrování je požadována zakázaná velikost zařízení."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Probíhá přešifrování. Obnovu nelze provést."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "V metadatech je přešifrování LUKS2 již inicializováno."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Inicializace přešifrování LUKS2 v metadatech selhala."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Nastavení segmentů zařízení pro další horkou zónu přešifrování selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Metadata pro odolnost při přešifrování se nepodařilo zapsat."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Rozšifrování selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Zápis oblasti s horkou zónou počínaje na %<PRIu64> selhal."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Synchronizace dat selhala."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Po dokončení přešifrování aktuální horké zóny se nepodařilo aktualizovat metadata."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Zápis metadat LUKS2 selhal."
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Vyčištění oblasti zařízení s nepoužívanými daty selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Odstranění nepoužívané (nepřiřazené) pozice s klíčem %d selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Odstranění pozice s klíčem přešifrování selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Nepřekonatelná chyba při přešifrování bloku na pozici %<PRIu64> dlouhého %<PRIu64> sektorů."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Přešifrování za běhu selhalo."
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Zařízení neprobouzejte, dokud jej ručně nenahradíte chybovým cílem."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "V přešifrování nelze pokračovat. Přešifrování se nachází v nečekaném stavu."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Chybějící nebo neplatný kontext přešifrování."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Zásobník zařízení k přešifrování se nepodařilo inicializovat."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Kontext přešifrování se nepodařilo aktualizovat."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Metadata o přešifrování jsou neplatná."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Parametry pro šifrování pozice s klíčem lze nastavit jen u zařízení LUKS2."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Zadejte PIN k tokenu: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Zadejte PIN k tokenu %d: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Nelze najít žádný známý vzorek se specifikaci šifry."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "POZOR: Jedná-li se o režim plain a je-li určen soubor s klíčem, parametr --hash se ignoruje.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "POZOR: Přepínač --keyfile-size se ignoruje, velikost pro čtení je stejná jako velikosti šifrovacího klíče.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Na %s byla nalezen vzorec zařízení. Pokračování může poškodit existující data."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "Operace zrušena.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Je vyžadován přepínač --key-file."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Zadejte PIM VeraCryptu: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Neplatná hodnota VIM: chyba rozboru"
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Neplatná hodnota PIM: 0"
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Neplatná hodnota PIM: mimo rozsah"
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "S tímto heslem není rozpoznatelná žádná hlavička zařízení."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Zařízení %s není platným zařízením BITLK."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Nelze určit velikost BITLK klíče svazku. Prosím, použijte přepínač --key-size."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Výpis hlavičky s klíčem svazku je citlivý údaj,\n"
+"který umožňuje přístup k šifrovanému oddílu bez znalosti hesla.\n"
+"Tento výpis by měl být vždy uložen na bezpečném místě a v zašifrované podobě."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Výpis hlavičky s klíčem svazku je citlivý údaj,\n"
+"který umožňuje přístup k šifrovanému oddílu bez znalosti hesla.\n"
+"Tento výpis by měl být uložen na bezpečném místě a v zašifrované podobě."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Zařízení %s není platným zařízením FVAULT2."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Nelze určit velikost klíče svazku pro FVAULT2. Prosím, použijte přepínač --key-size."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Zařízení %s je stále aktivní a naplánováno pro odložené odstranění.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Změna velikosti aktivního zařízení vyžaduje klíč svazku v klíčence. Byl však použit přepínač --disable-keyring."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Hodnocení výkonu přerušeno."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s –\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iterací za sekundu pro %zubitový klíč\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s –\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iterací, %5u paměti, %1u souběžných vláken (procesorů) pro %zubitový klíč (požadován čas %u ms)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Výsledek hodnocení výkonu není spolehlivý."
+
+# ???: are aproximated?
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Testy jsou počítány jen z práce s pamětí (žádné I/O úložiště).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*sAlgoritmus | Klíč | Šifrování | Dešifrování\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Šifra %s (s %ibitovým klíčem) není dostupná."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritmus | Klíč | Šifrování | Dešifrování\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "–"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Objevena nechráněná metadata o přešifrování LUKS2. Prosím, ověřte, že operace\n"
+"přešifrování je žádoucí (vizte výstup luksDump) a pokračujte (zvýšení verze\n"
+"metadat) pouze, když poznáte, že operace je chtěná."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Zadejte heslo pro ochránění metadat o přešifrování a pro zvýšení jejich verze: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Opravdu pokračovat s obnovou přešifrování LUKS2?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Zadejte heslo pro ověření otisku metadat o přešifrování: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Zadejte heslo pro obnovení přešifrování: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Opravdu se pokusit opravit hlavičku zařízení LUKS?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Výmaz přerušen."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Maže se zařízení, aby se inicializovaly kontrolní součty integrity.\n"
+"Lze přerušit pomocí Ctrl+C (zbytek nesmazaného zařízení bude obsahovat\n"
+"neplatné součty).\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Dočasné zařízení %s nelze deaktivovat."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Volby integrity lze použít jen při formátu LUKS2."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Nepodporované volby velikosti metadat LUKS2."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Soubor s hlavičkou neexistuje. Chcete jej vytvořit?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Soubor s hlavičkou %s nelze vytvořit."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Nelze najít žádný známý vzorek se specifikací integrity."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "%s nelze použít pro hlavičku uvnitř disku."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Toto nevratně přepíše data na %s."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Nastavení parametrů PBKDF selhalo."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Zmenšená poloha dat je dovolena jen u oddělené hlavičky LUKS."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "Souborový kontejner LUKS %s je na aktivaci příliš malý. Nezbývá žádné místo pro data."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Bez pozic pro klíče nelze určit velikost LUKS klíče svazku. Prosím, použijte přepínač --key-size."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Zařízení aktivováno, ale příznaky nelze učinit trvalými."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Ke smazání vybrán klíč na pozici %d."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr ""
+"Toto je poslední pozice klíče. Smazáním tohoto klíče přijdete o možnost\n"
+"zařízení použít."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Zadejte jakékoliv jiné heslo: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operace zrušena, pozice klíče NEBYLA vymazána.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Zadejte heslo, které se má smazat: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Zařízení %s není platným zařízením LUKS2."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Zadejte nové heslo pro pozici klíče: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "POZOR: Parametr --key-slot se použije pro číslo nové pozice klíče.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Zadejte jakékoliv existující heslo: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Zadejte heslo, které má být změněno: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Zadejte nové heslo: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Zadejte heslo pro pozici klíče, který má být převeden: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "U operace isLuks je podporován pouze jeden argument se zařízením."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Pozice klíče %d neobsahuje nepřiřazený klíč."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Výpis hlavičky s nepřiřazeným klíčem je citlivý údaj.\n"
+"Tento výpis by měl být uložen na bezpečném místě a v zašifrované podobě."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s není název aktivního zařízení %s."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s není název aktivního zařízení LUKS nebo mu chybí hlavička."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "Je vyžadován přepínač --header-backup-file."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s není zařízení spravované nástrojem cryptsetup."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Reaktivace není na zařízení typu %s podporována"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Nerozpoznaná metadata druhu zařízení %s."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "Příkaz vyžaduje jako argumenty zařízení a mapovaný název."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Tento úkon smaže všechny pozice s klíči na zařízení %s.\n"
+"Po jeho dokončení zařízení bude nepoužitelné."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operace zrušena, pozice s klíči NEBYLY smazány.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Neplatný druh formátu LUKS. Podporován je pouze LUKS1 a LUKS2."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Zařízení je již druhu %s."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Tato operace převede formát %s na %s.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operace zrušena, zařízení NEBYLO převedeno.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Chybí přepínač --priority, --label nebo --subsystem."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Token %d je neplatný."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Token %d se používá."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Přidání tokenu %d klíčenky LUKS2 selhalo."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Přiřazení tokenu %d do pozice s klíčem %d selhalo."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Token %d se nepoužívá."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Import tokenu ze souboru selhal."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Získání tokenu %d za účelem exportu selhalo."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Token %d není přiřazen pozici s klíčem %d."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Zrušení přiřazení tokenu %d k pozici s klíčem %d selhalo."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Přepínač --tcrypt-hidden, --tcrypt-system nebo --tcrypt-backup je podporován jen u zařízení TCRYPT."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Přepínače --veracrypt a --disable-veracrypt jsou podporovány jen u typu zařízení TCRYPT."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Přepínač --veracrypt-pim je podporován jen u zařízení kompatibilním s VeraCrypt."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Přepínač --veracrypt-query-pim je podporován jen u zařízení kompatibilním s VeraCrypt."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Přepínače --veracrypt-pim a --veracrypt-query-pim se vzájemně vylučují."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Přepínač --persistent není dovolen současně s --test-passphrase."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Přepínače --refresh a --test-passphrase se vzájemně vylučují."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Přepínač --shared je dovolen jen při úkonu otevírání zařízení plain."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Přepínač --skip je podporován jen při otevírání zařízení plain a loopaes."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Při otevírání je přepínač --offset podporován jen u zařízení plain a loopaes."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Přepínač --tcrypt-hidden nelze použít s přepínačem --allow-discards."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Otevírání s přepínačem velikosti sektoru je podporován jen u zařízení plain."
+
+# FIXME: "Large IV sectors" should read "IV large sectors".
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Volba inicializačního vektoru s velkými sektory je podporována jen při otevírání zařízení typu plain s velikostí sektoru větší než 512 bajtů."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "Přepínač --test-passphrase je dovolen pouze při otevírání zařízení LUKS, TCRYPT, BITLK a FVAULT2."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Přepínače --device-size a --size nelze kombinovat."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Přepínač --unbound je dovolen jen při otevírání zařízení LUKS."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Přepínač --unbound není dovolen současně s --test-passphrase."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Přepínače --cancel-deferred a --deferred se vzájemně vylučují."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Přepínače --reduce-device-size a --data-size nelze kombinovat."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Přepínač --active-name lze použít jen u zařízení LUKS2."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Přepínače --active-name a --force-offline-reencrypt nelze kombinovat."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Je nutné určit pozici s klíčem."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Přepínače --align-payload a --offset nelze kombinovat."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Přepínač --integrity-no-wipe smí být použit jen při formátování s rozšířením integrity."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Je dovolen pouze jeden z přepínačů --use-[u]random."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "Přepínač --unbound vyžaduje velikost klíče."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "Neplatná operace tokenu."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Parametr --key-description je při přidávání tokenu povinný."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Akce vyžaduje určitý token. Použijte parametr --token-id."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "Přepínač --unbound lze použít pouze s akcí přidání."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Přepínače --key-slot a --unbound nelze kombinovat."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "Akce vyžaduje určitou pozici klíče. Použijte parametr --key-slot."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<zařízení> [--type <druh>] [<název>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "otevře zařízení jako <název>"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<název>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "zavře zařízení (odstraní mapování)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "změní velikost aktivního zařízení"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "zobrazí stav zařízení"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <šifra>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "zhodnotí výkon šifry"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<zařízení>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "pokusí se opravit metadata uložená na disku"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "přešifruje zařízení LUKS2"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "smaže všechny pozice s klíči (odstraní šifrovací klíč)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "převede formát LUKS do/z formátu LUKS2"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "nastaví trvalé volby konfigurace pro LUKS2"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<zařízení> [<soubor_s_novým_klíčem>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "naformátuje zařízení LUKS"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "do zařízení LUKS přidá klíč"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<zařízení> [<soubor_s_klíčem>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "odstraní zadaný klíč nebo soubor s klíčem ze zařízení LUKS"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "změní zadaný klíč nebo soubor s klíčem u zařízení LUKS"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "převede klíč do nových parametrů PBKDF"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<zařízení> <pozice_klíče>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "smaže klíč s číslem <pozice_klíče> ze zařízení LUKS"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "zobrazí UUID zařízení LUKS"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "otestuje <zařízení> na hlavičku oddílu LUKS"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "vypíše údaje o oddílu LUKS"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "vypíše údaje o oddílu TCRYPT"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "vypíše údaje o zařízení BITLK"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "vypíše údaje o zařízení FVAULT2"
+
+# TODO: not consistent with previous line
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Uspí zařízení LUKS a smaže klíč (všechny operace budou zmrazeny)"
+
+# TODO: not consistent with previous line
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "Probudí uspané zařízení LUKS"
+
+# TODO: not consistent with previous line
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Zálohuje hlavičku zařízení LUKS a jeho pozice s klíči"
+
+# TODO: not consistent with previous line
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Obnoví hlavičku zařízení LUKS a jeho pozice s klíči"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <zařízení>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "Zachází s tokeny LUKS2"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<akce> je jedna z:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Rovněž lze použít aliasy se starým zápisem <akce>:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<název> je zařízení, které se má vytvořit v %s\n"
+"<zařízení> je zašifrované zařízení\n"
+"<pozice_klíče> je číslo pozice klíče LUKS, který se má upravit\n"
+"<soubor_s_klíčem> je volitelný soubor s novým klíčem pro akci luksAddKey\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Výchozí zakompilovaný formát metadat (pro akci luksFormat) je %s.\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Podpora pro zásuvný modul externího tokenu LUKS2 je %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "zakompilována"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Cesta k zásuvnému modulu externího tokenu LUKS2: %s.\n"
+
+# Support is %s
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "vypnuta"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Výchozí zakompilované parametry klíče a hesla:\n"
+"\tMaximální velikost souboru s klíčem: %d kB, maximální délka interaktivního hesla %d (znaků)\n"
+"Výchozí PBKDF pro LUKS1: %s, doba opakování: %d (ms)\n"
+"Výchozí PBKDF pro LUKS2: %s\n"
+"\tDoba iterací: %d, nutná paměť: %d kB, souběžná vlákna: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Výchozí zakompilované parametry šifer zařízení:\n"
+"\tloop-AES: %s, Klíč %d bitů\n"
+"\tplain: %s, Klíč: %d bitů, Haš hesla: %s\n"
+"\tLUKS: %s, Klíč: %d bitů, Haš hlavičky LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: V režimu XTS (dva vnitřní klíče) bude výchozí velikost klíče zdvojnásobena.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: vyžaduje %s jako argumenty"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Pozice klíče není platná."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Velikost zařízení musí být násobkem 512bajtových sektorů."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Zadána neplatná maximální velikost horké zóny při přešifrování."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Velikost klíče musí být násobkem 8 bitů."
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Maximální velikost zmenšení zařízení je 1 GiB."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Velikost zmenšení musí být násobkem 512bajtových sektorů."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Přepínač --priority smí mít pouze argument ignore, normal a prefer."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Zobrazí tuto nápovědu"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Zobrazí stručný návod na použití"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Vypíše verzi balíku"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Přepínače nápovědy:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[PŘEPÍNAČ…] <akce> <přepínače_akce>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Chybí argument <akce>."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Neznámá akce."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Přepínač --key-file má přednost před zadaným argumentem souboru s klíčem."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Je dovolen pouze jeden argument přepínače --key-file."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Funkce pro odvození klíče na základě hesla (PBKDF) smí být pouze pbkdf2 nebo argon2i/argon2id."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Vynucené iterace PBKDF nelze kombinovat s volnou doby iterací."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Přepínače --keyslot-cipher a --keyslot-key-size musí být použity spolu."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Žádný úkon nebude proveden. Zavoláno s přepínačem --test-args.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Zamykání metadata nelze vypnout."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Zadán neplatný řetězec se solí."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Nelze vytvořit obraz hašů %s určený k zápisu."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Nelze vytvořit obraz FEC %s určený k zápisu."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Nelze vytvořit soubor %s s kořenovým hašem určený k zápisu."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Do souboru %s s kořenovým hašem nelze zapsat."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Zařízení %s není platným zařízením VERITY."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Soubor %s s kořenovým hašem nelze vytvořit."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Neplatný soubor %s s kořenovým hašem."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "Zadán neplatný řetězec s kořenovým hašem."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Neplatné soubor s podpisem %s."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Soubor s podpisem %s nelze číst."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Příkaz vyžaduje argument <kořenový_haš> nebo přepínač --root-hash-file."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<zařízení_dat> <zařízení_hašů>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "naformátuje zařízení"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<zařízení_dat> <zařízení_hašů> [<kořenový_haš>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "ověří zařízení"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<zařízení_dat> <název> <zařízení_hašů> [<kořenový_haš>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "zobrazí stav aktivního zařízení"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<zařízení_hašů>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "zobrazí údaje z disku"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<název> je zařízení, které bude vytvořeno pod %s\n"
+"<zařízení_dat> je datové zařízení\n"
+"<zařízení_hašů> je zařízení obsahující ověřovací data\n"
+"<kořenový_haš> haš kořenového uzlu na <zařízení_hašů>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Výchozí zakompilované parametry dm-verity:\n"
+"\tHaš: %s, Datový blok (bajty): %u, Blok hašů (bajty): %u, Velikost soli: %u, Formát haše: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Přepínače --ignore-corruption a --restart-on-corruption nelze použít najednou."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Přepínač --panic-on-corruption a --restart-on-corruption nelze použít najednou."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Toto nevratně přepíše data na %s a %s.\n"
+"Pro zachování datového zařízení použije přepínač --no-wipe (a pak jej\n"
+"aktivujte pomocí --integrity-recalculate)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formátováno s velikostí značky %u, vnitřní integrita %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Nastavení příznaku přepočtu není podporováno, místo toho zvažte použití --wipe."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Zařízení %s není platným zařízením INTEGRITY."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<zařízení_s_daty_integrity>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<zařízení_s_daty_integrity> <název>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<název> je zařízení, které bude vytvořeno pod %s\n"
+"<zařízení_s_daty_integrity> je zařízení obsahující data se značkami integrity\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Výchozí zakompilované parametry dm-integrity:\n"
+"\tAlgoritmus kontrolního součtu: %s\n"
+"\tMaximální velikost souboru s klíčem: %d kB\n"
+
+# TODO: Pluralize
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Neplatná velikost --%s. Maximální je %u bajtů."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Musí být zadány oba přepínače pro soubor s klíčem a velikostí klíče."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Musí být zadány oba přepínače pro soubor s klíčem žurnálu a velikostí klíče."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Je-li použit klíč integrity žurnálu, musí být zadán algoritmus integrity žurnálu."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Musí být zadány oba přepínače pro soubor s šifrovacím klíčem žurnálu a velikostí klíče."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Je-li použit šifrovací klíč žurnálu, musí být zadán algoritmus šifrování žurnálu."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Přepínače režimu bitmapy a obnovení se vzájemně vylučují."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Přepínače žurnálu nelze použití spolu s režimem bitmapy."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Přepínače bitmapy lze použít jen při režimu bitmapy."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"POZOR!\n"
+"======\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Jste si jisti? (Napište „yes“ velkými písmeny): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Chyba při čtení odpovědi z terminálu."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Příkaz úspěšně vykonán."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "špatné nebo chybějící parametry"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "žádné oprávnění nebo chybné heslo"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "nedostatek paměti"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "zadáno špatné zařízení nebo soubor"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "zařízení již existuje nebo zařízení je zaneprázdněno"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "neznámá chyba"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Příkaz selhal s kódem %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Pozice klíče %i vytvořena."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Pozice klíče %i odemknuta."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Pozice klíče %i odemknuta."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Token %i vytvořen."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Token %i se odstraněn."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Tímto PIN nebylo možné odemknou žádný token."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Token %i vyžaduje PIN."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Token (druh %s) vyžaduje PIN."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token %i nedokáže odemknout přiřazené pozice s klíči (chybné heslo pozice)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token (druh %s) nedokáže odemknout přiřazené pozice s klíči (chybné heslo pozice)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Token %i vyžaduje dodatečné chybějící zdroje."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Token (druh %s) vyžaduje dodatečné chybějící zdroje."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Žádný token (druhu %s) není dostupný."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Není dostupný žádný použitelný token."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Soubor s klíčem %s nelze číst."
+
+# FIXME: Pluralize
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Ze souboru s klíčem %2$s nelze přečíst %1$d bajtů."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Soubor s klíčem %s nelze otevřít pro zápis."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Do souboru s klíčem %s nelze zapsat."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64> m %02<PRIu64> s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64> h %02<PRIu64> m %02<PRIu64> s"
+
+# TODO: Pluralize
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> dnů"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "zapsáno %4<PRIu64> %s"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "rychlost %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Průběh: %5.1f %%, zbývá %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Dokončeno, čas %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Odolnost hesla nelze prověřit: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Kontrola odolnosti hesla selhala:\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Kontrola odolnosti hesla selhala: Špatné heslo (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "Chyba při čtení hesla z terminálu."
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "Ověřte heslo: "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "Hesla se neshodují."
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "Ve vstupu z terminálu nelze měnit polohu."
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Zadejte heslo: "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Zadejte heslo pro %s: "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "S tímto heslem není dostupný žádný klíč."
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "Nejsou dostupné žádné použitelné pozice s klíči."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Se vstupem mimo terminál nelze ověřit heslo."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Soubor %s se nepodařilo otevřít pouze pro čtení."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Poskytněte JSON s platným tokenem LUKS2:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Soubor s dokumentem JSON se nepodařilo přečíst."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Čtení přerušeno."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Otevření souboru %s pro zápis selhalo."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Zápis přerušen."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Zapsaní souboru s dokumentem JSON selhalo."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Automaticky nalezené aktivní zařízení DM „%s“ pro datové zařízení %s.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Držitele zařízení %s nebylo možné automaticky nalézt."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Zařízení %s není blokovým zařízením.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Nelze rozhodnout, jestli zařízení %s je nebo není aktivováno.\n"
+"Jste si jisti, že si přejete pokračovat v přešifrování v režimu offline?\n"
+"To může vést k poškození dat, bylo-li zařízení ve skutečnosti aktivováno.\n"
+"Pro přešifrování za běhu použijte parametr --active-name.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Zařízení %s není blokovým zařízením. Nelze určit, jestli je\n"
+"aktivní, nebo ne. Pro obejití kontroly a spuštění v režimu offline\n"
+"(nebezpečné!) použijte --force-offline-reencrypt."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Na současnou operaci přešifrování nelze použít požadovaný přepínač --resilience."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Zařízení není ve stavu přešifrování LUKS2. Neslučitelný přepínač --encrypt."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Zařízení není ve stavu dešifrování LUKS2. Neslučitelný přepínač --decrypt."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Zařízení je ve stavu přešifrování pomocí odolnosti posunu dat. Požadovaný přepínač --resilience nelze použít."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Zařízení vyžaduje obnovu přešifrování. Spusťte nejprve opravu."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Zařízení %s je již ve stavu přešifrování LUKS2. Přejete si dokončit dříve zahájenou operaci?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Zastaralé přešifrování LUKS2 již není podporováno."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Přešifrování zařízení s profilem integrity není podporováno."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Požadovaný --sector-size %<PRIu32> není slučitelný se superblokem %s\n"
+"(velikost bloku %<PRIu32> bajtů) nalezeném na zařízení %s."
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Přešifrování bez oddělené hlavičky (--header) není možné bez zmenšení velikosti datového zařízení (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Požadovaný počátek dat musí být menší nebo roven polovině parametru --reduce-device-size"
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Upravuje se hodnota --reduce-device-size na dvojnásobek --offset %<PRIu64> (v sektorech).\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Dočasný soubor s hlavičkou %s již existuje. Operace se ruší."
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Dočasný soubor s hlavičkou %s nelze vytvořit."
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Velikost metadat LUKS2 je větší než hodnota posunu dat."
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Umístění nové hlavičky na začátek zařízení %s selhalo."
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s je nyní aktivní a připraveno pro přešifrování za běhu.\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Aktivní zařízení %s není LUKS2."
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "Obnovuje se původní hlavička LUKS2."
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "Obnovení původní hlavičky LUKS2 selhalo."
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Soubor s hlavičkou %s neexistuje. Přejete si zahájit dešifrování LUKS2 zařízení %s a export hlavičku LUKS2 do souboru %s?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Přidání práv na čtení/zápis souboru s hlavičkou selhalo."
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Inicializace přešifrování selhala. Záloha hlavičky je dostupná v %s."
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "Dešifrování LUKS2 je podporováno jen u zařízení s oddělenou hlavičkou (počátek dat na 0)."
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "Nedostatek pozic s klíči pro přešifrování."
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Soubor s klíčem lze použít jen s přepínačem --key-slot nebo s právě jednou aktivní pozicí klíče."
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Zadejte heslo pro pozici klíče %d: "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Zadejte heslo pro pozici klíče %u: "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Přepíná se algoritmus šifrování dat na %s.\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Žádné parametry oblasti s daty nebyly změněny. Přešifrování zrušeno."
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Zvětšení velikosti šifrovaného sektoru na zařízení v režimu offline není\n"
+"podporováno. Nejprve zařízení aktivujte, nebo použijte přepínač\n"
+"--force-offline-reencrypt (nebezpečné!)."
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Přešifrování přerušeno."
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Dokončuje se přešifrování LUKS ve vynuceném režimu offline.\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Zařízení %s obsahuje porušená metadata LUKS. Operace se ruší."
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Zařízení %s je již zařízením LUKS. Operace se ruší."
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Zařízení %s je již ve stavu přešifrování LUKS. Operace se ruší."
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "Dešifrování LUKS2 vyžaduje přepínač --header."
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "Příkaz vyžaduje jako argument zařízení."
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Neslučitelné verze. Zařízení %s je LUKS1."
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Neslučitelné verze. Zařízení %s je ve stavu přešifrování LUKS1."
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Neslučitelné verze. Zařízení %s je LUKS2."
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Neslučitelné verze. Zařízení %s je ve stavu přešifrování LUKS2."
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Přešifrování LUKS2 je již inicializováno. Operace se ruší."
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "Neprobíhá žádné přešifrování zařízení."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Zařízení %s nelze výlučně otevřít. Zařízení se používá."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Alokace zarovnané paměti se nezdařila."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Ze zařízení %s nelze číst."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "LUKS1 zařízení %s se označuje za nepoužitelné."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Zařízení %s není možné zapsat."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Nelze zapsat soubor s protokolem přešifrování."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Soubor s protokolem přešifrování nelze načíst."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Chybný formát protokolu."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Soubor s protokolem %s existuje, pokračuje se v přerušeném přešifrování.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Aktivuje se dočasné zařízení za pomoci staré hlavičky LUKS."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Aktivuje se dočasné zařízení za pomoci nové hlavičky LUKS."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Aktivace dočasných zařízení selhala."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Nastavení polohy dat selhalo."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Nastavení velikosti metadat selhalo."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Byla vytvořena nová hlavička LUKS zařízení %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Záloha hlavičky %s zařízení %s byla vytvořena."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Záložní hlavičky LUKS se nepodařilo vytvořit."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Hlavičku %s na zařízení %s nelze obnovit."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Hlavička %s na zařízení %s byla obnovena."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Nelze otevřít dočasné zařízení LUKS."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Velikost zařízení nelze zjistit."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "Chyba vstupu/výstupu během přešifrování."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Poskytnuté UUID není platné."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Nelze otevřít soubor s protokolem přešifrování."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Žádné dešifrování není rozpracované. Poskytnuté UUID lze použít jen k dokončení pozastaveného procesu dešifrování."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Přešifrování změní: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "klíč svazku"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "nastaví haš na "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", nastaví šifru na "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "POZOR: Zařízení %s již obsahuje vzorec oddílu „%s“.\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "POZOR: Zařízení %s již obsahuje vzorec superbloku „%s“.\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Sondu vzorců zařízení se nepodařilo inicializovat."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "O zařízení %s nebylo možné zjistit údaje."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Soubor %s nebylo možné otevřít pro čtení i zápis."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Existující vzorec oddílu „%s“ na zařízení %s bude vymazán."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Existující vzorec superbloku „%s“ na zařízení %s bude vymazán."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Odstranění vzorce ze zařízení selhalo."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Otestování zařízení %s na vzorce selhalo."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Zadána neplatná velikost v parametru --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Přepínač --%s není dovolen s akcí %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Zapsaní dokumentu JSON pro token SSH selhalo."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Pokusný modul do cryptsetupu pro odemykání zařízení LUKS2 pomocí tokenu připojeného k serveru SSH\vV současnosti tento modul umožňuje pouze přidání tokenu k existující pozici s klíčem.\n"
+"\n"
+"Zadaný SSH server musí obsahovat na zadané cestě soubor s heslem pro existující pozici klíče v zařízení.\n"
+"Zadané přihlašovací údaje použije cryptsetup pro získání hesla, až bude otevírat zařízení pomocí tokenu.\n"
+"\n"
+"Poznámka: Údaje poskytnuté při přidávání tokenu (adresa SSH serveru, uživatel a cesta) budou uloženy do hlavičky LUKS2 v nešifrované podobě."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<akce> <zařízení>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Přepínače pro akci „add“:"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "IP adresa / URL vzdáleného serveru pro tento token"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Uživatelské jméno ke vzdálenému serveru"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Cesta k souboru s klíčem na vzdáleném serveru"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Cesta ke klíči SSH pro připojení ke vzdálenému serveru"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Pozice klíče, ke které se má přiřadit token. Nebude-li určeno, token bude přiřazen k první pozici odpovídající poskytnutému heslu."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Obecné přepínače:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Zobrazuje podrobnější chybové hlášky"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Zobrazuje ladicí hlášky"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Zobrazuje ladicí hlášky včetně metadat JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Otevření a import soukromého klíče selhalo:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Import soukromého klíče selhal (chráněný heslem?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Heslo pro %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Rozbor argumentů selhal.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Je třeba zadat akci\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Pro akci „%s“ je třeba zadat zařízení.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Pro akci „%s“ je třeba zadat SSH server.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Pro akci „%s“ je třeba zadat uživatele SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Pro akci „%s“ je třeba zadat SSH cestu.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Pro akci „%s“ je třeba zadat cestu ke klíči SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Otevření %s pomocí zadaných přihlašovacích údajů selhalo.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "V současnosti je tímto modulem podporována pouze akce „add“.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Relaci SFTP nelze sestavit: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Relaci SFTP nelze inicializovat: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Relaci SFTP nelze otevřít: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Údaje o SFTP souboru nelze získat: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Nedostatek paměti.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Vzdálený klíč nelze přečíst: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Spojení selhalo: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Server není znám: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Na stroji není povolena autentizace veřejným klíčem.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Chyba při autentizaci veřejným klíčem: "
+
+#~ msgid "WARNING: Data offset is outside of currently available data device.\n"
+#~ msgstr "POZOR: Poloha dat je mimo nyní dostupné zařízení s daty.\n"
+
+#~ msgid "Cannot get process priority."
+#~ msgstr "Nelze zjistit prioritu procesu."
+
+#~ msgid "Cannot unlock memory."
+#~ msgstr "Paměť nelze odemknout."
+
+#~ msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+#~ msgstr "Zamykací adresář %s/%s bude vytvořen s výchozími zakompilovanými právy."
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Z %s nebylo možné načíst vzorec BITLK."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Neplatná nebo neznámá značka zařízení BITLK."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Vyčištění dat záložní části selhalo."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Vypnutí příznaku požadavku na přešifrování selhalo."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Šifrování je podporováno jen s formátem LUKS2."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "Na %s zjištěno zařízeno LUKS. Přejete si toto zařízení LUKS znovu zašifrovat?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "Nyní je podporován pouze formát LUKS2. Pro LUKS1, prosím, použijte nástroj cryptsetup-reencrypt."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Zastaralé offline přešifrování již probíhá. Použijte nástroj cryptsetup-reencrypt."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "Zařízení LUKS2 se nepřešifrovává."
+
+#~ msgid "Reencryption already in-progress."
+#~ msgstr "Přešifrování již probíhá."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "Na zařízení %s se nastavuje příznak offline přešifrování."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Tato verze cryptsetup-reencrypt neumí zacházet s novým vnitřním druhem tokenů %s."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Přečtení příznaků pro aktivaci ze záložní hlavičky selhalo."
+
+#~ msgid "Failed to write activation flags to new header."
+#~ msgstr "Zápis příznaků pro aktivaci do nové hlavičky selhal."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "Parametry PBKDF pro pozici klíče %i změněny."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Velikost bloku při přešifrování může nabývat hodnot pouze mezi 1 a 64 MiB."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "Maximální velikost zmenšení zařízení je 64 MiB."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[PŘEPÍNAČ…] <zařízení>"
+
+#~ msgid "Argument required."
+#~ msgstr "Vyžadován argument."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "Přepínač --new musí být použit spolu s --reduce-device-size nebo --header."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "Přepínač --keep-key lze použít jen s přepínači --hash, --iter-time nebo --pbkdf-force-iterations."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "Přepínač --new nelze být použit spolu s --decrypt."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "Přepínač --decrypt se neslučuje se zadanými parametry."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "Přepínač --uuid lze použít jen spolu s přepínačem --decrypt."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Neplatný druh LUKS. Použijte jeden z: „luks“, „luks1“ nebo „luks2“"
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Zařízení %s se používá. K formátování nelze přikročit."
+
+#~ msgid "No free token slot."
+#~ msgstr "Žádná volná pozice s tokenem"
+
+#~ msgid "Failed to create builtin token %s."
+#~ msgstr "Vestavěný token %s nebylo možné vytvořit"
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Neplatný druh zařízení LUKS."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Šifra použita k zašifrování disku (vizte /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Haš použit k vytvoření šifrovacího klíče z hesla"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Ověřuje heslo dvojitým dotazem"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Klíč načte ze souboru"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "(Hlavní) klíč svazku načte ze souboru."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Vypíše (hlavní) klíč svazku namísto údajů o pozicích klíčů"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Velikost šifrovacího klíče"
+
+#~ msgid "BITS"
+#~ msgstr "BITY"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Omezí čtení ze souboru s klíčem"
+
+#~ msgid "bytes"
+#~ msgstr "bajty"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Přeskočí daný počet bajtů na začátku souboru s klíčem"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Omezí čtení z nově přidaného souboru s klíčem"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Přeskočí daný počet bajtů na začátku nově přidaného souboru s klíčem"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Číslo pozice pro nový klíč (výchozí je první volná)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Velikost zařízení"
+
+#~ msgid "SECTORS"
+#~ msgstr "SEKTORY"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Použije zadanou velikost zařízení (ignoruje zbytek zařízení). NEBEZPEČNÉ!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Poloha začátku dat v podkladovém zařízení"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Kolik sektorů šifrovaných dat se má na začátku přeskočit"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Vytvoří mapování určené jen pro čtení"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Nevyžaduje potvrzení"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Časový limit pro interaktivní dotaz na heslo (v sekundách)"
+
+#~ msgid "secs"
+#~ msgstr "sekundy"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Aktualizace ukazatele postupu (v sekundách)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Kolikrát se lze zeptat na heslo"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Zarovnává data na hranici <n> sektorů – pro luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Soubor se zálohou hlavičky LUKS a pozic s klíči"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Pro vytvoření klíče svazku použije /dev/random"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Pro vytvoření klíče svazku použije /dev/urandom"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Zařízení sdílí s jiným nepřekrývajícím se šifrovaným segmentem"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "Použije zařízení s UUID"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Povolí u daného zařízení požadavky na zahození (TRIM)"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Zařízení nebo soubor s oddělenou hlavičkou LUKS"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Zařízení neaktivuje, jen zkontroluje heslo"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Použije se skrytá hlavička (skryté zařízení TCRYPT)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Zařízení je systémová jednotka TCRYPT (se zavaděčem)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Použije se záložní (druhá) hlavička TCRYPT"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Hledá také zařízení kompatibilní s VeraCrypt"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Osobní iterační činitel (PIM) pro zařízení kompatibilní s VeraCrypt"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Zeptá se na Osobní iterační činitel pro zařízení kompatibilní s VeraCrypt"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Druh metadat zařízení: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Vypne kontrolku odolnosti hesla (byla-li zapnuta)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Použije výkonnostně kompatibilní přepínač dmcryptu same_cpu_crypt"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Použije výkonnostně kompatibilní přepínač dmcryptu submit_from_crypt_cpus"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Přeskočit pracovní frontu dm-cryptu a zpracovávat požadavky na čtení synchronně"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Přeskočit pracovní frontu dm-cryptu a zpracovávat požadavky na zápis synchronně"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "Odstranění zařízení se odloží, dokud jej poslední uživatel neuzavře"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Pro serializaci paměti těžkého PBKDF použije globální zámek (obezlička při nedostatku paměti)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "Doba opakování PBKDF pro LUKS (v ms)"
+
+#~ msgid "msecs"
+#~ msgstr "milisekundy"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "Algoritmus PBKDF (pro LUKS2): argon2i, argon2id, pbkdf2"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "omezení paměťové náročnosti PBKDF"
+
+#~ msgid "kilobytes"
+#~ msgstr "kilobajty"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "náročnost paralelizace PBKDF"
+
+#~ msgid "threads"
+#~ msgstr "vlákna"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "náročnost iterací PBKDF (vynuceno, vypne test složitosti)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Priorita pozice klíče: ignore [ignorovat], normal [normální], prefer [upřednostnit]"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Vypne zamykání metadata uložených na disku"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Vypne načítání klíčů svazků přes jadernou klíčenku"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Algoritmus pro integritu dat (pouze LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Vypne žurnál pro zařízení s integritou"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Po formátu nevymazat zařízení"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Použije neefektivní zastaralé vyplňování (stará jádra)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Neptá se na heslo, když aktivace tokenem selže"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Číslo tokenu (výchozí cokoliv)"
+
+#~ msgid "Key description"
+#~ msgstr "Popis klíče"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Velikost sektoru šifrování (výchozí: 512 bajtů)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Inicializační vektor počítá ve velikostech sektoru (nikoliv po 512 bajtech)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Nastaví trvalé příznaky pro aktivaci zařízení"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Nastaví jmenovku zařízení LUKS2"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Nastaví jmenovku podsystému zařízení LUKS2"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Vytvoří nebo vypíše nepřiřazenou (žádný datový segment nepřiřazen) LUKS2 pozici s klíčem"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Načte nebo zapíše JSON z nebo do souboru"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Velikost oblasti s metadaty hlavičky LUKS2"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Velikost oblasti s pozicemi klíčů hlavičky LUKS"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Reaktivuje zařízení s novými parametry"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "Pozice s klíčem LUKS2: Velikost šifrovacího klíče"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "Pozice s klíčem LUKS2: Šifra použitá pro šifrování pozice s klíčem"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Zašifruje zařízení LUKS2 (šifrování bez mezikopie)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Natrvalo dešifruje zařízení LUKS2 (odstraní šifrování)."
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Inicializuje přešifrování LUKS2 pouze v metadatech."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Pouze dokončí již inicializované přešifrování LUKS2."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Zmenší velikost datového zařízení (posune začátek dat). NEBEZPEČNÉ!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Maximální velikost horké zóny při přešifrování."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Druh odolnosti horké zóny při přešifrování (checksum [kontrolní součet], journal [žurnál], none [žádná])"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Algoritmus kontrolního součtu při přešifrování"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Přebije automatické hledání zařízení DM pro přešifrování"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "Přepínač --deferred je dovolen jen při příkazu zavření."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "Přepínač --allow-discards je dovolen jen při úkonu otevírání."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "Přepínač --persistent je dovolen jen při úkonu otevírání."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "Přepínač --serialize-memory-hard-pbkdf je dovolen jen při úkonu otevírání."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Přepínač --key-size je dovolen jen pro akce luksFormat, luksAddKey,\n"
+#~ "open a benchmark. Čtení ze souboru s klíčem lze omezit\n"
+#~ "pomocí --keyfile-size=(bajty)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "Přepínač --integrity je dovolen pouze u luksFormat (LUKS2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Přepínače --label a --subsystem jsou dovoleny jen při úkonech luksFormat a config s LUKS2."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "U přepínače není záporné číslo dovoleno."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "Přepínač --use-[u]random je dovolen pouze u luksFormat."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "Přepínač --uuid je dovolen pouze u luksFormat a luksUUID."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "Přepínač --align-payload je dovolen pouze u luksFormat."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Přepínače --luks2-metadata-size a --opt-luks2-keyslots-size jsou dovoleny jen při úkonu luksFormat s LUKS2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Zadána neplatná velikost metadat LUKS2."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Zadána neplatná velikost pozic s klíči LUKS2."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "Přepínač --offset je podporován jen při otevírání zařízení plain a loopaes a při úkonu luksFormat a přešifrování."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Zadán neplatný argument parametru --veracrypt-pim."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "Tento příkaz nepodporuje volbu velikosti sektoru."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "Přepínač --refresh lze použít pouze s úkonem otevření."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "Zadána neplatná velikost zařízení."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Velikost ke zmenšení přetekla."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Nepoužije superblok verity"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Druh formátu (1 – běžný, 0 – původní z OS Chrome)"
+
+#~ msgid "number"
+#~ msgstr "číslo"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Velikost bloku na zařízení dat"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Velikost bloku na zařízení hašů"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "Paritní bajty FEC"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Počet bloků v datovém souboru"
+
+#~ msgid "blocks"
+#~ msgstr "bloky"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Cesta k zařízení s daty pro opravu chyb"
+
+#~ msgid "path"
+#~ msgstr "cesta"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Poloha začátku dat v zařízení hašů"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Poloha začátku dat v zařízení FEC"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Hašovací algoritmus"
+
+#~ msgid "string"
+#~ msgstr "řetězec"
+
+#~ msgid "Salt"
+#~ msgstr "Sůl"
+
+#~ msgid "hex string"
+#~ msgstr "šestnáctkový řetězec"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Cesta k souboru s podpisem kořenového otisku"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Restartuje jádro, pokud je zjištěno poškození"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Jádro zpanikaří, pokud je zjištěno poškození"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Ignoruje poškození, pouze jej zaznamená"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Neověřuje vynulované bloky"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Ověří datový blok pouze při prvním čtení"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Přepínače --ignore-corruption, --restart-on-corruption nebo --ignore-zero-blocks jsou dovoleny jen při úkonu otevírání."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "Přepínač --root-hash-signature smí být použit jen při otevírání."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Cesta k zařízení s daty (je-li odděleno)"
+
+#~ msgid "Journal size"
+#~ msgstr "Velikost žurnálu"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Prokládat sektory"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Zaplněnost žurnálu"
+
+#~ msgid "percent"
+#~ msgstr "procenta"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Perioda vyprazdňování žurnálu"
+
+#~ msgid "ms"
+#~ msgstr "ms"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Počet 512bajtových sektorů na bit (režim bitmapy)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Perioda vyprazdňování při režimu bitmapy"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Velikost značky (na sektor)"
+
+#~ msgid "Sector size"
+#~ msgstr "Velikost sektoru"
+
+#~ msgid "Buffers size"
+#~ msgstr "Velikost vyrovnávací paměti"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Algoritmus pro kontrolu integrity dat"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Velikost klíče pro integritu dat"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Klíč pro integritu načte ze souboru"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Algoritmus pro integritu žurnálu"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Velikost klíče integrity žurnálu"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Klíč integrity žurnálu načte ze souboru"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Algoritmus šifrování žurnálu"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Velikost šifrovacího klíče žurnálu"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Šifrovací klíč žurnálu načte ze souboru"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Režim obnovy (žádný žurnál, žádná kontrola značek)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Ke sledování změn použije bitmapu a vypne žurnál pro zařízení s integritou"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Automaticky přepočítá počáteční značky."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Nechrání superblok pomocí HMAC (stará jádra)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Povolí přepočet svazků s klíči HMAC (stará jádra)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "Přepínač --integrity-recalculate smí být použit jen při otevírání."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Přepínače --journal-size, --interleave-sectors, --sector-size, --tag-size a --no-wipe lze použít jen při formátování."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "Zadána neplatná velikost žurnálu."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Velikost bloku přešifrování"
+
+#~ msgid "MiB"
+#~ msgstr "MiB"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Nezmění klíč, oblast s daty se nepřešifruje"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Nový (hlavní) klíč svazku načte ze souboru"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "K zařízením se bude přistupovat pomocí přímého I/O"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Po každém bloku se zavolá fsync"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Po každém bloku se aktualizuje soubor s protokolem"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Použije se pouze tato pozice (ostatní budou zakázány)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Vytvoří novou hlavičku na nešifrovaném zařízení"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Natrvalo dešifruje zařízení (odstraní šifrování)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "UUID, které se použije pro dokončení dešifrování"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Druh metadat LUKS: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "POZOR: Adresář se zámkem %s/%s chybí!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Neplatné parametry velikosti pro zařízení VERITY."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "Je-li použit klíč integrity, musí být zadán algoritmus integrity."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Špatná velikost klíče."
+
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands."
+#~ msgstr "Přepínač --refresh je dovolen jen při příkazu otevření nebo reaktivace."
+
+#~ msgid "Unsupported encryption sector size.\n"
+#~ msgstr "Nepodporovaná velikost šifrovaného sektoru.\n"
+
+#~ msgid "Offline reencryption in progress. Aborting."
+#~ msgstr "Probíhá offline přešifrování. Operace se ruší."
+
+#~ msgid "Online reencryption in progress. Aborting."
+#~ msgstr "Probíhá přešifrování za běhu. Operace se ruší."
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Přerušeno signálem."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "V režimu FIPS není funkce dostupná."
+
+#~ msgid "Failed to finalize hash."
+#~ msgstr "Dokončení otisku selhalo."
+
+#~ msgid "Invalid resilience parameters (internal error)."
+#~ msgstr "Neplatné parametry odolnosti (vnitřní chyba)."
+
+#~ msgid "Failed to assign new enc segments."
+#~ msgstr "Přiřazení nových částí k šifrování se nezdařilo."
+
+#~ msgid "Failed to assign digest %u to segment %u."
+#~ msgstr "Přiřazení otisku %u k části %u se nezdařilo."
+
+#~ msgid "Failed to assign reencrypt previous backup segment."
+#~ msgstr "Přiřazení předchozí zálohové části při přešifrování selhalo."
+
+#~ msgid "Failed to assign reencrypt final backup segment."
+#~ msgstr "Přiřazení poslední zálohové části při přešifrování selhalo."
+
+#~ msgid "Failed generate 2nd segment."
+#~ msgstr "Vytvoření druhé části selhalo."
+
+#~ msgid "Failed generate 1st segment."
+#~ msgstr "Vytvoření první části selhalo."
+
+#~ msgid "Failed to allocate device %s."
+#~ msgstr "Alokace zařízení %s selhala."
+
+#~ msgid "Failed to allocate dm segments."
+#~ msgstr "Alokace částí DM selhalo."
+
+#~ msgid "Failed to create dm segments."
+#~ msgstr "Vytvoření částí DM selhalo."
+
+#~ msgid "Failed to allocate device for new backing device."
+#~ msgstr "Alokace zařízení pro nové podpůrné zařízení selhalo."
+
+#~ msgid "Failed to reload overlay device %s."
+#~ msgstr "Znovuzavedení překryvného zařízení %s selhalo."
+
+#~ msgid "Failed to refresh helper devices."
+#~ msgstr "Obnovení pomocných zařízení selhalo."
+
+#~ msgid "Failed to create reencryption backup segments."
+#~ msgstr "Vytvoření záložních částí při přešifrování selhalo."
+
+#~ msgid "Failed to set online-reencryption requirement."
+#~ msgstr "Nastavení požadavků na přešifrování za běhu selhalo."
+
+#~ msgid "Failed to hash sector at offset %zu."
+#~ msgstr "Vypočtení otisku sektoru na pozici %zu selhalo."
+
+#~ msgid "Failed to read sector hash."
+#~ msgstr "Načtení otisku sektoru selhalo."
+
+#~ msgid "Error: Calculated reencryption offset %<PRIu64> is beyond device size %<PRIu64>."
+#~ msgstr "Chyba: Vypočtená pozice pro přešifrování %<PRIu64> je větší než velikost zařízení %<PRIu64>."
+
+#~ msgid "Failed to calculate new segments."
+#~ msgstr "Výpočet nových částí selhal."
+
+#~ msgid "Failed finalize hotzone resilience, retval = %d"
+#~ msgstr "Dokončení odolnosti horké zóny selhalo, návratová hodnota = %d"
+
+#~ msgid "Failed to write data."
+#~ msgstr "Zápis dat selhal."
+
+#~ msgid "Failed to update metadata or reassign device segments."
+#~ msgstr "Aktualizace metadat nebo opětovné přiřazení částí zařízení selhalo."
+
+#~ msgid "Failed to reload %s device."
+#~ msgstr "Opětovné zavedení zařízení %s selhalo."
+
+#~ msgid "Failed to erase backup segments"
+#~ msgstr "Výmaz záložních částí selhal"
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Požadované výkonnostní volby dmcryptu nejsou podporovány."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "Zařízení %s, které se stále používá, nelze formátovat."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "Pozice klíče %d není použita."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "Ke smazání vybrán klíč na pozici %d."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "otevře zařízení jako mapování <název>"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "zavře zařízení (deaktivuje a odstraní mapování)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "Nastavení parametrů PBKDF selhalo."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "Nelze se přesunout na požadované místo v zařízení.\n"
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Zařízení %s je příliš malé. (LUKS2 vyžaduje alespoň %<PRIu64> bajtů.)"
+
+#~ msgid "Replaced with key slot %d."
+#~ msgstr "Nahrazeno pozicí klíče %d."
+
+#~ msgid "Missing LUKS target type, option --type is required."
+#~ msgstr "Chybí druh cíle LUKS, je potřeba přepínač --type."
+
+#~ msgid "Missing --token option specifying token for removal."
+#~ msgstr "Chybí přepínač --token určující token, který se má odebrat."
+
+#~ msgid "Add or remove keyring token"
+#~ msgstr "Přidá nebo odebere token klíčenky"
+
+#~ msgid "Activated keyslot %i."
+#~ msgstr "Pozice klíče %i aktivována."
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "chyba alokace paměti v action_luksFormat"
+
+#~ msgid "Key slot is invalid.\n"
+#~ msgstr "Pozice klíče není platná.\n"
+
+#~ msgid "Using default pbkdf parameters for new LUKS2 header.\n"
+#~ msgstr "Pro novou hlavičku LUKS2 se použije výchozí parametry PBKDF.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Příliš mnoho úrovní stromu ve svazku VERITY.\n"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "Klíč %d není aktivní. Nelze jej odstranit.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<název> <zařízení_dat> <zařízení_hašů> <kořenový_haš>"
+
+#~ msgid "create active device"
+#~ msgstr "vytvoří aktivní zařízení"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "odstraní (deaktivuje) zařízení"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Průběh: %5.1f %%, ETA %02llu:%02llu, zapsáno %'4llu MiB, rychlost %'5.1f MiB/s%s"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Nelze najít volné zařízení zpětné smyčky.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Zařízení %s nelze otevřít\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Dokud probíhá dešifrování, předaný UUID nelze použít.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "LUKS zařízení %s se označuje za použitelné.\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "POZOR: toto je pokusný kód, může zničit vaše data.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "Ověření kontrolního součtu FIPS selhalo.\n"
+
+#~ msgid "WARNING: device %s is a partition, for TCRYPT system encryption you usually need to use whole block device path.\n"
+#~ msgstr "POZOR: zařízení %s je oddíl. U systémového šifrování TCRYPT je obvykle třeba použít cestu k celému blokovému zařízení.\n"
+
+#~ msgid "Enter LUKS passphrase: "
+#~ msgstr "Zadejte heslo LUKS: "
+
+#~ msgid "Enter new LUKS passphrase: "
+#~ msgstr "Zadejte nové heslo LUKS: "
+
+#~ msgid "Enter any LUKS passphrase: "
+#~ msgstr "Zadejte jakékoliv heslo LUKS: "
+
+#~ msgid "Backup file %s doesn't exist.\n"
+#~ msgstr "Záložní soubor %s neexistuje.\n"
+
+#~ msgid "create device"
+#~ msgstr "vytvoří zařízení"
+
+#~ msgid "remove device"
+#~ msgstr "odstraní zařízení"
+
+#~ msgid "remove LUKS mapping"
+#~ msgstr "odstraní mapování LUKS"
+
+#~ msgid "open loop-AES device as mapping <name>"
+#~ msgstr "otevře zařízení loop-AES jako mapování <název>"
+
+#~ msgid "remove loop-AES mapping"
+#~ msgstr "odstraní mapování loop-AES"
+
+#~ msgid "Cannot open device %s for %s%s access.\n"
+#~ msgstr "Zařízení %s nelze otevřít pro %s%s přístup.\n"
+
+#~ msgid "exclusive "
+#~ msgstr "výlučný "
+
+#~ msgid "read-only"
+#~ msgstr "jen pro čtení"
+
+#~ msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+#~ msgstr "POZOR!!! Zřejmě nezabezpečená paměť. Jste root?\n"
+
+#~ msgid "Unable to obtain sector size for %s"
+#~ msgstr "Není možné zjistit velikost sektoru u %s"
+
+#~ msgid "Cannot use device %s (crypt segments overlaps or in use by another device).\n"
+#~ msgstr "Zařízení %s nelze použít (šifrované segmenty se překrývají nebo jsou používány jiným zařízením).\n"
+
+#~ msgid "Key slot %d verified.\n"
+#~ msgstr "Pozice klíče %d ověřena.\n"
+
+#~ msgid "Block mode XTS is available since kernel 2.6.24.\n"
+#~ msgstr "Blokový režim XTS je dostupný až od jádra 2.6.24.\n"
+
+#~ msgid "Key size in LRW mode must be 256 or 512 bits.\n"
+#~ msgstr "V režimu LRW musí být velikost klíče 256 nebo 512 bitů.\n"
+
+#~ msgid "Block mode LRW is available since kernel 2.6.20.\n"
+#~ msgstr "Blokový režim LRW je dostupný až od jádra 2.6.20.\n"
+
+#~ msgid "Negative keyfile size not permitted.\n"
+#~ msgstr "Záporná velikost souboru s klíčen není dovolena.\n"
+
+#~ msgid "Warning: exhausting read requested, but key file is not a regular file, function might never return.\n"
+#~ msgstr "Pozor: požadováno úplné čtení, avšak soubor s klíčem není běžný soubor. Funkce se možná nikdy nevrátí.\n"
diff --git a/po/da.po b/po/da.po
new file mode 100644
index 0000000..6858311
--- /dev/null
+++ b/po/da.po
@@ -0,0 +1,3893 @@
+# Danish translation cryptsetup-2.3.1.da.po.
+# Copyright (C) 2020 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Joe Hansen <joedalton2@yahoo.dk>, 2015, 2016, 2017, 2018, 2019, 2020.
+#
+# Konventioner
+# argument -> argument
+# deferred -> udskudt
+# iteration -> iteration (gennemløb)
+# memory hard -> hukommelsestung (bedre mulighed?) det er nok et tilvalg, så
+# evt. bevar den uændret. nok engelsk fejl hvor det er uden bindestreg.
+# parameter -> parameter
+# probe -> undersøge (bedre mulighed?)
+# reencryption -> omkryptering
+# suspended -> suspenderet (skal det være standset i stedet for?)
+# wipe -> rydde
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup-2.3.1-rc0\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2020-03-08 10:59+0100\n"
+"PO-Revision-Date: 2020-03-08 22:35+0200\n"
+"Last-Translator: Joe Hansen <joedalton2@yahoo.dk>\n"
+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/libdevmapper.c:396
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Kan ikke initialisere enhedsoversætter, kører som ikke-root bruger."
+
+#: lib/libdevmapper.c:399
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Kan ikke initialisere enhedsoversætter. Er dm_mod-kernemodulet indlæst?"
+
+#: lib/libdevmapper.c:1119
+msgid "Requested deferred flag is not supported."
+msgstr "Det anmodede udskudte flag er ikke understøttet."
+
+#: lib/libdevmapper.c:1186
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID for enheden %s blev afkortet."
+
+#: lib/libdevmapper.c:1508
+msgid "Unknown dm target type."
+msgstr "Ukendt dm-måltype."
+
+#: lib/libdevmapper.c:1611 lib/libdevmapper.c:1663
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Forespurgte dm-crypt-ydelsestilvalg er ikke understøttede."
+
+#: lib/libdevmapper.c:1618
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Forespurgte dm-verity-håndteringstilvalg for datakorruption er ikke understøttede."
+
+#: lib/libdevmapper.c:1622
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Forespurgte dm-verity FEC-tilvalg er ikke understøttede."
+
+#: lib/libdevmapper.c:1626
+msgid "Requested data integrity options are not supported."
+msgstr "Forespurgte dataintegritetstilvalg er ikke understøttede."
+
+#: lib/libdevmapper.c:1628
+msgid "Requested sector_size option is not supported."
+msgstr "Forespurgte sector_size-tilvalg er ikke understøttet."
+
+#: lib/libdevmapper.c:1633
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Forespurgte automatiske genberegning af integritetsmærker er ikke understøttet."
+
+#: lib/libdevmapper.c:1637
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Forespurgte dm-integritetsbitmaptilstand er ikke understøttet."
+
+#: lib/libdevmapper.c:1666
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM %s er ikke understøttet."
+
+#: lib/libdevmapper.c:2584
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Kunne ikke forespørge dm-%s-segment."
+
+#: lib/random.c:75
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Systemet har ikke nok entropi til oprettelse af diskenhedsnøgle.\n"
+"Flyt venligst musen eller indtast noget tekst i et andet vindue for at samle nogle vilkårlige hændelser.\n"
+
+#: lib/random.c:79
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Opretter nøgle (%d%% færdig).\n"
+
+#: lib/random.c:165
+msgid "Running in FIPS mode."
+msgstr "Kører i FIPS-tilstand."
+
+#: lib/random.c:171
+msgid "Fatal error during RNG initialisation."
+msgstr "Fatal fejl under RNG-initialisering."
+
+#: lib/random.c:208
+msgid "Unknown RNG quality requested."
+msgstr "Der blev anmodt om ukendt RNG-kvalitet."
+
+#: lib/random.c:213
+msgid "Error reading from RNG."
+msgstr "Der opstod en fejl under læsning fra RNG."
+
+#: lib/setup.c:229
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Kan ikke initialisere crypto RNG-motor."
+
+#: lib/setup.c:235
+msgid "Cannot initialize crypto backend."
+msgstr "Kan ikke initialisere crypto-motor."
+
+#: lib/setup.c:266 lib/setup.c:2046 lib/verity/verity.c:119
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Hashalgoritmen %s er ikke understøttet."
+
+#: lib/setup.c:269 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Nøglebehandlingsfejl (der bruger hash %s)."
+
+#: lib/setup.c:335 lib/setup.c:362
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Kan ikke bestemme enhedstype. Er aktivering af enhed ikke kompatibel?"
+
+#: lib/setup.c:341 lib/setup.c:3050
+msgid "This operation is supported only for LUKS device."
+msgstr "Denne operation er kun understøttet for LUKS-enhed."
+
+#: lib/setup.c:368
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Denne operation er kun understøttet for LUKS2-enhed."
+
+#: lib/setup.c:423 lib/luks2/luks2_reencrypt.c:2345
+msgid "All key slots full."
+msgstr "Alle nøglepladser er udfyldt."
+
+#: lib/setup.c:434
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Nøglepladsen %d er ugyldig, vælg venligst mellem 0 og %d."
+
+#: lib/setup.c:440
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Nøglepladsen %d er fuld, vælg venligst en anden."
+
+#: lib/setup.c:525 lib/setup.c:2824
+msgid "Device size is not aligned to device logical block size."
+msgstr "Enhedsstørrelsen er ikke justeret til logisk blokstørrelse for enhed."
+
+#: lib/setup.c:624
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Teksthoved registreret men enheden %s er for lille."
+
+#: lib/setup.c:661
+msgid "This operation is not supported for this device type."
+msgstr "Denne operation er ikke understøttet for denne enhedstype."
+
+#: lib/setup.c:666
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Ulovlig operation med omkryptering i gang."
+
+#: lib/setup.c:832 lib/luks1/keymanage.c:475
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "LUKS-version %d er ikke understøttet."
+
+#: lib/setup.c:849 lib/setup.c:1539 lib/setup.c:1959
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Frakoblet metadataenhed er ikke understøttet for denne crypttype."
+
+#: lib/setup.c:1427 lib/setup.c:2544 lib/setup.c:2616 lib/setup.c:2628
+#: lib/setup.c:2777 lib/setup.c:4512
+#, c-format
+msgid "Device %s is not active."
+msgstr "Enheden %s er ikke aktiv."
+
+#: lib/setup.c:1444
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Underliggende enhed for cryptenheden %s forsvandt."
+
+#: lib/setup.c:1524
+msgid "Invalid plain crypt parameters."
+msgstr "Ugyldige rene crypt-parametre."
+
+#: lib/setup.c:1529 lib/setup.c:1949 src/integritysetup.c:73
+msgid "Invalid key size."
+msgstr "Ugyldig nøglestørrelse."
+
+#: lib/setup.c:1534 lib/setup.c:1954 lib/setup.c:2157
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID er ikke understøttet for denne crypttype."
+
+#: lib/setup.c:1549 lib/setup.c:1739 lib/luks2/luks2_reencrypt.c:2308
+#: src/cryptsetup.c:1237
+msgid "Unsupported encryption sector size."
+msgstr "Sektorstørrelsen på krypteringen er ikke understøttet."
+
+#: lib/setup.c:1557 lib/setup.c:1864 lib/setup.c:2818
+msgid "Device size is not aligned to requested sector size."
+msgstr "Enhedsstørrelsen er ikke justeret til den anmodede sektorstørrelse."
+
+#: lib/setup.c:1608 lib/setup.c:1727
+msgid "Can't format LUKS without device."
+msgstr "Kan ikke formatere LUKS uden enhed."
+
+#: lib/setup.c:1614 lib/setup.c:1733
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Forespurgte datajustering er ikke kompatibel med dataforskydning."
+
+#: lib/setup.c:1682 lib/setup.c:1851
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr "ADVARSEL: Dataforskydning er uden for nuværende tilgængelige dataenhed.\n"
+
+#: lib/setup.c:1692 lib/setup.c:1879 lib/setup.c:1900 lib/setup.c:2169
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Kan ikke rydde teksthoved på enheden %s."
+
+#: lib/setup.c:1744
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "ADVARSEL: Enhedsaktiveringen vil fejle, dm-crypt mangler understøttelse for anmodet størrelse på krypteringssektor.\n"
+
+#: lib/setup.c:1766
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Diskenhedsnøglen er for lille til kryptering med integritetsudvidelser."
+
+#: lib/setup.c:1821
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Krypteringsalgoritmen %s-%s (nøglestørrelse %zd bit) er ikke tilgængelig."
+
+#: lib/setup.c:1854
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "ADVARSEL: LUKS2-metadatastørrelse ændret til %<PRIu64> byte.\n"
+
+#: lib/setup.c:1858
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "ADVARSEL: LUKS2-nøglepladsens områdestørrelse er ændret til %<PRIu64> byte.\n"
+
+#: lib/setup.c:1882 lib/utils_device.c:828 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:2356 lib/luks2/luks2_reencrypt.c:3367
+#, c-format
+msgid "Device %s is too small."
+msgstr "Enheden %s er for lille."
+
+#: lib/setup.c:1893 lib/setup.c:1919
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Kan ikke formatere enheden %s i brug."
+
+#: lib/setup.c:1896 lib/setup.c:1922
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Kan ikke formatere enheden %s, tilladelse nægtet."
+
+#: lib/setup.c:1908 lib/setup.c:2229
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Kan ikke formatere integritet for enheden %s."
+
+#: lib/setup.c:1926
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Kan ikke formatere enheden %s."
+
+#: lib/setup.c:1944
+msgid "Can't format LOOPAES without device."
+msgstr "Kan ikke formatere LOOPAES uden enhed."
+
+#: lib/setup.c:1989
+msgid "Can't format VERITY without device."
+msgstr "Kan ikke formatere VERITY uden enhed."
+
+#: lib/setup.c:2000 lib/verity/verity.c:102
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "VERITY-hashtypen %d er ikke understøttet."
+
+#: lib/setup.c:2006 lib/verity/verity.c:110
+msgid "Unsupported VERITY block size."
+msgstr "VERITY-blokstørrelse er ikke understøttet."
+
+#: lib/setup.c:2011 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "VERITY-hashforskydning er ikke understøttet."
+
+#: lib/setup.c:2016
+msgid "Unsupported VERITY FEC offset."
+msgstr "VERITY FEC-forskydning er ikke understøttet."
+
+#: lib/setup.c:2040
+msgid "Data area overlaps with hash area."
+msgstr "Dataområde overlapper med hashområde."
+
+#: lib/setup.c:2065
+msgid "Hash area overlaps with FEC area."
+msgstr "Dataområde overlapper med FEC-område."
+
+#: lib/setup.c:2072
+msgid "Data area overlaps with FEC area."
+msgstr "Dataområde overlapper med FEC-område."
+
+#: lib/setup.c:2208
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "ADVARSEL: Anmodte mærkestørrelse %d byte er forskellig fra %s størrelsesuddata (%d byte).\n"
+
+#: lib/setup.c:2286
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Der blev anmodt om ukendt crypt-enhedstype %s."
+
+#: lib/setup.c:2550 lib/setup.c:2622 lib/setup.c:2635
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Ikke understøttede parametre på enheden %s."
+
+#: lib/setup.c:2556 lib/setup.c:2641 lib/luks2/luks2_reencrypt.c:2408
+#: lib/luks2/luks2_reencrypt.c:2737
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Parametre matcher ikke på enheden %s."
+
+#: lib/setup.c:2661
+msgid "Crypt devices mismatch."
+msgstr "Crypt-enheder er forskellige."
+
+#: lib/setup.c:2698 lib/setup.c:2703 lib/luks2/luks2_reencrypt.c:2054
+#: lib/luks2/luks2_reencrypt.c:3145
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Kunne ikke genindlæse enheden %s."
+
+#: lib/setup.c:2708 lib/setup.c:2713 lib/luks2/luks2_reencrypt.c:2025
+#: lib/luks2/luks2_reencrypt.c:2032
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Kunne ikke placere enheden %s i dvale."
+
+#: lib/setup.c:2718 lib/luks2/luks2_reencrypt.c:2039
+#: lib/luks2/luks2_reencrypt.c:3080 lib/luks2/luks2_reencrypt.c:3149
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Kunne ikke genoptage enheden %s."
+
+#: lib/setup.c:2732
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Der opstod en fatal fejl under genindlæsning af enheden %s (oven på enheden %s)."
+
+#: lib/setup.c:2735 lib/setup.c:2737
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Kunne ikke skifte enheden %s til dm-error."
+
+#: lib/setup.c:2809
+msgid "Cannot resize loop device."
+msgstr "Kan ikke ændre størrelse på loop-enhed."
+
+#: lib/setup.c:2882
+msgid "Do you really want to change UUID of device?"
+msgstr "Ønsker du at ændre UUID for enhed?"
+
+#: lib/setup.c:2958
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Sikkerhedskopifilen indeholder ikke gyldige LUKS-teksthoveder."
+
+#: lib/setup.c:3058
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Diskenheden %s er ikke aktiv."
+
+#: lib/setup.c:3069
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Diskenheden %s er allerede suspenderet."
+
+#: lib/setup.c:3082
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Suspension er ikke understøttet for enheden %s."
+
+#: lib/setup.c:3084
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Fejl under suspension af enheden %s."
+
+#: lib/setup.c:3117 lib/setup.c:3184 lib/setup.c:3267
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Diskenheden %s er ikke suspenderet."
+
+#: lib/setup.c:3146
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Genoptag er ikke understøttet for enheden %s."
+
+#: lib/setup.c:3148 lib/setup.c:3216 lib/setup.c:3297
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Fejl under genoptagelse af enheden %s."
+
+#: lib/setup.c:3282 lib/setup.c:3648 lib/setup.c:4309 lib/setup.c:4322
+#: lib/setup.c:4330 lib/setup.c:4343 lib/setup.c:4693 lib/setup.c:5839
+msgid "Volume key does not match the volume."
+msgstr "Diskenhedsnøgle matcher ikke diskenheden."
+
+#: lib/setup.c:3343 lib/setup.c:3531
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Kan ikke tilføje nøgleplads, alle pladser er deaktiveret og ingen diskenhedsnøgle tilbudt."
+
+#: lib/setup.c:3483
+msgid "Failed to swap new key slot."
+msgstr "Kunne ikke swappe ny nøgleplads."
+
+#: lib/setup.c:3669
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Nøglepladsen %d er ugyldig."
+
+#: lib/setup.c:3675 src/cryptsetup.c:1583 src/cryptsetup.c:1928
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Nøglepladsen %d er ikke aktiv."
+
+#: lib/setup.c:3694
+msgid "Device header overlaps with data area."
+msgstr "Enhedsteksthoved overlapper med dataområde."
+
+#: lib/setup.c:3981
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Omkryptering er i gang. Kan ikke aktivere enhed."
+
+#: lib/setup.c:3983 lib/luks2/luks2_json_metadata.c:2238
+#: lib/luks2/luks2_reencrypt.c:2836
+msgid "Failed to get reencryption lock."
+msgstr "Kunne ikke indhente omkrypteringslås."
+
+#: lib/setup.c:3996 lib/luks2/luks2_reencrypt.c:2855
+msgid "LUKS2 reencryption recovery failed."
+msgstr "LUKS2-omkrypteringsgendannelse mislykkedes."
+
+#: lib/setup.c:4127 lib/setup.c:4379
+msgid "Device type is not properly initialized."
+msgstr "Enhedstypen er ikke ordentlig initialiseret."
+
+#: lib/setup.c:4171
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Kan ikke bruge enheden %s, navnet er ugyldigt eller stadig i brug."
+
+#: lib/setup.c:4174
+#, c-format
+msgid "Device %s already exists."
+msgstr "Enheden %s findes allerede."
+
+#: lib/setup.c:4296
+msgid "Incorrect volume key specified for plain device."
+msgstr "Ukorrekt diskenhedsnøgle specificeret for ren enhed."
+
+#: lib/setup.c:4405
+msgid "Incorrect root hash specified for verity device."
+msgstr "Ukorrekt roothash specificeret for verity-enhed."
+
+#: lib/setup.c:4412
+msgid "Root hash signature required."
+msgstr "Roothash-signatur er krævet."
+
+#: lib/setup.c:4421
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Kernenøglering mangler: krævet for at sende signatur til kernen."
+
+#: lib/setup.c:4438 lib/setup.c:5915
+msgid "Failed to load key in kernel keyring."
+msgstr "Kunne ikke indlæse nøgle i kernenøglefil."
+
+#: lib/setup.c:4491 lib/setup.c:4507 lib/luks2/luks2_json_metadata.c:2291
+#: src/cryptsetup.c:2603
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Enheden %s er stadig i brug."
+
+#: lib/setup.c:4516
+#, c-format
+msgid "Invalid device %s."
+msgstr "Ugyldig enhed %s."
+
+#: lib/setup.c:4632
+msgid "Volume key buffer too small."
+msgstr "Diskenhedsnøglebuffer er for lille."
+
+#: lib/setup.c:4640
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Kan ikke indhente diskenhedsnøgle for ren enhed."
+
+#: lib/setup.c:4657
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Kan ikke hente roothash for verity-enhed."
+
+#: lib/setup.c:4659
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Denne operation er ikke understøttet for %s crypt-enhed."
+
+#: lib/setup.c:4865
+msgid "Dump operation is not supported for this device type."
+msgstr "Dump-operation er ikke understøttet for denne enhedstype."
+
+#: lib/setup.c:5190
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Dataforskydning er ikke et multiplum af %u byte."
+
+#: lib/setup.c:5475
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Kan ikke konvertere enheden %s som stadig er i brug."
+
+#: lib/setup.c:5772
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Kunne ikke tildele nøglepladsen %u som den nye diskenhedsnøgle."
+
+#: lib/setup.c:5845
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Kunne ikke initialisere standardparametre for LUKS2-nøgleplads."
+
+#: lib/setup.c:5851
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Kunne ikke tildele nøglepladsen %d til sammendrag."
+
+#: lib/setup.c:5982
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Kernenøglering er ikke understøttet af kernen."
+
+#: lib/setup.c:5992 lib/luks2/luks2_reencrypt.c:2952
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Kunne ikke læse adgangsfrase fra nøglering (fejl %d)."
+
+#: lib/setup.c:6016
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Kunne ikke indhente global adgangsserialiseringslås for memory-hard."
+
+#: lib/utils.c:80
+msgid "Cannot get process priority."
+msgstr "Kan ikke indhente procesprioritet."
+
+#: lib/utils.c:94
+msgid "Cannot unlock memory."
+msgstr "Kan ikke låse hukommelsen op."
+
+#: lib/utils.c:168 lib/tcrypt/tcrypt.c:497
+msgid "Failed to open key file."
+msgstr "Kunne ikke åbne nøglefil."
+
+#: lib/utils.c:173
+msgid "Cannot read keyfile from a terminal."
+msgstr "Kan ikke læse nøglefilen fra en terminal."
+
+#: lib/utils.c:190
+msgid "Failed to stat key file."
+msgstr "Kunne ikke køre stat på nøglefil."
+
+#: lib/utils.c:198 lib/utils.c:219
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Kan ikke søge til anmodede nøglefilsforskydning."
+
+#: lib/utils.c:213 lib/utils.c:228 src/utils_password.c:188
+#: src/utils_password.c:201
+msgid "Out of memory while reading passphrase."
+msgstr "Ikke nok hukommelse under læsning af adgangsfrase."
+
+#: lib/utils.c:248
+msgid "Error reading passphrase."
+msgstr "Der opstod en fejl under læsning af adgangsfrase."
+
+#: lib/utils.c:265
+msgid "Nothing to read on input."
+msgstr "Intet at læse på inddata."
+
+#: lib/utils.c:272
+msgid "Maximum keyfile size exceeded."
+msgstr "Nøglefilsstørrelsen er over maksimum."
+
+#: lib/utils.c:277
+msgid "Cannot read requested amount of data."
+msgstr "Kan ikke læse den anmodede datamængde."
+
+#: lib/utils_device.c:187 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Enheden %s findes ikke eller adgang nægtet."
+
+#: lib/utils_device.c:197
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Enheden %s er ikke kompatibel."
+
+#: lib/utils_device.c:642
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Enheden %s er for lille. Kræver mindst %<PRIu64> byte."
+
+#: lib/utils_device.c:723
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Kan ikke bruge enheden %s som er i brug (allerede kortlagt eller monteret)."
+
+#: lib/utils_device.c:727
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Kan ikke bruge enheden %s, tilladelse nægtet."
+
+#: lib/utils_device.c:730
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Kan ikke indhente information om enheden %s."
+
+#: lib/utils_device.c:753
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Kan ikke bruge en loopback-enhed, kører som ikke-root bruger."
+
+#: lib/utils_device.c:763
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Vedhæftelse af loopback-enhed mislykkedes (loop-enhed med flaget autoclear er krævet)."
+
+#: lib/utils_device.c:809
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Anmodt forskydning er mere end den reelle størrelse for enheden %s."
+
+#: lib/utils_device.c:817
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Enheden %s har nul størrelse."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Anmodede PBKDF-måltidspunkt kan ikke være nul."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Ukendt PBKDF-type %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Den anmodede hash %s er ikke understøttet."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Den anmodede PBKDF-type er ikke understøttet for LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "PBKDF maks hukommelse eller parallelle tråde må ikke angives med pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Tvungen iterationantal er for lavt for %s (minimum er %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Tvungen hukommelsesomkostning er for lav for %s (minimum er %u kilobyte)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Anmodede maksimal PBKDF-hukommelsesomkostning er for høj (maksimum er %d kilobyte)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Anmodede maksimal PBKDF-hukommelse kan ikke være nul."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Anmodede PBKDF parallelle tråde kan ikke være nul."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Kun PBKDF2 er understøttet i FIPS-tilstand."
+
+#: lib/utils_benchmark.c:166
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "PBKDF-sammenligning deaktiveret men iterationer er ikke angivet."
+
+#: lib/utils_benchmark.c:185
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Ikke kompatible PBKDF2-tilvalg (der bruger hash-algoritme %s)."
+
+#: lib/utils_benchmark.c:205
+msgid "Not compatible PBKDF options."
+msgstr "Ikke kompatible PBKDF2-tilvalg."
+
+#: lib/utils_device_locking.c:102
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Låsning afbrudt. Låsestien %s/%s kan ikke bruges (ikke en mappe eller mangler)."
+
+#: lib/utils_device_locking.c:109
+#, c-format
+msgid "WARNING: Locking directory %s/%s is missing!\n"
+msgstr "ADVARSEL: Låsemappen %s/%s mangler!\n"
+
+#: lib/utils_device_locking.c:119
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Låsning afbrudt. Låsestien %s/%s kan ikke bruges (%s er ikke en mappe)."
+
+#: lib/utils_wipe.c:184 src/cryptsetup_reencrypt.c:934
+#: src/cryptsetup_reencrypt.c:1018
+msgid "Cannot seek to device offset."
+msgstr "Kan ikke søge til enhedsforskydning."
+
+#: lib/utils_wipe.c:208
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Sletningsfejl for enhed (wipe), forskydning %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Kunne ikke opsætte dm-crypt nøgleoversættelse for enheden %s.\n"
+"Kontroller at kernen understøtter krypteringsalgoritmen %s (kontroller syslog for yderligere information)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Nøglestørrelse i XTS-tilstand skal være 256- eller 512-bit."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Specifikation for krypteringsalgoritme skal være i [cipher]-[mode]-[iv]-format."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:344
+#: lib/luks1/keymanage.c:635 lib/luks1/keymanage.c:1080
+#: lib/luks2/luks2_json_metadata.c:1252 lib/luks2/luks2_keyslot.c:734
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Kan ikke skrive til enheden %s, tilladelse nægtet."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Kunne ikke åbne midlertidig nøglelagerenhed."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Kunne ikke tilgå midlertidig nøglelagerenhed."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:60
+#: lib/luks2/luks2_keyslot_luks2.c:78 lib/luks2/luks2_keyslot_reenc.c:134
+msgid "IO error while encrypting keyslot."
+msgstr "IO-fejl under kryptering af nøgleplads."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:347
+#: lib/luks1/keymanage.c:588 lib/luks1/keymanage.c:638 lib/tcrypt/tcrypt.c:672
+#: lib/verity/verity.c:80 lib/verity/verity.c:178 lib/verity/verity_hash.c:311
+#: lib/verity/verity_hash.c:322 lib/verity/verity_hash.c:342
+#: lib/verity/verity_fec.c:241 lib/verity/verity_fec.c:253
+#: lib/verity/verity_fec.c:258 lib/luks2/luks2_json_metadata.c:1255
+#: src/cryptsetup_reencrypt.c:205
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Kan ikke åbne enheden %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:137
+msgid "IO error while decrypting keyslot."
+msgstr "IO-fejl under dekryptering af nøgleplads."
+
+#: lib/luks1/keymanage.c:110
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Enheden %s er for lille. (LUKS1 kræver mindst %<PRIu64> byte.)"
+
+#: lib/luks1/keymanage.c:131 lib/luks1/keymanage.c:139
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:162
+#: lib/luks1/keymanage.c:174
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "LUKS-nøgleplads %u er ugyldig."
+
+#: lib/luks1/keymanage.c:228 lib/luks1/keymanage.c:472
+#: lib/luks2/luks2_json_metadata.c:1083 src/cryptsetup.c:1444
+#: src/cryptsetup.c:1570 src/cryptsetup.c:1627 src/cryptsetup.c:1683
+#: src/cryptsetup.c:1750 src/cryptsetup.c:1853 src/cryptsetup.c:1917
+#: src/cryptsetup.c:2077 src/cryptsetup.c:2270 src/cryptsetup.c:2330
+#: src/cryptsetup.c:2396 src/cryptsetup.c:2560 src/cryptsetup.c:3210
+#: src/cryptsetup.c:3219 src/cryptsetup_reencrypt.c:1381
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Enheden %s er ikke en gyldig LUKS-enhed."
+
+#: lib/luks1/keymanage.c:246 lib/luks2/luks2_json_metadata.c:1100
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Den anmodede sikkerhedskopifil %s for teksthoveder findes allerede."
+
+#: lib/luks1/keymanage.c:248 lib/luks2/luks2_json_metadata.c:1102
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Kan ikke oprette sikkerhedskopifilen %s for teksthoveder."
+
+#: lib/luks1/keymanage.c:255 lib/luks2/luks2_json_metadata.c:1109
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Kan ikke skrive sikkerhedskopifilen %sf for teksthoveder."
+
+#: lib/luks1/keymanage.c:286 lib/luks2/luks2_json_metadata.c:1161
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Sikkerhedskopifilen indeholder ikke gyldige LUKS-teksthoveder."
+
+#: lib/luks1/keymanage.c:299 lib/luks1/keymanage.c:549
+#: lib/luks2/luks2_json_metadata.c:1182
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Kan ikke åbne sikkerhedskopifilen %s for teksthoveder."
+
+#: lib/luks1/keymanage.c:307 lib/luks2/luks2_json_metadata.c:1190
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Kan ikke læse sikkerhedskopifilen %s for teksthoveder."
+
+#: lib/luks1/keymanage.c:317
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Dataforskydning eller nøglestørrelse er forskellige på enhed eller sikkerhedskopi, gendannelse mislykkedes."
+
+#: lib/luks1/keymanage.c:325
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Enheden %s %s%s"
+
+#: lib/luks1/keymanage.c:326
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "indeholder ikke LUKS-teksthoveder. Erstatning af teksthoved kan ødelægge data på den enhed."
+
+#: lib/luks1/keymanage.c:327
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "indeholder allerede LUKS-teksthoveder. Erstatning af teksthoveder vil ødelægge eksisterende nøglepladser."
+
+#: lib/luks1/keymanage.c:328 lib/luks2/luks2_json_metadata.c:1224
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"ADVARSEL: reel enhedsteksthoved har en anden UUID end sikkerhedskopien!"
+
+#: lib/luks1/keymanage.c:375
+msgid "Non standard key size, manual repair required."
+msgstr "Nøglestørrelsen følger ikke standarden, en manuel reparation er krævet."
+
+#: lib/luks1/keymanage.c:380
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Nøglepladsopstillingen følger ikke standarden, en manuel reparation er krævet."
+
+#: lib/luks1/keymanage.c:390
+msgid "Repairing keyslots."
+msgstr "Reparerer nøglepladser."
+
+#: lib/luks1/keymanage.c:409
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Nøgleplads %i: forskydning repareret (%u -> %u)."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Nøgleplads %i: striber (»stripes«) repareret (%u -> %u)."
+
+#: lib/luks1/keymanage.c:426
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Nøgleplads %i: falsk partitionssignatur."
+
+#: lib/luks1/keymanage.c:431
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Nøgleplads %i: salt ryddet."
+
+#: lib/luks1/keymanage.c:448
+msgid "Writing LUKS header to disk."
+msgstr "Skriver LUKS-teksthovedet til disken."
+
+#: lib/luks1/keymanage.c:453
+msgid "Repair failed."
+msgstr "Reparation mislykkedes."
+
+#: lib/luks1/keymanage.c:481 lib/luks1/keymanage.c:750
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Den anmodede LUKS-hash %s er ikke understøttet."
+
+#: lib/luks1/keymanage.c:509 src/cryptsetup.c:1144
+msgid "No known problems detected for LUKS header."
+msgstr "Ingen kendte problemer registreret for LUKS-teksthoved."
+
+#: lib/luks1/keymanage.c:660
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Fejl under opdatering af LUKS-teksthoved på enheden %s."
+
+#: lib/luks1/keymanage.c:668
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Fejl under genlæsning af LUKS-teksthoved efter opdatering på enheden %s."
+
+#: lib/luks1/keymanage.c:744
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Dataforskydning for LUKS-teksthoved skal være enten 0 eller større end teksthovedstørrelse."
+
+#: lib/luks1/keymanage.c:755 lib/luks1/keymanage.c:825
+#: lib/luks2/luks2_json_format.c:283 lib/luks2/luks2_json_metadata.c:1001
+#: src/cryptsetup.c:2723
+msgid "Wrong LUKS UUID format provided."
+msgstr "Forkert LUKS UUID-format anført."
+
+#: lib/luks1/keymanage.c:778
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Kan ikke oprette LUKS-teksthoved: læsning af vilkårlig salt mislykkedes."
+
+#: lib/luks1/keymanage.c:804
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Kan ikke oprette LUKS-teksthoved: Teksthovedsammendrag mislykkedes (bruger hash %s)."
+
+#: lib/luks1/keymanage.c:848
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Nøgleplads %d aktiv, nulstil (purge) den først."
+
+#: lib/luks1/keymanage.c:854
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Nøgleplads %d-materiale inkluderer for få striber (»stribes«). Teksthovedmanipulering?"
+
+#: lib/luks1/keymanage.c:990
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Kan ikke åbne nøgleplads (der bruger hash %s)."
+
+#: lib/luks1/keymanage.c:1066
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Nøgleplads %d er ugyldig, vælg nøgleplads mellem 0 og %d."
+
+#: lib/luks1/keymanage.c:1084 lib/luks2/luks2_keyslot.c:738
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Kan ikke rydde enheden %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Registreret endnu ikke understøttet GPG-krypteret nøglefil."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Brug venligst gpg --decrypt <NØGLEFIL> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Ikke kompatibel loop-AES-nøglefil registreret."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Kerne understøtter ikke loop-AES-kompatibel oversættelse."
+
+#: lib/tcrypt/tcrypt.c:504
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Fejl under læsning af nøglefilen %s."
+
+#: lib/tcrypt/tcrypt.c:556
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Den maksimale længde for TCRYPT-adgangsfrasen (%zu) er overskredet."
+
+#: lib/tcrypt/tcrypt.c:597
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "PBKDF2-hashalgoritmen %s er ikke tilgængelig, udelader."
+
+#: lib/tcrypt/tcrypt.c:613 src/cryptsetup.c:1021
+msgid "Required kernel crypto interface not available."
+msgstr "Krævet kernegrænseflade for crypto er ikke tilgængelig."
+
+#: lib/tcrypt/tcrypt.c:615 src/cryptsetup.c:1023
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Sikr dig at du har kernemodulet algif_skcipher indlæst."
+
+#: lib/tcrypt/tcrypt.c:755
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Aktivering er endnu ikke understøttet for %d sektorstørrelse."
+
+#: lib/tcrypt/tcrypt.c:761
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Kerne understøtter ikke aktivering for denne TCRYPT legacy-tilstand."
+
+#: lib/tcrypt/tcrypt.c:795
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Aktivering af TCRYPT-systemkryptering for partition %s."
+
+#: lib/tcrypt/tcrypt.c:873
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Kerne understøtter ikke TCRYPT-kompatibel oversættelse."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Denne funktion er ikke understøttet uden TCRYPT-teksthovedindlæsning."
+
+#: lib/bitlk/bitlk.c:332
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Uventet metadataindgangstype »%u« fundet da understøttet Volume Master Key blev fortolket."
+
+#: lib/bitlk/bitlk.c:379
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Ugyldig streng fundet da Volume Master Key blev fortolket."
+
+#: lib/bitlk/bitlk.c:384
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Uventet streng (»%s«) fundet da Volume Master Key blev fortolket."
+
+#: lib/bitlk/bitlk.c:398
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Uventet metadataindgangsværdi »%u« fundet da Volume Master Key blev fortolket."
+
+#: lib/bitlk/bitlk.c:477
+#, c-format
+msgid "Failed to read BITLK signature from %s."
+msgstr "Kunne ikke læse BITLK-signatur fra %s."
+
+#: lib/bitlk/bitlk.c:483
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK version 1 er i øjeblikket ikke understøttet."
+
+#: lib/bitlk/bitlk.c:489
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Ugyldig eller ukendt opstartssignatur for BITLK-enhed."
+
+#: lib/bitlk/bitlk.c:501
+msgid "Invalid or unknown signature for BITLK device."
+msgstr "Ugyldig eller ukendt signatur for BITLK-enhed."
+
+#: lib/bitlk/bitlk.c:509
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Kunne ikke læse BITLK-teksthoved fra %s."
+
+#: lib/bitlk/bitlk.c:534
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Kunne ikke læse BITLK FVE-metadata fra %s."
+
+#: lib/bitlk/bitlk.c:585
+msgid "Unknown or unsupported encryption type."
+msgstr "Ukendt eller ikke understøttet krypteringstype."
+
+#: lib/bitlk/bitlk.c:618
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Kunne ikke læse BITLK-metadataposter fra %s."
+
+#: lib/bitlk/bitlk.c:911
+msgid "This operation is not supported."
+msgstr "Denne operation er ikke understøttet."
+
+#: lib/bitlk/bitlk.c:919
+msgid "Wrong key size."
+msgstr "Forkert nøglestørrelse."
+
+#: lib/bitlk/bitlk.c:971
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Denne BITLK-enhed er i en ikkeunderstøttet tilstand og kan ikke aktiveres."
+
+#: lib/bitlk/bitlk.c:977
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "BITLK-enheder med typen »%s« kan ikke aktiveres."
+
+#: lib/bitlk/bitlk.c:1059
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Aktivering af delvist dekrypteret BITLK-enhed er ikke understøttet."
+
+#: lib/bitlk/bitlk.c:1192
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Kan ikke aktivere enhed, kernel dm-crypt mangler understøttelse for BITLK IV."
+
+#: lib/bitlk/bitlk.c:1196
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Kan ikke aktivere enhed, kernen dm-crypt mangler understøttelse for BITLK Elephant diffuser."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:171
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Verity-enheden %s bruger ikke on-disk-teksthoved."
+
+#: lib/verity/verity.c:90
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Enheden %s er ikke en gyldig VERITY-enhed."
+
+#: lib/verity/verity.c:97
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Ikke understøttet VERITY-version %d."
+
+#: lib/verity/verity.c:128
+msgid "VERITY header corrupted."
+msgstr "VERITY-teksthovedet er ødelagt."
+
+#: lib/verity/verity.c:165
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Forkert VERITY UUID-format indeholdt på enheden %s."
+
+#: lib/verity/verity.c:198
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Fejl under opdatering af verity-teksthoved på enheden %s."
+
+#: lib/verity/verity.c:256
+msgid "Root hash signature verification is not supported."
+msgstr "Roothash-signaturverifikation er ikke understøttet."
+
+#: lib/verity/verity.c:267
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Fejl kan ikke repareres med FEC-enhed."
+
+#: lib/verity/verity.c:269
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Fandt %u fejl der kan repareres med FEC-enhed."
+
+#: lib/verity/verity.c:308
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Kerne understøtter ikke dm-verity-oversættelse."
+
+#: lib/verity/verity.c:312
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Kerne understøtter ikke dm-verity-signaturtilvalg."
+
+#: lib/verity/verity.c:323
+msgid "Verity device detected corruption after activation."
+msgstr "Verity-enheden registrerede korruption efter aktivering."
+
+#: lib/verity/verity_hash.c:59
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Ledigt område nulstilles ikke (»not zeroed«) på position %<PRIu64>."
+
+#: lib/verity/verity_hash.c:163 lib/verity/verity_hash.c:290
+#: lib/verity/verity_hash.c:303
+msgid "Device offset overflow."
+msgstr "Forskydningsoverløb for enhed."
+
+#: lib/verity/verity_hash.c:203
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Verificering mislykkedes på position %<PRIu64>."
+
+#: lib/verity/verity_hash.c:276
+msgid "Invalid size parameters for verity device."
+msgstr "Ugyldig størrelse for parametre for verity-enhed."
+
+#: lib/verity/verity_hash.c:296
+msgid "Hash area overflow."
+msgstr "Hashområdeoverløb."
+
+#: lib/verity/verity_hash.c:373
+msgid "Verification of data area failed."
+msgstr "Verifikation af dataområde mislykkedes."
+
+#: lib/verity/verity_hash.c:378
+msgid "Verification of root hash failed."
+msgstr "Verifikation af root-hash mislykkedes."
+
+#: lib/verity/verity_hash.c:384
+msgid "Input/output error while creating hash area."
+msgstr "Inddata/uddata-fejl under oprettelse af hash-område."
+
+#: lib/verity/verity_hash.c:386
+msgid "Creation of hash area failed."
+msgstr "Oprettelse af hash-område mislykkedes."
+
+#: lib/verity/verity_hash.c:433
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "ADVARSEL: Kerne kan ikke aktivere enhed hvis dataenes blokstørrelse er større end sidestørrelsen (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Kunne ikke allokere RS-kontekst."
+
+#: lib/verity/verity_fec.c:146
+msgid "Failed to allocate buffer."
+msgstr "Kunne ikke allokere buffer."
+
+#: lib/verity/verity_fec.c:156
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Kunne ikke læse RS-blok %<PRIu64> byte %d."
+
+#: lib/verity/verity_fec.c:169
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Kunne ikke læse paritet for RS-blok %<PRIu64>."
+
+#: lib/verity/verity_fec.c:177
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Kunne ikke reparere paritet for blok %<PRIu64>."
+
+#: lib/verity/verity_fec.c:188
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Kunne ikke skrive paritet for RS-blok %<PRIu64>.."
+
+#: lib/verity/verity_fec.c:223
+msgid "Block sizes must match for FEC."
+msgstr "Blokstørrelser skal matche for FEC."
+
+#: lib/verity/verity_fec.c:229
+msgid "Invalid number of parity bytes."
+msgstr "Ugyldigt antal paritetsbyte."
+
+#: lib/verity/verity_fec.c:265
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Kunne ikke bestemme størrelsen på enheden %s."
+
+#: lib/integrity/integrity.c:271 lib/integrity/integrity.c:343
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Kerne understøtter ikke dm-integrity-oversættelse."
+
+#: lib/integrity/integrity.c:277
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Kerne understøtter ikke dm-integrity fast metadatajustering."
+
+#: lib/luks2/luks2_disk_metadata.c:383 lib/luks2/luks2_json_metadata.c:959
+#: lib/luks2/luks2_json_metadata.c:1244
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Kunne ikke indhente skrivelås på enheden %s."
+
+#: lib/luks2/luks2_disk_metadata.c:392
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Registreret forsøg på samtidig LUKS2-metadataopdering. Afbryder operation."
+
+#: lib/luks2/luks2_disk_metadata.c:691 lib/luks2/luks2_disk_metadata.c:712
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Enhed indeholder tvetydige signaturer, kan ikke gendanne LUKS2 automatisk.\n"
+"Kør venligst »cryptsetup repair« for gendannelse."
+
+#: lib/luks2/luks2_json_format.c:227
+msgid "Requested data offset is too small."
+msgstr "Forespurgte dataforskydning er for lille."
+
+#: lib/luks2/luks2_json_format.c:271
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "ADVARSEL: nøglepladsområde (%<PRIu64> byte) er meget lille, tilgængelige LUKS2-nøglepladsantal er meget begrænset.\n"
+
+#: lib/luks2/luks2_json_metadata.c:946 lib/luks2/luks2_json_metadata.c:1074
+#: lib/luks2/luks2_json_metadata.c:1150 lib/luks2/luks2_keyslot_luks2.c:92
+#: lib/luks2/luks2_keyslot_luks2.c:114
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Kunne ikke indhente læselås på enheden %s."
+
+#: lib/luks2/luks2_json_metadata.c:1167
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Forbudt LUKS2-krav registreret i sikkerhedskopien %s."
+
+#: lib/luks2/luks2_json_metadata.c:1208
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Dataforskydning er forskellig på enhed eller sikkerhedskopi, gendannelse mislykkedes."
+
+#: lib/luks2/luks2_json_metadata.c:1214
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Binær teksthoved med nøglepladsområdestørrelse er forskellige på enhed eller sikkerhedskopi, gendannelse mislykkedes."
+
+#: lib/luks2/luks2_json_metadata.c:1221
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Enheden %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1222
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "indeholder ikke LUKS2-teksthoveder. Erstatning af teksthoved kan ødelægge data på den enhed."
+
+#: lib/luks2/luks2_json_metadata.c:1223
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "indeholder allerede LUKS2-teksthoveder. Erstatning af teksthoveder vil ødelægge eksisterende nøglepladser."
+
+#: lib/luks2/luks2_json_metadata.c:1225
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"ADVARSEL: Ukendte LUKS2-krav registreret i reel enhedsteksthoved!\n"
+"Erstatning af teksthoved med sikkerhedskopi kan ødelægge data på den enhed!"
+
+#: lib/luks2/luks2_json_metadata.c:1227
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"ADVARSEL: Ufærdig frakoblet omkryptering registreret på enheden!\n"
+"Erstatning af teksthoved med sikkerhedskopi kan ødelægge data."
+
+#: lib/luks2/luks2_json_metadata.c:1323
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Ignorerede ukendt flag %s."
+
+#: lib/luks2/luks2_json_metadata.c:2010 lib/luks2/luks2_reencrypt.c:1746
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Manglende nøgle for dm-crypt-segmentet %u"
+
+#: lib/luks2/luks2_json_metadata.c:2022 lib/luks2/luks2_reencrypt.c:1764
+msgid "Failed to set dm-crypt segment."
+msgstr "Kunne ikke angive dm-crypt-segmentet."
+
+#: lib/luks2/luks2_json_metadata.c:2028 lib/luks2/luks2_reencrypt.c:1770
+msgid "Failed to set dm-linear segment."
+msgstr "Kunne ikke angive dm-linear-segmentet."
+
+#: lib/luks2/luks2_json_metadata.c:2155
+msgid "Unsupported device integrity configuration."
+msgstr "Ikke understøttet konfiguration for enhedsintegritet."
+
+#: lib/luks2/luks2_json_metadata.c:2236
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Omkryptering i gang. Kan ikke deaktivere enhed."
+
+#: lib/luks2/luks2_json_metadata.c:2247 lib/luks2/luks2_reencrypt.c:3190
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Kunne ikke erstatte enheden %s i dvale med dm-error-mål."
+
+#: lib/luks2/luks2_json_metadata.c:2327
+msgid "Failed to read LUKS2 requirements."
+msgstr "Kunne ikke læse LUKS2-krav."
+
+#: lib/luks2/luks2_json_metadata.c:2334
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Uopfyldte LUKS2-krav registreret."
+
+#: lib/luks2/luks2_json_metadata.c:2342
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Operation er ikke kompatibel med enhed markeret for forældet omkryptering. Afbryder."
+
+#: lib/luks2/luks2_json_metadata.c:2344
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Operation er ikke kompatibel med enhed markeret for LUKS2-omkryptering. Afbryder."
+
+#: lib/luks2/luks2_keyslot.c:547 lib/luks2/luks2_keyslot.c:584
+msgid "Not enough available memory to open a keyslot."
+msgstr "Ikke nok hukommelse tilgængelig til at åbne en nøgleplads."
+
+#: lib/luks2/luks2_keyslot.c:549 lib/luks2/luks2_keyslot.c:586
+msgid "Keyslot open failed."
+msgstr "Åbning af nøgleplads mislykkedes."
+
+#: lib/luks2/luks2_keyslot_luks2.c:53 lib/luks2/luks2_keyslot_luks2.c:108
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Kan ikke brug %s-%s-krypteringsalgoritmen til nøglepladskryptering."
+
+#: lib/luks2/luks2_keyslot_luks2.c:480
+msgid "No space for new keyslot."
+msgstr "Ingen plads for ny nøgleplads."
+
+#: lib/luks2/luks2_luks1_convert.c:482
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Kan ikke kontrollere status for enheden med uuid: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:508
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Kan ikke konvertere teksthoved med yderligere metadata for LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:548
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Kan ikke flytte nøglepladsområde. Ikke nok plads."
+
+#: lib/luks2/luks2_luks1_convert.c:599
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Kan ikke flytte nøglepladsområde. LUKS2-nøglepladsområdet er for lille."
+
+#: lib/luks2/luks2_luks1_convert.c:605 lib/luks2/luks2_luks1_convert.c:887
+msgid "Unable to move keyslot area."
+msgstr "Kan ikke flytte nøglepladsområde."
+
+#: lib/luks2/luks2_luks1_convert.c:697
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Kan ikke konvertere til LUKS1-format - krypteringssektorstørrelsen for standardsegmenter er ikke 512 byte."
+
+#: lib/luks2/luks2_luks1_convert.c:705
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Kan ikke konverterer til LUKS1-format - nøglepladssammendrag er ikke LUKS1-kompatibel."
+
+#: lib/luks2/luks2_luks1_convert.c:717
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr ""
+"Kan ikke konverterer til LUKS1-format - enheden bruger omsluttet\n"
+"nøglekrypteringsalgoritme %s."
+
+#: lib/luks2/luks2_luks1_convert.c:725
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr ""
+"Kan ikke konverterer til LUKS1-format - LUKS2-teksthoved indeholder\n"
+"%u symboler (tokens)."
+
+#: lib/luks2/luks2_luks1_convert.c:739
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Kan ikke konvertere til LUKS1-format - nøgleplads %u er i ugyldig tilstand."
+
+#: lib/luks2/luks2_luks1_convert.c:744
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr ""
+"Kan ikke konverterer til LUKS1-format - plads %u (over maksimalt antal pladser)\n"
+"er stadig aktiv."
+
+#: lib/luks2/luks2_luks1_convert.c:749
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr ""
+"Kan ikke konvertere til LUKS1-format - nøglepladsen %u er ikke\n"
+"LUKS1-kompatibel."
+
+#: lib/luks2/luks2_reencrypt.c:892
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Hotzonestørrelsen skal være et multiplum af beregnet zonejustering (%zu byte)."
+
+#: lib/luks2/luks2_reencrypt.c:897
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Enhedsstørrelsen skal være et multiplum af beregnet zonejustering (%zu byte)."
+
+#: lib/luks2/luks2_reencrypt.c:941
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Resilience-tilstanden %s er ikke understøttet"
+
+#: lib/luks2/luks2_reencrypt.c:1158 lib/luks2/luks2_reencrypt.c:1313
+#: lib/luks2/luks2_reencrypt.c:1396 lib/luks2/luks2_reencrypt.c:1430
+#: lib/luks2/luks2_reencrypt.c:3030
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Kunne ikke initialisere gammelt lageromslag for segmentet."
+
+#: lib/luks2/luks2_reencrypt.c:1172 lib/luks2/luks2_reencrypt.c:1291
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Kunne ikke initialisere nyt lageromslag for segmentet."
+
+#: lib/luks2/luks2_reencrypt.c:1340
+msgid "Failed to read checksums for current hotzone."
+msgstr "Kunne ikke læse kontrolsummer for nuværende hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1347 lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Kunne ikke læse hotzone-område startende på %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1366
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Kunne ikke dekryptere sektor %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1372
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Kunne ikke gendanne sektor %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1867
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Størrelsen på kilde- og målenhed er forskellig. Kilde %<PRIu64>, mål: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1965
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Kunne ikke køre aktivere hotzone-enheden %s."
+
+#: lib/luks2/luks2_reencrypt.c:1982
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Kunne ikke aktivere overlagsenheden %s med faktiske origin-tabel."
+
+#: lib/luks2/luks2_reencrypt.c:1989
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Kunne ikke indlæse ny oversættelse for enheden %s."
+
+#: lib/luks2/luks2_reencrypt.c:2060
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Kunne ikke opdatere omkrypteringsenhedsstakken."
+
+#: lib/luks2/luks2_reencrypt.c:2216
+msgid "Failed to set new keyslots area size."
+msgstr "Kunne ikke angive områdestørrelse for nye nøglepladser."
+
+#: lib/luks2/luks2_reencrypt.c:2318
+#, c-format
+msgid "Data shift is not aligned to requested encryption sector size (%<PRIu32> bytes)."
+msgstr "Dataflytning er ikke justeret til den anmodede krypteringssektorstørrelse (%<PRIu32> byte)."
+
+#: lib/luks2/luks2_reencrypt.c:2339
+#, c-format
+msgid "Data device is not aligned to requested encryption sector size (%<PRIu32> bytes)."
+msgstr "Datanhed er ikke justeret til den anmodede krypteringssektorstørrelse (%<PRIu32> byte)."
+
+#: lib/luks2/luks2_reencrypt.c:2360
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Dataskift (%<PRIu64> sektorer) er mindre end fremtidig dataforskydning (%<PRIu64> sektorer)."
+
+#: lib/luks2/luks2_reencrypt.c:2366 lib/luks2/luks2_reencrypt.c:2779
+#: lib/luks2/luks2_reencrypt.c:2800
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Kan ikke åbne %s i eksklusiv tilstand (allerede kortlagt eller monteret)."
+
+#: lib/luks2/luks2_reencrypt.c:2534
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Enhed er ikke markeret for LUKS2-omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:2540 lib/luks2/luks2_reencrypt.c:3295
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Kunne ikke indlæse LUKS2-omkrypteringskontekst."
+
+#: lib/luks2/luks2_reencrypt.c:2619
+msgid "Failed to get reencryption state."
+msgstr "Kunne ikke indhente omkrypteringstilstand."
+
+#: lib/luks2/luks2_reencrypt.c:2623
+msgid "Device is not in reencryption."
+msgstr "Enheden er ikke under omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:2630
+msgid "Reencryption process is already running."
+msgstr "Omkrypteringsproces er allerede i gang."
+
+#: lib/luks2/luks2_reencrypt.c:2632
+msgid "Failed to acquire reencryption lock."
+msgstr "Kunne ikke indhente omkrypteringslås."
+
+#: lib/luks2/luks2_reencrypt.c:2650
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Kan ikke fortsætte med omkryptering. Kør omkrypteringsgendannelse først."
+
+#: lib/luks2/luks2_reencrypt.c:2750
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Aktiv enhedsstørrelse og anmodet sektorstørrelse er forskellige."
+
+#: lib/luks2/luks2_reencrypt.c:2764
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "Ugyldig enhedsstørrelse i omkrypteringsparametrene."
+
+#: lib/luks2/luks2_reencrypt.c:2834
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Omkryptering er i gang. Kan ikke udføre gendannelse."
+
+#: lib/luks2/luks2_reencrypt.c:2906
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "LUKS2-omkryptering er allerede initialiseret i metadata."
+
+#: lib/luks2/luks2_reencrypt.c:2913
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Kunne ikke initialisere LUKS2-omkryptering i metadata."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Kunne ikke angive enhedssegmenter for næste omkrypteringshotzone."
+
+#: lib/luks2/luks2_reencrypt.c:3046
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Kunne ikke skrive resilience-metadata for omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3053
+msgid "Decryption failed."
+msgstr "Dekryptering mislykkedes."
+
+#: lib/luks2/luks2_reencrypt.c:3058
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Kunne ikke skrive hotzoneområde startende på %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3063
+msgid "Failed to sync data."
+msgstr "Kunne ikke synkronisere data."
+
+#: lib/luks2/luks2_reencrypt.c:3071
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Kunne ikke opdatere metadata efter nuværende omkrypteringshotzone var fuldført."
+
+#: lib/luks2/luks2_reencrypt.c:3138
+msgid "Failed to write LUKS2 metadata."
+msgstr "Kunne ikke skrive LUKS2-metadata."
+
+#: lib/luks2/luks2_reencrypt.c:3161
+msgid "Failed to wipe backup segment data."
+msgstr "Kunne ikke rydde segmentdata for sikkerhedskopien."
+
+#: lib/luks2/luks2_reencrypt.c:3174
+msgid "Failed to disable reencryption requirement flag."
+msgstr "Kunne ikke deaktivere kravflag for omkrypteringen."
+
+#: lib/luks2/luks2_reencrypt.c:3182
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Der opstod en fatal fejl under omkryptering af kodestump startende på %<PRIu64>, %<PRIu64> sektorer i alt."
+
+#: lib/luks2/luks2_reencrypt.c:3191
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Genaktiver ikke enheden med mindre erstattet med fejlmål manuelt."
+
+#: lib/luks2/luks2_reencrypt.c:3240
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Kan ikke fortsætte med omkryptering. Uventet omkrypteringsstatus."
+
+#: lib/luks2/luks2_reencrypt.c:3246
+msgid "Missing or invalid reencrypt context."
+msgstr "Manglende eller ugyldig omkrypteringskontekst."
+
+#: lib/luks2/luks2_reencrypt.c:3253
+msgid "Failed to initialize reencryption device stack."
+msgstr "Kunne ikke initialisere enhedsstak for omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3272 lib/luks2/luks2_reencrypt.c:3308
+msgid "Failed to update reencryption context."
+msgstr "Kunne ikke opdatere omkrypteringskontekst."
+
+#: lib/luks2/luks2_token.c:262
+msgid "No free token slot."
+msgstr "Ingen frie symbolpladser."
+
+#: lib/luks2/luks2_token.c:269
+#, c-format
+msgid "Failed to create builtin token %s."
+msgstr "Kunne ikke oprette indbygget symbol %s."
+
+#: src/cryptsetup.c:163
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Kan ikke udføre verificering af adgangsfrase på ikke-tty-inddata."
+
+#: src/cryptsetup.c:216
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Parametre til kryptering af nøgleplads kan kun angives for LUKS2-enhed."
+
+#: src/cryptsetup.c:246 src/cryptsetup.c:955 src/cryptsetup.c:1280
+#: src/cryptsetup.c:3084 src/cryptsetup_reencrypt.c:716
+#: src/cryptsetup_reencrypt.c:786
+msgid "No known cipher specification pattern detected."
+msgstr "Ikke kendt specifikationsmønster for krypteringsalgoritme registreret."
+
+#: src/cryptsetup.c:254
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "ADVARSEL: Parameteren --hash bliver ignoreret i ren (plain) tilstand med nøglefil specificeret.\n"
+
+#: src/cryptsetup.c:262
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "ADVARSEL: Tilvalget --keyfile-size bliver ignoreret, læsestørrelsen er den samme som størrelsen for krypteringsnøglen.\n"
+
+#: src/cryptsetup.c:302
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Registrerede enhedssignaturer på %s. Videre behandling kan beskadige eksisterende data."
+
+#: src/cryptsetup.c:308 src/cryptsetup.c:1101 src/cryptsetup.c:1153
+#: src/cryptsetup.c:1257 src/cryptsetup.c:1330 src/cryptsetup.c:1985
+#: src/cryptsetup.c:2621 src/cryptsetup.c:2744 src/integritysetup.c:232
+msgid "Operation aborted.\n"
+msgstr "Operation afbrudt.\n"
+
+#: src/cryptsetup.c:376
+msgid "Option --key-file is required."
+msgstr "Tilvalget --key-file er krævet."
+
+#: src/cryptsetup.c:429
+msgid "Enter VeraCrypt PIM: "
+msgstr "Indtast VeraCrypt-PIM: "
+
+#: src/cryptsetup.c:438
+msgid "Invalid PIM value: parse error."
+msgstr "Ugyldig PIM-værdi: fortolkningsfejl."
+
+#: src/cryptsetup.c:441
+msgid "Invalid PIM value: 0."
+msgstr "Ugyldig PIM-værdi: 0."
+
+#: src/cryptsetup.c:444
+msgid "Invalid PIM value: outside of range."
+msgstr "Ugyldig PIM-værdi: uden for interval."
+
+#: src/cryptsetup.c:467
+msgid "No device header detected with this passphrase."
+msgstr "Intet enhedsteksthoved registreret med denne adgangsfrase."
+
+#: src/cryptsetup.c:536
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Enheden %s er ikke en gyldig BITLK-enhed."
+
+#: src/cryptsetup.c:571 src/cryptsetup.c:2012
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Teksthoveddump med diskenhedsnøgle er sensitiv information\n"
+"som giver adgang til krypteret partition uden adgangsfrase.\n"
+"Dette dump bør altid lagres krypteret et sikkert sted."
+
+#: src/cryptsetup.c:668
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Enheden %s er stadig aktiv og planlagt til udskudt fjernelse.\n"
+
+#: src/cryptsetup.c:696
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Ændring af størrelse på aktiv enhed kræver diskenhedsnøgle i nøglering men tilvalget --disable-keyring er ikke angivet."
+
+#: src/cryptsetup.c:833
+msgid "Benchmark interrupted."
+msgstr "Sammenligning afbrudt."
+
+#: src/cryptsetup.c:854
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s -\n"
+
+#: src/cryptsetup.c:856
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iterationer per sekund for %zu-bit nøgle\n"
+
+#: src/cryptsetup.c:870
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s .\n"
+
+#: src/cryptsetup.c:872
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iterationer, %5u hukommelse, %1u parallelle tråde (CPU'er) for %zu-bit nøgle (anmodet %u ms time)\n"
+
+#: src/cryptsetup.c:896
+msgid "Result of benchmark is not reliable."
+msgstr "Sammenligningens resultat er ikke troværdigt."
+
+#: src/cryptsetup.c:947
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Test bruger kun hukommelse omtrentlig (ingen lager-IO).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:981
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algoritme | Nøgle | Kryptering | Dekryptering\n"
+
+#: src/cryptsetup.c:985
+#, c-format
+msgid "Cipher %s is not available."
+msgstr "Krypteringsalgoritmen %s er ikke tilgængelig."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1005
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritme | Nøgle | Kryptering | Dekryptering\n"
+
+#: src/cryptsetup.c:1014
+msgid "N/A"
+msgstr "-"
+
+#: src/cryptsetup.c:1094
+msgid ""
+"Seems device does not require reencryption recovery.\n"
+"Do you want to proceed anyway?"
+msgstr ""
+"Ser ud til at enheden ikke kræver omkrypteringsgendannelse.\n"
+"Ønsker du at fortsætte alligevel?"
+
+#: src/cryptsetup.c:1100
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Fortsæt med LUKS2-omkrypteringsgendannelse?"
+
+#: src/cryptsetup.c:1109
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Indtast adgangsfrase for omkrypteringsgendannelse: "
+
+#: src/cryptsetup.c:1152
+msgid "Really try to repair LUKS device header?"
+msgstr "Skal LUKS-enhedsteksthovedet forsøges repareres?"
+
+#: src/cryptsetup.c:1171 src/integritysetup.c:145
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Rydder enhed for at initialisere integritetskontrolsum.\n"
+"Du kan afbryde dette ved at trykke på CTRL+c (resten af ikke ryddet enhed vil indeholder ugyldig kontrolsum).\n"
+
+#: src/cryptsetup.c:1193 src/integritysetup.c:167
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Kan ikke deaktivere midlertidig enhed %s."
+
+#: src/cryptsetup.c:1242
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Integritetstilvalg kan kun bruges for LUKS2-format."
+
+#: src/cryptsetup.c:1247 src/cryptsetup.c:1307
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Indstillinger for LUKS2-metadatastørrelse er ikke understøttet."
+
+#: src/cryptsetup.c:1264
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Kan ikke oprette teksthovedfilen %s."
+
+#: src/cryptsetup.c:1287 src/integritysetup.c:194 src/integritysetup.c:203
+#: src/integritysetup.c:212 src/integritysetup.c:283 src/integritysetup.c:292
+#: src/integritysetup.c:302
+msgid "No known integrity specification pattern detected."
+msgstr "Ikke kendt specifikationsmønster for krypteringsalgoritme registreret."
+
+#: src/cryptsetup.c:1300
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Kan ikke bruge %s på on-disk-teksthoved."
+
+#: src/cryptsetup.c:1324 src/integritysetup.c:226
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Dette vil uigenkaldeligt overskrive data på %s."
+
+#: src/cryptsetup.c:1365 src/cryptsetup.c:1699 src/cryptsetup.c:1766
+#: src/cryptsetup.c:1868 src/cryptsetup.c:1934 src/cryptsetup_reencrypt.c:546
+msgid "Failed to set pbkdf parameters."
+msgstr "Kunne ikke angive pbkdf-parametre."
+
+#: src/cryptsetup.c:1450
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Reduceret dataforskydning er kun tilladt for frakoblet LUKS-teksthoved."
+
+#: src/cryptsetup.c:1461 src/cryptsetup.c:1772
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Kan ikke bestemme nøglestørrelsen på diskenheden for LUKS uden nøglepladser, brug venligst tilvalget --key-size."
+
+#: src/cryptsetup.c:1499
+msgid "Device activated but cannot make flags persistent."
+msgstr "Enhed aktiveret men kan ikke gøre flag vedvarende."
+
+#: src/cryptsetup.c:1580 src/cryptsetup.c:1650
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Nøgleplads %d valgt for sletning."
+
+#: src/cryptsetup.c:1592 src/cryptsetup.c:1653
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Dette er den sidste nøgleplads. Enheden vil blive ubrugelig efter fjernelse af denne nøgle."
+
+#: src/cryptsetup.c:1593
+msgid "Enter any remaining passphrase: "
+msgstr "Indtast en eventuel tilbageværende adgangsfrase: "
+
+#: src/cryptsetup.c:1594 src/cryptsetup.c:1655
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operation afbrudt, nøglepladsen var IKKE ryddet.\n"
+
+#: src/cryptsetup.c:1632
+msgid "Enter passphrase to be deleted: "
+msgstr "Indtast adgangsfrase som skal slettes: "
+
+#: src/cryptsetup.c:1713 src/cryptsetup.c:1787 src/cryptsetup.c:1821
+msgid "Enter new passphrase for key slot: "
+msgstr "Indtast ny adgangsfrase for nøgleplads: "
+
+#: src/cryptsetup.c:1804 src/cryptsetup_reencrypt.c:1336
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Indtast en eventuel eksisterende adgangsfrase: "
+
+#: src/cryptsetup.c:1872
+msgid "Enter passphrase to be changed: "
+msgstr "Indtast adgangsfrase som skal ændres: "
+
+#: src/cryptsetup.c:1888 src/cryptsetup_reencrypt.c:1322
+msgid "Enter new passphrase: "
+msgstr "Indtast ny adgangsfrase: "
+
+#: src/cryptsetup.c:1938
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Indtast adgangsfrase for nøgleplads til konvertering: "
+
+#: src/cryptsetup.c:1962
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Kun et enhedsargument for isLuks-operation er understøttet."
+
+#: src/cryptsetup.c:2146 src/cryptsetup.c:2167
+msgid "Option --header-backup-file is required."
+msgstr "Tilvalget --header-backup-file er krævet."
+
+#: src/cryptsetup.c:2197
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s er ikke en cryptsetup-håndteret enhed."
+
+#: src/cryptsetup.c:2208
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Opdater er ikke understøttet for enhedstypen %s"
+
+#: src/cryptsetup.c:2250
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Metadataenhedstypen %s blev ikke genkendt."
+
+#: src/cryptsetup.c:2253
+msgid "Command requires device and mapped name as arguments."
+msgstr "Kommandoen kræver enhedsnavn og oversat navn som argumenter."
+
+#: src/cryptsetup.c:2275
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Denne operation vil slette alle nøglepladser på enheden %s.\n"
+"Enheden vil blive ubrugelig efter denne operation."
+
+#: src/cryptsetup.c:2282
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operation afbrudt, nøglepladser blev IKKE fjernet (wiped).\n"
+
+#: src/cryptsetup.c:2319
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Ugyldig LUKS-type, kun luks1 og luks2 er understøttet."
+
+#: src/cryptsetup.c:2337
+#, c-format
+msgid "Device is already %s type."
+msgstr "Enheden er allerede %s-type."
+
+#: src/cryptsetup.c:2342
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Denne operation vil konvertere %s til %s-format.\n"
+
+#: src/cryptsetup.c:2348
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operation afbrudt, enheden blev IKKE konverteret.\n"
+
+#: src/cryptsetup.c:2388
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Tilvalget --priority, --label eller --subsystem mangler."
+
+#: src/cryptsetup.c:2422 src/cryptsetup.c:2455 src/cryptsetup.c:2478
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Symbolet %d er ugyldigt."
+
+#: src/cryptsetup.c:2425 src/cryptsetup.c:2481
+#, c-format
+msgid "Token %d in use."
+msgstr "Symbolet %d er i brug."
+
+#: src/cryptsetup.c:2432
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Kunne ikke tilføje luks2-keyringsymbolet %d."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2503
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Kunne ikke tildele symbolet %d til nøglepladsen %d."
+
+#: src/cryptsetup.c:2458
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Symbolet %d er ikke i brug."
+
+#: src/cryptsetup.c:2493
+msgid "Failed to import token from file."
+msgstr "Kunne ikke importere symbol fra fil."
+
+#: src/cryptsetup.c:2518
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Kunne ikke indhente symbolet %d for eksport."
+
+#: src/cryptsetup.c:2533
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "parameteren --key-description er obligatorisk for symbol tilføj-handling."
+
+#: src/cryptsetup.c:2539 src/cryptsetup.c:2547
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Handling kræver specifik symbol. Brug parameteren --token-id."
+
+#: src/cryptsetup.c:2552
+#, c-format
+msgid "Invalid token operation %s."
+msgstr "Ugyldig symboloperation %s."
+
+#: src/cryptsetup.c:2607
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Automatisk registreret aktiv dm-enhed »%s« for dataenheden %s.\n"
+
+#: src/cryptsetup.c:2611
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Enheden %s er ikke en blokenhed.\n"
+
+#: src/cryptsetup.c:2613
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Kunne ikke automatisk registrere enheds-%s-holdere."
+
+#: src/cryptsetup.c:2615
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Kan ikke afklare om enheden %s er aktiv eller ej.\n"
+"Er du sikker på, at du ønsker at fortsætte med omkryptering i frakoblet\n"
+"tilstand?\n"
+"Det kan medføre dataødelæggelse, hvis enheden aktiveres.\n"
+"For at afvikle omkryptering i frakoblet tilstand bruges parameteren\n"
+"--active-name.\n"
+
+#: src/cryptsetup.c:2695
+msgid "Invalid LUKS device type."
+msgstr "Ugyldig LUKS-enhedstype."
+
+#: src/cryptsetup.c:2700
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Kryptering uden frakoblet teksthoved (--header) er ikke muligt uden størrelsesreduktion for dataenhed (--reduce-device-size)."
+
+#: src/cryptsetup.c:2705
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Anmodte dataforskydning skal være mindre end eller lig med halvdelen af --reduce-device-size parameter."
+
+#: src/cryptsetup.c:2714
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Justerer --reduce-device-size value til det dobbelte af --offset %<PRIu64> (sektorer).\n"
+
+#: src/cryptsetup.c:2718
+msgid "Encryption is supported only for LUKS2 format."
+msgstr "Kryptering er kun understøttet for formatet LUKS2."
+
+#: src/cryptsetup.c:2740
+#, c-format
+msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+msgstr "Registrerede LUKS-enhed på %s. Ønsker du at kryptere den LUKS-enhed igen?"
+
+#: src/cryptsetup.c:2755
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Midlertidig teksthovedfil %s findes allerede. Afbryder."
+
+#: src/cryptsetup.c:2757 src/cryptsetup.c:2764
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Kan ikke oprette midlertidig teksthovedfil %s."
+
+#: src/cryptsetup.c:2828
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s er nu aktiv og klar til kryptering via nettet.\n"
+
+#: src/cryptsetup.c:2992 src/cryptsetup.c:2998
+msgid "Not enough free keyslots for reencryption."
+msgstr "Ikke nok ledige nøglepladser for omkryptering."
+
+#: src/cryptsetup.c:3018 src/cryptsetup_reencrypt.c:1287
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Nøglefil kan kun bruges med --key-slot eller med præcis en aktiv nøgleplads."
+
+#: src/cryptsetup.c:3027 src/cryptsetup_reencrypt.c:1334
+#: src/cryptsetup_reencrypt.c:1345
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Indtast adgangsfrase for nøgleplads %d: "
+
+#: src/cryptsetup.c:3035
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Indtast adgangsfrase for nøgleplads %u: "
+
+#: src/cryptsetup.c:3202
+msgid "Command requires device as argument."
+msgstr "Kommandoen kræver enhed som argument."
+
+#: src/cryptsetup.c:3224
+msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+msgstr "Kun formatet LUKS2 er i øjeblikket understøttet. Brug venligst værktøjet cryptsetup-reencrypt for LUKS1."
+
+#: src/cryptsetup.c:3236
+msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+msgstr "Forældet frakoblet omkryptering er allerede i gang. Brug redskabet cryptsetup-reencrypt."
+
+#: src/cryptsetup.c:3246 src/cryptsetup_reencrypt.c:178
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Omkryptering af enhed med integritetsprofil er ikke understøttet."
+
+#: src/cryptsetup.c:3254
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "LUKS2-omkryptering er allerede initialiseret. Afbryder operation."
+
+#: src/cryptsetup.c:3258
+msgid "LUKS2 device is not in reencryption."
+msgstr "LUKS2-enheden er ikke i omkryptering."
+
+#: src/cryptsetup.c:3285
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<enhed> [--type <type>] [<navn>]"
+
+#: src/cryptsetup.c:3285 src/veritysetup.c:394 src/integritysetup.c:474
+msgid "open device as <name>"
+msgstr "åbn enhed som <navn>"
+
+#: src/cryptsetup.c:3286 src/cryptsetup.c:3287 src/cryptsetup.c:3288
+#: src/veritysetup.c:395 src/veritysetup.c:396 src/integritysetup.c:475
+#: src/integritysetup.c:476
+msgid "<name>"
+msgstr "<navn>"
+
+#: src/cryptsetup.c:3286 src/veritysetup.c:395 src/integritysetup.c:475
+msgid "close device (remove mapping)"
+msgstr "luk enhed (fjern oversættelse)"
+
+#: src/cryptsetup.c:3287
+msgid "resize active device"
+msgstr "ændr størrelse på aktiv enhed"
+
+#: src/cryptsetup.c:3288
+msgid "show device status"
+msgstr "vis enhedsstatus"
+
+#: src/cryptsetup.c:3289
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <krypteringsalgoritme>]"
+
+#: src/cryptsetup.c:3289
+msgid "benchmark cipher"
+msgstr "krypteringsalgoritme for sammenligning"
+
+#: src/cryptsetup.c:3290 src/cryptsetup.c:3291 src/cryptsetup.c:3292
+#: src/cryptsetup.c:3293 src/cryptsetup.c:3294 src/cryptsetup.c:3301
+#: src/cryptsetup.c:3302 src/cryptsetup.c:3303 src/cryptsetup.c:3304
+#: src/cryptsetup.c:3305 src/cryptsetup.c:3306 src/cryptsetup.c:3307
+#: src/cryptsetup.c:3308 src/cryptsetup.c:3309
+msgid "<device>"
+msgstr "<enhed>"
+
+#: src/cryptsetup.c:3290
+msgid "try to repair on-disk metadata"
+msgstr "prøv at reparere on-disk-metadata"
+
+#: src/cryptsetup.c:3291
+msgid "reencrypt LUKS2 device"
+msgstr "omkrypter LUKS2-enhed"
+
+#: src/cryptsetup.c:3292
+msgid "erase all keyslots (remove encryption key)"
+msgstr "slet alle nøglepladser (fjern krypteringsnøgle)"
+
+#: src/cryptsetup.c:3293
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "konverter LUKS fra/til LUKS2-format"
+
+#: src/cryptsetup.c:3294
+msgid "set permanent configuration options for LUKS2"
+msgstr "angiv permanente konfigurationstilvalg for LUKS2"
+
+#: src/cryptsetup.c:3295 src/cryptsetup.c:3296
+msgid "<device> [<new key file>]"
+msgstr "<enhed> [<ny nøglefil>]"
+
+#: src/cryptsetup.c:3295
+msgid "formats a LUKS device"
+msgstr "formaterer en LUKS-enhed"
+
+#: src/cryptsetup.c:3296
+msgid "add key to LUKS device"
+msgstr "tilføj nøgle til LUKS-enhed"
+
+#: src/cryptsetup.c:3297 src/cryptsetup.c:3298 src/cryptsetup.c:3299
+msgid "<device> [<key file>]"
+msgstr "<enhed> [<nøglefil>]"
+
+#: src/cryptsetup.c:3297
+msgid "removes supplied key or key file from LUKS device"
+msgstr "fjerner leveret nøgle eller nøglefil fra LUKS-enhed"
+
+#: src/cryptsetup.c:3298
+msgid "changes supplied key or key file of LUKS device"
+msgstr "ændrer leveret nøgle eller nøglefil for LUKS-enhed"
+
+#: src/cryptsetup.c:3299
+msgid "converts a key to new pbkdf parameters"
+msgstr "konverterer en nøgle til nye pbkdf-parametre"
+
+#: src/cryptsetup.c:3300
+msgid "<device> <key slot>"
+msgstr "<enhed> <nøgleplads>"
+
+#: src/cryptsetup.c:3300
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "rydder nøgle med nummer <nøgleplads> fra LUKS-enhed"
+
+#: src/cryptsetup.c:3301
+msgid "print UUID of LUKS device"
+msgstr "vis UUID for lUKS-enhed"
+
+#: src/cryptsetup.c:3302
+msgid "tests <device> for LUKS partition header"
+msgstr "tester <enhed> for LUKS-partitionsteksthoved"
+
+#: src/cryptsetup.c:3303
+msgid "dump LUKS partition information"
+msgstr "dump LUKS-partitionsinformation"
+
+#: src/cryptsetup.c:3304
+msgid "dump TCRYPT device information"
+msgstr "dump TCRYPT-enhedsinformation"
+
+#: src/cryptsetup.c:3305
+msgid "dump BITLK device information"
+msgstr "dump BITLK-enhedsinformation"
+
+#: src/cryptsetup.c:3306
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Suspender LUKS-enhed og ryd nøgle (alle IO'er fryses fast)"
+
+#: src/cryptsetup.c:3307
+msgid "Resume suspended LUKS device"
+msgstr "Genoptag suspenderet LUKS-enhed"
+
+#: src/cryptsetup.c:3308
+msgid "Backup LUKS device header and keyslots"
+msgstr "Lav sikkerhedskopi af LUKS-enhedsteksthoved og nøglepladser"
+
+#: src/cryptsetup.c:3309
+msgid "Restore LUKS device header and keyslots"
+msgstr "Gendan LUKS-teksthoved og nøglepladser"
+
+#: src/cryptsetup.c:3310
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <enhed>"
+
+#: src/cryptsetup.c:3310
+msgid "Manipulate LUKS2 tokens"
+msgstr "Manipuler LUKS2-symboler"
+
+#: src/cryptsetup.c:3328 src/veritysetup.c:412 src/integritysetup.c:492
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<handling> er en af:\n"
+
+#: src/cryptsetup.c:3334
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+msgstr ""
+"\n"
+"Du kan også bruge gamle <handling> syntaksaliasser:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+
+#: src/cryptsetup.c:3338
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<navn> er enheden at oprette under %s\n"
+"<enhed> er den krypterede enhed\n"
+"<nøgleplads> er LUKS-nøglens pladsnummer, der skal ændres\n"
+"<nøglefil> valgfri nøglefil for den nye nøgle for luksAddKey-handling\n"
+
+#: src/cryptsetup.c:3345
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Standardindkompileret metadataformat er %s (for luksFormat-handling).\n"
+
+#: src/cryptsetup.c:3350
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Standardindkompileret nøgle og adgangsfraseparametre.\n"
+"\tMaksimal nøglefilsstørrelse: %dkB, Maksimal interaktiv adgangsfraselængde %d (tegn)\n"
+"Standard-PBKDF for LUKS1: %s, iterationtid: %d (ms)\n"
+"Standard-PBKDF for LUKS2: %s\n"
+"\tTterationtid: %d, hukommelse krævet: %dkB, parallelle tråde: %d\n"
+
+#: src/cryptsetup.c:3361
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Standardindkompileret enhedskrypteringsalgoritmeparametre:\n"
+"\tloop-AES: %s, Nøgle %d bit\n"
+"\tplain: %s, Nøgle: %d bit, Adgangskodehashing: %s\n"
+"\tLUKS: %s, Nøgle: %d bit, LUKS-teksthovedhashing: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3370
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: Standardstørrelse på nøgle med XTS-tilstand (to interne nøgler) vil blive fordoblet.\n"
+
+#: src/cryptsetup.c:3386 src/veritysetup.c:569 src/integritysetup.c:634
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: kræver %s som argumenter"
+
+#: src/cryptsetup.c:3419 src/veritysetup.c:457 src/integritysetup.c:530
+#: src/cryptsetup_reencrypt.c:1600
+msgid "Show this help message"
+msgstr "Vis denne hjælpetekst"
+
+#: src/cryptsetup.c:3420 src/veritysetup.c:458 src/integritysetup.c:531
+#: src/cryptsetup_reencrypt.c:1601
+msgid "Display brief usage"
+msgstr "Vis en kort brugsmanual"
+
+#: src/cryptsetup.c:3421 src/veritysetup.c:459 src/integritysetup.c:532
+#: src/cryptsetup_reencrypt.c:1602
+msgid "Print package version"
+msgstr "Vis pakkeversion"
+
+#: src/cryptsetup.c:3425 src/veritysetup.c:463 src/integritysetup.c:536
+#: src/cryptsetup_reencrypt.c:1606
+msgid "Help options:"
+msgstr "Hjælpetilvalg:"
+
+#: src/cryptsetup.c:3426 src/veritysetup.c:464 src/integritysetup.c:537
+#: src/cryptsetup_reencrypt.c:1607
+msgid "Shows more detailed error messages"
+msgstr "Viser mere detaljerede fejlbeskeder"
+
+#: src/cryptsetup.c:3427 src/veritysetup.c:465 src/integritysetup.c:538
+#: src/cryptsetup_reencrypt.c:1608
+msgid "Show debug messages"
+msgstr "Vis fejlsøgningsbeskeder"
+
+#: src/cryptsetup.c:3428
+msgid "Show debug messages including JSON metadata"
+msgstr "Vis fejlsøgningsbeskeder inklusive JSON-metadata"
+
+#: src/cryptsetup.c:3429 src/cryptsetup_reencrypt.c:1610
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "Krypteringsalgoritmen brugt til at kryptere disken (se /proc/crypto)"
+
+#: src/cryptsetup.c:3430 src/cryptsetup_reencrypt.c:1612
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "Hashen brugt til at oprette krypteringsnøglen fra adgangsfrasen"
+
+#: src/cryptsetup.c:3431
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Verificerer adgangsfrasen ved at anmode om den to gange"
+
+#: src/cryptsetup.c:3432 src/cryptsetup_reencrypt.c:1614
+msgid "Read the key from a file"
+msgstr "Læs nøglen fra en fil"
+
+#: src/cryptsetup.c:3433
+msgid "Read the volume (master) key from file."
+msgstr "Læs diskenhedens (master) nøgle fra fil."
+
+#: src/cryptsetup.c:3434
+msgid "Dump volume (master) key instead of keyslots info"
+msgstr "Dump diskenheds (master) nøgle i stedet for information om nøgleplads"
+
+#: src/cryptsetup.c:3435 src/cryptsetup_reencrypt.c:1611
+msgid "The size of the encryption key"
+msgstr "Krypteringsnøglens størrelse"
+
+#: src/cryptsetup.c:3435 src/cryptsetup.c:3495 src/integritysetup.c:556
+#: src/integritysetup.c:560 src/integritysetup.c:564
+#: src/cryptsetup_reencrypt.c:1611
+msgid "BITS"
+msgstr "BIT"
+
+#: src/cryptsetup.c:3436 src/cryptsetup_reencrypt.c:1627
+msgid "Limits the read from keyfile"
+msgstr "Begræns læsningen fra nøglefil"
+
+#: src/cryptsetup.c:3436 src/cryptsetup.c:3437 src/cryptsetup.c:3438
+#: src/cryptsetup.c:3439 src/cryptsetup.c:3442 src/cryptsetup.c:3492
+#: src/cryptsetup.c:3493 src/cryptsetup.c:3501 src/cryptsetup.c:3502
+#: src/veritysetup.c:468 src/veritysetup.c:469 src/veritysetup.c:470
+#: src/veritysetup.c:473 src/veritysetup.c:474 src/integritysetup.c:545
+#: src/integritysetup.c:551 src/integritysetup.c:552
+#: src/cryptsetup_reencrypt.c:1626 src/cryptsetup_reencrypt.c:1627
+#: src/cryptsetup_reencrypt.c:1628 src/cryptsetup_reencrypt.c:1629
+msgid "bytes"
+msgstr "byte"
+
+#: src/cryptsetup.c:3437 src/cryptsetup_reencrypt.c:1626
+msgid "Number of bytes to skip in keyfile"
+msgstr "Antallet af byte at udelade i nøglefil"
+
+#: src/cryptsetup.c:3438
+msgid "Limits the read from newly added keyfile"
+msgstr "Begræns læsningnen fra nyligt tilføjet nøglefil"
+
+#: src/cryptsetup.c:3439
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "Antallet af byte at udelade i senest tilføjet nøglefil"
+
+#: src/cryptsetup.c:3440
+msgid "Slot number for new key (default is first free)"
+msgstr "Pladsnummer for ny nøgle (standard er den første ledige)"
+
+#: src/cryptsetup.c:3441
+msgid "The size of the device"
+msgstr "Størrelse på enheden"
+
+#: src/cryptsetup.c:3441 src/cryptsetup.c:3443 src/cryptsetup.c:3444
+#: src/cryptsetup.c:3450 src/integritysetup.c:546 src/integritysetup.c:553
+msgid "SECTORS"
+msgstr "SEKTORER"
+
+#: src/cryptsetup.c:3442 src/cryptsetup_reencrypt.c:1629
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "Brug kun specificeret enhedstørrelse (ignorer resten af enheden). FARLIGT!"
+
+#: src/cryptsetup.c:3443
+msgid "The start offset in the backend device"
+msgstr "Startforskydningen i motorenheden"
+
+#: src/cryptsetup.c:3444
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Antal sektorer med krypterede data som skal udelades i begyndelsen"
+
+#: src/cryptsetup.c:3445
+msgid "Create a readonly mapping"
+msgstr "Opret en skrivebeskyttet oversættelse"
+
+#: src/cryptsetup.c:3446 src/integritysetup.c:539
+#: src/cryptsetup_reencrypt.c:1617
+msgid "Do not ask for confirmation"
+msgstr "Anmod ikke om bekræftelse"
+
+#: src/cryptsetup.c:3447
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Tidsudløb for interaktiv adgangsfraseprompt (i sekunder)"
+
+#: src/cryptsetup.c:3447 src/cryptsetup.c:3448 src/integritysetup.c:540
+#: src/cryptsetup_reencrypt.c:1618
+msgid "secs"
+msgstr "sek"
+
+#: src/cryptsetup.c:3448 src/integritysetup.c:540
+#: src/cryptsetup_reencrypt.c:1618
+msgid "Progress line update (in seconds)"
+msgstr "Statuslinjeopdatering (i sekunder)"
+
+#: src/cryptsetup.c:3449 src/cryptsetup_reencrypt.c:1619
+msgid "How often the input of the passphrase can be retried"
+msgstr "Hvor ofte inddata for adgangsfrasen kan indhentes"
+
+#: src/cryptsetup.c:3450
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Juster belastning ved <n> sektorgrænser - for luksFormat"
+
+#: src/cryptsetup.c:3451
+msgid "File with LUKS header and keyslots backup"
+msgstr "Fil med LUKS-teksthoved og sikkerhedskopi af nøglepladser"
+
+#: src/cryptsetup.c:3452 src/cryptsetup_reencrypt.c:1620
+msgid "Use /dev/random for generating volume key"
+msgstr "Brug /dev/random til oprettelse af diskenhedsnøgle"
+
+#: src/cryptsetup.c:3453 src/cryptsetup_reencrypt.c:1621
+msgid "Use /dev/urandom for generating volume key"
+msgstr "Brug /dev/urandom til oprettelse af diskenhedsnøgle"
+
+#: src/cryptsetup.c:3454
+msgid "Share device with another non-overlapping crypt segment"
+msgstr "Del enhed med et andet ikkeoverlappende kryptsegment"
+
+#: src/cryptsetup.c:3455 src/veritysetup.c:477
+msgid "UUID for device to use"
+msgstr "UUID som enheden skal bruge"
+
+#: src/cryptsetup.c:3456
+msgid "Allow discards (aka TRIM) requests for device"
+msgstr "Tillader fjernelsesforespørgsler (a.k.a. TRIM) for enhed"
+
+#: src/cryptsetup.c:3457 src/cryptsetup_reencrypt.c:1638
+msgid "Device or file with separated LUKS header"
+msgstr "Enhed eller fil med adskilt LUKS-teksthoved"
+
+#: src/cryptsetup.c:3458
+msgid "Do not activate device, just check passphrase"
+msgstr "Aktiver ikke enhed, kontroller bare adgangsfrase"
+
+#: src/cryptsetup.c:3459
+msgid "Use hidden header (hidden TCRYPT device)"
+msgstr "Brug skjult teksthoved (skjult TCRYPT-enhed)"
+
+#: src/cryptsetup.c:3460
+msgid "Device is system TCRYPT drive (with bootloader)"
+msgstr "Enhed er system-TCRYPT-drev (med opstartsindlæser)"
+
+#: src/cryptsetup.c:3461
+msgid "Use backup (secondary) TCRYPT header"
+msgstr "Brug sikkerhedskopi (sekundær) TCRYPT-teksthoved"
+
+#: src/cryptsetup.c:3462
+msgid "Scan also for VeraCrypt compatible device"
+msgstr "Skan også for VeraCrypt-kompatibel enhed"
+
+#: src/cryptsetup.c:3463
+msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Personlig iterationmultiplikator for VeraCrypt-kompatibel enhed"
+
+#: src/cryptsetup.c:3464
+msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Forespørg personlig iterationmultiplikator for VeraCrypt-kompatibel enhed"
+
+#: src/cryptsetup.c:3465
+msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+msgstr "Type for enhedsmetadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#: src/cryptsetup.c:3466
+msgid "Disable password quality check (if enabled)"
+msgstr "Deaktiver kontrol af adgangskodens kvalitet (hvis aktiveret)"
+
+#: src/cryptsetup.c:3467
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+msgstr "Brug tilvalgene dm-crypt og same_cpu_crypt for ydelseskompatibilitet"
+
+#: src/cryptsetup.c:3468
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+msgstr "Brug tilvalgene dm-crypt og submit_from_crypt_cpus for ydelseskompatibilitet"
+
+#: src/cryptsetup.c:3469
+msgid "Device removal is deferred until the last user closes it"
+msgstr "Enhedsfjernelse er udskudt indtil den sidste bruger lukker enheden"
+
+#: src/cryptsetup.c:3470
+msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+msgstr "Brug global lås til at serialisere memory-hard-PBKDF (OOM-alternativ)"
+
+#: src/cryptsetup.c:3471
+msgid "PBKDF iteration time for LUKS (in ms)"
+msgstr "PBKDF-iterationstid for LUKS (i ms)"
+
+#: src/cryptsetup.c:3471 src/cryptsetup_reencrypt.c:1616
+msgid "msecs"
+msgstr "ms"
+
+#: src/cryptsetup.c:3472 src/cryptsetup_reencrypt.c:1634
+msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+msgstr "PBKDF-algoritme (for LUKS2): argon2i, argon2id, pbkdf2"
+
+#: src/cryptsetup.c:3473 src/cryptsetup_reencrypt.c:1635
+msgid "PBKDF memory cost limit"
+msgstr "PBKDF-hukommelsesomkostningsbegrænsning"
+
+#: src/cryptsetup.c:3473 src/cryptsetup_reencrypt.c:1635
+msgid "kilobytes"
+msgstr "kilobyte"
+
+#: src/cryptsetup.c:3474 src/cryptsetup_reencrypt.c:1636
+msgid "PBKDF parallel cost"
+msgstr "PBKDF-parallel omkostning"
+
+#: src/cryptsetup.c:3474 src/cryptsetup_reencrypt.c:1636
+msgid "threads"
+msgstr "tråde"
+
+#: src/cryptsetup.c:3475 src/cryptsetup_reencrypt.c:1637
+msgid "PBKDF iterations cost (forced, disables benchmark)"
+msgstr "PBKDF-iterationsomkostning (tvunget, deaktiverer sammenligning)"
+
+#: src/cryptsetup.c:3476
+msgid "Keyslot priority: ignore, normal, prefer"
+msgstr "Nøglepladsprioritet: ignore, normal, prefer"
+
+#: src/cryptsetup.c:3477
+msgid "Disable locking of on-disk metadata"
+msgstr "Deaktiver låsning af on-disk-metadata"
+
+#: src/cryptsetup.c:3478
+msgid "Disable loading volume keys via kernel keyring"
+msgstr "Deaktiver indlæsning af diskenhedsnøgler via kernenøglering"
+
+#: src/cryptsetup.c:3479
+msgid "Data integrity algorithm (LUKS2 only)"
+msgstr "Dataintegritetsalgoritme (kun LUKS2)"
+
+#: src/cryptsetup.c:3480 src/integritysetup.c:567
+msgid "Disable journal for integrity device"
+msgstr "Deaktiver journal for integritetsenhed"
+
+#: src/cryptsetup.c:3481 src/integritysetup.c:541
+msgid "Do not wipe device after format"
+msgstr "Ryd ikke enhed efter formatering"
+
+#: src/cryptsetup.c:3482 src/integritysetup.c:571
+msgid "Use inefficient legacy padding (old kernels)"
+msgstr "Brug ineffektive forældede mellemrum (gamle kerner)"
+
+#: src/cryptsetup.c:3483
+msgid "Do not ask for passphrase if activation by token fails"
+msgstr "Spørg ikke om adgangsfrase hvis aktivering via symbol mislykkes"
+
+#: src/cryptsetup.c:3484
+msgid "Token number (default: any)"
+msgstr "Symbolnummer (standard: alle)"
+
+#: src/cryptsetup.c:3485
+msgid "Key description"
+msgstr "Nøglebeskrivelse"
+
+#: src/cryptsetup.c:3486
+msgid "Encryption sector size (default: 512 bytes)"
+msgstr "Sektorstørrelse for kryptering (standard: 512 byte)"
+
+#: src/cryptsetup.c:3487
+msgid "Set activation flags persistent for device"
+msgstr "Angiv aktiveringsflag vedvarende for enhed"
+
+#: src/cryptsetup.c:3488
+msgid "Set label for the LUKS2 device"
+msgstr "Angiv etiket for LUKS2-enhed"
+
+#: src/cryptsetup.c:3489
+msgid "Set subsystem label for the LUKS2 device"
+msgstr "Angiv undersystemetiket for LUKS2-enhed"
+
+#: src/cryptsetup.c:3490
+msgid "Create unbound (no assigned data segment) LUKS2 keyslot"
+msgstr "Opret ubunden (intet tildelt datasegment) LUKS2-nøgleplads"
+
+#: src/cryptsetup.c:3491
+msgid "Read or write the json from or to a file"
+msgstr "Læs eller skriv json fra eller til en fil"
+
+#: src/cryptsetup.c:3492
+msgid "LUKS2 header metadata area size"
+msgstr "Størrelse på metadataområdet for LUKS2-teksthovedet"
+
+#: src/cryptsetup.c:3493
+msgid "LUKS2 header keyslots area size"
+msgstr "Størrelse på nøglepladsområdet for LUKS2-teksthovedet"
+
+#: src/cryptsetup.c:3494
+msgid "Refresh (reactivate) device with new parameters"
+msgstr "Opdater (genaktiver) enhed med nye parametre"
+
+#: src/cryptsetup.c:3495
+msgid "LUKS2 keyslot: The size of the encryption key"
+msgstr "LUKS2-nøgleplads: Krypteringsnøglens størrelse"
+
+#: src/cryptsetup.c:3496
+msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+msgstr "LUKS2-nøgleplads: krypteringsalgoritmen brugt for nøglepladskryptering"
+
+#: src/cryptsetup.c:3497
+msgid "Encrypt LUKS2 device (in-place encryption)."
+msgstr "Krypter LUKS2-enhed (på stedet kryptering)."
+
+#: src/cryptsetup.c:3498
+msgid "Decrypt LUKS2 device (remove encryption)."
+msgstr "Dekrypter LUKS2-enhed (fjern kryptering)."
+
+#: src/cryptsetup.c:3499
+msgid "Initialize LUKS2 reencryption in metadata only."
+msgstr "Initialiser LUKS2-omkryptering kun i metadata."
+
+#: src/cryptsetup.c:3500
+msgid "Resume initialized LUKS2 reencryption only."
+msgstr "Genoptag kun initialiseret LUKS2-omkryptering."
+
+#: src/cryptsetup.c:3501 src/cryptsetup_reencrypt.c:1628
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "Reducer dataenhedstørrelse (flyt dataforskydning). FARLIGT!"
+
+#: src/cryptsetup.c:3502
+msgid "Maximal reencryption hotzone size."
+msgstr "Maksimal størrelse for omkrypteringshotzone."
+
+#: src/cryptsetup.c:3503
+msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+msgstr "Resilience-type for omkrypteringshotzonen (checksum,journal,none)"
+
+#: src/cryptsetup.c:3504
+msgid "Reencryption hotzone checksums hash"
+msgstr "Kontrolsumshash for omkrypteringshotzonen"
+
+#: src/cryptsetup.c:3505
+msgid "Override device autodetection of dm device to be reencrypted"
+msgstr "Overskriv automatisk registrering af enhed for dm-enhed der skal omkrypteres"
+
+#: src/cryptsetup.c:3521 src/veritysetup.c:499 src/integritysetup.c:587
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[TILVALG...] <handling> <handling-specifik>"
+
+#: src/cryptsetup.c:3572 src/veritysetup.c:533 src/integritysetup.c:598
+msgid "Argument <action> missing."
+msgstr "Argument <handling> mangler."
+
+#: src/cryptsetup.c:3641 src/veritysetup.c:564 src/integritysetup.c:629
+msgid "Unknown action."
+msgstr "Ukendt handling."
+
+#: src/cryptsetup.c:3651
+msgid "Parameter --refresh is only allowed with open or refresh commands.\n"
+msgstr "Parameteren --refresh er kun tilladt for kommandoerne open (åbn) eller refresh (opdater).\n"
+
+#: src/cryptsetup.c:3656
+msgid "Options --refresh and --test-passphrase are mutually exclusive.\n"
+msgstr "Tilvalgene --refresh og --test-passphrase udelukker hinanden.\n"
+
+#: src/cryptsetup.c:3661
+msgid "Option --deferred is allowed only for close command.\n"
+msgstr "Tilvalget --deferred er kun tilladt for kommandoen close (luk).\n"
+
+#: src/cryptsetup.c:3666
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "Tilvalget --shared er kun tilladt for åbning af en ren enhed.\n"
+
+#: src/cryptsetup.c:3671
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "Tilvalget --allow-discards er kun tilladt for åbne operationer.\n"
+
+#: src/cryptsetup.c:3676
+msgid "Option --persistent is allowed only for open operation.\n"
+msgstr "Tilvalget --persistent er kun tilladt for åben operation.\n"
+
+#: src/cryptsetup.c:3681
+msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation.\n"
+msgstr "Tilvalget --serialize-memory-hard-pbkdf er kun tilladt for åbne operationer.\n"
+
+#: src/cryptsetup.c:3686
+msgid "Option --persistent is not allowed with --test-passphrase.\n"
+msgstr "Tilvalget --persistent er ikke tilladt med --test-passphrase.\n"
+
+#: src/cryptsetup.c:3696
+msgid ""
+"Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+"open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"Tilvalget --key-size er kun tilladt for luksFormat, luksAddKey,\n"
+"åbn- og sammenligningshandlinger. For at begrænse læsning fra nøglefilen bruges\n"
+"--keyfile-size=(bytes)."
+
+#: src/cryptsetup.c:3702
+msgid "Option --integrity is allowed only for luksFormat (LUKS2).\n"
+msgstr "Tilvalget --integrity er kun tilladt for luksFormat (LUKS2).\n"
+
+#: src/cryptsetup.c:3707
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension.\n"
+msgstr "Tilvalget --integrity-no-wipe kan kun bruges for formathandling med integritetudvidelse.\n"
+
+#: src/cryptsetup.c:3713
+msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations.\n"
+msgstr "Tilvalget --label og --subsystem er kun tilladt for luksFormat og config LUKS2-operationer.\n"
+
+#: src/cryptsetup.c:3719
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT and BITLK devices.\n"
+msgstr "Tilvalget --test-passphrase er kun tilladt for åbning af LUKS- TCRYPT- og BITLK-enheder.\n"
+
+#: src/cryptsetup.c:3724 src/cryptsetup_reencrypt.c:1701
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Nøglestørrelse skal gå op i 8 bit"
+
+#: src/cryptsetup.c:3730 src/cryptsetup_reencrypt.c:1387
+#: src/cryptsetup_reencrypt.c:1706
+msgid "Key slot is invalid."
+msgstr "Nøgleplads er ugyldig."
+
+#: src/cryptsetup.c:3737
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Tilvalget --key-file har forrang over specificeret nøglefilsargument."
+
+#: src/cryptsetup.c:3744 src/veritysetup.c:576 src/integritysetup.c:650
+#: src/cryptsetup_reencrypt.c:1680
+msgid "Negative number for option not permitted."
+msgstr "Negativ nummer for tilvalg er ikke tilladt."
+
+#: src/cryptsetup.c:3748
+msgid "Only one --key-file argument is allowed."
+msgstr "Kun et argument for --key-file er tilladt."
+
+#: src/cryptsetup.c:3752 src/cryptsetup_reencrypt.c:1672
+#: src/cryptsetup_reencrypt.c:1710
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Kun et af tilvalgene --use-[u]random er tilladt."
+
+#: src/cryptsetup.c:3756
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "Tilvalget --use-[u]random er kun tilladt for luksFormat."
+
+#: src/cryptsetup.c:3760
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "Tilvalget --uid er kun tilladt for luksFormat og luksUUID."
+
+#: src/cryptsetup.c:3764
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "Tilvalget --align-payload er kun tilladt for luksFormat."
+
+#: src/cryptsetup.c:3768
+msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+msgstr "Tilvalgene --luks2-metadata-size og --opt-luks2-keyslots-size er kun tilladt for luksFormat med LUKS2."
+
+#: src/cryptsetup.c:3773
+msgid "Invalid LUKS2 metadata size specification."
+msgstr "Ugyldig specifikation for størrelsen på LUKS2-metadata."
+
+#: src/cryptsetup.c:3777
+msgid "Invalid LUKS2 keyslots size specification."
+msgstr "Ugyldig specifikation for størrelsen på LUKS2-nøgleplads."
+
+#: src/cryptsetup.c:3781
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Tilvalgene --align-payload og --offset kan ikke kombineres."
+
+#: src/cryptsetup.c:3787
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "Tilvalget --skip er kun understøttet for åbning af plain- og loopaes-enheder.\n"
+
+#: src/cryptsetup.c:3794
+msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption.\n"
+msgstr "Tilvalget --offset er kun understøttet for åbning af plain- og loopaes-enheder, luksFormat og enhedsomkryptering.\n"
+
+#: src/cryptsetup.c:3800
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "Tilvalgene --tcrypt-hidden, --tcrypt-system eller --tcrypt-backup er kun understøttet for TCRYPT-enhed.\n"
+
+#: src/cryptsetup.c:3805
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "Tilvaget --tcrypt-hidden kan ikke kombineres med --allow-discards.\n"
+
+#: src/cryptsetup.c:3810
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "Tilvalget --veracrypt er kun understøttet for TCRYPT-enhedstype.\n"
+
+#: src/cryptsetup.c:3816
+msgid "Invalid argument for parameter --veracrypt-pim supplied.\n"
+msgstr "Ugyldigt argument for parameteren --veracrypt-pim angivet.\n"
+
+#: src/cryptsetup.c:3820
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "Tilvalget --veracrypt-pim er kun understøttet for VeraCrypt-kompatible enheder.\n"
+
+#: src/cryptsetup.c:3828
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "Tilvalget --veracrypt-query-pim er kun understøttet for VeraCrypt-kompatible enheder.\n"
+
+#: src/cryptsetup.c:3832
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive.\n"
+msgstr "Tilvalgene --veracrypt-pim og --veracrypt-query-pm udelukker hinanden.\n"
+
+#: src/cryptsetup.c:3839
+msgid "Option --priority can be only ignore/normal/prefer.\n"
+msgstr "Tilvalget --priority kan kun være ignore/normal/prefer.\n"
+
+#: src/cryptsetup.c:3844
+msgid "Keyslot specification is required.\n"
+msgstr "Nøglepladsspecifikation er krævet.\n"
+
+#: src/cryptsetup.c:3849 src/cryptsetup_reencrypt.c:1686
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id.\n"
+msgstr "Adgangskodebaseret nøgleudledningsfunktion (PBKDF) kan kun være pbkdf2 eller argon2i/argon2id.\n"
+
+#: src/cryptsetup.c:3854 src/cryptsetup_reencrypt.c:1691
+msgid "PBKDF forced iterations cannot be combined with iteration time option.\n"
+msgstr "PBKDF-tvungne iterationer kan ikke kombineres med tilvalg for iterationstid.\n"
+
+#: src/cryptsetup.c:3860
+msgid "Sector size option is not supported for this command.\n"
+msgstr "Tilvalg for sektorstørrelse er ikke understøttet for denne kommando.\n"
+
+#: src/cryptsetup.c:3866
+msgid "Unsupported encryption sector size.\n"
+msgstr "Krypteringsektorstørrelsen er ikke understøttet.\n"
+
+#: src/cryptsetup.c:3871
+msgid "Key size is required with --unbound option.\n"
+msgstr "Nøglestørrelse er krævet med tilvalget --unbound.\n"
+
+#: src/cryptsetup.c:3876
+msgid "Option --unbound may be used only with luksAddKey action.\n"
+msgstr "Tilvalget --unbound kan kun bruges med luksAddKey-handlingen.\n"
+
+#: src/cryptsetup.c:3881
+msgid "Option --refresh may be used only with open action.\n"
+msgstr "Tilvalget --refresh kan kun bruges med open-handlingen.\n"
+
+#: src/cryptsetup.c:3892
+msgid "Cannot disable metadata locking.\n"
+msgstr "Kan ikke deaktivere metadatalåsning.\n"
+
+#: src/cryptsetup.c:3902
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Ugyldig maksimal størrelsesspecifikation for omkrypteringshotzonen."
+
+#: src/cryptsetup.c:3910 src/cryptsetup_reencrypt.c:1715
+#: src/cryptsetup_reencrypt.c:1720
+msgid "Invalid device size specification."
+msgstr "Ugyldig specifikation for enhedsstørrelse."
+
+#: src/cryptsetup.c:3913
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Maksimal reduceringsstørrelse for enhed er 1 GiB."
+
+#: src/cryptsetup.c:3916 src/cryptsetup_reencrypt.c:1726
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Reducer størrelse skal være multiplum af 512 byte sektor."
+
+#: src/cryptsetup.c:3921
+msgid "Invalid data size specification."
+msgstr "Ugyldig størrelsesspecifikation for data."
+
+#: src/cryptsetup.c:3926
+msgid "Reduce size overflow."
+msgstr "Reducer størrelsesoverløb."
+
+#: src/cryptsetup.c:3930
+msgid "LUKS2 decryption requires option --header."
+msgstr "LUKS2-omkryptering kræver tilvalget --header."
+
+#: src/cryptsetup.c:3934
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Enhedsstørrelse skal være multiplum af 512 byte sektor."
+
+#: src/cryptsetup.c:3938
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Tilvalgene --reduce-device-size og --data-size kan ikke kombineres."
+
+#: src/cryptsetup.c:3942
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Tilvalgene --device-size og --size kan ikke kombineres."
+
+#: src/veritysetup.c:66
+msgid "Invalid salt string specified."
+msgstr "Ugyldig salt-streng angivet."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Kan ikke oprette hashaftryk %s for skriving."
+
+#: src/veritysetup.c:107
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Kan ikke oprette FEC-aftryk %s for skriving."
+
+#: src/veritysetup.c:179
+msgid "Invalid root hash string specified."
+msgstr "Ugyldig root-hash-streng angivet."
+
+#: src/veritysetup.c:187
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Ugyldig signaturfil %s."
+
+#: src/veritysetup.c:194
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Kan ikke læse signaturfilen %s."
+
+#: src/veritysetup.c:392
+msgid "<data_device> <hash_device>"
+msgstr "<data_enhed> <hash_device>"
+
+#: src/veritysetup.c:392 src/integritysetup.c:473
+msgid "format device"
+msgstr "formater enhed"
+
+#: src/veritysetup.c:393
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<data_enhed> <hash_enhed> <root_hash>"
+
+#: src/veritysetup.c:393
+msgid "verify device"
+msgstr "verificer enhed"
+
+#: src/veritysetup.c:394
+msgid "<data_device> <name> <hash_device> <root_hash>"
+msgstr "<data_enhed> <navn> <hash_enhed> <root_hash>"
+
+#: src/veritysetup.c:396 src/integritysetup.c:476
+msgid "show active device status"
+msgstr "vis aktiv enhedsstatus"
+
+#: src/veritysetup.c:397
+msgid "<hash_device>"
+msgstr "<hash_enhed>"
+
+#: src/veritysetup.c:397 src/integritysetup.c:477
+msgid "show on-disk information"
+msgstr "vis on-disk-information"
+
+#: src/veritysetup.c:416
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<navn> er enheden der skal opretttes under %s\n"
+"<data_enhed> er dataenheden\n"
+"<hash_enhed> er enheden indeholdende verifikationsdata\n"
+"<root_hash> hash for root-knuden på <hash_enhed>\n"
+
+#: src/veritysetup.c:423
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Standardindkompilerede dm-verity-parametre:\n"
+"\tHash: %s, Databok (byte): %u, Hashblok (byte): %u, Salt-str.: %u, Hashformat: %u\n"
+
+#: src/veritysetup.c:466
+msgid "Do not use verity superblock"
+msgstr "Brug ikke verity-superblok"
+
+#: src/veritysetup.c:467
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "Formatype (1 - normal, 0 - original Chrome OS)"
+
+#: src/veritysetup.c:467
+msgid "number"
+msgstr "nummer"
+
+#: src/veritysetup.c:468
+msgid "Block size on the data device"
+msgstr "Blokstørrelse på dataenheden"
+
+#: src/veritysetup.c:469
+msgid "Block size on the hash device"
+msgstr "Blokstørrelse på hashenheden"
+
+#: src/veritysetup.c:470
+msgid "FEC parity bytes"
+msgstr "FEC-paritetbyte"
+
+#: src/veritysetup.c:471
+msgid "The number of blocks in the data file"
+msgstr "Antallet af blokke i datafilen"
+
+#: src/veritysetup.c:471
+msgid "blocks"
+msgstr "blokke"
+
+#: src/veritysetup.c:472
+msgid "Path to device with error correction data"
+msgstr "Sti til enhed med fejlkorrektionsdata"
+
+#: src/veritysetup.c:472 src/integritysetup.c:543
+msgid "path"
+msgstr "sti"
+
+#: src/veritysetup.c:473
+msgid "Starting offset on the hash device"
+msgstr "Starter forskydning på hashenheden"
+
+#: src/veritysetup.c:474
+msgid "Starting offset on the FEC device"
+msgstr "Starter forskydning på FEC-enheden"
+
+#: src/veritysetup.c:475
+msgid "Hash algorithm"
+msgstr "Hashalgoritme"
+
+#: src/veritysetup.c:475
+msgid "string"
+msgstr "streng"
+
+#: src/veritysetup.c:476
+msgid "Salt"
+msgstr "Salt"
+
+#: src/veritysetup.c:476
+msgid "hex string"
+msgstr "hex-streng"
+
+#: src/veritysetup.c:478
+msgid "Path to root hash signature file"
+msgstr "Stil til roothash-signaturfil"
+
+#: src/veritysetup.c:479
+msgid "Restart kernel if corruption is detected"
+msgstr "Genstart kerne hvis korruption er registreret"
+
+#: src/veritysetup.c:480
+msgid "Ignore corruption, log it only"
+msgstr "Ignorer korruption, log den kun"
+
+#: src/veritysetup.c:481
+msgid "Do not verify zeroed blocks"
+msgstr "Bekræft ikke nulstillede blokke"
+
+#: src/veritysetup.c:482
+msgid "Verify data block only the first time it is read"
+msgstr "Verificer kun datablok første gang den læses"
+
+#: src/veritysetup.c:582
+msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation.\n"
+msgstr "Tilvalgene --ignore-corruption, --restart-on-corruption eller --ignore-zero-blocks er kun tilladt for åben operation.\n"
+
+#: src/veritysetup.c:587
+msgid "Option --root-hash-signature can be used only for open operation.\n"
+msgstr "Tilvalget --root-hash-signature kan kun bruges til åben operation.\n"
+
+#: src/veritysetup.c:592
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together.\n"
+msgstr "Tilvalgene --ignore-corruption og --restart-on-corruption kan ikke bruges sammen.\n"
+
+#: src/integritysetup.c:83 src/utils_password.c:305
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Kan ikke læse nøglefilen %s."
+
+#: src/integritysetup.c:87 src/utils_password.c:310
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Kan ikke læse %d byte fra nøglefilen %s."
+
+#: src/integritysetup.c:253
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formateret med mærkestørrelse %u, intern integritet %s.\n"
+
+#: src/integritysetup.c:473 src/integritysetup.c:477
+msgid "<integrity_device>"
+msgstr "<integritet_enhed>"
+
+#: src/integritysetup.c:474
+msgid "<integrity_device> <name>"
+msgstr "<integritet_enhed> <navn>"
+
+#: src/integritysetup.c:496
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<navn> er enheden der skal opretttes under %s\n"
+"<integritet_enhed> er enheden indeholdende data med integritetsmærker\n"
+
+#: src/integritysetup.c:501
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+msgstr ""
+"\n"
+"Standardindkompilerede dm-integrity-parametre:\n"
+"\tkontrolsumalgoritme: %s\n"
+
+#: src/integritysetup.c:543
+msgid "Path to data device (if separated)"
+msgstr "Sti til dataenhed (hvis adskilt)"
+
+#: src/integritysetup.c:545
+msgid "Journal size"
+msgstr "Journalstørrelse"
+
+#: src/integritysetup.c:546
+msgid "Interleave sectors"
+msgstr "Interleave-sektorer"
+
+#: src/integritysetup.c:547
+msgid "Journal watermark"
+msgstr "Journalvandmærke"
+
+#: src/integritysetup.c:547
+msgid "percent"
+msgstr "procent"
+
+#: src/integritysetup.c:548
+msgid "Journal commit time"
+msgstr "Journal commit-tid"
+
+#: src/integritysetup.c:548 src/integritysetup.c:550
+msgid "ms"
+msgstr "ms"
+
+#: src/integritysetup.c:549
+msgid "Number of 512-byte sectors per bit (bitmap mode)."
+msgstr "Antallet af 512-byte sektorer per bit (bitmap-tilstand)."
+
+#: src/integritysetup.c:550
+msgid "Bitmap mode flush time"
+msgstr "Flush-tid for Bitmap-tilstand"
+
+#: src/integritysetup.c:551
+msgid "Tag size (per-sector)"
+msgstr "Mærkestørrelse (per-sektor)"
+
+#: src/integritysetup.c:552
+msgid "Sector size"
+msgstr "Sektorstørrelse"
+
+#: src/integritysetup.c:553
+msgid "Buffers size"
+msgstr "Bufferstørrelse"
+
+#: src/integritysetup.c:555
+msgid "Data integrity algorithm"
+msgstr "Dataintegritetsalgoritme"
+
+#: src/integritysetup.c:556
+msgid "The size of the data integrity key"
+msgstr "Størrelsen for dataintegritetsnøglen"
+
+#: src/integritysetup.c:557
+msgid "Read the integrity key from a file"
+msgstr "Læs integritetsnøglen fra en fil"
+
+#: src/integritysetup.c:559
+msgid "Journal integrity algorithm"
+msgstr "Journalintegritetsalgoritme"
+
+#: src/integritysetup.c:560
+msgid "The size of the journal integrity key"
+msgstr "Størrelsen for journalintegritetsnøglen"
+
+#: src/integritysetup.c:561
+msgid "Read the journal integrity key from a file"
+msgstr "Læs journalintegritetsnøglen fra en fil"
+
+#: src/integritysetup.c:563
+msgid "Journal encryption algorithm"
+msgstr "Journalkrypteringsalgoritme"
+
+#: src/integritysetup.c:564
+msgid "The size of the journal encryption key"
+msgstr "Størrelsen for journalkrypteringsnøglen"
+
+#: src/integritysetup.c:565
+msgid "Read the journal encryption key from a file"
+msgstr "Læs journalkrypteringsnøglen fra en fil"
+
+#: src/integritysetup.c:568
+msgid "Recovery mode (no journal, no tag checking)"
+msgstr "Gendannelsestilstand (ingen journal, ingen mærkekontrol)"
+
+#: src/integritysetup.c:569
+msgid "Use bitmap to track changes and disable journal for integrity device"
+msgstr "Brug bitmap til at registrere ændringer og deaktivere journal for integritetsenhed"
+
+#: src/integritysetup.c:570
+msgid "Recalculate initial tags automatically."
+msgstr "Genberegn oprindelige mærker automatisk."
+
+#: src/integritysetup.c:641
+msgid "Option --integrity-recalculate can be used only for open action."
+msgstr "Tilvalget --integrity-recalculate kan kun bruges for open-handling."
+
+#: src/integritysetup.c:656
+msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action.\n"
+msgstr "Tilvalgene --journal-size, --interleave-sectors, --sector-size, --tag-size og --no-wipe kan kun bruges for formathandlingen.\n"
+
+#: src/integritysetup.c:662
+msgid "Invalid journal size specification."
+msgstr "Ugyldig specifikation for journalstørrelse."
+
+#: src/integritysetup.c:667
+msgid "Both key file and key size options must be specified."
+msgstr "Både nøglefil og tilvalg for nøglestørrelse skal være angivet."
+
+#: src/integritysetup.c:670
+msgid "Integrity algorithm must be specified if integrity key is used."
+msgstr "Integritetsalgoritme skal være angivet hvis der bruges integritetsnøgle."
+
+#: src/integritysetup.c:675
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Både journalintegritetsnøglefil og tilvalg for nøglestørrelse skal være angivet."
+
+#: src/integritysetup.c:678
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Journalintegritetsalgoritme skal være angivet hvis journalintegritetsnøgle anvendes."
+
+#: src/integritysetup.c:683
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Både journalkrypteringsnøglefil og tilvalg for nøglestørrelse skal være angivet."
+
+#: src/integritysetup.c:686
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Journalkrypteringsalgoritme skal være angivet hvis journalkrypteringsnøgle bruges."
+
+#: src/integritysetup.c:690
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Tilvalgene recovery og bitmap udelukker hinanden."
+
+#: src/integritysetup.c:694
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Journaltilvalg kan ikke bruges i bitmap-tilstand."
+
+#: src/integritysetup.c:698
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Bitmap-tilvalg kan kun bruges i bitmap-tilstand."
+
+#: src/cryptsetup_reencrypt.c:172
+msgid "Reencryption already in-progress."
+msgstr "Omkryptering er allerede i gang."
+
+#: src/cryptsetup_reencrypt.c:201
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Kan ikke eksklusivt åbne %s, enheden er i brug."
+
+#: src/cryptsetup_reencrypt.c:215 src/cryptsetup_reencrypt.c:1128
+msgid "Allocation of aligned memory failed."
+msgstr "Allokering af tilpasset hukommelse mislykkedes."
+
+#: src/cryptsetup_reencrypt.c:222
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Kan ikke læse enheden %s."
+
+#: src/cryptsetup_reencrypt.c:233
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Markerer LUKS-enheden %s som ubrugelig."
+
+#: src/cryptsetup_reencrypt.c:237
+#, c-format
+msgid "Setting LUKS2 offline reencrypt flag on device %s."
+msgstr "Angivelse af LUKS2 som frakoblet omkrypterer flag på enheden %s."
+
+#: src/cryptsetup_reencrypt.c:254
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Kan ikke skrive enhed %s."
+
+#: src/cryptsetup_reencrypt.c:302
+msgid "Cannot write reencryption log file."
+msgstr "Kan ikke skrive omkrypteringslogfilen."
+
+#: src/cryptsetup_reencrypt.c:358
+msgid "Cannot read reencryption log file."
+msgstr "Kan ikke læse omkrypteringslogfilen."
+
+#: src/cryptsetup_reencrypt.c:396
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Logfilen %s findes, genoptager omkryptering.\n"
+
+#: src/cryptsetup_reencrypt.c:445
+msgid "Activating temporary device using old LUKS header."
+msgstr "Aktiverer midlertidig enhed via brug af gammelt LUKS-teksthoved."
+
+#: src/cryptsetup_reencrypt.c:455
+msgid "Activating temporary device using new LUKS header."
+msgstr "Aktiverer midlertidig enhed via brug af nyt LUKS-teksthoved."
+
+#: src/cryptsetup_reencrypt.c:465
+msgid "Activation of temporary devices failed."
+msgstr "Aktivering af midlertidige enheder mislykkedes."
+
+#: src/cryptsetup_reencrypt.c:552
+msgid "Failed to set data offset."
+msgstr "Kunne ikke angive dataforskydning."
+
+#: src/cryptsetup_reencrypt.c:558
+msgid "Failed to set metadata size."
+msgstr "Kunne ikke angive metadatastørrelse."
+
+#: src/cryptsetup_reencrypt.c:566
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Nyt LUKS-teksthoved for enheden %s oprettet."
+
+#: src/cryptsetup_reencrypt.c:626
+#, c-format
+msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+msgstr "Denne version af cryptsetup-reencrypt kan ikke håndtere ny intern symboltype %s."
+
+#: src/cryptsetup_reencrypt.c:648
+msgid "Failed to read activation flags from backup header."
+msgstr "Kunne ikke læse aktiveringsflag fra sikkerhedskopiteksthoved."
+
+#: src/cryptsetup_reencrypt.c:652
+msgid "Failed to write activation flags to new header."
+msgstr "Kunne ikke skrive aktiveringsflag til nyt teksthoved."
+
+#: src/cryptsetup_reencrypt.c:656 src/cryptsetup_reencrypt.c:660
+msgid "Failed to read requirements from backup header."
+msgstr "Kunne ikke læse krav fra sikkerhedskopiteksthoved."
+
+#: src/cryptsetup_reencrypt.c:698
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "%s-sikkerhedskopi af teksthoved for enheden %s er oprettet."
+
+#: src/cryptsetup_reencrypt.c:761
+msgid "Creation of LUKS backup headers failed."
+msgstr "Oprettelse af LUKS-sikkerhedskopiteksthoveder mislykkedes."
+
+#: src/cryptsetup_reencrypt.c:894
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Kan ikke gendanne %s-teksthoved på enheden %s."
+
+#: src/cryptsetup_reencrypt.c:896
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "%s-teksthoved på enheden %s er gendannet."
+
+#: src/cryptsetup_reencrypt.c:1100 src/cryptsetup_reencrypt.c:1106
+msgid "Cannot open temporary LUKS device."
+msgstr "Kan ikke åbne midlertidig LUKS-enhed."
+
+#: src/cryptsetup_reencrypt.c:1111 src/cryptsetup_reencrypt.c:1116
+msgid "Cannot get device size."
+msgstr "Kan ikke indhente enhedsstørrelse."
+
+#: src/cryptsetup_reencrypt.c:1151
+msgid "IO error during reencryption."
+msgstr "IO-fejl under omkryptering."
+
+#: src/cryptsetup_reencrypt.c:1182
+msgid "Provided UUID is invalid."
+msgstr "Angivet UUID er ugyldig."
+
+#: src/cryptsetup_reencrypt.c:1416
+msgid "Cannot open reencryption log file."
+msgstr "Kan ikke åbne omkrypteringslogfilen."
+
+#: src/cryptsetup_reencrypt.c:1422
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Ingen dekryptering i gang, angivet UUID kan kun bruges til at genoptage suspenderet dekrypteringsproces."
+
+#: src/cryptsetup_reencrypt.c:1497
+#, c-format
+msgid "Changed pbkdf parameters in keyslot %i."
+msgstr "Ændret pbkdf-parameter i nøgleplads %i."
+
+#: src/cryptsetup_reencrypt.c:1609
+msgid "Reencryption block size"
+msgstr "Blokstørrelse for omkryptering"
+
+#: src/cryptsetup_reencrypt.c:1609
+msgid "MiB"
+msgstr "MiB"
+
+#: src/cryptsetup_reencrypt.c:1613
+msgid "Do not change key, no data area reencryption"
+msgstr "Ændr ikke nøgle, ingen dataområdeomkryptering"
+
+#: src/cryptsetup_reencrypt.c:1615
+msgid "Read new volume (master) key from file"
+msgstr "Læs ny diskenhednøgle (master) fra fil"
+
+#: src/cryptsetup_reencrypt.c:1616
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "PBKDF2-iterationstid for LUKS (i ms)"
+
+#: src/cryptsetup_reencrypt.c:1622
+msgid "Use direct-io when accessing devices"
+msgstr "Brug direct-io når enheder tilgås"
+
+#: src/cryptsetup_reencrypt.c:1623
+msgid "Use fsync after each block"
+msgstr "Brug fsync efter hver blok"
+
+#: src/cryptsetup_reencrypt.c:1624
+msgid "Update log file after every block"
+msgstr "Opdater logfil efter hver blok"
+
+#: src/cryptsetup_reencrypt.c:1625
+msgid "Use only this slot (others will be disabled)"
+msgstr "Brug kun denne plads (andre vil blive deaktiveret)"
+
+#: src/cryptsetup_reencrypt.c:1630
+msgid "Create new header on not encrypted device"
+msgstr "Opret nyt teksthoved på ikke krypteret enhed"
+
+#: src/cryptsetup_reencrypt.c:1631
+msgid "Permanently decrypt device (remove encryption)"
+msgstr "Dekrypter enhed permanent (fjern kryptering)"
+
+#: src/cryptsetup_reencrypt.c:1632
+msgid "The UUID used to resume decryption"
+msgstr "UUID'en brugt til at genoptage dekryptering"
+
+#: src/cryptsetup_reencrypt.c:1633
+msgid "Type of LUKS metadata: luks1, luks2"
+msgstr "Type for LUKS-metadata: luks1, luks2"
+
+#: src/cryptsetup_reencrypt.c:1652
+msgid "[OPTION...] <device>"
+msgstr "[TILVALG...] <enhed>"
+
+#: src/cryptsetup_reencrypt.c:1660
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Omkryptering vil ændre: %s%s%s%s%s%s."
+
+#: src/cryptsetup_reencrypt.c:1661
+msgid "volume key"
+msgstr "diskenhedsnøgle"
+
+#: src/cryptsetup_reencrypt.c:1663
+msgid "set hash to "
+msgstr "sæt hash til "
+
+#: src/cryptsetup_reencrypt.c:1664
+msgid ", set cipher to "
+msgstr ", set krypteringsalgoritme til "
+
+#: src/cryptsetup_reencrypt.c:1668
+msgid "Argument required."
+msgstr "Argument krævet."
+
+#: src/cryptsetup_reencrypt.c:1696
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Kun værdier mellem 1 MiB og 64 MiB tilladt for omkrypteringsblokstørrelsen."
+
+#: src/cryptsetup_reencrypt.c:1723
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "Maksimal reduceringsstørrelse for enhed er 64 MiB."
+
+#: src/cryptsetup_reencrypt.c:1730
+msgid "Option --new must be used together with --reduce-device-size or --header."
+msgstr "Tilvalget --new skal bruges sammen med --reduce-device-size eller --header."
+
+#: src/cryptsetup_reencrypt.c:1734
+msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+msgstr "Tilvalget --keep-key kan kun bruges med --hash, --iter-time eller --pbkdf-force-iterations."
+
+#: src/cryptsetup_reencrypt.c:1738
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "Tilvalget --new kan ikke bruges sammen med --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1742
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "Tilvalget --decrypt er ikke kompatibelt med specificerede parametre."
+
+#: src/cryptsetup_reencrypt.c:1746
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "Tilvalget --uuid er kun tilladt sammen med --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1750
+msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+msgstr "Ugyldig luks-type. Brug en af disse: »luks«, »luks2« eller »luks2«."
+
+#: src/utils_tools.c:151
+msgid "Error reading response from terminal."
+msgstr "Fejl ved læsning af svar fra terminal."
+
+#: src/utils_tools.c:186
+msgid "Command successful.\n"
+msgstr "Kommando succesfuld.\n"
+
+#: src/utils_tools.c:194
+msgid "wrong or missing parameters"
+msgstr "forkert eller manglende parametre"
+
+#: src/utils_tools.c:196
+msgid "no permission or bad passphrase"
+msgstr "ingen tilladelse eller ugyldg adgangsfrase"
+
+#: src/utils_tools.c:198
+msgid "out of memory"
+msgstr "ikke nok hukommelse"
+
+#: src/utils_tools.c:200
+msgid "wrong device or file specified"
+msgstr "forkert enhed eller fil angivet"
+
+#: src/utils_tools.c:202
+msgid "device already exists or device is busy"
+msgstr "enheden findes allerede eller enheden er optaget"
+
+#: src/utils_tools.c:204
+msgid "unknown error"
+msgstr "ukendt fejl"
+
+#: src/utils_tools.c:206
+#, c-format
+msgid "Command failed with code %i (%s).\n"
+msgstr "Kommando mislykkedes med kode %i (%s).\n"
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Key slot %i created."
+msgstr "Nøglepladsen %i oprettet."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Nøgleplads %i låst op."
+
+#: src/utils_tools.c:287
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Nøgleplads %i fjernet."
+
+#: src/utils_tools.c:296
+#, c-format
+msgid "Token %i created."
+msgstr "Symbol %i oprettet."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "Token %i removed."
+msgstr "Symbol %i fjernet."
+
+#: src/utils_tools.c:464
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Sletning (wipe) afbrudt."
+
+#: src/utils_tools.c:475
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "ADVARSEL: Enheden %s indeholder allerede en »%s«-partitionsignatur.\n"
+
+#: src/utils_tools.c:483
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "ADVARSEL: Enheden %s indeholder allerede en »%s«-superbloksignatur.\n"
+
+#: src/utils_tools.c:504 src/utils_tools.c:568
+msgid "Failed to initialize device signature probes."
+msgstr "Kunne ikke initialisere enhedssignaturundersøgelser."
+
+#: src/utils_tools.c:548
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Kunne ikke køre stat på enheden %s."
+
+#: src/utils_tools.c:561
+#, c-format
+msgid "Device %s is in use. Can not proceed with format operation."
+msgstr "Enheden %s er i brug. Kan ikke fortsætte med formatoperation."
+
+#: src/utils_tools.c:563
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Kunne ikke åbne filen %s i læs/skriv-tilstand."
+
+#: src/utils_tools.c:577
+#, c-format
+msgid "Existing '%s' partition signature (offset: %<PRIi64> bytes) on device %s will be wiped."
+msgstr "Eksisterende »%s«-partitionsignatur (forskydning: %<PRIi64> byte) på enheden %s vil blive slettet."
+
+#: src/utils_tools.c:580
+#, c-format
+msgid "Existing '%s' superblock signature (offset: %<PRIi64> bytes) on device %s will be wiped."
+msgstr "Eksisterende »%s«-superbloksignatur (forskydning: %<PRIi64> byte) på enheden %s vil blive slettet."
+
+#: src/utils_tools.c:583
+msgid "Failed to wipe device signature."
+msgstr "Kunne ikke rydde enhedssignatur."
+
+#: src/utils_tools.c:590
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Kunne ikke undersøge enheden %s for en signatur."
+
+#: src/utils_tools.c:629
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Omkryptering afbrudt."
+
+#: src/utils_password.c:43 src/utils_password.c:75
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Kan ikke kontrollere adganskodekvalitet: %s"
+
+#: src/utils_password.c:51
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Kontrol af adgangskodens kvalitet mislykkedes:\n"
+" %s"
+
+#: src/utils_password.c:83
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Kontrol af adgangskodens kvalitet mislykkedes: Ugyldig adgangsfrase (%s)"
+
+#: src/utils_password.c:193 src/utils_password.c:208
+msgid "Error reading passphrase from terminal."
+msgstr "Kunne ikke læse adgangsfrase fra terminal."
+
+#: src/utils_password.c:206
+msgid "Verify passphrase: "
+msgstr "Verificer adgangsfrase: "
+
+#: src/utils_password.c:213
+msgid "Passphrases do not match."
+msgstr "Adgangsfraser matcher ikke."
+
+#: src/utils_password.c:250
+msgid "Cannot use offset with terminal input."
+msgstr "Kan ikke bruge forskydning med terminalinddata."
+
+#: src/utils_password.c:253
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Indtast adgangsfrase: "
+
+#: src/utils_password.c:256
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Indtast adgangsfrase for %s: "
+
+#: src/utils_password.c:287
+msgid "No key available with this passphrase."
+msgstr "Ingen nøgle tilgængelig med denne adgangsfrase."
+
+#: src/utils_password.c:289
+msgid "No usable keyslot is available."
+msgstr "Ingen brugbar nøgleplads tilgængelig."
+
+#: src/utils_password.c:328
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Kan ikke bne nøglefilen %s for skrivning."
+
+#: src/utils_password.c:335
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Kan ikke skrive til nøglefilen %s."
+
+#: src/utils_luks2.c:47
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Kunne ikke åbne filen %s i skrivebeskyttet tilstand."
+
+#: src/utils_luks2.c:60
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Tilbyd gyldig LUKS2-symbol JSON:\n"
+
+#: src/utils_luks2.c:67
+msgid "Failed to read JSON file."
+msgstr "Kunne ikke læse JSON-fil."
+
+#: src/utils_luks2.c:72
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Læsning afbrudt."
+
+#: src/utils_luks2.c:113
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Kunne ikke åbne filen %s i skrive-tilstand."
+
+#: src/utils_luks2.c:122
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Skrivning afbrudt."
+
+#: src/utils_luks2.c:126
+msgid "Failed to write JSON file."
+msgstr "Kunne ikke skrive JSON-fil."
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Forespurgte dmcrypt-ydelsestilvalg er ikke understøttede."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "Kan ikke formatere enheden %s som stadig er i brug."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "Nøglepladsen %d er ikke brugt."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "Funktion er ikke tilgængelig i FIPS-tilstand."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "Nøgleplads %d valgt for sletning."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "åbn enhed som oversættelse <navn>"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "luk enhed (deaktiver og fjern oversættelse)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "Kunne ikke angive PBKDF-parametre."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "Kan ikke søge til enhedsforskydning.\n"
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Afbrudt af et signal."
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Enheden %s er for lille. (LUKS2 kræver mindst %<PRIu64> byte.)"
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000..b3b84fb
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,4644 @@
+# German translation for the cryptsetup package.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Roland Illig <roland.illig@gmx.de>, 2010-2023.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-02 22:57+0100\n"
+"Last-Translator: Roland Illig <roland.illig@gmx.de>\n"
+"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Das Kernelmodul »device-mapper« kann nicht initialisiert werden, da das Programm nicht mit Root-Rechten läuft."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Das Kernelmodul »device-mapper« kann nicht initialisiert werden. Ist das Kernelmodul »dm_mod« geladen?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Verlangter »deferred«-Schalter wird nicht unterstützt."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID für Gerät »%s« wurde verkürzt."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Unbekannte Art des dm-Ziels."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Die verlangten dm-crypt-Performance-Optionen werden nicht unterstützt."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Die verlangten dm-verity-Datenbeschädigungs-Optionen werden nicht unterstützt."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "Die verlangte dm-verity-Tasklet-Option wird nicht unterstützt."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Die verlangten dm-verity-FEC-Optionen werden nicht unterstützt."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Die verlangten Datenintegritäts-Optionen werden nicht unterstützt."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "Die verlangte sector_size-Option wird nicht unterstützt."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Die verlangte automatische Berechnung der Integritätsangaben wird nicht unterstützt."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "»Discard/TRIM« wird nicht unterstützt."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Der verlangte Bitmap-Modus für dm-Integrität wird nicht unterstützt."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Fehler beim Abfragen des »dm-%s«-Segments."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Das System hat keine Entropie mehr, um den Laufwerksschlüssel zu generieren.\n"
+"Bitte bewegen Sie die Maus oder tippen Sie etwas Text in ein anderes Fenster, um einige zufällige Ereignisse zu sammeln.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Schlüssel wird generiert (%d %% erledigt).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Laufe im FIPS-Modus."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "Fataler Fehler während der Initialisierung des Zufallszahlengenerators."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Unbekannte Qualität des Zufallszahlengenerators verlangt."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Fehler beim Einlesen vom Zufallszahlengenerator."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Fehler beim Initialisieren des Krypto-Zufallszahlengenerator-Backends."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Fehler beim Initialisieren des Krypto-Backends."
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Hash-Algorithmus »%s« wird nicht unterstützt."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Fehler beim Verarbeiten des Schlüssels (mit Hash-Algorithmus »%s«)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Geräte-Art kann nicht bestimmt werden. Inkompatible Aktivierung des Geräts?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "Diese Operation wird nur für LUKS-Geräte unterstützt."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Diese Operation wird nur für LUKS2-Geräte unterstützt."
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Alle Schlüsselfächer sind voll."
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Schlüsselfach %d ist ungültig, bitte wählen Sie eins zwischen 0 und %d."
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Schlüsselfach %d ist voll, bitte wählen Sie ein anderes."
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "Gerätegröße ist nicht an logischer Sektorgröße ausgerichtet."
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Header gefunden, aber Gerät »%s« ist zu klein."
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Diese Operation wird für diese Geräteart nicht unterstützt."
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Ungültige Operation, während die Wiederverschlüsselung läuft."
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Fehler beim Rückabwickeln der LUKS2-Metadaten im Speicher."
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Gerät »%s« ist kein gültiges LUKS-Gerät."
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Nicht unterstützte LUKS-Version %d."
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "Gerät »%s« ist nicht aktiv."
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Zugrundeliegendes Gerät für das Kryptogerät »%s« ist verschwunden."
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "Ungültige Parameter für Plain-Verschlüsselung."
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "Ungültige Schlüsselgröße."
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID wird für diese Verschlüsselungsart nicht unterstützt."
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Gerät für separierte Metadaten wird für diese Verschlüsselungsart nicht unterstützt."
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Nicht unterstützte Sektorengröße für Verschlüsselung."
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "Gerätegröße ist nicht an verlangter Sektorgröße ausgerichtet."
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "Ohne Gerät kann LUKS nicht formatiert werden."
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Die angeforderte Datenausrichtung ist nicht mit dem Datenoffset kompatibel."
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Fehler beim Auslöschen des Headers auf Gerät »%s«."
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Gerät %s ist zu klein für die Aktivierung, es ist kein Platz mehr für Daten vorhanden.\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "WARNUNG: Die Geräteaktivierung wird fehlschlagen, dm-crypt fehlt die Unterstützung für die angeforderte Verschlüsselungsgröße.\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Laufwerksschlüssel ist zu klein für die Verschlüsselung mit Integritätserweiterungen."
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Verschlüsselung »%s-%s« (Schlüsselgröße %zd Bits) ist nicht verfügbar."
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "Warnung: Größe der LUKS2-Metadaten wurde auf %<PRIu64> geändert.\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "Warnung: Größe des LUKS2-Schlüsselfachbereichs wurde auf %<PRIu64> Bytes geändert.\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Gerät »%s« ist zu klein."
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Gerät »%s« kann nicht formatiert werden, da es gerade benutzt wird."
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Gerät »%s« kann nicht formatiert werden, Zugriff verweigert."
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Fehler beim Formatieren der Integrität auf Gerät »%s«."
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Gerät »%s« kann nicht formatiert werden."
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "Ohne Gerät kann LOOPAES nicht formatiert werden."
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "Ohne Gerät kann VERITY nicht formatiert werden."
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Nicht unterstützte VERITY-Hash-Art %d."
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Nicht unterstützte VERITY-Blockgröße."
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Nicht unterstützter VERITY-Hash-Offset."
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "Nicht unterstützter VERITY-FEC-Offset."
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "Datenbereich und Hashbereich überlappen sich."
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "Hashbereich und FEC-Bereich überlappen sich."
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "Datenbereich und FEC-Bereich überlappen sich."
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "WARNUNG: Angeforderte Taggröße mit %d Bytes unterscheidet sich von der Ausgabe der Größe %s (%d Bytes).\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Unbekannte Art des Verschlüsselungsgeräts »%s« verlangt."
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Nicht unterstützte Parameter für Gerät %s."
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Parameter für Gerät %s sind durcheinander."
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Verschlüsselungsgeräte passen nicht zusammen."
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Gerät »%s« konnte nicht neugeladen werden."
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Gerät »%s« konnte nicht stillgelegt werden."
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Gerät »%s« konnte nicht fortgesetzt werden."
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Schwerwiegender Fehler beim Neuladen von Gerät »%s« (über Gerät »%s«)."
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Gerät »%s« konnte nicht auf dm-error umgeschaltet werden."
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "Fehler beim Ändern der Größe des Loopback-Geräts."
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "WARNUNG: Die maximale Größe ist bereits eingestellt oder der Kernel unterstützt die Größenänderung nicht.\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Fehler bei Größenänderung, der Kernel unterstützt sie nicht."
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "Wollen Sie wirklich die UUID des Geräts ändern?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Header-Backupdatei enthält keinen kompatiblen LUKS-Header."
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Laufwerk »%s« ist nicht aktiv."
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Laufwerk »%s« ist bereits im Ruhezustand."
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Das Gerät »%s« unterstützt keinen Ruhezustand."
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Das Gerät »%s« kann nicht in den Ruhezustand versetzt werden."
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Das Gerät »%s« kann nicht aus dem Ruhezustand aufgeweckt werden."
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Fehler beim Aufwecken von Gerät »%s« aus dem Ruhezustand."
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Laufwerk »%s« ist nicht im Ruhezustand."
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Der Laufwerksschlüssel passt nicht zum Laufwerk."
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "Neues Schlüsselfach konnte nicht ausgewechselt werden."
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Schlüsselfach %d ist ungültig."
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Schlüsselfach %d ist nicht aktiv."
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "Geräteheader und Datenbereich überlappen sich."
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Wiederverschlüsselung läuft bereits. Das Gerät kann nicht aktiviert werden."
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Fehler beim Zugriff auf die Sperre zur Wiederverschlüsselung."
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Fehler beim Wiederherstellen der LUKS2-Wiederverschlüsselung."
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "Geräteart ist nicht richtig initialisiert."
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "Das Gerät »%s« existiert bereits."
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Gerät »%s« kann nicht verwendet werden, da es gerade benutzt wird oder der Name ungültig ist."
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "Falscher Laufwerksschlüssel für Plain-Gerät angegeben."
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "Falscher Root-Hash-Schlüssel für VERITY-Gerät angegeben."
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "Signatur des Stammhashes erforderlich."
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Der Kernel-Schlüsselbund fehlt. Wird benötigt, um die Signatur zum Kernel zu übergeben."
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "Fehler beim Laden des Schlüssels im Kernel-Schlüsselbund."
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Fehler beim Abbrechen des verzögerten Löschens von Gerät »%s«."
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Gerät »%s« wird gerade benutzt."
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "Ungültiges Gerät »%s«."
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "Laufwerks-Schlüsselpuffer zu klein."
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Fehler beim Ermitteln des Laufwerksschlüssels für LUKS2-Gerät."
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Fehler beim Ermitteln des Laufwerksschlüssels für LUKS1-Gerät."
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Fehler beim Ermitteln des Laufwerksschlüssels für Plain-Gerät."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Root-Hash für Verity-Gerät kann nicht ermittelt werden."
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Fehler beim Ermitteln des Laufwerksschlüssels für BITLK-Gerät."
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Fehler beim Ermitteln des Laufwerksschlüssels für FVAULT2-Gerät."
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Diese Operation wird für Kryptogerät »%s« nicht unterstützt."
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "Die Dump-Operation wird für diese Geräteart nicht unterstützt."
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Datenoffset ist kein Vielfaches von %u Bytes."
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Gerät »%s« kann nicht konvertiert werden, da es gerade benutzt wird."
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Schlüsselfach %u konnte nicht dem Laufwerksschlüssel zugeordnet werden."
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Fehler beim Initialisieren der LUKS2-Schlüsselfach-Parameter."
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Schlüsselfach %d konnte nicht dem Digest zugeordnet werden."
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Schlüsselfach kann nicht hinzugefügt werden, da alle Fächer deaktiviert sind und kein Laufwerksschlüssel angegeben wurde."
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Der Kernel-Schlüsselbund wird vom Kernel nicht unterstützt."
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Fehler beim Lesen der Passphrase vom Schlüsselbund (Fehler %d)."
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Globale Speicherzugriffsserialisierungssperre konnte nicht angefordert werden."
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Fehler beim Öffnen der Schlüsseldatei."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Fehler beim Einlesen der Schlüsseldatei »%s« vom Terminal."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "Fehler beim Öffnen der Schlüsseldatei."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Fehler beim Zugriff auf die Schlüsseldatei."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "Zu wenig Speicher zum Einlesen der Passphrase."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Fehler beim Einlesen der Passphrase."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Nichts zu lesen in der Eingabe."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Größenbegrenzung für die Schlüsseldatei überschritten."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "Die gewünschte Menge an Daten kann nicht eingelesen werden."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Gerät »%s« existiert nicht oder Zugriff verweigert."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Gerät »%s« ist nicht kompatibel."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Merkwürdige Optimale-Datenübertragungs-Größe für Datengerät (%u Bytes) wird ignoriert."
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Gerät »%s« ist zu klein. Mindestens %<PRIu64> Bytes erforderlich."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Gerät »%s« kann nicht benutzt werden, da es bereits anderweitig benutzt wird."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Gerät »%s« kann nicht verwendet werden, Zugriff verweigert."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Fehler beim Abrufen der Infos über Gerät »%s«."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Das Loopback-Gerät kann nicht benutzt werden, da das Programm nicht mit Root-Rechten läuft."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Anklemmen des Loopback-Geräts fehlgeschlagen (das Loopback-Gerät benötigt den »autoclear«-Schalter)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Der angeforderte Offset ist jenseits der wirklichen Größe des Geräts »%s«."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Gerät »%s« hat die Größe 0."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Verlangte Vorgabezeit für PBKDF darf nicht 0 sein."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Unbekannte PBKDF, Typ »%s«."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Verlangter Hash »%s« wird nicht unterstützt."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Verlangter PBKDF-Typ wird von LUKS1 nicht unterstützt."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Für pbkdf2 dürfen weder das Speichermaximum noch die Anzahl der Threads angegeben werden."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Anzahl der verlangten Durchläufe ist zu gering für %s (Minimum ist %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Verlangte Speicherkosten sind zu gering für %s (Minimum sind %u Kilobyte)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Das verlangte Speicherkosten-Maximum ist zu hoch (maximal %d Kilobyte)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Der verlangte PBKDF-Speicherbedarf darf nicht 0 sein."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Die Anzahl der verlangten parallelen Threads für PBKDF darf nicht 0 sein."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Im FIPS-Modus wird ausschließlich PBKDF2 unterstützt."
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "PBKDF-Benchmark deaktiviert, aber Anzahl der Iterationen nicht angegeben."
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Inkompatible PBKDF2-Optionen (mit Hash-Algorithmus »%s«)."
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "Inkompatible PBKDF2-Optionen."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Sperren abgebrochen. Der Sperrpfad %s/%s ist unbenutzbar (kein Verzeichnis oder existiert nicht)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Sperren abgebrochen. Der Sperrpfad %s/%s ist unbenutzbar (%s ist kein Verzeichnis)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Fehler beim Springen zum Gerät-Offset."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Fehler beim gründlichen Löschen des Geräts, an Offset %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Einrichten der dm-crypt-Schlüsselzuordnung für Gerät »%s« fehlgeschlagen.\n"
+"Stellen Sie sicher, dass der Kernel die Verschlüsselung »%s« unterstützt.\n"
+"(Sehen Sie im System-Log nach, ob sich dort Hinweise finden.)"
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Schlüsselgröße im XTS-Modus muss entweder 256 oder 512 Bits sein."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Verschlüsselungsverfahren sollte im Format [Verfahren]-[Modus]-[IV] sein."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Fehler beim Schreiben auf Gerät »%s«, Zugriff verweigert."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Fehler beim Öffnen des temporären Schlüsselspeichergeräts."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Fehler beim Zugriff auf das temporäre Schlüsselspeichergerät."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "E/A-Fehler beim Verschlüsseln des Schlüsselfachs."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Fehler beim Öffnen des Geräts »%s«."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "E/A-Fehler beim Entschlüsseln des Schlüsselfachs."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Gerät »%s« ist zu klein. (LUKS1 benötigt mindestens %<PRIu64> Bytes.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "LUKS-Schlüsselfach %u ist ungültig."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Angeforderte Header-Backupdatei »%s« existiert bereits."
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Fehler beim Anlegen der Header-Backupdatei »%s«."
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Fehler beim Speichern der Header-Backupdatei »%s«."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Backupdatei enthält keinen gültigen LUKS-Header."
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Fehler beim Öffnen der Header-Backupdatei »%s«."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Fehler beim Einlesen der Header-Backupdatei »%s«."
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Unterschiedlicher Offset oder Schlüsselgröße zwischen Gerät und Backup. Wiederherstellung fehlgeschlagen."
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Gerät »%s« %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "enthält keinen LUKS-Header. Das Ersetzen des Headers kann Daten auf dem Gerät zerstören."
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "enthält bereits einen LUKS-Header. Das Ersetzen des Headers wird bestehende Schlüsselfächer zerstören."
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"WARNUNG: Der Header des echten Geräts hat eine andere UUID als das Backup!"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "Ungewöhnliche Schlüsselgröße, manuelles Reparieren erforderlich."
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Ungewöhnliche Ausrichtung der Schlüsselfächer, manuelles Reparieren erforderlich."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Verschlüsselungsmodus repariert (%s -> %s)."
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Chiffre-Hash in Kleinbuchstaben umgewandelt (%s)."
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Verlangter LUKS-Hash »%s« wird nicht unterstützt."
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "Schlüsselfächer werden repariert."
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Schlüsselfach %i: Offset repariert (%u -> %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Schlüsselfach %i: Streifen repariert (%u -> %u)."
+
+# XXX
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Schlüsselfach %i: schwindlerische Partitions-Signatur."
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Schlüsselfach %i: Salt gelöscht."
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "LUKS-Header wird auf den Datenträger geschrieben."
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "Fehler beim Reparieren."
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "LUKS-Verschlüsselungsmodus %s ist ungültig."
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "LUKS-Hash %s ist ungültig."
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "Keine bekannten Probleme im LUKS-Header erkannt."
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Fehler beim Aktualisieren des LUKS-Headers auf Gerät »%s«."
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Fehler beim Neueinlesen des LUKS-Headers nach dem Aktualisieren auf Gerät »%s«."
+
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Daten-Offset für LUKS-Header muss entweder 0 sein oder mehr als die Headergröße."
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "Falsches LUKS-UUID-Format angegeben."
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "LUKS-Header kann nicht angelegt werden: Fehler beim Einlesen des zufälligen Salts."
+
+# XXX
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "LUKS-Header kann nicht angelegt werden: Fehler beim Hashen des Headers (mit Hash-Algorithmus »%s«)."
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Schlüsselfach %d aktiv, löschen Sie es erst."
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Material für Schlüsselfach %d enthält zu wenige Streifen. Manipulation des Headers?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "Überlauf im Iterationswert von PBKDF2."
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Schlüsselfach kann nicht geöffnet werden (mit Hash-Algorithmus »%s«)."
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Schlüsselfach %d ist ungültig, bitte wählen Sie ein Schlüsselfach zwischen 0 und %d."
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Gerät »%s« kann nicht ausgelöscht werden."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Noch nicht unterstützte verschlüsselte GPG-Schlüsseldatei erkannt."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Bitte benutzen Sie »gpg --decrypt <SCHLÜSSELDATEI> | cryptsetup --keyfile=- …«\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Inkompatible Loop-AES-Schlüsseldatei erkannt."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Kernel unterstützt Loop-AES-kompatibles Mapping nicht."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Fehler beim Einlesen der Schlüsseldatei »%s«."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Maximale Länge der TCRYPT-Passphrase (%zu) überschritten."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Der Hash-Algorithmus »%s« für PBKDF2 wird nicht unterstützt, überspringe diesen Teil."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "Die benötigte Crypto-Kernel-Schnittstelle ist nicht verfügbar."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Stellen Sie sicher, dass das Kernelmodul »algif_skcipher« geladen ist."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Aktivierung wird für die Sektorengröße %d nicht unterstützt."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Der Kernel unterstützt die Aktivierung für diesen TCRYPT-Legacymodus nicht."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "TCRYPT-Systemverschlüsselung für Partition »%s« wird aktiviert."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Kernel unterstützt TCRYPT-kompatibles Mapping nicht."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Diese Funktionalität braucht einen geladenen TCRYPT-Header."
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Unerwartete Art »%u« des Metadaten-Eintrags beim Parsen des unterstützten Volume Master Keys gefunden."
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Ungültige Zeichenkette beim Parsen des Volume Master Key gefunden."
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Unerwartete Zeichenkette »%s« beim Parsen des Volume Master Key gefunden."
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Unerwarteter Metadaten-Eintrag %u beim Einlesen des unterstützten Volume Master Key gefunden."
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK Version 1 wird derzeit nicht unterstützt."
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Ungültige oder unbekannte Bootsignatur für BITLK-Gerät."
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Nicht unterstützte Sektorengröße %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Fehler beim Lesen des BITLK-Headers von »%s«."
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Fehler beim Schreiben der BITLK-FVE-Metadaten von »%s«."
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "Unbekannte oder nicht unterstützte Verschlüsselungsart."
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Fehler beim Lesen der BITLK-Metadaten von »%s«."
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "Fehler beim Konvertieren der BITLK-Volumenbeschreibung"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Unerwartete Art »%u« des Metadaten-Eintrags beim Parsen des externen Schlüssels gefunden."
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "Die GUID der BEK-Datei »%s« stimmt nicht mit der GUID des Laufwerks überein."
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Unerwarteter Metadaten-Eintrag »%u« beim Einlesen des externen Schlüssels gefunden."
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Nicht unterstützte BEK-Metadatenversion %<PRIu32>"
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Unerwartete BEK-Metadatengröße %<PRIu32> stimmt nicht mit BEK-Dateilänge überein"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Unerwartete Art »%u« des Metadaten-Eintrags beim Einlesen des Startschlüssels gefunden."
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "Diese Operation wird nicht unterstützt."
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "Unerwartete Größe des Datenschlüssels."
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Dieses BITLK-Gerät ist in einem nicht unterstützten Zustand und kann daher nicht aktiviert werden."
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "BITLK-Geräte der Art »%s« können nicht aktiviert werden."
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Aktivieren eines teilweise entschlüsselten BITLK-Geräts wird nicht unterstützt."
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "WARNUNG: BitLocker-Datenträgergröße %<PRIu64> stimmt nicht mit der zugrunde liegenden Gerätegröße %<PRIu64> überein"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Gerät kann nicht aktiviert werden, dem Kernelmodul dm-crypt fehlt die Unterstützung für BITLK-IV."
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Gerät kann nicht aktiviert werden, da dem Kernelmodul dm-crypt die Unterstützung für BITLK-Elephant-Verschleierer fehlt."
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Gerät kann nicht aktiviert werden, dem Kernelmodul dm-crypt fehlt die Unterstützung für große Sektoren."
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Gerät kann nicht aktiviert werden, das Kernelmodul dm-crypt existiert nicht."
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Fehler beim Einlesen von %u Bytes aus dem Laufwerks-Kopfbereich."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Nicht unterstützte VFAULT2-Version %<PRIu16>."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Verity-Gerät »%s« benutzt keinen Header auf dem Datenträger."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Nicht unterstützte VERITY-Version %d."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "VERITY-Header verfälscht."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Falsches VERITY-UUID-Format über Gerät »%s« angegeben."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Fehler beim Aktualisieren des VERITY-Headers auf Gerät »%s«."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Verifikation der Stammhash-Signatur wird nicht unterstützt."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Fehler können mit einem FEC-Gerät nicht repariert werden."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "%u reparierbare Fehler mit FEC-Gerät gefunden."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Kernel unterstützt dm-verity-Zuordnung nicht."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Kernel unterstützt Signatur-Option für dm-verity nicht."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Verity-Gerät hat eine Verfälschung nach der Aktivierung festgestellt."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Zusätzlicher Platz an Position %<PRIu64> ist nicht ausgenullt."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Überlauf beim Geräte-Offset."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Fehler beim Verifizieren an Position %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Überlauf des Hashbereichs."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Fehler beim Verifizieren des Datenbereichs."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Fehler beim Verifizieren des Root-Hashes."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "E/A-Fehler beim Anlegen des Hash-Bereiches."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Fehler beim Anlegen des Hash-Bereiches."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "WARNUNG: Kernel kann das Gerät nicht aktivieren, wenn die Datenblockgröße die Seitengröße (%u) übersteigt."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Fehler beim Reservieren des RS-Kontexts."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Fehler beim Reservieren des Puffers."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Fehler beim Lesen des RS-Blocks %<PRIu64>, Byte %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Fehler beim Lesen der Parität für RS-Block %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Fehler beim Reparieren der Parität für RS-Block %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Fehler beim Schreiben der Parität für RS-Block %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Blockgrößen müssen für FEC zusammen passen."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Ungültige Anzahl von Paritätsbytes."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Ungültige FEC-Segmentlänge."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Fehler beim Ermitteln der Größe von Gerät »%s«."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Inkompatible Metadaten des Kernelmoduls dm-integrity (Version %u) auf %s entdeckt."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Kernel unterstützt dm-integrity-Zuordnung nicht."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Kernel unterstützt feste Ausrichtung der Metadaten für dm-integrity nicht."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Der Kernel weigert sich, die unsichere Neuberechnungs-Option zu aktivieren. Um dies zu übersteuern, können Sie die veralteten Aktivierungsoptionen nutzen."
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Fehler beim exklusiven Schreibzugriff auf Gerät »%s«."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Es wurde ein Versuch erkannt, die LUKS2-Metadaten nebenläufig zu ändern. Die Operation wird abgebrochen."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Gerät enthält mehrdeutige Signaturen, LUKS2 kann nicht automatisch wiederhergestellt werden.\n"
+"Bitte führen Sie \"cryptsetup repair\" zur Wiederherstellung aus."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Verlangter Daten-Offset ist zu klein."
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "WARNING: Der Schlüsselfach-Bereich (%<PRIu64> Bytes) ist sehr klein, die LUKS2-Schlüsselfachanzahl ist sehr begrenzt.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Fehler beim Zugriff auf die Lesesperre für das Gerät »%s«."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Verbotene LUKS2-Anforderungen in Backup »%s« entdeckt."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Unterschiedliche Datenoffsets auf Gerät und Backup. Wiederherstellung fehlgeschlagen."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Unterschiedliche Größe der Binärheader mit Schlüsselfach-Bereichen zwischen Gerät und Backup. Wiederherstellung fehlgeschlagen."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Gerät »%s« %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "enthält keinen LUKS2-Header. Das Ersetzen des Headers kann Daten auf dem Gerät zerstören."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "enthält bereits einen LUKS2-Header. Das Ersetzen des Headers wird bestehende Schlüsselfächer zerstören."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"WARNUNG: Unbekannte LUKS2-Anforderungen im echten Geräteheader entdeckt!\n"
+"Das Ersetzen des Headers mit dem Backup kann zu Datenverlust auf dem Gerät führen!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"WARNUNG: Unvollendete Offline-Wiederverschlüsselung auf dem Gerät entdeckt!\n"
+"Das Ersetzen des Headers mit dem Backup kann zu Datenverlust auf dem Gerät führen."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Unbekannter Schalter »%s« wird ignoriert."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Fehlender Schlüssel für dm-crypt-Segment %u"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Fehler beim Festlegen des »dm-crypt«-Segments."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Fehler beim Festlegen des »dm-linear«-Segments."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Nicht unterstützte Konfiguration für Geräteintegrität."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Wiederverschlüsselung läuft gerade. Das Gerät kann nicht deaktiviert werden."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Das stillgelegte Gerät »%s« mit dm-error-Ziel konnte nicht in den Fehlerzustand gesetzt werden."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Fehler beim Lesen der LUKS2-Anforderungen."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Unerfüllte LUKS2-Anforderungen entdeckt."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Diese Operation kann nicht mit einem Gerät durchgeführt werden, das für Altlasten-Wiederverschlüsselung markiert ist. Wird abgebrochen."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Diese Operation kann nicht mit einem Gerät durchgeführt werden, das für LUKS2-Wiederverschlüsselung markiert ist. Wird abgebrochen."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Nicht genügend Speicher, um ein Schlüsselfach zu öffnen."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Fehler beim Öffnen des Schlüsselfachs."
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Der Algorithmus %s-%s kann nicht für Schlüsselfach-Verschlüsselung verwendet werden."
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Der Hash-Algorithmus »%s« ist nicht verfügbar."
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "Nicht genug Speicherplatz für neues Schlüsselfach."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Ungültige Änderung des Modus für die robuste Wiederverschlüsselung angefordert."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Die Art der Robustheit kann nicht geändert werden. Die neue Art bietet nur %<PRIu64> Bytes, der erforderliche Platz ist jedoch %<PRIu64> Bytes."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Fehler beim Auffrischen des Zusammenfassungswerts der Prüfung der Wiederverschlüsselung."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Fehler beim Prüfen des Zustands von Gerät mit der UUID %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Fehler beim Konvertieren des Headers mit zusätzlichen LUKSMETA-Metadaten."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Die Chiffrierspezifikation %s-%s kann für LUKS2 nicht verwendet werden."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Fehler beim Verschieben des Schlüsselfach-Bereichs. Nicht genug Speicherplatz."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Fehler beim Konvertieren ins LUKS2-Format: ungültige Metadaten."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Fehler beim Verschieben des Schlüsselfach-Bereichs. Bereich für die LUKS2-Schlüsselfächer ist zu klein."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Fehler beim Verschieben des Schlüsselfach-Bereichs."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: Standardgröße für Verschlüsselungssektoren ist nicht 512 Bytes."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: Schlüsselfach-Digeste sind nicht zu LUKS1 kompatibel."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: Gerät verwendet eingepacktes Verschlüsselungsverfahren %s."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Fehler beim Konvertieren ins LUKS1-Format: Gerät verwendet mehr Segmente."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: LUKS2-Header enthält %u Token."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: Schlüsselfach %u ist in ungültigem Zustand."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: Schlüsselfach %u (über Maximalfach) ist noch aktiv."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Fehler beim Konvertieren in LUKS1-Format: Schlüsselfach %u ist nicht zu LUKS1 kompatibel."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Die Größe der Hotzone muss ein Vielfaches der berechneten Zonenausrichtung (%zu Bytes) sein."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Gerätegröße muss ein Vielfaches der berechneten Zonenausrichtung (%zu Bytes) sein."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Fehler beim Initialisieren der Umverpackung für den Speicher alter Segmente."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Fehler beim Initialisieren der Umverpackung für den Speicher neuer Segmente."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Fehler beim Initialisieren des Hotzone-Schutzes."
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Fehler beim Lesen der Prüfsummen für die aktuelle Hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Fehler beim Lesen des Hotzone-Bereichs, der bei %<PRIu64> beginnt."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Fehler beim Entschlüsseln von Sektor %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Fehler beim Wiederherstellen von Sektor %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Die Größe der Quell- und Zielgeräte stimmt nicht überein. Quelle %<PRIu64>, Ziel: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Fehler beim Aktivieren des Hotzone-Geräts »%s«."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Fehler beim Aktivieren des Überlagerungsgeräts »%s« mit der tatsächlichen Ursprungstabelle."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Fehler beim Laden der neuen Zuordnung für Gerät »%s«."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Fehler beim Auffrischen des Gerätestapels für Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Fehler beim Festlegen der neuen Bereichsgröße für Schlüsselfächer."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Datenverschiebung ist nicht an der angeforderten Verschlüsselungs-Sektorgröße (%<PRIu32> Bytes) ausgerichtet."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Nicht unterstützter Modus »%s« für Widerstandsfähigkeit"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Die Größe des verschobenen Segments kann nicht größer als der Wert der Datenverschiebung sein."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Ungültige Parameter für die robuste Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Das verschobene Segment ist zu groß. Angeforderte Größe %<PRIu64>, verfügbarer Platz %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Fehler beim Leeren der Tabelle."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "Die reduzierte Datengröße ist größer als die tatsächliche Gerätegröße."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Datengerät ist nicht an der angeforderten Verschlüsselungs-Sektorgröße (%<PRIu32> Bytes) ausgerichtet."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Datenverschiebung (%<PRIu64> Sektoren) ist weniger als der zukünftige Datenoffset (%<PRIu64> Sektoren)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Fehler beim exklusiven Öffnen von »%s« (wird bereits anderweitig benutzt)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Das Gerät ist nicht für LUKS2-Wiederverschlüsselung markiert."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Fehler beim Laden des LUKS2-Wiederverschlüsselungs-Kontextes."
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Fehler beim Einlesen des Wiederverschlüsselungs-Zustands."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Das Gerät befindet sich nicht in der Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Der Wiederverschlüsselungs-Vorgang läuft bereits."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Fehler beim Zugriff auf die Schreibsperre für die Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Wiederverschlüsselung kann nicht fortgesetzt werden. Führen Sie zuerst die Wiederverschlüsselungs-Wiederherstellung durch."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Aktive Gerätegröße und angeforderte Wiederverschlüsselungsgröße passen nicht zusammen."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "Ungültige Gerätegröße wurde in den Wiederverschlüsselungsparametern angefordert."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Wiederverschlüsselung läuft bereits. Wiederherstellung ist nicht möglich."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "LUKS2-Wiederverschlüsselung ist in den Metadaten bereits initialisiert."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "LUKS2-Wiederverschlüsselung konnte in den Metadaten nicht initialisiert werden."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Fehler beim Festlegen der Gerätesegmente für die nächste Wiederverschlüsselungs-Hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Fehler beim Schreiben der Metadaten für robuste Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Fehler beim Entschlüsseln."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Fehler beim Schreiben des Hotzone-Bereichs, der bei %<PRIu64> beginnt."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Fehler beim Synchronisieren von Daten."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Fehler beim Aktualisieren der Metadaten, nachdem die aktuelle Wiederverschlüsselungs-Hotzone beendet wurde."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Fehler beim Schreiben der LUKS2-Metadaten."
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Fehler beim gründlichen Löschen des ungenutzten Bereichs auf dem Gerät."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Fehler beim Entfernen des ungenutzten (ungebundenen) Schlüsselfachs %d."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Fehler beim Entfernen des Schlüsselfachs zur Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Schwerwiegender Fehler beim Wiederverschlüsseln des Blocks bei %<PRIu64>, %<PRIu64> Sektoren lang."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Fehler bei Online-Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Das Gerät nicht fortsetzen, außer es wird manuell durch das Fehlerziel ersetzt."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Wiederverschlüsselung kann nicht fortgesetzt werden. Unerwarteter Zustand der Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Fehlender oder ungültiger Wiederverschlüsselungs-Kontext."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Fehler beim Initialisieren des Gerätestapels für Wiederverschlüsselung."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Fehler beim Aktualisieren des Wiederverschlüsselungskontexts."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Die Metadaten für die Wiederverschlüsselung sind ungültig."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Verschlüsselungsparameter für Schlüsselfach wird nur für LUKS2-Geräte unterstützt."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Geben Sie die PIN des Tokens ein: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Geben Sie die PIN des Tokens %d ein: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Kein bekanntes Verschlüsselungsmuster entdeckt."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "WARNUNG: Der Parameter --hash wird im Plain-Modus ignoriert, wenn eine Schlüsseldatei angegeben ist.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "WARNUNG: Die Option --keyfile-size wird ignoriert, da die Lesegröße die gleiche ist wie die Verschlüsselungsschlüsselgröße ist.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Gerätesignaturen auf »%s« erkannt. Wenn Sie fortfahren, könnte das bestehende Daten beschädigen."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "Vorgang abgebrochen.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Die Option »--key-file« muss angegeben werden."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "VeraCrypt-PIM eingeben: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Ungültiger PIM-Wert: Formatfehler."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Ungültiger PIM-Wert: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Ungültiger PIM-Wert: außerhalb des gültigen Bereichs."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Kein Geräte-Header mit dieser Passphrase gefunden."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Gerät »%s« ist kein gültiges BITLK-Gerät."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Die Größe des Laufwerksschlüssels für BITLK kann nicht ermittelt werden, bitte nutzen Sie die Option »--key-size«."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Der Headerdump zusammen mit dem Laufwerksschlüssel sind\n"
+"sensible Daten, mit deren Hilfe man ohne Passphrase auf die\n"
+"verschlüsselte Partition zugreifen kann. Dieser Dump sollte\n"
+"daher ausschließlich an einem sicheren Ort und verschlüsselt\n"
+"aufbewahrt werden."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Der Headerdump zusammen mit dem Laufwerksschlüssel sind\n"
+"sensible Daten, mit deren Hilfe man ohne Passphrase auf die\n"
+"verschlüsselte Partition zugreifen kann. Dieser Dump sollte\n"
+"daher ausschließlich an einem sicheren Ort und verschlüsselt\n"
+"aufbewahrt werden."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Gerät »%s« ist kein gültiges FVAULT2-Gerät."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Die Größe des Laufwerksschlüssels für FVAULT2 kann nicht ermittelt werden, bitte nutzen Sie die Option »--key-size«."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Gerät »%s« ist noch aktiv und zum verzögerten Entfernen eingeplant.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Um die Größe von aktiven Geräten zu öndern, muss der Laufwerksschlüssel im Schlüsselbund sein, aber die Option --disable-keyring wurde angegeben."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Benchmark unterbrochen."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s (nicht zutreffend)\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u Iterationen pro Sekunde für %zu-Bit-Schlüssel\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s (nicht zutreffend)\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u Iterationen, %5u Speicher, %1u parallele Threads (CPUs) für %zu-Bit-Schlüssel (Zieldauer %u Millisekunden)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Das Ergebnis des Benchmarks ist nicht zuverlässig."
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Die Tests sind nur annähernd genau, da sie nicht auf den Datenträger zugreifen.\n"
+
+# upstream: the following line should also be translated. This is because the long word "Schlüssel" for "Key" will break the layout, as well as "Verschlüsselung" for "Encryption".
+# To help the translators, you should provide an example for what goes into the %x placeholders, since I had to make an educated guess that the second %s would be exactly 4 characters long. This is an unnecessary burden for the translators.
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algorithmus | Schlüssel | Verschlüsselung | Entschlüsselung\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Verschlüsselung »%s« (mit Schlüsselgröße %i Bits) ist nicht verfügbar."
+
+# upstream: the following line should also be translated. This is because the long word "Schlüssel" for "Key" will break the layout, as well as "Verschlüsselung" for "Encryption".
+# To help the translators, you should provide an example for what goes into the %x placeholders, since I had to make an educated guess that the second %s would be exactly 4 characters long. This is an unnecessary burden for the translators.
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algorithmus | Schlüssel | Verschlüsselung | Entschlüsselung\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "N/A"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Ungeschützte LUKS2-Metadaten für die Wiederverschlüsselung entdeckt. Bitte überprüfen Sie, ob die Wiederverschlüsselungsoperation erwünscht ist (siehe luksDump-Ausgabe)\n"
+"und fahren Sie nur fort (Upgrade der Metadaten), wenn Sie den Vorgang als echt anerkennen."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Geben Sie die Passphrase für den Schutz und das Aktualisieren der Metadaten für die Wiederverschlüsselung ein: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Wirklich mit der Wiederherstellung der LUKS2-Wiederverschlüsselung fortfahren?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Geben Sie die Passphrase für das Prüfen der Metadaten für die Wiederverschlüsselung ein: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Geben Sie die Passphrase für die Wiederherstellung der Wiederverschlüsselung ein: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Wirklich versuchen, den LUKS-Geräteheader wiederherzustellen?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Gründlich löschen unterbrochen."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Gerät wird gesäubert, um die Prüfsumme für die Integrität zu initialisieren.\n"
+"Sie können diesen Vorgang mit Strg+C unterbrechen (der nicht gesäuberte Bereich des Geräts wird dann ungültige Prüfsummen haben).\n"
+
+# upstream: it is boring that I have to translate the newline at the end of each of these messages. Translating strings without newlines is much easier and faster. Since it is redundant anyway (all calls to log_err have a trailing newline), this newline should be written implicitly.
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Fehler beim Deaktivieren des temporären Geräts »%s«."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Die Integritätsoption kann nur für das LUKS2-Format verwendet werden."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Nicht unterstützte Optionen für Größe der LUKS-Metadaten."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Die Headerdatei existiert nicht, soll sie angelegt werden?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Fehler beim Anlegen der Headerdatei »%s«."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Kein bekanntes Integritätsspezifikationsmuster entdeckt."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Das Gerät »%s« kann nicht als Datenträger-Header benutzt werden."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Hiermit werden die Daten auf »%s« unwiderruflich überschrieben."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Fehler beim Festlegen der PBKDF-Parameter."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Verringerter Datenoffset ist nur für separaten LUKS-Header erlaubt."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "LUKS-Datei-Container %s ist zu klein für die Aktivierung, es ist kein Platz mehr für Daten vorhanden."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Die Größe des Laufwerksschlüssels erfordert Schlüsselfächer, bitte nutzen Sie dazu die Option »--key-size«."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Gerät aktiviert, aber die Schalter können nicht dauerhaft gespeichert werden."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Schlüsselfach %d zum Löschen ausgewählt."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Dies ist das letzte Schlüsselfach. Wenn Sie diesen Schlüssel löschen, wird das Gerät unbrauchbar."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Geben Sie irgendeine verbleibende Passphrase ein: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Vorgang abgebrochen, das Schlüsselfach wurde NICHT gesäubert.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Geben Sie die zu löschende Passphrase ein: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Gerät »%s« ist kein gültiges LUKS2-Gerät."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Geben Sie die neue Passphrase für das Schlüsselfach ein: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "WARNUNG: Der Parameter --key-slot wird für die neue Nummer des Schlüsselfachs verwendet.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Geben Sie irgendeine bestehende Passphrase ein: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Geben Sie die zu ändernde Passphrase ein: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Geben Sie die neue Passphrase ein: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Geben Sie die Passphrase für das umzuwandelnde Schlüsselfach ein: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Die Operation »isLuks« unterstützt nur genau ein Geräte-Argument."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Schlüsselfach %d enthält keinen unverbundenen Schlüssel."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Der Headerdump zusammen mit dem Laufwerksschlüssel sind sensible Daten.\n"
+"Dieser Dump sollte daher ausschließlich an einem sicheren Ort und\n"
+"verschlüsselt aufbewahrt werden."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s ist kein aktives %s-Gerät."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s ist kein aktives LUKS-Gerät, oder der Header fehlt."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "Option »--header-backup-file« muss angegeben werden."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s ist kein von cryptsetup verwaltetes Gerät."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Die Geräteart »%s« kann nicht aufgefrischt werden"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Unbekannte Art »%s« des Metadaten-Geräts."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "Dieser Befehl benötigt den Gerätenamen und den zugeordneten Namen als Argumente."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Diese Operation wird alle Schlüsselfächer auf Gerät »%s« löschen.\n"
+"Dadurch wird das Gerät unbrauchbar."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Vorgang abgebrochen, die Schlüsselfächer wurden NICHT gesäubert.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Invalid LUKS type, only luks1 and luks2 are supported."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Das Gerät hat bereits den Typ »%s«."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Diese Operation wird für »%s« ins Format »%s« umwandeln.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Vorgang abgebrochen, das Gerät wurde NICHT konvertiert.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Die Option --priority, --label oder --subsystem fehlt."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Token %d ist ungültig."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Token %d ist in Benutzung."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Fehler beim Hinzufügen des LUKS2-Schlüsselring-Tokens %d."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Token %d kann nicht dem Schlüsselfach %d zugeordnet werden."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Token %d wird gerade nicht verwendet."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Token konnte nicht aus der Datei importiert werden."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Auf Token %d kann nicht für den Export zugegriffen werden."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Token %d ist nicht dem Schlüsselfach %d zugeordnet."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Token %d kann nicht vom Schlüsselfach %d losgelöst werden."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Die Optionen --tcrypt-hidden, --tcrypt-system und --tcrypt-backup sind nur zusammen mit einem TCRYPT-Gerät erlaubt."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Die Optionen --veracrypt und --disable-veracrypt werden nur für TCRYPT-kompatible Geräte unterstützt."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Die Option --veracrypt-pim wird nur für VeraCrypt-kompatible Geräte unterstützt."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Die Option --veracrypt-query-pim wird nur für VeraCrypt-kompatible Geräte unterstützt."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Die Optionen --veracrypt-pim und --veracrypt-query-pim schließen sich gegenseitig aus."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Die Option --persistent ist nicht mit --test-passphrase kombinierbar."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Die Optionen --refresh und --test-passphrase schließen sich gegenseitig aus."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Die Option --shared ist nur beim beim »open«-Befehl eines Plain-Gerätes erlaubt."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Die Option --skip ist nur beim Öffnen von plain- und loopaes-Geräten erlaubt."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Die Option --offset mit der Aktion Öffnen wird nur für einfache und loopaes-Geräte unterstützt."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Die Option --tcrypt-hidden kann nicht mit --allow-discards kombiniert werden."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Die Option \"Sektorgröße\" mit der Aktion \"Öffnen\" wird nur für einfache Geräte unterstützt."
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Die Option für große IV-Sektoren wird nur unterstützt, wenn das geöffnete Gerät Sektoren größer als 512 Bytes hat."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "Die Option --test-passphrase ist nur beim Öffnen von LUKS-, TCRYPT-, BITLK- und FVAULT2-Geräten erlaubt."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Die Optionen --device-size und --size können nicht kombiniert werden."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Die Option »--unbound« ist nur beim »open«-Befehl eines LUKS-Gerätes erlaubt."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Die Option »--unbound« kann nur in Kombination mit »--test-passphrase« verwendet werden."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Die Optionen --cancel-deferred und --deferred können nicht kombiniert werden."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Die Optionen --reduce-device-size und --data-size können nicht kombiniert werden."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Die Option »--active-name« ist nur auf LUKS2-Geräte anwendbar."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Die Optionen »--active-name« und »--force-offline-reencrypt« können nicht kombiniert werden."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Das Schlüsselfach muss angegeben werden."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Die Optionen --align-payload und --offset können nicht kombiniert werden."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Die Option --integrity-no-wipe ist nur für die »format«-Aktion mit Integritätserweiterung erlaubt."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Nur eine der Optionen --use-[u]random ist erlaubt."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "Die Option »--unbound« erfordert die Schlüsselgröße."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "Ungültige Token-Aktion."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Der Parameter --key-description ist Pflicht für die Aktion »token add«."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Die Aktion erfordert ein bestimmtes Token. Verwenden Sie den Parameter --token-id."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "Die Option »--unbound« kann nur zusammen mit der Aktion zum Hinzufügen eines Tokens verwendet werden."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Die Optionen --key-slot und --unbound können nicht kombiniert werden."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "Die Aktion erfordert ein bestimmtes Schlüsselfach. Verwenden Sie den Parameter --key-slot."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<Gerät> [--type <Art>] [<Name>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "Gerät als <Name> öffnen"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<Name>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "Gerät schließen (Zuordnung entfernen)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "Größe des aktiven Geräts ändern"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "Gerätestatus anzeigen"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <Algorithmus>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "Verschlüsselungsalgorithmus benchmarken"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<Gerät>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "Versuchen, die Metadaten auf dem Datenträger zu reparieren"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "LUKS2-Gerät wiederverschlüsseln"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "Alle Schlüsselfächer löschen (Verschlüsselungsschlüssel entfernen)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "Zwischen den Formaten LUKS und LUKS2 umwandeln"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "Permanente Konfigurationsoptionen für LUKS2 festlegen"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<Gerät> [<neue Schlüsseldatei>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "Ein LUKS-Gerät formatieren"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "Schlüssel zu LUKS-Gerät hinzufügen"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<Gerät> [<Schlüsseldatei>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "Entfernt bereitgestellten Schlüssel oder Schlüsseldatei vom LUKS-Gerät"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "Ändert den angegebenen Schlüssel oder die Schlüsseldatei des LUKS-Geräts"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "Wandelt einen Schlüssel in neue PBKDF-Parameter um"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<Gerät> <Schlüsselfach>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "Löscht Schlüssel mit Nummer <Schlüsselfach> vom LUKS-Gerät"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "UUID des LUKS-Geräts ausgeben"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "Testet <Gerät> auf Header einer LUKS-Partition"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "LUKS-Partitionsinformationen ausgeben"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "TCRYPT-Geräteinformationen ausgeben"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "BITLK-Geräteinformationen ausgeben"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "VFAULT2-Geräteinformationen ausgeben"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "LUKS-Gerät in Ruhezustand versetzen und alle Schlüssel auslöschen (alle IOs werden eingefroren)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "LUKS-Gerät aus dem Ruhezustand aufwecken"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Header und Schlüsselfächer eines LUKS-Geräts sichern"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Header und Schlüsselfächer eines LUKS-Geräts wiederherstellen"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <Gerät>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "LUKS2-Token manipulieren"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<Aktion> ist eine von:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Sie können auch die alten <Aktion>-Aliase benutzen:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<Name> ist das Gerät, das unter »%s« erzeugt wird\n"
+"<Gerät> ist das verschlüsselte Gerät\n"
+"<Schlüsselfach> ist die Nummer des zu verändernden LUKS-Schlüsselfachs\n"
+"<Schlüsseldatei> optionale Schlüsseldatei für den neuen Schlüssel der »luksAddKey«-Aktion\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Vorgegebenes festeingebautes Metadatenformat ist %s (für luksFormat-Aktion).\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Die Unterstützung des externen Token-Plugins LUKS2 ist %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "integriert"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Pfad des Plugins für externe LUKS2-Token: %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "deaktiviert"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Werkseinstellungen für Schlüssel und Passphrasen:\n"
+"\tMaximale Größe der Schlüsseldatei: %d kB, Maximale Länge der interaktiven Passphrase: %d Zeichen\n"
+"Vorgabe-PBKDF für LUKS1: %s, Durchlaufzeit: %d Millisekunden\n"
+"Vorgabe-PBKDF für LUKS2: %s\n"
+"\tIterationszeit: %d, benötigter Speicher: %d kB, parallele Threads: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Standard-Verschlüsselungsparameter:\n"
+"\tLoop-AES: %s, Schlüssel %d Bits\n"
+"\tplain: %s, Schlüssel: %d Bits, Passphrase-Hashen: %s\n"
+"\tLUKS: %s, Schlüssel: %d Bits, LUKS-Header-Hashen: %s, Zufallszahlengenerator: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: Standard-Schlüsselgröße mit XTS-Modus (zwei interne Schlüssel) wird verdoppelt.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: Benötigt %s als Argumente"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Schlüsselfach ist ungültig."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Die Gerätegröße muss ein Vielfaches von 512-Byte-Sektoren sein."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Ungültige Angabe der Maximalgröße für die Wiederverschlüsselungs-Hotzone."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Schlüsselgröße muss ein Vielfaches von 8 Bit sein"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Die maximale Verkleinerungsgröße ist 1 GiB."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Die verkleinerte Größe muss ein Vielfaches von 512-Byte-Sektoren sein."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Die Option --priority kann nur »ignore/normal/prefer« sein."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Diese Hilfe anzeigen"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Kurze Aufrufsyntax anzeigen"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Paketversion ausgeben"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Hilfe-Optionen:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPTION...] <Aktion> <aktionsabhängig>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Argument <Aktion> fehlt."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Unbekannte Aktion."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Die Option --key-file wirkt stärker als das angegebene Schlüsseldatei-Argument."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Die Option --key-file ist nur einmal erlaubt."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Passwortbasierte Schlüsselableitungsfunktion (PBKDF) kann nur »pbkdf2« oder »argon2i/argon2id« sein."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Bei PBKDF darf nur entweder die Anzahl der Durchläufe oder die Zeitbegrenzung angegeben werden."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Die Optionen --keyslot-cipher und --keyslot-keysize können nur zusammen benutzt werden."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Es wird keine Aktion ausgeführt. Aufgerufen mit der Option --test-args.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Fehler beim Deaktivieren der Metadaten-Dateisperre."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Ungültiger Salt-String angegeben."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Fehler beim Schreiben des Hash-Abbilds »%s«."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Fehler beim Schreiben des FEC-Abbilds »%s«."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Fehler beim Schreiben des Wurzel-Hash-Abbilds »%s«."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Fehler beim Schreiben der Wurzel-Hashdatei »%s«."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Gerät »%s« ist kein gültiges VERITY-Gerät."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Fehler beim Anlegen der Wurzel-Hashdatei »%s«."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Ungültige Root-Hash-Datei »%s«."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "Ungültiger Root-Hash-String angegeben."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Ungültige Signaturdatei »%s«."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Fehler beim Einlesen der Signaturdatei »%s«."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Der Befehl erfordert die Option <root_hash> oder --root-hash-file als Argument."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<Datengerät> <Hash-Gerät>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "Gerät formatieren"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<Daten-Gerät> <Hash-Gerät> [<Wurzel_Hash>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "Gerät verifizieren"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<Datengerät> <Name> <Hash-Gerät> [<Wurzel-Hash>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "Status der aktiven Geräte anzeigen"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<Hash-Gerät>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "Auf dem Datenträger gespeicherte Informationen anzeigen"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<Name> ist das Gerät, das unter »%s« angelegt werden soll\n"
+"<Datengerät> ist das Datengerät\n"
+"<Hash-Gerät> ist das Gerät, das die Verifikationsdaten enthält\n"
+"<Root-Hash> ist der Hash des Rootknotens auf <Hash-Gerät>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Einkompilierte Vorgabewerte für dm-verity:\n"
+"\tHash: %s, Datenblock (Bytes): %u, Hashblock (Bytes): %u, Salt-Größe: %u, Hashformat: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Die Optionen --ignore-corruption und --restart-on-corruption können nicht zusammen benutzt werden."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Die Optionen --panic-on-corruption und --restart-on-corruption können nicht zusammen benutzt werden."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Dadurch werden Daten auf %s und %s unwiderruflich überschrieben.\n"
+"Um Daten auf dem Gerät zu bewahren, verwenden Sie die Option »--no-wipe« (und aktivieren Sie sie dann mit »--integrity-recalculate«)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formatiert mit Etikettgröße %u und interner Integrität %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Das Setzen der Option »recalculate« wird nicht unterstützt, Sie können stattdessen »--wipe« erwägen."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Gerät »%s« ist kein gültiges INTEGRITY-Gerät."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<Integritätsgerät>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<Integritätsgerät> <Name>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<Name> ist das Gerät, das unter »%s« angelegt werden soll\n"
+"<Integritätsgerät> ist das Gerät, das die Daten mit Integritätsangaben enthält\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Einkompilierte Vorgabewerte für dm-integrity:\n"
+"\tPrüfalgorithmus: %s\n"
+"\tMaximalgröße der Schlüsseldatei: %d kB\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Ungültige Größe für --%s. Maximum ist %u Bytes."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Sowohl die Schlüsseldatei als auch die Schlüsselgröße müssen angegeben werden."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Sowohl die Schlüsseldatei als auch die Schlüsselgröße müssen für die Journalintegrität angegeben werden."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Wenn ein Integritätsschlüssel für das Journal verwendet wird, muss auch der Integritätsalgorithmus angegeben werden."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Sowohl der Verschlüsselungsschlüssel als auch die Schlüsselgröße müssen für die Journalverschlüsselung angegeben werden."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Wenn ein Verschlüsselungsschlüssel für das Journal verwendet wird, muss auch der Verschlüsselungsalgorithmus angegeben werden."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Die Modi Wiederherstellung und Bitmap schließen sich gegenseitig aus."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Die Journal-Optionen können nicht im Bitmap-Modus verwendet werden."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Die Bitmapoptionen können nur im Bitmapmodus verwendet werden."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"WARNUNG!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Sind Sie sicher? (Tippen Sie 'yes' in Großbuchstaben): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Fehler beim Lesen der Antwort vom Terminal."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Befehl erfolgreich."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "Falsche oder fehlende Parameter"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "Kein Zugriff, oder falsche Passphrase"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "Nicht genug Speicher"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "Falsches Gerät oder falsche Datei angegeben"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "Das Gerät existiert bereits oder wird bereits benutzt"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "Unbekannter Fehler"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Fehler %i beim Ausführen des Befehls »%s«."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Schlüsselfach %i erstellt."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Schlüsselfach %i entsperrt."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Schlüsselfach %i entfernt."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Token %i erstellt."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Token %i entfernt."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Mit dieser PIN konnte kein Token entsperrt werden."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Token %i benötigt eine PIN."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Token (Art %s) benötigt eine PIN."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token %i kann zugewiesenes Schlüsselfach nicht freischalten (falsche Schlüsselfach-Passphrase)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token (Art %s) kann zugewiesenes Schlüsselfach nicht freischalten (falsche Schlüsselfach-Passphrase)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Token %i erfordert zusätzliche fehlende Ressource."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Token (Art %s) erfordert zusätzliche fehlende Ressource."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Es ist kein verwendbares Token (Art %s) vorhanden."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Es ist kein verwendbares Token verfügbar."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Fehler beim Einlesen der Schlüsseldatei »%s«."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Fehler beim Einlesen von %d Bytes aus der Schlüsseldatei »%s«."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Fehler beim Schreiben der Schlüsseldatei »%s«."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Fehler beim Schreiben der Schlüsseldatei »%s«."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> Tage"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> %s geschrieben"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "Geschwindigkeit %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Fortschritt: %5.1f%%, ETA %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Fertiggestellt, Zeit %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Fehler beim Prüfen der Passwortqualität: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Passwort-Qualitätsüberprüfung fehlgeschlagen:\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Passwort-Qualitätsüberprüfung fehlgeschlagen: Falsche Passphrase (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "Fehler beim Lesen der Passphrase vom Terminal."
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "Passphrase bestätigen: "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "Passphrasen stimmen nicht überein."
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "Offset kann nicht zusammen mit Terminaleingabe benutzt werden."
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Passphrase eingeben: "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Geben Sie die Passphrase für »%s« ein: "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "Kein Schlüssel mit dieser Passphrase verfügbar."
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "Es ist kein nutzbares Schlüsselfach verfügbar."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Passphrase-Verifikation ist nur auf Terminal-Eingaben möglich."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Datei %s konnte nicht im Nur-Lese-Modus geöffnet werden."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Geben Sie gültiges LUKS2-Token-JSON an:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "JSON-Datei konnte nicht gelesen werden."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Lesen unterbrochen."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Datei %s konnte nicht im Schreibmodus geöffnet werden."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Schreiben unterbrochen."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "JSON-Datei konnte nicht geschrieben werden."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Automatisch erkanntes aktives dm-Gerät »%s« für Datengerät »%s«.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Fehler bei der automatischen Erkennung von Gerät »%s«."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Gerät »%s« ist kein Blockgerät.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Es ist unklar, ob das Gerät »%s« aktiviert ist oder nicht.\n"
+"Möchten Sie wirklich mit der Wiederverschlüsselung im Offline-Modus fortfahren?\n"
+"Es kann zu Datenverlust kommen, wenn das Gerät gerade aktiviert ist.\n"
+"Um die Wiederverschlüsselung im Online-Modus durchzuführen, verwenden Sie stattdessen den Parameter --active-name.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Gerät %s ist kein Blockgerät. Kann nicht automatisch erkennen, ob es aktiv ist oder nicht.\n"
+"Verwenden Sie --force-offline-reencrypt, um die Prüfung zu umgehen und im Offline-Modus zu laufen (gefährlich!)."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Die angeforderte Option »--resilience« kann nicht auf den aktuellen Wiederverschlüsselungsvorgang angewendet werden."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Das Gerät ist nicht der LUKS2-Verschlüsselung. Die Option »--encrypt« ist widersprüchlich."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Das Gerät ist nicht der LUKS2-Entschlüsselung. Die Option »--encrypt« ist widersprüchlich."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Das Gerät befindet sich in der Wiederverschlüsselung mit Datashift-Resilienz. Die angeforderte Option --resilience kann nicht angewendet werden."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Das Gerät erfordert die Wiederherstellung der Wiederverschlüsselung. Führen Sie zuerst die Reparatur aus."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Gerät %s befindet sich bereits in der LUKS2-Neuverschlüsselung. Möchten Sie den zuvor begonnenen Vorgang fortsetzen?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Die veraltete LUKS2-Wiederverschlüsselung wird nicht mehr unterstützt."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Wiederverschlüsselung von Geräten mit Integritätsprofil wird nicht unterstützt."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Angeforderte --sector-size %<PRIu32> ist nicht kompatibel mit dem %s-Superblock\n"
+"(Blockgröße: %<PRIu32>Bytes), der auf dem Gerät %s erkannt wurde."
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Verschlüsselung ohne separaten Kopfbereich (--header) ist nur möglich, wenn die Größe des Hauptgeräts reduziert wird (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Der angeforderte Datenoffset darf maximal die Hälfte des Parameters --reduce-device-size betragen."
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Der Wert von --reduce-device-size wird auf das Doppelte von --offset %<PRIu64> (in Sektoren) angepasst.\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Temporäre Headerdatei »%s« existiert bereits. Wird abgebrochen."
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Fehler beim Anlegen der temporären Headerdatei »%s«."
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Die Größe der LUKS2-Metadaten ist größer als der Wert der Datenverschiebung."
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Der neue Header konnte nicht am Kopf des Geräts %s platziert werden."
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s ist jetzt aktiv und bereit für die Onlineverschlüsselung.\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Das aktive Gerät »%s« ist kein LUKS2-Gerät."
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "Wiederherstellung des ursprünglichen LUKS2-Headers."
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "Fehler beim Wiederherstellen des ursprünglichen LUKS2-Headers."
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Die Header-Datei %s existiert nicht. Möchten Sie die LUKS2-Entschlüsselung von Gerät %s initialisieren und LUKS2-Header in Datei %s exportieren?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Fehler beim Hinzufügen der Lese-/Schreibberechtigung für die exportierte Header-Datei."
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Fehler beim Initialisieren der Wiederverschlüsselung. Eine Sicherungskopie des Headers befindet sich in %s."
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "LUKS2-Entschlüsselung wird nur mit losgelöstem Headergerät unterstützt (mit Datenoffset auf 0 gesetzt)."
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "Nicht genügend freie Schlüsselfächer für Wiederverschlüsselung."
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Schlüsseldatei kann nur mit --key-slot oder mit genau einem aktiven Schlüsselfach benutzt werden."
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Geben Sie die Passphrase für Schlüsselfach %d ein: "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Geben Sie die Passphrase für Schlüsselfach %u ein: "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Der Verschlüsselungsalgorithmus wird auf %s geändert.\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Keine Datensegmentparameter geändert. Wiederverschlüsselung abgebrochen."
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Die Zunahme der Größe des Verschlüsselungssektors auf einem Offline-Gerät wird nicht unterstützt.\n"
+"Aktivieren Sie das Gerät zuerst oder verwenden Sie die Option »--force-offline-reencrypt« (gefährlich!)."
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Wiederverschlüsselung unterbrochen."
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "LUKS-Wiederverschlüsselung wird im erzwungenen Offline-Modus fortgesetzt.\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Das Gerät %s enthält fehlerhafte LUKS-Metadaten. Vorgang wird abgebrochen."
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Gerät %s ist bereits ein LUKS-Gerät. Vorgang wird abgebrochen."
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Gerät %s befindet sich bereits in der LUKS-Wiederverschlüsselung. Vorgang wird abgebrochen."
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "LUKS2-Entschlüsselung erfordert die Option »--header«."
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "Dieser Befehl benötigt den Gerätenamen als Argument."
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Widersprüchliche Versionen. Gerät %s ist LUKS1."
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Widersprüchliche Versionen. Gerät %s befindet sich in der LUKS1-Wiederverschlüsselung."
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Widersprüchliche Versionen. Gerät %s ist LUKS2."
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Widersprüchliche Versionen. Gerät %s befindet sich in LUKS2-Wiederverschlüsselung."
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Die LUKS2-Wiederverschlüsselung wurde bereits begonnen. Die Operation wird abgebrochen."
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "Derzeit läuft keine Wiederverschlüsselung."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Gerät »%s« kann nicht exklusiv geöffnet werden, da es bereits benutzt wird."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Belegen des ausgerichteten Speichers fehlgeschlagen."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Fehler beim Lesen von Gerät »%s«."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "LUKS1-Gerät »%s« wird als unbenutzbar markiert."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Fehler beim Schreiben auf Gerät »%s«."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Fehler beim Speichern der Wiederverschlüsselungs-Logdatei."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Fehler beim Einlesen der Wiederverschlüsselungs-Logdatei."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Falsches Protokollformat."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Logdatei »%s« existiert, Wiederverschlüsselung wird fortgesetzt.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Temporäres Gerät mit dem alten LUKS-Header wird aktiviert."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Temporäres Gerät mit dem neuen LUKS-Header wird aktiviert."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Fehler beim Aktivieren der temporären Geräte."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Fehler beim Festlegen des Daten-Offsets."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Fehler beim Festlegen der Metadatengröße."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Neuer LUKS-Header für Gerät »%s« angelegt."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "%s-Backup-Header von Gerät »%s« angelegt."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Fehler beim Anlegen des LUKS-Backup-Headers."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Fehler beim Wiederherstellen des %s-Headers auf Gerät »%s«."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "%s-Header auf Gerät »%s« wiederhergestellt."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Fehler beim Öffnen des temporären LUKS-Geräts."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Fehler beim Ermitteln der Gerätegröße."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "E/A-Fehler während der Wiederverschlüsselung."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Die angegebene UUID ist ungültig."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Fehler beim Öffnen der Wiederverschlüsselungs-Logdatei."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Derzeit ist keine Entschlüsselung im Gange, die angegebene UUID kann nur benutzt werden, um einen unterbrochenen Entschlüsselungsvorgang fortzusetzen."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Wiederverschlüsselung ändert: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "Laufwerksschlüssel"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr ", Hash auf "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", Verschlüsselung auf "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "WARNUNG: Gerät %s enthält bereits eine '%s'-Partitionssignatur.\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "WARNUNG: Gerät %s enthält bereits eine '%s'-Superblock-Signatur.\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Fehler beim Initialisieren der Gerätesignatursonden."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Gerät %s konnte nicht gefunden werden."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Datei %s konnte nicht im Lese-/Schreibmodus geöffnet werden."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Die bestehende »%s«-Partitionssignatur auf Gerät %s wird gelöscht."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Die bestehende »%s«-Superblocksignatur auf Gerät %s wird gelöscht."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Fehler beim Löschen der Gerätesignatur."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Gerät %s konnte nicht auf eine Signatur geprüft werden."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Ungültige Größenangabe in Parameter --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Die Option --%s ist nicht mit der Aktion %s kombinierbar."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Fehler beim Schreiben des SSH-Tokens im JSON-Format."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Experimentelles cryptsetup-Plugin zum Entsperren von LUKS2-Geräten mit einem an einen SSH-Server angeschlossenen Token\\v\n"
+"Dieses Plugin erlaubt derzeit nur das Hinzufügen eines Tokens zu einem bestehenden Schlüsselfach.\n"
+"\n"
+"Der angegebene SSH-Server muss eine Schlüsseldatei im angegebenen Pfad mit einer Passphrase für ein bestehendes Schlüsselfach auf dem Gerät enthalten.\n"
+"Die angegebenen Anmeldedaten werden von cryptsetup verwendet, um das Passwort zu erhalten, wenn das Gerät mit dem Token geöffnet wird.\n"
+"\n"
+"Hinweis: Die beim Hinzufügen des Tokens angegebenen Informationen (SSH-Server-Adresse, Benutzer und Pfade) werden im LUKS2-Header im Klartext gespeichert."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<Aktion> <Gerät>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Optionen für die Aktion \"add\" (Hinzufügen):"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "IP-Adresse/URL des entfernten Servers für dieses Token"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Benutzername, der für den entfernten Server verwendet wird"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Pfad zur Schlüsseldatei auf dem entfernten Server"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Pfad zum SSH-Schlüssel für die Verbindung zum entfernten Server"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Schlüsselfach, dem das Token zugewiesen werden soll. Wenn nicht angegeben, wird das Token dem ersten Schlüsselfach zugewiesen, das zur angegebenen Passphrase passt."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Allgemeine Optionen:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Zeigt detailliertere Fehlermeldungen an"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Zeigt Debugging-Meldungen an"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Debugging-Meldungen anzeigen, inclusive JSON-Metadaten"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Öffnen und Importieren des privaten Schlüssels fehlgeschlagen:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Der Import des privaten Schlüssels (passwortgeschützt?) ist fehlgeschlagen.\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Passwort von %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Das Parsen der Argumente ist fehlgeschlagen.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Es muss eine Aktion angegeben werden\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Für die Aktion '%s' muss ein Gerät angegeben werden.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Für die Aktion '%s' muss ein SSH-Server angegeben werden.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Für die Aktion '%s' muss ein SSH-Benutzer angegeben werden.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Für die Aktion '%s' muss ein SSH-Pfad angegeben werden.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Für die Aktion '%s' muss ein SSH-Schlüsselpfad angegeben werden.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Öffnen von %s mit den angegebenen Anmeldeinformationen fehlgeschlagen.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Nur die Aktion \"add\" (Hinzufügen) wird derzeit von diesem Plugin unterstützt.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Kann keine sftp-Sitzung erstellen: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Kann sftp-Sitzung nicht starten: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Kann sftp-Sitzung nicht eröffnen: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Kann Eigenschaften der sftp-Datei nicht ermitteln: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Nicht genug Speicher.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Entfernter Schlüssel kann nicht gelesen werden: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Verbindung fehlgeschlagen: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Server nicht bekannt: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Authentifizierung mit öffentlichem Schlüssel ist auf dem Host nicht erlaubt.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Fehler bei der Authentifizierung mit öffentlichem Schlüssel: "
+
+#~ msgid "WARNING: Data offset is outside of currently available data device.\n"
+#~ msgstr "WARNING: Der Datenoffset ist außerhalb des derzeit verfügbaren Datengeräts.\n"
+
+#~ msgid "Cannot get process priority."
+#~ msgstr "Fehler beim Ermitteln der Prozesspriorität."
+
+#~ msgid "Cannot unlock memory."
+#~ msgstr "Fehler beim Entsperren des Speichers."
+
+#~ msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+#~ msgstr "Das Verzeichnis %s/%s, das die Dateisperren enthält, wird mit den vorgegebenen, fest einprogrammierten Berechtigungen erzeugt."
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Fehler beim Lesen der BITLK-Signatur von »%s«."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Ungültige oder unbekannte Signatur für BITLK-Gerät."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Fehler beim gründlichen Löschen der Backupsegmentdaten."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Fehler beim Deaktivieren der Wiederverschlüsselungsanforderung."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Verschlüsselung wird nur für das LUKS2-Format unterstützt."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "LUKS-Gerät auf »%s« erkannt. Möchten Sie dieses LUKS-Gerät erneut verschlüsseln?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "Derzeit wird nur das LUKS2-Format unterstützt. Bitte verwenden Sie das Werkzeug cryptsetup-reencrypt für LUKS1."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Veraltete Offline-Wiederverschlüsselung wird gerade durchgeführt. Verwenden Sie das Hilfsprogramm cryptsetup-reencrypt."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "LUKS2-Gerät wird derzeit nicht wiederverschlüsselt."
+
+#~ msgid "Reencryption already in-progress."
+#~ msgstr "Wiederverschlüsselung läuft bereits."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "LUKS2-Offline-Wiederverschlüsselungs-Kennzeichen wird auf Gerät »%s« festgelegt."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Diese Version von cryptsetup-reencrypt kann internen Tokentyp %s nicht verarbeiten."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Fehler beim Lesen der Aktivierungsschalter aus dem Backup-Header."
+
+#~ msgid "Failed to write activation flags to new header."
+#~ msgstr "Fehler beim Schreiben der Aktivierungsschalter in den neuen Header."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "PBKDF-Parameter in Schlüsselfach %i wurden geändert."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Für die Wiederverschlüsselungs-Blockgröße sind nur Werte zwischen 1 MiB und 64 MiB erlaubt."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "Die maximale Verkleinerungsgröße ist 64 MiB."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[OPTION...] <Gerät>"
+
+#~ msgid "Argument required."
+#~ msgstr "Argument muss angegeben werden."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "Die Option »--new« muss zusammen mit »--reduce-device-size« oder »--header« benutzt werden."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "Die Option »--keep-new« kann nur zusammen mit »--hash«, »--iter-time« oder »--pbkdf-force-iterations« benutzt werden."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "Die Option »--new« kann nicht zusammen mit »--decrypt« benutzt werden."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "Die Option --decrypt verträgt sich nicht mit den angegebenen Parametern."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "Die Option »--uuid« kann nur zusammen mit »--decrypt« benutzt werden."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Ungültiger LUKS-Typ. Verwenden Sie einen von diesen: luks, luks1, luks2."
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Gerät %s wird gerade benutzt. Das Formatieren ist gerade nicht möglich."
+
+#~ msgid "No free token slot."
+#~ msgstr "Kein freies Fach für Token."
+
+# upstream: period missing
+#~ msgid "Failed to create builtin token %s."
+#~ msgstr "Fehler beim Erzeugen des eingebauten Tokens »%s«."
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Ungültige LUKS-Geräteart."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Der Algorithmus zum Verschlüsseln des Datenträgers (siehe /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Das Hashverfahren, um den Verschlüsselungsschlüssel aus der Passphrase zu erzeugen"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Verifiziert die Passphrase durch doppeltes Nachfragen"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Schlüssel aus einer Datei lesen"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Laufwerks-(Master-)Schlüssel aus Datei lesen."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Laufwerks-(Master-)schlüssel anstelle der Schlüsselfach-Informationen wegschreiben"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Die Größe des Verschlüsselungsschlüssels"
+
+#~ msgid "BITS"
+#~ msgstr "BITS"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Begrenzt das Lesen aus der Schlüsseldatei"
+
+#~ msgid "bytes"
+#~ msgstr "Bytes"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Anzahl der Bytes, die in der Schlüsseldatei übersprungen werden"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Begrenzt das Lesen aus der neu erzeugten Schlüsseldatei"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Anzahl der Bytes, die in der neu erzeugten Schlüsseldatei übersprungen werden"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Fachnummer für den neuen Schlüssel (im Zweifel das nächste freie)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Die Größe des Geräts"
+
+#~ msgid "SECTORS"
+#~ msgstr "SEKTOREN"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Nur die angegebene Gerätegröße benutzen (Rest des Gerätes ignorieren). GEFÄHRLICH!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Der Startoffset im Backend-Gerät"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Wieviele Sektoren der verschlüsselten Daten am Anfang übersprungen werden sollen"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Eine schreibgeschützte Zuordnung erzeugen"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Nicht nach Bestätigung fragen"
+
+# XXX
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Frist für interaktive Eingabe der Passphrase (in Sekunden)"
+
+#~ msgid "secs"
+#~ msgstr "sek"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Aktualisierungsintervall für Fortschrittszeile (in Sekunden)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Wie oft die Eingabe der Passphrase wiederholt werden kann"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Nutzdaten an Grenzen von <n> Sektoren ausrichten - für luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Datei mit dem Backup der LUKS-Header und den Schlüsselfächern"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "/dev/random zum Generieren des Laufwerksschlüssels benutzen"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "/dev/urandom zum Generieren des Laufwerksschlüssels benutzen"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Gerät mit einem anderen nicht-überlappenden Kryptosegment teilen"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "UUID für das zu verwendende Gerät"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Auswurf-Anfragen (»TRIM«-Befehl) für das Gerät zulassen"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Gerät oder Datei mit separatem LUKS-Header"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Gerät nicht aktivieren, nur Passphrase überprüfen"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Versteckten Header benutzen (verstecktes TCRYPT-Gerät)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Das Gerät ist das System-TCRYPT-Laufwerk (mit Bootlader)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Backup-(Zweit-)-TCRYPT-Header benutzen"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Auch nach VeryCrypt-kompatiblen Geräten suchen"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Persönlicher Interations-Multiplizierer (PIM) für VeryCrypt-kompatibles Gerät"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Bei VeraCrypt-kompatiblem Gerät nach persönlichem Iterations-Multiplizierer (PIM) fragen"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Art der Geräte-Metadaten: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Passwort-Qualitätsprüfung deaktivieren (wenn sie aktiviert ist)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Kompatibilitäts-Performance-Option »same_cpu_crypt« für dm-crypt benutzen"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Kompatibilitäts-Performance-Option »submit_from_crypt_cpus« für dm-crypt benutzen"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Arbeitswarteschlangen von dm-crypt umgehen und Leseanfragen synchron abarbeiten"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Arbeitswarteschlangen von dm-crypt umgehen und Schreibanfragen synchron abarbeiten"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "Das Entfernen des Geräts wird aufgeschoben, bis der letzte Benutzer es schließt"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Globale Sperre verwenden, um speicherintensive PBKDF zu serialisieren (um Speicherprobleme zu umgehen)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "PBKDF-Iterationszeit for LUKS (in ms)"
+
+#~ msgid "msecs"
+#~ msgstr "msek"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "PBKDF-Algorithmus (für LUKS2): argon2i, argon2id, pbkdf2"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "PBKDF-Speicherkostengrenze"
+
+#~ msgid "kilobytes"
+#~ msgstr "Kilobytes"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "PBKDF-Parallelitätskosten"
+
+#~ msgid "threads"
+#~ msgstr "Threads"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "PBKDF-Iterationskosten (erzwungen, deaktiviert Benchmark)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Schlüsselfach-Priorität: ignore (ignorieren), normal, prefer (bevorzugen)"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Dateisperrung von Metadaten auf der Platte deaktivieren"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Deaktivieren, dass Laufwerksschlüssel über den Kernel-Schlüsselbund geladen werden"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Datenintegritätsalgorithmus (nur LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Aufzeichnung für Integritätsgerät deaktivieren"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Gerät nach dem Formatieren nicht säubern"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Ineffizientes Altlasten-Padding verwenden (für alte Kernel)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Nicht nach einer Passphrase fragen, wenn die Aktivierung durch Token fehlschlägt"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Token-Nummer (Vorgabe: eine beliebige)"
+
+#~ msgid "Key description"
+#~ msgstr "Schlüsselbeschreibung"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Verschlüsselungs-Sektorgröße (Vorgabe: 512 Bytes)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "IV verwenden (in Sektorgröße gezählt statt in Einheiten von 512 Bytes)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Aktivierungsschalter für Gerät permanent festlegen"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Beschriftung für das LUKS2-Gerät festlegen"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Teilsystem-Beschriftung für das LUKS2-Gerät festlegen"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Unbeschränktes LUKS2-Schlüsselfach (ohne zugeordnetem Datensegment) anlegen oder wegschreiben"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "JSON aus einer Datei lesen oder in eine Datei schreiben"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Größe des Bereichs für LUKS2-Header-Metadaten"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Größe des Bereichs für Schlüsselfächer im LUKS2-Header"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Gerät mit neuen Parametern auffrischen (reaktivieren)"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "LUKS2-Schlüsselfach: Die Größe des Verschlüsselungsschlüssels"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "LUKS2-Keyslot: Der Algorithmus, der für die Keyslot-Verschlüsselung verwendet wird"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "LUKS2-Gerät verschlüsseln (direkt am Ort)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "LUKS2-Gerät entschlüsseln (Verschlüsselung entfernen)."
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "LUKS2-Wiederverschlüsselung nur in Metadaten beginnen."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Nur eine begonnene LUKS2-Wiederverschlüsselung fortsetzen."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Größe des Datengeräts reduzieren (Datenoffset verschieben). GEFÄHRLICH!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Maximalgröße der Wiederverschlüsselungs-Hotzone."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Widerstandsfähigkeit der Hotzone für die Wiederverschlüsselung (checksum,journal,none)"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Hash für Prüfsummen der Wiederverschlüsselungs-Hotzone"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Automatische Geräteerkennung der dm-Geräte für die Wiederverschlüsselung übersteuern"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "Die Option --deferred ist nur beim »close«-Befehl erlaubt."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "Die Option --allow-discards ist nur beim »open«-Befehl erlaubt."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "Die Option --persistent ist nur beim »open«-Befehl erlaubt."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "Die Option --serialize-memory-hard-pbkdf ist nur beim »open«-Befehl erlaubt."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Die Option --key-size ist nur für »luksFormat«, »luksAddKey«,\n"
+#~ "»open« und »benchmark« erlaubt. Benutzen Sie stattdessen »--keyfile-size=(Bytes)«,\n"
+#~ "um das Lesen aus der Schlüsseldatei zu begrenzen."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "Die Option --integrity ist nur für luksFormat (LUKS2) erlaubt."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Die Optionen --label und --subsystem sind nur für die Aktionen »luksFormat« und »config LUKS2« erlaubt."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "Negative Zahl für die Option nicht erlaubt."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "Die Option --use-[u]random ist nur für luksFormat erlaubt."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "Die Option --uuid ist nur für luksFormat und luksUUID erlaubt."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "Die Option --align-payload ist nur für luksFormat erlaubt."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Die Optionen --luks2-metadata-size und --opt-luks2-keyslots-size sind nur für luksFormat mit LUKS2 erlaubt."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Ungültige Angabe für die Größe der LUKS2-Metadaten."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Ungültige Angabe für die Größe der LUKS2-Schlüsselfächer."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "Die Option --offset ist nur beim Öffnen von plain- und loopaes-Geräten erlaubt, sowie für luksFormat und Geräte-Wiederverschlüsselung."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Ungültiges Argument für Parameter --veracrypt-pim angegeben."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "Die Option Sektorgröße wird für diesen Befehl nicht unterstützt."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "Die Option --refresh kann nur zusammen mit der Aktion »open« benutzt werden."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "Ungültige Angabe der Gerätegröße."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Überlauf bei der Verringerungsgröße."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Verity-Superblock nicht benutzen"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Format-Art (1 - normal, 0 - originales Chrome-OS)"
+
+#~ msgid "number"
+#~ msgstr "Zahl"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Blockgröße auf dem Datengerät"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Blockgröße auf dem Hash-Gerät"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "FEC-Paritätsbytes"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Die Anzahl der Blöcke in der Datendatei"
+
+#~ msgid "blocks"
+#~ msgstr "Blöcke"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Pfad zum Gerät mit Fehlerkorrekturdaten"
+
+#~ msgid "path"
+#~ msgstr "Pfad"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Start-Offset auf dem Hash-Gerät"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Start-Offset auf dem FEC-Gerät"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Hash-Algorithmus"
+
+#~ msgid "string"
+#~ msgstr "Zeichenkette"
+
+#~ msgid "Salt"
+#~ msgstr "Salt"
+
+#~ msgid "hex string"
+#~ msgstr "Hex-Zeichenkette"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Pfad zur Signaturdatei des Stammhashes"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Kernel neustarten wenn Beschädigung festgestellt wird"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Kernel-Abbruch, wenn Beschädigung festgestellt wird"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Beschädigung ignorieren, nur mitloggen"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Ausgenullte Blöcke nicht überprüfen"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Datenblock nur beim erstmaligen Lesen verifizieren"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Die Optionen --ignore-corruption, --restart-on-corruption und --ignore-zero-blocks sind nur für die »open«-Aktion erlaubt."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "Die Option --root-hash-signature kann nur zusammen mit der Aktion »open« benutzt werden."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Pfad zum Datengerät (wenn getrennt)"
+
+#~ msgid "Journal size"
+#~ msgstr "Journalgröße"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Sektoren verschränken"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Jornal-Wasserzeichen"
+
+#~ msgid "percent"
+#~ msgstr "Prozent"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Journal-Commitzeit"
+
+#~ msgid "ms"
+#~ msgstr "ms"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Anzahl der 512-Byte-Sektoren pro Bit (Bitmap-Modus)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Zeit für sicheres Speichern im Bitmap-Modus"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Etikettgröße pro Sektor"
+
+#~ msgid "Sector size"
+#~ msgstr "Sektorengröße"
+
+#~ msgid "Buffers size"
+#~ msgstr "Puffergröße"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Datenintegritäts-Algorithmus"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Die Größe des Datenintegritätsschlüssels"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Integritätsschlüssel aus einer Datei lesen"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Integritätsalgorithmus für Journal"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Die Größe des Integritätsschlüssels für das Journal"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Integritätsschlüssel für das Journal aus einer Datei lesen"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Algorithmus für Journalverschlüsselung"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Die Größe des Journal-Verschlüsselungsschlüssels"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Journal-Verschlüsselungsschlüssel aus einer Datei lesen"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Wiederherstellungsmodus (kein Journal, keine Etikettprüfung)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Bitmap verwenden, um Änderungen nachzuverfolgen und Journal für Integritätsgerät deaktivieren"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Initiale Integritätsangaben automatisch neu berechnen."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Superblock nicht mit HMAC schützen (alte Kernel)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Neuberechnung von Laufwerken mit HMAC-Schlüsseln erlauben (alte Kernel)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "Die Option --integrity-recalculate kann nur zusammen mit der Aktion »open« benutzt werden."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Die Optionen --journal-size, --interleave-sectors, --sector-size, --tag-size und --no-wipe können nur bei der Aktion »format« verwendet werden."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "Ungültige Angabe der Journalgröße."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Wiederverschlüsselungs-Blockgröße"
+
+#~ msgid "MiB"
+#~ msgstr "MiB"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Schlüssel nicht ändern, Datenbereich nicht neu verschlüsseln"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Laufwerks-(Master-)Schlüssel aus Datei lesen"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Beim Zugriff auf die Geräte direct-io benutzen"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Nach jedem Block fsync aufrufen"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Logdatei nach jedem Block aktualisieren"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Nur dieses Schlüsselfach benutzen (alle anderen werden deaktiviert)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Neuen Header auf unverschlüsseltem Gerät anlegen"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Gerät dauerhaft entschlüsseln (Verschlüsselung entfernen)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "Die UUID, um das Entschlüsseln fortzusetzen"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Art der LUKS-Metadaten: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "WARNUNG: Zugriffssperren-Verzeichnis %s/%s ist nicht vorhanden!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Ungültige Größenparameter für Verity-Gerät."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "Wenn ein Integritätsschlüssel verwendet wird, muss auch der Integritätsalgorithmus angegeben werden."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Falsche Schlüsselgröße."
+
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands."
+#~ msgstr "Die Option --refresh ist nur beim »open«- oder »refresh«-Befehl erlaubt."
+
+#~ msgid "Unsupported encryption sector size.\n"
+#~ msgstr "Nicht unterstützte Sektorengröße für Verschlüsselung.\n"
+
+#~ msgid "Offline reencryption in progress. Aborting."
+#~ msgstr "Offline-Wiederverschlüsselung läuft gerade. Wird abgebrochen."
+
+#~ msgid "Online reencryption in progress. Aborting."
+#~ msgstr "Online-Wiederverschlüsselung läuft gerade. Wird abgebrochen."
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Durch ein Signal unterbrochen."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "Diese Funktion ist im FIPS-Modus nicht verfügbar."
+
+#~ msgid "Failed to finalize hash."
+#~ msgstr "Fehler beim Berechnen des Hashes."
+
+#~ msgid "Invalid resilience parameters (internal error)."
+#~ msgstr "Interner Fehler: ungültige Parameter für Widerstandsfähigkeit."
+
+#~ msgid "Failed to assign new enc segments."
+#~ msgstr "Fehler beim Zuweisen neuer Verschlüsselungssegmente."
+
+#~ msgid "Failed to assign digest %u to segment %u."
+#~ msgstr "Digest %u konnte dem Segment %u nicht zugewiesen werden."
+
+#~ msgid "Failed to assign reencrypt previous backup segment."
+#~ msgstr "Fehler beim Wiederverschlüsseln des vorigen Backupsegments."
+
+#~ msgid "Failed to assign reencrypt final backup segment."
+#~ msgstr "Fehler beim Wiederverschlüsseln des letzten Backupsegments."
+
+#~ msgid "Failed generate 2nd segment."
+#~ msgstr "Fehler beim Generieren des 2. Segments."
+
+#~ msgid "Failed generate 1st segment."
+#~ msgstr "Fehler beim Generieren des 1. Segments."
+
+#~ msgid "Failed to allocate device %s."
+#~ msgstr "Fehler beim Öffnen des Geräts »%s«."
+
+#~ msgid "Failed to allocate dm segments."
+#~ msgstr "Fehler beim Reservieren der dm-Segmente."
+
+#~ msgid "Failed to create dm segments."
+#~ msgstr "Fehler beim Anlegen der dm-Segmente."
+
+#~ msgid "Failed to allocate device for new backing device."
+#~ msgstr "Fehler beim Reservieren des Geräts für das neue Hintergrundgerät."
+
+#~ msgid "Failed to reload overlay device %s."
+#~ msgstr "Fehler beim Neuladen des Überlagerungsgeräts »%s«."
+
+#~ msgid "Failed to refresh helper devices."
+#~ msgstr "Fehler beim Auffrischen der Hilfsgeräte."
+
+#~ msgid "Failed to create reencryption backup segments."
+#~ msgstr "Fehler beim Erzeugen der Backupsegmente für die Wiederverschlüsselung."
+
+#~ msgid "Failed to set online-reencryption requirement."
+#~ msgstr "Fehler beim Festlegen der Anforderungen für Online-Wiederverschlüsselung."
+
+#~ msgid "Failed to hash sector at offset %zu."
+#~ msgstr "Fehler beim Hashen des Sektors an Offset %zu."
+
+#~ msgid "Failed to read sector hash."
+#~ msgstr "Fehler beim Lesen des Hashes des Sektors."
+
+#~ msgid "Error: Calculated reencryption offset %<PRIu64> is beyond device size %<PRIu64>."
+#~ msgstr "Fehler: Der berechnete Offset für die Wiederverschlüsselung %<PRIu64> liegt jenseits der Gerätegröße %<PRIu64>."
+
+#~ msgid "Failed to calculate new segments."
+#~ msgstr "Fehler beim Berechnen der neuen Segmente."
+
+#~ msgid "Failed finalize hotzone resilience, retval = %d"
+#~ msgstr "Interner Fehler beim Finalisieren der Hotzonen-Widerstandsfähigkeit, retval = %d"
+
+#~ msgid "Failed to write data."
+#~ msgstr "Fehler beim Schreiben von Daten."
+
+#~ msgid "Failed to update metadata or reassign device segments."
+#~ msgstr "Fehler beim Aktualisieren der Metadaten oder bei der Zuordnung von Gerätesegmenten."
+
+#~ msgid "Failed to reload %s device."
+#~ msgstr "Fehler beim Neuladen des Geräts »%s«."
+
+#~ msgid "Failed to erase backup segments"
+#~ msgstr "Fehler beim Löschen der Backupsegmente."
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Die verlangten dmcrypt-Performance-Optionen werden nicht unterstützt."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "Gerät »%s« kann nicht formatiert werden, da es gerade benutzt wird."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "Schlüsselfach %d ist unbenutzt."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "Schlüsselfach %d zum Löschen ausgewählt."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "Gerät als Zuordnung <Name> öffnen"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "Gerät schließen (deaktivieren und Zuordnung entfernen)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "Fehler beim Festlegen der PBKDF-Parameter."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "Fehler beim Springen zum Gerät-Offset.\n"
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Gerät »%s« ist zu klein. (LUKS2 benötigt mindestens %<PRIu64> Bytes.)"
+
+#~ msgid "Replaced with key slot %d."
+#~ msgstr "Ersetzt durch Schlüsselfach %d."
+
+#~ msgid "Missing LUKS target type, option --type is required."
+#~ msgstr "Fehlender LUKS-Zieltyp, die Option --type ist Pflicht."
+
+#~ msgid "Missing --token option specifying token for removal."
+#~ msgstr "Um ein Token zu löschen, muss die Option --token angegeben werden."
+
+#~ msgid "Add or remove keyring token"
+#~ msgstr "Schlüsselring-Token hinzufügen oder entfernen"
+
+#~ msgid "Activated keyslot %i."
+#~ msgstr "Schlüsselfach %i aktiviert."
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "Speicherproblem in action_luksFormat"
+
+#~ msgid "Key slot is invalid.\n"
+#~ msgstr "Schlüsselfach ist ungültig.\n"
+
+#~ msgid "Using default pbkdf parameters for new LUKS2 header.\n"
+#~ msgstr "Für den neuen LUKS2-Header werden die vorgegebenen PBKDF-Parameter verwendet.\n"
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..2a4d9f4
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,4373 @@
+# Spanish translations for cryptsetup package
+# Traducciones al español para el paquete cryptsetup.
+# Copyright (C) 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Antonio Ceballos <aceballos@gmail.com>, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021
+#
+# ######################################################################
+# Traducciones dudosas:
+# ######################################################################
+#
+# initialize = inicializar
+# kernel = núcleo
+#  imperativo - usted
+# % done = % hecho
+# fatal error = error fatal
+#  RNG = generador de números aleatorios
+# not supported = no disponible
+# key slot = ranura de claves
+# passphrase = frase contraseña
+# offset = desplazamiento
+# offset = posición
+# suspended = suspendido
+# plain device = dispositivo no cifrado (dispositivo en claro)
+# crypt device = dispositivo cifrado
+# error reading = error al leer
+# keyfile = fichero de claves (¿fichero de la clave?)
+#  checksum = suma de comprobación
+# loopback device = dispositivo de bucle invertido (Santiago: dispositivo de bucle)
+# backup file = fichero de copia de seguridad
+# please - omitido, porque ya es suficiente cortesía tratar de usted al usuario
+#  wipe = limpiar, borrar
+# interface = (la) interfaz
+# cipher = algoritmo de cifrado
+# default = predefinido
+# default compiled-in = predefinido de fábrica
+# debug = depuración
+# bootloader = cargador de arranque
+# verify = verificar
+# verification = verificación
+# log file = fichero de registro
+# temporary = temporal
+# reencryption = recifrado
+# invalid = no válido, -a
+# lock = bloqueo
+# hotzone = zona activa
+# unbound key = clave independiente
+#
+# #######################################################################
+# Términos no traducidos
+# #######################################################################
+#
+# device mapper
+# backend
+# hash
+# buffer
+# offset
+# bit(s)
+# byte(s)
+# loopaes
+# luks
+# tcrypt
+# salt
+# verity
+#
+# #######################################################################
+# Otras dudas
+# #######################################################################
+#
+# invalid = inválido, -a -> barbarismo -> mejor: no válido
+# on-disk
+#
+# #######################################################################
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.4.2-rc0\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2021-11-11 19:08+0100\n"
+"PO-Revision-Date: 2021-12-12 11:49+0100\n"
+"Last-Translator: Antonio Ceballos <aceballos@gmail.com>\n"
+"Language-Team: Spanish <es@tp.org.es>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: lib/libdevmapper.c:396
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "No se puede inicializar el «device mapper», ejecutando como usuario no administrador."
+
+#: lib/libdevmapper.c:399
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "No se puede inicializar el «device-mapper». ¿Está cargado el módulo del núcleo dm_mod?"
+
+#: lib/libdevmapper.c:1170
+msgid "Requested deferred flag is not supported."
+msgstr "El indicador diferido solicitado no está disponible."
+
+#: lib/libdevmapper.c:1239
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "El DM-UUID del dispositivo %s ha sido truncado."
+
+#: lib/libdevmapper.c:1567
+msgid "Unknown dm target type."
+msgstr "Tipo de objetivo dm desconocido."
+
+#: lib/libdevmapper.c:1688 lib/libdevmapper.c:1693 lib/libdevmapper.c:1757
+#: lib/libdevmapper.c:1760
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Las opciones de rendimiento de dm-crypt solicitadas no están disponibles."
+
+#: lib/libdevmapper.c:1700 lib/libdevmapper.c:1704
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Las opciones de manejo de corrupción de datos de dm-verity solicitadas no están disponibles."
+
+#: lib/libdevmapper.c:1708
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Las opciones FEC de dm-verity solicitadas no están disponibles."
+
+#: lib/libdevmapper.c:1712
+msgid "Requested data integrity options are not supported."
+msgstr "Las opciones de integridad de datos solicitadas no están disponibles."
+
+#: lib/libdevmapper.c:1714
+msgid "Requested sector_size option is not supported."
+msgstr "La opción sector_size solicitada no está disponible."
+
+#: lib/libdevmapper.c:1719 lib/libdevmapper.c:1723
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "El recómputo automático de las etiquetas de integridad solicitado no está disponible."
+
+#: lib/libdevmapper.c:1727 lib/libdevmapper.c:1763 lib/libdevmapper.c:1766
+#: lib/luks2/luks2_json_metadata.c:2204
+msgid "Discard/TRIM is not supported."
+msgstr "Descartar/TRIM no disponible."
+
+#: lib/libdevmapper.c:1731
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "El modo de mapa de bits de dm-integrity solicitado no está disponible."
+
+#: lib/libdevmapper.c:2705
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "No se ha podido consultar el segmento de dm-%s."
+
+#: lib/random.c:75
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"El sistema se ha quedado sin entropía mientras estaba generando la clave del volumen.\n"
+"Por favor, mueva el ratón o pulse alguna tecla en otra ventana para provocar algún evento aleatorio.\n"
+
+#: lib/random.c:79
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Generando la clave (%d%% hecho).\n"
+
+#: lib/random.c:165
+msgid "Running in FIPS mode."
+msgstr "Modo FIPS en funcionamiento."
+
+#: lib/random.c:171
+msgid "Fatal error during RNG initialisation."
+msgstr "Error fatal durante la inicialización del generador de números aleatorios."
+
+#: lib/random.c:208
+msgid "Unknown RNG quality requested."
+msgstr "La calidad solicitada para el generador de números aleatorios es desconocida."
+
+#: lib/random.c:213
+msgid "Error reading from RNG."
+msgstr "Error leyendo del generador de números aleatorios."
+
+#: lib/setup.c:226
+msgid "Cannot initialize crypto RNG backend."
+msgstr "No se puede inicializar el «backend» del generador de números aleatorios de cifrado."
+
+#: lib/setup.c:232
+msgid "Cannot initialize crypto backend."
+msgstr "No se puede inicializar el «backend» de cifrado."
+
+#: lib/setup.c:263 lib/setup.c:2079 lib/verity/verity.c:119
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Algoritmo «hash» %s no disponible."
+
+#: lib/setup.c:266 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Error de procesamiento de la clave (usando «hash» %s)."
+
+#: lib/setup.c:332 lib/setup.c:359
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "No se puede determinar el tipo de dispositivo. ¿Es incompatible la activación del dispositivo?"
+
+#: lib/setup.c:338 lib/setup.c:3142
+msgid "This operation is supported only for LUKS device."
+msgstr "Esta operación solamente está disponible para dispositivos LUKS."
+
+#: lib/setup.c:365
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Esta operación solamente está disponible para dispositivos LUKS2."
+
+#: lib/setup.c:420 lib/luks2/luks2_reencrypt.c:2440
+msgid "All key slots full."
+msgstr "Todas las ranuras de claves están llenas."
+
+#: lib/setup.c:431
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "La ranura de claves %d no es válida; seleccione un número entre 0 y %d."
+
+#: lib/setup.c:437
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "La ranura de claves %d está llena; seleccione otra."
+
+#: lib/setup.c:522 lib/setup.c:2900
+msgid "Device size is not aligned to device logical block size."
+msgstr "El tamaño del dispositivo no está alineado con el tamaño de bloque lógico del dispositivo."
+
+#: lib/setup.c:620
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Cabecera detectada pero el dispositivo %s es demasiado pequeño."
+
+#: lib/setup.c:661 lib/setup.c:2845
+msgid "This operation is not supported for this device type."
+msgstr "Esta operación no está disponible para este tipo de dispositivo."
+
+#: lib/setup.c:666
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Operación con recifrado en curso no válida."
+
+#: lib/setup.c:834 lib/luks1/keymanage.c:527
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Versión LUKS no disponible %d."
+
+#: lib/setup.c:1430 lib/setup.c:2610 lib/setup.c:2683 lib/setup.c:2695
+#: lib/setup.c:2853 lib/setup.c:4643
+#, c-format
+msgid "Device %s is not active."
+msgstr "El dispositivo %s no está activo."
+
+#: lib/setup.c:1447
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "El dispositivo subyacente asociado al dispositivo cifrado %s ha desaparecido."
+
+#: lib/setup.c:1527
+msgid "Invalid plain crypt parameters."
+msgstr "Parámetros de cifrado para modo claro no válidos."
+
+#: lib/setup.c:1532 lib/setup.c:1982
+msgid "Invalid key size."
+msgstr "Tamaño de clave no válido."
+
+#: lib/setup.c:1537 lib/setup.c:1987 lib/setup.c:2190
+msgid "UUID is not supported for this crypt type."
+msgstr "El UUID no está disponible para este tipo de cifrado."
+
+#: lib/setup.c:1542 lib/setup.c:1992
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "El dispositivo de metadatos separado no está disponible para este tipo de cifrado."
+
+#: lib/setup.c:1552 lib/setup.c:1754 lib/luks2/luks2_reencrypt.c:2401
+#: src/cryptsetup.c:1358 src/cryptsetup.c:3723
+msgid "Unsupported encryption sector size."
+msgstr "Tamaño de sector de cifrado no admitido."
+
+#: lib/setup.c:1560 lib/setup.c:1895 lib/setup.c:2894
+msgid "Device size is not aligned to requested sector size."
+msgstr "El tamaño del dispositivo no está alineado con el tamaño del sector solicitado."
+
+#: lib/setup.c:1612 lib/setup.c:1732
+msgid "Can't format LUKS without device."
+msgstr "Imposible dar formato LUKS sin dispositivo."
+
+#: lib/setup.c:1618 lib/setup.c:1738
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "El alineamiento de datos solicitado no es compatible con el desplazamiento de los datos."
+
+#: lib/setup.c:1686 lib/setup.c:1882
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr "ATENCIÓN: El desplazamiento de los datos está fuera del dispositivo de datos actualmente disponible.\n"
+
+#: lib/setup.c:1696 lib/setup.c:1912 lib/setup.c:1933 lib/setup.c:2202
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "No se puede limpiar la cabecera del dispositivo %s."
+
+#: lib/setup.c:1763
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "ATENCIÓN: La activación del dispositivo va a fallar; dm-crypt no admite el tamaño de sector de cifrado solicitado.\n"
+
+#: lib/setup.c:1786
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "La clave del volumen es demasiado pequeña para cifrado con extensiones de integridad."
+
+#: lib/setup.c:1856
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "El algoritmo de cifrado %s-%s (tamaño de clave %zd bits) no está disponible."
+
+#: lib/setup.c:1885
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "ATENCIÓN: el tamaño de los metadatos LUKS2 ha cambiado a %<PRIu64> bytes.\n"
+
+#: lib/setup.c:1889
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "ATENCIÓN: el tamaño de la zona de ranuras de claves LUKS2 ha cambiado a %<PRIu64> bytes.\n"
+
+#: lib/setup.c:1915 lib/utils_device.c:909 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:2451 lib/luks2/luks2_reencrypt.c:3488
+#, c-format
+msgid "Device %s is too small."
+msgstr "El dispositivo %s es demasiado pequeño."
+
+#: lib/setup.c:1926 lib/setup.c:1952
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "No se puede dar formato al dispositivo %s en uso."
+
+#: lib/setup.c:1929 lib/setup.c:1955
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "No se puede dar formato al dispositivo %s; permiso denegado."
+
+#: lib/setup.c:1941 lib/setup.c:2262
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "No se puede dar formato a la integridad del dispositivo %s."
+
+#: lib/setup.c:1959
+#, c-format
+msgid "Cannot format device %s."
+msgstr "No se puede dar formato al dispositivo %s."
+
+#: lib/setup.c:1977
+msgid "Can't format LOOPAES without device."
+msgstr "Imposible dar formato LOOPAES sin dispositivo."
+
+#: lib/setup.c:2022
+msgid "Can't format VERITY without device."
+msgstr "Imposible dar formato VERITY sin dispositivo."
+
+#: lib/setup.c:2033 lib/verity/verity.c:102
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Tipo de «hash» VERITY %d no disponible."
+
+#: lib/setup.c:2039 lib/verity/verity.c:110
+msgid "Unsupported VERITY block size."
+msgstr "Tamaño de bloque VERITY no disponible."
+
+#: lib/setup.c:2044 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Desplazamiento «hash» VERITY no disponible."
+
+#: lib/setup.c:2049
+msgid "Unsupported VERITY FEC offset."
+msgstr "Desplazamiento FEC VERITY no disponible."
+
+#: lib/setup.c:2073
+msgid "Data area overlaps with hash area."
+msgstr "La zona de datos se solapa con la zona «hash»."
+
+#: lib/setup.c:2098
+msgid "Hash area overlaps with FEC area."
+msgstr "La zona «hash» se solapa con la zona FEC."
+
+#: lib/setup.c:2105
+msgid "Data area overlaps with FEC area."
+msgstr "La zona de datos se solapa con la zona FEC."
+
+#: lib/setup.c:2241
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "ATENCIÓN: El tamaño de etiqueta de %d bytes solicitado difiere del tamaño de salida de %s (%d bytes).\n"
+
+#: lib/setup.c:2320
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "El tipo de dispositivo cifrado % solicitado es desconocido."
+
+#: lib/setup.c:2616 lib/setup.c:2688 lib/setup.c:2701
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Parámetros no admitidos para el dispositivo %s."
+
+#: lib/setup.c:2622 lib/setup.c:2708 lib/luks2/luks2_reencrypt.c:2503
+#: lib/luks2/luks2_reencrypt.c:2847
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Parámetros discordantes en el dispositivo %s."
+
+#: lib/setup.c:2728
+msgid "Crypt devices mismatch."
+msgstr "Los dispositivos de cifrado no concuerdan."
+
+#: lib/setup.c:2765 lib/setup.c:2770 lib/luks2/luks2_reencrypt.c:2143
+#: lib/luks2/luks2_reencrypt.c:3255
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "No se ha podido recargar el dispositivo %s."
+
+#: lib/setup.c:2776 lib/setup.c:2782 lib/luks2/luks2_reencrypt.c:2114
+#: lib/luks2/luks2_reencrypt.c:2121
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "No se ha podido suspender el dispositivo %s."
+
+#: lib/setup.c:2788 lib/luks2/luks2_reencrypt.c:2128
+#: lib/luks2/luks2_reencrypt.c:3190 lib/luks2/luks2_reencrypt.c:3259
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "No se ha podido reanudar el dispositivo %s."
+
+#: lib/setup.c:2803
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Error grave durante la recarga del dispositivo %s (por encima del dispositivo %s)."
+
+#: lib/setup.c:2806 lib/setup.c:2808
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "No se ha podido conmutar el dispositivo %s a dm-error."
+
+#: lib/setup.c:2885
+msgid "Cannot resize loop device."
+msgstr "No se ha podido cambiar el tamaño del dispositivo de bucle."
+
+#: lib/setup.c:2958
+msgid "Do you really want to change UUID of device?"
+msgstr "¿Está seguro de que quiere cambiar el UUID del dispositivo?"
+
+#: lib/setup.c:3034
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "El fichero de copia de seguridad de la cabecera no contiene una cabecera LUKS compatible."
+
+#: lib/setup.c:3150
+#, c-format
+msgid "Volume %s is not active."
+msgstr "El volumen %s no está activo."
+
+#: lib/setup.c:3161
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "El volumen %s ya está suspendido."
+
+#: lib/setup.c:3174
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "La suspensión no está disponible para el dispositivo %s."
+
+#: lib/setup.c:3176
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Error durante la suspensión del dispositivo %s."
+
+#: lib/setup.c:3212
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "La reanudación no está disponible para el dispositivo %s."
+
+#: lib/setup.c:3214
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Error durante la reanudación del dispositivo %s."
+
+#: lib/setup.c:3248 lib/setup.c:3296 lib/setup.c:3366
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "EL volumen %s no está suspendido."
+
+#: lib/setup.c:3381 lib/setup.c:3750 lib/setup.c:4423 lib/setup.c:4436
+#: lib/setup.c:4444 lib/setup.c:4457 lib/setup.c:4826 lib/setup.c:6008
+msgid "Volume key does not match the volume."
+msgstr "La clave de volumen no corresponde a este volumen."
+
+#: lib/setup.c:3428 lib/setup.c:3633
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "No se puede añadir ranura de claves; todas las ranuras están desactivadas y no se ha proporcionado una clave para el volumen."
+
+#: lib/setup.c:3585
+msgid "Failed to swap new key slot."
+msgstr "No se ha logrado intercambiar la nueva ranura de claves."
+
+#: lib/setup.c:3771
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "La ranura de claves %d no es válida."
+
+#: lib/setup.c:3777 src/cryptsetup.c:1701 src/cryptsetup.c:2041
+#: src/cryptsetup.c:2632 src/cryptsetup.c:2689
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "La ranura de claves %d no está activa."
+
+#: lib/setup.c:3796
+msgid "Device header overlaps with data area."
+msgstr "La cabecera del dispositivo se solapa con la zona de datos."
+
+#: lib/setup.c:4089
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Recifrado en curso. No se puede activar el dispositivo."
+
+#: lib/setup.c:4091 lib/luks2/luks2_json_metadata.c:2287
+#: lib/luks2/luks2_reencrypt.c:2946
+msgid "Failed to get reencryption lock."
+msgstr "No se ha podido conseguir el bloqueo de recifrado."
+
+#: lib/setup.c:4104 lib/luks2/luks2_reencrypt.c:2965
+msgid "LUKS2 reencryption recovery failed."
+msgstr "La recuperación del recifrado LUKS2 ha fallado."
+
+#: lib/setup.c:4235 lib/setup.c:4500
+msgid "Device type is not properly initialized."
+msgstr "Este tipo de dispositivo no se ha inicializado adecuadamente."
+
+#: lib/setup.c:4283
+#, c-format
+msgid "Device %s already exists."
+msgstr "El dispositivo %s ya existe."
+
+#: lib/setup.c:4290
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "No se puede utilizar el dispositivo %s; el nombre no es válido o todavía está en uso."
+
+#: lib/setup.c:4410
+msgid "Incorrect volume key specified for plain device."
+msgstr "Clave de volumen incorrecta para dispositivo no cifrado."
+
+#: lib/setup.c:4526
+msgid "Incorrect root hash specified for verity device."
+msgstr "«Hash» raíz incorrecta para dispositivo «verity»."
+
+#: lib/setup.c:4533
+msgid "Root hash signature required."
+msgstr "Se requiere la firma «hash» raíz."
+
+#: lib/setup.c:4542
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "El llavero de núcleo está ausente: se necesita para pasar la firma al núcleo."
+
+#: lib/setup.c:4559 lib/setup.c:6084
+msgid "Failed to load key in kernel keyring."
+msgstr "No se ha podido cargar la clave en el llavero del núcleo."
+
+#: lib/setup.c:4615
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "No se ha podido cancelar la eliminación diferida en el dispositivo %s."
+
+#: lib/setup.c:4622 lib/setup.c:4638 lib/luks2/luks2_json_metadata.c:2340
+#: src/cryptsetup.c:2785
+#, c-format
+msgid "Device %s is still in use."
+msgstr "El dispositivo %s todavía se está utilizando."
+
+#: lib/setup.c:4647
+#, c-format
+msgid "Invalid device %s."
+msgstr "Dispositivo inválido %s."
+
+#: lib/setup.c:4763
+msgid "Volume key buffer too small."
+msgstr "El «buffer» de la clave del volumen es demasiado pequeño."
+
+#: lib/setup.c:4771
+msgid "Cannot retrieve volume key for plain device."
+msgstr "No se puede recuperar la clave para el dispositivo no cifrado."
+
+#: lib/setup.c:4788
+msgid "Cannot retrieve root hash for verity device."
+msgstr "No se puede recuperar el «hash» raíz para dispositivo «verity»."
+
+#: lib/setup.c:4792
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Esta operación no está disponible para el dispositivo cifrado %s."
+
+#: lib/setup.c:4998 lib/setup.c:5009
+msgid "Dump operation is not supported for this device type."
+msgstr "Operación de volcado no deisponible para este tipo de dispositivo."
+
+#: lib/setup.c:5337
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "El desplazamiento de datos no es múltiplo de %u bytes."
+
+#: lib/setup.c:5622
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "No se puede convertir el dispositivo %s que todavía está en uso."
+
+#: lib/setup.c:5941
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "No se ha logrado asignar la ranura de claves %u como nueva clave del volumen."
+
+#: lib/setup.c:6014
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "No se han podido inicializar los parámetros predefinidos de la ranura de claves LUKS2."
+
+#: lib/setup.c:6020
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "No se ha logrado asignar la ranura de claves %d al resumen."
+
+#: lib/setup.c:6151
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "El llavero de núcleo no está admitido en el núcleo."
+
+#: lib/setup.c:6161 lib/luks2/luks2_reencrypt.c:3062
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "No se ha podido leer la frase contraseña desde el llavero (error %d)"
+
+#: lib/setup.c:6185
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "No se ha podido adquirir el bloqueo de la serialización de acceso duro de memoria global."
+
+#: lib/utils.c:80
+msgid "Cannot get process priority."
+msgstr "No se puede obtener la prioridad del proceso."
+
+#: lib/utils.c:94
+msgid "Cannot unlock memory."
+msgstr "No se puede desbloquear la memoria."
+
+#: lib/utils.c:168 lib/tcrypt/tcrypt.c:502
+msgid "Failed to open key file."
+msgstr "No se ha podido abrir el fichero de claves."
+
+#: lib/utils.c:173
+msgid "Cannot read keyfile from a terminal."
+msgstr "No se puede leer el fichero de claves desde un terminal."
+
+#: lib/utils.c:189
+msgid "Failed to stat key file."
+msgstr "No se ha podido efectuar «stat» sobre el fichero de claves."
+
+#: lib/utils.c:197 lib/utils.c:218
+msgid "Cannot seek to requested keyfile offset."
+msgstr "No es posible situarse en la posición solicitada del fichero de claves."
+
+#: lib/utils.c:212 lib/utils.c:227 src/utils_password.c:219
+#: src/utils_password.c:231
+msgid "Out of memory while reading passphrase."
+msgstr "Memoria agotada mientras se estaba leyendo la frase contraseña."
+
+#: lib/utils.c:247
+msgid "Error reading passphrase."
+msgstr "Error al leer la frase contraseña."
+
+#: lib/utils.c:264
+msgid "Nothing to read on input."
+msgstr "No hay nada para leer en la entrada."
+
+#: lib/utils.c:271
+msgid "Maximum keyfile size exceeded."
+msgstr "Se ha excedido el tamaño máximo de fichero de claves."
+
+#: lib/utils.c:276
+msgid "Cannot read requested amount of data."
+msgstr "No se puede leer la cantidad de datos solicitada."
+
+#: lib/utils_device.c:208 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "El dispositivo %s no existe o el acceso al mismo ha sido denegado."
+
+#: lib/utils_device.c:218
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "El dispositivo %s no es compatible."
+
+#: lib/utils_device.c:562
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Se ignorará por falso el tamaño de optimal-io para el dispositivo de datos (%u bytes)."
+
+#: lib/utils_device.c:720
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "El dispositivo %s es demasiado pequeño. Se necesitan %<PRIu64> bytes como mínimo."
+
+#: lib/utils_device.c:801
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "No se puede usar el dispositivo %s porque ya está en uso (asignado o montado)."
+
+#: lib/utils_device.c:805
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "No se puede utilizar el dispositivo %s; permiso denegado."
+
+#: lib/utils_device.c:808
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "No se puede obtener información del dispositivo %s."
+
+#: lib/utils_device.c:831
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "No se puede utilizar un dispositivo de bucle invertido como usuario no administrador."
+
+#: lib/utils_device.c:842
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "No se ha logrado asociar el dispositivo de bucle invertido (hace falta un dispositivo de bucle con marcador de auto-limpieza)."
+
+#: lib/utils_device.c:890
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "El «offset» solicitado está más allá del tamaño real del dispositivo %s."
+
+#: lib/utils_device.c:898
+#, c-format
+msgid "Device %s has zero size."
+msgstr "El dispositivo %s tiene tamaño cero."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "El tiempo objetivo máximo de PBKDF no puede ser cero."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Tipo de PBKDF %s desconocido."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "La «hash» solicitada %s no está disponible."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "El tipo de PBKDF solicitado no está disponible para LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "No se pueden establecer la memoria máxima de PBKDF ni los hilos paralelos con pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "El número de iteraciones forzadas es demasiado pequeño para %s (el mínimo es %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "El coste de la memoria forzada es demasiado bajo para %s (el mínimo es %u kilobytes)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "El coste de la memoria máxima solicitada de PBKDF es demasiado alto (el máximo es %d kilobytes)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "La memoria máxima solicitada de PBKDF no puede ser cero."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Los hilos paralelos solicitados de PBKDF no pueden ser cero."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Solo se admite PBKDF2 en el modo FIPS."
+
+#: lib/utils_benchmark.c:172
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Banco de pruebas PBKDF desactivado pero las iteraciones no están establecidas."
+
+#: lib/utils_benchmark.c:191
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Opciones PBKDF2 no compatibles (usando el algoritmo «hash» %s)."
+
+#: lib/utils_benchmark.c:211
+msgid "Not compatible PBKDF options."
+msgstr "Opciones PBKDF no compatibles."
+
+#: lib/utils_device_locking.c:102
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Bloqueo abortado. La ruta del bloqueo %s/%s no puede utilizarse (o no es un directorio o no existe)."
+
+#: lib/utils_device_locking.c:109
+#, c-format
+msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+msgstr "El directorio de bloqueo %s/%s se creará con los permisos predeterminados al compilar."
+
+#: lib/utils_device_locking.c:119
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Bloqueo abortado. La ruta del bloqueo %s/%s no puede utilizarse (%s no es un directorio)."
+
+#: lib/utils_wipe.c:184 src/cryptsetup_reencrypt.c:922
+#: src/cryptsetup_reencrypt.c:1010
+msgid "Cannot seek to device offset."
+msgstr "No es posible situarse en la posición del dispositivo."
+
+#: lib/utils_wipe.c:208
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Error al limpiar el dispositivo, desplazamiento %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"No se ha podido establecer asignación de clave dm-crypt al dispositivo %s.\n"
+"Compruebe que el núcleo admite el algoritmo de cifrado %s (consulte syslog para más información)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "El tamaño de clave en modo XTS debe ser 256 o 512 bits."
+
+# TODO
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "La especificación de cifrado debería estar en formato [cipher]-[mode]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:364
+#: lib/luks1/keymanage.c:674 lib/luks1/keymanage.c:1125
+#: lib/luks2/luks2_json_metadata.c:1276 lib/luks2/luks2_keyslot.c:740
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "No se puede escribir en el dispositivo %s; permiso denegado."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "No se ha podido abrir el dispositivo de almacenamiento de claves temporal."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "No se ha podido acceder al dispositivo de almacenamiento de claves temporal."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:60
+#: lib/luks2/luks2_keyslot_luks2.c:78 lib/luks2/luks2_keyslot_reenc.c:134
+msgid "IO error while encrypting keyslot."
+msgstr "Error de entrada/salida mientras se cifraba una ranura de claves."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:367
+#: lib/luks1/keymanage.c:627 lib/luks1/keymanage.c:677 lib/tcrypt/tcrypt.c:677
+#: lib/verity/verity.c:80 lib/verity/verity.c:193 lib/verity/verity_hash.c:320
+#: lib/verity/verity_hash.c:329 lib/verity/verity_hash.c:349
+#: lib/verity/verity_fec.c:251 lib/verity/verity_fec.c:263
+#: lib/verity/verity_fec.c:268 lib/luks2/luks2_json_metadata.c:1279
+#: src/cryptsetup_reencrypt.c:177 src/cryptsetup_reencrypt.c:189
+#, c-format
+msgid "Cannot open device %s."
+msgstr "No se puede abrir el dispositivo %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:137
+msgid "IO error while decrypting keyslot."
+msgstr "Error de entrada/salida mientras se descifraba una ranura de claves."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "El dispositivo %s es demasiado pequeño. (LUKS1 necesita %<PRIu64> btyes como mínimo.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "La ranura de claves LUKS %u no es válida."
+
+#: lib/luks1/keymanage.c:248 lib/luks1/keymanage.c:524
+#: lib/luks2/luks2_json_metadata.c:1107 src/cryptsetup.c:1557
+#: src/cryptsetup.c:1688 src/cryptsetup.c:1743 src/cryptsetup.c:1798
+#: src/cryptsetup.c:1863 src/cryptsetup.c:1966 src/cryptsetup.c:2030
+#: src/cryptsetup.c:2259 src/cryptsetup.c:2472 src/cryptsetup.c:2532
+#: src/cryptsetup.c:2597 src/cryptsetup.c:2741 src/cryptsetup.c:3423
+#: src/cryptsetup.c:3432 src/cryptsetup_reencrypt.c:1373
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "El dispositivo %s no es un dispositivo LUKS válido."
+
+#: lib/luks1/keymanage.c:266 lib/luks2/luks2_json_metadata.c:1124
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "El fichero de copia de seguridad de cabecera solicitado %s ya existe."
+
+#: lib/luks1/keymanage.c:268 lib/luks2/luks2_json_metadata.c:1126
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "No se puede crear el fichero de copia de seguridad %s."
+
+#: lib/luks1/keymanage.c:275 lib/luks2/luks2_json_metadata.c:1133
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "No se puede escribir en el fichero de copia de seguridad %s."
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1185
+msgid "Backup file does not contain valid LUKS header."
+msgstr "El fichero de copia de seguridad no contiene una cabecera LUKS válida."
+
+#: lib/luks1/keymanage.c:319 lib/luks1/keymanage.c:590
+#: lib/luks2/luks2_json_metadata.c:1206
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "No se puede abrir el fichero de copia de seguridad de cabecerda %s."
+
+#: lib/luks1/keymanage.c:327 lib/luks2/luks2_json_metadata.c:1214
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "No se puede leer el fichero de copia de seguridad de cabecerda %s."
+
+#: lib/luks1/keymanage.c:337
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "La posición de los datos o el tamaño de la clave no coinciden en el dispositivo y en la copia de seguridad."
+
+#: lib/luks1/keymanage.c:345
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Dispositivo %s %s%s"
+
+#: lib/luks1/keymanage.c:346
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "no contiene cabecera LUKS. Reemplazar la cabecera puede destruir los datos en ese dispositivo."
+
+#: lib/luks1/keymanage.c:347
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "ya contiene cabecera LUKS. Reemplazar la cabecera destruirá las ranuras de claves existentes."
+
+#: lib/luks1/keymanage.c:348 lib/luks2/luks2_json_metadata.c:1248
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"ATENCIÓN: ¡la cabecera del dispositivo real tiene un UUID distinto que el de la copia de seguridad!"
+
+#: lib/luks1/keymanage.c:395
+msgid "Non standard key size, manual repair required."
+msgstr "El tamaño de la clave no es estándar; se requiere una reparación manual."
+
+#: lib/luks1/keymanage.c:405
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "El alineamiento de las ranuras de claves no es estándar; se requiere una reparación manual."
+
+#: lib/luks1/keymanage.c:414
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Modo de cifrado reparado (%s -> %s)."
+
+#: lib/luks1/keymanage.c:425
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "«Hash» de cifrado reparado a minúsculas (%s)."
+
+#: lib/luks1/keymanage.c:427 lib/luks1/keymanage.c:533
+#: lib/luks1/keymanage.c:789
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "La «hash» LUKS solicitada %s no está disponible."
+
+#: lib/luks1/keymanage.c:441
+msgid "Repairing keyslots."
+msgstr "Reparando ranuras de claves."
+
+#: lib/luks1/keymanage.c:460
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Ranura de claves %i: posición reparada (%u -> %u)."
+
+#: lib/luks1/keymanage.c:468
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Ranura de claves %i: bandas reparadas (%u -> %u)."
+
+#: lib/luks1/keymanage.c:477
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Ranura de claves %i: la firma de la partición es falsa."
+
+#: lib/luks1/keymanage.c:482
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Ranura de claves %i: «salt wiped»."
+
+#: lib/luks1/keymanage.c:499
+msgid "Writing LUKS header to disk."
+msgstr "Escribiendo cabecera LUKS en el disco."
+
+#: lib/luks1/keymanage.c:504
+msgid "Repair failed."
+msgstr "La reparación ha fallado."
+
+#: lib/luks1/keymanage.c:559
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "El modo de cifrado LUKS %s no es válido."
+
+#: lib/luks1/keymanage.c:564
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "El «hash» LUKS %s no es válido."
+
+#: lib/luks1/keymanage.c:571 src/cryptsetup.c:1243
+msgid "No known problems detected for LUKS header."
+msgstr "No se ha detectado ningún problema en la cabecera LUKS."
+
+#: lib/luks1/keymanage.c:699
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Error al actualizar la cabecera LUKS en el dispositivo %s."
+
+#: lib/luks1/keymanage.c:707
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Error al leer la cabecera LUKS después de actualizarla en el dispositivo %s."
+
+#: lib/luks1/keymanage.c:783
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "La posición de los datos de una cabecera LUKS debe ser 0 o superior al tamaño de la cabecera."
+
+#: lib/luks1/keymanage.c:794 lib/luks1/keymanage.c:863
+#: lib/luks2/luks2_json_format.c:287 lib/luks2/luks2_json_metadata.c:1015
+#: src/cryptsetup.c:2904
+msgid "Wrong LUKS UUID format provided."
+msgstr "El formato de UUID LUKS proporcionado es incorrecto."
+
+#: lib/luks1/keymanage.c:816
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "No se puede crear la cabecera LUKS: fallo en la lectura «random salt»."
+
+#: lib/luks1/keymanage.c:842
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "No se puede crear la cabecera LUKS: fallo en la cabecera (usando «hash» %s)."
+
+#: lib/luks1/keymanage.c:886
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "La ranura de claves %d está activa; primero hay que purgar."
+
+#: lib/luks1/keymanage.c:892
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "El material de la ranura de claves %d no tiene suficientes bandas. Quizá se haya manipulado la cabecera."
+
+#: lib/luks1/keymanage.c:1033
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "No se puede abrir la ranura de claves (usando «hash» %s)."
+
+#: lib/luks1/keymanage.c:1111
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "La ranura %d no es válida; seleccione una ranura de claves entre 0 y %d."
+
+#: lib/luks1/keymanage.c:1129 lib/luks2/luks2_keyslot.c:744
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "No se puede limpiar el dispositivo %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Se ha detectado un fichero de claves cifrado con GPG que el programa aún no no puede procesar."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Utilice 'gpg --decrypt <FICHERO-DE-CLAVES> | cryptsetup --keyfile=- ...'\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Se ha detectado un fichero de claves incompatible con «loop-AES»."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "El núcleo no admite asignación compatible con «loop-AES»."
+
+#: lib/tcrypt/tcrypt.c:509
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Error leyendo el fichero de claves %s."
+
+#: lib/tcrypt/tcrypt.c:559
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Se ha excedido la longitud máxima (%zu) de la frase contraseña TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:602
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "El algoritmo «hash» %s no está disponible, por lo que se ha ignorado."
+
+#: lib/tcrypt/tcrypt.c:618 src/cryptsetup.c:1110
+msgid "Required kernel crypto interface not available."
+msgstr "La interfaz de cifrado del núcleo requerida no está disponible."
+
+#: lib/tcrypt/tcrypt.c:620 src/cryptsetup.c:1112
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Asegúrese de que el módulo del núcleo algof_skcipher está cargado."
+
+#: lib/tcrypt/tcrypt.c:760
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "No es posible la activación para el tamaño de sector %d."
+
+#: lib/tcrypt/tcrypt.c:766
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "El núcleo no dispone de activación para este modo antiguo TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:797
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Activando el sistema de cifrado TCRYPT para la partición %s."
+
+#: lib/tcrypt/tcrypt.c:875
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "El núcleo no admite asignación compatible con TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1088
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Esta función no está disponible sin carga de cabecera TCRYPT."
+
+#: lib/bitlk/bitlk.c:350
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "El tipo de entrada de metadatos '%u' no esperado se ha encontrado mientras se analizaba la clave maestra del volumen soportado."
+
+#: lib/bitlk/bitlk.c:397
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Se ha encontrado una cadena no válida mientras se analizaba la clave maestra del volumen."
+
+#: lib/bitlk/bitlk.c:402
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Se ha encontrado una cadena no esperada ('%s') mientras se analizaba la clave maestra del volumen soportado."
+
+#: lib/bitlk/bitlk.c:419
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "El valor de entrada de metadatos '%u' no esperado se ha encontrado mientras se analizaba la clave maestra del volumen soportado."
+
+#: lib/bitlk/bitlk.c:502
+#, c-format
+msgid "Failed to read BITLK signature from %s."
+msgstr "No se ha podido leer la firma BITLK de %s."
+
+#: lib/bitlk/bitlk.c:514
+msgid "Invalid or unknown signature for BITLK device."
+msgstr "Firma no válida o desconocida para el dispositivo BITLK"
+
+#: lib/bitlk/bitlk.c:520
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK versión 1 no está admitido actualmente."
+
+#: lib/bitlk/bitlk.c:526
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Firma de arranque no válida o desconocida para el dispositivo BITLK"
+
+#: lib/bitlk/bitlk.c:538
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Tamaño de sector no admitido %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:546
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "No se ha podido leer la cabecera BITLK de %s."
+
+#: lib/bitlk/bitlk.c:571
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "No se han podido leer los metadatos BITLK FVE de %s."
+
+#: lib/bitlk/bitlk.c:622
+msgid "Unknown or unsupported encryption type."
+msgstr "Tipo de cifrado desconocido o no admitido."
+
+#: lib/bitlk/bitlk.c:655
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "No se han podido leer las entradas de los metadatos BITLK de %s."
+
+#: lib/bitlk/bitlk.c:897
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Tipo de entrada de metadatos '%u' encontrado inesperadamente mientras se analizaba clave externa."
+
+#: lib/bitlk/bitlk.c:912
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Valor de entrada de metadatos '%u' encontrado inesperadamente mientras se analizaba clave externa."
+
+#: lib/bitlk/bitlk.c:950
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Versión %<PRIu32> de metadatos BEK no admitida."
+
+#: lib/bitlk/bitlk.c:955
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Tamaño %<PRIu32> de metadatos BEK no esperado, no coincide con la longitud del fichero BEK"
+
+#: lib/bitlk/bitlk.c:980
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Entrada de metadatos encontrada inesperadamente mientras se analizaba clave de inicio."
+
+#: lib/bitlk/bitlk.c:1071
+msgid "This operation is not supported."
+msgstr "Esta operación no está disponible."
+
+#: lib/bitlk/bitlk.c:1079
+msgid "Unexpected key data size."
+msgstr "Tamaño de datos de la clave no esperado."
+
+#: lib/bitlk/bitlk.c:1205
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Este dispositivo BITLK se encuentra en un estado en el que no puede activarse."
+
+#: lib/bitlk/bitlk.c:1210
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Los dispositivos BITLK con tipo '%s' no puede activarse."
+
+#: lib/bitlk/bitlk.c:1217
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "La activación de un dispositivo BITLK parcialmente descifrado no puede hacerse."
+
+#: lib/bitlk/bitlk.c:1380
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "No se puede activar el dispositivo; el dm-crypt del núcleo no sirve para BITLK IV."
+
+#: lib/bitlk/bitlk.c:1384
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "No se puede activar el dispositivo; el dm-crypt del núcleo no sirve para difusor BITLK «Elephant»."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:179
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "El dispositivo «verity» %s no utiliza cabecera en disco."
+
+#: lib/verity/verity.c:90
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "El dispositivo %s no es un dispositivo VERITY válido."
+
+#: lib/verity/verity.c:97
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Versión VERITY %d no disponible."
+
+#: lib/verity/verity.c:128
+msgid "VERITY header corrupted."
+msgstr "Cabecera VERITY corrupta."
+
+#: lib/verity/verity.c:173
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "El formato UUID VERITY proporcionado en el dispositivo %s es incorrecto."
+
+#: lib/verity/verity.c:217
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Error al actualizar la cabecera «verity» en el dispositivo %s."
+
+#: lib/verity/verity.c:275
+msgid "Root hash signature verification is not supported."
+msgstr "La verificación de firma «hash» raíz solicitada no está disponible."
+
+#: lib/verity/verity.c:287
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Los errores no pueden repararse con dispositivo FEC."
+
+#: lib/verity/verity.c:289
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Se han encontrado %u errores reparables con dispositivo FEC."
+
+#: lib/verity/verity.c:332
+msgid "Kernel does not support dm-verity mapping."
+msgstr "El núcleo no dispone de asignación «dm-verity»."
+
+#: lib/verity/verity.c:336
+msgid "Kernel does not support dm-verity signature option."
+msgstr "El núcleo no dispone de opción de firma «dm-verity»."
+
+#: lib/verity/verity.c:347
+msgid "Verity device detected corruption after activation."
+msgstr "El dispositivo «verity» ha detectado algo corrupto después de la activación."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "El área de reserva no tiene ceros en la posición %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Desbordamiento de la posición del dispositivo."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "La verificación ha fallado en la posición %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Desbordamiento del área «hash»."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Fallo en la verificación del área de datos."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Fallo en la verificación de la «hash» raíz."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Error de entrada/salida al crear el área «hash»."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "La creación del área «hash» ha fallado."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "ATENCIÓN: el núcleo no puede activar un dispositivo si el tamaño del bloque de datos excede el tamaño de página (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "No se ha podido asignar contexto RS."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "No se ha podido asignar «buffer»."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "No se ha podido leer el bloque RS %<PRIu64> byte %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "No se ha podido leer la paridad para el bloque RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "No se ha podido reparar la paridad para el bloque %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "No se ha podido escribir la paridad para el bloque RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:228
+msgid "Block sizes must match for FEC."
+msgstr "Los tamaños de bloque deben coincidir para FEC."
+
+#: lib/verity/verity_fec.c:234
+msgid "Invalid number of parity bytes."
+msgstr "Número no válido de bytes de paridad."
+
+#: lib/verity/verity_fec.c:239
+msgid "Invalid FEC segment length."
+msgstr "Longitud de segmento FEC no válida."
+
+#: lib/verity/verity_fec.c:303
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "No se ha podido determinar el tamaño para el dispositivo %s."
+
+#: lib/integrity/integrity.c:272 lib/integrity/integrity.c:355
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "El núcleo no dispone de asociación «dm-integrity»."
+
+#: lib/integrity/integrity.c:278
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "El núcleo no dispone de alineamiento de metadatos fijo «dm-integrity»."
+
+#: lib/integrity/integrity.c:287
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "El núcleo rehúsa activar la opción de recálculo inseguro (véanse las opciones de activación antiguas para cambiar ese funcionamiento)."
+
+#: lib/luks2/luks2_disk_metadata.c:393 lib/luks2/luks2_json_metadata.c:973
+#: lib/luks2/luks2_json_metadata.c:1268
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "No se ha podido adquirir el bloqueo de escritura del dispositivo %s."
+
+#: lib/luks2/luks2_disk_metadata.c:402
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Se ha detectado un intento de actualizar los metadatos LUKS2 concurrentemente. Se aborta la operación."
+
+#: lib/luks2/luks2_disk_metadata.c:701 lib/luks2/luks2_disk_metadata.c:722
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"El dispositivo contiene firmas ambiguas; no se puede autorecuperar LUKS2.\n"
+"Por favor, ejecute \"cryptsetup repair\" para recuperación."
+
+#: lib/luks2/luks2_json_format.c:230
+msgid "Requested data offset is too small."
+msgstr "El desplazamiento de datos solicitado es demasiado pequeño."
+
+#: lib/luks2/luks2_json_format.c:275
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "ATENCIÓN: la zona de ranuras de claves (%<PRIu64> bytes) es muy pequeña; el número de ranuras de claves LUKS2 disponibles es muy limitado.\n"
+
+#: lib/luks2/luks2_json_metadata.c:960 lib/luks2/luks2_json_metadata.c:1098
+#: lib/luks2/luks2_json_metadata.c:1174 lib/luks2/luks2_keyslot_luks2.c:92
+#: lib/luks2/luks2_keyslot_luks2.c:114
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "No se ha podido adquirir el bloqueo de lectura para el dispositivo %s."
+
+#: lib/luks2/luks2_json_metadata.c:1191
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Se han detectado requisitos prohibidos para LUKS2 en la copia de seguridad %s."
+
+#: lib/luks2/luks2_json_metadata.c:1232
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "La posición de los datos no coinciden en el dispositivo y en la copia de seguridad; ha fallado la restauración."
+
+#: lib/luks2/luks2_json_metadata.c:1238
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "La cabecera binaria con el tamaño de las áreas de ranuras de claves no coinciden en el dispositivo y en la copia de seguridad; la restauración ha fallado."
+
+#: lib/luks2/luks2_json_metadata.c:1245
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Dispositivo %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1246
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "no contiene cabecera LUKS2. Reemplazar la cabecera puede destruir los datos en ese dispositivo."
+
+#: lib/luks2/luks2_json_metadata.c:1247
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "ya contiene cabecera LUKS2. Reemplazar la cabecera destruirá las ranuras de claves existentes."
+
+#: lib/luks2/luks2_json_metadata.c:1249
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"ATENCIÓN: ¡Se han detectado requisitos LUKS2 desconocidos en cabecera de\n"
+"dispositivo real! Reemplazar la cabecera con la copia de seguridad puede\n"
+"corromper los datos en ese dispositivo!"
+
+#: lib/luks2/luks2_json_metadata.c:1251
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"ATENCIÓN: ¡Se ha detectado recifrado «offline» no terminado en el dispositivo!\n"
+"¡Reemplazar la cabecera con la copia de seguridad puede corromper los datos!"
+
+#: lib/luks2/luks2_json_metadata.c:1349
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Se hará caso omiso del indicador desconocido %s."
+
+#: lib/luks2/luks2_json_metadata.c:2054 lib/luks2/luks2_reencrypt.c:1843
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Falta la clave para el segmento dm-crypt %u"
+
+#: lib/luks2/luks2_json_metadata.c:2066 lib/luks2/luks2_reencrypt.c:1857
+msgid "Failed to set dm-crypt segment."
+msgstr "No se ha podido establecer el segmento de dm-crypt."
+
+#: lib/luks2/luks2_json_metadata.c:2072 lib/luks2/luks2_reencrypt.c:1863
+msgid "Failed to set dm-linear segment."
+msgstr "No se ha podido establecer el segmento de dm-linear."
+
+#: lib/luks2/luks2_json_metadata.c:2199
+msgid "Unsupported device integrity configuration."
+msgstr "Configuración de integridad de dispositivo no admitida."
+
+#: lib/luks2/luks2_json_metadata.c:2285
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Recifrado en curso. No se puede desactivar el dispositivo."
+
+#: lib/luks2/luks2_json_metadata.c:2296 lib/luks2/luks2_reencrypt.c:3300
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "No se ha podido reemplazar el dispositivo suspendido %s con el objetivo dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2376
+msgid "Failed to read LUKS2 requirements."
+msgstr "No se ha podido leer los requisitos LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2383
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Se han detectado requisitos LUKS2 no satisfechos."
+
+#: lib/luks2/luks2_json_metadata.c:2391
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Operación incompatible con dispositivo marcado para recifrado obsoleto. Se aborta."
+
+#: lib/luks2/luks2_json_metadata.c:2393
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Operación incompatible con dispositivo marcado para recifrado LUKS2. Se aborta."
+
+#: lib/luks2/luks2_keyslot.c:554 lib/luks2/luks2_keyslot.c:591
+msgid "Not enough available memory to open a keyslot."
+msgstr "No hay memoria disponible suficiente para abrir una ranura de claves."
+
+#: lib/luks2/luks2_keyslot.c:556 lib/luks2/luks2_keyslot.c:593
+msgid "Keyslot open failed."
+msgstr "Fallo al abrir la ranura de claves."
+
+#: lib/luks2/luks2_keyslot_luks2.c:53 lib/luks2/luks2_keyslot_luks2.c:108
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "No se puede utilizar el algoritmo de cifrado %s-%s para el cifrado de ranuras de clave."
+
+#: lib/luks2/luks2_keyslot_luks2.c:485
+msgid "No space for new keyslot."
+msgstr "No hay espacio para la nueva ranura de claves."
+
+#: lib/luks2/luks2_luks1_convert.c:482
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "No se puede comprobar el estado del dispositivo con uuid: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:508
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Imposible convertir cabecera con metadatos adicionales LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:548
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Imposible mover el área de la ranura de claves. No hay suficiente espacio."
+
+#: lib/luks2/luks2_luks1_convert.c:599
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Imposible mover el área de la ranura de claves. Área de ranuras de clave LUKS2 demasiado pequeña."
+
+#: lib/luks2/luks2_luks1_convert.c:605 lib/luks2/luks2_luks1_convert.c:889
+msgid "Unable to move keyslot area."
+msgstr "Imposible mover el área de la ranura de claves."
+
+#: lib/luks2/luks2_luks1_convert.c:697
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "No se puede convertir a formato LUKS1 - el tamaño predefinido de sector de cifrado del segmento no es 512 bytes."
+
+#: lib/luks2/luks2_luks1_convert.c:705
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "No se puede convertir a formato LUKS1 - los resúmenes de rarunas de claves no son compatibles con LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:717
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "No se puede convertir a formato LUKS1 - el dispositivo utiliza el cifrado de clave encapsulado %s."
+
+#: lib/luks2/luks2_luks1_convert.c:725
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "No se puede convertir a formato LUKS1 - la cabecera LUKS2 contiene %u «token(s)»."
+
+#: lib/luks2/luks2_luks1_convert.c:739
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "No se puede convertir a formato LUKS1 - la ranura de claves %u está en un estado no válido."
+
+#: lib/luks2/luks2_luks1_convert.c:744
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "No se puede convertir a formato LUKS1 - la ranura %u (sobre las ranuras máximas) todavía está activa."
+
+#: lib/luks2/luks2_luks1_convert.c:749
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "No se puede convertir a formato LUKS1 - la ranura de claves %u no es compatible con LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:993
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "El tamaño de la zona activa debe ser múltiplo del alineamiento de zona calculado (%zu bytes)."
+
+#: lib/luks2/luks2_reencrypt.c:998
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "El tamaño del dispositivo debe ser múltiplo del alineamiento de zona calculado (%zu bytes)."
+
+#: lib/luks2/luks2_reencrypt.c:1042
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Modo de resiliencia %s no admitido."
+
+#: lib/luks2/luks2_reencrypt.c:1259 lib/luks2/luks2_reencrypt.c:1414
+#: lib/luks2/luks2_reencrypt.c:1497 lib/luks2/luks2_reencrypt.c:1531
+#: lib/luks2/luks2_reencrypt.c:3140
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "No se ha podido inicializar la envoltura antigua de almacenamiento del segmento."
+
+#: lib/luks2/luks2_reencrypt.c:1273 lib/luks2/luks2_reencrypt.c:1392
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "No se ha podido inicializar la envoltura nueva de almacenamiento del segmento."
+
+#: lib/luks2/luks2_reencrypt.c:1441
+msgid "Failed to read checksums for current hotzone."
+msgstr "No se han podido leer las sumas de comprobación para la zona activa actual."
+
+#: lib/luks2/luks2_reencrypt.c:1448 lib/luks2/luks2_reencrypt.c:3148
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "No se ha podido leer la zona activa que comienza en %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1467
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "No se ha podido descifrar el sector %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1473
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "No se ha podido recuperar el sector %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1956
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Los tamaños de los dispositivos origen y destino no coinciden. Origen %<PRIu64>, destino: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2054
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "No se ha podido activar el dispositivo con zona activa %s."
+
+#: lib/luks2/luks2_reencrypt.c:2071
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "No se ha podido activar el dispositivo de superposición %s con la tabla de orígenes actual."
+
+#: lib/luks2/luks2_reencrypt.c:2078
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "No se ha podido cargar el nuevo mapa para el dispositivo %s."
+
+#: lib/luks2/luks2_reencrypt.c:2149
+msgid "Failed to refresh reencryption devices stack."
+msgstr "No se ha podido refrescar la pila del dispositivo de recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:2309
+msgid "Failed to set new keyslots area size."
+msgstr "No se ha logrado establecer el tamaño de las nuevas ranuras de claves."
+
+#: lib/luks2/luks2_reencrypt.c:2413
+#, c-format
+msgid "Data shift is not aligned to requested encryption sector size (%<PRIu32> bytes)."
+msgstr "El desplazamiento de datos no está alineado con el tamaño del sector de cifrado solicitado (%<PRIu32> bytes)."
+
+#: lib/luks2/luks2_reencrypt.c:2434
+#, c-format
+msgid "Data device is not aligned to requested encryption sector size (%<PRIu32> bytes)."
+msgstr "El dispositivo de datos no está alineado con el tamaño del sector de cifrado solicitado (%<PRIu32> bytes)."
+
+#: lib/luks2/luks2_reencrypt.c:2455
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "El desplazamiento de datos (%<PRIu64> sectores) es menor que el desplazamiento de datos futuros (%<PRIu64> sectores)."
+
+#: lib/luks2/luks2_reencrypt.c:2461 lib/luks2/luks2_reencrypt.c:2889
+#: lib/luks2/luks2_reencrypt.c:2910
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "No se ha podido abrir %s en modo exclusivo (ya está asignado o montado)."
+
+#: lib/luks2/luks2_reencrypt.c:2629
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "El dispositivo no está marcado para recifrado LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:2635 lib/luks2/luks2_reencrypt.c:3415
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "No se ha podido cargar el contexto del recifrado LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:2715
+msgid "Failed to get reencryption state."
+msgstr "No se ha podido obtener el estado del recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:2719
+msgid "Device is not in reencryption."
+msgstr "El dispositivo no está en recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:2726
+msgid "Reencryption process is already running."
+msgstr "El proceso de recifrado ya está en marcha."
+
+#: lib/luks2/luks2_reencrypt.c:2728
+msgid "Failed to acquire reencryption lock."
+msgstr "No se ha podido adquirir el bloqueo de recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:2746
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "No se puede proceder con el recifrado. Ejecute primero la recuperación de recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:2860
+msgid "Active device size and requested reencryption size don't match."
+msgstr "El tamaño del dispositivo activo y el tamaño de recifrado solicitado no coinciden."
+
+#: lib/luks2/luks2_reencrypt.c:2874
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "El tamaño de dispositivo solicitado en los parámetros de recifrado no es válido."
+
+#: lib/luks2/luks2_reencrypt.c:2944
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Recifrado en proceso. No se puede llevar a cabo una recuperación."
+
+#: lib/luks2/luks2_reencrypt.c:3016
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "Recifrado LUKS2 ya inicializado en los metadatos."
+
+#: lib/luks2/luks2_reencrypt.c:3023
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "No se ha podido inicializar el recifrado LUKS2 en los metadatos."
+
+#: lib/luks2/luks2_reencrypt.c:3114
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "No se han podido establecer los segmentos del dispositivo para la siguiente zona activa de recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:3156
+msgid "Failed to write reencryption resilience metadata."
+msgstr "No se han podido escribir los metadatos de resiliencia de recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:3163
+msgid "Decryption failed."
+msgstr "El descifrado ha fallado."
+
+#: lib/luks2/luks2_reencrypt.c:3168
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "No se ha podido escribir la zona activa que comienza en %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3173
+msgid "Failed to sync data."
+msgstr "No se han podido sincronizar los datos."
+
+#: lib/luks2/luks2_reencrypt.c:3181
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "No se han podido actualizar los metadatos tras completar la zona activa de recifrado actual."
+
+#: lib/luks2/luks2_reencrypt.c:3248
+msgid "Failed to write LUKS2 metadata."
+msgstr "No se han podido escribir los metadatos de LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3271
+msgid "Failed to wipe backup segment data."
+msgstr "No se han podido limpiar los datos de segmentos de respaldo."
+
+#: lib/luks2/luks2_reencrypt.c:3284
+msgid "Failed to disable reencryption requirement flag."
+msgstr "No se ha podido desactivar el indicador del requisito de descifrado."
+
+#: lib/luks2/luks2_reencrypt.c:3292
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Error fatal mientras se recifraba una porción que comienza en %<PRIu64>, de %<PRIu64> sectores de longitud."
+
+#: lib/luks2/luks2_reencrypt.c:3296
+msgid "Online reencryption failed."
+msgstr "El recifrado «online» ha fallado."
+
+# No sé cómo traducir 'error target'.
+#: lib/luks2/luks2_reencrypt.c:3301
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "No reanudar el dispositivo a menos que se reemplace con «error target» manualmente."
+
+#: lib/luks2/luks2_reencrypt.c:3353
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "No se puede proceder con el recifrado. Estado de recifrado inesperado."
+
+#: lib/luks2/luks2_reencrypt.c:3359
+msgid "Missing or invalid reencrypt context."
+msgstr "Contexto de recifrado ausente o no válido."
+
+#: lib/luks2/luks2_reencrypt.c:3366
+msgid "Failed to initialize reencryption device stack."
+msgstr "No se ha podido inicializar la pila del dispositivo de recifrado."
+
+#: lib/luks2/luks2_reencrypt.c:3385 lib/luks2/luks2_reencrypt.c:3428
+msgid "Failed to update reencryption context."
+msgstr "No se ha podido actualizar el contexto de recifrado."
+
+#: src/cryptsetup.c:108
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "No se puede hacer verificación de frase contraseña en entradas no tty."
+
+#: src/cryptsetup.c:171
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Los parámetros de cifrado de ranura de claves solo pueden configurarse para dispositivos LUKS2."
+
+#: src/cryptsetup.c:198
+#, c-format
+msgid "Enter token PIN:"
+msgstr "Introduzca el PIN del «token»:"
+
+#: src/cryptsetup.c:200
+#, c-format
+msgid "Enter token %d PIN:"
+msgstr "Introduzca el PIN del «token» %d:"
+
+#: src/cryptsetup.c:245 src/cryptsetup.c:1057 src/cryptsetup.c:1401
+#: src/cryptsetup.c:3288 src/cryptsetup_reencrypt.c:700
+#: src/cryptsetup_reencrypt.c:770
+msgid "No known cipher specification pattern detected."
+msgstr "No se ha detectado ningún patrón conocido de especificación de cifrado."
+
+#: src/cryptsetup.c:253
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "ATENCIÓN: No se va a hacer caso del parámetro --hash en modo no cifrado con el fichero de claves especificado.\n"
+
+#: src/cryptsetup.c:261
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "ATENCIÓN: No se va a hacer caso de la opción --keyfile-size; el tamaño de lectura es igual al tamaño de la clave de cifrado.\n"
+
+#: src/cryptsetup.c:301
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Se ha(n) detectado firma(s) de dispositivo en %s. Si se prosigue, pueden dañarse los datos existentes."
+
+#: src/cryptsetup.c:307 src/cryptsetup.c:1197 src/cryptsetup.c:1253
+#: src/cryptsetup.c:1378 src/cryptsetup.c:1451 src/cryptsetup.c:2099
+#: src/cryptsetup.c:2805 src/cryptsetup.c:2927 src/integritysetup.c:176
+msgid "Operation aborted.\n"
+msgstr "Operación abortada.\n"
+
+#: src/cryptsetup.c:375
+msgid "Option --key-file is required."
+msgstr "Es necesaria la opción --key-file."
+
+#: src/cryptsetup.c:426
+msgid "Enter VeraCrypt PIM: "
+msgstr "Introduzca PIM de VeraCrypt: "
+
+#: src/cryptsetup.c:435
+msgid "Invalid PIM value: parse error."
+msgstr "Valor de PIM no válido: error de análisis."
+
+#: src/cryptsetup.c:438
+msgid "Invalid PIM value: 0."
+msgstr "Valor de PIM no válido: 0."
+
+#: src/cryptsetup.c:441
+msgid "Invalid PIM value: outside of range."
+msgstr "Valor de PIM no válido: fuera de rango."
+
+#: src/cryptsetup.c:464
+msgid "No device header detected with this passphrase."
+msgstr "No se ha detectado ninguna cabecera de dispositivo con esa frase contraseña."
+
+#: src/cryptsetup.c:537
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "El dispositivo %s no es un dispositivo BITLK válido."
+
+#: src/cryptsetup.c:545
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "No se puede determinar el tamaño de la clave del volumen para BITLK; utilice la opción --key-size."
+
+#: src/cryptsetup.c:588
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"El volcado de la cabecera con la clave del volumen es información\n"
+"sensible que permite el acceso a una partición cifrada sin frase contraseña.\n"
+"Este volcado debería almacenarse siempre cifrado en un lugar seguro."
+
+#: src/cryptsetup.c:661 src/cryptsetup.c:2125
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"El volcado de la cabecera con la clave del volumen es información\n"
+"sensible que permite el acceso a una partición cifrada sin frase contraseña.\n"
+"Este volcado debería almacenarse cifrado en un lugar seguro."
+
+#: src/cryptsetup.c:756 src/veritysetup.c:318 src/integritysetup.c:313
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "El dispositivo %s todavía está activo y programado para borrado diferido.\n"
+
+#: src/cryptsetup.c:790
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "El cambio de tamaño del dispositivo activo requiere clave de volumen en el llavero pero la opción --disable-keyring está puesta."
+
+#: src/cryptsetup.c:936
+msgid "Benchmark interrupted."
+msgstr "Comparativa interrumpida."
+
+#: src/cryptsetup.c:957
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/A\n"
+
+#: src/cryptsetup.c:959
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iteraciones por segundo para clave de %zu bits\n"
+
+#: src/cryptsetup.c:973
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/A\n"
+
+#: src/cryptsetup.c:975
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iteraciones, %5u memora, %1u hilos paralelos (CPUs) para clave de %zu bits (tiempo solicitado %u ms)\n"
+
+#: src/cryptsetup.c:999
+msgid "Result of benchmark is not reliable."
+msgstr "El resultado de la comparativa no es fiable."
+
+#: src/cryptsetup.c:1049
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Las pruebas son solo aproximadas usando memoria (no hay entrada/salida de almacenadmiento).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1069
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algoritmo | Clave | Cifrado | Descifrado\n"
+
+#: src/cryptsetup.c:1073
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "El algoritmo de cifrado %s (con clave de %i bits) no está disponible."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1092
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritmo | Clave | Cifrado | Descifrado\n"
+
+#: src/cryptsetup.c:1103
+msgid "N/A"
+msgstr "/N/A"
+
+#: src/cryptsetup.c:1190
+msgid ""
+"Seems device does not require reencryption recovery.\n"
+"Do you want to proceed anyway?"
+msgstr ""
+"Parece que el dispositivo no necesita recuperación del recifrado.\n"
+"¿Desea continuar de todos modos?"
+
+#: src/cryptsetup.c:1196
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "¿Está seguro de proceder con la recuperación del recifrado LUKS2?"
+
+#: src/cryptsetup.c:1204
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Introduzca la frase contraseña para la recuperación del recifrado: "
+
+#: src/cryptsetup.c:1252
+msgid "Really try to repair LUKS device header?"
+msgstr "¿Está seguro de que quiere intentar reparar la cabecera del dispositivo LUKS?"
+
+#: src/cryptsetup.c:1277 src/integritysetup.c:90
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Limpieza de dispositivo para inicializar la suma de comprobación de integridad.\n"
+"Puede interrumpirse pulsando CTRL+c (el resto de dispositivo no limpiado contendrá sumas de comprobación no válidas.\n"
+
+#: src/cryptsetup.c:1299 src/integritysetup.c:112
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "No se puede desactivar el dispositivo temporal %s."
+
+#: src/cryptsetup.c:1363
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "La opción de integridad solo puede utilizarse para formato LUKS2."
+
+#: src/cryptsetup.c:1368 src/cryptsetup.c:1428
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Opciones de tamaño de metadatos LUKS2 no admitidas."
+
+#: src/cryptsetup.c:1377
+msgid "Header file does not exist, do you want to create it?"
+msgstr "No existe el fichero de cabecera; ¿desea crearlo?"
+
+#: src/cryptsetup.c:1385
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "No se puede crear el fichero de cabecera %s."
+
+#: src/cryptsetup.c:1408 src/integritysetup.c:138 src/integritysetup.c:146
+#: src/integritysetup.c:155 src/integritysetup.c:230 src/integritysetup.c:238
+#: src/integritysetup.c:248
+msgid "No known integrity specification pattern detected."
+msgstr "No se ha detectado ningún patrón conocido de especificación de integridad."
+
+#: src/cryptsetup.c:1421
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "No se puede utilizar %s como cabecera en disco."
+
+#: src/cryptsetup.c:1445 src/integritysetup.c:170
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Esto sobreescribirá los datos en %s de forma irrevocable."
+
+#: src/cryptsetup.c:1478 src/cryptsetup.c:1814 src/cryptsetup.c:1879
+#: src/cryptsetup.c:1981 src/cryptsetup.c:2047 src/cryptsetup_reencrypt.c:530
+msgid "Failed to set pbkdf parameters."
+msgstr "No se han podido establecer los parámetros pbkdf."
+
+#: src/cryptsetup.c:1563
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "La posición de datos reducida está permitida solamente para cabecera LUKS separada."
+
+#: src/cryptsetup.c:1574 src/cryptsetup.c:1885
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "No se puede determinar el tamaño de la clave del volumen para LUKS2 sin ranuras de claves; utilice la opción --key-size."
+
+#: src/cryptsetup.c:1619
+msgid "Device activated but cannot make flags persistent."
+msgstr "Dispositivo activado pero los indicadores no pueden hacerse persistentes."
+
+#: src/cryptsetup.c:1698 src/cryptsetup.c:1766
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "La ranura de claves %d se va a borrar."
+
+#: src/cryptsetup.c:1710 src/cryptsetup.c:1770
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Esta es la última ranura de claves. El dispositivo quedará inutilizado después de purgar esta clave."
+
+#: src/cryptsetup.c:1711
+msgid "Enter any remaining passphrase: "
+msgstr "Introduzca cualquier frase contraseña que quede: "
+
+#: src/cryptsetup.c:1712 src/cryptsetup.c:1772
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operación abortada; la ranura de claves NO estaba limpia.\n"
+
+#: src/cryptsetup.c:1748
+msgid "Enter passphrase to be deleted: "
+msgstr "Introduzca la frase contraseña que hay que borrar: "
+
+#: src/cryptsetup.c:1828 src/cryptsetup.c:1900 src/cryptsetup.c:1934
+msgid "Enter new passphrase for key slot: "
+msgstr "Introduzca una nueva frase contraseña para la ranura de claves: "
+
+#: src/cryptsetup.c:1917 src/cryptsetup_reencrypt.c:1328
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Introduzca cualquier frase contraseña que exista: "
+
+#: src/cryptsetup.c:1985
+msgid "Enter passphrase to be changed: "
+msgstr "Introduzca la frase contraseña que hay que cambiar: "
+
+#: src/cryptsetup.c:2001 src/cryptsetup_reencrypt.c:1314
+msgid "Enter new passphrase: "
+msgstr "Introduzca una nueva frase contraseña: "
+
+#: src/cryptsetup.c:2051
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Introduzca la frase contraseña para la ranura de claves que se va a convertir: "
+
+#: src/cryptsetup.c:2075
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "La operación isLuks solo admite un argumento de dispositivo."
+
+#: src/cryptsetup.c:2190
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "La ranura de claves %d no contiene clave independiente."
+
+#: src/cryptsetup.c:2195
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"El volcado de la cabecera con clave independiente del volumen es información\n"
+"sensible. Este volcado debería almacenarse cifrado en un lugar seguro."
+
+#: src/cryptsetup.c:2286 src/cryptsetup.c:2314
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s no es un nombre de dispositivo %s activo."
+
+#: src/cryptsetup.c:2309
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s no es un nombre de dispositivo LUKS activo o falta la cabecera."
+
+#: src/cryptsetup.c:2347 src/cryptsetup.c:2366
+msgid "Option --header-backup-file is required."
+msgstr "Es necesaria la opción --header-backup-file."
+
+#: src/cryptsetup.c:2397
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s no es un dispositivo gestionable por cryptsetup."
+
+#: src/cryptsetup.c:2408
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "El refresco no está disponible para el tipo de dispositivo %s"
+
+#: src/cryptsetup.c:2454
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Tipo de dispositivo de metadatos %s no reconocido."
+
+#: src/cryptsetup.c:2456
+msgid "Command requires device and mapped name as arguments."
+msgstr "Esta orden necesita como argumentos el dispositivo y el nombre asociado."
+
+#: src/cryptsetup.c:2477
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Esta operación borrará todas las ranuras de claves en el dispositivo %s.\n"
+"El dispositivo quedará inutilizable después de esta operación."
+
+#: src/cryptsetup.c:2484
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operación abortada; las ranuras de claves NO estaban limpias.\n"
+
+#: src/cryptsetup.c:2523
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Tipo LUKS no válido; solo se admiten luks1 y luks2."
+
+#: src/cryptsetup.c:2539
+#, c-format
+msgid "Device is already %s type."
+msgstr "El dispositivo ya es de tipo %s."
+
+#: src/cryptsetup.c:2546
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Esta operación convertirá el formato %s a %s.\n"
+
+#: src/cryptsetup.c:2549
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operación abortada; el dispositivo NO estaba convertido.\n"
+
+#: src/cryptsetup.c:2589
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Falta la opción --priority, --label o --subsystem."
+
+#: src/cryptsetup.c:2623 src/cryptsetup.c:2660 src/cryptsetup.c:2680
+#, c-format
+msgid "Token %d is invalid."
+msgstr "El «token» %d no es válido."
+
+#: src/cryptsetup.c:2626 src/cryptsetup.c:2683
+#, c-format
+msgid "Token %d in use."
+msgstr "El «token» %d está en uso."
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "No se ha podido añadir el «token» %d al llavero luks."
+
+#: src/cryptsetup.c:2646 src/cryptsetup.c:2709
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "No se ha logrado asignar el «token» %d a la ranura de claves %d."
+
+#: src/cryptsetup.c:2663
+#, c-format
+msgid "Token %d is not in use."
+msgstr "El «token» %d no está en uso."
+
+#: src/cryptsetup.c:2700
+msgid "Failed to import token from file."
+msgstr "No se ha podido importar el «token» del fichero."
+
+#: src/cryptsetup.c:2725
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "No se ha logrado obtener el «token» %d para exportar."
+
+#: src/cryptsetup.c:2789
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Se ha detectado automáticamente el dispositivo dm activo '%s' para el dispositivo de datos %s.\n"
+
+#: src/cryptsetup.c:2793
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "El dispositivo %s no es un dispositivo de bloques.\n"
+
+#: src/cryptsetup.c:2795
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "No se han podido detectar automáticamente los propietarios del dispositivo %s."
+
+#: src/cryptsetup.c:2799
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Imposible decidir si el dispositivo %s está activado o no.\n"
+"¿Está seguro de que desea proceder con el recifrado en modo «offline»?\n"
+"Puede provocarse corrupción de datos si el dispositivo está realmente\n"
+"activado. Para realizar recifrado en modo «online», utilice en su lugar\n"
+"el parámetro --active-name.\n"
+
+#: src/cryptsetup.c:2881
+msgid "Encryption is supported only for LUKS2 format."
+msgstr "El cifrado solo puede hacerse con formato LUKS2."
+
+#: src/cryptsetup.c:2886
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "El cifrado sin cabecera separada (--header) no es posible sin reducción del tamaño del dispositivo de datos (--reduce-device-size)."
+
+#: src/cryptsetup.c:2891
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "El desplazamiento de datos solicitado debe ser menor o igual que la mitad del parámetro --reduce-device-size."
+
+#: src/cryptsetup.c:2900
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Ajustando el valor de --reduce-device-size al doble de --offset %<PRIu64> (sectores).\n"
+
+#: src/cryptsetup.c:2923
+#, c-format
+msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+msgstr "Se ha detectado un dispositivo LUKS en %s. ¿Desea cifrar de nuevo ese dispositivo LUKS?"
+
+#: src/cryptsetup.c:2941
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "El fichero de cabecera temporal %s ya existe. Se aborta."
+
+#: src/cryptsetup.c:2943 src/cryptsetup.c:2950
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "No se puede crear el fichero de cabecera temporal %s."
+
+#: src/cryptsetup.c:2975
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "El tamaño de los metadatos LUKS2 es mayor que el valor del desplazamiento de los datos."
+
+#: src/cryptsetup.c:3007
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "No se ha podido colocar la nueva cabecera en la cabeza del dispositivo %s."
+
+#: src/cryptsetup.c:3018
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s ahora está activo y preparado para cifrado «online».\n"
+
+#: src/cryptsetup.c:3055
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "El descifrado LUKS2 solo admite dispositivo con cabecera separada (con desplazamiento de datos puesto a 0)."
+
+#: src/cryptsetup.c:3189 src/cryptsetup.c:3195
+msgid "Not enough free keyslots for reencryption."
+msgstr "No hay suficientes ranuras de claves para el recifrado."
+
+#: src/cryptsetup.c:3215 src/cryptsetup_reencrypt.c:1279
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "El fichero de claves solo puede usarse con --key-slot o con una sola ranura de claves activa exactamente."
+
+#: src/cryptsetup.c:3224 src/cryptsetup_reencrypt.c:1326
+#: src/cryptsetup_reencrypt.c:1337
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Introduzca la frase contraseña para la ranura de claves %d: "
+
+#: src/cryptsetup.c:3233
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Introduzca la frase contraseña para la ranura de claves %u: "
+
+#: src/cryptsetup.c:3278
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Cambiando el algoritmo de cifrado de datos a %s.\n"
+
+#: src/cryptsetup.c:3415
+msgid "Command requires device as argument."
+msgstr "Esta orden necesita un dispositivo como argumento."
+
+#: src/cryptsetup.c:3437
+msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+msgstr "Actualmente solo se admite el formato LUKS2. Utilice la herramienta cryptsetup-reencrypt para LUKS1."
+
+#: src/cryptsetup.c:3449
+msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+msgstr "Ya hay un recifrado «offline» heredado en proceso. Utilice la utilidad cryptsetup-reencrypt."
+
+#: src/cryptsetup.c:3459 src/cryptsetup_reencrypt.c:155
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "El recifrado de dispositivo con perfil de integridad no está admitido."
+
+#: src/cryptsetup.c:3467
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "El recifrado LUKS2 ya está inicializado. Se aborta la operación."
+
+#: src/cryptsetup.c:3471
+msgid "LUKS2 device is not in reencryption."
+msgstr "El dispositivo LUKS2 no está en recifrado."
+
+#: src/cryptsetup.c:3498
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<dispositivo> [--type <tipo> [<nombre>]"
+
+#: src/cryptsetup.c:3498 src/veritysetup.c:480 src/integritysetup.c:446
+msgid "open device as <name>"
+msgstr "abrir el dispositivo como <nombre>"
+
+#: src/cryptsetup.c:3499 src/cryptsetup.c:3500 src/cryptsetup.c:3501
+#: src/veritysetup.c:481 src/veritysetup.c:482 src/integritysetup.c:447
+#: src/integritysetup.c:448
+msgid "<name>"
+msgstr "<nombre>"
+
+#: src/cryptsetup.c:3499 src/veritysetup.c:481 src/integritysetup.c:447
+msgid "close device (remove mapping)"
+msgstr "cerrar dispositivo (eliminar asociación)"
+
+#: src/cryptsetup.c:3500
+msgid "resize active device"
+msgstr "cambiar el tamaño del dispositivo activo"
+
+#: src/cryptsetup.c:3501
+msgid "show device status"
+msgstr "mostrar el estado del dispositivo"
+
+#: src/cryptsetup.c:3502
+msgid "[--cipher <cipher>]"
+msgstr "[--cypher <algoritmo_de_cifrador>]"
+
+#: src/cryptsetup.c:3502
+msgid "benchmark cipher"
+msgstr "algoritmo de cifrado para pruebas"
+
+#: src/cryptsetup.c:3503 src/cryptsetup.c:3504 src/cryptsetup.c:3505
+#: src/cryptsetup.c:3506 src/cryptsetup.c:3507 src/cryptsetup.c:3514
+#: src/cryptsetup.c:3515 src/cryptsetup.c:3516 src/cryptsetup.c:3517
+#: src/cryptsetup.c:3518 src/cryptsetup.c:3519 src/cryptsetup.c:3520
+#: src/cryptsetup.c:3521 src/cryptsetup.c:3522
+msgid "<device>"
+msgstr "<dispositivo>"
+
+#: src/cryptsetup.c:3503
+msgid "try to repair on-disk metadata"
+msgstr "intentar reparar metadatos en disco"
+
+#: src/cryptsetup.c:3504
+msgid "reencrypt LUKS2 device"
+msgstr "recifrar dispositivo LUKS2"
+
+#: src/cryptsetup.c:3505
+msgid "erase all keyslots (remove encryption key)"
+msgstr "borrar todas las ranuras de claves (eliminar clave de cifrado)"
+
+#: src/cryptsetup.c:3506
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "convertir formato LUKS de/en LUKS2"
+
+#: src/cryptsetup.c:3507
+msgid "set permanent configuration options for LUKS2"
+msgstr "establecer opciones de configuración permanentes para LUKS2"
+
+#: src/cryptsetup.c:3508 src/cryptsetup.c:3509
+msgid "<device> [<new key file>]"
+msgstr "<dispositivo> [<nuevo fichero de claves>]"
+
+#: src/cryptsetup.c:3508
+msgid "formats a LUKS device"
+msgstr "da formato a un dispositivo LUKS"
+
+#: src/cryptsetup.c:3509
+msgid "add key to LUKS device"
+msgstr "añadir clave a un dispositivo LUKS"
+
+#: src/cryptsetup.c:3510 src/cryptsetup.c:3511 src/cryptsetup.c:3512
+msgid "<device> [<key file>]"
+msgstr "<dispositivo> [<fichero de claves>]"
+
+#: src/cryptsetup.c:3510
+msgid "removes supplied key or key file from LUKS device"
+msgstr "elimina la clave suministrada o el fichero de claves del dispositivo LUKS"
+
+#: src/cryptsetup.c:3511
+msgid "changes supplied key or key file of LUKS device"
+msgstr "cambia la clave suministrada o el fichero de claves del dispositivo LUKS"
+
+#: src/cryptsetup.c:3512
+msgid "converts a key to new pbkdf parameters"
+msgstr "convierte una clave a los nuevos parámetros pbkdf"
+
+#: src/cryptsetup.c:3513
+msgid "<device> <key slot>"
+msgstr "<dispositivo> <ranura de claves>"
+
+#: src/cryptsetup.c:3513
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "borra la clave con el número <ranura de clave> del dispositivo LUKS"
+
+#: src/cryptsetup.c:3514
+msgid "print UUID of LUKS device"
+msgstr "imprimir el UUID del dispositivo LUKS"
+
+#: src/cryptsetup.c:3515
+msgid "tests <device> for LUKS partition header"
+msgstr "comprueba si <dispositivo> tiene cabecera de partición LUKS"
+
+#: src/cryptsetup.c:3516
+msgid "dump LUKS partition information"
+msgstr "volcar información sobre la partición LUKS"
+
+#: src/cryptsetup.c:3517
+msgid "dump TCRYPT device information"
+msgstr "volcar información sobre el dispositivo TCRYPT"
+
+#: src/cryptsetup.c:3518
+msgid "dump BITLK device information"
+msgstr "volcar información sobre el dispositivo BITLK"
+
+#: src/cryptsetup.c:3519
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Suspender el dispositivo LUKS y limpiar la clave (todas las entradas/salidas congeladas)."
+
+#: src/cryptsetup.c:3520
+msgid "Resume suspended LUKS device"
+msgstr "Reanudar el dispositivo LUKS suspendido."
+
+#: src/cryptsetup.c:3521
+msgid "Backup LUKS device header and keyslots"
+msgstr "Hacer copia de seguridad de la cabecera y de las ranuras de claves del dispositivo LUKS"
+
+#: src/cryptsetup.c:3522
+msgid "Restore LUKS device header and keyslots"
+msgstr "Restaurar la cabecera y las ranuras de claves del dispositivo LUKS"
+
+#: src/cryptsetup.c:3523
+msgid "<add|remove|import|export> <device>"
+msgstr "<añade|elimina|importa|exporta> <dispositivo>"
+
+#: src/cryptsetup.c:3523
+msgid "Manipulate LUKS2 tokens"
+msgstr "Manipular «tokens» LUKS2"
+
+#: src/cryptsetup.c:3543 src/veritysetup.c:498 src/integritysetup.c:464
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<acción> es una de:\n"
+
+#: src/cryptsetup.c:3549
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+msgstr ""
+"\n"
+"También se pueden utilizar los alias del tipo <acción> de la antigua sintaxis:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+
+#: src/cryptsetup.c:3553
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nombre> es el dispositivo que se va a crear en %s\n"
+"<dispositivo> es el dispositivo cifrado\n"
+"<ranura de claves> es el número de la ranura de claves que se va a modificar\n"
+"<fichero de claves> fichero de claves opcional para la nueva clave para la acción 'luksAddKey'\n"
+
+#: src/cryptsetup.c:3560
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"El formato de metadatos predefinido de fábrica es %s (para la acción luksFormat).\n"
+
+#: src/cryptsetup.c:3565 src/cryptsetup.c:3568
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"El soporte del «plugin» del «token» externo LUKS2 es %s.\n"
+
+#: src/cryptsetup.c:3565
+msgid "compiled-in"
+msgstr "integrado en la compilación"
+
+#: src/cryptsetup.c:3566
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "ruta del «plugin» del «token» externo LUKS2: %s.\n"
+
+#: src/cryptsetup.c:3568
+msgid "disabled"
+msgstr "desactivado"
+
+#: src/cryptsetup.c:3572
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Parámetros predefinidos de fábrica de clave y de frase contraseña:\n"
+"\tTamaño máximo del fichero de claves: %dk8, Longitud máxima de frase contraseña interactiva: %d (caracteres)\n"
+"PBKDF predefinido para LUKS1: %s, tiempo de iteración: %d (ms)\n"
+"PBKDF predefinido para LUKS2: %s\n"
+"\tTiempo de iteración: %d, Memoria requerida: %dkB, hilos en paralelo: %d\n"
+
+#: src/cryptsetup.c:3583
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Parámetros predefinidos de fábrica del algoritmo de cifrado de dispositivos:\n"
+"\tbucle-AES: %s, Clave %d bits\n"
+"\tsin cifrado: %s, Clave: %d bits, Contraseña «hashing»: %s\n"
+"\tLUKS: %s, Clave: %d bits, «hashing» de la cabecera LUKS: %s, Generador de números aleatorios: %s\n"
+
+#: src/cryptsetup.c:3592
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: El tamaño de clave predefinido con modo XTS (dos claves internas) va a ser duplicado.\n"
+
+#: src/cryptsetup.c:3610 src/veritysetup.c:637 src/integritysetup.c:620
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: necesita %s como argumentos"
+
+#: src/cryptsetup.c:3648 src/cryptsetup_reencrypt.c:1379
+#: src/cryptsetup_reencrypt.c:1704
+msgid "Key slot is invalid."
+msgstr "La ranura de claves no es válida."
+
+#: src/cryptsetup.c:3675
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "El tamaño del dispositivo debe ser múltiplo de sectores de 512 bytes."
+
+#: src/cryptsetup.c:3680
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "La especificación del tamaño máximo de zona activa del dispositivo no es válida."
+
+#: src/cryptsetup.c:3694 src/cryptsetup.c:3706 src/cryptsetup_reencrypt.c:1623
+msgid "Key size must be a multiple of 8 bits"
+msgstr "El tamaño de clave debe ser un múltiplo de 8 bits"
+
+#: src/cryptsetup.c:3711
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "El tamaño máximo de reducción del dispositivo es de 1 GiB."
+
+#: src/cryptsetup.c:3714 src/cryptsetup_reencrypt.c:1631
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "El tamaño de reducción debe ser múltiplo de sectores de 512 bytes."
+
+#: src/cryptsetup.c:3731
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "La opción --priority solo puede ser ignore/normal/prefer."
+
+#: src/cryptsetup.c:3741 src/veritysetup.c:561 src/integritysetup.c:543
+#: src/cryptsetup_reencrypt.c:1641
+msgid "Show this help message"
+msgstr "Mostrar este mensaje de ayuda"
+
+#: src/cryptsetup.c:3742 src/veritysetup.c:562 src/integritysetup.c:544
+#: src/cryptsetup_reencrypt.c:1642
+msgid "Display brief usage"
+msgstr "Mostrar brevemente cómo se usa"
+
+#: src/cryptsetup.c:3743 src/veritysetup.c:563 src/integritysetup.c:545
+#: src/cryptsetup_reencrypt.c:1643
+msgid "Print package version"
+msgstr "Imprimir versión del paquete"
+
+#: src/cryptsetup.c:3754 src/veritysetup.c:574 src/integritysetup.c:556
+#: src/cryptsetup_reencrypt.c:1654
+msgid "Help options:"
+msgstr "Opciones de ayuda:"
+
+#: src/cryptsetup.c:3771 src/veritysetup.c:592 src/integritysetup.c:573
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPCIÓN...] <acción> <acción-específica>"
+
+#: src/cryptsetup.c:3780 src/veritysetup.c:601 src/integritysetup.c:584
+msgid "Argument <action> missing."
+msgstr "El argumento <acción> no se ha proporcionado."
+
+#: src/cryptsetup.c:3850 src/veritysetup.c:632 src/integritysetup.c:615
+msgid "Unknown action."
+msgstr "Acción desconocida."
+
+#: src/cryptsetup.c:3861
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Las opciones --refresh y --test-passphrase son mutuamente excluyentes."
+
+#: src/cryptsetup.c:3866 src/veritysetup.c:656 src/integritysetup.c:663
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Las opciones --cancel-deferred y --deferred no pueden utilizarse a la vez."
+
+#: src/cryptsetup.c:3872
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "La opción --shared solo se permite para abrir dispositivos no cifrados."
+
+#: src/cryptsetup.c:3877
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "La opción --persistent no se permite con --test-passphrase."
+
+#: src/cryptsetup.c:3882
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "La opción --integrity-no-wipe solo puede usarse para la acción de formato con extensión de integridad."
+
+#: src/cryptsetup.c:3889
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT and BITLK devices."
+msgstr "La opción --test-passphrase solo se permite para abrir dispositivos LUKS, TCRYPT y BITLK."
+
+#: src/cryptsetup.c:3901
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "La opción --key-file tiene precedencia sobre el argumento de fichero de claves especificado."
+
+#: src/cryptsetup.c:3907
+msgid "Only one --key-file argument is allowed."
+msgstr "Solo se permite un argumento --key-file."
+
+#: src/cryptsetup.c:3911 src/cryptsetup_reencrypt.c:1689
+#: src/cryptsetup_reencrypt.c:1708
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Solo se permite una de las opciones --use-[u]random."
+
+#: src/cryptsetup.c:3915
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Las opciones --align-payload y --offset no pueden combinarse."
+
+#: src/cryptsetup.c:3921
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "La opción --skip solo está disponible para abrir dispositivos no cifrados y «loopaes»."
+
+#: src/cryptsetup.c:3927
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "La opción --offset con acción de apertura solo está disponible para abrir dispositivos no cifrados y «loopaes»."
+
+#: src/cryptsetup.c:3933
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "La opción --tcrypt-hidden o --tcrypt-system o --tcrypt-backup solo está disponible para dispositivos TCRYPT."
+
+#: src/cryptsetup.c:3938
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "La opción --tcrypt-hidden no puede combinarse con --allow-discards."
+
+#: src/cryptsetup.c:3943
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Las opciones --veracrypt y --disable-veracrypt solo están disponibles para dispositivos de tipo TCRYPT."
+
+#: src/cryptsetup.c:3948
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "La opción --veracrypt-pim solo está disponible para dispositivos compatibles con VeraCrypt."
+
+#: src/cryptsetup.c:3954
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "La opción --veracrypt-query-pim solo está disponible para dispositivos compatibles con VeraCrypt."
+
+#: src/cryptsetup.c:3958
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Las opciones --veracrypt-pim y --veracrypt-query-pim son mutuamente excluyentes."
+
+#: src/cryptsetup.c:3966 src/cryptsetup.c:4002
+msgid "Keyslot specification is required."
+msgstr "Se requiere especificación de ranura de claves."
+
+#: src/cryptsetup.c:3971 src/cryptsetup_reencrypt.c:1694
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "La función de derivación de clave basada en contraseña (PBKDF) solo puede ser pbkdf2 o argon2i/argon2id."
+
+#: src/cryptsetup.c:3976 src/cryptsetup_reencrypt.c:1699
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Las iteraciones forzadas de PBKDF no pueden combinarse con la opción de tiempo de iteración."
+
+#: src/cryptsetup.c:3983
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "La opción de tamaño de sector con acción de apertura solamente está disponible para dispositivos no cifrados."
+
+#: src/cryptsetup.c:3990
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "La opción de sectores IV grandes solo se admite para abrir dispositivo de tipo plano con tamaño de sector mayor de 512 bytes."
+
+#: src/cryptsetup.c:3996
+msgid "Key size is required with --unbound option."
+msgstr "El tamaño de la clave es requerido con la opción --unbound."
+
+#: src/cryptsetup.c:4012
+msgid "LUKS2 decryption requires option --header."
+msgstr "El descifrado LUKS2 requiere la opción --header."
+
+#: src/cryptsetup.c:4016
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Las opciones --reduce-device-size y --data-size no pueden combinarse."
+
+#: src/cryptsetup.c:4020
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Las opciones --device-size y --size no pueden combinarse."
+
+#: src/cryptsetup.c:4024
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Las opciones --keyslot-cipher y --keyslot-key-size deben utilizarse juntas."
+
+#: src/cryptsetup.c:4028
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "No se ha realizado ninguna acción. Invocado con la opción --test-args.\n"
+
+#: src/cryptsetup.c:4040
+msgid "Invalid token action."
+msgstr "Acción de «token» no válida."
+
+#: src/cryptsetup.c:4045
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "El parámetro --key-description es obligatorio para la acción de añadir «token»."
+
+#: src/cryptsetup.c:4051
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "La acción requiere un «token» específico. Utilice el parámetro --token-id."
+
+#: src/cryptsetup.c:4062
+msgid "Cannot disable metadata locking."
+msgstr "No se puede desactivar el bloqueo de metadatos."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "La cadena «salt» especificada no es válida."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "No se puede crear la imagen «hash» %s para escribir."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "No se puede crear la imagen FEC %s para escribir."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "No se puede crear el fichero «hash» raíz %s para escribir."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "No se puede escribir en el fichero «hash» raíz %s."
+
+#: src/veritysetup.c:210 src/veritysetup.c:227
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "No se puede leer el fichero «hash» raíz %s."
+
+#: src/veritysetup.c:215
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "El fichero «hash» raíz %s no es válido."
+
+#: src/veritysetup.c:236
+msgid "Invalid root hash string specified."
+msgstr "La cadena «hash» raíz especificada no es válida."
+
+#: src/veritysetup.c:244
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Fichero de firmas inválido %s."
+
+#: src/veritysetup.c:251
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "No se puede leer el fichero de firmas %s."
+
+#: src/veritysetup.c:274 src/veritysetup.c:288
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Esta orden necesita <«hash»_raíz> o la opción --root-hash-file como argumento."
+
+#: src/veritysetup.c:478
+msgid "<data_device> <hash_device>"
+msgstr "<dispositivo_de_datos> <dispositivo_«hash»>"
+
+#: src/veritysetup.c:478 src/integritysetup.c:445
+msgid "format device"
+msgstr "dar formato al dispositivo"
+
+#: src/veritysetup.c:479
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<dispositivo_de_datos> <dispositivo_«hash»> [<«hash»_raíz>]"
+
+#: src/veritysetup.c:479
+msgid "verify device"
+msgstr "verificar dispositivo"
+
+#: src/veritysetup.c:480
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<dispositivo_de_datos> <nombre> <dispositivo_«hash»> [<«hash»_raíz>]"
+
+#: src/veritysetup.c:482 src/integritysetup.c:448
+msgid "show active device status"
+msgstr "mostrar el estado del dispositivo activo"
+
+#: src/veritysetup.c:483
+msgid "<hash_device>"
+msgstr "<dispositivo_«hash»>"
+
+#: src/veritysetup.c:483 src/integritysetup.c:449
+msgid "show on-disk information"
+msgstr "mostrar información sobre el disco"
+
+#: src/veritysetup.c:502
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nombre> es el dispositivo que se va a crear bajo %s\n"
+"<dispositivo_de_datos> es el dispositivo de datos\n"
+"<dispositivo_«hash»> es el dispositivo que contiene los datos de verificación\n"
+"<«hash»_raíz> «hash» del nodo raíz en «dispositivo—«hash»>\n"
+
+#: src/veritysetup.c:509
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Parámetros dm-verity predefinidos de fábrica:\n"
+"\tAlgoritmo «hash»: %s, Bloque de datos (bytes): %u, Bloque «hash» (bytes): %u, Tamaño de «salt»: %u, Formato «hash»: %u\n"
+
+#: src/veritysetup.c:646
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Las opciones --ignore-corruption y --restart-on-corruption no pueden utilizarse juntas."
+
+#: src/veritysetup.c:651
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Las opciones --panic-on-corruption y --restart-on-corruption no pueden utilizarse juntas."
+
+#: src/integritysetup.c:201
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formato dado con tamaño de etiqueta %u, integridad interna %s.\n"
+
+#: src/integritysetup.c:445 src/integritysetup.c:449
+msgid "<integrity_device>"
+msgstr "<dispositivo_de_integridad>"
+
+#: src/integritysetup.c:446
+msgid "<integrity_device> <name>"
+msgstr "<dispositivo_de_integridad> <nombre>"
+
+#: src/integritysetup.c:468
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<nombre> es el dispositivo que se va a crear bajo %s\n"
+"<dispositivo_de_integridad> es el dispositivo que contiene datos con etiquetas de integridad\n"
+
+#: src/integritysetup.c:473
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Parámetros dm-integrity predefinidos de fábrica:\n"
+"\tAlgoritmo de la suma de comprobación: %s\n"
+"\tTamaño máximo del fichero de claves: %dkB\n"
+
+#: src/integritysetup.c:530
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Tamaño de --%s no válido. El máximo es %u bytes."
+
+#: src/integritysetup.c:628
+msgid "Both key file and key size options must be specified."
+msgstr "Deben especificarse las opciones tanto de fichero de claves como tamaño de clave."
+
+#: src/integritysetup.c:632
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Deben especificarse la opción del fichero de clave de integridad del diario y la del tamaño de la clave."
+
+#: src/integritysetup.c:635
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Debe especificarse el algoritmo de integridad del diario si va a utilizarse la clave de integridad del diario."
+
+#: src/integritysetup.c:639
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Deben especificarse la opción del fichero de la clave de cifrado del diario y la del tamaño de la clave."
+
+#: src/integritysetup.c:642
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Debe especificarse el algoritmo de cifrado del diario si va a utilizarse la clave de cifrado del diario."
+
+#: src/integritysetup.c:646
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Las opciones de recuperación y de modo mapa de bits son mutuamente excluyentes."
+
+#: src/integritysetup.c:653
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Las opciones de diario no pueden utilizarse en modo mapa de bits."
+
+#: src/integritysetup.c:658
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Las opciones de mapa de bits solo pueden utilizarse en el modo mapa de bits."
+
+#: src/cryptsetup_reencrypt.c:149
+msgid "Reencryption already in-progress."
+msgstr "Recifrado ya en curso."
+
+#: src/cryptsetup_reencrypt.c:185
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "No se puede abrir %s en exclusividad; el dispositivo está en uso."
+
+#: src/cryptsetup_reencrypt.c:199 src/cryptsetup_reencrypt.c:1120
+msgid "Allocation of aligned memory failed."
+msgstr "La reserva de memoria alineada ha fallado."
+
+#: src/cryptsetup_reencrypt.c:206
+#, c-format
+msgid "Cannot read device %s."
+msgstr "No se puede leer el dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:217
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Marcando el dispositivo LUKS1 %s como inutilizable."
+
+#: src/cryptsetup_reencrypt.c:221
+#, c-format
+msgid "Setting LUKS2 offline reencrypt flag on device %s."
+msgstr "Estableciendo el indicador de recifrado fuera de línea LUKS2 en el dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:238
+#, c-format
+msgid "Cannot write device %s."
+msgstr "No se puede escribir en el dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:286
+msgid "Cannot write reencryption log file."
+msgstr "No se puede escribir en el fichero de registro de recifrado."
+
+#: src/cryptsetup_reencrypt.c:342
+msgid "Cannot read reencryption log file."
+msgstr "No se puede leer el fichero de registro de recifrado."
+
+#: src/cryptsetup_reencrypt.c:353
+msgid "Wrong log format."
+msgstr "Formato del fichero de registro incorrecto."
+
+#: src/cryptsetup_reencrypt.c:380
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "El fichero de registro %s ya existe; reanudando el recifrado.\n"
+
+#: src/cryptsetup_reencrypt.c:429
+msgid "Activating temporary device using old LUKS header."
+msgstr "Activando dispositivo temporal utilizando cabecera LUKS antigua."
+
+#: src/cryptsetup_reencrypt.c:439
+msgid "Activating temporary device using new LUKS header."
+msgstr "Activando dispositivo temporal utilizando cabecera LUKS nueva."
+
+#: src/cryptsetup_reencrypt.c:449
+msgid "Activation of temporary devices failed."
+msgstr "Fallo en la activación de los dispositivos temporales."
+
+#: src/cryptsetup_reencrypt.c:536
+msgid "Failed to set data offset."
+msgstr "No se ha podido establecer el desplazamiento de los datos."
+
+#: src/cryptsetup_reencrypt.c:542
+msgid "Failed to set metadata size."
+msgstr "No se ha podido establecer el tamaño de los metadatos."
+
+#: src/cryptsetup_reencrypt.c:550
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Se ha creado una nueva cabecera LUKS para el dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:610
+#, c-format
+msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+msgstr "Esta versión de cryptsetup-reencrypt no sabe manejar el nuevo tipo de «token» interno %s."
+
+#: src/cryptsetup_reencrypt.c:632
+msgid "Failed to read activation flags from backup header."
+msgstr "No se ha podido leer los indicadores de activación en la cabecera de respaldo."
+
+#: src/cryptsetup_reencrypt.c:636
+msgid "Failed to write activation flags to new header."
+msgstr "No se ha podido escribir los indicadores de activación en la nueva cabecera."
+
+#: src/cryptsetup_reencrypt.c:640 src/cryptsetup_reencrypt.c:644
+msgid "Failed to read requirements from backup header."
+msgstr "No se ha podido leer los requisitos en la cabecera de respaldo."
+
+#: src/cryptsetup_reencrypt.c:682
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Se ha creado una copia de seguridad de la cabecera %s del dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:745
+msgid "Creation of LUKS backup headers failed."
+msgstr "No se ha podido crear la copia de seguridad de las cabeceras LUKS."
+
+#: src/cryptsetup_reencrypt.c:878
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "No se puede restaurar la cabecera %s en el dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:880
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Se ha restaurado la cabecera %s en el dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:1092 src/cryptsetup_reencrypt.c:1098
+msgid "Cannot open temporary LUKS device."
+msgstr "No se puede abrir el dispositivo LUKS temporal."
+
+#: src/cryptsetup_reencrypt.c:1103 src/cryptsetup_reencrypt.c:1108
+msgid "Cannot get device size."
+msgstr "No se puede obtener el tamaño del dispositivo."
+
+#: src/cryptsetup_reencrypt.c:1143
+msgid "IO error during reencryption."
+msgstr "Error de entrada/salida durante el recifrado."
+
+#: src/cryptsetup_reencrypt.c:1174
+msgid "Provided UUID is invalid."
+msgstr "El UUID proporcionado no es válido."
+
+#: src/cryptsetup_reencrypt.c:1408
+msgid "Cannot open reencryption log file."
+msgstr "No se puede abrir el fichero de registro de recifrado."
+
+#: src/cryptsetup_reencrypt.c:1414
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "No hay ningún proceso de descifrado en marcha; el UUID proporcionado solo puede utilizarse para reanudar un proceso de descifrado suspendido."
+
+#: src/cryptsetup_reencrypt.c:1489
+#, c-format
+msgid "Changed pbkdf parameters in keyslot %i."
+msgstr "Se han cambiado los parámetros pbkdf en la ranura de claves %i."
+
+#: src/cryptsetup_reencrypt.c:1614
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Solo se permiten valores entre 1 MiB y 64 MiB para el tamaño de bloque de recifrado."
+
+#: src/cryptsetup_reencrypt.c:1628
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "El tamaño máximo de reducción del dispositivo es de 64 MiB."
+
+#: src/cryptsetup_reencrypt.c:1669
+msgid "[OPTION...] <device>"
+msgstr "[OPCIÓN...] <dispositivo>"
+
+#: src/cryptsetup_reencrypt.c:1677
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "El recifrado va a cambiar: %s%s%s%s%s%s."
+
+#: src/cryptsetup_reencrypt.c:1678
+msgid "volume key"
+msgstr "clave del volumen"
+
+#: src/cryptsetup_reencrypt.c:1680
+msgid "set hash to "
+msgstr "nuevo algoritmo «hash» "
+
+#: src/cryptsetup_reencrypt.c:1681
+msgid ", set cipher to "
+msgstr ", nuevo algoritmo de cifrado: "
+
+#: src/cryptsetup_reencrypt.c:1685
+msgid "Argument required."
+msgstr "Hace falta argumento."
+
+#: src/cryptsetup_reencrypt.c:1712
+msgid "Option --new must be used together with --reduce-device-size or --header."
+msgstr "La opción --new debe utilizarse conjuntamente con --reduce-device-size o --header."
+
+#: src/cryptsetup_reencrypt.c:1716
+msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+msgstr "La opción --keep-key solamente puede utilizarse con --hash, --iter-time o --pbkdf-force-iterations."
+
+#: src/cryptsetup_reencrypt.c:1720
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "La opción --new no puede utilizarse conjuntamente con --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1726
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "La opción --decrypt es incompatible con los parámetros especificados."
+
+#: src/cryptsetup_reencrypt.c:1730
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "La opción --uuid solo está permitida conjuntamente con --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1734
+msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+msgstr "Tipo de luks no válido. Utilice uno de estos: 'luks', 'luks1' o 'luks2'."
+
+#: src/utils_tools.c:119
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"¡ATENCIÓN!\n"
+"==========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:121
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"¿Está seguro? (Teclee 'yes' en mayúsculas): "
+
+#: src/utils_tools.c:127
+msgid "Error reading response from terminal."
+msgstr "Error de lectura de la respuesta recibida desde el terminal."
+
+#: src/utils_tools.c:159
+msgid "Command successful."
+msgstr "Orden ejecutada correctamente."
+
+#: src/utils_tools.c:167
+msgid "wrong or missing parameters"
+msgstr "parámetros incorrectos u omisos"
+
+#: src/utils_tools.c:169
+msgid "no permission or bad passphrase"
+msgstr "sin permiso o frase de paso mala"
+
+#: src/utils_tools.c:171
+msgid "out of memory"
+msgstr "sin memoria"
+
+#: src/utils_tools.c:173
+msgid "wrong device or file specified"
+msgstr "se ha especificado un dispositivo o fichero incorrecto"
+
+#: src/utils_tools.c:175
+msgid "device already exists or device is busy"
+msgstr "el dispositivo ya existe o está ocupado"
+
+#: src/utils_tools.c:177
+msgid "unknown error"
+msgstr "error desconocido"
+
+#: src/utils_tools.c:179
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "La orden ha fallado con código %i (%s)."
+
+#: src/utils_tools.c:257
+#, c-format
+msgid "Key slot %i created."
+msgstr "Ranura de claves %i creada."
+
+#: src/utils_tools.c:259
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Ranura de claves %i desbloqueada."
+
+#: src/utils_tools.c:261
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Ranura de claves %i eliminada."
+
+#: src/utils_tools.c:270
+#, c-format
+msgid "Token %i created."
+msgstr "«Token» %i creado."
+
+#: src/utils_tools.c:272
+#, c-format
+msgid "Token %i removed."
+msgstr "«Token» %i eliminado."
+
+#: src/utils_tools.c:282
+msgid "No token could be unlocked with this PIN."
+msgstr "No se ha podido desbloquear ningún «token» con este PIN."
+
+#: src/utils_tools.c:284
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "El «token» %i requiere PIN."
+
+#: src/utils_tools.c:286
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "El «token» (tipo %s) requiere PIN."
+
+#: src/utils_tools.c:289
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "El «token» %i no puede desbloquear ranura(s) de clave asignada(s) (frase contraseña incorrecta)."
+
+#: src/utils_tools.c:291
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "El «token» (tipo %s) no puede desbloquear ranura(s) de clave asignada(s) (frase contraseña incorrecta)."
+
+#: src/utils_tools.c:294
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "El «token» %i requiere un recurso adicional que no está presente."
+
+#: src/utils_tools.c:296
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "El «token» (tipo %s) requiere un recurso adicional que no está presente."
+
+#: src/utils_tools.c:299
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Ningún «token» utilizable (tipo %s) está disponible."
+
+#: src/utils_tools.c:301
+msgid "No usable token is available."
+msgstr "Ningún «token» utilizable está disponible."
+
+#: src/utils_tools.c:463
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Limpieza interrumpida."
+
+#: src/utils_tools.c:492
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Recifrado interrumpido."
+
+#: src/utils_tools.c:511
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "No se puede leer el fichero de claves %s."
+
+#: src/utils_tools.c:516
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "No se pueden leer %d «bytes» en el fichero de claves %s."
+
+#: src/utils_tools.c:541
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "No se puede abrir el fichero de claves %s para escritura."
+
+#: src/utils_tools.c:548
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "No se puede escribir en el fichero de claves %s."
+
+#: src/utils_password.c:41 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "No se puede comprobar la calidad de la contraseña: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Fallo en la comprobación de la calidad de la contraseña:\n"
+" %s"
+
+#: src/utils_password.c:81
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Fallo en la comprobación de la calidad de la contraseña: frase contraseña incorrecta (%s)"
+
+#: src/utils_password.c:224 src/utils_password.c:238
+msgid "Error reading passphrase from terminal."
+msgstr "Error al leer la frase contraseña desde el terminal."
+
+#: src/utils_password.c:236
+msgid "Verify passphrase: "
+msgstr "Verifique la frase contraseña: "
+
+#: src/utils_password.c:243
+msgid "Passphrases do not match."
+msgstr "La frase contraseña no coincide."
+
+#: src/utils_password.c:280
+msgid "Cannot use offset with terminal input."
+msgstr "No se puede usar «offset» con entrada desde terminal."
+
+#: src/utils_password.c:283
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Introduzca la frase contraseña: "
+
+#: src/utils_password.c:286
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Introduzca la frase contraseña de %s: "
+
+#: src/utils_password.c:317
+msgid "No key available with this passphrase."
+msgstr "No hay ninguna clave disponible con esa frase contraseña."
+
+#: src/utils_password.c:319
+msgid "No usable keyslot is available."
+msgstr "No hay niguna ranura de claves utilizable disponible."
+
+#: src/utils_luks2.c:47
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "No se ha podido abrir el fichero %s para solo lectura."
+
+#: src/utils_luks2.c:60
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Proporciona «token» LUKS2 válido en JSON:\n"
+
+#: src/utils_luks2.c:67
+msgid "Failed to read JSON file."
+msgstr "No se ha podido leer el fichero JSON."
+
+#: src/utils_luks2.c:72
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Lectura interrumpida."
+
+#: src/utils_luks2.c:113
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "No se ha podido abrir el fichero %s para escritura."
+
+#: src/utils_luks2.c:122
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Escritura interrumpida."
+
+#: src/utils_luks2.c:126
+msgid "Failed to write JSON file."
+msgstr "No se ha podido escribir el fichero JSON."
+
+#: src/utils_blockdev.c:192
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "ATENCIÓN: El dispositivo %s ya contiene una firma de partición '%s'.\n"
+
+#: src/utils_blockdev.c:200
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "ATENCIÓN: El dispositivo %s ya contiene una firma de superbloque '%s'.\n"
+
+#: src/utils_blockdev.c:221 src/utils_blockdev.c:285
+msgid "Failed to initialize device signature probes."
+msgstr "No se han podido inicializar los sondeos de firma del dispositivo."
+
+#: src/utils_blockdev.c:265
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "No se ha podido efectuar «stat» sobre el dispositivo %s."
+
+#: src/utils_blockdev.c:278
+#, c-format
+msgid "Device %s is in use. Cannot proceed with format operation."
+msgstr "El dispositivo %s está en uso. No se puede proceder con la operación de dar formato."
+
+#: src/utils_blockdev.c:280
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "No se ha podido abrir el fichero %s para lectura y escritura."
+
+#: src/utils_blockdev.c:294
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "La firma de la partición '%s' existente en el dispositivo %s va a ser borrada."
+
+#: src/utils_blockdev.c:297
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "La firma del superbloque '%s' existente en el dispositivo %s va a ser borrada."
+
+#: src/utils_blockdev.c:300
+msgid "Failed to wipe device signature."
+msgstr "No se ha podido limpiar la firma del dispositivo."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "No se ha podido sondear el dispositivo %s para una firma."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "La especificación del tamaño no es válida en el parámetro --%s."
+
+#: src/utils_args.c:121
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "La opción --%s no se permite con la acción %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:108
+msgid "Failed to write ssh token json."
+msgstr "No se ha podido escribir el json del «token» ssh."
+
+#: tokens/ssh/cryptsetup-ssh.c:126
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"«Plugin» experimental de cryptsetup para desbloquear dispositivos LUKS2 con «token» conectado a servidor SSH\vEste «plugin» actualmente permite únicamente añadir un «token» a una ranura de claves que ya exista.\n"
+"\n"
+"El servidor SSH especificado debe contener un fichero de claves en la ruta especificada con una frase contraseña para una ranura de claves que ya exista en el dispositivo.\n"
+"Las credenciales proporcionadas cryptsetup las utilizará para obtener la contraseña al abrir el dispositivo mediante el «token».\n"
+"\n"
+"Nota: la información proporcionada al añadir el «token» (dirección del servidor SSH, usuario y rutas) se almacenará en la cabecera LUKS2 en texto plano."
+
+#: tokens/ssh/cryptsetup-ssh.c:136
+msgid "<action> <device>"
+msgstr "<acción> <dispositivo>"
+
+#: tokens/ssh/cryptsetup-ssh.c:139
+msgid "Options for the 'add' action:"
+msgstr "Opciones para la acción 'add':"
+
+#: tokens/ssh/cryptsetup-ssh.c:140
+msgid "IP address/URL of the remote server for this token"
+msgstr "Dirección IP/URL del servidor remoto para este «token»"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Username used for the remote server"
+msgstr "Nombre de usuario utilizado para el servidor remoto"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "Path to the key file on the remote server"
+msgstr "Ruta del fichero de claves en el servidor remoto"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Ruta de la clave SSH para conectarse al servidor remoto"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Ranura de claves a la que asignar el «token». Si no se especifica, el «token» será asignado a la primera ranura de claves que coincida con la frase contraseña proporcionada."
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Generic options:"
+msgstr "Opciones genéricas:"
+
+#: tokens/ssh/cryptsetup-ssh.c:147
+msgid "Shows more detailed error messages"
+msgstr "Muestra mensajes de error más detallados"
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Show debug messages"
+msgstr "Mostrar mensajes de depuración"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Show debug messages including JSON metadata"
+msgstr "Mostrar mensajes de depuración incluidos los metadatos JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:260
+msgid "Failed to open and import private key:\n"
+msgstr "No se ha podido abrir e importar la clave privada:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:264
+msgid "Failed to import private key (password protected?).\n"
+msgstr "No se ha podido importar la clave privada (¿está protegida por contraseña?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:266
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Contraseña de %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:355
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "No se han podido analizar los argumentos.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:366
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Es preciso especificar una acción\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:372
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Es preciso especificar el dispositivo para la acción '%s'.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:377
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Es preciso especificar el servidor SSH para la acción '%s'.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:382
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Es preciso especificar el usuario SSH para la acción '%s'.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:387
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Es preciso especificar la ruta SSH para la acción '%s'.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:392
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Es preciso especificar la ruta de la ruta SSH para la acción '%s'.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:399
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "No se ha podido abrir %s con las credenciales proporcionadas.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:415
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Actualmente este «plugin» solo admite la acción 'add'.\n"
+
+#: tokens/ssh/ssh-utils.c:46 tokens/ssh/ssh-utils.c:59
+msgid "Cannot create sftp session: "
+msgstr "No se puede crear la sesión sftp: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "No se puede iniciar la sesión sftp: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "No se puede obtener el estado del fichero sftp: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "No hay memoria suficiente.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "No se puede leer la clave remota: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "La conexión ha fallado: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Servidor no conocido: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "El método de autenticación de clave pública no está permitido en el «host».\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Error de autenticación de clave pública: "
+
+#~ msgid "No free token slot."
+#~ msgstr "No hay ninguna ranura de «token» libre."
+
+#~ msgid "Failed to create builtin token %s."
+#~ msgstr "No se ha podido crear el «token» interno %s."
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Tipo de dispositivo LUKS no válido."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Algoritmo de cifrado utilizado para cifrar el disco (ver /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Algoritmo «hash» utilizado para crear la clave de cifrado a partir de la frase contraseña"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Verifica la frase contraseña preguntándola dos veces"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Leer la clave de un fichero."
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Leer la clave (maestra) del volumen desde fichero."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Volcar la clave (maestra) del volumen en lugar de la información de las ranuras de claves."
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Tamaño de la clave de cifrado"
+
+#~ msgid "BITS"
+#~ msgstr "BITS"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Limita la lectura desde fichero de claves"
+
+#~ msgid "bytes"
+#~ msgstr "bytes"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Número de bytes que hay que saltar en el fichero de claves"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Limita la lectura desde un fichero de claves recién añadido"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Número de bytes que hay que saltar en el fichero de claves recién añadido"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Número de ranura para la nueva clave (el primero libre es lo predefinido)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Tamaño del dispositivo"
+
+#~ msgid "SECTORS"
+#~ msgstr "SECTORES"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Utilizar solamente el tamaño especificado de dispositivo (ignorar el resto del dispositivo). ¡PELIGROSO!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "iPosición de comienzo en el dispositivo «backend»"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Cuántos sectores de los datos cifrados hay que saltar al principio"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Crear una asignación alatoria"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "No pedir confirmación"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Tiempo de espera máximo para petición interactiva de frase contraseña (en segundos)"
+
+#~ msgid "secs"
+#~ msgstr "s"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Actualización de la línea de progreso (en segundos)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Con qué frecuencia se puede volver a intentar introducir la frase contraseña"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Alinear los datos a <n> bordes de sector - para luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Fichero con copia de seguridad de cabecera LUKS y de ranuras de clave."
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Usar /dev/random para generar la clave del volumen."
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Usar /dev/urandom para generar la clave del volumen."
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Compartir dispositivo con otro segmento cifrado no solapado."
+
+#~ msgid "UUID for device to use"
+#~ msgstr "UUID del dispositivo que se va a usar"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Permitir solicitudes de descarte (también llamadas TRIM) para el dispositivo"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Dispositivo o fichero con cabecera LUKS separada"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "No activar dispositivo; comprobar frase contraseña solamente"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Utilizar cabecera oculta (dispositivo TCRYPT oculto)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "El dispositivo es una unidad con sistema TCRYPT (con cargador de arranque)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Utilizar la cabecera TCRYPT de respaldo (secundaria)"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Explorar también si es un dispositivo compatible con VeraCrypt"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Multiplicador de iteración personal para dispositivo compatible con VeraCrypt"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Consulta el multiplicador de iteración personal para dispositivo compatible con VeraCrypt"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Tipo de metadatos del dispositivo: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Desactivar la comprobación de la calidad de la contraseña (si estaba activada)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Utilizar la opción de compatibilidad de rendimiento same_cpu_crypt de dm-crypt"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Utilizar la opción de compatibilidad de rendimiento submit_from_crypt_cpus de dm-crypt"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Obviar la cola de trabajo de dm-crypt y procesar las peticiones de lectura de forma síncrona"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Obviar la cola de trabajo de dm-crypt y procesar las peticiones de escritura de forma síncrona"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "La eliminación del dispositivo está diferida hasta que el último usuario lo cierre"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Utilizar un bloqueo global para serializar PBKDF estricto en memoria (solución OOM)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "Tiempo de iteración PBKDF para LUKS (en ms)"
+
+#~ msgid "msecs"
+#~ msgstr "ms"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "Algoritmo PBKDF (para LUKS2): argon2i, argon2id, pbkdf2"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "Límite del coste de memoria PBKDF"
+
+#~ msgid "kilobytes"
+#~ msgstr "kilobytes"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "Coste del paralelismo PBKDF"
+
+#~ msgid "threads"
+#~ msgstr "hilos"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "Coste de las iteraciones PBKDF (forzado, desactiva el banco de pruebas)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Prioridad de la ranura de claves: ignorada, normal, preferente"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Desactiva el bloqueo de metadatos en disco"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Desactiva la carga de las claves del volumen mediante el llavero del núcleo"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Algoritmo de integridad de datos (solo LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Desactiva el diario para dispositivo de integridad"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "No limpiar dispositivo después de dar formato"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Utilizar relleno obsoleto ineficiente (núcleos antiguos)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "No pedir frase de paso si falla la activación por «token»"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Número de «token» (predefinido: cualquiera)"
+
+#~ msgid "Key description"
+#~ msgstr "Descripción de la clave"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Tamaño de sector de cifrado (predeterminado: 512 bytes)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Utiliza IV contado en tamaño de sector (no en unidades de 512 bytes)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Establecer indicadores de activación persistentes para el dispositivo"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Poner etiqueta al dispositivo LUKS2"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Poner etiqueta de subsistema al dispositivo LUKS2"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Crear o volcar ranura de claves LUKS2 independiente (sin segmento de datos asignado)"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Leer o escribir el json de o en un fichero"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Tamaño de la zona de metadatos de la cabecera LUKS2"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Tamaño de la zona de ranuras de clave de la cabecera LUKS2"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Refrescar (reactivar) el dispositivo con los nuevos parámetros"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "Ranura de clave de LUKS2: Tamaño de la clave de cifrado"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "Ranura de clave de LUKS2: El algoritmo de cifrado utilizado para el cifrado de ranuras de clave"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Crifrar el dispositivo LUKS2 (cifrado in situ)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Descifrar el dispositivo LUKS2 (elimina cifrado)"
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Inicializar solamente recifrado LUKS2 de los metadatos."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Reanudar solamente recifrado LUKS2 inicializado."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Reducir el tamaño del dispositivo de datos (mover la posición de los datos). ¡PELIGROSO!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Tamaño de zona activa de recifrado máximo."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Tipo de resiliencia de zona activa de recifrado (checksum,journal,none)"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "«Hash» de suma de comprobación de zona activa de recifrado"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Anular la autodetección de dispositivos del dispositivo dm que se va a recifrar"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "La opción --deferred solo se permite con la orden de cerrar."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "La opción --allow-discards solo se permite para la operación de abrir."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "La opción --persistent solo se permite para la operación de abrir."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "La opción --serialize-memory-hard-pbkdf solo se permite para la operación de abrir."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "La opción --key-size solo se permite con las acciones luksFormat, luksAddKey,\n"
+#~ "open y benchmark. Para limitar la lectura del fichero de claves, utilizar --keyfile-size=(bytes)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "La opción --integrity solo se permite con luksFormat (LUKS2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Las opciones --label y --subsystem solo se permiten con las operaciones luksFormat y config LUKS2."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "No se permiten números negativos para esta opción."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "La opción --use-[u]random solo se permite con luksFormat."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "La opción --uuid solo se permite con luksFormat luksUUID."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "La opción --align-payload solo se permite con luksFormat."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Las opciones --luks2-metadata-size y --opt-luks2-keyslots-size solo se permiten para luksFormat con LUKS2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "La especificación del tamaño de los metadatos LUKS2 no es válida."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "La especificación del tamaño de las ranuras de claves LUKS2 no es válida."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "La opción --offset solo está disponible para abrir dispositivos no cifrados y «loopaes», «luksFormat» y recifrado de dispositivo."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Argumento no válido para el parámetro --veracrypt-pim supplied."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "La opción de tamaño de sector no está disponible para esta orden."
+
+#~ msgid "Option --unbound may be used only with luksAddKey and luksDump actions."
+#~ msgstr "La opción --unbound solo puede utilizarse con las acciones luksAddKey y luksDump."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "La opción --refresh solo puede utilizarse con la acción de abrir."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "La especificación del tamaño del dispositivo no es válida."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Desbordamiento del tamaño de la reducción."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "No utilizar superbloque «verity»"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Tipo de formato (1 - normal, 0 - Chrome OS original)"
+
+#~ msgid "number"
+#~ msgstr "número"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Tamaño de bloque en el dispositivo de datos"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Tamaño de bloque en el dispositivo «hash»"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "Bytes de paridad FEC"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Número de bloques en el fichero de datos"
+
+#~ msgid "blocks"
+#~ msgstr "bloques"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Ruta a dispositivo con datos de corrección de errores"
+
+#~ msgid "path"
+#~ msgstr "ruta"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Posición inicial en el dispositivo «hash»"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Posición inicial en el dispositivo FEC"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Algoritmo «hash»"
+
+#~ msgid "string"
+#~ msgstr "cadena"
+
+#~ msgid "Salt"
+#~ msgstr "«Salt»"
+
+#~ msgid "hex string"
+#~ msgstr "cadena hexadecimal"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Ruta al fichero de firmas «hash» raíz"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Reiniciar el núcleo si se detecta corrupción"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Poner en pánico al núcleo si se detecta corrupción"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Ignorar corrupción, tomar nota únicamente"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "No verificar bloques con zeros"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Verificar el bloque de datos solo en la primera lectura"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Las opciones --ignore-corruption, --restart-on-corruption y --ignore-zero-blocks solo están permitidas para la operación de abrir."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "La opción --root-hash-signature solo puede usarse para la acción de abrir."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Ruta al dispositivo de datos (si está separado)"
+
+#~ msgid "Journal size"
+#~ msgstr "Tamaño del diario"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Sectores de entrelazado"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Marca de agua del diario"
+
+#~ msgid "percent"
+#~ msgstr "por ciento"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Tiempo de escritura en el diario"
+
+#~ msgid "ms"
+#~ msgstr "ms"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Número de sectores de 512 bytes por bit (modo mapa de bits)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Tiempo de «flush» del modo mapa de bits"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Tamaño de etiqueta (por sector)"
+
+#~ msgid "Sector size"
+#~ msgstr "Tamaño de sector"
+
+#~ msgid "Buffers size"
+#~ msgstr "Tamaño de los «buffers»"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Algoritmo para la integridad de datos"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Tamaño de la clave de integridad de datos"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Leer la clave de integridad de un fichero"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Algoritmo de integridad del diario"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Tamaño de la clave de integridad del diario"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Leer la clave de integridad del diario de un fichero"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Algoritmo de cifrado del diario"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Tamaño de la clave de cifrado del diario"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Leer la clave de cifrado del diario de un fichero"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Modo de recuperación (sin diario, sin comprobación de etiqueta)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Utilice bitmap para seguir los cambios y desactive el diario para el dispositivo de integridad"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Recalcular las etiquetas iniciales automáticamente."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "No proteger superbloque con HMAC (núcleos antiguos)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Permitir recalcular volúmenes con claves HMAC (núcleos antiguos)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "La opción --integrity-recalculate solo puede usarse para la acción de abrir."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Las opciones --journal-size, --interleave-sectors, --sector-size, --tag-size y --no-wipe solo pueden utilizarse para la acción de dar formato."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "La especificación del tamaño del diario no es válida."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Tamaño de bloque de recifrado"
+
+#~ msgid "MiB"
+#~ msgstr "MiB"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "No cambie la clave; no hay recifrado en la zona de datos"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Leer la clave (maestra) del volumen desde fichero"
+
+#~ msgid "PBKDF2 iteration time for LUKS (in ms)"
+#~ msgstr "Tiempo de iteración PBKDF2 para LUKS (en ms)"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Utilizar entrada/salida directa para acceder a los dispositivos"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Utilizar fsync después de cada bloque"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Actualizar el fichero de registro después de cada bloque"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Utilizar solamente esta ranura (se desactivarán las demás)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Crear nueva cabecera en dispositivo no cifrado"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Descifrar el dispositivo de forma permanente (eliminar cifrado)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "El UUID utilizado para reanudar el descifrado"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Tipo de metadato LUKS: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "ATENCIÓN: ¡Falta el directorio de bloqueo %s/%s!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Parámetros de tamaño inválido para un dispositivo «verity»."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "El algoritmo para la integridad debe especificarse si se va a utilizar clave de integridad."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Tamaño de clave incorrecto."
+
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands."
+#~ msgstr "El parámetro --refresh solo se permite con las órdenes de abrir y de refrescar."
+
+#~ msgid "Cipher %s is not available."
+#~ msgstr "El algoritmo de cifrado %s no está disponible."
+
+#~ msgid "Unsupported encryption sector size.\n"
+#~ msgstr "Tamaño de sector de cifrado no admitido.\n"
+
+#~ msgid "Offline reencryption in progress. Aborting."
+#~ msgstr "Recifrado «offline» en curso. Se aborta."
+
+#~ msgid "Online reencryption in progress. Aborting."
+#~ msgstr "Recifrado «online» en curso. Se aborta."
+
+#~ msgid "No LUKS2 reencryption in progress."
+#~ msgstr "No hay ningún recifrado LUKS2 en proceso."
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Interrumpido por una señal."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "Función no disponible en modo FIPS."
+
+#~ msgid "Failed to finalize hash."
+#~ msgstr "No se ha podido finalizar el «hash»."
+
+#~ msgid "Invalid resilience parameters (internal error)."
+#~ msgstr "Parámetros de resiliencia no válidos (error interno)."
+
+#~ msgid "Failed to assign new enc segments."
+#~ msgstr "No se han logrado asignar los nuevos segmentos enc."
+
+#~ msgid "Failed to assign digest %u to segment %u."
+#~ msgstr "No se ha logrado asignar el resumen %u al segmento %u."
+
+#~ msgid "Failed to assign reencrypt previous backup segment."
+#~ msgstr "No se ha podido asignar recifrado al segmento de respaldo anterior."
+
+#~ msgid "Failed to assign reencrypt final backup segment."
+#~ msgstr "No se ha podido asignar recifrado al segmento de respaldo final."
+
+#~ msgid "Failed generate 2nd segment."
+#~ msgstr "No se ha podido generar el segundo segmento."
+
+#~ msgid "Failed generate 1st segment."
+#~ msgstr "No se ha podido generar el primer segmento."
+
+#~ msgid "Failed to allocate device %s."
+#~ msgstr "No se ha podido asignar el dispositivo %s."
+
+#~ msgid "Failed to allocate dm segments."
+#~ msgstr "No se han podido asignar los segmentos dm."
+
+#~ msgid "Failed to create dm segments."
+#~ msgstr "No se han podido crear los segmentos dm."
+
+#~ msgid "Failed to allocate device for new backing device."
+#~ msgstr "No se ha podido asignar el dispositivo para el nuevo dispositivo de respaldo."
+
+#~ msgid "Failed to reload overlay device %s."
+#~ msgstr "No se ha podido recargar el dispositivo de superposición %s."
+
+#~ msgid "Failed to refresh helper devices."
+#~ msgstr "No se han podido actualizar los dispositivos de ayuda."
+
+#~ msgid "Failed to create reencryption backup segments."
+#~ msgstr "No se ha podido crear los segmentos de respaldo de recifrado."
+
+#~ msgid "Failed to set online-reencryption requirement."
+#~ msgstr "No se ha podido establecer el requisito de recifrado «online»."
+
+#~ msgid "Failed to hash sector at offset %zu."
+#~ msgstr "No se ha podido hacer «hash» del sector en el desplazamiento %zu."
+
+#~ msgid "Failed to read sector hash."
+#~ msgstr "No se ha podido leer el «hash« del sector."
+
+#~ msgid "Error: Calculated reencryption offset %<PRIu64> is beyond device size %<PRIu64>."
+#~ msgstr "Error: El desplazamiento %<PRIu64> de recifrado calculado sobrepasa el tamaño %<PRIu64> del dispositivo."
+
+#~ msgid "Device is not in clean reencryption state."
+#~ msgstr "El dispositivo no está en un estado de recifrado limpio."
+
+#~ msgid "Failed to calculate new segments."
+#~ msgstr "No se ha podido calcular los nuevos segmentos."
+
+#~ msgid "Failed finalize hotzone resilience, retval = %d"
+#~ msgstr "No se ha podido finalizar la resiliencia de zona caliente, retval = %d"
+
+#~ msgid "Failed to write data."
+#~ msgstr "No se han podido escribir los datos."
+
+#~ msgid "Failed to update metadata or reassign device segments."
+#~ msgstr "No se han podido actualizar los metadatos o reasignar los segmentos del dispositivo."
+
+#~ msgid "Failed to reload %s device."
+#~ msgstr "No se ha podido recargar el dispositivo %s."
+
+#~ msgid "Failed to erase backup segments"
+#~ msgstr "No se han podido borrar los segmentos de respaldo."
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Las opciones de rendimiento de dmcrypt solicitadas no están disponibles."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "No se puede dar formato al dispositivo %s que todavía está en uso."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "La ranura de claves %d no se está utilizando."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "La ranura de claves %d se va a borrar."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "abrir el dispositivo como asociado a <nombre>"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "cerrar dispositivo (desactivar y eliminar la asociación)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "No se han podido establecer los parámetros PBKDF."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "No es posible situarse en la posición del dispositivo.\n"
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "El dispositivo %s es demasiado pequeño. (LUKS3 necesita %<PRIu64> btyes como mínimo.)"
+
+#~ msgid "Replaced with key slot %d."
+#~ msgstr "Reemplazado con ranura de claves %d."
+
+#~ msgid "Missing LUKS target type, option --type is required."
+#~ msgstr "Falta el tipo de objetivo LUKS, se requiere la opción --type."
+
+#~ msgid "Missing --token option specifying token for removal."
+#~ msgstr "Falta la opción --token que especifica el «token» que se va a borrar."
+
+#~ msgid "Add or remove keyring token"
+#~ msgstr "Añadir o eliminar «token» de llavero"
+
+#~ msgid "Activated keyslot %i."
+#~ msgstr "Se ha activado la ranura de claves %i."
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "error de reserva de memoria en action_luksFormat"
+
+#~ msgid "Key slot is invalid.\n"
+#~ msgstr "La ranura de claves no es válida.\n"
+
+#~ msgid "Using default pbkdf parameters for new LUKS2 header.\n"
+#~ msgstr "Se está utilizando los parámetros pbkdf predeterminados para la nueva cabecera LUKS2.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Demasiados niveles de arborescencia en el volumen «verity».\n"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "La clave %d no está activa. No se puede limpiar.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<nombre> <dispositivo_de_datos> <dispositivo_«hash»> <«hash»_raíz>"
+
+#~ msgid "create active device"
+#~ msgstr "crear dispositivo activo"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "eliminar (desactivar) dispositivo"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Progreso: %5.1f%%, ETA %02llu:%02llu, %4llu MiB escritos, velocidad %5.1f MiB/s%s"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "No se ha encontrado ningún dispositivo de bucle invertido libre.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "No se puede abrir el dispositivo %s\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "No se puede utilizar el UUID pasado a menos que haya descifrado en curso.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "Marcando el dispositivo LUKS %s como utilizable.\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "ATENCIÓN: este código es experimental; puede ser que sus datos queden deteriorados por completo.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "La verificación de suma («checksum») FIPS ha fallado.\n"
+
+#~ msgid "WARNING: device %s is a partition, for TCRYPT system encryption you usually need to use whole block device path.\n"
+#~ msgstr "ATENCIÓN: el dispositivo %s es una partición; para el sistema de cifrado TCRYPT normalmente se necesita usar la ruta de un dispositivo de bloque entero.\n"
diff --git a/po/fi.po b/po/fi.po
new file mode 100644
index 0000000..7cfbba4
--- /dev/null
+++ b/po/fi.po
@@ -0,0 +1,1933 @@
+# Finnish messages for cryptsetup.
+# Copyright © 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# This file is distributed under the same license as the cryptsetup package.
+# Jorma Karvonen <karvonen.jorma@gmail.com>, 2011-2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 1.7.0\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2015-10-29 13:27+0100\n"
+"PO-Revision-Date: 2015-11-08 12:48+0200\n"
+"Last-Translator: Jorma Karvonen <karvonen.jorma@gmail.com>\n"
+"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
+"Language: fi\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: lib/libdevmapper.c:253
+msgid "Cannot initialize device-mapper, running as non-root user.\n"
+msgstr "Laitekuvaimen alustus epäonnistui, suoritetaan ei-root-käyttäjänä.\n"
+
+#: lib/libdevmapper.c:256
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"
+msgstr "Laitekuvaimen alustus epäonnistui. Onko dm_mod-käyttöjärjestelmäydinmoduuli ladattu?\n"
+
+#: lib/libdevmapper.c:551
+#, c-format
+msgid "DM-UUID for device %s was truncated.\n"
+msgstr "DM-UUID laitteelle %s typistettiin.\n"
+
+#: lib/libdevmapper.c:699
+msgid "Requested dmcrypt performance options are not supported.\n"
+msgstr "Pyydetyt dmcrypt-suorituskykyvalitsimet eivät ole tuettuja.\n"
+
+# Entropy viittaa tässä ilmeisesti tiivistettävän tekstin satunnaisuuteen. Mitä satunnaisempi se on, sitä vähemmän sitä voi tiivistää.
+#: lib/random.c:76
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Järjestelmässä ei ole satunnaisuutta taltioavainta tuotettaessa.\n"
+"Siirrä hiirtä tai kirjoita jotain tekstiä toiseen ikkunaan joidenkin satunnaistapahtumien keräämiseksi.\n"
+
+#: lib/random.c:80
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Avainta tuotetaan (%d%% valmis).\n"
+
+#: lib/random.c:166
+msgid "Running in FIPS mode.\n"
+msgstr "Suoritetaan FIPS-tilassa.\n"
+
+#: lib/random.c:172
+msgid "Fatal error during RNG initialisation.\n"
+msgstr "Kohtalokas virhe RNG-alustuksen aikana.\n"
+
+#: lib/random.c:209
+msgid "Unknown RNG quality requested.\n"
+msgstr "Tuntematonta RNG-laatua pyydetty.\n"
+
+#: lib/random.c:214
+#, c-format
+msgid "Error %d reading from RNG: %s\n"
+msgstr "Virhe %d luettaessa kohteesta RNG: %s\n"
+
+#: lib/setup.c:200
+msgid "Cannot initialize crypto RNG backend.\n"
+msgstr "RNG-salaustaustaohjelman alustus epäonnistui.\n"
+
+#: lib/setup.c:206
+msgid "Cannot initialize crypto backend.\n"
+msgstr "Salaustaustaohjelman alustus epäonnistui.\n"
+
+#: lib/setup.c:237 lib/setup.c:1193 lib/verity/verity.c:123
+#, c-format
+msgid "Hash algorithm %s not supported.\n"
+msgstr "Tiivistealgoritmia %s ei tueta.\n"
+
+#: lib/setup.c:240 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s).\n"
+msgstr "Avainkäsittelyvirhe (käytetään tiivistealgoritmia %s).\n"
+
+#: lib/setup.c:285
+msgid "Cannot determine device type. Incompatible activation of device?\n"
+msgstr "Laitetyypin määritteleminen epäonnistui. Laitteen yhteensopimaton aktivointi?\n"
+
+#: lib/setup.c:289 lib/setup.c:1546
+msgid "This operation is supported only for LUKS device.\n"
+msgstr "Tätä toimintoa tuetaan vain LUKS-laitteelle.\n"
+
+#: lib/setup.c:321
+msgid "All key slots full.\n"
+msgstr "Kaikki avainvälit ovat täynnä.\n"
+
+#: lib/setup.c:328
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d.\n"
+msgstr "Avainväli %d on virheellinen, valitse väliltä 0 ... %d.\n"
+
+#: lib/setup.c:334
+#, c-format
+msgid "Key slot %d is full, please select another one.\n"
+msgstr "Avainväli %d on täynnä, valitse joku toinen.\n"
+
+#: lib/setup.c:473
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Kirjoita salasanalause kohteelle %s: "
+
+#: lib/setup.c:654
+#, c-format
+msgid "Header detected but device %s is too small.\n"
+msgstr "Otsake havaittu, mutta laite %s on liian pieni.\n"
+
+#: lib/setup.c:670 lib/setup.c:1429
+msgid "This operation is not supported for this device type.\n"
+msgstr "Tätä toimintoa ei tueta tälle laitetyypille.\n"
+
+#: lib/setup.c:909 lib/setup.c:1382 lib/setup.c:2273
+#, c-format
+msgid "Device %s is not active.\n"
+msgstr "Laite %s ei ole aktiivinen.\n"
+
+#: lib/setup.c:926
+#, c-format
+msgid "Underlying device for crypt device %s disappeared.\n"
+msgstr "Salauslaitteen %s perustana oleva laite hävisi.\n"
+
+#: lib/setup.c:995
+msgid "Invalid plain crypt parameters.\n"
+msgstr "Virheelliset tavalliset salausparametrit.\n"
+
+#: lib/setup.c:1000 lib/setup.c:1120
+msgid "Invalid key size.\n"
+msgstr "Virheellinen avainkoko.\n"
+
+#: lib/setup.c:1005 lib/setup.c:1125
+msgid "UUID is not supported for this crypt type.\n"
+msgstr "UUID ei ole tuettu tälle laitetyypille.\n"
+
+#: lib/setup.c:1047
+msgid "Can't format LUKS without device.\n"
+msgstr "Kohteen LUKS pohjustus ilman laitetta epäonnistui.\n"
+
+#: lib/setup.c:1090
+#, c-format
+msgid "Cannot format device %s which is still in use.\n"
+msgstr "Laitteen %s pohjustus epäonnistui, koska se on yhä käytössä.\n"
+
+#: lib/setup.c:1093
+#, c-format
+msgid "Cannot format device %s, permission denied.\n"
+msgstr "Laitteen %s pohjustus epäonnistui, koska pääsy laitteeseen on kielletty.\n"
+
+#: lib/setup.c:1097
+#, c-format
+msgid "Cannot wipe header on device %s.\n"
+msgstr "Otsakkeen pyyhkiminen pois laitteesta %s epäonnistui.\n"
+
+#: lib/setup.c:1115
+msgid "Can't format LOOPAES without device.\n"
+msgstr "Kohteen LOOPAES pohjustus ilman laitetta epäonnistui.\n"
+
+#: lib/setup.c:1153
+msgid "Can't format VERITY without device.\n"
+msgstr "Kohteen VERITY pohjustus ilman laitetta epäonnistui.\n"
+
+#: lib/setup.c:1161 lib/verity/verity.c:106
+#, c-format
+msgid "Unsupported VERITY hash type %d.\n"
+msgstr "Tukematon VERITY-tiivistetyyppi %d.\n"
+
+#: lib/setup.c:1167 lib/verity/verity.c:114
+msgid "Unsupported VERITY block size.\n"
+msgstr "Tukematon VERITY-lohkokoko.\n"
+
+#: lib/setup.c:1172 lib/verity/verity.c:76
+msgid "Unsupported VERITY hash offset.\n"
+msgstr "Tukematon VERITY-tiivistesiirros.\n"
+
+#: lib/setup.c:1286
+#, c-format
+msgid "Unknown crypt device type %s requested.\n"
+msgstr "Tuntematon salauslaitetyyppi %s pyydetty.\n"
+
+#: lib/setup.c:1396
+msgid "Cannot resize loop device.\n"
+msgstr "Silmukkalaitteen koon muuttaminen epäonnistui.\n"
+
+#: lib/setup.c:1444
+msgid "Do you really want to change UUID of device?"
+msgstr "Haluatko todella vaihtaa laitteen UUID-tunnistetta?"
+
+#: lib/setup.c:1554
+#, c-format
+msgid "Volume %s is not active.\n"
+msgstr "Taltio %s ei ole käytössä.\n"
+
+#: lib/setup.c:1565
+#, c-format
+msgid "Volume %s is already suspended.\n"
+msgstr "Taltio %s on jo keskeytetty.\n"
+
+#: lib/setup.c:1572
+#, c-format
+msgid "Suspend is not supported for device %s.\n"
+msgstr "Keskeyttämistä ei tueta laitetyypille %s.\n"
+
+#: lib/setup.c:1574
+#, c-format
+msgid "Error during suspending device %s.\n"
+msgstr "Virhe keskeytettäessä laitetta %s.\n"
+
+#: lib/setup.c:1600 lib/setup.c:1647
+#, c-format
+msgid "Volume %s is not suspended.\n"
+msgstr "Taltiota %s ei ole keskeytetty.\n"
+
+#: lib/setup.c:1614
+#, c-format
+msgid "Resume is not supported for device %s.\n"
+msgstr "Jatkamista ei tueta laiteelle %s.\n"
+
+#: lib/setup.c:1616 lib/setup.c:1668
+#, c-format
+msgid "Error during resuming device %s.\n"
+msgstr "Virhe jatkettaessa laitteella %s.\n"
+
+#: lib/setup.c:1654 lib/setup.c:2089 lib/setup.c:2103 src/cryptsetup.c:183
+#: src/cryptsetup.c:244 src/cryptsetup.c:732 src/cryptsetup.c:1162
+msgid "Enter passphrase: "
+msgstr "Kirjoita salasanalause: "
+
+# Volume key tarkoittaa yleensä äänenvoimakkuussäädintä, ei välttämättä tässä.
+#: lib/setup.c:1716 lib/setup.c:1852
+msgid "Cannot add key slot, all slots disabled and no volume key provided.\n"
+msgstr "Avainvälin lisäys epäonnistui, kaikki välit on otettu pois käytöstä ja yhtään taltioavainta ei ole tarjottu.\n"
+
+#: lib/setup.c:1725 lib/setup.c:1858 lib/setup.c:1862
+msgid "Enter any passphrase: "
+msgstr "Kirjoita mikä tahansa salasanalause: "
+
+#: lib/setup.c:1742 lib/setup.c:1875 lib/setup.c:1879 lib/setup.c:1941
+#: src/cryptsetup.c:992 src/cryptsetup.c:1023
+msgid "Enter new passphrase for key slot: "
+msgstr "Kirjoita uusi salasanalause avainvälille: "
+
+#: lib/setup.c:1807
+#, c-format
+msgid "Key slot %d changed.\n"
+msgstr "Avaivälin %d vaihtui.\n"
+
+#: lib/setup.c:1810
+#, c-format
+msgid "Replaced with key slot %d.\n"
+msgstr "Korvattiin avainvälillä %d.\n"
+
+#: lib/setup.c:1815
+msgid "Failed to swap new key slot.\n"
+msgstr "Uuden avainvälin vaihtaminen epäonnistui.\n"
+
+#: lib/setup.c:1932 lib/setup.c:2193 lib/setup.c:2206 lib/setup.c:2348
+msgid "Volume key does not match the volume.\n"
+msgstr "Taltioavain ei täsmää taltion kanssa.\n"
+
+#: lib/setup.c:1970
+#, c-format
+msgid "Key slot %d is invalid.\n"
+msgstr "Avainväli %d on virheellinen.\n"
+
+#: lib/setup.c:1975
+#, c-format
+msgid "Key slot %d is not used.\n"
+msgstr "Avainväli %d ei ole käytössä.\n"
+
+#: lib/setup.c:2005 lib/setup.c:2077 lib/setup.c:2169
+#, c-format
+msgid "Device %s already exists.\n"
+msgstr "Laite %s on jo olemassa.\n"
+
+#: lib/setup.c:2180
+msgid "Incorrect volume key specified for plain device.\n"
+msgstr "Virheellinen taltioavain määritelty tavalliselle laitteelle.\n"
+
+#: lib/setup.c:2213
+msgid "Incorrect root hash specified for verity device.\n"
+msgstr "Virheellinen root-tiiviste määritelty verity-laitteelle.\n"
+
+#: lib/setup.c:2236
+msgid "Device type is not properly initialised.\n"
+msgstr "Laitetyyppi ei ole alustettu oikein.\n"
+
+#: lib/setup.c:2268
+#, c-format
+msgid "Device %s is still in use.\n"
+msgstr "Laite %s on yhä käytössä.\n"
+
+#: lib/setup.c:2277
+#, c-format
+msgid "Invalid device %s.\n"
+msgstr "Virheellinen laite %s.\n"
+
+#: lib/setup.c:2298
+msgid "Function not available in FIPS mode.\n"
+msgstr "Funktio ei ole käytettävissä FIPS-tilassa.\n"
+
+#: lib/setup.c:2304
+msgid "Volume key buffer too small.\n"
+msgstr "Taltioavainpuskuri on liian pieni.\n"
+
+#: lib/setup.c:2312
+msgid "Cannot retrieve volume key for plain device.\n"
+msgstr "Taltioavaimen nouto tavalliselle laitteelle epäonnistui.\n"
+
+#: lib/setup.c:2319
+#, c-format
+msgid "This operation is not supported for %s crypt device.\n"
+msgstr "Tätä toimintoa ei tueta %s-salauslaitteelle.\n"
+
+#: lib/setup.c:2515
+msgid "Dump operation is not supported for this device type.\n"
+msgstr "Dump-toimintoa ei tueta tälle laitetyypille.\n"
+
+#: lib/utils.c:244
+msgid "Cannot get process priority.\n"
+msgstr "Prosessiprioriteetin hakeminen epäonnistui.\n"
+
+#: lib/utils.c:258
+msgid "Cannot unlock memory.\n"
+msgstr "Muistin lukituksen avaus epäonnistui.\n"
+
+#: lib/utils_crypt.c:241 lib/utils_crypt.c:254 lib/utils_crypt.c:401
+#: lib/utils_crypt.c:416
+msgid "Out of memory while reading passphrase.\n"
+msgstr "Muisti loppui luettaessa salasanalausetta.\n"
+
+#: lib/utils_crypt.c:246 lib/utils_crypt.c:261
+msgid "Error reading passphrase from terminal.\n"
+msgstr "Virhe luettaessa salasanalausetta pääteikkunasta.\n"
+
+#: lib/utils_crypt.c:259
+msgid "Verify passphrase: "
+msgstr "Todenna salasanalause: "
+
+#: lib/utils_crypt.c:266
+msgid "Passphrases do not match.\n"
+msgstr "Salasanalauseet eivät täsmää.\n"
+
+#: lib/utils_crypt.c:350
+msgid "Cannot use offset with terminal input.\n"
+msgstr "Siirrososoitteen käyttö pääteikkunasyötteellä epäonnistui.\n"
+
+#: lib/utils_crypt.c:369 lib/tcrypt/tcrypt.c:467
+msgid "Failed to open key file.\n"
+msgstr "Avaintiedoston avaus epäonnistui.\n"
+
+#: lib/utils_crypt.c:378
+msgid "Failed to stat key file.\n"
+msgstr "Avaintiedoston kutsuminen stat-funktiolla epäonnistui.\n"
+
+#: lib/utils_crypt.c:386 lib/utils_crypt.c:407
+msgid "Cannot seek to requested keyfile offset.\n"
+msgstr "Pyydetyn avaintiedostosiirrososoitteen etsintä epäonnistui.\n"
+
+#: lib/utils_crypt.c:424
+msgid "Error reading passphrase.\n"
+msgstr "Virhe luettaessa salasanalausetta.\n"
+
+#: lib/utils_crypt.c:447
+msgid "Maximum keyfile size exceeded.\n"
+msgstr "Avaintiedoston enimmäiskoko ylitettiin.\n"
+
+#: lib/utils_crypt.c:452
+msgid "Cannot read requested amount of data.\n"
+msgstr "Pyydetyn tietomäärän lukeminen epäonnistui.\n"
+
+#: lib/utils_device.c:136 lib/luks1/keyencryption.c:90
+#, c-format
+msgid "Device %s doesn't exist or access denied.\n"
+msgstr "Laite %s ei ole olemassa tai pääsy siihen on kielletty.\n"
+
+#: lib/utils_device.c:430
+msgid "Cannot use a loopback device, running as non-root user.\n"
+msgstr "Silmukkalaitteen käyttö epäonnistui, suoritetaan ei-root-käyttäjänä.\n"
+
+#: lib/utils_device.c:433
+msgid "Cannot find a free loopback device.\n"
+msgstr "Vapaan silmukkalaiteen löytäminen epäonnistui.\n"
+
+#: lib/utils_device.c:440
+msgid "Attaching loopback device failed (loop device with autoclear flag is required).\n"
+msgstr "Silmukkalaitteeseen liittyminen epäonnistui (vaaditaan silmukkalaite autoclear-lipulla).\n"
+
+#: lib/utils_device.c:484
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted).\n"
+msgstr "Laitteen %s käyttö epäonnistui, koska se on jo käytössä (jo kuvattu tai liitetty).\n"
+
+#: lib/utils_device.c:488
+#, c-format
+msgid "Cannot get info about device %s.\n"
+msgstr "Tietojen hakeminen laitteesta %s epäonnistui.\n"
+
+#: lib/utils_device.c:494
+#, c-format
+msgid "Requested offset is beyond real size of device %s.\n"
+msgstr "Pyydetty siirrososoite on laitteen %s todellisen koon ulkopuolella.\n"
+
+#: lib/utils_device.c:502
+#, c-format
+msgid "Device %s has zero size.\n"
+msgstr "Laitteen %s koko on nolla.\n"
+
+#: lib/utils_device.c:513
+#, c-format
+msgid "Device %s is too small.\n"
+msgstr "Laite %s on liian pieni.\n"
+
+#: lib/luks1/keyencryption.c:37
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info).\n"
+msgstr ""
+"Dm-crypt -avainkuvausasetus laitteelle %s epäonnistui.\n"
+"Tarkista, että käyttöjärjestelmäydin tukee %s-salakirjoitusmenetelmää (lisätietoja tarkistamalla syslog).\n"
+
+#: lib/luks1/keyencryption.c:42
+msgid "Key size in XTS mode must be 256 or 512 bits.\n"
+msgstr "Avainkoon on oltava XTS-tilassa 256 tai 512 bittiä.\n"
+
+#: lib/luks1/keyencryption.c:96 lib/luks1/keymanage.c:296
+#: lib/luks1/keymanage.c:572 lib/luks1/keymanage.c:1022
+#, c-format
+msgid "Cannot write to device %s, permission denied.\n"
+msgstr "Laitteeseen %s kirjoittaminen epäonnistui, pääsy kielletty.\n"
+
+#: lib/luks1/keyencryption.c:111
+msgid "Failed to open temporary keystore device.\n"
+msgstr "Tilapäisen avainsäiliön avaaminen epäonnistui.\n"
+
+#: lib/luks1/keyencryption.c:118
+msgid "Failed to access temporary keystore device.\n"
+msgstr "Pääsy tilapäiseen avainsäiliölaitteeseen epäonnistui.\n"
+
+#: lib/luks1/keyencryption.c:191
+msgid "IO error while encrypting keyslot.\n"
+msgstr "Siirräntävirhe salattaessa avainväliä.\n"
+
+#: lib/luks1/keyencryption.c:256
+msgid "IO error while decrypting keyslot.\n"
+msgstr "Siirräntävirhe purettaessa avainvälin salausta.\n"
+
+#: lib/luks1/keymanage.c:90
+#, c-format
+msgid "Device %s is too small. (LUKS requires at least %<PRIu64> bytes.)\n"
+msgstr "Laite %s on liian pieni. (LUKS vaatii vähintään %<PRIu64> tavua.)\n"
+
+#: lib/luks1/keymanage.c:180 lib/luks1/keymanage.c:418
+#: src/cryptsetup_reencrypt.c:1131
+#, c-format
+msgid "Device %s is not a valid LUKS device.\n"
+msgstr "Laite %s ei ole kelvollinen LUKS-laite.\n"
+
+#: lib/luks1/keymanage.c:198
+#, c-format
+msgid "Requested header backup file %s already exists.\n"
+msgstr "Pyydetty otsakevarmuuskopiotiedosto %s on jo olemassa.\n"
+
+#: lib/luks1/keymanage.c:200
+#, c-format
+msgid "Cannot create header backup file %s.\n"
+msgstr "Otsakevarmuuskopiotiedoston %s luominen epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:205
+#, c-format
+msgid "Cannot write header backup file %s.\n"
+msgstr "Otsakevarmuuskopiotiedoston %s kirjoittaminen epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:239
+msgid "Backup file doesn't contain valid LUKS header.\n"
+msgstr "Varmuuskopiotiedosto ei sisällä kelvollista LUKS-otsaketta.\n"
+
+#: lib/luks1/keymanage.c:252 lib/luks1/keymanage.c:496
+#, c-format
+msgid "Cannot open header backup file %s.\n"
+msgstr "Otsakevarmuuskopiotiedoston %s avaus epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:258
+#, c-format
+msgid "Cannot read header backup file %s.\n"
+msgstr "Otsakevarmuuskopiotiedoston %s lukeminen epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:269
+msgid "Data offset or key size differs on device and backup, restore failed.\n"
+msgstr "Tietosiirrososoite tai avainkoko eroaa laitteessa ja varmuuskopiossa, palautus epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:277
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Laite %s %s%s"
+
+#: lib/luks1/keymanage.c:278
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "ei sisällä LUKS-otsaketta. Otsakkeen korvaaminen voi tuhota tietoja tuossa laitteessa."
+
+#: lib/luks1/keymanage.c:279
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "sisältää jo LUKS-otsakkeen. Otsakkeen korvaaminen tuhoaa olemassaolevat avainvälit."
+
+#: lib/luks1/keymanage.c:280
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"VAROITUS: oikealla laiteotsakkeella on eri UUID-tunniste kuin varmuuskopiolla!"
+
+#: lib/luks1/keymanage.c:299 lib/luks1/keymanage.c:535
+#: lib/luks1/keymanage.c:575 lib/tcrypt/tcrypt.c:624 lib/verity/verity.c:82
+#: lib/verity/verity.c:179 lib/verity/verity_hash.c:292
+#: lib/verity/verity_hash.c:303 lib/verity/verity_hash.c:323
+#, c-format
+msgid "Cannot open device %s.\n"
+msgstr "Laitteen %s avaus epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:329
+msgid "Non standard key size, manual repair required.\n"
+msgstr "Ei-vakio avainkoko, manuaalinen korjaus pyydetty.\n"
+
+#: lib/luks1/keymanage.c:334
+msgid "Non standard keyslots alignment, manual repair required.\n"
+msgstr "Ei-vakiot avainvälitasaukset, manuaalinen korjaus pyydetty.\n"
+
+#: lib/luks1/keymanage.c:340
+msgid "Repairing keyslots.\n"
+msgstr "Korjataan avainvälit.\n"
+
+#: lib/luks1/keymanage.c:351
+msgid "Repair failed."
+msgstr "Korjaus epäonnistui."
+
+#: lib/luks1/keymanage.c:363
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u).\n"
+msgstr "Avainväli %i: siirrososoite korjattu (%u -> %u).\n"
+
+#: lib/luks1/keymanage.c:371
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u).\n"
+msgstr "Avainväli %i: raidat korjattu (%u -> %u).\n"
+
+#: lib/luks1/keymanage.c:380
+#, c-format
+msgid "Keyslot %i: bogus partition signature.\n"
+msgstr "Avainväli %i: valeosiotunniste.\n"
+
+#: lib/luks1/keymanage.c:385
+#, c-format
+msgid "Keyslot %i: salt wiped.\n"
+msgstr "Avainväli %i: satunnaisarvosiemen tuhottu.\n"
+
+#: lib/luks1/keymanage.c:396
+msgid "Writing LUKS header to disk.\n"
+msgstr "Kirjoitetaan LUKS-otsake levylle.\n"
+
+#: lib/luks1/keymanage.c:421
+#, c-format
+msgid "Unsupported LUKS version %d.\n"
+msgstr "Tukematon LUKS-versio %d.\n"
+
+#: lib/luks1/keymanage.c:427 lib/luks1/keymanage.c:661
+#, c-format
+msgid "Requested LUKS hash %s is not supported.\n"
+msgstr "Pyydetty LUKS-tiiviste %s ei ole tuettu.\n"
+
+#: lib/luks1/keymanage.c:442
+#, c-format
+msgid "LUKS keyslot %u is invalid.\n"
+msgstr "LUKS-avainväli %u on virheellinen.\n"
+
+#: lib/luks1/keymanage.c:456 src/cryptsetup.c:664
+msgid "No known problems detected for LUKS header.\n"
+msgstr "Tuntemattomat pulmat havaittu LUKS-otsakkeelle.\n"
+
+#: lib/luks1/keymanage.c:596
+#, c-format
+msgid "Error during update of LUKS header on device %s.\n"
+msgstr "Virhe LUKS-otsakkeen päivityksen aikana laitteessa %s.\n"
+
+#: lib/luks1/keymanage.c:603
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s.\n"
+msgstr "Virhe luettaessa uudelleen LUKS-otsaketta päivityksen jälkeen laitteessa %s.\n"
+
+#: lib/luks1/keymanage.c:654
+#, c-format
+msgid "Data offset for detached LUKS header must be either 0 or higher than header size (%d sectors).\n"
+msgstr "Tietosiirrososoitteen irrotetulle LUKS-otsakkeelle on oltava joko 0 tai suurempi kuin otsakekoko (%d sektoria).\n"
+
+#: lib/luks1/keymanage.c:666 lib/luks1/keymanage.c:757
+msgid "Wrong LUKS UUID format provided.\n"
+msgstr "Väärä LUKS UUID-muoto tarjottu.\n"
+
+#: lib/luks1/keymanage.c:695
+msgid "Cannot create LUKS header: reading random salt failed.\n"
+msgstr "LUKS-otsakkeen luominen epäonnistui: satunnaisarvosiemenen lukeminen epäonnistui.\n"
+
+#: lib/luks1/keymanage.c:702 lib/luks1/keymanage.c:798
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s).\n"
+msgstr "Ei ole yhteensopiva PBKDF2-valitsimien kanssa (käytetään tiivitstealgoritmia %s).\n"
+
+#: lib/luks1/keymanage.c:717
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s).\n"
+msgstr "LUKS-otsakkeen luominen epäonnistui: otsaketiiviste epäonnistui (käytettäen tiivistettä %s).\n"
+
+#: lib/luks1/keymanage.c:782
+#, c-format
+msgid "Key slot %d active, purge first.\n"
+msgstr "Avainväli %d aktiivinen, puhdista ensimmäinen.\n"
+
+#: lib/luks1/keymanage.c:788
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?\n"
+msgstr "Avainvälin %d materiaali sisältää liian vähän raitoja. Otsaketta on käsitelty?\n"
+
+#: lib/luks1/keymanage.c:955
+#, c-format
+msgid "Key slot %d unlocked.\n"
+msgstr "Avaivälin %d lukitus avattu.\n"
+
+#: lib/luks1/keymanage.c:990 src/cryptsetup.c:858
+#: src/cryptsetup_reencrypt.c:1020 src/cryptsetup_reencrypt.c:1057
+msgid "No key available with this passphrase.\n"
+msgstr "Tälle salasanalauseelle ei ole saatavissa avainta.\n"
+
+#: lib/luks1/keymanage.c:1008
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d.\n"
+msgstr "Avainväli %d on virheellinen, valitse avainväli välillä 0 ... %d.\n"
+
+#: lib/luks1/keymanage.c:1026
+#, c-format
+msgid "Cannot wipe device %s.\n"
+msgstr "Laitteen %s pyyhkiminen tyhjäksi epäonnistui.\n"
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile.\n"
+msgstr "Havaittu vielä tukematon GPG-salausavaintiedosto.\n"
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Käytä gpg --decrypt <AVAINTIEDOSTO> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected.\n"
+msgstr "Yhteensopimaton loop-AES -avaintiedosto havaittu.\n"
+
+#: lib/loopaes/loopaes.c:244
+msgid "Kernel doesn't support loop-AES compatible mapping.\n"
+msgstr "Käyttöjärjestelmäydin ei tule loop-AES -yhteensopivaa kuvausta.\n"
+
+#: lib/tcrypt/tcrypt.c:475
+#, c-format
+msgid "Error reading keyfile %s.\n"
+msgstr "Virhe luettaessa avaintiedostoa %s.\n"
+
+#: lib/tcrypt/tcrypt.c:513
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%d) exceeded.\n"
+msgstr "TCRYPT-salasanalauseen enimmäispituus (%d) ylitettiin.\n"
+
+#: lib/tcrypt/tcrypt.c:543
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping.\n"
+msgstr "PBKDF2-tiivistealgoritmi %s ei ole käytettävissä, ohitetaan.\n"
+
+#: lib/tcrypt/tcrypt.c:561 src/cryptsetup.c:617
+msgid "Required kernel crypto interface not available.\n"
+msgstr "Pyydetty ydinsalauskäyttöliittymä ei ole käytettävissä.\n"
+
+#: lib/tcrypt/tcrypt.c:563 src/cryptsetup.c:619
+msgid "Ensure you have algif_skcipher kernel module loaded.\n"
+msgstr "Varmista, että algif_skcipher-käyttöjärjestelmäydinmoduuli on ladattu.\n"
+
+#: lib/tcrypt/tcrypt.c:707
+#, c-format
+msgid "Activation is not supported for %d sector size.\n"
+msgstr "Aktivointia ei tueta sektorikoolle %d.\n"
+
+#: lib/tcrypt/tcrypt.c:713
+msgid "Kernel doesn't support activation for this TCRYPT legacy mode.\n"
+msgstr "Käyttöjärjestelmäydin ei tue aktivointia tälle TCRYPT-perinnetilassa.\n"
+
+#: lib/tcrypt/tcrypt.c:744
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s.\n"
+msgstr "Aktivoidaan TCRYPT-järjestelmäsalaus osiolle %s.\n"
+
+#: lib/tcrypt/tcrypt.c:810
+msgid "Kernel doesn't support TCRYPT compatible mapping.\n"
+msgstr "Käyttöjärjestelmäydin ei tue TCRYPT -yhteensopivaa kuvausta.\n"
+
+#: lib/tcrypt/tcrypt.c:1024
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Tätä toimintoa ei tueta ilman TCRYPT-otsakelatausta."
+
+#: lib/verity/verity.c:70 lib/verity/verity.c:172
+#, c-format
+msgid "Verity device %s doesn't use on-disk header.\n"
+msgstr "Verity-laite %s ei käytä paikallista levyotsaketta.\n"
+
+#: lib/verity/verity.c:94
+#, c-format
+msgid "Device %s is not a valid VERITY device.\n"
+msgstr "Laite %s ei ole kelvollinen VERITY-laite.\n"
+
+#: lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY version %d.\n"
+msgstr "Tukematon VERITY-versio %d.\n"
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted.\n"
+msgstr "VERITY-otsake rikkinäinen.\n"
+
+#: lib/verity/verity.c:166
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s.\n"
+msgstr "Väärä VERITY UUID-muoto tarjottu laitteessa %s.\n"
+
+#: lib/verity/verity.c:196
+#, c-format
+msgid "Error during update of verity header on device %s.\n"
+msgstr "Virhe verity-otsakkeen päivityksen aikana laitteessa %s.\n"
+
+#: lib/verity/verity.c:276
+msgid "Kernel doesn't support dm-verity mapping.\n"
+msgstr "Käyttöjärjestelmäydin ei tule dm-verity -yhteensopivaa kuvausta.\n"
+
+#: lib/verity/verity.c:287
+msgid "Verity device detected corruption after activation.\n"
+msgstr "Verity-laite havaitsi rikkoutumisen aktivoinnin jälkeen.\n"
+
+#: lib/verity/verity_hash.c:59
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>.\n"
+msgstr "Vapaa-aluetta ei ole nollattu sijainnissa %<PRIu64>.\n"
+
+#: lib/verity/verity_hash.c:121 lib/verity/verity_hash.c:249
+#: lib/verity/verity_hash.c:277 lib/verity/verity_hash.c:284
+msgid "Device offset overflow.\n"
+msgstr "Laitesiirrososoitteen ylivuoto.\n"
+
+#: lib/verity/verity_hash.c:161
+#, c-format
+msgid "Verification failed at position %<PRIu64>.\n"
+msgstr "Todennus epäonnistui sijainnissa %<PRIu64>.\n"
+
+#: lib/verity/verity_hash.c:235
+msgid "Invalid size parameters for verity device.\n"
+msgstr "Virheelliset kokoparametrit verity-laitteelle.\n"
+
+#: lib/verity/verity_hash.c:266
+msgid "Too many tree levels for verity volume.\n"
+msgstr "Verity-taltiolla liian monta puutasoa.\n"
+
+#: lib/verity/verity_hash.c:354
+msgid "Verification of data area failed.\n"
+msgstr "Data-alueen todentaminen epäonnistui.\n"
+
+#: lib/verity/verity_hash.c:359
+msgid "Verification of root hash failed.\n"
+msgstr "Root-tiivisteen todentaminen epäonnistui.\n"
+
+#: lib/verity/verity_hash.c:365
+msgid "Input/output error while creating hash area.\n"
+msgstr "Syöte/tulostevirhe luotaessa tiivistealuetta.\n"
+
+#: lib/verity/verity_hash.c:367
+msgid "Creation of hash area failed.\n"
+msgstr "Tiivistealueen luominen epäonnistui.\n"
+
+#: lib/verity/verity_hash.c:414
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u).\n"
+msgstr "VAROITUS: Käyttöjärjestelmäydin ei voi aktivoida laitetta, jos lohkokoko ylittää sivukoon (%u).\n"
+
+#: src/cryptsetup.c:91
+msgid "Can't do passphrase verification on non-tty inputs.\n"
+msgstr "Salasanalauseiden todennus epäonnistui ei-tty-syötteissä.\n"
+
+#: src/cryptsetup.c:132 src/cryptsetup.c:560 src/cryptsetup.c:707
+#: src/cryptsetup_reencrypt.c:523 src/cryptsetup_reencrypt.c:577
+msgid "No known cipher specification pattern detected.\n"
+msgstr "Havaittu tuntematon salakirjoitusmenetelmämäärittelymalli.\n"
+
+#: src/cryptsetup.c:140
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "VAROITUS: Parametri --hash ohitetaan tavallisessa tilassa kun avaintiedosto on määritelty.\n"
+
+#: src/cryptsetup.c:148
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "VAROITUS: Valitsin --keyfile-size ohitetaan , lukukoko on sama kuin salausavaimen koko.\n"
+
+#: src/cryptsetup.c:214
+msgid "Option --key-file is required.\n"
+msgstr "Vaaditaan valitsin --key-file.\n"
+
+#: src/cryptsetup.c:263
+msgid "No device header detected with this passphrase.\n"
+msgstr "Tälle salasanalauseelle ei ole saatavissa laiteotsaketta.\n"
+
+#: src/cryptsetup.c:323 src/cryptsetup.c:1151
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Otsakevedos taltioavaimella on arkaluonteista tietoa,\n"
+"joka sallii pääsyn salatulle osiolle ilman salasanaa.\n"
+"Tämä vedos pitäisi aina tallentaa salattuna turvallisessa paikasssa."
+
+#: src/cryptsetup.c:513
+msgid "Result of benchmark is not reliable.\n"
+msgstr "Suorituskykytestin tulos ei ole luotettava.\n"
+
+#: src/cryptsetup.c:554
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Testit käyttävät vain muistia ylimalkaan (ei tallennussiirtos).\n"
+
+#: src/cryptsetup.c:579 src/cryptsetup.c:601
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritmi | Avain | Salaus | Salauksen purku\n"
+
+#: src/cryptsetup.c:583
+#, c-format
+msgid "Cipher %s is not available.\n"
+msgstr "Salaus %s ei ole käytettävissä.\n"
+
+#: src/cryptsetup.c:610
+msgid "N/A"
+msgstr "Ei käytössä"
+
+#: src/cryptsetup.c:635
+#, c-format
+msgid "Cannot read keyfile %s.\n"
+msgstr "Avaintiedoston %s lukeminen epäonnistui.\n"
+
+#: src/cryptsetup.c:639
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s.\n"
+msgstr "Ei voida lukea %d tavua avaintiedostosta %s.\n"
+
+#: src/cryptsetup.c:668
+msgid "Really try to repair LUKS device header?"
+msgstr "Yritetäänkö todella korjata LUKS-laiteotsake?"
+
+#: src/cryptsetup.c:693
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Tämä korvaa tiedot kohteella %s peruuttamattomasti."
+
+#: src/cryptsetup.c:695
+msgid "memory allocation error in action_luksFormat"
+msgstr "muistivarausvirhe kohteessa action_luksFormat"
+
+#: src/cryptsetup.c:717
+#, c-format
+msgid "Cannot use %s as on-disk header.\n"
+msgstr "Kohteen %s käyttö paikallisena levyotsakkeena epäonnistui.\n"
+
+#: src/cryptsetup.c:784
+msgid "Reduced data offset is allowed only for detached LUKS header.\n"
+msgstr "Pienennetty tietosiirrososoite sallitaan vain irrotetulle LUKS-otsakkeelle.\n"
+
+#: src/cryptsetup.c:881 src/cryptsetup.c:937
+#, c-format
+msgid "Key slot %d selected for deletion.\n"
+msgstr "Avainväli %d valittu poistoa varten.\n"
+
+#: src/cryptsetup.c:884
+#, c-format
+msgid "Key %d not active. Can't wipe.\n"
+msgstr "Avain %d ei ole käytössä. Ei voida pyyhkiä pois.\n"
+
+#: src/cryptsetup.c:892 src/cryptsetup.c:940
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Tämä on viimeinen avainväli. Laite tulee käyttökelvottomaksi tämän avaimen poistamisen jälkeen."
+
+#: src/cryptsetup.c:893
+msgid "Enter any remaining passphrase: "
+msgstr "Kirjoita mikä tahansa jäljellä oleva salasanalause: "
+
+#: src/cryptsetup.c:921
+msgid "Enter passphrase to be deleted: "
+msgstr "Kirjoita poistettava salasanalause: "
+
+#: src/cryptsetup.c:1008 src/cryptsetup_reencrypt.c:1095
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Kirjoita mikä tahansa olemassa oleva salasanalause: "
+
+#: src/cryptsetup.c:1063
+msgid "Enter passphrase to be changed: "
+msgstr "Kirjoita vaihdettava salasanalause: "
+
+#: src/cryptsetup.c:1077 src/cryptsetup_reencrypt.c:1080
+msgid "Enter new passphrase: "
+msgstr "Kirjoita uusi salasanalause: "
+
+#: src/cryptsetup.c:1101
+msgid "Only one device argument for isLuks operation is supported.\n"
+msgstr "Tuetaan vain yhtä laiteargumenttia isLuks-toiminnolle.\n"
+
+#: src/cryptsetup.c:1257 src/cryptsetup.c:1278
+msgid "Option --header-backup-file is required.\n"
+msgstr "Vaaditaan valitsin --header-backup-file.\n"
+
+#: src/cryptsetup.c:1315
+#, c-format
+msgid "Unrecognized metadata device type %s.\n"
+msgstr "Tunnistamaton metatietolaitetyyppi %s.\n"
+
+#: src/cryptsetup.c:1318
+msgid "Command requires device and mapped name as arguments.\n"
+msgstr "Komento vaatii laitteen ja kuvausnimen argumenttina.\n"
+
+#: src/cryptsetup.c:1337
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Tämä toiminto poistaa kaikki avainvälit laitteesta %s.\n"
+"Laite tulee käyttökelvottomaksi tämän toiminnon jälkeen."
+
+#: src/cryptsetup.c:1371
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<laite> [--type <tyyppi>] [<nimi>]"
+
+#: src/cryptsetup.c:1371
+msgid "open device as mapping <name>"
+msgstr "avaa laite kuvauksena <nimi>"
+
+#: src/cryptsetup.c:1372 src/cryptsetup.c:1373 src/cryptsetup.c:1374
+#: src/cryptsetup.c:1375 src/veritysetup.c:311 src/veritysetup.c:312
+msgid "<name>"
+msgstr "<nimi>"
+
+#: src/cryptsetup.c:1372
+msgid "close device (remove mapping)"
+msgstr "sulje laite (poista kuvaus)"
+
+#: src/cryptsetup.c:1373
+msgid "resize active device"
+msgstr "muuta käytössä olevan laitteen kokoa"
+
+#: src/cryptsetup.c:1374
+msgid "show device status"
+msgstr "näytä laitetila"
+
+#: src/cryptsetup.c:1375
+msgid "benchmark cipher"
+msgstr "koestussalaus"
+
+#: src/cryptsetup.c:1376 src/cryptsetup.c:1377 src/cryptsetup.c:1383
+#: src/cryptsetup.c:1384 src/cryptsetup.c:1385 src/cryptsetup.c:1386
+#: src/cryptsetup.c:1387 src/cryptsetup.c:1388 src/cryptsetup.c:1389
+#: src/cryptsetup.c:1390
+msgid "<device>"
+msgstr "<laite>"
+
+#: src/cryptsetup.c:1376
+msgid "try to repair on-disk metadata"
+msgstr "yritä korjata levyn sisäiset metatiedot"
+
+#: src/cryptsetup.c:1377
+msgid "erase all keyslots (remove encryption key)"
+msgstr "poista kaikki avainvälit (poista salausavain)"
+
+#: src/cryptsetup.c:1378 src/cryptsetup.c:1379
+msgid "<device> [<new key file>]"
+msgstr "<laite> [<uusi avaintiedosto>]"
+
+#: src/cryptsetup.c:1378
+msgid "formats a LUKS device"
+msgstr "pohjustaa LUKS-laitteen"
+
+#: src/cryptsetup.c:1379
+msgid "add key to LUKS device"
+msgstr "lisää avain LUKS-laitteeseen"
+
+#: src/cryptsetup.c:1380 src/cryptsetup.c:1381
+msgid "<device> [<key file>]"
+msgstr "<laite> [<avaintiedosto>]"
+
+#: src/cryptsetup.c:1380
+msgid "removes supplied key or key file from LUKS device"
+msgstr "poistaa tarjotun avaimen tai avaintiedoston LUKS-laitteesta"
+
+#: src/cryptsetup.c:1381
+msgid "changes supplied key or key file of LUKS device"
+msgstr "vaihtaa LUKS-laitteen tarjotun avaimen tai avaintiedoston"
+
+#: src/cryptsetup.c:1382
+msgid "<device> <key slot>"
+msgstr "<laite> <avainväli>"
+
+#: src/cryptsetup.c:1382
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "pyyhkäisee pois avaimen numerolla <avainväli> LUKS-laitteesta"
+
+#: src/cryptsetup.c:1383
+msgid "print UUID of LUKS device"
+msgstr "tulostaa LUKS-laitteen UUID-tunnuksen"
+
+#: src/cryptsetup.c:1384
+msgid "tests <device> for LUKS partition header"
+msgstr "testaa <laite> LUKS-osio-otsakkeesta"
+
+#: src/cryptsetup.c:1385
+msgid "dump LUKS partition information"
+msgstr "vedosta LUKS-osiotiedot"
+
+#: src/cryptsetup.c:1386
+msgid "dump TCRYPT device information"
+msgstr "vedosta TCRYPT-laitetiedot"
+
+#: src/cryptsetup.c:1387
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)."
+msgstr "Keskeytä LUKS-laite ja pyyhi pois avain (kaikki siirräntäliitännät jäädytetään)."
+
+#: src/cryptsetup.c:1388
+msgid "Resume suspended LUKS device."
+msgstr "Aloita uudelleen pysäytetty LUKS-laite."
+
+#: src/cryptsetup.c:1389
+msgid "Backup LUKS device header and keyslots"
+msgstr "Varmuuskopioi LUKS-laiteotsake ja avainvälit"
+
+#: src/cryptsetup.c:1390
+msgid "Restore LUKS device header and keyslots"
+msgstr "Palauta LUKS-laiteotsake ja avainvälit"
+
+#: src/cryptsetup.c:1407 src/veritysetup.c:328
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<toiminto> on yksi seuraavista:\n"
+
+#: src/cryptsetup.c:1413
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+msgstr ""
+"\n"
+"Voit myös käyttää vanhaa <toiminto>-syntaksialiasta:\n"
+"\topen: luo (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: poista (plainClose), luksClose, loopaesClose, tcryptClose\n"
+
+#: src/cryptsetup.c:1417
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nimi> on laite, joka luodaan kohteen %s alaisena\n"
+"<laite> on salaussuojattu laite\n"
+"<avainväli> on LUKS-avainväli muokattavaksi\n"
+"<avaintiedosto> valinnainen avaintiedosto uudelle avaimelle luksAddKey-toimintoa varten\n"
+
+#: src/cryptsetup.c:1424
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF2 iteration time for LUKS: %d (ms)\n"
+msgstr ""
+"\n"
+"Käännetyn avaintiedoston ja salasanan oletusparametrit:\n"
+"\tAvaintiedoston enimmäiskoko: %d kilobittiä, vuorovaikutteisen\n"
+"\tsalasanalauseen enimmäispituus %d (merkkiä)\n"
+"PBKDF2-iteroinnin enimmäisaika LUKS-avainvälille: %d (millisekuntia)\n"
+
+#: src/cryptsetup.c:1431
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS1: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Käännetyn laitesalakirjoitusmenetelmän oletusparametrit:\n"
+"\tloop-AES: %s, Avain %d bittiä\n"
+"\tplain-tyyppi: %s, Avain: %d bittiä, Salasanatiivistys: %s\n"
+"\tLUKS1: %s, Avain: %d bittiä, LUKS-otsaketiivistys: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:1448 src/veritysetup.c:460
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: vaatii %s argumentteina"
+
+#: src/cryptsetup.c:1481 src/veritysetup.c:368 src/cryptsetup_reencrypt.c:1274
+msgid "Show this help message"
+msgstr "Näytä tämä opastesanoma"
+
+#: src/cryptsetup.c:1482 src/veritysetup.c:369 src/cryptsetup_reencrypt.c:1275
+msgid "Display brief usage"
+msgstr "Näytä lyhyt käyttöopaste"
+
+#: src/cryptsetup.c:1486 src/veritysetup.c:373 src/cryptsetup_reencrypt.c:1279
+msgid "Help options:"
+msgstr "Opastevalitsimet:"
+
+#: src/cryptsetup.c:1487 src/veritysetup.c:374 src/cryptsetup_reencrypt.c:1280
+msgid "Print package version"
+msgstr "Tulosta pakkausversio"
+
+#: src/cryptsetup.c:1488 src/veritysetup.c:375 src/cryptsetup_reencrypt.c:1281
+msgid "Shows more detailed error messages"
+msgstr "Näyttää yksityiskohtaisemmat virheilmoitukset"
+
+#: src/cryptsetup.c:1489 src/veritysetup.c:376 src/cryptsetup_reencrypt.c:1282
+msgid "Show debug messages"
+msgstr "Näytä vianjäljityssanomat"
+
+#: src/cryptsetup.c:1490 src/cryptsetup_reencrypt.c:1284
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "Salakirjoitusmenetelmä, jota käytetään salaamaan levy (katso /proc/crypto)"
+
+#: src/cryptsetup.c:1491 src/cryptsetup_reencrypt.c:1286
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "Tiivisteavain, jota käytetään salausavaimen luomiseen salasanalauseesta"
+
+#: src/cryptsetup.c:1492
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Todentaa salasanalauseen kysymällä kahdesti"
+
+#: src/cryptsetup.c:1493 src/cryptsetup_reencrypt.c:1288
+msgid "Read the key from a file."
+msgstr "Lue avain tiedostosta."
+
+#: src/cryptsetup.c:1494
+msgid "Read the volume (master) key from file."
+msgstr "Lue taltion (pää)avain tiedostosta."
+
+#: src/cryptsetup.c:1495
+msgid "Dump volume (master) key instead of keyslots info."
+msgstr "Vedosta taltion (pää)avain eikä avainvälien tiedot."
+
+#: src/cryptsetup.c:1496 src/cryptsetup_reencrypt.c:1285
+msgid "The size of the encryption key"
+msgstr "Salausavaimen koko"
+
+#: src/cryptsetup.c:1496 src/cryptsetup_reencrypt.c:1285
+msgid "BITS"
+msgstr "BITTIÄ"
+
+#: src/cryptsetup.c:1497 src/cryptsetup_reencrypt.c:1299
+msgid "Limits the read from keyfile"
+msgstr "Avaintiedostosta luettavat rajat"
+
+#: src/cryptsetup.c:1497 src/cryptsetup.c:1498 src/cryptsetup.c:1499
+#: src/cryptsetup.c:1500 src/veritysetup.c:379 src/veritysetup.c:380
+#: src/veritysetup.c:382 src/cryptsetup_reencrypt.c:1298
+#: src/cryptsetup_reencrypt.c:1299 src/cryptsetup_reencrypt.c:1300
+#: src/cryptsetup_reencrypt.c:1301
+msgid "bytes"
+msgstr "tavua"
+
+#: src/cryptsetup.c:1498 src/cryptsetup_reencrypt.c:1298
+msgid "Number of bytes to skip in keyfile"
+msgstr "Avaintiedostossa ohitettavien tavujen määrä"
+
+#: src/cryptsetup.c:1499
+msgid "Limits the read from newly added keyfile"
+msgstr "Äskettäin lisätystä avaintiedostosta luetut rajat"
+
+#: src/cryptsetup.c:1500
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "Ohitettu tavumäärä äskettäin lisätyssä avaintiedostossa"
+
+#: src/cryptsetup.c:1501
+msgid "Slot number for new key (default is first free)"
+msgstr "Välinumero uudelle avaimelle (oletus on ensimmäinen vapaa)"
+
+#: src/cryptsetup.c:1502
+msgid "The size of the device"
+msgstr "Laitteen koko"
+
+#: src/cryptsetup.c:1502 src/cryptsetup.c:1503 src/cryptsetup.c:1504
+#: src/cryptsetup.c:1510
+msgid "SECTORS"
+msgstr "SEKTORIA"
+
+#: src/cryptsetup.c:1503
+msgid "The start offset in the backend device"
+msgstr "Alkusiirrososoite taustalaitteessa"
+
+#: src/cryptsetup.c:1504
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Kuinka monta salaustietojen sektoria ohitetaan alussa"
+
+#: src/cryptsetup.c:1505
+msgid "Create a readonly mapping"
+msgstr "Luo kirjoitussuojattu kuvaus"
+
+#: src/cryptsetup.c:1506 src/cryptsetup_reencrypt.c:1289
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "PBKDF2-iterointiaika kohteelle LUKS (millisekunneissa)"
+
+#: src/cryptsetup.c:1506 src/cryptsetup_reencrypt.c:1289
+msgid "msecs"
+msgstr "ms"
+
+#: src/cryptsetup.c:1507 src/cryptsetup_reencrypt.c:1290
+msgid "Do not ask for confirmation"
+msgstr "Älä pyydä vahvistusta"
+
+#: src/cryptsetup.c:1508
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Aikakatkaisu vuorovaikutteiselle salasanalausekyselylle (sekunteina)"
+
+#: src/cryptsetup.c:1508
+msgid "secs"
+msgstr "s"
+
+#: src/cryptsetup.c:1509 src/cryptsetup_reencrypt.c:1291
+msgid "How often the input of the passphrase can be retried"
+msgstr "Kuinka usein salasanasyötettä voidaan yrittää uudelleen"
+
+#: src/cryptsetup.c:1510
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Tasaa tietosisältö osoitteessa <n> sektorirajoihin - kohdetta luksFormat varten"
+
+#: src/cryptsetup.c:1511
+msgid "File with LUKS header and keyslots backup."
+msgstr "Tiedosto LUKS-otsakkeella ja avainvälien varmuuskopiolla."
+
+#: src/cryptsetup.c:1512 src/cryptsetup_reencrypt.c:1292
+msgid "Use /dev/random for generating volume key."
+msgstr "Käytä /dev/random taltioavaimen synnyttämiseen."
+
+#: src/cryptsetup.c:1513 src/cryptsetup_reencrypt.c:1293
+msgid "Use /dev/urandom for generating volume key."
+msgstr "Käytä /dev/urandom taltioavaimen synnyttämiseen."
+
+#: src/cryptsetup.c:1514
+msgid "Share device with another non-overlapping crypt segment."
+msgstr "Jaa laite toisen ei-päällekkäisen salaussegmentin kanssa."
+
+#: src/cryptsetup.c:1515 src/veritysetup.c:385
+msgid "UUID for device to use."
+msgstr "UUID laitteelle käytettäväksi."
+
+#: src/cryptsetup.c:1516
+msgid "Allow discards (aka TRIM) requests for device."
+msgstr "Salli hylkäys(lempinimeltään TRIM)-pyynnöt laitteelle."
+
+#: src/cryptsetup.c:1517
+msgid "Device or file with separated LUKS header."
+msgstr "Laite tai tiedosto erillisellä LUKS-otsakkeella."
+
+#: src/cryptsetup.c:1518
+msgid "Do not activate device, just check passphrase."
+msgstr "Älä aktivoi laitetta, tarkista vain salasanalauseke."
+
+#: src/cryptsetup.c:1519
+msgid "Use hidden header (hidden TCRYPT device)."
+msgstr "Käytä piilotettua otsaketta (piilotettu TCRYPT-laite)."
+
+#: src/cryptsetup.c:1520
+msgid "Device is system TCRYPT drive (with bootloader)."
+msgstr "Laite on järjestelmä-TCRYPT-levyasema (alkulatausohjelmalla)."
+
+#: src/cryptsetup.c:1521
+msgid "Use backup (secondary) TCRYPT header."
+msgstr "Käytä (toissijaista) TCRYPT-varmuuskopio-otsaketta."
+
+#: src/cryptsetup.c:1522
+msgid "Scan also for VeraCrypt compatible device."
+msgstr "Tutkinta myös VeraCrypt-yhteensopivalle laitteelle."
+
+#: src/cryptsetup.c:1523
+msgid "Type of device metadata: luks, plain, loopaes, tcrypt."
+msgstr "Laitemetatietojen tyyppi: luks, plain, loopaes, tcrypt."
+
+#: src/cryptsetup.c:1524
+msgid "Disable password quality check (if enabled)."
+msgstr "Ota pois käytöstä salasanan laatutarkistus (jos käytössä)."
+
+#: src/cryptsetup.c:1525
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option."
+msgstr "Käytä dm-crypt same_cpu_crypt-suorituskyky-yhteensopivuusvalitsinta."
+
+#: src/cryptsetup.c:1526
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option."
+msgstr "Käytä dm-crypt submit_from_crypt_cpus-suorituskyky-yhteensopivuusvalitsinta."
+
+#: src/cryptsetup.c:1542 src/veritysetup.c:402
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[VALITSIN...] <toiminto> <toimintokohtainen>"
+
+#: src/cryptsetup.c:1589 src/veritysetup.c:439
+msgid "Argument <action> missing."
+msgstr "Argumentti <toiminto> puuttuu."
+
+#: src/cryptsetup.c:1642 src/veritysetup.c:445
+msgid "Unknown action."
+msgstr "Tuntematon toiminto."
+
+#: src/cryptsetup.c:1652
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "Valitsin --shared sallitaan vain pelkän laitteen avaukseen.\n"
+
+#: src/cryptsetup.c:1657
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "Valitsin --allow-discards sallitaan vain open-toiminnolle.\n"
+
+#: src/cryptsetup.c:1665
+msgid ""
+"Option --key-size is allowed only for luksFormat, open and benchmark.\n"
+"To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"Valitsin --key-size sallitaan vain muodoille luksFormat, open ja benchmark.\n"
+"Käytä avaintiedostosta lukemisen rajoittamiseksi valitsinta --keyfile-size=(tavua)."
+
+#: src/cryptsetup.c:1672
+msgid "Option --test-passphrase is allowed only for open of LUKS and TCRYPT devices.\n"
+msgstr "Valitsin --test-passphrase sallitaan vain LUKS- ja TCRYPT-laitteiden avaamiseen.\n"
+
+#: src/cryptsetup.c:1677 src/cryptsetup_reencrypt.c:1360
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Avainkoon on oltava 8-bitin monikerta"
+
+#: src/cryptsetup.c:1684 src/cryptsetup_reencrypt.c:1365
+msgid "Key slot is invalid."
+msgstr "Avainväli on virheellinen."
+
+#: src/cryptsetup.c:1691
+msgid "Option --key-file takes precedence over specified key file argument.\n"
+msgstr "Valitsin --key-file on ensisijainen määritellylle avaintiedostoargumentille.\n"
+
+#: src/cryptsetup.c:1699 src/veritysetup.c:467 src/cryptsetup_reencrypt.c:1349
+msgid "Negative number for option not permitted."
+msgstr "Valitsimelle ei sallita negatiivista numeroa."
+
+#: src/cryptsetup.c:1703 src/cryptsetup_reencrypt.c:1343
+#: src/cryptsetup_reencrypt.c:1369
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Vain yksi --use-[u]random -valitsin on sallittu."
+
+#: src/cryptsetup.c:1707
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "Valitsin --use-[u]random sallitaan vain luksFormat-muodolle."
+
+#: src/cryptsetup.c:1711
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "Valitsin --uuid sallitaan vain luksFormat-muodolle ja luksUUID-muodolle."
+
+#: src/cryptsetup.c:1715
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "Valitsin --align-payload sallitaan vain luksFormat-muodolle."
+
+#: src/cryptsetup.c:1721
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "Valitsinta --skip tuetaan vain plain- ja loopaes-laitteiden avaamiseen.\n"
+
+#: src/cryptsetup.c:1727
+msgid "Option --offset is supported only for open of plain and loopaes devices.\n"
+msgstr "Valitsinta --offset tuetaan vain plain- ja loopaes-laitteiden avaamiseen.\n"
+
+#: src/cryptsetup.c:1733
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "Valitsinta --tcrypt-hidden, --tcrypt-system tai --tcrypt-backup tuetaan vain TCRYPT-laiteeelle.\n"
+
+#: src/cryptsetup.c:1738
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "Valitsinta --tcrypt-hidden ei voida yhdistää valitsimeen --allow-discards.\n"
+
+#: src/cryptsetup.c:1743
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "Valitsinta --veracrypt tuetaan vain TCRYPT-laiteeelle.\n"
+
+#: src/veritysetup.c:58
+msgid "Invalid salt string specified.\n"
+msgstr "Määritelty virheellinen satunnaisarvosiemenmerkkijono.\n"
+
+#: src/veritysetup.c:88
+#, c-format
+msgid "Cannot create hash image %s for writing.\n"
+msgstr "Tiivistevedoksen %s luominen kirjoittamista varten epäonnistui.\n"
+
+#: src/veritysetup.c:148
+msgid "Invalid root hash string specified.\n"
+msgstr "Virheellinen root-tiivistemerkkijono määritelty.\n"
+
+#: src/veritysetup.c:308
+msgid "<data_device> <hash_device>"
+msgstr "<data_laite> <tiiviste_laite>"
+
+#: src/veritysetup.c:308
+msgid "format device"
+msgstr "pohjusta laite"
+
+#: src/veritysetup.c:309
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<data_laite> <tiiviste_laite> <root_tiiviste>"
+
+#: src/veritysetup.c:309
+msgid "verify device"
+msgstr "todenna laite"
+
+#: src/veritysetup.c:310
+msgid "<name> <data_device> <hash_device> <root_hash>"
+msgstr "<nimi> <data_laite> <tiiviste_laite> <root_tiiviste>"
+
+#: src/veritysetup.c:310
+msgid "create active device"
+msgstr "luo aktiivilaite"
+
+#: src/veritysetup.c:311
+msgid "remove (deactivate) device"
+msgstr "poista (deaktivoi) laite"
+
+#: src/veritysetup.c:312
+msgid "show active device status"
+msgstr "näytä aktiivilaitteen tila"
+
+#: src/veritysetup.c:313
+msgid "<hash_device>"
+msgstr "<tiiviste_laite>"
+
+#: src/veritysetup.c:313
+msgid "show on-disk information"
+msgstr "näytä paikallisen levyn tiedot"
+
+#: src/veritysetup.c:332
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nimi> on kohteen alle %s luotava laite\n"
+"<data_laite> on datalaite\n"
+"<tiiviste_laite> on todennusdataa sisältävä laite\n"
+"<root_tiiviste> root-solmun tiiviste kohteella <tiiviste_laite>\n"
+
+#: src/veritysetup.c:339
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Käännetyt dm-verity oletusparametrit:\n"
+"\tTiiviste: %s, Data-lohko (tavua): %u, Tiivistelohko (tavua): %u, Satunnaislukuarvosiemenen koko: %u, Tiivistemuoto: %u\n"
+
+#: src/veritysetup.c:377
+msgid "Do not use verity superblock"
+msgstr "Älä käytä verity-superlohkoa"
+
+#: src/veritysetup.c:378
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "Muototyyppi (1 - normaali, 0 - alkuperäinen Chrome OS)"
+
+#: src/veritysetup.c:378
+msgid "number"
+msgstr "numero"
+
+#: src/veritysetup.c:379
+msgid "Block size on the data device"
+msgstr "Data-laitteen lohkokoko"
+
+#: src/veritysetup.c:380
+msgid "Block size on the hash device"
+msgstr "Tiivistelaitteen lohkokoko"
+
+#: src/veritysetup.c:381
+msgid "The number of blocks in the data file"
+msgstr "Data-tiedoston lohkojen määrä"
+
+#: src/veritysetup.c:381
+msgid "blocks"
+msgstr "lohkoa"
+
+#: src/veritysetup.c:382
+msgid "Starting offset on the hash device"
+msgstr "Tiivistelaitteen alkusiirrososoite"
+
+#: src/veritysetup.c:383
+msgid "Hash algorithm"
+msgstr "Tiivistealgoritmi"
+
+#: src/veritysetup.c:383
+msgid "string"
+msgstr "merkkijono"
+
+#: src/veritysetup.c:384
+msgid "Salt"
+msgstr "Satunnaisarvosiemenluku"
+
+#: src/veritysetup.c:384
+msgid "hex string"
+msgstr "heksadesimaalimerkkijono"
+
+#: src/cryptsetup_reencrypt.c:147
+#, c-format
+msgid "Cannot exclusively open %s, device in use.\n"
+msgstr "Kohteen %s avaaminen eksklusiivisesti epäonnistui, laite on käytössä.\n"
+
+#: src/cryptsetup_reencrypt.c:151
+#, c-format
+msgid "Cannot open device %s\n"
+msgstr "Laitteen %s avaus epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:161 src/cryptsetup_reencrypt.c:914
+msgid "Allocation of aligned memory failed.\n"
+msgstr "Tasatun muistin varaaminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:168
+#, c-format
+msgid "Cannot read device %s.\n"
+msgstr "Laitteen %s lukeminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:179
+#, c-format
+msgid "Marking LUKS device %s unusable.\n"
+msgstr "Merkitään LUKS-laite %s käyttökelvottomaksi.\n"
+
+#: src/cryptsetup_reencrypt.c:184
+#, c-format
+msgid "Marking LUKS device %s usable.\n"
+msgstr "Merkitään LUKS-laite %s käyttökelpoiseksi.\n"
+
+#: src/cryptsetup_reencrypt.c:200
+#, c-format
+msgid "Cannot write device %s.\n"
+msgstr "Laitteelle %s kirjoittaminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:281
+msgid "Cannot write reencryption log file.\n"
+msgstr "Uudelleensalauslokitiedoston kirjoittaminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:337
+msgid "Cannot read reencryption log file.\n"
+msgstr "Uudelleensalauslokitiedoston lukeminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:374
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Lokitiedosto %s on olemassa, aloitetaan salaus uudelleen.\n"
+
+#: src/cryptsetup_reencrypt.c:424
+msgid "Activating temporary device using old LUKS header.\n"
+msgstr "Aktivoidaan tilapäinen laite käyttäen vanhaa LUKS-otsaketta.\n"
+
+#: src/cryptsetup_reencrypt.c:435
+msgid "Activating temporary device using new LUKS header.\n"
+msgstr "Aktivoidaan tilapäinen laite käyttäen uutta LUKS-otsaketta.\n"
+
+#: src/cryptsetup_reencrypt.c:445
+msgid "Activation of temporary devices failed.\n"
+msgstr "Tilapäisten laitteiden aktivoiminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:471
+#, c-format
+msgid "New LUKS header for device %s created.\n"
+msgstr "Luotiin uusi LUKS-otsake laitteelle %s.\n"
+
+#: src/cryptsetup_reencrypt.c:479
+#, c-format
+msgid "Activated keyslot %i.\n"
+msgstr "Aktivoitiin avainväli %i.\n"
+
+#: src/cryptsetup_reencrypt.c:505
+#, c-format
+msgid "LUKS header backup of device %s created.\n"
+msgstr "Laitteen %s LUKS-otsakkeen varmuuskopio luotu.\n"
+
+#: src/cryptsetup_reencrypt.c:553
+msgid "Creation of LUKS backup headers failed.\n"
+msgstr "LUKS-varmuuskopio-otsakkeiden luominen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:655
+#, c-format
+msgid "Cannot restore LUKS header on device %s.\n"
+msgstr "LUKS-otsakkeen palautus laitteeseen %s epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:657
+#, c-format
+msgid "LUKS header on device %s restored.\n"
+msgstr "LUKS-otsake palautettu laitteessa %s.\n"
+
+#: src/cryptsetup_reencrypt.c:690
+#, c-format
+msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+msgstr "Eteneminen: %5.1f%%, ETA %02llu:%02llu, %4llu Mebitavua kirjoitettu, nopeus %5.1f Mebitavua/s%s"
+
+#: src/cryptsetup_reencrypt.c:729 src/cryptsetup_reencrypt.c:805
+#: src/cryptsetup_reencrypt.c:847
+msgid "Cannot seek to device offset.\n"
+msgstr "Laitteen siirrososoitteen etsintä epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:886 src/cryptsetup_reencrypt.c:892
+msgid "Cannot open temporary LUKS device.\n"
+msgstr "Tilapäisen LUKS-laitteen avaaminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:897 src/cryptsetup_reencrypt.c:902
+msgid "Cannot get device size.\n"
+msgstr "Laitekoon hakeminen epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:940
+msgid "Interrupted by a signal.\n"
+msgstr "Signaalin keskeyttämä.\n"
+
+#: src/cryptsetup_reencrypt.c:942
+msgid "IO error during reencryption.\n"
+msgstr "Siirräntävirhe uudelleensalauksen aikana.\n"
+
+#: src/cryptsetup_reencrypt.c:1049
+msgid "Key file can be used only with --key-slot or with exactly one key slot active.\n"
+msgstr "Avaintiedostoa voidaan käyttää vain valitsimen --key-slot kanssa tai täsmälleen yhden avainvälin ollessa aktiivisena.\n"
+
+#: src/cryptsetup_reencrypt.c:1093 src/cryptsetup_reencrypt.c:1108
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Kirjoita salasanalause avainvälille %u: "
+
+#: src/cryptsetup_reencrypt.c:1157
+msgid "Cannot open reencryption log file.\n"
+msgstr "Uudelleensalauslokitiedoston avaus epäonnistui.\n"
+
+#: src/cryptsetup_reencrypt.c:1283
+msgid "Reencryption block size"
+msgstr "Uudelleensalauslohkon koko"
+
+#: src/cryptsetup_reencrypt.c:1283
+msgid "MiB"
+msgstr "Mebitavua"
+
+#: src/cryptsetup_reencrypt.c:1287
+msgid "Do not change key, no data area reencryption."
+msgstr "Älä vaihda avainta, yhtään data-aluetta ei ole salattu uudelleen."
+
+#: src/cryptsetup_reencrypt.c:1294
+msgid "Use direct-io when accessing devices."
+msgstr "Käytä direct-io -siirräntää laitteisiin yhdistettäessä."
+
+#: src/cryptsetup_reencrypt.c:1295
+msgid "Use fsync after each block."
+msgstr "Käytä fsync-komentoa jokaisen lohkon jälkeen."
+
+#: src/cryptsetup_reencrypt.c:1296
+msgid "Update log file after every block."
+msgstr "Päivitä lokitiedosto jokaisen lohkon jälkeen."
+
+#: src/cryptsetup_reencrypt.c:1297
+msgid "Use only this slot (others will be disabled)."
+msgstr "Käytä vain tätä väliä (muut ovat pois käytöstä)."
+
+#: src/cryptsetup_reencrypt.c:1300
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "Pienennä datalaitekokoa (siirrä datasiirrososoitetta). VAARALLINEN!"
+
+#: src/cryptsetup_reencrypt.c:1301
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "Käytä vain määriteltyä laitekokoa (ohita laitteen loppu). VAARALLINEN!"
+
+#: src/cryptsetup_reencrypt.c:1302
+msgid "Create new header on not encrypted device."
+msgstr "Luo uusi otsake ei-salattuun laitteeseen."
+
+#: src/cryptsetup_reencrypt.c:1303
+msgid "Permanently decrypt device (remove encryption)."
+msgstr "Poista laitteen salaus pysyvästi (poista salaus)"
+
+#: src/cryptsetup_reencrypt.c:1319
+msgid "[OPTION...] <device>"
+msgstr "[VALITSIN...] <laite>"
+
+#: src/cryptsetup_reencrypt.c:1333
+#, c-format
+msgid "Reencryption will change: volume key%s%s%s%s.\n"
+msgstr "Uudelleensalauas muuttuu: taltio key%s%s%s%s.\n"
+
+#: src/cryptsetup_reencrypt.c:1334
+msgid ", set hash to "
+msgstr ", aseta tiivisteeksi "
+
+#: src/cryptsetup_reencrypt.c:1335
+msgid ", set cipher to "
+msgstr ", aseta salaukseksi "
+
+#: src/cryptsetup_reencrypt.c:1339
+msgid "Argument required."
+msgstr "Argumentti vaadittu."
+
+#: src/cryptsetup_reencrypt.c:1355
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Vain arvot välillä 1 mebitavua ja 64 mebitavua ovat sallittuja uudelleensalauslohkokokoja."
+
+#: src/cryptsetup_reencrypt.c:1374 src/cryptsetup_reencrypt.c:1379
+msgid "Invalid device size specification."
+msgstr "Virheellinen laitekokomäärittely."
+
+#: src/cryptsetup_reencrypt.c:1382
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "Maksimi laitepienennyskoko on 64 mebitavua."
+
+#: src/cryptsetup_reencrypt.c:1385
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Pienennyskoon on oltava 512-tavuisen sektorin monikerta."
+
+#: src/cryptsetup_reencrypt.c:1389
+msgid "Option --new must be used together with --reduce-device-size."
+msgstr "Valitsinta --new on käytettävä yhdessä valitsimen --reduce-device-size kanssa."
+
+#: src/cryptsetup_reencrypt.c:1393
+msgid "Option --keep-key can be used only with --hash or --iter-time."
+msgstr "Valitsinta --keep-key voidaan käyttää vain valitsimen --hash tai --iter-time kanssa."
+
+#: src/cryptsetup_reencrypt.c:1397
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "Valitsinta --new ei voi käytttää yhdessä valitsimen --decrypt kanssa."
+
+#: src/cryptsetup_reencrypt.c:1401
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "Valitsin --decrypt on yhteensopimaton määriteltyjen parametrien kanssa."
+
+#: src/utils_tools.c:151
+msgid "Error reading response from terminal.\n"
+msgstr "Virhe luettaessa vastausta pääteikkunasta.\n"
+
+#: src/utils_tools.c:173
+msgid "Command successful.\n"
+msgstr "Komento onnistui.\n"
+
+#: src/utils_tools.c:191
+#, c-format
+msgid "Command failed with code %i"
+msgstr "Komento epäonnistui koodilla %i"
+
+#: src/utils_password.c:42 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s\n"
+msgstr "Salasanan laatutarkistus epäonnistui: %s\n"
+
+#: src/utils_password.c:50
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s\n"
+msgstr ""
+"Salasanan laatutarkistus epäonnistui:\n"
+" %s\n"
+
+#: src/utils_password.c:82
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)\n"
+msgstr "Salasanan laatutarkistus epäonnistui: Virheellinen salasana (%s)\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "VAROITUS: tämä on kokeellista koodia, se voi rikkoa tietosi kokonaan.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "FIPS-tarkistussummavarmennus epäonnistui.\n"
+
+#~ msgid "WARNING: device %s is a partition, for TCRYPT system encryption you usually need to use whole block device path.\n"
+#~ msgstr "VAROITUS: laite %s on osio, TCRYPT-järjestelmäsalaukselle tarvitaan normaalisti koko lohkolaitepolun käyttö.\n"
+
+#~ msgid "Kernel doesn't support plain64 IV.\n"
+#~ msgstr "Käyttöjärjestelmäydin ei tule plain64 IV.\n"
+
+#~ msgid "Enter LUKS passphrase: "
+#~ msgstr "Kirjoita LUKS-salasanalause: "
+
+#~ msgid "Enter new LUKS passphrase: "
+#~ msgstr "Kirjoita uusi LUKS-salasanalause: "
+
+#~ msgid "Enter any LUKS passphrase: "
+#~ msgstr "Kirjoita mikä tahansa LUKS-salasanalause: "
+
+#~ msgid "Cannot check passsword quality: %s\n"
+#~ msgstr "Salasanan laatutarkistus epäonnistui: %s\n"
+
+#~ msgid "Failed to obtain device mapper directory."
+#~ msgstr "Laitekuvaajahakemiston hankkiminen epäonnistui."
+
+#~ msgid "Backup file %s doesn't exist.\n"
+#~ msgstr "Varmuuskopiotiedostoa %s ei ole olemassa.\n"
+
+#~ msgid "Cannot open file %s.\n"
+#~ msgstr "Tiedoston %s avaus epäonnistui.\n"
+
+#~ msgid "<name> <device>"
+#~ msgstr "<nimi> <laite>"
+
+#~ msgid "create device"
+#~ msgstr "luo laite"
+
+#~ msgid "remove device"
+#~ msgstr "poista laite"
+
+#~ msgid "remove LUKS mapping"
+#~ msgstr "poista LUKS-kuvaus"
+
+#~ msgid "open loop-AES device as mapping <name>"
+#~ msgstr "avaa loop-AES -laitteen kuvauksena <nimi>"
+
+#~ msgid "remove loop-AES mapping"
+#~ msgstr "poista loop-AES -kuvaus"
+
+#~ msgid "Option --allow-discards is allowed only for luksOpen, loopaesOpen and create operation.\n"
+#~ msgstr "Valitsin --allow-discards sallitaan vain luksOpen-, loopaesOpen- ja create-toiminnoille .\n"
+
+#~ msgid "Cannot open device %s for %s%s access.\n"
+#~ msgstr "Ei voida avata laitetta %s kohteeseen %s%s pääsyä varten.\n"
+
+#~ msgid "exclusive "
+#~ msgstr "yksinomainen "
+
+#~ msgid "writable"
+#~ msgstr "kirjoitettava"
+
+#~ msgid "read-only"
+#~ msgstr "kirjoitussuojattu"
+
+#~ msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+#~ msgstr "VAROITUS!!! Mahdollisesti turvaton muisti. Oletko pääkäyttäjä?\n"
+
+#~ msgid "Unable to obtain sector size for %s"
+#~ msgstr "Ei kyetä samaan sektorikokoa kohteelle %s"
+
+#~ msgid "Failed to write to key storage.\n"
+#~ msgstr "Avainsäiliöön kirjoittaminen epäonnistui.\n"
+
+#~ msgid "Failed to read from key storage.\n"
+#~ msgstr "Avainsäiliöstä lukeminen epäonnistui.\n"
+
+#~ msgid "Cannot use device %s (crypt segments overlaps or in use by another device).\n"
+#~ msgstr "Ei voida käyttää laitetta %s (salatut segmentit ovat päällekkäin tai toisen laitteen käyttämiä).\n"
+
+#~ msgid "Key slot %d verified.\n"
+#~ msgstr "Avainväli %d on todennettu.\n"
+
+#~ msgid "Invalid key size %d.\n"
+#~ msgstr "Virheellinen avainkoko %d.\n"
+
+#~ msgid "Block mode XTS is available since kernel 2.6.24.\n"
+#~ msgstr "Lohkotila XTS on käytetettävissä käyttöjärjestelmäytimestä 2.6.24 alkaen.\n"
+
+#~ msgid "Key size in LRW mode must be 256 or 512 bits.\n"
+#~ msgstr "Avainkoon on oltava LRW-tilassa 256 tai 512 bittiä.\n"
+
+#~ msgid "Block mode LRW is available since kernel 2.6.20.\n"
+#~ msgstr "Lohkotila LRW on käytettävissä käyttöjärjestelmäytimestä 2.6.20 alkaen.\n"
+
+#~ msgid "Negative keyfile size not permitted.\n"
+#~ msgstr "Negatiivinen avaintiedostokoko ei ole sallittu.\n"
+
+#~ msgid "Warning: exhausting read requested, but key file is not a regular file, function might never return.\n"
+#~ msgstr "Varoitus: uuvuttava luku pyydetty, mutta avaintiedosto ei ole tavallinen tiedosto, funktio ei ehkä koskaan palaa.\n"
+
+#~ msgid "Cannot find compatible device-mapper kernel modules.\n"
+#~ msgstr "Ei voida löytää yhteensopivia laitekuvaimen käyttöjärjestelmäydinmoduuleja.\n"
+
+#~ msgid "Cannot open device: %s\n"
+#~ msgstr "Ei voida avata laitetta: %s\n"
+
+#~ msgid "BLKROGET failed on device %s.\n"
+#~ msgstr "BLKROGET epäonnistui laitteessa %s.\n"
+
+#~ msgid "BLKGETSIZE failed on device %s.\n"
+#~ msgstr "BLKGETSIZE epäonnistui laitteessa %s.\n"
+
+#~ msgid "identical to luksKillSlot - DEPRECATED - see man page"
+#~ msgstr "identtinen kohteelle luksKillSlot - VANHENTUNUT - katso man-sivua"
+
+#~ msgid "modify active device - DEPRECATED - see man page"
+#~ msgstr "muokkaa aktiivista laitetta - VANHENTUNUT - katso man-sivua"
+
+#~ msgid ""
+#~ "The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\n"
+#~ "WARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"
+#~ msgstr ""
+#~ "Uudelleenlataustoiminto on vanhentunut. Käytä ”dmsetup reload” siinä tapauksessa, että todella tarvitset tätä toiminnallisuutta.\n"
+#~ "VAROITUS: älä käytä uudelleenlatausta koskettamaan LUKS-laitteita. Jos näin on laita, paina nyt näppäimiä Ctrl-C.\n"
+
+#~ msgid "Obsolete option --non-exclusive is ignored.\n"
+#~ msgstr "Vanhentunut valitsin --non-exclusive ohitetaan.\n"
+
+#~ msgid "Read the key from a file (can be /dev/random)"
+#~ msgstr "Lue avain tiedostosta (voi olla /dev/random)"
+
+#~ msgid "(Obsoleted, see man page.)"
+#~ msgstr "(Vanhentunut, katso man-sivu.)"
+
+#~ msgid "%s is not LUKS device.\n"
+#~ msgstr "%s ei ole LUKS-laite.\n"
+
+#~ msgid "%s is not LUKS device."
+#~ msgstr "%s ei ole LUKS-laite."
+
+#~ msgid "Unknown crypto device type %s requesed.\n"
+#~ msgstr "Tuntematon salauslaitetyyppi %s pyydetty.\n"
+
+#~ msgid "Limits to read from keyfile"
+#~ msgstr "Avaintiedostosta luettavat rajat"
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 0000000..7517b8a
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,4764 @@
+# Messages français pour cryptsetup.
+# Copyright (C) 2023 Free Software Foundation, Inc.
+# This file is put in the public domain.
+#
+# Solveig <perso@solveig.org>, 2009.
+# Nicolas Provost <nprovost@quadriv.com>, 2011.
+# Frédéric Marchal <fmarchal@perso.be>, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-02 15:51+0100\n"
+"Last-Translator: Frédéric Marchal <fmarchal@perso.be>\n"
+"Language-Team: French <traduc@traduc.org>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n >= 2);\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Impossible d'initialiser le gestionnaire « device-mapper ». Exécution comme un utilisateur non-root."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Impossible d'initialiser le gestionnaire « device-mapper ». Le module noyau dm_mod est-il chargé ?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Le fanion différé demandé n'est pas supporté."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "Le DM-UUID du périphérique %s a été tronqué."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Type de cible dm inconnu."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Les options de performance dm-crypt demandées ne sont pas supportées."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Les options demandées de gestion de corruption des données dm-verity ne sont pas supportées."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "L'option dm-verity tasklets demandée n'est pas supportée."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Les options dm-verity FEC demandées ne sont pas supportées."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Les options d'intégrité de données demandées ne sont pas supportées."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "L'option sector_size demandée n'est pas supportée."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Le recalcule automatique des balises de sécurité demandés n'est pas supporté."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM n'est pas supporté."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Le mode de carte de bits d'intégrité dm demandé n'est pas supporté."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Échec lors de l'interrogation du segment dm-%s."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Le système a manqué d'entropie lors de la génération de la clef de volume.\n"
+"Veuillez remuer la souris ou taper du texte dans une autre fenêtre pour générer des événements aléatoires.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Génération de la clef (%d%% effectués).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Fonctionne en mode FIPS."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "Erreur fatale d'initialisation RNG."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "La qualité du générateur aléatoire RNG demandé est inconnue."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Erreur en lecture du générateur aléatoire RNG "
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Impossible d'initialiser le moteur aléatoire RNG pour le chiffrement."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Impossible d'initialiser le moteur de chiffrement."
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "L'algorithme de hachage %s n'est pas supporté."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Erreur de traitement de clé (valeur hachage %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Impossible de déterminer le type de périphérique. Activation du périphérique incompatible ?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "Cette opération n'est possible que pour les périphériques LUKS."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Cette opération n'est possible que pour les périphériques LUKS2."
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Tous les emplacements de clés sont utilisés."
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "L'emplacement de clé %d n'est pas valide, merci d'en choisir un entre 0 et %d."
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "L'emplacement de clé %d est utilisé, merci d'en sélectionner un autre."
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "La taille du périphérique n'est pas alignée avec la taille d'un bloc logique du périphérique."
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "En-tête détecté mais le périphérique %s est trop petit."
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Cette opération n'est pas supportée pour ce type de périphérique."
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Opération illégale avec une re-chiffrement en cours."
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Échec lors du retour en arrière des métadonnées LUKS2 en mémoire."
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "%s n'est pas un périphérique LUKS valide."
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "La version %d de LUKS n'est pas supportée."
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "Le périphérique %s n'est pas activé."
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Le périphérique sous-jacent pour le périphérique chiffré %s a disparu."
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "Paramètres de chiffrement non valides."
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "La taille de la clé n'est pas valide."
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "le UUID n'est pas supporté avec ce type de chiffrement."
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Un périphérique avec des métadonnées détachées n'est pas supporté avec ce type de chiffrement."
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Taille de secteur de chiffrement non supportée."
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "La taille du périphérique n'est pas alignée avec la taille de secteur demandée."
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "Impossible de formater en LUKS sans périphérique."
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "L'alignement de données demandé n'est pas compatible avec le décalage des données."
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Impossible d'effacer l'en-tête du périphérique %s."
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Le périphérique %s est trop petit pour l'activation, il ne reste pas d'espace pour les données.\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "AVERTISSEMENT: L'activation du périphérique va échouer, dm-crypt ne supporte pas la taille de secteur de chiffrement demandée.\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "La clé de volume est trop petite pour chiffrer avec les extensions d'intégrité."
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Le chiffrement %s-%s (clé de %zd bits) n'est pas disponible."
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "ATTENTION: La taille des métadonnées LUKS2 est devenue %<PRIu64> octets.\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "ATTENTION: La taille de la zone des emplacements de clés LUKS2 est devenue %<PRIu64> octets.\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Le périphérique %s est trop petit."
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Impossible de formater le périphérique %s qui est en cours d'utilisation."
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Impossible de formater le périphérique %s. Permission refusée."
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Impossible de formater l'intégrité du périphérique %s."
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Impossible de formater le périphérique %s"
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "Impossible de formater LOOPAES sans périphérique."
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "Impossible de formater VERITY sans périphérique."
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Type de hachage VERITY %d non supporté."
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Taille de bloc VERITY non supportée."
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Décalage de hachage VERITY non supporté."
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "Décalage VERITY FEC non supporté."
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "La zone de données recouvre la zone de hachage."
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "La zone de hachage recouvre la zone FEC."
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "La zone de données recouvre la zone FEC."
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "ATTENTION : La taille %d demandée pour l'étiquette est différente de la taille de sortie de %s (%d octets).\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Type de chiffrement de périphérique demandé (%s) inconnu."
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Paramètres non supportés sur le périphérique %s."
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Paramètres non concordants sur le périphérique %s."
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Désaccord entre les périphériques crypt."
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Impossible de recharger le périphérique %s."
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Impossible de suspendre le périphérique %s."
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Impossible de redémarrer le périphérique %s."
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Erreur fatale en rechargeant le périphérique %s (au dessus du périphérique %s)"
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Impossible de basculer le périphérique %s en dm-error."
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "Impossible de redimensionner le périphérique loopback."
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "ATTENTION: La taille maximale est déjà définie ou le noyau ne supporte pas le redimensionnement.\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Le redimensionnement a échoué, le noyau ne le supporte pas."
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "Voulez vous réellement changer l'UUID du périphérique ?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Le fichier de sauvegarde de l'en-tête ne contient pas d'en-tête compatible LUKS."
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Le volume %s n'est pas actif."
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Le volume %s est déjà suspendu."
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Le périphérique %s ne supporte pas la suspension."
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Erreur lors de la suspension du périphérique %s."
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Le périphérique %s ne supporte pas la remise en service."
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Erreur lors de la remise en service du périphérique %s."
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Le volume %s n'est pas suspendu."
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Ceci n'est pas la clé du volume."
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "Nouvel emplacement de clé impossible à échanger."
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "L'emplacement de clé %d n'est pas valide."
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "L'emplacement de clé %d n'est pas actif."
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "L'en-tête du périphérique recouvre la zone de données."
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Re-chiffrement en cours. Impossible d'activer le périphérique."
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Impossible d'obtenir le verrou de re-chiffrement."
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "La récupération du rechiffrement LUKS2 a échoué."
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "Type de périphérique improprement initialisé."
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "Le périphérique %s existe déjà."
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Impossible d'utiliser le périphérique %s, le nom est invalide ou est toujours utilisé."
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "Clé de volume incorrecte pour le périphérique en clair."
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "Hachage racine incorrect spécifié pour le périphérique verity."
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "Signature de hachage racine requise."
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Le porte-clé du noyau est manquant : il est requis pour passer une signature au noyau."
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "Impossible de charger la clé dans le porte-clé du noyau."
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Impossible d'annuler la suppression différée du périphérique %s."
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Le périphérique %s est toujours occupé."
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "Le périphérique %s n'est pas valide."
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "Le tampon de la clé du volume est trop petit."
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Impossible de récupérer la clé du volume pour le périphérique LUKS2."
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Impossible de récupérer la clé du volume pour le périphérique LUKS1."
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Impossible de récupérer la clé du volume pour ce périphérique de type « plain »."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Impossible de récupérer le hachage racine pour le périphérique verity."
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Impossible de récupérer la clé du volume pour le périphérique BITLK."
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Impossible de récupérer la clé du volume pour le périphérique FVAULT2."
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Cette opération n'est pas possible pour le périphérique chiffré %s."
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "L'opération de vidage n'est pas supportée pour ce type de périphérique."
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Le décalage des données n'est pas un multiple de %u octets."
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Impossible de convertir le périphérique %s qui est toujours en cours d'utilisation."
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Échec de l'affectation de l'emplacement de clé %u pour la nouvelle clé de volume."
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Échec de l'initialisation des paramètres par défaut des emplacement de clé LUKS2."
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Échec de l'affectation de l'emplacement de clé %d aux résumé."
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Impossible d'ajouter un emplacement de clé, tous les emplacements sont désactivés et aucune clé n'a été fournie pour ce volume."
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Le porte-clé du noyau n'est pas supporté par ce noyau."
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Échec lors de la lecture du mot de passe depuis le porte-clé (erreur %d)."
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Erreur lors de l'acquisition du verrou global de sérialisation des accès strictes à la mémoire"
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Impossible d'ouvrir le fichier de clef."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Impossible de lire le fichier de clé depuis un terminal."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "Impossible d'exécuter « stat » sur le fichier de clef."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Impossible de sauter au décalage demandé dans le fichier de clé."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "Plus assez de mémoire lors de la lecture de la phrase secrète."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Erreur de lecture de la phrase secrète."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Rien à lire en entrée."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Taille max. de fichier de clé dépassée."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "Impossible de lire la quantité de données demandée."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Le périphérique %s n'existe pas ou l'accès y est interdit."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Le périphérique %s n'est pas compatible."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "La mauvaise taille de optimal-io est ignorée pour le périphérique de données (%u octets)."
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Le périphérique %s est trop petit. Il a besoin d'au moins %<PRIu64> octets."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Impossible d'utiliser le périphérique %s actuellement utilisé (déjà mappé ou monté)."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Impossible d'utiliser le périphérique %s, permission refusée."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Impossible d'obtenir des informations au sujet du périphérique %s."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Impossible d'utiliser un périphérique loopback. Fonctionne comme un utilisateur non-root."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Impossible d'associer le périphérique loopback (le drapeau « autoclear » est requis)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Le décalage demandé est au delà de la taille réelle du périphérique %s."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Le périphérique %s a une taille nulle."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Le temps cible PBKDF demandé ne peut pas être zéro."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Type PBKDF %s inconnu."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "L'algorithme de hachage %s demandé n'est pas supporté."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Le type PBKDF demandé n'est pas supporté par LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "La mémoire maximum ou les threads parallèles de PBKDF ne peuvent pas être définis avec pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Le nombre d'itérations forcées est trop petit pour %s (le minimum est %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Le coût de la mémoire forcé est trop petit pour %s (le minimum est %u kilooctets)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Le coût de la mémoire PBKDF maximum demandée est trop grand (maximum est %d kilooctets)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "La mémoire PBKDF maximum demandée ne peut pas être zéro."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Le nombre de threads parallèles PBKDF demandé ne peut pas être zéro."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Seul PBKDF2 est supporté en mode FIPS."
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "L'étalon PBKDF est désactivé mais les itérations ne sont pas définies."
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Options PBKDF2 incompatibles (en utilisant l'algorithme de hachage %s)."
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "Options PBKDF incompatibles."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Verrouillage interrompu. Le chemin de verrouillage %s/%s est inutilisable (pas un répertoire ou est manquant)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Verrouillage interrompu. Le chemin de verrouillage %s/%s est inutilisable (%s n'est pas un répertoire)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Impossible de se déplacer au décalage du périphérique."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Erreur durant l'effacement total, offset %<PRIu64>"
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Impossible de configurer la correspondance des clés dm-crypt du périphérique %s.\n"
+"Vérifiez que le noyau supporte le chiffrement %s (pour plus d'informations, voir les journaux syslog)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "La taille de la clé en mode XTS doit être un multiple de 256 ou 512 bits."
+
+# Frédéric: Je laisse iv (initialisation vector) sous cette forme car elle est plus habituelle que vi
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "La spécification du chiffrement devrait être au format [chiffrement]-[mode]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Impossible d'écrire sur le périphérique %s. Permission refusée."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Échec lors de l'ouverture du périphérique de stockage temporaire de clés."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Impossible d'accéder au périphérique de stockage temporaire de clés."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Erreur E/S pendant le chiffrement de l'emplacement de clé."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Impossible d'ouvrir le périphérique %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "Erreur E/S pendant le déchiffrement de l'emplacement de clé."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Le périphérique %s est trop petit (LUKS1 a besoin d'au moins %<PRIu64> octets)."
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "L'emplacement de clé LUKS %u n'est pas valide."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Le fichier de sauvegarde d'en-tête demandé %s existe déjà."
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Impossible de créer le fichier de sauvegarde d'en-tête %s."
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Impossible d'écrire le fichier de sauvegarde d'en-tête %s."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Le fichier de sauvegarde ne contient pas d'en-tête LUKS valide."
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Impossible d'ouvrir le fichier de sauvegarde d'en-tête %s."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Impossible de lire le fichier de sauvegarde d'en-tête %s."
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Le décalage des données (« offset ») ou la taille de la clé ne sont pas identiques dans le périphérique et la sauvegarde. La restauration a échouée."
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Périphérique %s %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "ne contient pas d'en-tête LUKS. Remplacer l'en-tête peut détruire les données de ce périphérique."
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "contient déjà un en-tête LUKS. Remplacer l'en-tête détruira les emplacements de clés actuels."
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"ATTENTION : l'en-tête du périphérique a un UUID différent de celui de la sauvegarde !"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "Taille de clé non standard. Réparation manuelle requise."
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Alignement non standard des emplacements de clé. Réparation manuelle requise."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Mode de chiffrement réparé (%s -> %s)."
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Valeur hachée du chiffrement réparée vers des minuscules (%s)."
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "L'algorithme de hachage LUKS demandé (%s) n'est pas supporté."
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "Réparation des emplacements de clé."
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Emplacement de clé %i : décalage réparé (%u -> %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Emplacement de clé %i : bandes réparées (%u -> %u)."
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Emplacement de clé %i : signature de partition contrefaite."
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Emplacement de clé %i : aléa effacé."
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "Écriture de l'en-tête LUKS sur le disque."
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "Échec de la réparation."
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Le mode de chiffrement LUKS %s n'est pas valide."
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "La valeur hachée LUKS %s n'est pas valide."
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "Aucun problème connu détecté pour l'en-tête LUKS."
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Erreur lors de la mise à jour de l'en-tête LUKS sur le périphérique %s."
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Erreur lors de la relecture de l'en-tête LUKS après la mise à jour sur le périphérique %s."
+
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "L'offset des données d'un en-tête LUKS doit être soit 0 ou soit plus grand que la taille de l'en-tête."
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "Mauvais format fourni pour le UUID LUKS."
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Impossible de créer un en-tête LUKS : échec lors de la lecture de l'aléa."
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Impossible de créer un en-tête LUKS : le résumé (« digest ») de l'en-tête a échoué (en utilisant l'algorithme de hachage %s)."
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "L'emplacement de clé %d est activé, effacez le d'abord."
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Le matériel de l'emplacement de clé %d a trop peu de bandes. L'en-tête a-t-il été modifié ?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "Débordement de la valeur d'itération de PBKDF2."
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Impossible d'ouvrir l'emplacement de clé (en utilisant le hachage %s)."
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "L'emplacement de clé %d n'est pas valide, merci de sélectionner un emplacement entre 0 et %d."
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Impossible d'effacer de façon sécurisée le périphérique %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Fichier de clé GPG chiffré détecté mais pas encore supporté."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "SVP utilisez gpg --decrypt <FICHIER DE CLE> | cryptsetup --keyfile=-...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Fichier de clé incompatible pour boucle « loop-AES »."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Le noyau ne supporte pas les associations de type boucle « loop-AES »."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Erreur lors de la lecture du fichier de clé %s."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Longueur maximum de la phrase secrète TCRYPT (%zu) dépassée."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "L'algorithme de hachage PBKDF2 %s n'est pas supporté, ignoré."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "L'interface du noyau requise pour le chiffrement n'est pas disponible."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Vérifiez que le module du noyau algif_skcipher est chargé."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "L'activation n'est pas supportée pour des secteurs de taille %d."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Le noyau ne supporte pas l'activation pour ce mode TCRYPT historique."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Activation du chiffrement du système TCRYPT sur la partition %s."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Le noyau ne supporte pas les associations de type TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Cette fonction n'est pas supportée sans le chargement de l'en-tête TCRYPT."
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Un type d'entrée « %u » inattendu a été trouvé dans la méta-donnée en analysant la Clé Maître du Volume supportée."
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Chaîne texte invalide rencontrée en analysant la Clé Maître du Volume."
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Chaîne texte (« %s ») inattendue rencontrée en analysant la Clé Maître du Volume supportée."
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "La valeur « %u » pour l'entrée de la méta-donnée est inattendue en analysant la Clé Maître du Volume supportée."
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "La version 1 de BITLK n'est actuellement pas supportée."
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Signature d'amorce invalide ou inconnue pour le périphérique BITLK."
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Taille de secteur %<PRIu16> non supportée."
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Impossible de lire l'en-tête BITLK depuis %s."
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Impossible de lire les méta-données BITLK FVE depuis %s."
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "Type de chiffrement inconnu ou non supporté."
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Impossible de lire les entrées des méta-données de BITLK depuis %s."
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "Échec lors de la conversion de la description du volume BITLK"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Un type d'entrée « %u » inattendu a été trouvé dans la méta-donnée en analysant la clé externe."
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "Le GUID du fichier BEK « %s » ne correspond pas au GUID du volume."
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "La valeur « %u » pour l'entrée de la méta-donnée est inattendue en analysant la clé externe."
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Métadonnées BEK version %<PRIu32> non supportées"
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "La taille inattendue des métadonnées BEK %<PRIu32> ne correspond pas à la longueur du fichier BEK"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Une entrée de méta-donnée inattendue a été trouvée en analysant la clé de démarrage."
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "Cette opération n'est pas supportée."
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "Taille inattendue pour les données de la clé."
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Ce périphérique BITLK est dans un état non supporté et ne peut pas être activé."
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Les périphériques BITLK avec le type « %s » ne peuvent pas être activés."
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "L'activation d'un périphérique BITLK partiellement déchiffré n'est pas supporté."
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "AVERTISSEMENT: La taille %<PRIu64> du volume BitLocker ne correspond pas à la taille %<PRIu64> du périphérique sous-jacent"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Impossible d'activer le périphérique car dm-crypt dans le noyau ne supporte pas BITLK IV."
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Impossible d'activer le périphérique car dm-crypt dans le noyau ne supporte pas le diffuseur BITLK Elephant."
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Impossible d'activer le périphérique car dm-crypt dans le noyau ne supporte pas une grande taille de secteur."
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Impossible d'activer le périphérique car le module dm-zero est manquant dans le noyau."
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Échec à la lecture de %u octets dans l'en-tête du volume."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Version FVAULT2 %<PRIu16> non supportée."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Le périphérique verity %s n'utilise pas l'en-tête sur le disque."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "La version VERITY %d n'est pas supportée."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "En-tête VERITY corrompu."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Mauvais format d'UUID VERITY fourni sur le périphérique %s."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Erreur lors de la mise à jour de l'en-tête verity sur le périphérique %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "La vérification de la signature du hachage racine n'est pas supportée."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Les erreurs ne savent pas être réparées avec un périphérique FEC."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "%u erreurs réparables ont été trouvées avec le périphérique FEC."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Le noyau ne supporte pas les associations de type dm-verity."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Le noyau ne supporte pas les options de signature dm-verity."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Le périphérique verity a détecté une corruption après l'activation."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "La zone de réserve n'a pas été mise à zéro à la positon %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Débordement du décalage du périphérique."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "La vérification a échoué à la position %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Débordement de la zone de hachage."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "La vérification de la zone de données a échoué."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "La vérification du hachage de la racine a échoué."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Erreur d'entrée/sortie lors de la création de la zone de hachage."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "La création de la zone de hachage a échoué."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "ATTENTION : Le kernel ne peut pas activer le périphérique si la taille des blocs de données dépasse la taille d'une page (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Échec de l'allocation du contexte RS."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Échec de l'allocation du tampon."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Échec de lecture du bloc RS %<PRIu64> octet %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Échec de la lecture de la parité du bloc RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Échec de la réparation de la parité du bloc %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Échec de l'écriture de la parité du bloc RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Les tailles des blocs doivent concorder pour FEC."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Nombre d'octets de parité invalide."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Longueur de segment FEC invalide."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Impossible de déterminer la taille du périphérique %s."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Métadonnées dm-integrity du noyau incompatible (version %u) détectée sur %s."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Le noyau ne supporte pas les associations de type dm-integrity."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Le noyau ne supporte pas les alignements de méta-données fixés de dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Le noyau refuse d'activer l'option de recalcul non sûre (voyez les options d'activation historique pour outrepasser)."
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Impossible d'acquérir un verrou en écriture sur le périphérique %s."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Tentative détectée de mettre à jour les métadonnées LUKS2 de manière concurrent. L'opération est abandonnée."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Le périphérique contient une signature ambigüe, impossible de récupérer automatiquement LUKS2.\n"
+"Veuillez exécuter « cryptsetup repair » pour la récupération."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Le décalage de données demandé est trop petit."
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "ATTENTION: la zone des emplacements de clés (%<PRIu64> octets) est très petite, le nombre d'emplacements de clés LUKS2 est très limité.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Impossible d'acquérir le verrou de lecture sur le périphérique %s."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Des exigences LUKS2 interdites ont été détectées dans la sauvegarde %s."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Les décalages des données ne sont pas identiques sur le périphérique et la sauvegarde, la restauration a échoué."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Les en-têtes binaires avec des tailles de zones d'emplacements de clés sont différents sur le périphérique et la sauvegarde, la restauration a échouée."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Périphérique %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "ne contient pas d'en-tête LUKS2. Remplacer l'en-tête peut détruire les données de ce périphérique."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "contient déjà un en-tête LUKS2. Remplacer l'en-tête détruira les emplacements de clés actuels."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"ATTENTION: des exigences LUKS2 inconnues ont été détectées sur l'en-tête du périphérique réel !\n"
+"Remplacer l'en-tête par la sauvegarde peut corrompre les données sur ce périphérique !"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"ATTENTION: Un rechiffrement hors-ligne non terminé a été détecté sur le périphérique !\n"
+"Remplacer l'en-tête par la sauvegarde peut corrompre les données."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Fanion inconnu %s ignoré."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Clé manquante pour le segment %u de dm-crypt"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Impossible de définir le segment dm-crypt."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Impossible de définir le segment dm-linear."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Configuration d'intégrité du périphérique non supportée."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Re-chiffrement en cours. Le périphérique ne peut être désactivé."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Échec du remplacement du périphérique suspendu %s avec la cible dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Échec lors de la lecture des exigences LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Des exigences LUKS2 non rencontrées ont été détectées."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Opération incompatible avec un périphérique marqué pour le rechiffrement historique. Abandon."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Opération incompatible avec un périphérique marqué pour le rechiffrement LUKS2. Abandon."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Pas assez de mémoire disponible pour ouvrir l'emplacement de clé."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Échec de l'ouverture de l'emplacement de clé."
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Impossible d'utiliser le chiffrement %s-%s pour le chiffrement de l'emplacement de clé"
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "L'algorithme de hachage %s n'est pas disponible."
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "Plus d'espace pour le nouvel emplacement de clé."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Requête de changement du mode de résilience du rechiffrement invalide."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Impossible de mettre à jour le type de résilience. Le nouveau type ne fourni que %<PRIu64> octets alors que l'espace requis est %<PRIu64> octets."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Impossible de rafraîchir le résumé de la vérification de rechiffrement."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Ne peut vérifier le statut du périphérique avec le uuid : %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Impossible de convertir un en-tête avec des métadonnées LUKSMETA supplémentaires."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Impossible d'utiliser la spécification de chiffrement %s-%s pour LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Impossible de déplacer la zone des emplacements de clés. Pas assez d'espace."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Impossible de convertir au format LUKS2 – métadonnées invalides."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Impossible de déplacer la zone des emplacements de clés. Les emplacements de clés LULS2 sont trop petits."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Impossible de déplacer la zone des emplacements de clés."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Impossible de convertir au format LUKS1 – la taille du secteur de chiffrement du segment par défaut n'est pas 512 octets."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Impossible de convertir au format LUKS1 – les résumés des emplacements de clés ne sont pas compatibles avec LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Impossible de convertir au format LUKS1 – le périphérique utilise des clés de chiffrement %s emballées."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Impossible de convertir au format LUKS1 – le périphérique utilise plus de segments."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Impossible de convertir au format LUKS1 – l'en-tête LUKS2 contient %u jeton(s)."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Impossible de convertir au format LUKS1 – l'emplacement de clé %u est dans un état invalide."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Impossible de convertir au format LUKS1 – l'emplacement %u (sur les emplacements maximum) est toujours actif."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Impossible de convertir au format LUKS1 – l'emplacement de clé %u n'est pas compatible avec LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "La taille de la zone chaude doit être un multiple de l'alignement de zone calculé (%zu octets)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "La taille du périphérique doit être un multiple de l'alignement de zone calculé (%zu octets)."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Impossible d'initialiser l'encapsulation pour le stockage de l'ancien segment."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Impossible d'initialiser l'encapsulation pour le stockage du nouveau segment."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Impossible d'initialiser la protection des zones chaudes."
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Impossible de lire les sommes de contrôle pour la zone chaude actuelle."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Échec de la lecture de la zone chaude démarrant à %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Échec lors du déchiffrement du secteur %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Échec lors de la récupération du secteur %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Les tailles des périphériques source et cible ne correspondent pas. Source %<PRIu64>, cible: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Échec de l'activation du périphérique de zone chaude %s."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Impossible d'activer le périphérique de surcouche %s avec la table d'origine actuelle."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Impossible de charger la nouvelle cartographie du périphérique %s."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Impossible de rafraîchir la pile des périphériques de rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Impossible de définir la taille de la nouvelle zone des emplacements de clés."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "La valeur de décalage de données n'est pas alignée sur la taille de secteur de chiffrement (%<PRIu32> octets)."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Mode de résilience %s non supporté"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "La taille du secteur déplacé ne peut pas être plus grande que la valeur de décalage des données."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Paramètres de rechiffrement de la résilience invalides."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Le segment déplacé est trop grand. La taille demandée est %<PRIu64>, l'espace disponible est %<PRIu64>"
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Erreur lors de la suppression de la table."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "La taille des données réduites est plus grande que la taille réelle du périphérique."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Le périphérique de données n'est pas aligné sur la taille de secteur de chiffrement (%<PRIu32> octets)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Le décalage de données (%<PRIu64> secteurs) est plus petit que le décalage de données future (%<PRIu64> secteurs)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Erreur lors de l'ouverture de %s en mode exclusif (déjà mappé ou monté)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Le périphérique n'est pas marqué pour le rechiffrement LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Échec du chargement du contexte de rechiffrement LUKS2"
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Impossible d'obtenir l'état de rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Le périphérique n'est pas en rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Le rechiffrement est déjà en cours."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Impossible d'acquérir le verrou de rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Impossible de réaliser le rechiffrement. Exécutez d'abord la récupération du rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "La taille du périphérique actif et la taille de rechiffrement demandée ne correspondent pas."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "Taille de périphérique illégale demandée dans les paramètres de rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Rechiffrement en cours. La récupération ne peut pas être réalisée."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "Rechiffrement LUKS2 déjà initialisé dans les métadonnées."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Échec de l'initialisation du rechiffrement LUKS2 dans les métadonnées."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Impossible de définir les segments du périphérique pour le rechiffrement suivant de la zone chaude."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Échec lors de l'écriture des métadonnées de la résilience du rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Échec du déchiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Échec de l'écriture de la zone chaude démarrant à %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Erreur lors de la synchronisation des données."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Échec de la mise à jour des métadonnées après la fin du rechiffrement de la zone chaude courante."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Échec lors de l'écriture des métadonnées LUKS2"
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Impossible d'effacer la zone du périphérique contenant les données inutilisées."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Erreur lors de la suppression de l'emplacement de clé inutilisé (unbound) %d."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Erreur lors de la suppression de l'emplacement de clé de re-chiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Erreur fatale en rechiffrant le morceau commençant à %<PRIu64> d'une longueur de %<PRIu64> secteurs."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Échec du rechiffrement en-ligne."
+
+# Frédéric: Je n'ai pas la moindre idée de ce que le développeur a voulu écrire. Qu'est-ce que "error target" dans ce contexte ?
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Ne pas redémarrer le périphérique à moins qu'il ait été remplacé manuellement par la cible en erreur."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Impossible de réaliser le rechiffrement. Statut de rechiffrement inattendu."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Contexte de rechiffrement manquant ou invalide."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Impossible d'initialiser la pile du périphérique de rechiffrement."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Échec de la mise à jour du contexte de rechiffrement."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Les méta-données de rechiffrement sont invalides."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Les paramètres de chiffrement des emplacement de clés peuvent uniquement être définis pour un périphérique LUKS2."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Entrez le code PIN du jeton : "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Entrez le code PIN du jeton %d : "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Aucun motif connu d'algorithme de chiffrement n'a été détecté."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "ATTENTION: Le paramètre --hash est ignoré en mode non chiffré quand le fichier de clé est spécifié.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "ATTENTION: L'option --keyfile-size est ignorée. La taille de lecture est la même que la taille de la clé de chiffrement.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Signature(s) de périphérique détectée(s) sur %s. Continuer risque d'endommager les données existantes."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "Opération interrompue.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "L'option --key-file est requise."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Entrez le PIN VeraCrypt : "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Valeur PIN invalide : erreur d'analyse"
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Valeur PIN invalide: 0"
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Valeur PIN invalide: hors des limites."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Aucun en-tête détecté avec cette phrase secrète sur le périphérique."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Le périphérique %s n'est pas un périphérique BITLK valide."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Impossible de déterminer la taille de la clé de volume pour BITLK, veuillez utiliser l'option --key-size."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Le contenu de l'en-tête avec la clé de volume est une information\n"
+"sensible qui permet d'accéder à la partition chiffrée sans mot de passe.\n"
+"Ce contenu devrait toujours être stocké, chiffré, en lieu sûr."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Le contenu de l'en-tête avec la clé de volume est une information\n"
+"sensible qui permet d'accéder à la partition chiffrée sans mot de passe.\n"
+"Ce contenu devrait être stocké, chiffré, en lieu sûr."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Le périphérique %s n'est pas un périphérique FVAULT2 valide."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Impossible de déterminer la taille de la clé de volume pour FVAULT2, veuillez utiliser l'option --key-size."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Le périphérique %s est toujours actif et prévu pour une suppression différée.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Le redimensionnement d'un périphérique actif requiert que la clé du volume soit dans le porte-clé mais l'option --disable-keyring est définie."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Test de performance interrompu."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/A\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u itérations par seconde pour une clé de %zu bits\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/A\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u itérations, %5u mémoire, %1u threads parallèles (CPUs) pour une clé de %zu bits (temps de %u ms demandé)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Le résultat de l'évaluation de performance n'est pas fiable."
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Tests approximatifs en utilisant uniquement la mémoire (pas de stockage E/S).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algorithme | Clé | Chiffrement | Déchiffrement\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Le chiffrement %s (avec une clé de %i bits) n'est pas disponible."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algorithme | Clé | Chiffrement | Déchiffrement\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "N/D"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Des métadonnées de rechiffrement LUKS2 non protégées ont été détectées. Veuillez vérifier si l'opération de rechiffrement est\n"
+"désirable (consultez la sortie de luksDump) et continuez (mise à niveau des métadonnées) uniquement si vous constatez que\n"
+"l'opération est légitime."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Entrez la phrase secrète pour protéger et mettre à niveau les métadonnées de rechiffrement : "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Réellement procéder à la récupération du rechiffrement LUKS2 ?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Entrez la phrase secrète pour vérifier le résumé des métadonnées du rechiffrement : "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Entrez la phrase secrète pour la récupération du rechiffrement : "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Réellement essayer de réparer l'en-tête du périphérique LUKS ?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Effacement interrompu."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Effacement du périphérique pour initialiser les sommes de contrôle d'intégrité.\n"
+"Vous pouvez interrompre ceci en appuyant sur CTRL+c (le reste du périphérique effacé contiendra toujours des sommes de contrôle invalides).\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Impossible de désactiver le périphérique temporaire %s."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "L'option d'intégrité peut uniquement être utilisée avec le format LUKS2."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Options de taille des métadonnées LUKS2 non supportées."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Le fichier d'en-tête n'existe pas, voulez-vous le créer ?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Impossible de créer le fichier d'en-tête %s."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Aucun motif connu de spécification d'intégrité n'a été détecté."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Ne peut utiliser %s comme en-tête sur disque."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Cette action écrasera définitivement les données sur %s."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Impossible de définir les paramètres pbkdf."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Décalage réduit de données est uniquement permis dans un en-tête LUKS détaché."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "Le container %s du fichier LUKS est trop petit pour l'activation, il ne reste pas d'espace pour les données."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Impossible de déterminer la taille de la clé de volume pour LUKS sans emplacement de clé, veuillez utiliser l'option --key-size."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Le périphérique a été activé mais les fanions ne peuvent pas être rendus permanents."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Emplacement de clé %d sélectionné pour suppression."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Ceci est le dernier emplacement de clé. Le périphérique sera inutilisable après la suppression de cette clé."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Entrez toute phrase secrète restante : "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Opération interrompue, l'emplacement de clé n'a PAS été effacé.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Entrez la phrase secrète à effacer : "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "%s n'est pas un périphérique LUKS2 valide."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Entrez une nouvelle phrase secrète pour l'emplacement de clé : "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "ATTENTION: Le paramètre --key-slot est utilisé pour le nouveau numéro de l'emplacement de clé.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Entrez une phrase secrète existante : "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Entrez la phrase secrète à changer : "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Entrez la nouvelle phrase secrète : "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Entrez la phrase secrète pour l'emplacement de clé à convertir: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "L'opération isLuks supporte seulement un périphérique en argument."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "L'emplacement de clé %d ne contient pas de clé non liée."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Le contenu de l'en-tête avec une clé non liée est une information sensible.\n"
+"Ce contenu devrait être stocké, chiffré, en lieu sûr."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s n'est pas un nom de périphérique %s actif."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s n'est pas un nom de périphérique LUKS actif ou l'en-tête est manquant."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "L'option --header-backup-file est requise."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s n'est pas un périphérique géré par cryptsetup."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Le rafraîchissement n'est pas supporté pour un périphérique de type %s"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Type de métadonnée du périphérique %s non reconnu."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "La commande exige un périphérique et un nom de correspondance comme arguments."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Cette opération va supprimer tous les emplacements de clés du périphérique %s.\n"
+"Le périphérique sera inutilisable après cette opération."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Opération interrompue, les emplacements de clés n'ont PAS été effacés.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Type LUKS invalide, seuls luks1 et luks2 sont supportés."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Le périphérique est déjà du type %s."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Cette opération va convertir %s au format %s.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Opération interrompue, le périphérique n'a PAS été converti.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "L'option --priority, --label ou --subsystem est manquante."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Le jeton %d est invalide."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Le jeton %d est utilisé."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Échec lors de l'ajout du jeton %d au porte-clé luks2."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Échec lors de l'affectation du jeton %d à l'emplacement de clé %d."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Le jeton %d n'est pas utilisé."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Impossible d'importer le jeton depuis le fichier."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Impossible d'obtenir le jeton %d pour l'export."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Le jeton %d n'est pas assigné à l'emplacement de clé %d."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Impossible de dissocier le jeton %d de l'emplacement de clé %d."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Les options --tcrypt-hidden, --tcrypt-system ou --tcrypt-backup sont supportées seulement pour un périphérique TCRYPT."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "L'option --veracrypt ou --disable-veracrypt est uniquement supportée pour un périphérique de type TCRYPT."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "L'option --veracrypt-pim est uniquement supportée pour un périphérique compatible avec VeraCrypt."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "L'option --veracrypt-query-pim est uniquement supportée pour un périphérique compatible avec VeraCrypt."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Les options --veracrypt-pim et --veracrypt-query-pim sont mutuellement exclusives."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "L'option --persistent n'est pas permise avec --test-passphrase."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Les options --refresh et --test-passphrase sont mutuellement exclusives."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "L'option --shared est permise uniquement pour ouvrir un périphérique ordinaire."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "L'option --skip est supportée uniquement pour ouvrir des périphériques ordinaires et loopaes."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "L'option --offset avec l'action d'ouverture est supportée uniquement pour des périphériques ordinaires et loopaes."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "L'option --tcrypt-hidden ne peut pas être combinée avec --allow-discards."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "L'option de taille de secteur avec l'action d'ouverture est uniquement supportée pour des périphérique ordinaires."
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "L'option des secteurs IV (vecteur d'initialisation) de grande taille est supportée uniquement à l'ouverture de périphériques de type simple avec une taille de secteur supérieure à 512 octets."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "L'option --test-passphrase est autorisée uniquement pour ouvrir des périphériques LUKS, TCRYPT, BITLK et FVAULT2."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Les options --device-size et --size ne peuvent pas être combinées."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "L'option --unbound est permise uniquement pour ouvrir un périphérique luks."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "L'option --unbound ne peut pas être utilisée sans --test-passphrase."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Les options --cancel-deferred et --deferred ne peuvent pas être utilisées en même temps."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Les options --reduce-device-size et --data-size ne peuvent pas être combinées."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "L'option --active-name peut uniquement être définie pour un périphérique LUKS2."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Les options --active-name et --force-offline-reencrypt ne peuvent pas être combinées."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Une spécification d'emplacement de clé est requise."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Les options --align-payload et --offset ne peuvent pas être combinées."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "L'option --integrity-no-wipe peut uniquement être utilisée pour une action de formatage avec l'extension d'intégrité."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Seule une des deux possibilités --use-[u]random est autorisée."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "La taille de clé est requise avec l'option --unbound."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "L'action de jeton est invalide."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Le paramètre --key-description est requis pour l'action d'ajout d'un jeton."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "L'action requiert un jeton spécifique. Utilisez le paramètre --token-id."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "L'option --unbound est uniquement valable avec l'action d'ajout d'un jeton."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Les options --key-slot et --unbound ne peuvent pas être combinées."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "L'action requiert un jeton spécifique. Utilisez le paramètre --key-slot."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<périphérique> [--type <type>] [<nom>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "ouvrir le périphérique comme <nom>"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<nom>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "fermeture du périphérique (supprime le « mapping »)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "redimensionner le périphérique actif"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "afficher le statut du périphérique"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <chiffrement>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "chiffrement pour test de performance"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<périphérique>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "essayer de réparer les métadonnées sur le disque"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "rechiffrer le périphérique LUKS2"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "supprimer tous les emplacements de clés (supprime la clé de chiffrement)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "convertir LUKS depuis/vers le format LUKS2"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "définir les options de configuration permanentes pour LUKS2"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<périphérique> [<fichier de la nouvelle clé>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "formater un périphérique LUKS"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "ajouter une clé au périphérique LUKS"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<périphérique> [<fichier de clé>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "retire du périphérique LUKS la clé ou le fichier de clé fourni"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "modifie la clé ou le fichier de clé fourni pour le périphérique LUKS"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "converti une clé vers les nouveaux paramètres pbkdf"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<périphérique> <emplacement de clé>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "efface de façon sécurisée la clé avec le numéro <emplacement de clé> du périphérique LUKS"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "afficher l'UUID du périphérique LUKS"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "teste si <périphérique> a un en-tête de partition LUKS"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "affiche les informations LUKS de la partition"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "affiche les informations du périphérique TCRYPT"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "affiche les informations du périphérique BITLK"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "affiche les informations du périphérique FVAULT2"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Suspendre le périphérique LUKS et effacer de façon sécurisée la clé (toutes les entrées/sorties sont suspendues)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "Remettre en service le périphérique LUKS suspendu"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Sauvegarder l'en-tête et les emplacements de clés du périphérique LUKS"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Restaurer l'en-tête et les emplacements de clés du périphérique LUKS"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <périphérique>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "Manipuler les jetons LUKS2"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<action> est l'une de :\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Vous pouvez aussi utiliser les alias de l'ancienne syntaxe <action> :\n"
+"\touvrir : create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tfermer : remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nom> est le périphérique à créer dans %s\n"
+"<périphérique> est le périphérique chiffré\n"
+"<emplacement> est le numéro de l'emplacement de clé LUKS à modifier\n"
+"<fichier de clé> est un fichier optionnel contenant la nouvelle clé pour l'action luksAddKey\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Le format de métadonnées compilé par défaut est %s (pour l'action luksFormat).\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Le support du greffon de jeton externe LUKS2 est %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "intégré dans la compilation"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Chemin du greffon de jeton externe LUKS2 : %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "désactivé"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Clé compilée par défaut et paramètres de phrase secrète :\n"
+"\tTaille max. fichier de clé : %d ko, longueur max. interactive de phrase secrète %d (caractères)\n"
+"PBKDF par défaut pour LUKS1 : %s, temps d'itération : %d (ms)\n"
+"PBKDF par défaut pour LUKS2 : %s\n"
+"\tTemps d'itération: %d, Mémoire requise: %d ko, Threads parallèles: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Paramètres de chiffrement compilés par défaut :\n"
+"\tloop-AES: %s, Clé %d bits\n"
+"\tplain: %s, Clé: %d bits, Hachage mot de passe: %s\n"
+"\tLUKS: %s, Clé: %d bits, Hachage en-tête LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: La taille de clé par défaut en mode XTS (deux clés internes) sera doublée.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s : exige %s comme arguments."
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Emplacement de clé non valide."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "La taille du périphérique doit être un multiple d'un secteur de 512 octets."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "La spécification de la taille maximale de la zone chaude de rechiffrement est invalide."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "La taille de la clé doit être un multiple de 8 bits"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "La taille maximum réduite pour le périphérique est 1 GiB."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "La taille réduite doit être un multiple d'un secteur de 512 octets."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "L'option --priority peut uniquement être ignore/normal/prefer."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Afficher ce message d'aide"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Afficher, en résumé, la syntaxe d'invocation"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Afficher la version du paquet"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Options d'aide :"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPTION...] <action> <paramètres de l'action>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Il manque l'argument <action>."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Action inconnue."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "L'option --key-file est prioritaire par rapport à un fichier de clé spécifié en argument."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Un seul argument --key-file est autorisé."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "La fonction de dérivation d'une clé basée sur un mot de passe (PBKDF = Password-Based Key Derivation Function) peut uniquement être pbkdf2 ou argon2i/argon2id."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Les itérations forcées de PBKDF ne peuvent pas être combinées avec l'option de temps d'itération."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Les options --keyslot-cipher et --keyslot-key-size doivent être utilisées ensembles."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Aucune action réalisée. Invoqué avec l'option --test-args.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Impossible de désactiver le verrouillage des métadonnées."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Chaîne d'aléa spécifiée invalide."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Impossible de créer l'image de hachage %s en écriture."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Impossible de créer l'image FEC %s en écriture."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Impossible de créer le fichier de hachage racine %s en écriture."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Impossible d'écrire dans le fichier de hachage racine %s."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Le périphérique %s n'est pas un périphérique VERITY valable."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Impossible de lire le fichier de hachage racine %s."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Fichier de hachage racine %s invalide."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "Chaîne de hachage racine invalide."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Fichier de signature %s invalide."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Impossible de lire le fichier de signature %s."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "La commande exige <hachage_racine> ou l'option --root-hash-file comme argument."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<périph_données> <périph_hachage>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "formater le périphérique"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<périph_données> <périph_hachage> [<hachage_racine>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "vérifier le périphérique"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<périph_données> <nom> <périph_hachage> [<hachage_racine>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "afficher le statut du périphérique actif"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<périph_hachage>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "afficher les informations sur le disque"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nom> est le périphérique à créer sous %s\n"
+"<périph_données> est le périphérique de données\n"
+"<périph_hachage> est le périphérique contenant les données de vérification\n"
+"<hachage_racine> hachage du nœud racine sur <périph_hachage>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Paramètres compilés par défaut dans dm-verity :\n"
+"\tHachage: %s, Bloc données (octets): %u, Bloc hachage (octets): %u, Taille aléa: %u, Format hachage: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Les options --ignore-corruption et --restart-on-corruption ne peuvent être utilisées ensembles."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Les options --panic-on-corruption et --restart-on-corruption ne peuvent être utilisées ensembles."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Ceci écrasera les données sur %s et %s de manière irrévocable.\n"
+"Pour préserver le périphérique de données, utilisez l'option --no-wipe (et ensuite activez-le avec --integrity-recalculate)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formaté avec une taille de balise de %u, intégrité interne %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Définir le fanion pour le recalcul n'est pas supporté, envisagez plutôt d'utiliser --wipe."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Le périphérique %s n'est pas un périphérique INTEGRITY valable."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<périph_intégrité>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<périph_intégrigé> <nom>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<nom> est le périphérique à créer sous %s\n"
+"<périph_intégrité> est le périphérique contenant les données avec les balises d'intégrité\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Paramètres compilés par défaut dans dm-integrity :\n"
+"\tAlgorithme de somme de contrôle : %s\n"
+"\tTaille maximale du fichier de clé : %dko\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "La taille --%s n'est pas valide. Le maximum est %u octets."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Les options du fichier de clé et de la taille de la clé doivent être spécifiées toutes les deux."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Les options du fichier de clé de l'intégrité du journal et de la taille de la clé doivent être spécifiées toutes les deux."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "L'algorithme d'intégrité du journal doit être spécifié si la clé d'intégrité du journal est utilisée."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Les options du fichier de clé de chiffrement du journal et de la taille de la clé doivent être spécifiées toutes les deux."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "L'algorithme de chiffrement du journal doit être spécifié si la clé de chiffrement du journal est utilisée."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Les options de mode récupération et champ de bits sont mutuellement exclusives."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Les options de journal ne peuvent pas être utilisées en mode champ de bits."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Les options de champ de bits peuvent uniquement être utilisées en mode champ de bits."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"ATTENTION !\n"
+"===========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Êtes-vous sûr ? (Typez « yes » en majuscules) : "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Erreur de lecture de la réponse depuis le terminal."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Commande réussie."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "paramètres erronés ou manquants"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "Aucune permission ou mauvais mot de passe"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "mémoire épuisée"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "mauvais périphérique ou fichier spécifié"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "le périphérique existe déjà ou est utilisé"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "erreur inconnue"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "La commande a échoué avec le code %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Emplacement de clef %i créé."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Emplacement de clé %i déverrouillé."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Emplacement de clé %i supprimé."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Jeton %i créé."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Jeton %i supprimé."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Aucun jeton n'a pu être déverrouillé avec ce code PIN."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Jeton %i requiert un code PIN."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Le jeton (type %s) exige un code PIN."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Le jeton %i ne sait pas déverrouiller le/les emplacement(s) de clé assigné(s) (mauvaise phrase secrète pour l'emplacement de clé)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Le jeton (type %s) ne sait pas déverrouiller le/les emplacement(s) de clé assigné(s) (mauvaise phrase secrète pour l'emplacement de clé)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Le jeton %i a besoin d'une ressource supplémentaire qui est manquante."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Le jeton (type %s) a besoin d'une ressource supplémentaire qui est manquante."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Aucun jeton (type %s) utilisable est disponible."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Aucun jeton utilisable est disponible."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Impossible de lire le fichier de clé %s."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Échec à la lecture de %d octets du fichier de clé %s."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Impossible d'ouvrir le fichier de clé %s en écriture."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Impossible d'écrire dans le fichier de clé %s."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> jours"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> %s écrits"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "vitesse %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Progression : %5.1f%%, Fin prévue %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Terminé, temps %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Ne peut vérifier la qualité du mot de passe : %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Échec de la vérification de la qualité du mot de passe :\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Échec de la vérification de la qualité du mot de passe : Mauvais mot de passe (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "Erreur de lecture de la phrase secrète depuis la console."
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "Vérifiez la phrase secrète : "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "Les phrases secrètes ne sont pas identiques."
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "Le décalage n'est pas possible si l'entrée provient de la console."
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Saisissez la phrase secrète : "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Saisissez la phrase secrète pour %s : "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "Aucune clé disponible avec cette phrase secrète."
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "Aucun emplacement de clé utilisable est disponible."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Impossible de vérifier une phrase secrète non saisie sur une console."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Impossible d'ouvrir le fichier %s en lecture seule."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Fournissez le jeton LUKS valide au format JSON:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Impossible de lire le fichier JSON."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Lecture interrompue."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Impossible d'ouvrir le fichier %s en écriture seule."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Écriture interrompue."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Erreur lors de l'écriture du fichier JSON."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Périphérique dm actif auto-détecté « %s » pour le périphérique de données %s.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Échec de l'auto-détection des containers du périphérique %s."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Le périphérique %s n'est pas un périphérique blocs.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Impossible de décider si le périphérique %s est actif ou non.\n"
+"Êtes-vous sûr de vouloir procéder au rechiffrement en mode hors-ligne ?\n"
+"Les données pourraient être corrompues si le périphérique est réellement activé.\n"
+"Pour exécuter le rechiffrement en mode en ligne, utilisez le paramètre --active-name.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Le périphérique %s n'est pas un périphérique bloc. Impossible de détecter s'il est actif ou non.\n"
+"Utilisez --force-offline-reencrypt pour passer outre la vérification et exécuter en mode hors-ligne (dangereux !)."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "L'option --resilience demandée ne peut pas être appliquée à l'opération de rechiffrement courante."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Le périphérique n'est pas en cour de chiffrement LUKS2. Option --encrypt conflictuelle."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Le périphérique n'est pas en cours de déchiffrement LUKS2. Option --decrypt conflictuelle."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Le périphérique est en cours de rechiffrement en utilisant la résilience datashift. L'option --resilience demandée ne peut pas être appliquée."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Le périphérique requiert une récupération de rechiffrement. Exécuter d'abord une réparation."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Le périphérique %s est déjà en cours de rechiffrement LUKS2. Voulez-vous redémarrer l'opération précédemment initialisée ?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Le rechiffrement LUKS2 historique n'est plus supporté."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Le rechiffrement d'un périphérique avec un profil d'intégrité n'est pas supporté."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"La taille de secteur demandée avec --sector-size %<PRIu32> est incompatible avec le superbloc %s\n"
+"(taille de bloc : %<PRIu32> octets) détecté sur le périphérique %s."
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Le chiffrement sans en-tête détaché (--header) n'est pas possible sans une réduction de la taille du périphérique de données (--reduce-device-size)"
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Le décalage de données demandé doit être inférieur ou égal à la moitié du paramètre --reduce-device-size."
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Ajustement de la valeur de --reduce-device-size à deux fois --offset %<PRIu64> (secteurs).\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Le fichier temporaire d'en-tête %s existe déjà. Abandon."
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Impossible de créer le fichier temporaire d'en-tête %s."
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "La taille des métadonnées LUKS2 est plus grande que la valeur de décalage des données."
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Impossible de placer le nouvel en-tête au début du périphérique %s."
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s est maintenant actif et prêt pour un chiffrement en ligne.\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Le périphérique actif %s n'est pas LUKS2."
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "Restauration de l'en-tête LUKS2 original."
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "Échec de la restauration de l'en-tête LUKS2 original."
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Le fichier d'en-tête %s n'existe pas. Voulez-vous initialiser le déchiffrement LUKS2 du périphérique %s et exporter l'en-tête LUKS2 dans le fichier %s ?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Échec de l'ajout des permissions lecture/écriture pour exporter le fichier d'en-tête."
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "L'initialisation du rechiffrement a échoué. La sauvegarde de l'en-tête est disponible dans %s."
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "Le déchiffrement LUKS2 est uniquement supporté avec un périphérique à l'en-tête détaché (avec l'offset de données défini à 0)."
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "Pas assez d'emplacements de clés libres pour le rechiffrement."
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Le fichier de clé peut uniquement être utilisé avec --key-slot ou avec exactement un seul emplacement de clé actif."
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Entrez la phrase secrète pour l'emplacement de clé %d : "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Entrez la phrase secrète pour l'emplacement de clé %u : "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Basculement de l'algorithme de chiffrement de données vers %s.\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Aucun paramètre de segment de donnée changé. Rechiffrement abandonné."
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"L'augmentation de la taille du secteur de chiffrement n'est pas supportée sur un périphérique hors-ligne.\n"
+"Activez d'abord le périphérique ou utilisez l'option --force-offline-reencrypt (dangereux !)."
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Rechiffrement interrompu."
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Redémarrage du rechiffrement LUKS en mode hors-ligne forcé.\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Le périphérique %s contient des métadonnées LUKS endommagées. L'opération est abandonnée."
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Le périphérique %s est déjà un périphérique LUKS. L'opération est abandonnée."
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Le périphérique %s est déjà en cours de rechiffrement LUKS. L'opération est abandonnée."
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "Le déchiffrement LUKS2 requiert l'option --header."
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "La commande exige un périphérique comme argument."
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Versions conflictuelles. Le périphérique %s est LUKS1."
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Versions conflictuelles. Le périphérique %s est en cours de rechiffrement LUKS1."
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Versions conflictuelle. Le périphérique %s est LUKS2"
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Versions conflictuelles. Le périphérique %s est en cours de rechiffrement LUKS2."
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Rechiffrement LUKS2 déjà initialisé. Abandon de l'opération."
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "Le rechiffrement du périphérique n'est pas en cours."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Impossible d'ouvrir exclusivement %s : périphérique utilisé."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "La réservation de la mémoire alignée a échoué."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Impossible de lire le périphérique %s."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Marque le périphérique LUKS1 %s comme inutilisable."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Impossible d'écrire le périphérique %s."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Impossible d'écrire le journal de re-chiffrement."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Impossible de lire le journal de re-chiffrement."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Format de journal incorrect."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Fichier journal %s existe. Reprise du re-chiffrement.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Activation du périphérique temporaire en utilisant l'ancien en-tête LUKS."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Activation du périphérique temporaire un utilisant le nouvel en-tête LUKS."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Échec de l'activation des périphériques temporaires."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Impossible de définir les offsets des données."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Impossible de définir la taille des métadonnées."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Nouvel en-tête LUKS créé pour le périphérique %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Sauvegarde de l'en-tête %s du périphérique %s créée."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "La création de la sauvegarde des en-têtes LUKS a échoué."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Impossible de rétablir l'en-tête %s sur le périphérique %s."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "En-tête %s rétabli sur le périphérique %s."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Impossible d'ouvrir le périphérique LUKS temporaire."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Impossible d'obtenir la taille du périphérique."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "Erreur E/S pendant le re-chiffrement."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Le UUID fourni est invalide."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Impossible d'ouvrir le journal de re-chiffrement."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Pas de déchiffrement en cours. Le UUID fourni ne peut être utilisé que pour reprendre un déchiffrement suspendu."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Le re-chiffrement va changer : %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "clé de volume"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "change hachage en "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", change chiffrement en "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "ATTENTION: Le périphérique %s contient déjà une signature pour une partition « %s ».\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "ATTENTION: Le périphérique %s contient déjà une signature pour un superblock « %s ».\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Impossible d'initialiser les sondes de la signature du périphérique."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Impossible d'exécuter « stat » sur le périphérique %s."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Impossible d'ouvrir le fichier %s en mode lecture/écriture."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "La signature de partition « %s » existante sur le périphérique %s sera effacée."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "La signature de superbloc « %s » existante sur le périphérique %s sera effacée."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Impossible d'effacer la signature du périphérique."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Impossible de sonder le périphérique %s pour une signature."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "La spécification de taille est invalide dans le paramètre --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "L'option --%s n'est pas permise avec l'action %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Erreur lors de l'écriture du json du jeton ssh."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Greffon expérimental pour cryptsetup ayant pour but de déverrouiller des périphériques LUKS2 avec un jeton connecté à un serveur SSH\vCe greffon permet actuellement d'ajouter un jeton à un emplacement de clé existant.\n"
+"\n"
+"Le serveur SSH spécifié doit contenir un fichier de clé dans le chemin spécifié avec une phrase secrète pour l'emplacement de clé existant sur le périphérique.\n"
+"Les informations d'identification fournies seront utilisées par cryptsetup pour obtenir le mot de passe lors de l'ouverture du périphérique utilisant le jeton.\n"
+"\n"
+"Note : L'information fournie en ajoutant le jeton (adresse du serveur SSH, utilisateur et chemins) sont stockés dans l'en-tête LUKS2 sous forme de texte clair."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<action> <périphérique>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Options pour l'action « add » :"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "Adresse IP/URL du serveur distant pour ce jeton"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Nom d'utilisateur utilisé pour le serveur distant"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Chemin vers le fichier de clé sur le serveur distant"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Chemin vers la clé SSH pour se connecter au serveur distant"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Emplacement de clé à assigner au jeton. Si non spécifié, le jeton sera assigné au premier emplacement de clé correspondant à la phrase secrète fournie."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Options génériques :"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Afficher des messages d'erreur plus détaillés"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Afficher les messages de débogage"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Montrer les messages de débogage incluant les métadonnées JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Impossible d'ouvrir et d'importer la clé privée :\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Impossible d'importer la clé privée (protégée par mot de passe ?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "mot de passe de %s@%s : "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Échec lors de l'analyse des arguments.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Une action doit être spécifiée\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Le périphérique doit être spécifié pour l'action « %s ».\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Le serveur SSH doit être spécifié pour l'action « %s ».\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "L'utilisateur SSH doit être spécifié pour l'action « %s ».\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Le chemin SSH doit être spécifié pour l'action « %s ».\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Le chemin de la clé SSH doit être spécifié pour l'action « %s ».\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Échec de l'ouverture de %s en utilisant les identifiants fournis.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Seule l'action « add » est actuellement supportée par ce greffon.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Impossible de créer la session sftp : "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Impossible d'initialiser la session sftp : "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Impossible d'ouvrir la session sftp : "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Impossible d'exécuter stat sur le fichier sftp : "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Pas assez de mémoire.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Impossible de lire la clé distante : "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Échec de connexion : "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Serveur inconnu : "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "La méthode d'authentification par clé publique n'est pas permise sur l'hôte.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Erreur durant l'authentification par clé publique : "
+
+#~ msgid "WARNING: Data offset is outside of currently available data device.\n"
+#~ msgstr "AVERTISSEMENT: L'offset des données est en dehors du périphérique de données actuellement disponible.\n"
+
+#~ msgid "Cannot get process priority."
+#~ msgstr "Impossible d'obtenir la priorité du processus."
+
+#~ msgid "Cannot unlock memory."
+#~ msgstr "Impossible de déverrouiller la mémoire."
+
+#~ msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+#~ msgstr "Le répertoire de verrouillage %s/%s sera créé avec les permissions par défaut fournies durant la compilation."
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Impossible de lire la signature BITLK depuis %s."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Signature invalide ou inconnue pour le périphérique BITLK."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Échec lors de l'effacement des données du segment de sauvegarde."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Impossible de désactiver le fanion de demande de rechiffrement."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Le chiffrement est uniquement supporté avec le format LUKS2."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "Périphérique LUKS détecté sur %s. Voulez-vous chiffrer à nouveau ce périphérique LUKS ?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "Seul le format LUKS2 est actuellement supporté. Veuillez utiliser l'outil cryptsetup-reencrypt pour LUKS1."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Un rechiffrement hors-ligne historique est déjà en cours. Utilisez l'utilitaire cryptsetup-reencrypt."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "Le périphérique LUKS2 n'est pas en rechiffrement."
+
+#~ msgid "Reencryption already in-progress."
+#~ msgstr "Re-chiffrement déjà en cours."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "Activation du fanion de re-chiffrement hors-ligne de LUKS2 sur le périphérique %s."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Cette version de cryptsetup-reencrypt ne gère pas le nouveau type de jeton interne %s."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Échec lors de la lecture des fanions d'activation depuis l'en-tête de sauvegarde."
+
+#~ msgid "Failed to write activation flags to new header."
+#~ msgstr "Échec lors de l'écriture des fanions d'activation dans le nouvel en-tête."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "Les paramètres pbkdf ont été changés dans l'emplacement de clé %i."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Seules les valeurs entre 1 MiB et 64 MiB sont permises pour la taille des blocs de re-chiffrement."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "La taille maximum réduite pour le périphérique est 64 MiB."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[OPTION...] <périph>"
+
+#~ msgid "Argument required."
+#~ msgstr "Argument requis."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "L'option --new doit être utilisée avec --reduce-device-size ou --header."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "L'option --keep-key ne peut être utilisée que avec --hash, --iter-time ou --pbkdf-force-iterations²."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "L'option --new ne peut pas être utilisée avec --decrypt."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "L'option --decrypt est incompatible avec les paramètres spécifiés."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "L'option --uuid ne peut être utilisée qu'avec --decrypt."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Type luks invalide. Utilisez « luks », « luks1 » ou « luks2 »."
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Le périphérique %s est utilisé. Impossible de continuer avec l'opération de formatage."
+
+#~ msgid "No free token slot."
+#~ msgstr "Aucun emplacement de jeton libre"
+
+#~ msgid "Failed to create builtin token %s."
+#~ msgstr "Échec lors de la création du jeton intégré %s"
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Type de périphérique LUKS invalide."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "L'algorithme de chiffrement utilisé pour chiffrer le disque (voir /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "L'algorithme de hachage utilisé pour créer la clé de chiffrement à partir de la phrase secrète"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Vérifier la phrase secrète en la demandant deux fois"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Lire la clef depuis un fichier"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Lire la clé (maîtresse) du volume depuis un fichier."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Lister les informations de la clé (maîtresse) de volume au lieu des autres emplacements de clefs"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "La taille de la clé de chiffrement"
+
+#~ msgid "BITS"
+#~ msgstr "BITS"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Limite la lecture d'un fichier de clé"
+
+#~ msgid "bytes"
+#~ msgstr "octets"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Nombre d'octets à ignorer dans le fichier de clé"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Limite la lecture d'un nouveau fichier de clé ajouté"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Nombre d'octets à ignorer dans le fichier de clé nouvellement ajouté"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Numéro de l'emplacement pour la nouvelle clé (par défaut, le premier disponible)"
+
+#~ msgid "The size of the device"
+#~ msgstr "La taille du périphérique"
+
+#~ msgid "SECTORS"
+#~ msgstr "SECTEURS"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Utiliser uniquement la taille demandée du périphérique (ignore le reste du périphérique). DANGEREUX !"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Le décalage de départ dans le périphérique sous-jacent"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Combien de secteurs de données chiffrées à ignorer au début"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Crée une association en lecture seule"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Ne pas demander confirmation"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Délai d'expiration de la demande interactive de phrase secrète (en secondes)"
+
+#~ msgid "secs"
+#~ msgstr "s"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Mise à jour de la ligne de progression (en secondes)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Nombre de tentatives possibles pour entrer la phrase secrète"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Utiliser une limite de <n> secteurs pour aligner les données – pour luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Fichier contenant une sauvegarde de l'en-tête LUKS et des emplacements de clés"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Utiliser /dev/random pour générer la clé de volume"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Utiliser /dev/urandom pour générer la clé de volume"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Partager le périphérique avec un autre segment chiffré sans recouvrement"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "UUID du périphérique à utiliser"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Autoriser les demandes d'abandon (TRIM) pour le périphérique"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Périphérique ou fichier avec un en-tête LUKS séparé"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Ne pas activer le périphérique. Vérifie simplement le phrase secrète"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Utilise l'en-tête caché (périphérique TCRYPT caché)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Le périphérique est un lecteur TCRYPT système (avec secteur d'amorçage)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Utiliser l'en-tête TCRYPT de secours (secondaire)"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Recherche aussi des périphériques compatibles avec VeraCrypt"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Multiplicateur d'Itération Personnel pour le périphérique compatible avec VeraCrypt"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Interroger le Multiplicateur d'Itération Personnel pour le périphérique compatible avec VeraCrypt"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Type de métadonnées du périphérique : luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Désactive la vérification de la qualité du mot de passe (si activé)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Utilise l'option de compatibilité de performance dm-crypt same_cpu_crypt"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Utilise l'option de compatibilité de performance dm-crypt submit_from_crypt_cpus"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Passer outre la queue de travail de dm-crypt et traiter les requêtes en lecture de manière synchrone"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Passer outre la queue de travail de dm-crypt et traiter les requêtes en écriture de manière synchrone"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "La suppression du périphérique est différée jusqu'à ce que le dernier utilisateur le ferme"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Utiliser un verrou global pour sérialiser PBKDF qui utilise beaucoup de mémoire (évite le OOM)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "Temps d'itération de PBKDF pour LUKS (en ms)"
+
+#~ msgid "msecs"
+#~ msgstr "ms"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "Algorithme PBKDF (pour LUKS2): argon2i, argon2id, pbkdf2"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "Limite de coût mémoire PBKDF"
+
+#~ msgid "kilobytes"
+#~ msgstr "kilooctets"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "Coût parallèle PBKDF"
+
+#~ msgid "threads"
+#~ msgstr "threads"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "Coût d'itération PBKDF (forcé, désactive l'étalon)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Priorité de l'emplacement de clé: ignore, normal, prefer"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Désactiver le verrouillage des métadonnées sur le disque"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Désactiver le chargement des clés de volume via le porte-clé du noyau"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Algorithme d'intégrité des données (uniquement LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Désactiver le journal pour le périphérique d'intégrité"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Ne pas effacer le périphérique après le formatage"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Utiliser le rembourrage historique inefficace (vieux noyaux)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Ne pas demander le mot de passe si l'activation par jeton échoue"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Numéro de jeton (défaut: n'importe lequel)"
+
+#~ msgid "Key description"
+#~ msgstr "Description de clé"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Taille du secteur de chiffrement (défaut: 512 octets)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Utiliser le IV (vecteur d'initialisation) compté en taille de secteurs (pas en multiple de 512 octets)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Définir les fanions d'activation comme permanents pour le périphérique"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Définir l'étiquette pour le périphérique LUKS2"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Définir l'étiquette de sous-système pour le périphérique LUKS2"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Créer ou déverser un emplacement de clé LUKS2 non lié (aucun segment de donnée assigné)"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Lire ou écrire le json depuis ou vers un fichier"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Taille de la zone de métadonnées de l'en-tête LUKS2"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Taille de la zone des emplacements de clés de l'en-tête LUKS2"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Rafraîchir (réactiver) le périphérique avec de nouveaux paramètres"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "Emplacement de clé LUKS2: La taille de la clé de chiffrement"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "Emplacement de clé LUKS2: Le chiffrement utilisé pour le chiffrement de l'emplacement de clé"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Chiffrer le périphérique LUKS2 (chiffrement sur place)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Déchiffrer le périphérique LUKS2 (supprime le chiffrement)"
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Initialiser le rechiffrement LUKS2 uniquement dans les métadonnées."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Redémarrer uniquement le rechiffrement LUKS2 initialisé."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Réduire la taille des données du périphérique (déplace le décalage des données). DANGEREUX !"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Taille maximale de la zone chaude de rechiffrement."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Rechiffre le type de résilience de la zone chaude (checksum,journal,none)"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Rechiffrer le hachage des sommes de contrôle de la zone chaude"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Outrepasser l'auto-détection du périphérique pour le périphérique dm à rechiffrer"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "L'option --deferred est permise uniquement avec la commande close."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "L'option --allow-discards est permise uniquement pour une opération d'ouverture."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "L'option --persistent est permise uniquement pour une opération d'ouverture."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "L'option --serialize-memory-hard-pbkdf est permise uniquement pour une opération d'ouverture."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "L'option --key-size est permise seulement avec les actions luksFormat, luksAddKey,\n"
+#~ "open et benchmark. Pour limiter la lecture depuis un fichier de clé, utilisez --keyfile-size=(octets)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "L'option --integrity est autorisée uniquement avec luksFormat (LUKS2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Les options --label et --subsystem sont permises uniquement pour les opérations luksFormat et config LUKS2."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "Nombre négatif non autorisé pour l'option."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "L'option --use-[u]random est autorisée seulement avec luksFormat."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "L'option --uuid est autorisée seulement avec luksFormat et luksUUID."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "L'option --align-payload est autorisée uniquement avec luksFormat."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Les options --luks2-metadata-size et --opt-luks2-keyslots-size sont permises uniquement pour luksFormat avec LUKS2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Spécification de taille de métadonnées LUKS2 invalide."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Spécification de taille d'emplacements de clés LUKS2 invalide."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "L'option --offset est supportée uniquement pour ouvrir des périphériques ordinaires et loopaes, luksFormat et le rechiffrement de périphérique."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Argument invalide fourni pour le paramètre --veracrypt-pim."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "L'option de taille de secteur n'est pas supportée pour cette commande."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "L'option --refresh peut uniquement être utilisée avec l'action open."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "La taille de périphérique spécifiée est invalide."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Débordement de la taille de réduction."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Ne pas utiliser le superbloc de verity"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Type de format (1: normal ; 0: Chrome OS)"
+
+#~ msgid "number"
+#~ msgstr "nombre"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Taille de bloc sur le périphérique de données"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Taille de bloc sur le périphérique de hachage"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "Octets de parité FEC"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Le nombre de blocs dans le fichier de données"
+
+#~ msgid "blocks"
+#~ msgstr "blocs"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Chemin vers le périphérique avec les données de correction d'erreurs"
+
+#~ msgid "path"
+#~ msgstr "chemin"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Décalage de départ sur le périphérique de hachage"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Décalage de départ sur le périphérique FEC"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Algorithme de hachage"
+
+#~ msgid "string"
+#~ msgstr "chaîne"
+
+#~ msgid "Salt"
+#~ msgstr "Aléa"
+
+#~ msgid "hex string"
+#~ msgstr "chaîne hexa"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Chemin du fichier de signature du hachage racine"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Redémarrer le noyau si une corruption est détectée"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Faire paniquer le noyau si une corruption est détectée"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Ignore la corruption, elle est seulement enregistrée dans le journal"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Ne pas vérifier les blocs mis à zéro"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Vérifier le bloc de données uniquement à la première lecture"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "L'option --ignore-corruption, --restart-on-corruption ou --ignore-zero-blocks est seulement permise pour une opération d'ouverture."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "L'option --root-hash-signature peut uniquement être utilisée avec l'opération open."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Chemin vers le périphérique de données (si séparé)"
+
+#~ msgid "Journal size"
+#~ msgstr "Taille du journal"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Secteurs d'entrelacement"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Filigrane du journal"
+
+#~ msgid "percent"
+#~ msgstr "pourcent"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Temps pour écrire le journal"
+
+#~ msgid "ms"
+#~ msgstr "ms"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Nombre de secteurs de 512 octets par bit (mode champ de bit)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Temps de purge du mode champ de bit"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Taille de balise (par secteur)"
+
+#~ msgid "Sector size"
+#~ msgstr "Taille de secteur"
+
+#~ msgid "Buffers size"
+#~ msgstr "Taille des tampons"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Algorithme d'intégrité des données"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "La taille de la clé d'intégrité des données"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Lire la clef d'intégrité depuis un fichier"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Algorithme d'intégrité du journal"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "La taille de la clé du journal d'intégrité"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Lire la clé du journal d'intégrité depuis un fichier"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Algorithme de chiffrement du journal"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "La taille de la clé de chiffrement du journal"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Lire la clé de chiffrement du journal depuis un fichier"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Mode récupération (pas de journal, pas de vérification des balises)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Utiliser un champ de bits pour garder une trace des changements et désactiver le journal sur le périphérique d'intégrité"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Recalculer les balises initiales automatiquement."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Ne pas protéger le superbloc avec HMAC (anciens noyaux)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Autoriser le recalcul des volumes avec des clés HMAC (anciens noyaux)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "L'option --integrity-recalculate peut uniquement être utilisée avec l'action open."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Les options --journal-size, --interleave-sectors, --sector-size, --tag-size et --no-wipe peuvent uniquement être utilisée avec l'action de format."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "La spécification de la taille du journal est invalide."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Taille de bloc de re-chiffrement"
+
+#~ msgid "MiB"
+#~ msgstr "MiB"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Ne pas changer la clé, pas de re-chiffrement de la zone de donnée"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Lire la nouvelle clé (maîtresse) du volume depuis un fichier"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Utiliser direct-io pour accéder aux périphériques"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Utiliser fsync après chaque bloc"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Mettre le journal à jour après chaque bloc"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Utiliser uniquement cet emplacement (les autres seront désactivés)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Créer un nouvel en-tête sur le périphérique non chiffré"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Déchiffrer le périphérique de manière permanente (supprime le chiffrement)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "Le UUID utilisé pour poursuivre le déchiffrement"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Type de métadonnées LUKS: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "ATTENTION: Le répertoire verrou %s/%s est manquant !\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Mauvais paramètres de taille pour le périphérique verity."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "L'algorithme d'intégrité doit être spécifié si la clé d'intégrité est utilisée."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Mauvaise taille de clé."
+
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands."
+#~ msgstr "Le paramètre --refresh est permis uniquement avec les commandes open ou refresh."
+
+#~ msgid "Unsupported encryption sector size.\n"
+#~ msgstr "Taille de secteur de chiffrement non supportée.\n"
+
+#~ msgid "Offline reencryption in progress. Aborting."
+#~ msgstr "Un rechiffrement hors-ligne est en cours. Interruption."
+
+#~ msgid "Online reencryption in progress. Aborting."
+#~ msgstr "Un rechiffrement en-ligne est en cours. Interruption."
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Interrompu par un signal."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "Fonction pas disponible en mode FIPS."
+
+#~ msgid "Failed to finalize hash."
+#~ msgstr "Impossible de terminer le hachage."
+
+#~ msgid "Invalid resilience parameters (internal error)."
+#~ msgstr "Paramètres de résilience invalides (erreur interne)."
+
+#~ msgid "Failed to assign new enc segments."
+#~ msgstr "Échec lors de l'assignation des nouveaux segments enc."
+
+#~ msgid "Failed to assign digest %u to segment %u."
+#~ msgstr "Impossible d'affecter le résumé %u au segment %u."
+
+#~ msgid "Failed to assign reencrypt previous backup segment."
+#~ msgstr "Échec lors de l'assignation du segment de sauvegarde précédent rechiffré."
+
+#~ msgid "Failed to assign reencrypt final backup segment."
+#~ msgstr "Échec lors de l'assignation du segment de sauvegarde final rechiffré."
+
+#~ msgid "Failed generate 2nd segment."
+#~ msgstr "Échec lors de la génération du 2ème segment."
+
+#~ msgid "Failed generate 1st segment."
+#~ msgstr "Échec lors de la génération du 1er segment."
+
+#~ msgid "Failed to allocate device %s."
+#~ msgstr "Impossible d'allouer le périphérique %s."
+
+#~ msgid "Failed to allocate dm segments."
+#~ msgstr "Échec de l'allocation des segments dm."
+
+#~ msgid "Failed to create dm segments."
+#~ msgstr "Échec lors de la création des segments dm."
+
+#~ msgid "Failed to allocate device for new backing device."
+#~ msgstr "Impossible d'allouer le périphérique pour le nouveau périphérique de soutien."
+
+#~ msgid "Failed to reload overlay device %s."
+#~ msgstr "Impossible de recharger le périphérique de surcouche %s."
+
+#~ msgid "Failed to refresh helper devices."
+#~ msgstr "Échec lors du rafraichissement des périphériques de support."
+
+#~ msgid "Failed to create reencryption backup segments."
+#~ msgstr "Échec lors de la création des segments de sauvegarde du rechiffrement."
+
+#~ msgid "Failed to set online-reencryption requirement."
+#~ msgstr "Impossible de définir les exigences du rechiffrement en ligne."
+
+#~ msgid "Failed to hash sector at offset %zu."
+#~ msgstr "Échec du hachage du secteur à l'offset %zu."
+
+#~ msgid "Failed to read sector hash."
+#~ msgstr "Erreur de lecture du hachage du secteur."
+
+#~ msgid "Error: Calculated reencryption offset %<PRIu64> is beyond device size %<PRIu64>."
+#~ msgstr "Erreur: Le décalage de rechiffrement calculé %<PRIu64> est au delà de la taille du périphérique %<PRIu64>"
+
+#~ msgid "Failed to calculate new segments."
+#~ msgstr "Échec lors du calcul des nouveaux segments."
+
+#~ msgid "Failed finalize hotzone resilience, retval = %d"
+#~ msgstr "Échec de finalisation de la résilience de la zone chaude, retval = %d"
+
+#~ msgid "Failed to write data."
+#~ msgstr "Erreur lors de l'écriture des données."
+
+#~ msgid "Failed to update metadata or reassign device segments."
+#~ msgstr "Échec de la mise à jour des métadonnées ou de la réaffectation des segments du périphérique."
+
+#~ msgid "Failed to reload %s device."
+#~ msgstr "Erreur au rechargement du périphérique %s."
+
+#~ msgid "Failed to erase backup segments"
+#~ msgstr "Échec lors de l'effacement des segments de sauvegarde."
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Les options de performance dmcrypt demandées ne sont pas supportées."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "Impossible de formater le périphérique %s qui est déjà en cours d'utilisation."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "L'emplacement de clé %d n'est pas utilisé."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "Emplacement de clé %d sélectionné pour suppression."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "ouvrir un périphérique avec <nom> comme « mapping »"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "fermeture du périphérique (désactive et supprime le « mapping »)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "Impossible de définir les paramètres PBKDF."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "Impossible de se déplacer au décalage du périphérique.\n"
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Le périphérique %s est trop petit (LUKS2 a besoin d'au moins %<PRIu64> octets)."
+
+#~ msgid "Replaced with key slot %d."
+#~ msgstr "Remplacé par l'emplacement de clé %d."
+
+#~ msgid "Missing LUKS target type, option --type is required."
+#~ msgstr "Type de cible LUKS manquant, l'option --type est requise."
+
+#~ msgid "Missing --token option specifying token for removal."
+#~ msgstr "Il manque l'option --token pour spécifier le jeton à retirer."
+
+#~ msgid "Add or remove keyring token"
+#~ msgstr "Ajoute ou retire le jeton du porte-clé"
+
+#~ msgid "Activated keyslot %i."
+#~ msgstr "Emplacement de clé activé %i."
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "erreur d'allocation de mémoire dans action_luksFormat"
+
+#~ msgid "Key slot is invalid.\n"
+#~ msgstr "Emplacement de clé non valide.\n"
+
+#~ msgid "Using default pbkdf parameters for new LUKS2 header.\n"
+#~ msgstr "Utilisation des paramètres pbkdf par défaut pour le nouvel en-tête LUKS2.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Trop de niveaux dans l'arborescence du volume verity.\n"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "La clé %d n'est pas active. Impossible de l'effacer.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<nom> <périph_données> <périph_hachage> <hachage_racine>"
+
+#~ msgid "create active device"
+#~ msgstr "créer le périphérique actif"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "supprime (désactive) le périphérique"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Progression: %5.1f%%, ETA %02llu:%02llu, %4llu MiB écrits, vitesse %5.1f MIB/s%s"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Impossible de trouver un périphérique loopback libre.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Impossible d'ouvrir le périphérique %s\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Le UUID passé ne peut pas être utilisé à moins qu'un déchiffrement ne soit en cours.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "Marque le périphérique LUKS %s comme utilisable.\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "ATTENTION : ce code est expérimental. Il peut complètement détruire vos données.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "La vérification de la somme de contrôle FIPS a échoué.\n"
+
+#~ msgid "WARNING: device %s is a partition, for TCRYPT system encryption you usually need to use whole block device path.\n"
+#~ msgstr "ATTENTION : le périphérique %s est une partition. Pour le chiffrement de système TCRYPT, vous avez généralement besoin du chemin d'un périphérique bloc entier.\n"
+
+#~ msgid "Enter LUKS passphrase: "
+#~ msgstr "Saisissez la phrase secrète LUKS : "
+
+#~ msgid "Enter new LUKS passphrase: "
+#~ msgstr "Entrez la nouvelle phrase secrète LUKS : "
+
+#~ msgid "Enter any LUKS passphrase: "
+#~ msgstr "Entrez n'importe quelle phrase secrète LUKS : "
+
+#~ msgid "Backup file %s doesn't exist.\n"
+#~ msgstr "Le fichier de sauvegarde %s n'existe pas.\n"
+
+#~ msgid "create device"
+#~ msgstr "créer un périphérique"
+
+#~ msgid "remove device"
+#~ msgstr "retirer le périphérique"
+
+#~ msgid "remove LUKS mapping"
+#~ msgstr "retire une association LUKS"
+
+#~ msgid "open loop-AES device as mapping <name>"
+#~ msgstr "ouvre un périphérique loop-AES avec pour nom associé <nom>"
+
+#~ msgid "remove loop-AES mapping"
+#~ msgstr "enlève une association loop-AES"
+
+#~ msgid "Key slot %d verified.\n"
+#~ msgstr "L'emplacement de clé %d a été vérifié.\n"
+
+#~ msgid "Cannot open device %s for %s%s access.\n"
+#~ msgstr "Impossible d'ouvrir le périphérique %s pour un accès %s%s.\n"
+
+#~ msgid "exclusive "
+#~ msgstr "exclusif "
+
+#~ msgid "read-only"
+#~ msgstr "en lecture seule"
+
+#~ msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+#~ msgstr "ATTENTION !!! La mémoire n'est peut-être pas sécurisée. Êtes-vous super-utilisateur ?\n"
+
+#~ msgid "Negative keyfile size not permitted.\n"
+#~ msgstr "Taille négative de fichier de clé non autorisée.\n"
+
+#~ msgid "Unable to obtain sector size for %s"
+#~ msgstr "Impossible d'obtenir la taille de secteur de %s"
+
+#~ msgid "Block mode XTS is available since kernel 2.6.24.\n"
+#~ msgstr "Le mode \"bloc\" XTS est disponible depuis le noyau 2.6.24.\n"
+
+#~ msgid "Key size in LRW mode must be 256 or 512 bits.\n"
+#~ msgstr "La taille de la clé en mode LRW doit être un multiple de 256 ou 512 bits.\n"
+
+#~ msgid "Block mode LRW is available since kernel 2.6.20.\n"
+#~ msgstr "Le mode \"bloc\" LRW est disponible depuis le noyau 2.6.20.\n"
+
+#~ msgid "Warning: exhausting read requested, but key file is not a regular file, function might never return.\n"
+#~ msgstr "Attention : requête de lecture, mais le fichier de clef n'est pas régulier, la procédure peut rester bloquée.\n"
+
+#~ msgid "Cannot find compatible device-mapper kernel modules.\n"
+#~ msgstr "Impossible de trouver des modules noyau compatibles avec device-mapper.\n"
+
+#~ msgid "Cannot open device: %s\n"
+#~ msgstr "Impossible d'ouvrir le périphérique : %s\n"
+
+#~ msgid "BLKROGET failed on device %s.\n"
+#~ msgstr "BLKROGET a échoué sur le périphérique %s.\n"
+
+#~ msgid "BLKGETSIZE failed on device %s.\n"
+#~ msgstr "BLKGETSIZE a échoué sur le périphérique %s.\n"
+
+#~ msgid "identical to luksKillSlot - DEPRECATED - see man page"
+#~ msgstr "identique à luksKillSlot - OBSOLÈTE - voir la page de man"
+
+#~ msgid "modify active device - DEPRECATED - see man page"
+#~ msgstr "modifier le périphérique actif - OBSOLÈTE - voir la page de man"
+
+#~ msgid ""
+#~ "The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\n"
+#~ "WARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"
+#~ msgstr ""
+#~ "L'action « reload » est obsolète. Merci d'utiliser « dmsetup reload » si vous avez vraiment besoin de cette fonctionnalité.\n"
+#~ "ATTENTION : n'utilisez pas « reload » sur des périphériques LUKS. Si c'est le cas, tapez Ctrl-C.\n"
+
+#~ msgid "Obsolete option --non-exclusive is ignored.\n"
+#~ msgstr "L'option obsolète --non-exclusive est ignorée.\n"
+
+#~ msgid "Read the key from a file (can be /dev/random)"
+#~ msgstr "Lit la clé depuis un fichier (qui peut être /dev/random)"
+
+#~ msgid "(Obsoleted, see man page.)"
+#~ msgstr "(Obsolète, voir la page de man)."
diff --git a/po/id.po b/po/id.po
new file mode 100644
index 0000000..bd56880
--- /dev/null
+++ b/po/id.po
@@ -0,0 +1,815 @@
+# Pesan bahasa Indonesia untuk cryptsetup.
+# Copyright (C) 2009 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Arif E. Nugroho <arif_endro@yahoo.com>, 2009, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 1.1.0-rc4\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2009-12-30 20:09+0100\n"
+"PO-Revision-Date: 2010-01-27 07:30+0700\n"
+"Last-Translator: Arif E. Nugroho <arif_endro@yahoo.com>\n"
+"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: lib/libdevmapper.c:48
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"
+msgstr "Tidak dapat menginisialisasi pemeta-perangkat. Apakah kernel modul dm_mod telah dimuat?\n"
+
+#: lib/libdevmapper.c:304
+#, c-format
+msgid "DM-UUID for device %s was truncated.\n"
+msgstr "DM-UUID untuk perangkat %s telah terpotong.\n"
+
+#: lib/setup.c:103
+#, c-format
+msgid "Cannot not read %d bytes from key file %s.\n"
+msgstr "Tidak dapat membaca %d bytes dari berkas kunci %s.\n"
+
+#: lib/setup.c:115
+msgid "Key processing error.\n"
+msgstr "Terjadi kesalahan dalam pengolahan kunci.\n"
+
+#: lib/setup.c:169
+msgid "All key slots full.\n"
+msgstr "Semua slot kunci telah penuh.\n"
+
+#: lib/setup.c:176 lib/setup.c:304 lib/setup.c:778
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d.\n"
+msgstr "Slot kunci %d tidak valid, mohon pilih diantara 0 dan %d.\n"
+
+#: lib/setup.c:182
+#, c-format
+msgid "Key slot %d is full, please select another one.\n"
+msgstr "Slot kunci %d penuh, mohon pilih yang lain.\n"
+
+#: lib/setup.c:201
+msgid "Enter any remaining LUKS passphrase: "
+msgstr "Masukan kata sandi LUKS yang tersisa: "
+
+#: lib/setup.c:222
+#, c-format
+msgid "Key slot %d verified.\n"
+msgstr "Slot kunci %d telah terverifikasi.\n"
+
+#: lib/setup.c:257
+#, c-format
+msgid "Cannot get info about device %s.\n"
+msgstr "Tidak dapat mendapatkan informasi mengenai perangkat %s.\n"
+
+#: lib/setup.c:264
+#, c-format
+msgid "Device %s has zero size.\n"
+msgstr "Perangkat %s memiliki ukuran nol.\n"
+
+#: lib/setup.c:268
+#, c-format
+msgid "Device %s is too small.\n"
+msgstr "Perangkat %s terlalu kecil.\n"
+
+#: lib/setup.c:293
+msgid "Enter LUKS passphrase to be deleted: "
+msgstr "Masukan kata sandi LUKS yang akan dihapus: "
+
+#: lib/setup.c:299
+#, c-format
+msgid "key slot %d selected for deletion.\n"
+msgstr "slot kunci %d terpilih untuk penghapusan.\n"
+
+#: lib/setup.c:310
+#, c-format
+msgid "Key %d not active. Can't wipe.\n"
+msgstr "Kunci %d tidak aktif. Tidak dapat menghapus.\n"
+
+#: lib/setup.c:316
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Ini adalah slot kunci terakhir. Perangkat mungkin akan menjadi tidak stabil setelah menghapus kunci ini."
+
+#: lib/setup.c:364 lib/setup.c:1651 lib/setup.c:1704 lib/setup.c:1761
+#, c-format
+msgid "Device %s already exists.\n"
+msgstr "Perangkat %s telah ada.\n"
+
+#: lib/setup.c:369
+#, c-format
+msgid "Invalid key size %d.\n"
+msgstr "Besar kunci %d tidak valid.\n"
+
+#: lib/setup.c:471 lib/setup.c:1656
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Masukan kata sandi untuk %s: "
+
+#: lib/setup.c:600 lib/setup.c:628 lib/setup.c:1365 lib/setup.c:1712
+msgid "Enter passphrase: "
+msgstr "Masukan kata sandi: "
+
+#: lib/setup.c:661 lib/setup.c:1040 lib/setup.c:1803
+#, c-format
+msgid "Device %s is not active.\n"
+msgstr "Perangkat %s tidak aktif.\n"
+
+#: lib/setup.c:770
+msgid "No known cipher specification pattern detected.\n"
+msgstr "Tidak ada pola spesifikasi cipher yang dikenal terdeteksi.\n"
+
+#: lib/setup.c:784
+msgid "Enter LUKS passphrase: "
+msgstr "Masukan kata sandi LUKS: "
+
+#: lib/setup.c:1060
+msgid "Invalid plain crypt parameters.\n"
+msgstr "Parameter crypt tidak valid.\n"
+
+#: lib/setup.c:1065
+msgid "Invalid key size.\n"
+msgstr "Ukuran kunci tidak valid.\n"
+
+#: lib/setup.c:1097
+msgid "Can't format LUKS without device.\n"
+msgstr "Tidak dapat memformat LUKS tanpat perangkat.\n"
+
+#: lib/setup.c:1112
+#, c-format
+msgid "Can't wipe header on device %s.\n"
+msgstr "Tidak dapat menghapus kepala di perangkat %s.\n"
+
+#: lib/setup.c:1154
+#, c-format
+msgid "Unknown crypt device type %s requested.\n"
+msgstr "Tipe perangkat sandi %s yang diminta tidak diketahui.\n"
+
+#: lib/setup.c:1187
+msgid "Cannot initialize crypto backend.\n"
+msgstr "Tidak dapat menginisialisasi backend crypto.\n"
+
+#: lib/setup.c:1261
+#, c-format
+msgid "Volume %s is not active.\n"
+msgstr "Volume %s tidak aktif.\n"
+
+#: lib/setup.c:1274
+#, c-format
+msgid "Volume %s is already suspended.\n"
+msgstr "Volume %s telah disuspend.\n"
+
+#: lib/setup.c:1300 lib/setup.c:1347 lib/setup.c:1406 lib/setup.c:1484
+#: lib/setup.c:1556 lib/setup.c:1601 lib/setup.c:1695 lib/setup.c:1752
+#: lib/setup.c:1873 lib/setup.c:1956 lib/setup.c:2056
+msgid "This operation is supported only for LUKS device.\n"
+msgstr "Operasi ini hanya didukunga untuk perangkat LUKS.\n"
+
+#: lib/setup.c:1311 lib/setup.c:1358
+#, c-format
+msgid "Volume %s is not suspended.\n"
+msgstr "Volume %s tidak disuspend.\n"
+
+#: lib/setup.c:1420 lib/setup.c:1498
+msgid "Cannot add key slot, all slots disabled and no volume key provided.\n"
+msgstr "Tidak dapat menambahkan slot kunci, seluruh slot tidak aktif dan tidak ada volume kunci yang disediakan.\n"
+
+#: lib/setup.c:1429 lib/setup.c:1504 lib/setup.c:1507
+msgid "Enter any passphrase: "
+msgstr "Masukan kata sandi: "
+
+#: lib/setup.c:1448 lib/setup.c:1522 lib/setup.c:1526 lib/setup.c:1579
+msgid "Enter new passphrase for key slot: "
+msgstr "Masukan kasa sandi baru untuk slot kunci: "
+
+#: lib/setup.c:1570 lib/setup.c:1772 lib/setup.c:1884
+msgid "Volume key does not match the volume.\n"
+msgstr "Kunci volume tidak cocok dengan volume.\n"
+
+#: lib/setup.c:1607
+#, c-format
+msgid "Key slot %d is invalid.\n"
+msgstr "Slot kunci %d tidak valid.\n"
+
+#: lib/setup.c:1612
+#, c-format
+msgid "Key slot %d is not used.\n"
+msgstr "Slot kunci %d tidak digunakan.\n"
+
+#: lib/setup.c:1799
+#, c-format
+msgid "Device %s is busy.\n"
+msgstr "Perangkat %s sibuk.\n"
+
+#: lib/setup.c:1807
+#, c-format
+msgid "Invalid device %s.\n"
+msgstr "Perangkat %s tidak valid.\n"
+
+#: lib/setup.c:1831
+msgid "Volume key buffer too small.\n"
+msgstr "Penyangga kunci volume terlalu kecil.\n"
+
+#: lib/setup.c:1839
+msgid "Cannot retrieve volume key for plain device.\n"
+msgstr "Tidak dapat mendapatkan kunci volume untuk perangkat.\n"
+
+#: lib/setup.c:1861
+#, c-format
+msgid "This operation is not supported for %s crypt device.\n"
+msgstr "Operasi ini tidak didukung untuk perangkat crypt %s.\n"
+
+#: lib/utils.c:416
+#, c-format
+msgid "Failed to open key file %s.\n"
+msgstr "Gagal membuka berkas kunci %s.\n"
+
+#: lib/utils.c:436
+msgid "Error reading passphrase from terminal.\n"
+msgstr "Kesalahan dalam pembacaan kata sandi dari terminal.\n"
+
+#: lib/utils.c:441
+msgid "Verify passphrase: "
+msgstr "Memverifikasi kata sandi: "
+
+#: lib/utils.c:443
+msgid "Passphrases do not match.\n"
+msgstr "Kata sandi tidak cocok.\n"
+
+#: lib/utils.c:458
+msgid "Can't do passphrase verification on non-tty inputs.\n"
+msgstr "Tidak dapat melakukan verifikasi kata sandi di masukan bukan tty.\n"
+
+#: lib/utils.c:471
+#, c-format
+msgid "Failed to stat key file %s.\n"
+msgstr "Gagal memperoleh data statistik berkas kunci %s.\n"
+
+#: lib/utils.c:475
+#, c-format
+msgid "Warning: exhausting read requested, but key file %s is not a regular file, function might never return.\n"
+msgstr "Peringatan: pembacaan yang melelahkan diminta, tetapi berkas kunci %s bukan sebuah berkas biasa, fungsi mungkin tidak pernah kembali.\n"
+
+#: lib/utils.c:487
+msgid "Out of memory while reading passphrase.\n"
+msgstr "Kehabisan memori ketika membaca kata sandi.\n"
+
+#: lib/utils.c:494
+msgid "Error reading passphrase.\n"
+msgstr "Kesalahan dalam pembacaan kata sandi.\n"
+
+#: lib/utils.c:531
+#, c-format
+msgid "Device %s doesn't exist or access denied.\n"
+msgstr "Perangkat %s tidak ada atau akses ditolak.\n"
+
+#: lib/utils.c:538
+#, c-format
+msgid "Cannot open device %s for %s%s access.\n"
+msgstr "Tidak dapat membuka perangkat %s untuk akses %s%s.\n"
+
+#: lib/utils.c:539
+msgid "exclusive "
+msgstr "ekslusif "
+
+#: lib/utils.c:540
+msgid "writable"
+msgstr "dapat-ditulis"
+
+#: lib/utils.c:540
+msgid "read-only"
+msgstr "baca-saja"
+
+#: lib/utils.c:547
+#, c-format
+msgid "Cannot read device %s.\n"
+msgstr "Tidak dapat membaca perangkat %s.\n"
+
+#: lib/utils.c:577
+#, c-format
+msgid "Cannot open device: %s\n"
+msgstr "Tidak dapat membuka perangkat: %s\n"
+
+#: lib/utils.c:587
+#, c-format
+msgid "BLKROGET failed on device %s.\n"
+msgstr "BLKROGET gagal di perangkat %s.\n"
+
+#: lib/utils.c:612
+#, c-format
+msgid "BLKGETSIZE failed on device %s.\n"
+msgstr "BLKGETSIZE gagal di perangkat %s.\n"
+
+#: lib/utils.c:660
+msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+msgstr "PERINGATAN!!! Kemungkinan menggunakan memori tidak aman. Apakah anda root?\n"
+
+#: lib/utils.c:666
+msgid "Cannot get process priority.\n"
+msgstr "Tidak dapat mendapatkan prioritas proses.\n"
+
+#: lib/utils.c:669 lib/utils.c:682
+#, c-format
+msgid "setpriority %u failed: %s"
+msgstr "setpriority %u gagal: %s"
+
+#: lib/utils.c:680
+msgid "Cannot unlock memory."
+msgstr "Tidak dapat membuka kunci memori."
+
+#: luks/keyencryption.c:68
+#, c-format
+msgid "Unable to obtain sector size for %s"
+msgstr "Tidak dapat mendapatkan ukuran sektor untuk %s"
+
+#: luks/keyencryption.c:137
+msgid "Failed to obtain device mapper directory."
+msgstr "Gagal untuk memperoleh direktori pemeta-perangkat."
+
+#: luks/keyencryption.c:153
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info).\n"
+"%s"
+msgstr ""
+"Gagal untuk mengkonfigurasi pemetaan kunci dm-crypt untuk perangkat %s.\n"
+"Periksa apakah kernel mendukung cipher %s (periksa syslog untuk informasi lebih lanjut).\n"
+"%s"
+
+#: luks/keyencryption.c:163
+msgid "Failed to open temporary keystore device.\n"
+msgstr "Gagal untuk membuka perangkat penyimpan kunci sementara.\n"
+
+#: luks/keyencryption.c:170
+msgid "Failed to access temporary keystore device.\n"
+msgstr "Gagal untuk mengakses perangkat penyimpan kunci sementara.\n"
+
+#: luks/keymanage.c:91
+#, c-format
+msgid "Requested file %s already exist.\n"
+msgstr "Berkas %s yang diminta telah ada.\n"
+
+#: luks/keymanage.c:111
+#, c-format
+msgid "Device %s is not LUKS device.\n"
+msgstr "Perangkat %s bukan perangkat LUKS.\n"
+
+#: luks/keymanage.c:131
+#, c-format
+msgid "Cannot write header backup file %s.\n"
+msgstr "Tidak dapat menulis berkas cadangan header %s.\n"
+
+#: luks/keymanage.c:158
+#, c-format
+msgid "Backup file %s doesn't exist.\n"
+msgstr "Berkas cadangan %s tidak ada.\n"
+
+#: luks/keymanage.c:166
+msgid "Backup file do not contain valid LUKS header.\n"
+msgstr "Berkas cadangan tidak berisi header LUKS yang valid.\n"
+
+#: luks/keymanage.c:179
+#, c-format
+msgid "Cannot open header backup file %s.\n"
+msgstr "Tidak dapat membuka berkas cadangan header %s.\n"
+
+#: luks/keymanage.c:185
+#, c-format
+msgid "Cannot read header backup file %s.\n"
+msgstr "Tidak dapat membaca berkas cadangan header %s.\n"
+
+#: luks/keymanage.c:196
+msgid "Data offset or key size differs on device and backup, restore failed.\n"
+msgstr "Data offset atau ukuran kunci berbeda di perangkat dan cadangan, pengembalian gagal.\n"
+
+#: luks/keymanage.c:204
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Perangkat %s %s%s"
+
+#: luks/keymanage.c:205
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "tidak berisi header LUKS. Mengganti header dapat menghancurkan data di perangkat itu."
+
+#: luks/keymanage.c:206
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "telah berisi header LUKS. Mengganti header dapat mengganti slot kunci yang telah ada."
+
+#: luks/keymanage.c:207
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"PERINGATAN: header perangkat ril memiliki UUID berbeda dengan cadangan!"
+
+#: luks/keymanage.c:222 luks/keymanage.c:319 luks/keymanage.c:354
+#, c-format
+msgid "Cannot open device %s.\n"
+msgstr "Tidak dapat membuka perangkat %s.\n"
+
+#: luks/keymanage.c:254
+#, c-format
+msgid "%s is not LUKS device.\n"
+msgstr "%s bukan perangkat LUKS.\n"
+
+#: luks/keymanage.c:256
+#, c-format
+msgid "%s is not LUKS device."
+msgstr "%s bukan perangkat LUKS."
+
+#: luks/keymanage.c:259
+#, c-format
+msgid "Unsupported LUKS version %d.\n"
+msgstr "versi LUKS %d tidak didukung.\n"
+
+#: luks/keymanage.c:262
+#, c-format
+msgid "Requested LUKS hash %s is not supported.\n"
+msgstr "Hash %s LUKS yang diminta tidak didukung.\n"
+
+#: luks/keymanage.c:293
+#, c-format
+msgid "Cannot open file %s.\n"
+msgstr "Tidak dapat membuka berkas %s.\n"
+
+#: luks/keymanage.c:331
+#, c-format
+msgid "LUKS header detected but device %s is too small.\n"
+msgstr "Header LUKS terdeteksi tetapi perangkat %s terlalu kecil.\n"
+
+#: luks/keymanage.c:375
+#, c-format
+msgid "Error during update of LUKS header on device %s.\n"
+msgstr "Error selama memperbarui header LUKS di perangkat %s.\n"
+
+#: luks/keymanage.c:382
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s.\n"
+msgstr "Error membaca-kembali header LUKS setelah memperbarui di perangkat %s.\n"
+
+#: luks/keymanage.c:394
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Pilihan PBKDF2 tidak kompatibel (menggunakan algoritma hash %s)."
+
+#: luks/keymanage.c:439
+msgid "Cannot create LUKS header: reading random salt failed.\n"
+msgstr "Tidak dapat membuat header LUKS: pembacaan garam acak gagal.\n"
+
+#: luks/keymanage.c:456
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s).\n"
+msgstr "Tidak dapat membuat header LUKS: digest header gagal (menggunakan hash %s).\n"
+
+#: luks/keymanage.c:473
+msgid "Wrong UUID format provided, generating new one.\n"
+msgstr "Format UUID yang disediakan berbeda, membuat yang baru.\n"
+
+#: luks/keymanage.c:500
+#, c-format
+msgid "Key slot %d active, purge first.\n"
+msgstr "Slot kunci %d aktif, hapus terlebih dahulu.\n"
+
+#: luks/keymanage.c:505
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?\n"
+msgstr "Slot kunci %d material terdapat terlalu sedikit stripes. Manipulasi header?\n"
+
+#: luks/keymanage.c:564
+msgid "Failed to write to key storage.\n"
+msgstr "Gagal untuk menulis di penyimpanan kunci.\n"
+
+#: luks/keymanage.c:641
+msgid "Failed to read from key storage.\n"
+msgstr "Gagal untuk membaca dari penyimpanan kunci.\n"
+
+#: luks/keymanage.c:650
+#, c-format
+msgid "Key slot %d unlocked.\n"
+msgstr "Slot kunci %d tidak terkunci.\n"
+
+#: luks/keymanage.c:683
+msgid "No key available with this passphrase.\n"
+msgstr "Tidak ada kunci tersedia dengan kata sandi ini.\n"
+
+#: luks/keymanage.c:760
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d.\n"
+msgstr "Slot kunci %d tidak valid, mohon pilih slot kunci diantara 0 dan %d.\n"
+
+#: luks/keymanage.c:772
+#, c-format
+msgid "Cannot wipe device %s.\n"
+msgstr "Tidak dapat menghapus perangkat %s.\n"
+
+#: src/cryptsetup.c:71 src/cryptsetup.c:89
+msgid "<name> <device>"
+msgstr "<nama> <perangkat>"
+
+#: src/cryptsetup.c:71
+msgid "create device"
+msgstr "buat perangkat"
+
+#: src/cryptsetup.c:72 src/cryptsetup.c:73 src/cryptsetup.c:74
+#: src/cryptsetup.c:82
+msgid "<name>"
+msgstr "<nama>"
+
+#: src/cryptsetup.c:72
+msgid "remove device"
+msgstr "hapus perangkat"
+
+#: src/cryptsetup.c:73
+msgid "resize active device"
+msgstr "ubah ukuran perangkat aktif"
+
+#: src/cryptsetup.c:74
+msgid "show device status"
+msgstr "tampilkan status perangkat"
+
+#: src/cryptsetup.c:75 src/cryptsetup.c:77
+msgid "<device> [<new key file>]"
+msgstr "<perangkat> [<berkas kunci baru>]"
+
+#: src/cryptsetup.c:75
+msgid "formats a LUKS device"
+msgstr "format sebuah perangkat LUKS"
+
+#: src/cryptsetup.c:76
+msgid "<device> <name> "
+msgstr "<perangkat> <nama>"
+
+#: src/cryptsetup.c:76
+msgid "open LUKS device as mapping <name>"
+msgstr "buka perangkat LUKS sebagai pemetaan <nama>"
+
+#: src/cryptsetup.c:77
+msgid "add key to LUKS device"
+msgstr "tambahkan kunci ke perangkat LUKS"
+
+#: src/cryptsetup.c:78
+msgid "<device> [<key file>]"
+msgstr "<perangkat> [<berkas kunci>]"
+
+#: src/cryptsetup.c:78
+msgid "removes supplied key or key file from LUKS device"
+msgstr "hapus kunci yang diberikan atau berkas kunci dari perangkat LUKS"
+
+#: src/cryptsetup.c:79 src/cryptsetup.c:88
+msgid "<device> <key slot>"
+msgstr "<perangkat> <slot kunci>"
+
+#: src/cryptsetup.c:79
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "hapus kunci dengan nomor <slot kunci> dari perangkat LUKS"
+
+#: src/cryptsetup.c:80 src/cryptsetup.c:81 src/cryptsetup.c:83
+#: src/cryptsetup.c:84 src/cryptsetup.c:85 src/cryptsetup.c:86
+#: src/cryptsetup.c:87
+msgid "<device>"
+msgstr "<perangkat>"
+
+#: src/cryptsetup.c:80
+msgid "print UUID of LUKS device"
+msgstr "tampilkan UUID dari perangkat LUKS"
+
+#: src/cryptsetup.c:81
+msgid "tests <device> for LUKS partition header"
+msgstr "periksa <perangkat> untuk header partisi LUKS"
+
+#: src/cryptsetup.c:82
+msgid "remove LUKS mapping"
+msgstr "hapus pemetaan LUKS"
+
+#: src/cryptsetup.c:83
+msgid "dump LUKS partition information"
+msgstr "dump informasi partisi LUKS"
+
+#: src/cryptsetup.c:84
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)."
+msgstr "Hentikan perangkat LUKS dan hapus kunci (semua IO dihentikan)."
+
+#: src/cryptsetup.c:85
+msgid "Resume suspended LUKS device."
+msgstr "Lanjutkan perangkat LUKS yang dihentikan."
+
+#: src/cryptsetup.c:86
+msgid "Backup LUKS device header and keyslots"
+msgstr "Buat cadangan header perangkat LUKS dan slot kunci"
+
+#: src/cryptsetup.c:87
+msgid "Restore LUKS device header and keyslots"
+msgstr "Kembalikan header perangkat LUKS dan slot kunci"
+
+#: src/cryptsetup.c:88
+msgid "identical to luksKillSlot - DEPRECATED - see man page"
+msgstr "identik ke luksKillSlot - DITINGGALKAN - lihat halaman petunjuk penggunaan"
+
+#: src/cryptsetup.c:89
+msgid "modify active device - DEPRECATED - see man page"
+msgstr "modifikasi perangkat aktif - DITINGGALKAN - lihat halaman petunjuk penggunaan"
+
+#: src/cryptsetup.c:180
+msgid "Command successful.\n"
+msgstr "Perintah berhasil.\n"
+
+#: src/cryptsetup.c:194
+#, c-format
+msgid "Command failed with code %i"
+msgstr "Perintah gagal dengan kode %i"
+
+#: src/cryptsetup.c:222
+msgid ""
+"The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\n"
+"WARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"
+msgstr ""
+"Aksi muat kembali telah ditinggalkan. Mohon gunakan \"dmsetup reload\" dalam kasus anda benar benar membutuhkan fungsi ini.\n"
+"PERINGATAN: jangan gunakan muat-kembali untuk menyentuk perangkat LUKS. Jika itu masalahnya, tekan Ctrl-C sekarang.\n"
+
+#: src/cryptsetup.c:390
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Ini akan memaksa menulis data di %s secara permanen."
+
+#: src/cryptsetup.c:391
+msgid "memory allocation error in action_luksFormat"
+msgstr "alokasi memori error dalam action_luksFormat"
+
+#: src/cryptsetup.c:421
+msgid "Obsolete option --non-exclusive is ignored.\n"
+msgstr "Pilihan sudah ditinggalkan --no-exclusive diabaikan.\n"
+
+#: src/cryptsetup.c:581 src/cryptsetup.c:603
+msgid "Option --header-backup-file is required.\n"
+msgstr "Pilihan --header-backup-file dibutuhkan.\n"
+
+#: src/cryptsetup.c:637
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<aksi> adalah salah satu dari:\n"
+
+#: src/cryptsetup.c:643
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nama> adalah perangkat untuk dibuat dibawah %s\n"
+"<perangkat> adalah perangkat terenkripsi\n"
+"<slot kunci> adalah nomor slot kunci LUKS untuk dimodifikasi\n"
+"<berkas kunci> adalah berkas kunci opsional untuk kunci baru untuk aksi luksAddKey\n"
+
+#: src/cryptsetup.c:650
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS1: %s, Key: %d bits, LUKS header hashing: %s\n"
+msgstr ""
+"\n"
+"Parameter baku yang terkompilasi dalam perangkat penyandi:\n"
+"\tterbuka: %s, Kunci: %d bits, Hash kata sandi : %s\n"
+"\tLUKS1 : %s, Kunci: %d bits, Hash kepala LUKS: %s\n"
+
+#: src/cryptsetup.c:697
+msgid "Show this help message"
+msgstr "Tampilkan pesan bantuan ini"
+
+#: src/cryptsetup.c:698
+msgid "Display brief usage"
+msgstr "Tampilkan penggunaan singkat"
+
+#: src/cryptsetup.c:702
+msgid "Help options:"
+msgstr "Pilihan bantuan:"
+
+#: src/cryptsetup.c:703
+msgid "Shows more detailed error messages"
+msgstr "Tampilkan pesan kesalahan secara lebih detail"
+
+#: src/cryptsetup.c:704
+msgid "Show debug messages"
+msgstr "Tampilkan pesan penelusuran"
+
+#: src/cryptsetup.c:705
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "Cipher yang digunakan untuk mengenkripsi ke disk (lihat /proc/crypto)"
+
+#: src/cryptsetup.c:706
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "Hash yang digunakan untuk membuat kunci enkripsi dari kata sandi"
+
+#: src/cryptsetup.c:707
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Verifikasi kata sandi dengan menanyakan itu dua kali"
+
+#: src/cryptsetup.c:708
+msgid "Read the key from a file (can be /dev/random)"
+msgstr "Baca kunci dari sebuah berkas (dapat berupa /dev/random)"
+
+#: src/cryptsetup.c:709
+msgid "Read the volume (master) key from file."
+msgstr "Baca volume (master) kunci dari berkas."
+
+#: src/cryptsetup.c:710
+msgid "The size of the encryption key"
+msgstr "Besar dari kunci enkripsi"
+
+#: src/cryptsetup.c:710
+msgid "BITS"
+msgstr "BITS"
+
+#: src/cryptsetup.c:711
+msgid "Slot number for new key (default is first free)"
+msgstr "Nomor slot untuk kunci baru (baku adalah yang kosong pertama)"
+
+#: src/cryptsetup.c:712
+msgid "The size of the device"
+msgstr "Besar dari perangkat"
+
+#: src/cryptsetup.c:712 src/cryptsetup.c:713 src/cryptsetup.c:714
+#: src/cryptsetup.c:722
+msgid "SECTORS"
+msgstr "SEKTOR"
+
+#: src/cryptsetup.c:713
+msgid "The start offset in the backend device"
+msgstr "Awal ofset dalam perangkat backend"
+
+#: src/cryptsetup.c:714
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Berapa banyak sektor dari data terenkripsi yang dilewatkan di awal"
+
+#: src/cryptsetup.c:715
+msgid "Create a readonly mapping"
+msgstr "Buat pemetaan baca-saja"
+
+#: src/cryptsetup.c:716
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "waktu iterasi PBKDF2 untuk LUKS (dalam mdet)"
+
+#: src/cryptsetup.c:717
+msgid "msecs"
+msgstr "mdetik"
+
+#: src/cryptsetup.c:718
+msgid "Do not ask for confirmation"
+msgstr "Jangan tanya untuk konfirmasi"
+
+#: src/cryptsetup.c:719
+msgid "Print package version"
+msgstr "Tampilkan versi paket"
+
+#: src/cryptsetup.c:720
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Waktu habis untuk pertanyaan interaktif kata sandi (dalam detik)"
+
+#: src/cryptsetup.c:720
+msgid "secs"
+msgstr "detik"
+
+#: src/cryptsetup.c:721
+msgid "How often the input of the passphrase can be retried"
+msgstr "Seberapa sering masukan dari kata sandi dapat dicoba"
+
+#: src/cryptsetup.c:722
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Sesuaikan muatan di batas sektor <n> - untuk luksFormat"
+
+#: src/cryptsetup.c:723
+msgid "(Obsoleted, see man page.)"
+msgstr "(Ditinggalkan, lihat halaman petunjuk penggunaan.)"
+
+#: src/cryptsetup.c:724
+msgid "File with LUKS header and keyslots backup."
+msgstr "Berkas dengan header LUKS dan cadangan slot kunci."
+
+#: src/cryptsetup.c:742
+msgid "[OPTION...] <action> <action-specific>]"
+msgstr "[PILIHAN...] <aksi> <aksi-spesifik>]"
+
+#: src/cryptsetup.c:778
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Kunci harus kelipatan dari 8 bit"
+
+#: src/cryptsetup.c:782
+msgid "Argument <action> missing."
+msgstr "Argumen <aksi> hilang."
+
+#: src/cryptsetup.c:788
+msgid "Unknown action."
+msgstr "Aksi tidak diketahui."
+
+#: src/cryptsetup.c:803
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: membutuhkan %s sebagai argumen"
diff --git a/po/it.po b/po/it.po
new file mode 100644
index 0000000..7274009
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,3193 @@
+# Italian translation for cryptsetup.
+# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Sergio Zanchetta <primes2h@ubuntu.com>, 2010, 2011, 2012.
+# Milo Casagrande <milo@milo.name>, 2013, 2014, 2015, 2016, 2018, 2019.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup-2.1.0\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2019-01-26 19:02+0100\n"
+"PO-Revision-Date: 2019-01-28 09:18+0100\n"
+"Last-Translator: Milo Casagrande <milo@milo.name>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=(n!=1);\n"
+"X-Generator: Poedit 2.2.1\n"
+
+#: lib/libdevmapper.c:336
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Impossibile inizializzare device-mapper: in esecuzione come utente non-root."
+
+#: lib/libdevmapper.c:339
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Impossibile inizializzare device-mapper. Forse il modulo kernel dm_mod non è caricato."
+
+#: lib/libdevmapper.c:1010
+msgid "Requested deferred flag is not supported."
+msgstr "Il flag posticipato richiesto non è supportato."
+
+#: lib/libdevmapper.c:1077
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "Il DM-UUID per il dispositivo %s è stato troncato."
+
+#: lib/libdevmapper.c:1486
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Le opzioni di prestazioni richieste per dm-crypt non sono supportate."
+
+#: lib/libdevmapper.c:1493
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Le opzioni di gestione dei dati rovinati richieste per dm-verity non sono supportate."
+
+#: lib/libdevmapper.c:1497
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Le opzioni FEC dm-verity richieste non sono supportate."
+
+#: lib/libdevmapper.c:1501
+msgid "Requested data integrity options are not supported."
+msgstr "Le opzioni di integrità dei dati richieste non sono supportate."
+
+#: lib/libdevmapper.c:1503
+msgid "Requested sector_size option is not supported."
+msgstr "L'opzione sector_size richiesta non è supportata."
+
+#: lib/libdevmapper.c:1508
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Il ricalcolo automatico dei tag d'integrità non è supportato."
+
+#: lib/libdevmapper.c:1534
+msgid "Requested dmcrypt performance options are not supported."
+msgstr "Le opzioni di prestazioni richieste per dmcrypt non sono supportate."
+
+#: lib/libdevmapper.c:1537
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM non è supportato."
+
+#: lib/libdevmapper.c:2413
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Interrogazione del segmento dm-%s non riuscita."
+
+#: lib/random.c:80
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Il sistema non ha un'entropia sufficiente mentre viene generata la chiave di volume.\n"
+"Muovere il mouse o digitare del testo in un'altra finestra per accumulare più eventi casuali.\n"
+
+#: lib/random.c:84
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Generazione chiave (%d%% completato).\n"
+
+#: lib/random.c:170
+msgid "Running in FIPS mode."
+msgstr "Esecuzione in modalità FIPS."
+
+#: lib/random.c:176
+msgid "Fatal error during RNG initialisation."
+msgstr "Errore fatale durante l'inizializzazione dell'RNG."
+
+#: lib/random.c:213
+msgid "Unknown RNG quality requested."
+msgstr "Qualità richiesta per l'RNG sconosciuta."
+
+#: lib/random.c:218
+msgid "Error reading from RNG."
+msgstr "Errore nel leggere dall'RNG."
+
+#: lib/setup.c:214
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Impossibile inizializzare il backend crypto RNG."
+
+#: lib/setup.c:220
+msgid "Cannot initialize crypto backend."
+msgstr "Impossibile inizializzare il backend crypto."
+
+#: lib/setup.c:251 lib/setup.c:1899 lib/verity/verity.c:123
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Algoritmo di hash %s non supportato."
+
+#: lib/setup.c:254 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Errore nell'elaborazione della chiave (usando l'hash %s)."
+
+#: lib/setup.c:315 lib/setup.c:342
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Impossibile determinare il tipo di dispositivo. Attivazione incompatibile del dispositivo?"
+
+#: lib/setup.c:321 lib/setup.c:2892
+msgid "This operation is supported only for LUKS device."
+msgstr "Questa operazione è supportata solo per il dispositivo LUKS."
+
+#: lib/setup.c:348
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Questa operazione è supportata solo per il dispositivo LUKS2."
+
+#: lib/setup.c:396
+msgid "All key slots full."
+msgstr "Tutti gli slot di chiave sono pieni."
+
+#: lib/setup.c:407
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Lo slot di chiave %d non è valido, selezionarne uno tra 0 e %d."
+
+#: lib/setup.c:413
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Lo slot di chiave %d è pieno, selezionarne un altro."
+
+#: lib/setup.c:589
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Rilevato un header, ma il dispositivo %s è troppo piccolo."
+
+#: lib/setup.c:626
+msgid "This operation is not supported for this device type."
+msgstr "Questa operazione non è supportata per questo tipo di dispositivo."
+
+#: lib/setup.c:791 lib/luks1/keymanage.c:481
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Versione %d di LUKS non supportata."
+
+#: lib/setup.c:808 lib/setup.c:1403 lib/setup.c:1812
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Il dispositivo di metadati scollegato non è supportato per questo tipo di cifratura."
+
+#: lib/setup.c:1288 lib/setup.c:2392 lib/setup.c:2464 lib/setup.c:2476
+#: lib/setup.c:2625 lib/setup.c:4021
+#, c-format
+msgid "Device %s is not active."
+msgstr "Il dispositivo %s non è attivo."
+
+#: lib/setup.c:1310
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Device sottostante a quello cifrato %s scomparso."
+
+#: lib/setup.c:1388
+msgid "Invalid plain crypt parameters."
+msgstr "Parametri di cifratura in chiaro non validi."
+
+#: lib/setup.c:1393 lib/setup.c:1802 src/integritysetup.c:72
+msgid "Invalid key size."
+msgstr "Dimensione della chiave non valida."
+
+#: lib/setup.c:1398 lib/setup.c:1807 lib/setup.c:2009
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID non è supportato per questo tipo di cifratura."
+
+#: lib/setup.c:1413 lib/setup.c:1603 src/cryptsetup.c:1045
+msgid "Unsupported encryption sector size."
+msgstr "Dimensione settore di cifratura non supportato."
+
+#: lib/setup.c:1421 lib/setup.c:1720
+msgid "Device size is not aligned to requested sector size."
+msgstr "La dimensione del dispositivo non è allineata con la dimensione del settore richiesta."
+
+#: lib/setup.c:1472 lib/setup.c:1591
+msgid "Can't format LUKS without device."
+msgstr "Impossibile formattare LUKS senza dispositivo."
+
+#: lib/setup.c:1478 lib/setup.c:1597
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "L'allineamento dei dati richiesti non è compatibile con l'offset dei dati."
+
+#: lib/setup.c:1546 lib/setup.c:1715
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr "Attenzione: l'offset dei dati è al di fuori del dispositivo dati attualmente disponibile.\n"
+
+#: lib/setup.c:1556 lib/setup.c:1735 lib/setup.c:1754 lib/setup.c:2021
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Impossibile ripulire l'header sul dispositivo %s."
+
+#: lib/setup.c:1608
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "Attenzione: l'attivazione del dispositivo non riuscirà, dm-crypt manca il supporto per la dimensione del settore di crittografia richiesta.\n"
+
+#: lib/setup.c:1630
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "La chiave di volume è troppo piccola per la cifratura con estensioni di integrità."
+
+#: lib/setup.c:1685
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Il cifrario %s-%s (dimensione chiave di %zd byte) non è disponibile."
+
+#: lib/setup.c:1747
+#, c-format
+msgid "Cannot format device %s which is still in use."
+msgstr "Impossibile formattare il dispositivo %s che risulta ancora in uso."
+
+#: lib/setup.c:1750 lib/setup.c:1775
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Impossibile formattare il dispositivo %s, permessi non concessi."
+
+#: lib/setup.c:1762 lib/setup.c:2073
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Impossibile formattare l'integrità per il dispositivo %s."
+
+#: lib/setup.c:1772
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Impossibile formattare il dispositivo %s che risulta ancora in uso."
+
+#: lib/setup.c:1779
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Impossibile formattare il dispositivo %s."
+
+#: lib/setup.c:1797
+msgid "Can't format LOOPAES without device."
+msgstr "Impossibile formattare LOOPAES senza dispositivo."
+
+#: lib/setup.c:1842
+msgid "Can't format VERITY without device."
+msgstr "Impossibile formattare VERITY senza dispositivo."
+
+#: lib/setup.c:1853 lib/verity/verity.c:106
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Tipo di hash %d VERITY non supportato."
+
+#: lib/setup.c:1859 lib/verity/verity.c:114
+msgid "Unsupported VERITY block size."
+msgstr "Dimensione blocco VERITY non supportata."
+
+#: lib/setup.c:1864 lib/verity/verity.c:75
+msgid "Unsupported VERITY hash offset."
+msgstr "Offset hash VERITY non supportato."
+
+#: lib/setup.c:1869
+msgid "Unsupported VERITY FEC offset."
+msgstr "Offset FEC VERITY non supportato."
+
+#: lib/setup.c:1893
+msgid "Data area overlaps with hash area."
+msgstr "L'area dati si sovrappone a quella di hash."
+
+#: lib/setup.c:1918
+msgid "Hash area overlaps with FEC area."
+msgstr "L'area di hash si sovrappone a quella FEC."
+
+#: lib/setup.c:1925
+msgid "Data area overlaps with FEC area."
+msgstr "L'area dati si sovrappone a quella FEC."
+
+#: lib/setup.c:2130
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Richiesto dispositivo cifrato di tipo %s sconosciuto."
+
+#: lib/setup.c:2398 lib/setup.c:2470 lib/setup.c:2483
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Parametri non supportati sul dispositivo %s."
+
+#: lib/setup.c:2404 lib/setup.c:2489
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Parametri non corrispondenti sul dispositivo %s."
+
+#: lib/setup.c:2657
+msgid "Cannot resize loop device."
+msgstr "Impossibile ridimensionare un dispositivo di loopback."
+
+#: lib/setup.c:2666
+#, c-format
+msgid "Device %s size is not aligned to requested sector size (%u bytes)."
+msgstr "La dimensione del dispositivo %s non è allineata con la dimensione del settore richiesta (%u byte)."
+
+#: lib/setup.c:2725
+msgid "Do you really want to change UUID of device?"
+msgstr "Cambiare veramente l'UUID del dispositivo?"
+
+#: lib/setup.c:2801
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Il file di backup dell'header non contiene un header LUKS compatibile."
+
+#: lib/setup.c:2900
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Il volume %s non è attivo."
+
+#: lib/setup.c:2911
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Il volume %s è già sospeso."
+
+#: lib/setup.c:2925
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "La sospensione non è supportata per il dispositivo %s."
+
+#: lib/setup.c:2927
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Errore durante la sospensione del dispositivo %s."
+
+#: lib/setup.c:2960 lib/setup.c:3027
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Il volume %s non è sospeso."
+
+#: lib/setup.c:2989
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Il ripristino non è supportato per il dispositivo %s."
+
+#: lib/setup.c:2991 lib/setup.c:3059
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Errore durante il ripristino del dispositivo %s."
+
+#: lib/setup.c:3127 lib/setup.c:3315
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Impossibile aggiungere uno slot di chiave, tutti gli slot sono disabilitati e nessuna chiave di volume è stata fornita."
+
+#: lib/setup.c:3267
+msgid "Failed to swap new key slot."
+msgstr "Sostituzione del nuovo slot di chiave non riuscita."
+
+#: lib/setup.c:3432 lib/setup.c:3865 lib/setup.c:3878 lib/setup.c:3886
+#: lib/setup.c:3899 lib/setup.c:4198 lib/setup.c:5274
+msgid "Volume key does not match the volume."
+msgstr "La chiave di volume non corrisponde al volume."
+
+#: lib/setup.c:3453
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Lo slot di chiave %d non è valido."
+
+#: lib/setup.c:3459
+#, c-format
+msgid "Key slot %d is not used."
+msgstr "Lo slot di chiave %d non è utilizzato."
+
+#: lib/setup.c:3478
+msgid "Device header overlaps with data area."
+msgstr "L'header del dispositivo si sovrappone all'area dati."
+
+#: lib/setup.c:3684 lib/setup.c:3952
+msgid "Device type is not properly initialised."
+msgstr "Il tipo di dispositivo non è inizializzato correttamente."
+
+#: lib/setup.c:3726
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Impossibile formattare il dispositivo %s che risulta ancora in uso."
+
+#: lib/setup.c:3729
+#, c-format
+msgid "Device %s already exists."
+msgstr "Esiste già un dispositivo %s."
+
+#: lib/setup.c:3852
+msgid "Incorrect volume key specified for plain device."
+msgstr "Specificata una chiave di volume non corretta per il dispositivo in chiaro."
+
+#: lib/setup.c:3918
+msgid "Incorrect root hash specified for verity device."
+msgstr "Specificato un hash root non corretto per il dispositivo verity."
+
+#: lib/setup.c:3995 lib/setup.c:4010
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Il dispositivo %s è ancora in uso."
+
+#: lib/setup.c:4025
+#, c-format
+msgid "Invalid device %s."
+msgstr "Device %s non valido."
+
+#: lib/setup.c:4134
+msgid "Function not available in FIPS mode."
+msgstr "Funzione non disponibile in modalità FIPS."
+
+#: lib/setup.c:4148
+msgid "Volume key buffer too small."
+msgstr "Buffer di chiave del volume troppo piccolo."
+
+#: lib/setup.c:4156
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Impossibile recuperare la chiave di volume per il dispositivo in chiaro."
+
+#: lib/setup.c:4167
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Questa operazione non è supportata per il dispositivo cifrato %s."
+
+#: lib/setup.c:4354
+msgid "Dump operation is not supported for this device type."
+msgstr "L'operazione di dump non è supportata per questo tipo di dispositivo."
+
+#: lib/setup.c:4930
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Impossibile convertire il dispositivo %s che risulta ancora in uso."
+
+#: lib/setup.c:5213
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Assegnamento slot di chiave %u come nuova chiave del volume non riuscito."
+
+#: lib/setup.c:5280
+msgid "Failed to initialise default LUKS2 keyslot parameters."
+msgstr "Inizializzazione parametri predefiniti per lo slot di chiave LUKS2 non riuscita."
+
+#: lib/setup.c:5286
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Assegnazione slot di chiave %d al digest non riuscita."
+
+#: lib/setup.c:5370
+msgid "Failed to load key in kernel keyring."
+msgstr "Caricamento chiave nel portachiavi del kernel non riuscito."
+
+#: lib/setup.c:5425
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Il portachiavi del kernel non è supportato dal kernel."
+
+#: lib/setup.c:5435
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Lettura della passphrase dal portachiavi non riuscita (errore %d)."
+
+#: lib/utils.c:81
+msgid "Cannot get process priority."
+msgstr "Impossibile ottenere la priorità del processo."
+
+#: lib/utils.c:95
+msgid "Cannot unlock memory."
+msgstr "Impossibile sbloccare la memoria."
+
+#: lib/utils.c:169 lib/tcrypt/tcrypt.c:498
+msgid "Failed to open key file."
+msgstr "Apertura del file chiave non riuscita."
+
+#: lib/utils.c:174
+msgid "Cannot read keyfile from a terminal."
+msgstr "Impossibile leggere il file chiave dal terminale."
+
+#: lib/utils.c:191
+msgid "Failed to stat key file."
+msgstr "Stat del file chiave non riuscito."
+
+#: lib/utils.c:199 lib/utils.c:220
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Impossibile posizionarsi all'offset del file di chiave richiesto."
+
+#: lib/utils.c:214 lib/utils.c:229 src/utils_password.c:188
+#: src/utils_password.c:201
+msgid "Out of memory while reading passphrase."
+msgstr "Memoria esaurita durante la lettura della passphrase."
+
+#: lib/utils.c:249
+msgid "Error reading passphrase."
+msgstr "Errore nel leggere la passphrase."
+
+#: lib/utils.c:266
+msgid "Nothing to read on input."
+msgstr "Nessun dato da leggere sull'input."
+
+#: lib/utils.c:273
+msgid "Maximum keyfile size exceeded."
+msgstr "Dimensione massima del file chiave superata."
+
+#: lib/utils.c:278
+msgid "Cannot read requested amount of data."
+msgstr "Impossibile leggere la quantità richiesta di dati."
+
+#: lib/utils_device.c:184 lib/luks1/keyencryption.c:92
+#, c-format
+msgid "Device %s doesn't exist or access denied."
+msgstr "Il dispositivo %s non esiste oppure è negato l'accesso."
+
+#: lib/utils_device.c:194
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Il dispositivo %s non è compatibile."
+
+#: lib/utils_device.c:560
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Il dispositivo %s è troppo piccolo, sono necessari almeno %<PRIu64> byte."
+
+#: lib/utils_device.c:641
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Impossibile utilizzare il dispositivo %s il quale è in uso (già mappato o montato)."
+
+#: lib/utils_device.c:645
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Impossibile usare il dispositivo %s, permessi negati."
+
+#: lib/utils_device.c:648
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Impossibile ottenere informazioni sul dispositivo %s."
+
+#: lib/utils_device.c:671
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Impossibile usare un dispositivo di loopback, in esecuzione come utente non root."
+
+#: lib/utils_device.c:681
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Collegamento del dispositivo di loopback non riuscito (è richiesto un dispositivo di loop con flag autoclear)."
+
+#: lib/utils_device.c:727
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "L'offset richiesto è oltre la dimensione reale del dispositivo %s."
+
+#: lib/utils_device.c:735
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Il dispositivo %s ha dimensione zero."
+
+#: lib/utils_device.c:746 lib/luks1/keyencryption.c:252
+#, c-format
+msgid "Device %s is too small."
+msgstr "Il dispositivo %s è troppo piccolo."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Il tempo PBKDF richiesto non può essere zero."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Tipo PBKDF %s non riconosciuto."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "L'hash %s richiesto non è supportato."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Il tipo PBKDF richiesto non è supportato per LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Memoria massima o thread paralleli PBKDF non devono essere impostati con pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Il conteggio delle iterazioni forzate è troppo basso per %s (minimo è %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Il costo della memoria forzata è troppo basso per %s (minimo è %u kilobyte)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Il costo massimo richiesto per la memoria PBKDF è troppo elevato (massimo è %d kilobyte)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "La memoria PBKDF massima richiesta non può essere zero."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "I thread paralleli PBKDF richiesti non possono essere zero."
+
+#: lib/utils_benchmark.c:317
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Benchmark PBKDF disabilitato, ma iterazioni non impostate."
+
+#: lib/utils_benchmark.c:336
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Opzioni PBKDF2 non compatibili (usando l'algoritmo di hash %s)."
+
+#: lib/utils_benchmark.c:356
+msgid "Not compatible PBKDF options."
+msgstr "Opzioni PBKDF non compatibili."
+
+#: lib/utils_device_locking.c:80
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Blocco interrotto. Il percorso di blocco %s/%s è inutilizzabile (non una directory o mancante)."
+
+#: lib/utils_device_locking.c:87
+#, c-format
+msgid "WARNING: Locking directory %s/%s is missing!\n"
+msgstr "Attenzione: la directory di blocco %s/%s non esiste.\n"
+
+#: lib/utils_device_locking.c:97
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Blocco interrotto. Il percorso di blocco %s/%s è inutilizzabile (%s non è una directory)."
+
+#: lib/luks1/keyencryption.c:40
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Impostazione mappatura di chiave dm-crypt non riuscita per il dispositivo %s.\n"
+"Controllare che il kernel supporti il cifrario %s (controllare syslog per maggiori informazioni)."
+
+#: lib/luks1/keyencryption.c:45
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "La dimensione della chiave in modalità XTS deve essere 256 o 512 bit."
+
+#: lib/luks1/keyencryption.c:47
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "La specifica del cifrario dovrebbe essere nel formato [cifrario]-[modalità]-[iv]."
+
+#: lib/luks1/keyencryption.c:98 lib/luks1/keymanage.c:345
+#: lib/luks1/keymanage.c:642 lib/luks1/keymanage.c:1079
+#: lib/luks2/luks2_json_metadata.c:1157 lib/luks2/luks2_keyslot.c:448
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Impossibile scrivere sul dispositivo %s, permessi negati."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Apertura del dispositivo temporaneo di deposito chiavi non riuscita."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Accesso al dispositivo temporaneo di deposito chiavi non riuscito."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:91
+msgid "IO error while encrypting keyslot."
+msgstr "Errore di IO durante la cifratura dello slot di chiave."
+
+#: lib/luks1/keyencryption.c:243 lib/luks1/keymanage.c:348
+#: lib/luks1/keymanage.c:594 lib/luks1/keymanage.c:645 lib/tcrypt/tcrypt.c:663
+#: lib/verity/verity.c:81 lib/verity/verity.c:182 lib/verity/verity_hash.c:308
+#: lib/verity/verity_hash.c:319 lib/verity/verity_hash.c:339
+#: lib/verity/verity_fec.c:242 lib/verity/verity_fec.c:254
+#: lib/verity/verity_fec.c:259 lib/luks2/luks2_json_metadata.c:1160
+#: src/cryptsetup_reencrypt.c:208
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Impossibile aprire il dispositivo %s."
+
+#: lib/luks1/keyencryption.c:254 lib/luks2/luks2_keyslot_luks2.c:152
+msgid "IO error while decrypting keyslot."
+msgstr "Errore di IO durante la decifratura dello slot di chiave."
+
+#: lib/luks1/keymanage.c:111
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Il dispositivo %s è troppo piccolo (LUKS1 richiede almeno %<PRIu64> byte)."
+
+#: lib/luks1/keymanage.c:132 lib/luks1/keymanage.c:140
+#: lib/luks1/keymanage.c:152 lib/luks1/keymanage.c:163
+#: lib/luks1/keymanage.c:175
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "Lo slot di chiave LUKS %u non è valido."
+
+#: lib/luks1/keymanage.c:228 lib/luks1/keymanage.c:478
+#: lib/luks2/luks2_json_metadata.c:991 src/cryptsetup.c:1236
+#: src/cryptsetup.c:1355 src/cryptsetup.c:1412 src/cryptsetup.c:1468
+#: src/cryptsetup.c:1535 src/cryptsetup.c:1631 src/cryptsetup.c:1695
+#: src/cryptsetup.c:1855 src/cryptsetup.c:2044 src/cryptsetup.c:2104
+#: src/cryptsetup.c:2170 src/cryptsetup.c:2334 src/cryptsetup_reencrypt.c:1397
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Il dispositivo %s non è un dispositivo LUKS valido."
+
+#: lib/luks1/keymanage.c:247 lib/luks2/luks2_json_metadata.c:1010
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Il file di backup dell'header %s richiesto esiste già."
+
+#: lib/luks1/keymanage.c:249 lib/luks2/luks2_json_metadata.c:1012
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Impossibile creare il file di backup dell'header %s."
+
+#: lib/luks1/keymanage.c:254 lib/luks2/luks2_json_metadata.c:1017
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Impossibile scrivere il file di backup dell'header %s."
+
+#: lib/luks1/keymanage.c:287 lib/luks2/luks2_json_metadata.c:1066
+msgid "Backup file doesn't contain valid LUKS header."
+msgstr "Il file di backup non contiene un header LUKS valido."
+
+#: lib/luks1/keymanage.c:300 lib/luks1/keymanage.c:555
+#: lib/luks2/luks2_json_metadata.c:1087
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Impossibile aprire il file di backup dell'header %s."
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1093
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Impossibile leggere il file di backup dell'header %s."
+
+#: lib/luks1/keymanage.c:318
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "L'offset di dati oppure la dimensione della chiave sono diversi tra il dispositivo e il backup, ripristino non riuscito."
+
+#: lib/luks1/keymanage.c:326
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Il dispositivo %s %s%s"
+
+#: lib/luks1/keymanage.c:327
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "non contiene un header LUKS. La sostituzione dell'header può distruggere i dati in quel dispositivo."
+
+#: lib/luks1/keymanage.c:328
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "contiene già un header LUKS. La sostituzione dell'header distruggerà gli slot di chiave esistenti."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1129
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"Attenzione: l'header reale del dispositivo ha un UUID diverso da quello di backup."
+
+#: lib/luks1/keymanage.c:381
+msgid "Non standard key size, manual repair required."
+msgstr "Dimensione non standard della chiave, è richiesta una riparazione manuale."
+
+#: lib/luks1/keymanage.c:386
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Allineamento slot di chiave non standard, richiesta riparazione manuale."
+
+#: lib/luks1/keymanage.c:396
+msgid "Repairing keyslots."
+msgstr "Riparazione degli slot di chiave."
+
+#: lib/luks1/keymanage.c:415
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Slot di chiave %i: offset riparato (%u -> %u)."
+
+#: lib/luks1/keymanage.c:423
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Slot di chiave %i: strisce riparate (%u -> %u)."
+
+#: lib/luks1/keymanage.c:432
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Slot di chiave %i: firma della partizione non corretta."
+
+#: lib/luks1/keymanage.c:437
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Slot di chiave %i: salt ripulito."
+
+#: lib/luks1/keymanage.c:454
+msgid "Writing LUKS header to disk."
+msgstr "Scrittura dell'header LUKS sul disco."
+
+#: lib/luks1/keymanage.c:459
+msgid "Repair failed."
+msgstr "Riparazione non riuscita."
+
+#: lib/luks1/keymanage.c:487 lib/luks1/keymanage.c:758
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "L'hash %s di LUKS richiesto non è supportato."
+
+#: lib/luks1/keymanage.c:515 src/cryptsetup.c:960
+msgid "No known problems detected for LUKS header."
+msgstr "Nessun problema conosciuto rilevato per l'header LUKS."
+
+#: lib/luks1/keymanage.c:667
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Errore durante l'aggiornamento dell'header LUKS sul dispositivo %s."
+
+#: lib/luks1/keymanage.c:676
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Errore nel rileggere l'header LUKS dopo l'aggiornamento sul dispositivo %s."
+
+#: lib/luks1/keymanage.c:752
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "L'offset dei dati per l'header LUKS deve essere 0 o maggiore della dimensione dell'header."
+
+#: lib/luks1/keymanage.c:763 lib/luks1/keymanage.c:828
+#: lib/luks2/luks2_json_format.c:207 lib/luks2/luks2_json_metadata.c:909
+msgid "Wrong LUKS UUID format provided."
+msgstr "Fornito un formato UUID per LUKS errato."
+
+#: lib/luks1/keymanage.c:786
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Impossibile creare l'header LUKS: lettura salt casuale non riuscita."
+
+#: lib/luks1/keymanage.c:807
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Impossibile creare l'header LUKS: digest dell'header non riuscito (usando l'hash %s)."
+
+#: lib/luks1/keymanage.c:851
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Slot di chiave %d attivo, eliminarlo prima."
+
+#: lib/luks1/keymanage.c:857
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Il materiale dello slot di chiave %d contiene troppe poche strisce. Manipolazione dell'header?"
+
+#: lib/luks1/keymanage.c:1065
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Lo slot di chiave %d non è valido, selezionarne uno tra 0 e %d."
+
+#: lib/luks1/keymanage.c:1083 lib/luks2/luks2_keyslot.c:452
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Impossibile ripulire il dispositivo %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Rilevato un file chiave cifrato con GPG non ancora supportato."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Usare gpg --decrypt <FILECHIAVE> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Rilevato file chiave loop-AES non compatibile."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel doesn't support loop-AES compatible mapping."
+msgstr "Il kernel non supporta la mappatura compatibile loop-AES."
+
+#: lib/tcrypt/tcrypt.c:505
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Errore nel leggere il file chiave %s."
+
+#: lib/tcrypt/tcrypt.c:545
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%d) exceeded."
+msgstr "Lunghezza massima (%d) della passphrase TCRYPT superata."
+
+#: lib/tcrypt/tcrypt.c:586
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "L'algoritmo di hash PBKDF2 %s non è disponibile, viene saltato."
+
+#: lib/tcrypt/tcrypt.c:604 src/cryptsetup.c:915
+msgid "Required kernel crypto interface not available."
+msgstr "L'interfaccia kernel richiesta del cifrario non è disponibile."
+
+#: lib/tcrypt/tcrypt.c:606 src/cryptsetup.c:917
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Assicurarsi di avere il modulo del kernel algif_skcipher caricato."
+
+#: lib/tcrypt/tcrypt.c:746
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Attivazione non supportata per la dimensione del settore di %d."
+
+#: lib/tcrypt/tcrypt.c:752
+msgid "Kernel doesn't support activation for this TCRYPT legacy mode."
+msgstr "Il kernel non supporta l'attivazione per questa modalità legacy TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:786
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Attivazione sistema di cifratura TCRYPT per la partizione %s."
+
+#: lib/tcrypt/tcrypt.c:864
+msgid "Kernel doesn't support TCRYPT compatible mapping."
+msgstr "Il kernel non supporta la mappatura compatibile TCYPRT."
+
+#: lib/tcrypt/tcrypt.c:1085
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Questa funzione non è supportata senza l'header TCRYPT caricato."
+
+#: lib/verity/verity.c:69 lib/verity/verity.c:175
+#, c-format
+msgid "Verity device %s doesn't use on-disk header."
+msgstr "Il dispositivo verity %s non usa header su disco."
+
+#: lib/verity/verity.c:94
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Il dispositivo %s non è un dispositivo VERITY valido."
+
+#: lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Versione %d di VERITY non supportata."
+
+#: lib/verity/verity.c:132
+msgid "VERITY header corrupted."
+msgstr "Header VERITY danneggiato."
+
+#: lib/verity/verity.c:169
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Fornito un formato UUID per VERITY errato sul dispositivo %s."
+
+#: lib/verity/verity.c:202
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Errore durante l'aggiornamento dell'header verity sul dispositivo %s."
+
+#: lib/verity/verity.c:266
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Impossibile risolvere gli errori con dispositivo FEC."
+
+#: lib/verity/verity.c:268
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Trovati %u errori risolubili con dispositivo FEC."
+
+#: lib/verity/verity.c:306
+msgid "Kernel doesn't support dm-verity mapping."
+msgstr "Il kernel non supporta la mappatura dm-verity."
+
+#: lib/verity/verity.c:317
+msgid "Verity device detected corruption after activation."
+msgstr "Il dispositivo verity ha rilevato un'anomalia dopo l'attivazione."
+
+#: lib/verity/verity_hash.c:59
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "L'area spare non risulta essere a zero alla posizione %<PRIu64>."
+
+#: lib/verity/verity_hash.c:160 lib/verity/verity_hash.c:287
+#: lib/verity/verity_hash.c:300
+msgid "Device offset overflow."
+msgstr "Overflow offset del dispositivo."
+
+#: lib/verity/verity_hash.c:200
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Verifica alla posizione %<PRIu64> non riuscita."
+
+#: lib/verity/verity_hash.c:273
+msgid "Invalid size parameters for verity device."
+msgstr "Parametri della dimensione non validi per il dispositivo verity."
+
+#: lib/verity/verity_hash.c:293
+msgid "Hash area overflow."
+msgstr "Overflow dell'area di hash."
+
+#: lib/verity/verity_hash.c:370
+msgid "Verification of data area failed."
+msgstr "Verifica dell'area dati non riuscita."
+
+#: lib/verity/verity_hash.c:375
+msgid "Verification of root hash failed."
+msgstr "Verifica dall'hash root non riuscita."
+
+#: lib/verity/verity_hash.c:381
+msgid "Input/output error while creating hash area."
+msgstr "Errore di input/output nel creare l'area hash."
+
+#: lib/verity/verity_hash.c:383
+msgid "Creation of hash area failed."
+msgstr "Creazione dell'area hash non riuscita."
+
+#: lib/verity/verity_hash.c:430
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "Attenzione: il kernel non può attivare il dispositivo se la dimensione del blocco dati supera la dimensione di pagina (%u)."
+
+#: lib/verity/verity_fec.c:132
+msgid "Failed to allocate RS context."
+msgstr "Allocazione contesto RS non riuscita."
+
+#: lib/verity/verity_fec.c:147
+msgid "Failed to allocate buffer."
+msgstr "Allocazione buffer non riuscita."
+
+#: lib/verity/verity_fec.c:157
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Lettura del blocco RS %<PRIu64> byte %d non riuscita."
+
+#: lib/verity/verity_fec.c:170
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Lettura bit di parità per il blocco RS %<PRIu64> non riuscita."
+
+#: lib/verity/verity_fec.c:178
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Ripristino della parità per il blocco %<PRIu64> non riuscito."
+
+#: lib/verity/verity_fec.c:189
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Scrittura della parità per il blocco RS %<PRIu64> non riuscita."
+
+#: lib/verity/verity_fec.c:224
+msgid "Block sizes must match for FEC."
+msgstr "Le dimensioni del blocco devono corrispondere per FEC."
+
+#: lib/verity/verity_fec.c:230
+msgid "Invalid number of parity bytes."
+msgstr "Numero di byte di parità non valido."
+
+#: lib/verity/verity_fec.c:266
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Impossibile determinare la dimensione per il dispositivo %s."
+
+#: lib/integrity/integrity.c:239 lib/integrity/integrity.c:304
+msgid "Kernel doesn't support dm-integrity mapping."
+msgstr "Il kernel non supporta la mappatura dm-integrity."
+
+#: lib/luks2/luks2_disk_metadata.c:413
+msgid "Failed to acquire write device lock."
+msgstr "Impossibile acquisire blocco del dispositivo di scrittura."
+
+#: lib/luks2/luks2_disk_metadata.c:654 lib/luks2/luks2_disk_metadata.c:675
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Il dispositivo contiene firme ambigue, impossibile recuperare automaticamente LUKS2.\n"
+"Eseguire \"cryptsetup repair\" per il recupero."
+
+#: lib/luks2/luks2_json_format.c:99
+msgid "No space for new keyslot."
+msgstr "Spazio insufficiente per il nuovo slot di chiave."
+
+#: lib/luks2/luks2_json_format.c:158
+msgid "Requested data offset is too small."
+msgstr "L'offset dati richiesto è troppo piccolo."
+
+#: lib/luks2/luks2_json_format.c:195
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "Attenzione: l'area degli slot di chiave è molto piccola (%<PRIu64> byte), il conteggio degli slot di chiave LUKS2 disponibili è limitato.\n"
+
+#: lib/luks2/luks2_json_metadata.c:866 lib/luks2/luks2_json_metadata.c:982
+#: lib/luks2/luks2_json_metadata.c:1055 lib/luks2/luks2_keyslot_luks2.c:105
+#: lib/luks2/luks2_keyslot_luks2.c:128
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Impossibile acquisire il blocco di lettura sul dispositivo %s."
+
+#: lib/luks2/luks2_json_metadata.c:878 lib/luks2/luks2_json_metadata.c:1149
+#: lib/luks2/luks2_keyslot.c:431 lib/luks2/luks2_keyslot_luks2.c:40
+#: lib/luks2/luks2_keyslot_luks2.c:69
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Impossibile acquisire il blocco di scrittura sul dispositivo %s."
+
+#: lib/luks2/luks2_json_metadata.c:1072
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Rilevati requisiti LUKS2 proibiti nel backup %s."
+
+#: lib/luks2/luks2_json_metadata.c:1113
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "L'offset di dati è diverso tra il dispositivo e il backup, ripristino non riuscito."
+
+#: lib/luks2/luks2_json_metadata.c:1119
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "L'header binario con dimensione aree dello slot di chiave è diverso tra il dispositivo e il backup, ripristino non riuscito."
+
+#: lib/luks2/luks2_json_metadata.c:1126
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Il dispositivo %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1127
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "non contiene un header LUKS2. La sostituzione dell'header può distruggere i dati su quel dispositivo."
+
+#: lib/luks2/luks2_json_metadata.c:1128
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "contiene già un header LUKS2. La sostituzione dell'header distruggerà gli slot di chiave esistenti."
+
+#: lib/luks2/luks2_json_metadata.c:1130
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"Attenzione: requisiti LUKS2 sconosciuti rilevati nell'header del dispositivo reale.\n"
+"La sostituzione dell'header con il backup può danneggiare i dati su quel dispositivo."
+
+#: lib/luks2/luks2_json_metadata.c:1132
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"Attenzione: rilevata re-cifratura non completata sul dispositivo.\n"
+"La sostituzione dell'header con il backup potrebbe danneggiare i dati."
+
+#: lib/luks2/luks2_json_metadata.c:1234
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Flag %s sconosciuto ignorato."
+
+#: lib/luks2/luks2_json_metadata.c:1869
+msgid "Failed to read LUKS2 requirements."
+msgstr "Letture dei requisiti LUKS2 non riuscita."
+
+#: lib/luks2/luks2_json_metadata.c:1876
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Rilevati requisiti LUKS2 non soddisfatti."
+
+#: lib/luks2/luks2_json_metadata.c:1884
+msgid "Offline reencryption in progress. Aborting."
+msgstr "Re-cifratura offline in corso. Terminato."
+
+#: lib/luks2/luks2_luks1_convert.c:474
+#, c-format
+msgid "Can not check status of device with uuid: %s."
+msgstr "Impossibile controllare lo stato del dispositivo con UUID: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:500
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Impossibile convertire l'header con metadati LUKSMETA aggiuntivi."
+
+#: lib/luks2/luks2_luks1_convert.c:537
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Impossibile spostare l'area dello slot di chiave: spazio insufficiente."
+
+#: lib/luks2/luks2_luks1_convert.c:577 lib/luks2/luks2_luks1_convert.c:854
+msgid "Unable to move keyslot area."
+msgstr "Impossibile spostare l'area dello slot di chiave."
+
+#: lib/luks2/luks2_luks1_convert.c:672
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Impossibile convertire al formato LUKS1: i digest dello slot di chiave non sono compatibili con LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:684
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Impossibile convertire al formato LUKS1: il dispositivo utilizza una chiave di cifrario %s con wrapper."
+
+#: lib/luks2/luks2_luks1_convert.c:692
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Impossibile convertire al formato LUKS1: l'header LUKS2 contiene %u token."
+
+#: lib/luks2/luks2_luks1_convert.c:706
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Impossibile convertire al formato LUKS1: lo slot di chiave %u è in uno stato non valido."
+
+#: lib/luks2/luks2_luks1_convert.c:711
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Impossibile convertire al formato LUKS1: lo slot %u (oltre gli slot massimi) è ancora attivo."
+
+#: lib/luks2/luks2_luks1_convert.c:716
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Impossibile convertire al formato LUKS1: lo slot di chiave %u non è compatibile con LUKS1."
+
+#: lib/luks2/luks2_token.c:262
+msgid "No free token slot."
+msgstr "Nessun slot token libero."
+
+#: lib/luks2/luks2_token.c:269
+#, c-format
+msgid "Failed to create builtin token %s."
+msgstr "Impossibile creare token integrato %s."
+
+#: src/cryptsetup.c:141
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Impossibile verificare la passphrase su input non tty."
+
+#: src/cryptsetup.c:182
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "I parametri di cifratura dello slot di chiave possono essere impostati solo per dispositivi LUKS2."
+
+#: src/cryptsetup.c:212 src/cryptsetup.c:849 src/cryptsetup.c:1088
+#: src/cryptsetup_reencrypt.c:749 src/cryptsetup_reencrypt.c:814
+msgid "No known cipher specification pattern detected."
+msgstr "Non è stato rilevato alcun modello noto di specifica di cifrario."
+
+#: src/cryptsetup.c:220
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "Attenzione: il parametro --hash viene ignorato in modalità normale con file di chiave specificato.\n"
+
+#: src/cryptsetup.c:228
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "Attenzione: l'opzione --keyfile-size viene ignorata, la dimensione di lettura è la stessa della dimensione della chiave di cifratura.\n"
+
+#: src/cryptsetup.c:268
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Rilevata firma dispositivo su %s. Attenzione: continuare potrebbe danneggiare i dati esistenti."
+
+#: src/cryptsetup.c:274 src/cryptsetup.c:969 src/cryptsetup.c:1065
+#: src/cryptsetup.c:1138 src/cryptsetup.c:1763 src/integritysetup.c:230
+msgid "Operation aborted.\n"
+msgstr "Operazione interrotta.\n"
+
+#: src/cryptsetup.c:342
+msgid "Option --key-file is required."
+msgstr "È richiesta l'opzione --key-file."
+
+#: src/cryptsetup.c:395
+msgid "Enter VeraCrypt PIM: "
+msgstr "Inserire PIM VeraCrypt: "
+
+#: src/cryptsetup.c:404
+msgid "Invalid PIM value: parse error."
+msgstr "Valore PIM non valido: errore di lettura."
+
+#: src/cryptsetup.c:407
+msgid "Invalid PIM value: 0."
+msgstr "Valore PIM non valido: 0."
+
+#: src/cryptsetup.c:410
+msgid "Invalid PIM value: outside of range."
+msgstr "Valore PIM non valido: fuori dall'intervallo."
+
+#: src/cryptsetup.c:433
+msgid "No device header detected with this passphrase."
+msgstr "Nessun header di dispositivo rilevato con questa passphrase."
+
+#: src/cryptsetup.c:495 src/cryptsetup.c:1790
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Il dump dell'header con la chiave di volume contiene informazioni\n"
+"confidenziali che permettono di accedere alla partizione cifrata senza passphrase.\n"
+"Questo dump dovrebbe sempre essere salvato in modo cifrato in un luogo sicuro."
+
+#: src/cryptsetup.c:574
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Il dispositivo %s è ancora attivo ed è pianificato per essere rimosso.\n"
+
+#: src/cryptsetup.c:602
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Il ridimensionamento di un dispositivo attivo richiede la chiave del volume nel portachiavi, ma l'opzione --disable-keyring è impostata."
+
+#: src/cryptsetup.c:727
+msgid "Benchmark interrupted."
+msgstr "Benchmark interrotto."
+
+#: src/cryptsetup.c:748
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/D\n"
+
+#: src/cryptsetup.c:750
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iterazioni per secondo per chiave di %zu-bit\n"
+
+#: src/cryptsetup.c:764
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/D\n"
+
+#: src/cryptsetup.c:766
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iterazioni, %5u memoria, %1u thread paralleli (CPU) per chiave di %zu-bit (tempo richiesto %u ms)\n"
+
+#: src/cryptsetup.c:790
+msgid "Result of benchmark is not reliable."
+msgstr "Il risultato del benchmark non è attendibile."
+
+#: src/cryptsetup.c:841
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# I test sono approssimati usando solo la memoria (nessun IO dall'archivio).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:875
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr ""
+"#%*s Algoritmo | Chiave | Cifratura | Decrifrazione\n"
+"\n"
+
+#: src/cryptsetup.c:879
+#, c-format
+msgid "Cipher %s is not available."
+msgstr "Il cifrario %s non è disponibile."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:899
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr ""
+"# Algoritmo | Chiave | Cifratura | Decrifrazione\n"
+"\n"
+
+#: src/cryptsetup.c:908
+msgid "N/A"
+msgstr "N/D"
+
+#: src/cryptsetup.c:968
+msgid "Really try to repair LUKS device header?"
+msgstr "Provare a riparare l'header del dispositivo LUKS?"
+
+#: src/cryptsetup.c:984 src/integritysetup.c:144
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Pulizia del dispositivo per inizializzare il controllo dell'integrità.\n"
+"È possibile interrompere questa operazione premendo Ctrl+C: la parte del dispositivo non pulita\n"
+"conterrà dati di controllo non validi.\n"
+
+#: src/cryptsetup.c:1006 src/integritysetup.c:166
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Impossibile disattivare il dispositivo %s temporaneo."
+
+#: src/cryptsetup.c:1050
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "L'opzione di integrità può essere usata solo col formato LUKS2."
+
+#: src/cryptsetup.c:1055 src/cryptsetup.c:1115
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Opzioni dimensione metadati LUKS2 non supportate."
+
+#: src/cryptsetup.c:1072
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Impossibile creare il file header %s."
+
+#: src/cryptsetup.c:1095 src/integritysetup.c:192 src/integritysetup.c:201
+#: src/integritysetup.c:210 src/integritysetup.c:276 src/integritysetup.c:285
+#: src/integritysetup.c:295
+msgid "No known integrity specification pattern detected."
+msgstr "Non è stato rilevato alcun modello noto di specifica di integrità."
+
+#: src/cryptsetup.c:1108
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Impossibile usare %s come header on-disk."
+
+#: src/cryptsetup.c:1132 src/integritysetup.c:224
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Ciò sovrascriverà i dati in %s in modo irreversibile."
+
+#: src/cryptsetup.c:1173 src/cryptsetup.c:1484 src/cryptsetup.c:1551
+#: src/cryptsetup.c:1646 src/cryptsetup.c:1712
+msgid "Failed to set pbkdf parameters."
+msgstr "Impostazione dei parametri pbkdf non riuscita."
+
+#: src/cryptsetup.c:1242
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "L'offset di dati ridotti è ammesso solo per l'header LUKS scollegato."
+
+#: src/cryptsetup.c:1284
+msgid "Device activated but cannot make flags persistent."
+msgstr "Dispositivo attivato, ma non è possibile rendere i flag permanenti."
+
+#: src/cryptsetup.c:1365
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Slot di chiave %d selezionato per l'eliminazione."
+
+#: src/cryptsetup.c:1368 src/cryptsetup.c:1706
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Lo slot di chiave %d non è attivo."
+
+#: src/cryptsetup.c:1377 src/cryptsetup.c:1438
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Questo è l'ultimo slot di chiave. Il dispositivo sarà inutilizzabile dopo aver eliminato questa chiave."
+
+#: src/cryptsetup.c:1378
+msgid "Enter any remaining passphrase: "
+msgstr "Inserire una delle passphrase rimanenti: "
+
+#: src/cryptsetup.c:1379 src/cryptsetup.c:1440
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operazione terminata, lo slot di chiave NON è stato pulito.\n"
+
+#: src/cryptsetup.c:1417
+msgid "Enter passphrase to be deleted: "
+msgstr "Inserire la passphrase da eliminare: "
+
+#: src/cryptsetup.c:1435
+#, c-format
+msgid "Key slot %d selected for deletion."
+msgstr "Slot di chiave %d selezionato per l'eliminazione."
+
+#: src/cryptsetup.c:1498 src/cryptsetup.c:1565 src/cryptsetup.c:1599
+msgid "Enter new passphrase for key slot: "
+msgstr "Inserire la nuova passphrase per lo slot di chiave: "
+
+#: src/cryptsetup.c:1582 src/cryptsetup_reencrypt.c:1352
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Inserire una delle passphrase esistenti: "
+
+#: src/cryptsetup.c:1650
+msgid "Enter passphrase to be changed: "
+msgstr "Inserire la passphrase da cambiare: "
+
+#: src/cryptsetup.c:1666 src/cryptsetup_reencrypt.c:1338
+msgid "Enter new passphrase: "
+msgstr "Inserire la nuova passphrase: "
+
+#: src/cryptsetup.c:1716
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Inserire la passphrase per lo slot da convertire: "
+
+#: src/cryptsetup.c:1740
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "È supportato un solo argomento dispositivo per ogni operazione isLuks."
+
+#: src/cryptsetup.c:1924 src/cryptsetup.c:1945
+msgid "Option --header-backup-file is required."
+msgstr "È richiesta l'opzione --header-backup-file."
+
+#: src/cryptsetup.c:1975
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s non è un dispositivo gestito via cryptsetup."
+
+#: src/cryptsetup.c:1986
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "L'aggiornamento non è supportato per dispositivi di tipo %s"
+
+#: src/cryptsetup.c:2024
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Tipo di dispositivo metadati %s non riconosciuto."
+
+#: src/cryptsetup.c:2027
+msgid "Command requires device and mapped name as arguments."
+msgstr "Il comando richiede un dispositivo e un nome di mappatura come argomenti."
+
+#: src/cryptsetup.c:2049
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Questa operazione eliminerà tutti gli slot di chiave sul dispositivo %s.\n"
+"Il dispositivo sarà inutilizzabile dopo questa operazione."
+
+#: src/cryptsetup.c:2056
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operazione terminata, gli slot di chiave NON sono stati puliti.\n"
+
+#: src/cryptsetup.c:2093
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Tipo LUKS non valido, solo «luks1» o «luks2» sono supportati."
+
+#: src/cryptsetup.c:2111
+#, c-format
+msgid "Device is already %s type."
+msgstr "Il dispositivo è già di tipo %s."
+
+#: src/cryptsetup.c:2116
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr ""
+"Questa operazione converte %s nel formato %s.\n"
+"\n"
+
+#: src/cryptsetup.c:2122
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operazione terminata, il dispositivo NON è stato convertito.\n"
+
+#: src/cryptsetup.c:2162
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Manca l'opzione --priority, --label o --subsystem."
+
+#: src/cryptsetup.c:2196 src/cryptsetup.c:2229 src/cryptsetup.c:2252
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Il token %d non è valido."
+
+#: src/cryptsetup.c:2199 src/cryptsetup.c:2255
+#, c-format
+msgid "Token %d in use."
+msgstr "Il token %d è in uso."
+
+#: src/cryptsetup.c:2206
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Aggiunta del token luks2-keyring %d non riuscita."
+
+#: src/cryptsetup.c:2215 src/cryptsetup.c:2277
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Assegnazione del token %d allo slot di chiave %d non riuscita."
+
+#: src/cryptsetup.c:2232
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Il token %d non è in uso."
+
+#: src/cryptsetup.c:2267
+msgid "Failed to import token from file."
+msgstr "Importazione del token da file non riuscita."
+
+#: src/cryptsetup.c:2292
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Recupero del token %d per l'esportazione non riuscito."
+
+#: src/cryptsetup.c:2307
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Il parametro --key-description è obbligatorio per l'azione di aggiunta token."
+
+#: src/cryptsetup.c:2313 src/cryptsetup.c:2321
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "L'azione richiede un token specifico. Utilizzare il parametro --token-id."
+
+#: src/cryptsetup.c:2326
+#, c-format
+msgid "Invalid token operation %s."
+msgstr "Operazione token %s non valida."
+
+#: src/cryptsetup.c:2366
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<dispositivo> [--type <tipo>] [<nome>]"
+
+#: src/cryptsetup.c:2366
+msgid "open device as mapping <name>"
+msgstr "Apre il dispositivo come mappatura in <nome>"
+
+#: src/cryptsetup.c:2367 src/cryptsetup.c:2368 src/cryptsetup.c:2369
+#: src/veritysetup.c:363 src/veritysetup.c:364 src/integritysetup.c:464
+#: src/integritysetup.c:465
+msgid "<name>"
+msgstr "<nome>"
+
+#: src/cryptsetup.c:2367
+msgid "close device (remove mapping)"
+msgstr "Chiude il dispositivo (rimuove la mappatura)"
+
+#: src/cryptsetup.c:2368
+msgid "resize active device"
+msgstr "Ridimensiona il dispositivo attivo"
+
+#: src/cryptsetup.c:2369
+msgid "show device status"
+msgstr "Mostra lo stato del dispositivo"
+
+#: src/cryptsetup.c:2370
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <cifrario>]"
+
+#: src/cryptsetup.c:2370
+msgid "benchmark cipher"
+msgstr "Esegue benchmark del cifrario"
+
+#: src/cryptsetup.c:2371 src/cryptsetup.c:2372 src/cryptsetup.c:2373
+#: src/cryptsetup.c:2374 src/cryptsetup.c:2381 src/cryptsetup.c:2382
+#: src/cryptsetup.c:2383 src/cryptsetup.c:2384 src/cryptsetup.c:2385
+#: src/cryptsetup.c:2386 src/cryptsetup.c:2387 src/cryptsetup.c:2388
+msgid "<device>"
+msgstr "<dispositivo>"
+
+#: src/cryptsetup.c:2371
+msgid "try to repair on-disk metadata"
+msgstr "Prova a riparare i metadati on-disk"
+
+#: src/cryptsetup.c:2372
+msgid "erase all keyslots (remove encryption key)"
+msgstr "Elimina tutti gli slot di chiavi (rimuove chiave di cifratura)"
+
+#: src/cryptsetup.c:2373
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "Converte LUKS dal/al formato LUKS2"
+
+#: src/cryptsetup.c:2374
+msgid "set permanent configuration options for LUKS2"
+msgstr "Imposta opzioni di configurazione permanenti per LUKS2"
+
+#: src/cryptsetup.c:2375 src/cryptsetup.c:2376
+msgid "<device> [<new key file>]"
+msgstr "<dispositivo> [<nuovo file chiave>]"
+
+#: src/cryptsetup.c:2375
+msgid "formats a LUKS device"
+msgstr "Formatta un dispositivo LUKS"
+
+#: src/cryptsetup.c:2376
+msgid "add key to LUKS device"
+msgstr "Aggiunge chiave al dispositivo LUKS"
+
+#: src/cryptsetup.c:2377 src/cryptsetup.c:2378 src/cryptsetup.c:2379
+msgid "<device> [<key file>]"
+msgstr "<dispositivo> [<file chiave>]"
+
+#: src/cryptsetup.c:2377
+msgid "removes supplied key or key file from LUKS device"
+msgstr "Rimuove la chiave fornita o il file chiave dal dispositivo LUKS"
+
+#: src/cryptsetup.c:2378
+msgid "changes supplied key or key file of LUKS device"
+msgstr "Cambia la chiave fornita o il file chiave del dispositivo LUKS"
+
+#: src/cryptsetup.c:2379
+msgid "converts a key to new pbkdf parameters"
+msgstr "Converte una chiave nei nuovi parametri pbkdf"
+
+#: src/cryptsetup.c:2380
+msgid "<device> <key slot>"
+msgstr "<dispositivo> <slot di chiave>"
+
+#: src/cryptsetup.c:2380
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "Ripulisce la chiave con numero <slot di chiave> dal dispositivo LUKS"
+
+#: src/cryptsetup.c:2381
+msgid "print UUID of LUKS device"
+msgstr "Stampa l'UUID del dispositivo LUKS"
+
+#: src/cryptsetup.c:2382
+msgid "tests <device> for LUKS partition header"
+msgstr "Verifica l'header della partizione LUKS di <dispositivo>"
+
+#: src/cryptsetup.c:2383
+msgid "dump LUKS partition information"
+msgstr "Esegue il dump delle informazioni della partizione LUKS"
+
+#: src/cryptsetup.c:2384
+msgid "dump TCRYPT device information"
+msgstr "Esegue il dump delle informazioni TCRYPT del dispositivo"
+
+#: src/cryptsetup.c:2385
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Sospende il dispositivo LUKS e ripulisce la chiave (operazioni I/O bloccate)"
+
+#: src/cryptsetup.c:2386
+msgid "Resume suspended LUKS device"
+msgstr "Ripristina il dispositivo LUKS sospeso"
+
+#: src/cryptsetup.c:2387
+msgid "Backup LUKS device header and keyslots"
+msgstr "Fa il backup dell'header del dispositivo e degli slot di chiave"
+
+#: src/cryptsetup.c:2388
+msgid "Restore LUKS device header and keyslots"
+msgstr "Ripristina l'header del dispositivo LUKS e gli slot di chiave"
+
+#: src/cryptsetup.c:2389
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <dispositivo>"
+
+#: src/cryptsetup.c:2389
+msgid "Manipulate LUKS2 tokens"
+msgstr "Gestisce token LUKS2"
+
+#: src/cryptsetup.c:2407 src/veritysetup.c:380 src/integritysetup.c:481
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<azione> è una tra:\n"
+
+#: src/cryptsetup.c:2413
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+msgstr ""
+"\n"
+"È possibile usare anche la vecchia sintassi <azione>:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+
+#: src/cryptsetup.c:2417
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nome> è il dispositivo da creare in %s\n"
+"<dispositivo> è il dispositivo cifrato\n"
+"<slot di chiave> è il numero dello slot di chiave LUKS da modificare\n"
+"<file chiave> è il file chiave opzionale per la nuova chiave per l'azione luksAddKey\n"
+
+#: src/cryptsetup.c:2424
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Formato predefinito metadati compilati: %s (per azione luksFormat).\n"
+
+#: src/cryptsetup.c:2429
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Parametri predefiniti compilati di chiave e passphrase:\n"
+"\tdimensione massima file chiave: %dkB, lunghezza massima della passphrase interattiva %d (caratteri)\n"
+"PBKDF predefinito per LUKS1: %s, tempo iterazione: %d (ms)\n"
+"PBKDF predefinito per LUKS2: %s\n"
+"\tTempo iterazione: %d, memoria richiesta: %dkB, thread paralleli: %d\n"
+
+#: src/cryptsetup.c:2440
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Parametri predefiniti compilati del cifrario del dispositivo:\n"
+"\tloop-AES: %s, chiave: %d bit\n"
+"\tin chiaro: %s, chiave: %d bit, hash della password: %s\n"
+"\tLUKS: %s, chiave: %d bit, hash dell'header LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:2449
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: la dimensione predefinita della chiave in modalità XTS (due chiavi interne) viene raddoppiata.\n"
+
+#: src/cryptsetup.c:2460 src/veritysetup.c:537 src/integritysetup.c:621
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: richiede %s come argomenti"
+
+#: src/cryptsetup.c:2498 src/veritysetup.c:420 src/integritysetup.c:515
+#: src/cryptsetup_reencrypt.c:1611
+msgid "Show this help message"
+msgstr "Mostra questo messaggio d'aiuto"
+
+#: src/cryptsetup.c:2499 src/veritysetup.c:421 src/integritysetup.c:516
+#: src/cryptsetup_reencrypt.c:1612
+msgid "Display brief usage"
+msgstr "Mostra il modo d'uso sintetico"
+
+#: src/cryptsetup.c:2503 src/veritysetup.c:425 src/integritysetup.c:520
+#: src/cryptsetup_reencrypt.c:1616
+msgid "Help options:"
+msgstr "Opzioni di aiuto:"
+
+#: src/cryptsetup.c:2504 src/veritysetup.c:426 src/integritysetup.c:521
+#: src/cryptsetup_reencrypt.c:1617
+msgid "Print package version"
+msgstr "Stampa la versione del pacchetto"
+
+#: src/cryptsetup.c:2505 src/veritysetup.c:427 src/integritysetup.c:522
+#: src/cryptsetup_reencrypt.c:1618
+msgid "Shows more detailed error messages"
+msgstr "Mostra i messaggi di errore con maggior dettaglio"
+
+#: src/cryptsetup.c:2506 src/veritysetup.c:428 src/integritysetup.c:523
+#: src/cryptsetup_reencrypt.c:1619
+msgid "Show debug messages"
+msgstr "Mostra i messaggi di debug"
+
+#: src/cryptsetup.c:2507
+msgid "Show debug messages including JSON metadata"
+msgstr "Mostra i messaggi di debug compresi i metadati JSON"
+
+#: src/cryptsetup.c:2508 src/cryptsetup_reencrypt.c:1621
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "Il cifrario usato per cifrare il disco (vedere /proc/crypto)"
+
+#: src/cryptsetup.c:2509 src/cryptsetup_reencrypt.c:1623
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "L'hash usato per creare la chiave di cifratura dalla passphrase"
+
+#: src/cryptsetup.c:2510
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Verifica la passphrase chiedendola due volte"
+
+#: src/cryptsetup.c:2511 src/cryptsetup_reencrypt.c:1625
+msgid "Read the key from a file"
+msgstr "Legge la chiave da un file"
+
+#: src/cryptsetup.c:2512
+msgid "Read the volume (master) key from file."
+msgstr "Legge la chiave (master) del volume dal file."
+
+#: src/cryptsetup.c:2513
+msgid "Dump volume (master) key instead of keyslots info"
+msgstr "Esegue il dump della chiave (master) del volume invece delle informazioni sugli slot di chiave"
+
+#: src/cryptsetup.c:2514 src/cryptsetup_reencrypt.c:1622
+msgid "The size of the encryption key"
+msgstr "La dimensione della chiave di cifratura"
+
+#: src/cryptsetup.c:2514 src/cryptsetup.c:2571 src/integritysetup.c:539
+#: src/integritysetup.c:543 src/integritysetup.c:547
+#: src/cryptsetup_reencrypt.c:1622
+msgid "BITS"
+msgstr "BIT"
+
+#: src/cryptsetup.c:2515 src/cryptsetup_reencrypt.c:1638
+msgid "Limits the read from keyfile"
+msgstr "Limita la lettura dal file di chiave"
+
+#: src/cryptsetup.c:2515 src/cryptsetup.c:2516 src/cryptsetup.c:2517
+#: src/cryptsetup.c:2518 src/cryptsetup.c:2568 src/cryptsetup.c:2569
+#: src/veritysetup.c:431 src/veritysetup.c:432 src/veritysetup.c:433
+#: src/veritysetup.c:436 src/veritysetup.c:437 src/integritysetup.c:530
+#: src/integritysetup.c:534 src/integritysetup.c:535
+#: src/cryptsetup_reencrypt.c:1637 src/cryptsetup_reencrypt.c:1638
+#: src/cryptsetup_reencrypt.c:1639 src/cryptsetup_reencrypt.c:1640
+msgid "bytes"
+msgstr "byte"
+
+#: src/cryptsetup.c:2516 src/cryptsetup_reencrypt.c:1637
+msgid "Number of bytes to skip in keyfile"
+msgstr "Numero di byte da saltare nel file di chiave"
+
+#: src/cryptsetup.c:2517
+msgid "Limits the read from newly added keyfile"
+msgstr "Limita la lettura dal file di chiave appena aggiunto"
+
+#: src/cryptsetup.c:2518
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "Numero di byte da saltare nel file di chiave appena aggiunto"
+
+#: src/cryptsetup.c:2519
+msgid "Slot number for new key (default is first free)"
+msgstr "Numero dello slot per la nuova chiave (il primo libero è quello predefinito)"
+
+#: src/cryptsetup.c:2520
+msgid "The size of the device"
+msgstr "La dimensione del dispositivo"
+
+#: src/cryptsetup.c:2520 src/cryptsetup.c:2521 src/cryptsetup.c:2522
+#: src/cryptsetup.c:2528 src/integritysetup.c:531 src/integritysetup.c:536
+msgid "SECTORS"
+msgstr "SETTORI"
+
+#: src/cryptsetup.c:2521
+msgid "The start offset in the backend device"
+msgstr "L'offset iniziale del dispositivo di backend"
+
+#: src/cryptsetup.c:2522
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Quanti settori dei dati cifrati saltare dall'inizio"
+
+#: src/cryptsetup.c:2523
+msgid "Create a readonly mapping"
+msgstr "Crea una mappatura in sola lettura"
+
+#: src/cryptsetup.c:2524 src/integritysetup.c:524
+#: src/cryptsetup_reencrypt.c:1628
+msgid "Do not ask for confirmation"
+msgstr "Non chiede conferma"
+
+#: src/cryptsetup.c:2525
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Timeout per il prompt interattivo della passphrase (in secondi)"
+
+#: src/cryptsetup.c:2525 src/cryptsetup.c:2526 src/integritysetup.c:525
+#: src/cryptsetup_reencrypt.c:1629
+msgid "secs"
+msgstr "sec"
+
+#: src/cryptsetup.c:2526 src/integritysetup.c:525
+#: src/cryptsetup_reencrypt.c:1629
+msgid "Progress line update (in seconds)"
+msgstr "Aggiornamento linea di avanzamento (in secondi)"
+
+# (NDT) Descrizione dell'opzione
+# --tries, indica il numero di tentativi per richiesta
+#: src/cryptsetup.c:2527 src/cryptsetup_reencrypt.c:1630
+msgid "How often the input of the passphrase can be retried"
+msgstr "Quante volte può essere ritentato l'inserimento della passphrase"
+
+#: src/cryptsetup.c:2528
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Allinea il payload agli estremi del settore <n> - per luksFormat"
+
+#: src/cryptsetup.c:2529
+msgid "File with LUKS header and keyslots backup"
+msgstr "File con header LUKS e backup degli slot di chiave"
+
+#: src/cryptsetup.c:2530 src/cryptsetup_reencrypt.c:1631
+msgid "Use /dev/random for generating volume key"
+msgstr "Usa /dev/random per generare la chiave di volume"
+
+#: src/cryptsetup.c:2531 src/cryptsetup_reencrypt.c:1632
+msgid "Use /dev/urandom for generating volume key"
+msgstr "Usa /dev/urandom per generare la chiave di volume"
+
+#: src/cryptsetup.c:2532
+msgid "Share device with another non-overlapping crypt segment"
+msgstr "Condivide il dispositivo con un altro segmento cifrato non sovrapposto"
+
+#: src/cryptsetup.c:2533 src/veritysetup.c:440
+msgid "UUID for device to use"
+msgstr "UUID per il dispositivo da usare"
+
+#: src/cryptsetup.c:2534
+msgid "Allow discards (aka TRIM) requests for device"
+msgstr "Ammette le richieste di scarto (funzione TRIM) per il dispositivo"
+
+#: src/cryptsetup.c:2535 src/cryptsetup_reencrypt.c:1649
+msgid "Device or file with separated LUKS header"
+msgstr "Device o file con header LUKS separato"
+
+#: src/cryptsetup.c:2536
+msgid "Do not activate device, just check passphrase"
+msgstr "Non attiva il dispositivo, verifica solamente la passphrase"
+
+#: src/cryptsetup.c:2537
+msgid "Use hidden header (hidden TCRYPT device)"
+msgstr "Usa header nascosto (dispositivo TCRYPT nascosto)"
+
+#: src/cryptsetup.c:2538
+msgid "Device is system TCRYPT drive (with bootloader)"
+msgstr "Il dispositivo è l'unità TCRYPT di sistema (con bootloader)"
+
+#: src/cryptsetup.c:2539
+msgid "Use backup (secondary) TCRYPT header"
+msgstr "Usa header TCRYPT di backup (secondario)"
+
+#: src/cryptsetup.c:2540
+msgid "Scan also for VeraCrypt compatible device"
+msgstr "Ricerca anche dispositivo compatibile VeraCrypt"
+
+#: src/cryptsetup.c:2541
+msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "PIM (Personal Iteration Multiplier) per dispositivo VeraCrypt compatibile"
+
+#: src/cryptsetup.c:2542
+msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Interroga PIM (Personal Iteration Multiplier) per dispositivo VeraCrypt compatibile"
+
+#: src/cryptsetup.c:2543
+msgid "Type of device metadata: luks, plain, loopaes, tcrypt"
+msgstr "Tipo di metadati del dispositivo: luks, plain, loopaes, tcrypt"
+
+#: src/cryptsetup.c:2544
+msgid "Disable password quality check (if enabled)"
+msgstr "Disabilita la verifica della qualità della password (se abilitata)"
+
+#: src/cryptsetup.c:2545
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+msgstr "Usa l'opzione compatibile per prestazioni same_cpu_crypt di dm-crypt"
+
+#: src/cryptsetup.c:2546
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+msgstr "Usa l'opzione compatibile per prestazioni submit_from_crypt_cpus di dm-crypt"
+
+#: src/cryptsetup.c:2547
+msgid "Device removal is deferred until the last user closes it"
+msgstr "La rimozione del dispositivo è posticipata fino a quando l'ultimo utente lo chiude"
+
+#: src/cryptsetup.c:2548
+msgid "PBKDF iteration time for LUKS (in ms)"
+msgstr "Tempo di iterazione di PBKDF per LUKS (in ms)"
+
+#: src/cryptsetup.c:2548 src/cryptsetup_reencrypt.c:1627
+msgid "msecs"
+msgstr "msec"
+
+#: src/cryptsetup.c:2549 src/cryptsetup_reencrypt.c:1645
+msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+msgstr "Algoritmo PBKDF (per LUKS2): argon2i, argon2id, pbkdf2"
+
+#: src/cryptsetup.c:2550 src/cryptsetup_reencrypt.c:1646
+msgid "PBKDF memory cost limit"
+msgstr "Limite costo memoria PBKDF"
+
+#: src/cryptsetup.c:2550 src/cryptsetup_reencrypt.c:1646
+msgid "kilobytes"
+msgstr "kilobyte"
+
+#: src/cryptsetup.c:2551 src/cryptsetup_reencrypt.c:1647
+msgid "PBKDF parallel cost"
+msgstr "Costo PBKDF parallelo"
+
+#: src/cryptsetup.c:2551 src/cryptsetup_reencrypt.c:1647
+msgid "threads"
+msgstr "thread"
+
+#: src/cryptsetup.c:2552 src/cryptsetup_reencrypt.c:1648
+msgid "PBKDF iterations cost (forced, disables benchmark)"
+msgstr "Costo iterazioni PBKDF (forzato, disabilita benchmark)"
+
+#: src/cryptsetup.c:2553
+msgid "Keyslot priority: ignore, normal, prefer"
+msgstr "Priorità slot di chiave: ignore, normal, prefer"
+
+#: src/cryptsetup.c:2554
+msgid "Disable locking of on-disk metadata"
+msgstr "Disabilita il blocco dei metadati su disco"
+
+#: src/cryptsetup.c:2555
+msgid "Disable loading volume keys via kernel keyring"
+msgstr "Disabilita il caricamento delle chiavi di volume tramite il portachiavi del kernel"
+
+#: src/cryptsetup.c:2556
+msgid "Data integrity algorithm (LUKS2 only)"
+msgstr "Algoritmo integrità dei dati (solo LUKS2)"
+
+#: src/cryptsetup.c:2557 src/integritysetup.c:550
+msgid "Disable journal for integrity device"
+msgstr "Disabilita il journal per il dispositivo di integrità"
+
+#: src/cryptsetup.c:2558 src/integritysetup.c:526
+msgid "Do not wipe device after format"
+msgstr "Non pulisce il dispositivo dopo la formattazione"
+
+#: src/cryptsetup.c:2559
+msgid "Do not ask for passphrase if activation by token fails"
+msgstr "Non chiede la passphrase se l'attivazione con token non riesce"
+
+#: src/cryptsetup.c:2560
+msgid "Token number (default: any)"
+msgstr "Numero token (predefinito: any)"
+
+#: src/cryptsetup.c:2561
+msgid "Key description"
+msgstr "Descrizione chiave"
+
+#: src/cryptsetup.c:2562
+msgid "Encryption sector size (default: 512 bytes)"
+msgstr "Dimensione settore di cifratura (predefinito: 512 byte)"
+
+#: src/cryptsetup.c:2563
+msgid "Set activation flags persistent for device"
+msgstr "Imposta flag attivazione persistente per il dispositivo"
+
+#: src/cryptsetup.c:2564
+msgid "Set label for the LUKS2 device"
+msgstr "Imposta l'etichetta per il dispositivo LUKS2"
+
+#: src/cryptsetup.c:2565
+msgid "Set subsystem label for the LUKS2 device"
+msgstr "Imposta l'etichetta del sottosistema per il dispositivo LUKS2"
+
+#: src/cryptsetup.c:2566
+msgid "Create unbound (no assigned data segment) LUKS2 keyslot"
+msgstr "Crea slot di chiave LUKS2 non vincolato (segmento dati non assegnato)"
+
+#: src/cryptsetup.c:2567
+msgid "Read or write the json from or to a file"
+msgstr "Legge/Scrive JSON da/su file"
+
+#: src/cryptsetup.c:2568
+msgid "LUKS2 header metadata area size"
+msgstr "Dimensione area metadati header LUKS2"
+
+#: src/cryptsetup.c:2569
+msgid "LUKS2 header keyslots area size"
+msgstr "Dimensione area slot di chiave header LUKS2"
+
+#: src/cryptsetup.c:2570
+msgid "Refresh (reactivate) device with new parameters"
+msgstr "Aggiorna (riattiva) il dispositivo con nuovi parametri"
+
+#: src/cryptsetup.c:2571
+msgid "LUKS2 keyslot: The size of the encryption key"
+msgstr "Slot di chiave LUKS2: la dimensione della chiave di cifratura"
+
+#: src/cryptsetup.c:2572
+msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+msgstr "Slot di chiave LUKS2: il cifrario usato per la cifratura dello slot di chiave"
+
+#: src/cryptsetup.c:2588 src/veritysetup.c:461 src/integritysetup.c:568
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPZIONE...] <azione> <azione-specifica>]"
+
+#: src/cryptsetup.c:2645 src/veritysetup.c:501 src/integritysetup.c:585
+msgid "Argument <action> missing."
+msgstr "Argomento <azione> mancante."
+
+#: src/cryptsetup.c:2708 src/veritysetup.c:532 src/integritysetup.c:616
+msgid "Unknown action."
+msgstr "Azione sconosciuta."
+
+#: src/cryptsetup.c:2718
+msgid "Parameter --refresh is only allowed with open or refresh commands.\n"
+msgstr ""
+"Il parametro --refresh è consentito solo col comando open o refresh.\n"
+"\n"
+
+#: src/cryptsetup.c:2723
+msgid "Options --refresh and --test-passphrase are mutually exclusive.\n"
+msgstr ""
+"Solo un'opzione tra --refresh e --test-passphrase può essere usata.\n"
+"\n"
+
+#: src/cryptsetup.c:2728
+msgid "Option --deferred is allowed only for close command.\n"
+msgstr ""
+"L'opzione --deferred è consentita solo per il comando close.\n"
+"\n"
+
+#: src/cryptsetup.c:2733
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "L'opzione --shared è consentita solo per l'azione open di dispositivo in chiaro.\n"
+
+#: src/cryptsetup.c:2738
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "L'opzione --allow-discards è consentita solo per l'azione open.\n"
+
+#: src/cryptsetup.c:2743
+msgid "Option --persistent is allowed only for open operation.\n"
+msgstr "L'opzione --persistent è consentita solo per l'azione open.\n"
+
+#: src/cryptsetup.c:2748
+msgid "Option --persistent is not allowed with --test-passphrase.\n"
+msgstr "L'opzione --persistent non è consentita con --test-passphrase.\n"
+
+#: src/cryptsetup.c:2757
+msgid ""
+"Option --key-size is allowed only for luksFormat, luksAddKey (with --unbound),\n"
+"open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"L'opzione --key-size è consentita solo per le azioni luksFormat, luksAddKey (con --unbound),\n"
+"open e benchmark. Per limitare la lettura dal file chiave usare --keyfile-size=(byte)."
+
+#: src/cryptsetup.c:2763
+msgid "Option --integrity is allowed only for luksFormat (LUKS2).\n"
+msgstr "L'opzione --integrity è consentita solo per luksFormat (LUKS2).\n"
+
+#: src/cryptsetup.c:2768
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension.\n"
+msgstr ""
+"L'opzione --integrity-no-wipe può essere usata solo con l'azione format con estensione di integrità.\n"
+"\n"
+
+#: src/cryptsetup.c:2774
+msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations.\n"
+msgstr "Le opzioni --label e --subsystem sono consentite solo per operazioni LUKS2 luksFormat e config.\n"
+
+#: src/cryptsetup.c:2780
+msgid "Option --test-passphrase is allowed only for open of LUKS and TCRYPT devices.\n"
+msgstr "L'opzione --test-passphrase è consentita solo per l'operazione open di dispositivo LUKS e TCRYPT.\n"
+
+#: src/cryptsetup.c:2785 src/cryptsetup_reencrypt.c:1718
+msgid "Key size must be a multiple of 8 bits"
+msgstr "La dimensione della chiave deve essere un multiplo di 8 bit"
+
+#: src/cryptsetup.c:2791 src/cryptsetup_reencrypt.c:1403
+#: src/cryptsetup_reencrypt.c:1723
+msgid "Key slot is invalid."
+msgstr "Lo slot di chiave non è valido."
+
+#: src/cryptsetup.c:2798
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "L'opzione --key-file ha la precedenza sull'argomento specificato per il file chiave."
+
+#: src/cryptsetup.c:2805 src/veritysetup.c:544 src/integritysetup.c:640
+#: src/cryptsetup_reencrypt.c:1697
+msgid "Negative number for option not permitted."
+msgstr "Non è ammesso un numero negativo per l'opzione."
+
+#: src/cryptsetup.c:2809
+msgid "Only one --key-file argument is allowed."
+msgstr "È consentito solo un argomento --key-file."
+
+#: src/cryptsetup.c:2813 src/cryptsetup_reencrypt.c:1689
+#: src/cryptsetup_reencrypt.c:1727
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "È consentita solo una tra le opzioni --use-[u]random."
+
+#: src/cryptsetup.c:2817
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "L'opzione --use-[u]random è consentita solo per luksFormat."
+
+#: src/cryptsetup.c:2821
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "L'opzione --uuid è consentita solo per luksFormat e luksUUID."
+
+#: src/cryptsetup.c:2825
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "L'opzione --align-payload è consentita solo per luksFormat."
+
+#: src/cryptsetup.c:2829
+msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+msgstr "Le opzioni --luks2-metadata-size e --opt-luks2-keyslots-size sono consentite solo luksFormat con LUKS2."
+
+#: src/cryptsetup.c:2834
+msgid "Invalid LUKS2 metadata size specification."
+msgstr "Specifica di dimensione dei metadati LUKS2 non valida."
+
+#: src/cryptsetup.c:2838
+msgid "Invalid LUKS2 keyslots size specification."
+msgstr "Specifica di dimensione dello slot di chiave LUKS2 non valida."
+
+#: src/cryptsetup.c:2842
+msgid "Option --align-payload and --offset cannot be combined."
+msgstr "Le opzioni --align-payload --offset cannot non possono essere utilizzate assieme."
+
+#: src/cryptsetup.c:2848
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "L'opzione --skip è supportata solo per l'azione open di dispositivi in chiaro e loopaes.\n"
+
+#: src/cryptsetup.c:2855
+msgid "Option --offset is supported only for open of plain and loopaes devices and for luksFormat.\n"
+msgstr "L'opzione --offset è supportata solo per l'azione open di dispositivi in chiaro e loopaes e per luksFormat.\n"
+
+#: src/cryptsetup.c:2861
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "L'opzione --tcrypt-hidden, --tcrypt-system o --tcrypt-backup è supportata solo per dispositivo TCRYPT.\n"
+
+#: src/cryptsetup.c:2866
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "L'opzione --tcrypt-hidden non può essere utilizzata con --allow-discards.\n"
+
+#: src/cryptsetup.c:2871
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "L'opzione --veracrypt è supportata solo per dispositivo TCRYPT.\n"
+
+#: src/cryptsetup.c:2877
+msgid "Invalid argument for parameter --veracrypt-pim supplied.\n"
+msgstr "Argomento fornito per il parametro --veracrypt-pim non valido.\n"
+
+#: src/cryptsetup.c:2881
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr ""
+"L'opzione --veracrypt-pim è supportata solo per dispositivi compatibili VeraCrypt.\n"
+"\n"
+
+#: src/cryptsetup.c:2889
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "L'opzione --veracrypt-query-pim è supportata solo per dispositivi compatibili VeraCrypt.\n"
+
+#: src/cryptsetup.c:2893
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive.\n"
+msgstr ""
+"Solo un'opzione tra --veracrypt-pim e --veracrypt-query-pim può essere usata.\n"
+"\n"
+
+#: src/cryptsetup.c:2900
+msgid "Option --priority can be only ignore/normal/prefer.\n"
+msgstr "L'opzione --priority può essere solamente ignore/normal/prefer.\n"
+
+#: src/cryptsetup.c:2905
+msgid "Keyslot specification is required.\n"
+msgstr "È richiesta la specifica dello slot di chiave.\n"
+
+#: src/cryptsetup.c:2910 src/cryptsetup_reencrypt.c:1703
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id.\n"
+msgstr "La funzione di derivazione della chiave basata su password (PBKDF) può essere solamente pbkdf2 oppure argon2i/argon2id.\n"
+
+#: src/cryptsetup.c:2915 src/cryptsetup_reencrypt.c:1708
+msgid "PBKDF forced iterations cannot be combined with iteration time option.\n"
+msgstr "Le iterazioni forzate PBKDF non possono essere usate assieme all'opzione del tempo delle iterazioni.\n"
+
+#: src/cryptsetup.c:2921
+msgid "Sector size option is not supported for this command.\n"
+msgstr "L'opzione della dimensione del settore non è supportata con questo comando.\n"
+
+#: src/cryptsetup.c:2927
+msgid "Unsupported encryption sector size.\n"
+msgstr "Dimensione settore di cifratura non supportata.\n"
+
+#: src/cryptsetup.c:2932
+msgid "Key size is required with --unbound option.\n"
+msgstr "La dimensione della chiave è richiesta con l'opzione --unbound.\n"
+
+#: src/cryptsetup.c:2937
+msgid "Option --unbound may be used only with luksAddKey action.\n"
+msgstr "L'opzione --unbound può essere usata solamente con l'azione luksAddKey.\n"
+
+#: src/cryptsetup.c:2942
+msgid "Option --refresh may be used only with open action.\n"
+msgstr "L'opzione --refresh può essere usata solamente con l'azione open.\n"
+
+#: src/cryptsetup.c:2953
+msgid "Cannot disable metadata locking.\n"
+msgstr "Impossibile disabilitare il blocco dei metadati.\n"
+
+#: src/veritysetup.c:67
+msgid "Invalid salt string specified."
+msgstr "Stringa salt specificata non valida."
+
+#: src/veritysetup.c:98
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Impossibile creare l'immagine hash %s per la scrittura."
+
+#: src/veritysetup.c:108
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Impossibile creare l'immagine FEC %s per la scrittura."
+
+#: src/veritysetup.c:178
+msgid "Invalid root hash string specified."
+msgstr "Stringa hash root specificata non valida."
+
+#: src/veritysetup.c:360
+msgid "<data_device> <hash_device>"
+msgstr "<dispositivo_dati> <dispositivo_hash>"
+
+#: src/veritysetup.c:360 src/integritysetup.c:462
+msgid "format device"
+msgstr "Formatta il dispositivo"
+
+#: src/veritysetup.c:361
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<dispositivo_dati> <dispositivo_hash> <hash_root>"
+
+#: src/veritysetup.c:361
+msgid "verify device"
+msgstr "Verifica il dispositivo"
+
+#: src/veritysetup.c:362
+msgid "<data_device> <name> <hash_device> <root_hash>"
+msgstr "<dispositivo_dati> <nome> <dispositivo_hash> <hash_root>"
+
+#: src/veritysetup.c:362 src/integritysetup.c:463
+msgid "open device as <name>"
+msgstr "Apre il dispositivo come <nome>"
+
+#: src/veritysetup.c:363 src/integritysetup.c:464
+msgid "close device (deactivate and remove mapping)"
+msgstr "Chiude il dispositivo (disattiva e rimuove la mappatura)"
+
+#: src/veritysetup.c:364 src/integritysetup.c:465
+msgid "show active device status"
+msgstr "Mostra lo stato del dispositivo attivo"
+
+#: src/veritysetup.c:365
+msgid "<hash_device>"
+msgstr "<dispositivo_hash>"
+
+#: src/veritysetup.c:365 src/integritysetup.c:466
+msgid "show on-disk information"
+msgstr "Mostra informazioni on-disk"
+
+#: src/veritysetup.c:384
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nome> è il dispositivo da creare in %s\n"
+"<dispositivo_dati> è il dispositivo dei dati\n"
+"<dispositivo_hash> è il dispositivo che contiene i dati di verifica\n"
+"<hash_root> è l'hash del nodo radice nel <dispositivo_hash>\n"
+
+#: src/veritysetup.c:391
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Parametri predefiniti compilati in dm-verity:\n"
+"\tHash: %s, Blocco dati (byte): %u, Blocco hash (byte): %u, Dimensione salt: %u, Formato hash: %u\n"
+
+#: src/veritysetup.c:429
+msgid "Do not use verity superblock"
+msgstr "Non usa il super-blocco verity"
+
+#: src/veritysetup.c:430
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "Tipo di formato (1 - normale, 0 - ChromeOS originale)"
+
+#: src/veritysetup.c:430
+msgid "number"
+msgstr "numero"
+
+#: src/veritysetup.c:431
+msgid "Block size on the data device"
+msgstr "La dimensione del blocco sul dispositivo dati"
+
+#: src/veritysetup.c:432
+msgid "Block size on the hash device"
+msgstr "La dimensione del blocco sul dispositivo hash"
+
+#: src/veritysetup.c:433
+msgid "FEC parity bytes"
+msgstr "Byte di parità FEC"
+
+#: src/veritysetup.c:434
+msgid "The number of blocks in the data file"
+msgstr "Il numero di blocchi nel file dati"
+
+#: src/veritysetup.c:434
+msgid "blocks"
+msgstr "blocchi"
+
+#: src/veritysetup.c:435
+msgid "Path to device with error correction data"
+msgstr "Percorso al dispositivo con i dati di correzione degli errori"
+
+#: src/veritysetup.c:435 src/integritysetup.c:528
+msgid "path"
+msgstr "percorso"
+
+#: src/veritysetup.c:436
+msgid "Starting offset on the hash device"
+msgstr "L'offset iniziale del dispositivo di hash"
+
+#: src/veritysetup.c:437
+msgid "Starting offset on the FEC device"
+msgstr "L'offset iniziale del dispositivo FEC"
+
+#: src/veritysetup.c:438
+msgid "Hash algorithm"
+msgstr "Algoritmo di hash"
+
+#: src/veritysetup.c:438
+msgid "string"
+msgstr "stringa"
+
+#: src/veritysetup.c:439
+msgid "Salt"
+msgstr "Salt"
+
+#: src/veritysetup.c:439
+msgid "hex string"
+msgstr "stringa esadecimale"
+
+#: src/veritysetup.c:441
+msgid "Restart kernel if corruption is detected"
+msgstr "Riavvia il kernel se sono rilevati dati rovinati"
+
+#: src/veritysetup.c:442
+msgid "Ignore corruption, log it only"
+msgstr "Ignora i dati rovinati, li registra solamente"
+
+#: src/veritysetup.c:443
+msgid "Do not verify zeroed blocks"
+msgstr "Non verifica i blocchi azzerati"
+
+#: src/veritysetup.c:444
+msgid "Verify data block only the first time it is read"
+msgstr "Verifica i blocchi dati solo alla prima lettura"
+
+#: src/veritysetup.c:550
+msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation.\n"
+msgstr "L'opzione --ignore-corruption, --restart-on-corruption o --ignore-zero-blocks è consentita solo per l'operazione di apertura.\n"
+
+#: src/veritysetup.c:555
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together.\n"
+msgstr "Le opzioni --ignore-corruption e --restart-on-corruption non possono essere utilizzate assieme.\n"
+
+#: src/integritysetup.c:82 src/utils_password.c:298
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Impossibile leggere il file chiave %s."
+
+#: src/integritysetup.c:86 src/utils_password.c:302
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Impossibile leggere %d byte dal file chiave %s."
+
+#: src/integritysetup.c:248
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formattato con dimensione tag di %u, integrità interna %s.\n"
+
+#: src/integritysetup.c:462 src/integritysetup.c:466
+msgid "<integrity_device>"
+msgstr "<dispositivo_integrità>"
+
+#: src/integritysetup.c:463
+msgid "<integrity_device> <name>"
+msgstr "<dispositivo_integrità> <nome>"
+
+#: src/integritysetup.c:485
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<nome> è il dispositivo da creare in %s\n"
+"<dispositivo_integrità> è il dispositivo che contiene dai con i tag di integrità\n"
+
+#: src/integritysetup.c:490
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tTag size: %u bytes, Checksum algorithm: %s\n"
+msgstr ""
+"\n"
+"Parametri predefiniti compilati in dm-integrity:\n"
+"\tDimensione tag: %u byte - Algoritmo di controllo: %s\n"
+
+#: src/integritysetup.c:528
+msgid "Path to data device (if separated)"
+msgstr "Percorso al dispositivo dati (se scollegato)"
+
+#: src/integritysetup.c:530
+msgid "Journal size"
+msgstr "Dimensione journal"
+
+#: src/integritysetup.c:531
+msgid "Interleave sectors"
+msgstr "Settori di interfogliazione"
+
+#: src/integritysetup.c:532
+msgid "Journal watermark"
+msgstr "Watermark del journal"
+
+#: src/integritysetup.c:532
+msgid "percent"
+msgstr "percento"
+
+#: src/integritysetup.c:533
+msgid "Journal commit time"
+msgstr "Tempo scrittura del journal"
+
+#: src/integritysetup.c:533
+msgid "ms"
+msgstr "ms"
+
+#: src/integritysetup.c:534
+msgid "Tag size (per-sector)"
+msgstr "Dimensione tag (per settore)"
+
+#: src/integritysetup.c:535
+msgid "Sector size"
+msgstr "Dimensione settore"
+
+#: src/integritysetup.c:536
+msgid "Buffers size"
+msgstr "Dimensione buffer"
+
+#: src/integritysetup.c:538
+msgid "Data integrity algorithm"
+msgstr "Algoritmo integrità dati"
+
+#: src/integritysetup.c:539
+msgid "The size of the data integrity key"
+msgstr "La dimensione della chiave di integrità dei dati"
+
+#: src/integritysetup.c:540
+msgid "Read the integrity key from a file"
+msgstr "Legge la chiave di integrità da un file"
+
+#: src/integritysetup.c:542
+msgid "Journal integrity algorithm"
+msgstr "Algoritmo integrità journal"
+
+#: src/integritysetup.c:543
+msgid "The size of the journal integrity key"
+msgstr "La dimensione della chiave di integrità del journal"
+
+#: src/integritysetup.c:544
+msgid "Read the journal integrity key from a file"
+msgstr "Legge la chiave di integrità del journal da un file"
+
+#: src/integritysetup.c:546
+msgid "Journal encryption algorithm"
+msgstr "Algoritmo cifratura journal"
+
+#: src/integritysetup.c:547
+msgid "The size of the journal encryption key"
+msgstr "La dimensione della chiave di cifratura del journal"
+
+#: src/integritysetup.c:548
+msgid "Read the journal encryption key from a file"
+msgstr "Legge la chiave di cifratura del journal da un file"
+
+#: src/integritysetup.c:551
+msgid "Recovery mode (no journal, no tag checking)"
+msgstr "Modalità ripristino (jorunal e verifica tag disattivai)"
+
+#: src/integritysetup.c:552
+msgid "Recalculate initial tags automatically."
+msgstr "Ricalcola i tag iniziali automaticamente"
+
+#: src/integritysetup.c:631
+msgid "Option --integrity-recalculate can be used only for open action."
+msgstr "L'opzione --integrity-recalculate può essere usata solo con l'azione open."
+
+#: src/integritysetup.c:646
+msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action.\n"
+msgstr "Le opzioni --journal-size, --interleave-sectors, --sector-size, --tag-size e --no-wipe possono essere usate solamente per azioni di formattazione.\n"
+
+#: src/integritysetup.c:652
+msgid "Invalid journal size specification."
+msgstr "Specifica di dimensione del journal non valida."
+
+#: src/integritysetup.c:657
+msgid "Both key file and key size options must be specified."
+msgstr "Devono essere specificate entrambe le opzioni file della chiave e dimensione delle chiave."
+
+#: src/integritysetup.c:660
+msgid "Integrity algorithm must be specified if integrity key is used."
+msgstr "L'algoritmo di integrità deve essere specificato se viene usata la chiave di integrità."
+
+#: src/integritysetup.c:665
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Devono essere specificate entrambe le opzioni file della chiave e dimensione della chiave di integrità del journal."
+
+#: src/integritysetup.c:668
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "L'algoritmo di integrità del journal deve essere specificato se viene usata la chiave di integrità del journal."
+
+#: src/integritysetup.c:673
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Devono essere specificate entrambe le opzioni file della chiave e dimensione della chiave di cifratura del journal."
+
+#: src/integritysetup.c:676
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "L'algoritmo di cifratura del journal deve essere specificato se viene usata la chiave di cifratura del journal."
+
+#: src/cryptsetup_reencrypt.c:175
+msgid "Reencryption already in-progress."
+msgstr "Re-cifratura in corso."
+
+#: src/cryptsetup_reencrypt.c:181
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "La re-cifratura del dispositivo con un profilo di integrità non è supportata."
+
+#: src/cryptsetup_reencrypt.c:204
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Impossibile aprire esclusivamente il dispositivo %s, già in uso."
+
+#: src/cryptsetup_reencrypt.c:218 src/cryptsetup_reencrypt.c:1148
+msgid "Allocation of aligned memory failed."
+msgstr "Allocazione di memoria allineata non riuscita."
+
+#: src/cryptsetup_reencrypt.c:225
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Impossibile leggere il dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:236
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Impostazione dispositivo LUKS %s come inutilizzabile."
+
+#: src/cryptsetup_reencrypt.c:240
+#, c-format
+msgid "Setting LUKS2 offline reencrypt flag on device %s."
+msgstr "Impostazione flag re-cifratura offline LUKS2 sul dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:257
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Impossibile scrivere il dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:345
+msgid "Cannot write reencryption log file."
+msgstr "Impossibile scrivere il file di registro di re-cifratura."
+
+#: src/cryptsetup_reencrypt.c:401
+msgid "Cannot read reencryption log file."
+msgstr "Impossibile leggere il file di registro di re-cifratura."
+
+#: src/cryptsetup_reencrypt.c:439
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Il file di registro %s esiste, viene ripristinata la re-cifratura.\n"
+
+#: src/cryptsetup_reencrypt.c:488
+msgid "Activating temporary device using old LUKS header."
+msgstr "Attivazione dispositivo temporaneo usando il vecchio header LUKS."
+
+#: src/cryptsetup_reencrypt.c:498
+msgid "Activating temporary device using new LUKS header."
+msgstr "Attivazione dispositivo temporaneo usando il nuovo header LUKS."
+
+#: src/cryptsetup_reencrypt.c:508
+msgid "Activation of temporary devices failed."
+msgstr "Attivazione del dispositivo temporaneo non riuscita."
+
+#: src/cryptsetup_reencrypt.c:586
+msgid "Failed to set PBKDF parameters."
+msgstr "Impostazione parametri PBKDF non riuscita."
+
+#: src/cryptsetup_reencrypt.c:592
+msgid "Failed to set data offset."
+msgstr "Impostazione offset dei dati non riuscita."
+
+#: src/cryptsetup_reencrypt.c:600
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Creato nuovo header LUKS per il dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:660
+#, c-format
+msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+msgstr "Questa versione di cryptsetup-reencrypt non può gestire token interni di tipo %s."
+
+#: src/cryptsetup_reencrypt.c:682
+msgid "Failed to read activation flags from backup header."
+msgstr "Lettura dei flag di attivazione dall'header di backup non riuscita."
+
+#: src/cryptsetup_reencrypt.c:686
+msgid "Failed to write activation flags to new header."
+msgstr "Scrittura dei flag di attivazione sul nuovo header non riuscita."
+
+#: src/cryptsetup_reencrypt.c:690 src/cryptsetup_reencrypt.c:694
+msgid "Failed to read requirements from backup header."
+msgstr "Lettura dei requisiti dall'header di backup non riuscita."
+
+#: src/cryptsetup_reencrypt.c:731
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Header %s di backup del dispositivo %s creato."
+
+#: src/cryptsetup_reencrypt.c:789
+msgid "Creation of LUKS backup headers failed."
+msgstr "Creazione degli header di backup LUKS non riuscita."
+
+#: src/cryptsetup_reencrypt.c:918
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Impossibile ripristinare l'header %s sul dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:920
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Ripristinato l'header %s sul dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:958 src/cryptsetup_reencrypt.c:1038
+msgid "Cannot seek to device offset."
+msgstr "Impossibile posizionarsi all'offset del dispositivo."
+
+#: src/cryptsetup_reencrypt.c:1081
+msgid "Cannot seek to device offset.\n"
+msgstr "Impossibile posizionarsi all'offset del dispositivo.\n"
+
+#: src/cryptsetup_reencrypt.c:1120 src/cryptsetup_reencrypt.c:1126
+msgid "Cannot open temporary LUKS device."
+msgstr "Impossibile aprire il dispositivo temporaneo LUKS."
+
+#: src/cryptsetup_reencrypt.c:1131 src/cryptsetup_reencrypt.c:1136
+msgid "Cannot get device size."
+msgstr "Impossibile ottenere la dimensione del dispositivo."
+
+#: src/cryptsetup_reencrypt.c:1173
+msgid "Interrupted by a signal."
+msgstr "Interrotto da un segnale."
+
+#: src/cryptsetup_reencrypt.c:1175
+msgid "IO error during reencryption."
+msgstr "Errore di IO durante la re-cifratura."
+
+#: src/cryptsetup_reencrypt.c:1206
+msgid "Provided UUID is invalid."
+msgstr "Lo UUID fornito non è valido."
+
+#: src/cryptsetup_reencrypt.c:1309
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Il file chiave può essere usato solamente con --key-slot o con esattamente uno slot di chiave attivo."
+
+#: src/cryptsetup_reencrypt.c:1350 src/cryptsetup_reencrypt.c:1361
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Inserire la passphrase per lo slot di chiave %u: "
+
+#: src/cryptsetup_reencrypt.c:1432
+msgid "Cannot open reencryption log file."
+msgstr "Impossibile aprire il file di registro di re-cifratura."
+
+#: src/cryptsetup_reencrypt.c:1438
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Nessuna decifrazione in corso: lo UUID fornito può essere usato solamente per riprendere un processo di decifrazione."
+
+#: src/cryptsetup_reencrypt.c:1513
+#, c-format
+msgid "Changed pbkdf parameters in keyslot %i."
+msgstr "Parametri pbkdf modificati nello slot di chiave %i."
+
+#: src/cryptsetup_reencrypt.c:1620
+msgid "Reencryption block size"
+msgstr "Dimensione blocco re-cifratura"
+
+#: src/cryptsetup_reencrypt.c:1620
+msgid "MiB"
+msgstr "MiB"
+
+#: src/cryptsetup_reencrypt.c:1624
+msgid "Do not change key, no data area reencryption"
+msgstr "Non cambia chiave, nessuna re-cifratura dei dati"
+
+#: src/cryptsetup_reencrypt.c:1626
+msgid "Read new volume (master) key from file"
+msgstr "Legge la chiave (master) del volume da file"
+
+#: src/cryptsetup_reencrypt.c:1627
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "Tempo di iterazione di PBKDF2 per LUKS (in ms)"
+
+#: src/cryptsetup_reencrypt.c:1633
+msgid "Use direct-io when accessing devices"
+msgstr "Usa IO diretto negli accessi ai dispositivi"
+
+#: src/cryptsetup_reencrypt.c:1634
+msgid "Use fsync after each block"
+msgstr "Usa fsync dopo ogni blocco"
+
+#: src/cryptsetup_reencrypt.c:1635
+msgid "Update log file after every block"
+msgstr "Aggiorna il registro a ogni blocco"
+
+#: src/cryptsetup_reencrypt.c:1636
+msgid "Use only this slot (others will be disabled)"
+msgstr "Usa solo questo slot (gli altri vengono disabilitati)"
+
+#: src/cryptsetup_reencrypt.c:1639
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "Riduce la dimensione dei dati del dispositivo (muove l'offset dei dati) PERICOLOSO"
+
+#: src/cryptsetup_reencrypt.c:1640
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "Usa solo la dimensione specificata del dispositivo (ignora il resto del dispositivo) PERICOLOSO"
+
+#: src/cryptsetup_reencrypt.c:1641
+msgid "Create new header on not encrypted device"
+msgstr "Crea un nuovo header su un dispositivo non cifrato"
+
+#: src/cryptsetup_reencrypt.c:1642
+msgid "Permanently decrypt device (remove encryption)"
+msgstr "Decifra definitivamente il dispositivo (rimuove la cifratura)"
+
+#: src/cryptsetup_reencrypt.c:1643
+msgid "The UUID used to resume decryption"
+msgstr "Lo UUID utilizzato per riprendere la decifrazione"
+
+#: src/cryptsetup_reencrypt.c:1644
+msgid "Type of LUKS metadata: luks1, luks2"
+msgstr "Metadati di tipo LUKS: luks1, luks2"
+
+#: src/cryptsetup_reencrypt.c:1663
+msgid "[OPTION...] <device>"
+msgstr "[OPZIONI...] <dispositivo>"
+
+#: src/cryptsetup_reencrypt.c:1677
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "La re-cifratura modificherà: %s%s%s%s%s%s."
+
+#: src/cryptsetup_reencrypt.c:1678
+msgid "volume key"
+msgstr "chiave volume"
+
+#: src/cryptsetup_reencrypt.c:1680
+msgid "set hash to "
+msgstr "imposta l'hash a "
+
+#: src/cryptsetup_reencrypt.c:1681
+msgid ", set cipher to "
+msgstr ", imposta il cifrario a "
+
+#: src/cryptsetup_reencrypt.c:1685
+msgid "Argument required."
+msgstr "Argomento richiesto."
+
+#: src/cryptsetup_reencrypt.c:1713
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Solo valori tra 1 MiB e 64 MiB sono consentiti per la dimensione del blocco di re-cifratura."
+
+#: src/cryptsetup_reencrypt.c:1732 src/cryptsetup_reencrypt.c:1737
+msgid "Invalid device size specification."
+msgstr "Specifica di dimensione del dispositivo non valida."
+
+#: src/cryptsetup_reencrypt.c:1740
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "La dimensione massima di riduzione del dispositivo è 64 MiB."
+
+#: src/cryptsetup_reencrypt.c:1743
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "La dimensione di riduzione deve essere un multiplo di 512 byte."
+
+#: src/cryptsetup_reencrypt.c:1747
+msgid "Option --new must be used together with --reduce-device-size or --header."
+msgstr "L'opzione --new deve essere usata con --reduce-device-size o --header."
+
+#: src/cryptsetup_reencrypt.c:1751
+msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+msgstr "L'opzione --keep-key può essere usata solo con --hash, --iter-time --pbkdf-force-iterations."
+
+#: src/cryptsetup_reencrypt.c:1755
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "L'opzione --new non può essere usata con --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1759
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "L'opzione --decrypt non è compatibile con i parametri specificati."
+
+#: src/cryptsetup_reencrypt.c:1763
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "L'opzione --uuid può essere usata solo con --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1767
+msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+msgstr "Tipo luks non valido. Usare uno tra: \"luks\", \"luks1\" o \"luks2\"."
+
+#: src/utils_tools.c:150
+msgid "Error reading response from terminal."
+msgstr "Errore nel leggere la risposta dal terminale."
+
+#: src/utils_tools.c:175
+msgid "Command successful.\n"
+msgstr "Comando eseguito con successo.\n"
+
+#: src/utils_tools.c:183
+msgid "wrong or missing parameters"
+msgstr "parametri errati o mancanti"
+
+#: src/utils_tools.c:185
+msgid "no permission or bad passphrase"
+msgstr "permessi mancanti o passphrase errata"
+
+#: src/utils_tools.c:187
+msgid "out of memory"
+msgstr "memoria esaurita"
+
+#: src/utils_tools.c:189
+msgid "wrong device or file specified"
+msgstr "dispositivo o file specificato errato"
+
+#: src/utils_tools.c:191
+msgid "device already exists or device is busy"
+msgstr "il dispositivo esiste già o è occupato"
+
+#: src/utils_tools.c:193
+msgid "unknown error"
+msgstr "errore sconosciuto"
+
+#: src/utils_tools.c:195
+#, c-format
+msgid "Command failed with code %i (%s).\n"
+msgstr "Comando non riuscito con codice %i (%s).\n"
+
+#: src/utils_tools.c:272
+#, c-format
+msgid "Key slot %i created."
+msgstr "Slot di chiave %i creato."
+
+#: src/utils_tools.c:274
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Slot di chiave %i sbloccato."
+
+#: src/utils_tools.c:276
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Slot di chiave %i rimosso."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token %i created."
+msgstr "Token %i creato."
+
+#: src/utils_tools.c:287
+#, c-format
+msgid "Token %i removed."
+msgstr "Token %i rimosso."
+
+#: src/utils_tools.c:453
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "Attenzione: il dispositivo %s contiene già una firma di partizione «%s».\n"
+
+#: src/utils_tools.c:461
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "Attenzione: il dispositivo %s contiene già una firma di super-blocco «%s».\n"
+
+#: src/utils_tools.c:482 src/utils_tools.c:546
+msgid "Failed to initialize device signature probes."
+msgstr "Inizializzazione sonde per la firma del dispositivo non riuscita."
+
+#: src/utils_tools.c:526
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Stat del dispositivo %s non riuscita."
+
+#: src/utils_tools.c:539
+#, c-format
+msgid "Device %s is in use. Can not proceed with format operation."
+msgstr "Il dispositivo %s è in uso. Impossibile procedere con l'operazione di formattazione."
+
+#: src/utils_tools.c:541
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Apertura del file %s in lettura/scrittura non riuscita."
+
+#: src/utils_tools.c:561
+msgid "Failed to wipe device signature."
+msgstr "Pulizia della firma del dispositivo non riuscita."
+
+#: src/utils_tools.c:568
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Esame del dispositivo %s per una firma non riuscito."
+
+#: src/utils_password.c:43 src/utils_password.c:75
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Impossibile controllare la qualità della password: %s"
+
+#: src/utils_password.c:51
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Controllo qualità della password non riuscito:\n"
+" %s"
+
+#: src/utils_password.c:83
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Controllo qualità della password non riuscito: passphrase non valida (%s)"
+
+#: src/utils_password.c:193 src/utils_password.c:208
+msgid "Error reading passphrase from terminal."
+msgstr "Errore nel leggere la passphrase dal terminale."
+
+#: src/utils_password.c:206
+msgid "Verify passphrase: "
+msgstr "Verifica passphrase: "
+
+#: src/utils_password.c:213
+msgid "Passphrases do not match."
+msgstr "Le passphrase non corrispondono."
+
+#: src/utils_password.c:250
+msgid "Cannot use offset with terminal input."
+msgstr "Impossibile usare l'offset con l'input da terminale."
+
+#: src/utils_password.c:253
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Inserire la passphrase: "
+
+#: src/utils_password.c:255
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Inserire la passphrase per %s: "
+
+#: src/utils_password.c:285
+msgid "No key available with this passphrase."
+msgstr "Nessuna chiave disponibile con questa passphrase."
+
+#: src/utils_password.c:320
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Impossibile aprire il file chiave %s per la scrittura."
+
+#: src/utils_password.c:327
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Impossibile scrivere sul file chiave %s."
+
+#: src/utils_luks2.c:47
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Apertura del file %s in sola lettura non riuscita."
+
+#: src/utils_luks2.c:60
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Fornire token JSON LUKS2 valido:\n"
+
+#: src/utils_luks2.c:67
+msgid "Failed to read JSON file."
+msgstr "Lettura file JSON non riuscita."
+
+#: src/utils_luks2.c:72
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Lettura interrotta."
+
+#: src/utils_luks2.c:113
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Apertura del file %s in lettura non riuscita."
+
+#: src/utils_luks2.c:122
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Scrittura interrotta."
+
+#: src/utils_luks2.c:126
+msgid "Failed to write JSON file."
+msgstr "Scrittura file JSON non riuscita."
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Il dispositivo %s è troppo piccolo (LUKS2 richiede almeno %<PRIu64> byte)."
+
+#~ msgid "Replaced with key slot %d.\n"
+#~ msgstr "Sostituito con lo slot di chiave %d.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Troppi livelli d'albero per il volume verity.\n"
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "errore di allocazione di memoria in action_luksFormat"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "Chiave %d non attiva. Impossibile ripulirla.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<nome> <dispositivo_dati> <dispositivo_hash> <hash_root>"
+
+#~ msgid "create active device"
+#~ msgstr "Crea dispositivo attivo"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "Rimuove (disattiva) dispositivo"
+
+#~ msgid "Activated keyslot %i.\n"
+#~ msgstr "Slot di chiave %i attivato.\n"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Avanzamento: %5.1f%%, ETA %02llu:%02llu, %4llu MiB scritti, velocità %5.1f MiB/s%s"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Impossibile trovare un dispositivo di loopback libero.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Impossibile aprire il dispositivo %s\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Impossibile utilizzare lo UUID fornito se non è in corso una decifratura.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "Impostazione device LUKS %s come utilizzabile.\n"
diff --git a/po/ja.po b/po/ja.po
new file mode 100644
index 0000000..db3799e
--- /dev/null
+++ b/po/ja.po
@@ -0,0 +1,3850 @@
+# Japanese messages for cryptsetup.
+# Copyright (C) 2019, 2020 Free Software Foundation, Inc.
+# This file is put in the public domain, to the extent permitted under applicable law.
+# Hiroshi Takekawa <sian@big.or.jp>, <sian.ht@gmail.com>, 2019, 2020, 2021, 2022, 2023
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-02 20:52+0900\n"
+"Last-Translator: Hiroshi Takekawa <sian@big.or.jp>\n"
+"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "device-mapper を初期化できません、non-root で実行します。"
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "device-mapper を初期化できません。dm_mod モジュールはロードされてますか?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "指定された延期フラグはサポートされていません。"
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "デバイス %s の DM-UUID は短縮されています。"
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "不明な dm target タイプです。"
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "指定された dm-crypt パフォーマンスオプションはサポートされていません。"
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "指定された dm-verity のデータ破壊時の対応についてのオプションはサポートされていません。"
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "指定された dm-verity のタスクレットオプションはサポートされていません。"
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "指定された dm-verity の誤り訂正(FEC)オプションはサポートされていません。"
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "指定されたデータの無改ざん確認のオプションはサポートされていません。"
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "指定された sector_size オプションはサポートされていません。"
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "指定された改ざん確認タグの自動再計算はサポートされていません。"
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM はサポートしていません。"
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "要求された dm-integrity のビットマップモードはサポートされていません。"
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "dm-%s のクエリーに失敗しました。"
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"ボリュームキーを生成するためのエントロピー(この文脈では乱数の乱れ度合)が足りません。\n"
+"マウスを動かしたり、他のウィンドウで文字を入力したりしてみてください。\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "キー生成中 (%d%% 完了)。\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "FIPS モードで実行中。"
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "RNG(乱数生成器)初期化中に重大なエラーが発生しました。"
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "不明な RNG(乱数生成器) の質(quality)が要求されました。"
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "RNG(乱数生成器)から読み込み中にエラー。"
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "暗号向けRNG(乱数生成器)バックエンドの初期化ができません。"
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "暗号バックエンドの初期化ができません。"
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "ハッシュアルゴリズム %s がサポートされていません。"
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "鍵の処理でエラー (ハッシュ %s を使用)。"
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "デバイスタイプがわかりません。互換性のないデバイスのアクティベーションをしようとしていませんか?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "この操作は LUKS デバイスでしかサポートされていません。"
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "この操作は LUKS2 デバイスでしかサポートされていません。"
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "キースロットがいっぱいです。"
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "キースロット %d は不正です。0 から %d の間を選んでください。"
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "キースロット %d は使われています。別の番号を選んでください。"
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "デバイスサイズが論理ブロックサイズのアライメントに合いません。"
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "ヘッダが検出されましたがデバイス %s が小さすぎます。"
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "この操作はこのデバイスタイプではサポートされていません。"
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "オフラインでの再暗号化中です。中止します。"
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "メモリ上の LUKS2 メタデータのロールバックに失敗しました。"
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "デバイス %s は有効な LUKS デバイスではありません。"
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "LUKS バージョン %d はサポートされていません。"
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "デバイス %s はアクティブではありません。"
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "暗号化されたデバイス %s の元になるデバイスが消滅しました。"
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "不正な plain crypt のパラメータ。"
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "不正なキーサイズ。"
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID はこの暗号タイプではサポートされていません。"
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "分離したメタデータデバイスはこの暗号タイプではサポートされていません。"
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "サポートされていない暗号化セクタサイズです。"
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "デバイスサイズが要求されたセクタサイズのアライメントに合いません。"
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "デバイスなしには LUKS 形式にフォーマットできません。"
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "要求されたデータアライメントとデータオフセットが合いません。"
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "デバイス %s のヘッダを消し去れません。"
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "デバイス %s はアクティベートするのに小さすぎます。データ用のスペースがありません。\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "警告: デバイスアクティベーションが失敗しました。dm-crypt が要求された暗号セクタサイズをサポートしていません。\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "ボリュームキーは改ざん耐性拡張のため暗号には鍵長が小さすぎます。"
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "暗号 %s-%s (キーサイズ %zd ビット) は利用できません。"
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "警告: LUKS2 メタデータサイズが %<PRIu64> バイトに変更されました。\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "警告: LUKS2 キースロット領域サイズが %<PRIu64> バイトに変更されました。\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "デバイス %s のサイズが小さすぎます。"
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "デバイス %s は使用中のためフォーマットできません。"
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "デバイス %s は権限がないためフォーマットできません。"
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "デバイス %s を改ざん耐性がつくようフォーマットできません。"
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "デバイス %s をフォーマットできません。"
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "LOOPAES としてフォーマットするにはデバイスが必要です。"
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "VERITY としてフォーマットするにはデバイスが必要です。"
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "VERITY ハッシュタイプ %d はサポートしていません。"
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "サポートしていない VERITY ブロックサイズです。"
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "サポートしていない VERITY ハッシュオフセットです。"
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "サポートしていない VERITY FEC オフセットです。"
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "データ領域がハッシュ領域と重なっています。"
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "ハッシュ領域が FEC 領域と重なっています。"
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "データ領域が FEC 領域と重なっています。"
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "警告: 指定されたタグのサイズ %d バイトが %s の出力サイズと異なります (%d バイト)。\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "不明な暗号デバイスタイプ %s が指定されました。"
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "デバイス %s のパラメータはサポートしていません。"
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "デバイス %s のパラメータがミスマッチしています。"
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Crypt デバイスが一致しません。"
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "デバイス %s のリロードに失敗しました。"
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "デバイス %s のサスペンドに失敗しました。"
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "デバイス %s のリジュームに失敗しました。"
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "デバイス %s のリロード中に致命的なエラー(デバイス %s の上で)。"
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "デバイス %s を dm-error にスイッチできません。"
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "ループデバイスはリサイズできません。"
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "警告: 最大サイズが既に設定済かカーネルがリサイズをサポートしていません。\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "リサイズに失敗しました。カーネルがサポートしていません。"
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "デバイスの UUID を本当に変更してもいいですか?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "ヘッダのバックアップファイルの中味が LUKS ヘッダと互換性がありません。"
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "ボリューム %s はアクティブではありません。"
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "ボリューム %s は既に停止されています。"
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "デバイス %s の停止はサポートされていません。"
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "デバイス %s 停止中にエラー。"
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "デバイス %s は再開をサポートしていません。"
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "デバイス %s の再開中にエラー。"
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "ボリューム %s は停止されていません。"
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "ボリュームキーがボリュームに合いません。"
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "新しいキースロットを交換できませんでした。"
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "キースロット %d は不正です。"
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "キースロット %d は非アクティブです。"
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "デバイスヘッダがデータ領域に重なっています。"
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "既に再暗号化中です。デバイスをアクティベートできません。"
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "再暗号化ロックを取得できません。"
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "LUKS2 の再暗号化は既に初期化されました。"
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "デバイスタイプが正しく初期化されていません。"
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "デバイス %s は既に存在します。"
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "デバイス %s を使えません。名前が不正か使用中です。"
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "正しくないボリュームキーがプレーンデバイスに指定されました。"
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "正しくないルートハッシュが verity デバイスに指定されました。"
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "ルートハッシュ署名が必要です。"
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "署名をカーネルに渡すのに必要なカーネルキーリングをカーネルがサポートしていません。"
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "キーをカーネルキーリングにロードできません。"
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "デバイス %s からの遅延削除をキャンセルできませんでした。"
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "デバイス %s は使用中です。"
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "デバイス %s は不正です。"
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "ボリュームキーのバッファが小さすぎます。"
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "LUKS2 デバイス向けのボリュームキーが取得できません。"
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "LUKS1 デバイス向けのボリュームキーが取得できません。"
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "プレーンデバイス向けのボリュームキーが取得できません。"
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "verity デバイスのルートハッシュが読み出せません。"
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "BITLK デバイス向けのボリュームキーが取得できません。"
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "FVAULT2 デバイス向けのボリュームキーが取得できません。"
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "この操作は %s 暗号化デバイスではサポートされていません。"
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "このデバイスタイプはダンプ操作をサポートしていません。"
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "データオフセットが %u バイトの倍数である必要があります。"
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "使用中のデバイス %s を変換できません。"
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "新しいボリュームキー向けのキースロット %u を確保できません。"
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "デフォルト LUKS2 キースロットパラメータを初期化できません。"
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "ダイジェストするためのキースロット %d が確保できません。"
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "キースロットを追加できません。全てのスロットが無効でボリュームキーが渡されませんでした。"
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "カーネルがカーネルキーリングをサポートしていません。"
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "キーリングからパスフレーズが読み出せません (エラー %d)。"
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "グローバル memory-hard アクセス直列化ロックが取れません。"
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "キーファイルがオープンできません。"
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "ターミナルからキーファイルを読みこめません。"
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "キーファイルを stat() できません。"
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "指定されたキーファイルオフセットにシークできません。"
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "パスフレーズ読み込み中にメモリが不足しました。"
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "パスフレーズの読み込みでエラー。"
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "読もうとしたら入力が空です。"
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "キーファイルが最大サイズを超えています。"
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "指定されたサイズのデータを読み込めません。"
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "デバイス %s は存在しないかアクセスが拒否されました。"
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "デバイス %s は互換性がありません。"
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "データデバイスのおかしな(bogus) optimal-io サイズ (%u バイト) は無視します。"
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "デバイス %s が小さすぎます。少なくとも %<PRIu64> バイト必要です。"
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "デバイス %s は使用中で使えません (既にマップされているかマウントされています)。"
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "デバイス %s が使えません、拒否されました。"
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "デバイス %s についての情報が取得できません。"
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "ループバックデバイスが使えません、非 root ユーザで実行していませんか。"
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "ループデバイスのアタッチできません (autoclear 付きのループデバイスが必要です)。"
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "指定されたオフセットはデバイス %s の実際のサイズを超えています。"
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "デバイス %s のサイズが 0 です。"
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "要求された PBKDF の目標時間は 0 ではいけません。"
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "%s は不明な PBKDF タイプです。"
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "要求されたハッシュ %s はサポートしていません。"
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "要求された PBKDF タイプは LUKS1 ではサポートされていません。"
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "PBKDF の max memory や parallel threads は pbkdf2 の時は設定できません。"
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "%s について強制される最小繰り返し回数が小さすぎます (最小 %u)。"
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "%s について強制されるメモリコストが小さすぎます (最小 %u KB)。"
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "指定された PBKDF メモリコストが大きすぎます (最大 %d KB)。"
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "PBKDF メモリは 0 ではいけません。"
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "要求された PBKDF 並列スレッド数は 0 ではいけません。"
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "FIPS モードでは PBKDF2 しかサポートしていません。"
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "PBKDF ベンチマークが無効ですが繰り返し回数が設定されていません。"
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "PBKDF2 と互換性のないオプションです (ハッシュアルゴリズム %s)。"
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "互換性のない PBKDF オプションです。"
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "ロックを中止します。ロックに使うパス %s/%s が使用できません (ディレクトリでないか存在していません)。"
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "ロックを中止します。ロックに使うパス %s/%s が使用できません (%s はディレクトリではありません)。"
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "デバイスオフセットまで seek できません。"
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "デバイスのワイプでエラー, オフセット %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"デバイス %s の dm-crypt のキーマッピングの設定に失敗しました。\n"
+"カーネルが暗号 %s をサポートしているか確認してください (syslog にさらに情報があります)。"
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "XTS モードのキーサイズは 256 か 512 ビットでなければなりません。"
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "暗号の指定は [暗号]-[モード]-[初期ベクタ] という形式であるべきです。"
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "デバイス %s に書き込めません。パーミッションがありません。"
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "一時的なキーストアデバイスを開けません。"
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "一時的なキーストアデバイスにアクセスできません。"
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "キースロットを暗号化中にI/Oエラーが発生しました。"
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "デバイス %s を開けません。"
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "キースロットを復号化中にI/Oエラーが発生しました。"
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "デバイス %s が小さすぎます。(LUKS1 は最低でも %<PRIu64> バイト必要です。)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "LUKS キースロット %u は不正です。"
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "要求されたヘッダバックアップファイル %s は既に存在しています。"
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "ヘッダバックアップファイル %s が作成できません。"
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "ヘッダバックアップファイル %s に書き込めません。"
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "バックアップファイルが有効な LUKS ヘッダを含んでいません。"
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "ヘッダバックアップファイル %s をオープンできません。"
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "ヘッダバックアップファイル %s を読めません。"
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "データオフセットかキーサイズがデバイスとバックアップで異なるのでリストアできません。"
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "デバイス %s %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "LUKS ヘッダが含まれていません。ヘッダを置き換えるとデバイスのデータを破壊する恐れがあります。"
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "LUKS ヘッダを既に含んでいます。ヘッダを置き換えると既にあるキースロットを破壊します。"
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"警告: 実デバイスのヘッダはバックアップとUUIDが異なります!"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "標準的でないキーサイズなので、手動の修復が必要です。"
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "標準的でないキースロットアライメントなので、手動の修復が必要です。"
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "暗号モードを修復しました (%s -> %s)。"
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "暗号ハッシュを小文字に修復しました (%s)。"
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "要求された LUKS ハッシュ %s はサポートしていません。"
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "キースロットを修復中です。"
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "キースロット %i: オフセットを修復 (%u -> %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "キースロット %i: のストライプを修復 (%u -> %u)."
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "キースロット %i: パーティションの印(signature)がおかしいです。"
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "キースロット %i: ソルトを消しました。"
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "LUKS ヘッダを書きこんでいます。"
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "修復に失敗しました。"
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "LUKS 暗号モード %s は不正です。"
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "LUKS ハッシュ %s は不正です。"
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "LUKS ヘッダに既知の不具合は検出されませんでした。"
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "デバイス %s の LUKS ヘッダを更新中にエラーが発生しました。"
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "デバイス %s の LUKS ヘッダを更新後の再読み込み中にエラーが発生しました。"
+
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "LUKS ヘッダのデータへのオフセットは 0 かヘッダサイズより大きくなければいけません。"
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "LUKS UUID の形式が間違っています。"
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "LUKS ヘッダを作成できません: ランダムなソルトを読み込めません。"
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "LUKS ヘッダを作成できません: ヘッダのハッシュが求められません (ハッシュには %s を使用)。"
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "キースロット %d が使用中なので、パージしてください。"
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "キースロット %d のストライプが少なすぎます。ヘッダを細工でもしましたか?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "PBKDF2 イテレーション回数がオーバーフローしました。"
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "キースロットをオープンできません (ハッシュ %s を使用)。"
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "キースロット %d は不正です。0 から %d の間を選んでください。"
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "デバイス %s をワイプできません。"
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "GPG の暗号化されたキーファイルがまだサポートされていません。"
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "以下のようにしてください。 gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "互換性のない loop-AES キーファイルが検出されました。"
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "カーネルが loop-AES 互換マッピングをサポートしていません。"
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "キーファイル %s を読み込み中にエラー。"
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "TCRYPT パスフレーズの最大長 (%zu) を超えました。"
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "PBKDF2 ハッシュアルゴリズム %s が利用できないのでスキップします。"
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "必要なカーネル crypto インターフェースが使用できません。"
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "algif_skcipher カーネルモジュールをロードしてください。"
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "アクティベーションは %d セクタサイズではサポートしていません。"
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "カーネルが TCRYPT レガシーモードのアクティベーションをサポートしていません。"
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "TCRYPT システム暗号をパーティション %s に対してアクティベーションしました。"
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "カーネルが TCRYPT 互換のマッピングをサポートしていません。"
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "この機能は TCRYPT ヘッダの読み込みなしではサポートしません。"
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "ボリュームマスターキーを解釈中に予期しないメタデータエントリタイプ '%u' が見つかりました。"
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "ボリュームマスターキーを解釈中に不正な文字列が見つかりました。"
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "ボリュームマスターキーを解釈中に予期しない文字列 ('%s') が見つかりました。"
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "ボリュームマスターキーを解釈中に予期しないメタデータエントリー値 '%u' が見つかりました。"
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK version 1 はサポートされていません。"
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "BITLK デバイスのブートシグネチャが不正また不明です。"
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "サポートされていないセクタサイズ %<PRIu16> です。"
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "%s から BITLK ヘッダを読み出すのに失敗しました。"
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "%s から BITLK FVE メタデータを読み込めませんでした。"
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "不明かサポートされていない暗号化タイプです。"
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "%s から BITLK メタデータエントリを読み込めませんでした。"
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "BITLKボリュームの description を変換できません。"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "外部キーを解釈中に予期しないメタデータエントリタイプ '%u' が見つかりました。"
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "BEK ファイル GUID '%s' がボリュームの GUID と一致しません。"
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "外部キーを解釈中に予期しないメタデータエントリー値 '%u' が見つかりました。"
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "サポートされていない BEK メタデータバージョン %<PRIu32> です。"
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "予期しない BEK メタデータサイズ %<PRIu32> は BEK ファイルサイズと合いません"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "スタートアップキーを解釈中に予期しないメタデータエントリが見つかりました。"
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "この操作はサポートされていません。"
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "予期しないキーデータサイズです。"
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "この BITLK デバイスはサポートされてない状態にあるためアクティベートできません。"
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "タイプ '%s' の BITLK デバイスはアクティベートできません。"
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "部分的に復号された BITLK デバイスのアクティベーションはサポートされていません。"
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "警告: BitLocker ボリュームサイズ %<PRIu64> がデバイスサイズ %<PRIu64> と一致しません"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "カーネルの dm-crypt が BITLK IV をサポートしていないためデバイスをアクティベートできません。"
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "カーネルの dm-crypt が BITLK Elephant diffuser をサポートしていないためデバイスをアクティベートできません。"
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "カーネルの dm-crypt がラージセクタサイズをサポートしていないためデバイスをアクティベートできません。"
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "カーネルの dm-zero モジュールがないためデバイスをアクティベートできません。"
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "ボリュームヘッダの %u バイトを読みこめませんでした。"
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "FVAULT2 のバージョン %<PRIu16> はサポートされていません。"
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Verity デバイス %s はディスク上のヘッダを使いません。"
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "VERITY バージョン %d はサポートされていません。"
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "VERITY ヘッダが壊れています。"
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "デバイス %s の VERITY UUID フォーマットが間違っています。"
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "デバイス %s の verity ヘッダを更新中にエラー。"
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "ルートハッシュ署名の検証はサポートしていません。"
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "FEC デバイスのエラーが修復できません。"
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "FEC デバイスに %u 個の修復可能なエラーが見つかりました。"
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "カーネルが dm-verity マッピングをサポートしていません。"
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "カーネルが dm-verity 署名オプションをサポートしていません。"
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "アクティベーションされた Verity デバイスが破損が見つかりました。"
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "ポジション %<PRIu64> にあるスペア領域が 0 埋めされていません。"
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "デバイスオフセットオーバーフロー。"
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "検証がポジション %<PRIu64> で失敗しました。"
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "ハッシュ領域がオーバーフロー。"
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "データ領域の検証に失敗しました。"
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "ルートハッシュの検証に失敗しました。"
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "ハッシュ領域を生成中に I/O エラー。"
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "ハッシュ領域の作成に失敗しました。"
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "警告: カーネルはデータブロックサイズがページサイズ (%u) を超えているとアクティベートできません。"
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Reed-Solomon 処理のためのコンテキストが確保できません。"
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "バッファを確保できませんでした。"
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Reed-Solomon ブロック %<PRIu64> バイト %d を読み込めませんでした。"
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Reed-Solomon ブロック %<PRIu64> のパリティを読み込めませんでした。"
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "ブロック %<PRIu64> のパリティが修復できませんでした。"
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Reed-Solomon ブロック %<PRIu64> のパリティの書き込みに失敗しました。"
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "ブロックサイズが FEC と合っていません。"
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "パリティのバイト数が不正です。"
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "FEC セグメント長が不正です。"
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "デバイス %s のサイズが不明です。"
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "互換性のないカーネルの dm-integrity のメタデータ (バージョン %u) が %s に検出されました。"
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "カーネルが dm-integrity マッピングをサポートしていません。"
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "カーネルが dm-integrity 固定メタデータアラインメントをサポートしていません。"
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "カーネルが安全でない再計算オプションを拒否しました (レガジーアクティベーションオプションでオーバーライドできます)。"
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "デバイス %s の書き込みのためのロックを取得できませんでした。"
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "LUKS2 メタデータの更新の並列実行をしそうになりました。実行を中止します。"
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"デバイスのシグネチャが曖昧なので、LUKS2 の自動修復ができません。.\n"
+"修復するには \"cryptsetup repair\" を実行してください。"
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "要求されたデータオフセットが小さすぎます。"
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "警告: キースロット領域 (%<PRIu64> バイト) がとても小さいため、利用可能な LUKS2 キースロット数が制限されます。\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "デバイス %s の読み込みのためのロックを取得できませんでした。"
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "禁止された LUKS2 要求がバックアップ %s に検出されました。"
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "データオフセットがデバイスとバックアップと異なるため修復できません。"
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "キースロット領域のあるバイナリヘッダのサイズがデバイスとバックアップで異なるため修復できません。"
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "デバイス %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "LUKS2 ヘッダが含まれていません。ヘッダを置き換えるとデータを破壊しかねません。"
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "既に LUKS2 ヘッダがあります。ヘッダを置き換えると既にあるキースロットを破壊します。"
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"警告: 不明な LUKS2 への要求がリアルデバイスヘッダにあります!\n"
+"ヘッダをバックアップで置き換えるとデータを破壊する恐れがあります!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"警告: オフラインの再暗号化が終了していません!\n"
+"ヘッダを置き換えるとデータを破壊しかねません。"
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "不明なフラグ %s を無視しました。"
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "dm-crypt セグメント %u にキーがありません"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "dm-crypt セグメントの設定に失敗しました。"
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "dm-linear セグメントの設定に失敗しました。"
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "サポートしていないデバイス整合性設定です。"
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "再暗号化が実行中なのでデバイスのデアクティベートできません。. Cannot deactivate device."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "サスペンドされたデバイス %s を dm-error ターゲットで置き換えられません。"
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "LUKS2 の必要条件を読み込めませんでした。"
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "満たせない LUKS2 の必要条件があります。"
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "操作がレガシー再暗号化とマークされたデバイスと互換性がありません。中止します。"
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "操作が LUKS2 再暗号化とマークされたデバイスと互換性がありません。中止します。"
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "キースロットをオープンするのにメモリが足りません。"
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "キースロットのオープンに失敗しました。"
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "キースロットの暗号化に %s- %s 暗号は使えません。"
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "ハッシュアルゴリズム %s が利用できません。"
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "新しいキースロット用の領域がありません。"
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "不正な再暗号化耐性モード変更を要求されました。"
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "耐性タイプを更新できません。新しいタイプは %<PRIu64> バイトしかありませんが、%<PRIu64> バイト必要です。"
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "再暗号化検証ダイジェストのリフレッシュに失敗しました。"
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "UUID が %s のデバイスの状態が確認できません。"
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "LUKSMETA メタデータ付きのヘッダは変換できません。"
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "暗号スペック %s-%s は LUKS2 に使えません。"
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "領域が足りないのでキースロット領域を動かせません。"
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "LUKS2 形式に変換できません - メタデータが不正です。"
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "LUKS2 キースロット領域が足りないのでキースロット領域を動かせません。"
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "キースロット領域を動かせません。"
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "LUKS1 形式に変換できません - デフォルトの暗号セクタサイズが 512 バイトではありません。"
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "LUKS1 形式に変換できません - キースロットのハッシュ関数が LUKS1 互換ではありません。"
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "LUKS1 形式に変換できません - ラップされたキーの暗号に %s が使われています。"
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "LUKS1 形式に変換できません - デバイスが多くのセグメントを使っています。"
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "LUKS1 形式に変換できません - LUKS2 ヘッダ %u 個のトークンを含んでいます。"
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "LUKS1 形式に変換できません - キースロット %u が不正な状態です。"
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "LUKS1 形式に変換できません - スロット %u が(最大個数を超過して)有効です。"
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "LUKS1 形式に変換できません - キースロット %u が LUKS1 と互換ではありません。"
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "ホットゾーンサイズは計算されたゾーンアライメントの倍数である必要がありす (%zu バイト)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "デバイスサイズが計算ゾーンアライメント (%zu バイト) に合っていません。"
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "古いセグメントのストレージラッパの初期化に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "新しいセグメントのストレージラッパの初期化に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "ホットゾーン保護の初期化に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "現在のホットゾーンのチェックサムを読み込めません。"
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "%<PRIu64> から始めるホットゾーンエリアを読み込めません。"
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "セクタ %zu を復号できません。"
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "セクタ %zu を復元できません。"
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "ソースとターゲットデバイスのサイズが一致しません。ソース %<PRIu64>, ターゲット: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "ホットゾーンデバイス %s がアクティベートできません。"
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "実際の origin table があるオーバーレイデバイス %s をアクティベートできません。"
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "デバイス %s の新しいマッピングをロードできません。"
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "再暗号化デバイススタックのリフレッシュに失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "新しいキースロットエリアサイズを設定できません。"
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "データシフト値が要求された暗号化セクタサイズにアラインされていません(%<PRIu32> バイト)。"
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "耐性(resilience)モード %s はサポートしていません"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "移動されるセグメントサイズはデータシフト値より大きくできません。"
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "不正な再暗号化耐性パラメータを要求されました。"
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "移動されるセグメントが大きすぎます。要求されているサイズは %<PRIu64> ですが、使えるサイズは %<PRIu64> です。"
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "テーブルをクリアできません。"
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "小さくしたデータサイズが実際のデバイスサイズより大きいです。"
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "データデバイスが暗号化セクタサイズにアラインされていません(%<PRIu32> バイト)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "データシフト (%<PRIu64> セクタ) が今後のデータオフセットより少ないです (%<PRIu64> セクタ)。"
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "デバイス %s を排他モードでオープンでません (既にマップされているかマウントされています)。"
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "デバイスは LUKS2 再暗号化向けにマークされていません。"
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "LUKS2 再暗号化コンテキストをロードできません。"
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "再暗号化状態を取得できません。"
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "デバイス %s は再暗号化中ではありません。"
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "既に再暗号化中です。"
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "再暗号化ロックを取得できません。"
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "再暗号化を開始できません。再暗号化のリカバリを先にしてください。"
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "実際のデバイスサイズと要求された再暗号化サイズが一致しません。"
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "再暗号化のパラメータとして不正なデバイスサイズが要求されました。"
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "既に再暗号化中です。復元を実行できません。"
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "メタデータの LUKS2 の再暗号化は既に初期化されました。"
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "メタデータの LUKS2 再暗号化に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "デバイスセグメントの次の再暗号化ホットゾーンの設定に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "再暗号化した耐性用メタデータを書き込めません。"
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "復号に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "%<PRIu64> から始まるホットゾーンエリアに書き込めません。"
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "データを sync できません。"
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "現在のホットゾーンの再暗号化完了後にメタデータが更新できません。"
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "LUKS2 メタデータが書き込めません。"
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "未使用データデバイス領域を消せません。"
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "未使用のキースロット %d を削除できませんでした。"
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "再暗号化キースロットが削除できません。"
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "%<PRIu64> から %<PRIu64> セクタのチャンクの再暗号化中に致命的なエラー。"
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "オンライン再暗号化に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "手動でエラーターゲットに置き換えた場合以外はデバイスのレジュームをしないでください。"
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "再暗号化を開始できません。予期しない再暗号化状態です。"
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "ないか不正な再暗号化コンテキストです。"
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "再暗号化デバイススタックの初期化に失敗しました。"
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "再暗号化コンテキストが更新できません。"
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "再暗号化メタデータが不正です。"
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "キースロットの暗号化パラメータは LUKS2 デバイスでしか設定できません。"
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "トークンPINを入力してください: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "トークン %d PINを入力してください: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "未知の暗号スペックです。"
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "警告: --hash パラメータは plain モードでキーファイルが指定されていると無視されます。\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "警告: --keyfile-size オプションは無視されて、読み込みサイズは暗号鍵のサイズと同じになります。\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "%s にデバイス署名が検出されました。既にあるデータを破壊しかねません。"
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "中止されました。\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "オプション --key-file が必要です。"
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "VeraCrypt PIM を入力してください: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "不正な PIM: 解釈できません。"
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "不正 PIM の値で 0 です。"
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "不正な PIM の値: 範囲外です。"
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "このパスフレーズではデバイスヘッダが検出されませんでした。"
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "デバイス %s は有効な BITLK デバイスではありません。"
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "BITLK のボリュームキーサイズが決定できないので、--key-size を使ってください。"
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"ボリュームキーを有効にしたヘッダダンプは\n"
+"暗号化されたパーティションにパスフレーズなしでアクセス可能にます。\n"
+"このダンプは暗号化された安全な所に保存してください。"
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"ボリュームキーを使ったヘッダダンプは取り扱いに注意すべき情報で\n"
+"暗号化されたパーティションにパスフレーズなしでアクセス可能になります。\n"
+"このダンプは暗号化された安全な所に保存してください。"
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "デバイス %s は有効な FVAULT2 デバイスではありません。"
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "FVAULT2 のボリュームキーサイズが決定できないので、--key-size を使ってください。"
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "デバイス %s はまたアクティブで後から削除される予定になっています。.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "アクティブなデバイスをリサイズするにはボリュームキーがキーリングに必要ですが、--disable-keyring が指定されています。"
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "ベンチマークが中止されました。"
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s 計測値なし\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u 回/秒 (%zu ビットの鍵)\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s 計測値なし\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u 回, %5u KB使用, %1u スレッド (%zu のビットの鍵) (%u ms 計測)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "ベンチマークの結果は信頼できません。"
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# テストはストレージI/Oがなくメモリ上のもののため目安です。\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algorithm | キー | 暗号化 | 復号化\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "暗号 %s (キーサイズ %i ビット) は利用できません。"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algorithm | キー | 暗号化 | 復号化\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "計測値なし"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"保護されていない LUKS2 再暗号化メタデータが検出されました。再暗号化操作が望ましいものか確認してください。(luksDump の出力を見てください)\n"
+"そのうえで、この操作が問題ないと確認できたら継続(メタデータのアップグレード)してください。"
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "再暗号化メタデータの保護とアップグレードのためのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "本当に LUKS2 再暗号化リカバリを行いますか?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "再暗号化メタデータダイジェストを検証するためのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "再暗号化のリカバリのためのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "本当に LUKS デバイスヘッダの復元を試みていいですか?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"ワイプが中断されました。"
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"整合性チェックサムの初期化のためにデバイスのデータを消去しています。\n"
+"CTRL+c で中止できます (初期化されなかったデバイスのチェックサムは正しくなくなります)。\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "一時的デバイス %s を非アクティブにできません。"
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "整合性オプションは LUKS2 形式でしか使えません。"
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "サポートされていない LUKS2 メタデータのサイズオプションです。"
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "ヘッダファイルがありません。作成しますか?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "ヘッダファイル %s を作成できません。"
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "サポートしている整合性確認方式が検出されませんでした。"
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "%s を on-disk ヘッダとして使えません。"
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "%s のデータを上書きします。戻せません。"
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "pbkdf パラメータを設定できません。"
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "分離された LUKS ヘッダでのみ少ないデータオフセットが使えます。"
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "LUKS ファイルコンテナ %s がアクティベートするには小さすぎます。データ用の領域に空きがありません。"
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "キースロットのない LUKS のボリュームキーサイズが決定できないので、--key-size を使ってください。"
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "デバイスはアクティベートされましたが、フラグを恒常的なものにできません。"
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "キースロット %d は削除対象として選択されました。"
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "これは最後のキースロットです。このキーがなくなるとデバイスは使用不能になります。"
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "残っているパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "操作は中止されました。キースロットは消去されていません。\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "削除するキーのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "デバイス %s は有効な LUKS2 デバイスではありません。"
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "キースロットの新しいパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "警告: --key-slot パラメータは新しいキースロット番号に使われます。\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "有効なパスフレーズをどれか入力してください: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "変更するキーのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "新しいキーのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "変換されるキースロットのパスフレーズを入力してください: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "isLuks は一つのデバイス引数しかサポートしていません。"
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "キースロット %d は unbound キーを含んでいません。"
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"unbound キーを使ったヘッダダンプは取り扱いに注意すべき情報です。\n"
+"このダンプは暗号化された安全な所に保存してください。"
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s はアクティブな %s デバイスではありません。"
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s はアクティブな LUKS デバイス名ではないか、ヘッダがありません。"
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "オプション --header-backup-file が必要です。"
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s は cryptsetup で管理されているデバイスではありません。"
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "リフレッシュはデバイスタイプ %s ではサポートされていません。"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "%s は認識できないメタデータデータタイプです。"
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "コマンドはデバイスとマップされた名前を引数として必要とします。"
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"この処理はデバイス %s の全てのキースロットを消去します。\n"
+"デバイスのデータは使用できなくなります。"
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "処理は中止されました。キースロットは消去されません。\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "不正な LUKS タイプです。luks1 と luks2 しかサポートしていません。"
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "デバイスは既にタイプ %s です。"
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "この処理は %s から %s フォーマットに変換します。\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "処理は中止されました。デバイスは変換されませんでした。\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "オプション --priority, --label か --subsystem がありません。"
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "トークン %d は不正です。"
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "トークン %d は使用中です。"
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "luks2-キーリングトークン %d を追加できませんでした。"
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "トークン %d をキースロット %d に割りあてられませんでした。"
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "トークン %d は使われていません。"
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "ファイルからトークンをインポートできません。"
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "トークン %d をエクスポートのために取得できませんでした。"
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "トークン %d をキースロット %d に割りあてられませんでした。"
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "トークン %d をキースロット %d の割り当てから解除できませんでした。"
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "--tcrypt-hidden と --tcrypt-system と --tcrypt-backup は TCRYPT デバイスしか使えません。"
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "--veracrypt や --disable-veracrypt は TCRYPT デバイスでしか使えません。"
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "--veracrypt-pim は VeraCrypt 互換デバイスにしか使えません。"
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "--veracrypt-query-pim は VeraCrypt 互換デバイスにしか使えません。"
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "--veracrypt-pim と --veracrypt-query-pim はどちらかしか使えません。"
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "--persistent は --test-passphrase と一緒には使えません。"
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "--refresh と --test-passphrase は同時には使えません。"
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "--shared は plain デバイスの open にしか使えません。"
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "--skip は plain か loopaes デバイスの open にしか使えません。"
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "--offset は plain か loopaes デバイスの open にしか使えません。"
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "--tcrypt-hidden は --allow-discards と一緒に使えません。"
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "オープン時のセクタサイズオプションは plain デバイスでしかサポートされていません。"
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "大きな IV セクタオプションは plain タイプでセクタサイズが 512 バイトより大きいものをオープンする時しかサポートしていません。"
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "--test-passphrase は LUKS か TCRYPT か BITLK か FVAULT2 デバイスの open にしか使えません。."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "--device-size と --size は一緒に使えません。"
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "オプション --unbound は luks デバイスの open にしか使えません。"
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "オプション --unbound は --test-passphrase がないと使えません。"
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "オプション --cancel-deferred と --deferred は同時に使えません。"
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "オプション --reduce-device-size と --data-size は一緒に使えません。"
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "オプション --active-nameは LUKS2 デバイスでしか設定できません。"
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "オプション --active-name と --force-offline-reencrypt は一緒に使えません。"
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "キースロットの指定が必要です。"
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "--align-payload と --offset は一緒に使えません。"
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "--integrity-no-wipe は format で integrity extension 付きの時しか使えません。"
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "--use-[u]random は一つしか使えません。"
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "--unbound にはキーサイズが必要です。"
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "不正なトークンアクションです。"
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "--key-description はトークン追加には必須です。"
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "トークンを必要としています。--token-id を使用してください。"
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "オプション --unbound はトークンの追加にしか使えません。"
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "--key-slot と --unbound は一緒に使えません。"
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "特定のキースロットを必要としています。--key-slot を使用してください。"
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<デバイス> [--type <タイプ>] [<名前>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "デバイスを <名前> としてオープン"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<名前>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "デバイスをクローズします (マッピングを削除します)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "アクティブデバイスをリサイズ"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "デバイスステータスを表示"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <暗号>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "暗号ベンチマーク"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<デバイス>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "on-disk メタデータを修復しようとしています"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "LUKS2 デバイスを再暗号化"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "全てのキースロットを消去します (暗号鍵も削除します)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "LUKS2 から LUKS もしくは LUKS から LUKS2 形式に変換します"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "LUKS2 の permanent configuration オプションを設定します"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<デバイス> [<新しいキーファイル>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "LUKS デバイスをフォーマットします"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "LUKS デバイスにキーを追加します"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<デバイス> [<キーファイル>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "与えられたキーかキーファイルを LUKS デバイスから削除します。"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "与えられた LUKS デバイスのキーかキーファイルを変更します"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "キーを新しい pbkdf パラメータに変換します"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<デバイス> <キースロット>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "<キースロット>のキーを LUKS デバイスから削除します"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "LUKS デバイスの UUID を表示"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "<デバイス> の LUKS パーティションヘッダをテストします"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "LUKS パーティション情報をダンプします"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "TCRYPT デバイス情報をダンプします"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "BITLK デバイス情報をダンプします"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "FVAULT2 デバイス情報をダンプします"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "LUKS デバイスを停止してキーを削除します (全てのI/Oは停止します)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "停止していた LUKS デバイスを再開します"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "LUKS デバイスヘッダとキースロットをバックアップします"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "LUKS デバイスヘッダとキースロットをリストアします"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <デバイス>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "LUKS2 トークンを操作します"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<action> は以下のうちの一つです:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"古い <アクション> という形式も使えます:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<名前> は %s に作られるデバイス名\n"
+"<デバイス> は暗号化デバイス\n"
+"<キースロット> は変更する LUKS キースロット番号\n"
+"<キーファイル> は luskAddKey でオプションで与えられる新しいキーのキーファイル\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"デフォルトのコンパイル時に決められたメタデータ形式は %s です(luksFormat で使われます)。\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"LUKS2 外部トークンプラグインサポート: %s\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "本体に内蔵"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "LUKS2 外部トークンプラグインパス: %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "利用不可"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"デフォルトのコンパイル時に決められたキーとパスフレーズのパラメータ:\n"
+"\t最大キーファイルサイズ: %dkB, 最大パスフレーズ長 %d (文字数)\n"
+"デフォルト LUKS1 向け PBKDF: %s, 繰り返す時間: %d (ms)\n"
+"デフォルト LUKS2 向け PBKDF: %s\n"
+"\t繰り返す時間: %d, 使うメモリ: %dkB, 並列スレッド: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"デフォルトのコンパイル時に決められたデバイス暗号化のパラメータ:\n"
+"\tloop-AES: %s, キー %d ビット\n"
+"\tplain: %s, キー: %d ビット, パスワードハッシュ: %s\n"
+"\tLUKS: %s, キー: %d ビット, LUKS ヘッダハッシュ: %s, 乱数生成: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: XTS モードのデフォルトキーサイズは (2つの内部キーがあるため) 倍になります。\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: は %s を引数で与える必要があります"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "キースロットは不正です。"
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "デバイスサイズは 512 バイトセクタの倍数である必要があります。"
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "再暗号化ホットゾーン最大サイズの指定が不正です。"
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "キーサイズは 8bit の倍数でなければなりません"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "デバイスを減らせる最大値は 1 GiB です。"
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "減らすサイズは 512 バイトセクタの倍数である必要があります。"
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "--priority の引数は ignore/normal/prefer のいずれかのみです。"
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "このヘルプを表示します"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "コンパクトな使用法表示をします"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "パッケージのバージョンを表示"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "ヘルプオプション:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[オプション...] <アクション> <アクション特有>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "<アクション> がありません。"
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "未知のアクションです。"
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "--key-file は他で指定されたキーファイルを上書きします。"
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "--key-file は一つしか使えません。"
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "パスワードからキーを作る関数 (PBKDF) は pbkdf2 argon2i argon2id のいずれかのみです。"
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "PBKDF の繰り返し回数の強制と繰り返し時間指定オプションは共存できません。"
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "--keyslot-cipher と --keyslot-key-size は同時に使う必要があります。"
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "--test-args オプションつきだったため、何もしません。\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "メタデータロックを禁止できません。"
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "不正なソルト文字列が指定されました。"
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "ハッシュイメージ %s を書けるように作成できませんでした。"
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "FEC イメージ %s を書けるように作成できませんでした。"
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "ルートハッシュファイル %s を書けるように作成できませんでした。"
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "ルートハッシュファイル %s に書き込めません。"
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "デバイス %s が有効な VERITY デバイスではありません。"
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "ルートハッシュファイル %s を読み込めません。"
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "不正なルートハッシュファイル %s です。"
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "不正なルートハッシュ文字列が指定されました。"
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "署名ファイル %s が不正です。"
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "署名ファイル %s を読み込めませんでした。"
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "コマンドは <root_hash> か --root-hash-file オプションを引数として必要とします。"
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<データデバイス> <ハッシュデバイス>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "デバイスをフォーマット"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<データデバイス> <ハッシュデバイス> [<ルートハッシュ>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "デバイスを検証"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<データデバイス> <名前> <ハッシュデバイス> [<ルートハッシュ>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "アクティブデバイスのステータスを表示"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<ハッシュデバイス>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "ディスク上の情報を表示"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<名前> は %s に作られるデバイス\n"
+"<データデバイス> はデータが入るデバイス\n"
+"<ハッシュデバイス> は検証用データが入るデバイス\n"
+"<ルートハッシュ> は <ハッシュデバイス> のルートノードのハッシュ\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"コンパイル時に決めた dm-verity のデフォルトパラメータ:\n"
+"\tハッシュ: %s, データブロック (バイト): %u, ハッシュブロック (バイト): %u, ソルトサイズ: %u, ハッシュフォーマット: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "--ignore-corruption と --restart-on-corruption は同時に使えません。"
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "--panic-on-corruption と --restart-on-corruption は同時に使えません。"
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"%s と %s のデータを復元不能な形で上書きします。\n"
+"データデバイスを保持するにはオプション --no-wipe を使ってください (その後、--integrity-recalculate を付けてアクティベートしてください)。"
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "タグサイズ %u、内部整合性は %s でフォーマットされました。\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "再計算フラグの設定はサポートされていません。代わりに --wipe を使うことを検討してください。"
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "デバイス %s が有効な INTEGRITY デバイスではありません。"
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<整合性デバイス>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<整合性デバイス> <名前>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<名前> は %s に作られるデバイス\n"
+"<整合性デバイス> は整合性タグを格納するデバイス\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"コンパイル時に決められたデフォルトの dm-integrity のパラメータ:\n"
+"\tチェックサムアルゴリズム: %s\n"
+" 最大キーファイルサイズ: %dkB\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "不正な --%s サイズです。最大は %u バイトです。"
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "キーファイルとキーサイズの両方の指定が必要です。"
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "ジャーナル整合性キーファイルとキーサイズの両方の指定が必要です。"
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "ジャーナル整合性キーを使う場合はアルゴリズムの指定が必要です。"
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "ジャーナル暗号キーファイルとキーサイズの両方の指定が必要です。"
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "ジャーナル暗号キーを使う場合はアルゴリズムの指定が必要です。"
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "リカバリと bitmap モードオプションは同時には使えません。"
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "ジャーナルオプションは bitmap モードでは使えません。"
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "bitmap オプションは bitmap モードでしか使えません。"
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"警告!!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"よろしいですか? ('yes' を大文字で入力してください): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "端末から応答を読み込み中にエラー。"
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "コマンド成功。"
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "パラメータが間違っているか指定されていません"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "権限がないかパスフレーズが間違っています"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "メモリ不足"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "間違ったデバイスかファイルが指定されました"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "デバイスが既にあるかビジーです"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "不明なエラー"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "コマンド失敗:コード %i (%s)"
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "キースロット %i が作成されました。"
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "キースロット %i がアンロックされました。"
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "キースロット %i が削除されました。"
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "トークン %i が作成されました。"
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "トークン %i が削除されました。"
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "この PIN でアンロックできるトークンがありません。"
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "トークン %i は PIN が必要です。"
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "トークン (タイプ %s) は PIN が必要です。"
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "トークン %i では割り当てられたキースロットをアンロックできません (間違ったキースロットパスフレーズ)。"
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "トークン (タイプ %s) では割り当てられたキースロットをアンロックできません (間違ったキースロットパスフレーズ)。"
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "トークン %i は追加のリソースが必要です。"
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "トークン (タイプ %s) は追加のリソースが必要です。"
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "使用可能なトークン (タイプ %s) がありません。"
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "使用可能なトークンがありません。"
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "キーファイル %s を読みこめませんでした。"
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "%d バイトをキーファイル %s から読みこめませんでした。"
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "キーファイル %s を書き込み用にオープンできません。"
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "キーファイル %s に書き込めません。"
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>分%02<PRIu64>秒"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>時間%02<PRIu64>分%02<PRIu64>秒"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> 日"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> %s 書き込み済"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "速度 %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "進捗: %5.1f%%, 残り時間 %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "終了。所要時間 %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "パスワードの質を確認できません: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"パスワードの質の確認に失敗:\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "パスワードの質が確認できません: 質の悪いパスフレーズ (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "端末からパスフレーズを読み込めません。"
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "同じパスフレーズを入力してください: "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "パスフレーズが一致しません。"
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "端末からの入力でオフセットは使用できません。"
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "パスフレーズを入力してください: "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "%s のパスフレーズを入力してください: "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "このパスフレーズで使用可能なキーはありません。"
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "使用可能なキースロットがありません。"
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "tty 入力以外ではパスフレーズ認証できません。"
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "ファイル %s を読み込み専用モードでオープンできません。"
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "妥当な LUKS2 トークンを JSON で与えてください:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "JSON ファイルを読み込めません。"
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"読み込みが中断されました。"
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "ファイル %s を書き込みモードでオープンできません。"
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"書き込みが中断されました。"
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "JSON ファイルに書き込めません。"
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "データデバイス %2s のアクティブな dm デバイス '%1s'を自動検出しました。\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "デバイス %s のホルダ(holders)を自動検出できません。"
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "デバイス %s は有効なブロックデバイスではありません。\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"デバイス %s がアクティベートされているかどうか判断できません。\n"
+"オフラインでの再暗号化を進めていいですか?\n"
+"アクティベートされていたらデータが破壊されるかもしれません。\n"
+"再暗号化をオンラインで行う場合は --active-name を代わりに使ってください。\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"デバイス %s はブロックデバイスではありません。アクティブであろうとなかろうと自動検出できません。\n"
+"このチェックをバイパスしてオフラインモードで動作するには --force-offline-reencrypt を使ってください。(ただし危険です!)。"
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "要求された --resilience オプションは現在の再暗号化処理に適用できません。"
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "デバイスは LUKS2 暗号化状態にありません。オプション --encrypt と競合します。"
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "デバイスは LUKS2 復号状態にありません。オプション --decrypt と競合します。"
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "デバイスはデータシフト耐性を使った再暗号化状態にあります。--resilience オプションは適用できません。"
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "デバイスは再暗号化リカバリが必要です。先に修復してください。"
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "デバイス %s は既に LUKS2 再暗号化状態にあります。以前に初期化された処理に復帰しますか?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "古い LUKS2 再暗号化はサポートされなくなりました。"
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "整合性プロファイルつきのデバイスの再暗号化はサポートされていません。"
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"要求された --sector-size %<PRIu32> は %s superblock\n"
+"(ブロックサイズ: %<PRIu32> バイト、デバイス %s)と互換性がありません。"
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "データデバイスサイズの縮小(--reduce-device-size)なしに分離ヘッダ(--header)による暗号化はできません。"
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "要求されたデータオフセットは --reduce-device-size パラメータの半分以下である必要があります。"
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "--reduce-device-size の値を --offset %<PRIu64> (セクタ) の倍にします。\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "テンポラリヘッダファイル %s は既に存在しているので、中止します。"
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "テンポラリヘッダファイル %s を作成できません。"
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "LUKS2 メタデータサイズがデータシフト値より大きいです。"
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "デバイス %s の先頭に新しいヘッダを置けません。"
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s がアクティブでオンライン暗号化可能です。\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "アクティブなデバイス %s は LUKS2 ではありません。"
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "オリジナルの LUKS2 ヘッダを復元しています。"
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "オリジナルの LUKS ヘッダの復元に失敗しました。"
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "ヘッダファイル %s が存在しません。デバイス %s の復号化をして LUKS2 ヘッダをファイル %s に出力しますか?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "エクスポートされたヘッダファイルに読み書き権限を付与できません。"
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "再暗号化の初期化に失敗しました。ヘッダのバックアップは %s にあります。"
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "LUKS2 復号は分離(detached)ヘッダデバイスしかサポートしていません(データへのオフセットが0)。"
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "再暗号化に必要な空きキースロットがありません。"
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "キーファイルは --key-slot と使うか、1 つのキースロットだけアクティブの時にしか使えません。"
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "キースロット %d のパスフレーズを入力してください: "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "キースロット %u のパスフレーズを入力してください: "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "データの暗号化用の暗号アルゴリズムを %s にします。\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "データセグメントのパラメータが変わっていません。再暗号化を中止します。"
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"オフラインデバイスの暗号化セクタサイズの増加はサポートしていません。\n"
+"まずデバイスをアクティベートするか、--force-offline-reencrypt オプションを使ってください (ただし危険です!)。"
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"再暗号化が中断されました。"
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "LUKS 再暗号化を強制オフラインモードで再開します。\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "デバイス %s は壊れた LUKS メタデータを含んでいます。処理を中止します。"
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "デバイス %s は既に LUKS デバイスです。処理を中止します。"
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "デバイス %s は既に LUKS 再暗号化状態にあります。処理を中止します。"
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "LUKS2 復号には --header オプションが必要です。"
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "コマンドはデバイスを引数として必要とします。"
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "バージョンが衝突しています。デバイス %s は LUKS1 です。"
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "バージョンが衝突しています。デバイス %s は LUKS1 再暗号化状態にあります。"
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "バージョンが衝突しています。デバイス %s は LUKS2 です。"
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "バージョンが衝突しています。デバイス %s は LUKS2 再暗号化状態にあります。"
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "LUKS2 再暗号化が既に初期化済なので操作を中止します。"
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "再暗号化処理を実行中ではありません。"
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "デバイスが使用中のため %s を排他的にオープンできません。"
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "アライメントつきメモリの確保ができませんでした。"
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "デバイス %s を読めません。"
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "LUKS1 デバイス %s を使用不可としてマークします。"
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "デバイス %s に書き込めません。"
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "再暗号化ログファイルに書きこめません。"
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "再暗号化ログファイルを読み込めません。"
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "誤ったログフォーマットです。"
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "ログファイル %s が既にあるので再暗号化を再開します。\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "古い LUKS ヘッダを使っているテンポラリデバイスを有効にします。"
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "新しい LUKS ヘッダを使っているテンポラリデバイスを有効にします。"
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "テンポラリデバイスの有効化に失敗しました。"
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "データオフセットの設定に失敗しました。"
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "メタデータサイズの設定に失敗しました。"
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "デバイス %s の新しい LUKS ヘッダを作成しました。"
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "%s ヘッダバックアップデバイス %s が作成されました。"
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "LUKS バックアップヘッダが作成できません。"
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "デバイス %2s の %1s ヘッダが復元できません。"
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "デバイス %2s の %1s ヘッダを復元しました。"
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "テンポラリ LUKS デバイスをオープンできません。"
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "デバイスサイズを取得できません。"
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "再暗号化中に I/O エラーが発生しました。"
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "与えられた UUID が不正です。"
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "再暗号化ログファイルを開けません。"
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "復号を実行中ではありません。与えられた UUID は中止された復号を再開するためだけに使えます。"
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "再暗号化で以下が変わります: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "ボリュームキー"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "ハッシュ"
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr "暗号(cipher)"
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "警告: デバイス %s が既に '%s' パーティションシグネチャを含んでいます。\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "警告: デバイス %s が既に '%s' のスーパーブロックシグネチャを含んでいます。\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "デバイスシグネチャ検出の初期化に失敗しました。"
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "デバイス %s の stat() に失敗しました。"
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "ファイル %s を読み書き可能なモードでオープンできません。"
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "今ある '%s' パーティションシグネチャはデバイス %s から消されます。"
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "今ある '%s' スーパーブロックシグネチャはデバイス %s から消されます。"
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "デバイスシグネチャを消せません。"
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "デバイス %s のシグネチャが検出できません。"
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "--%s のサイズの指定が不正です。"
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "オプション --%s は %s アクションと一緒には使えません。"
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "ssh token json ファイルに書き込めません。"
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"SSH サーバに接続されたトークンで LUKS2 デバイスをアンロックする cryptsetup プラグイン。このプラグインは既に存在するキースロットにトークンを追加できます。\n"
+"\n"
+"デバイスに存在するキースロットに対して、SSH サーバは指定されたパスにあるパスフレーズ付きのキーファイルを持っていなければなりません。\n"
+"与えられた credential がトークンを使ってデバイスをオープンする時のパスワードを得るのに使われます。\n"
+"\n"
+"Note: トークンを追加する時に与えられる情報 (SSH server address, user and paths) は LUKS2 ヘッダに平文で保存されます。"
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<アクション> <デバイス>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "'add' アクションのオプション:"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "このトークンのリモートサーバのIPアドレス/URL"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "リモートサーバで使うユーザ名"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "リモートサーバのキーファイルのパス"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "リモートサーバに接続するための SSH キーへのパス"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "トークンが割り当てられるキースロット。指定されなければトークンは与えられたパスフレーズがマッチする最初のキースロットに割り当てられます。"
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "一般オプション:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "より詳細なエラーメッセージを表示します"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "デバッグメッセージを表示します"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "JSON メタデータを含むデバッグメッセージを表示する"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "秘密鍵を開いてインポートできませんでした:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "秘密鍵のインポートに失敗しました(パスワードで保護されているのでは?)。\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "%s@%s のパスワード: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "引数の解釈に失敗しました。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "アクションの指定が必要です\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "'%s' アクションにはデバイスの指定が必要です。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "'%s' アクションには SSH サーバの指定が必要です。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "'%s' アクションには SSH ユーザの指定が必要です。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "'%s' アクションには SSH パスの指定が必要です。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "'%s' アクションには SSH キーパスの指定が必要です。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "与えられた credential ではファイル %s をオープンできません。\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "今のところ、このプラグインでは 'add' アクションしかサポートされていません。\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "sftp セッションが作成できません: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "sftp セッションが初期化できません: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "sftp セッションをオープンできません: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "sftp ファイルの stat できません: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "メモリ不足。\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "リモートキーを読み込めません: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "接続に失敗しました: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "サーバが不明です: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "公開鍵暗号認証がホストで許可されていません。\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "公開鍵認証エラー: "
diff --git a/po/ka.po b/po/ka.po
new file mode 100644
index 0000000..189e176
--- /dev/null
+++ b/po/ka.po
@@ -0,0 +1,3756 @@
+# Georgian translation for cryptsetup.
+# Copyright (C) 2022 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.0-rc1\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2022-11-20 12:38+0100\n"
+"PO-Revision-Date: 2022-12-28 18:51+0100\n"
+"Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n"
+"Language-Team: Georgian <(nothing)>\n"
+"Language: ka\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr ""
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr ""
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr ""
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "უცნობი dm სამიზნის ტიპი."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM მხარდაუჭერელია."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr ""
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr ""
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "გასაღების გენერაცია (%d%% მზადაა).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "FIPS რეჟიმში მუშაობა."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "ფატალური შეცდომა RNG-ის ინიციალიზაციისას."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "RNG-ის მოთხოვნილი ხარისხი უცნობია."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "RNG-დან წაკითხვის შეცდომა."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "კრიპტოს RNG უკანაბოლოს ინიციალიზაციის შეცდომა."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "კრიპტო უკანაბოლოს ინიციალიზაციის შეცდომა."
+
+#: lib/setup.c:268 lib/setup.c:2139 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr ""
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "გასაღების დამუშავების შეცდომა (გამოყენებული ჰეში %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr ""
+
+#: lib/setup.c:348 lib/setup.c:3308
+msgid "This operation is supported only for LUKS device."
+msgstr ""
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr ""
+
+#: lib/setup.c:430 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "გასაღების ყველა სლოტი სავსეა."
+
+#: lib/setup.c:441
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr ""
+
+#: lib/setup.c:447
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr ""
+
+#: lib/setup.c:532 lib/setup.c:3030
+msgid "Device size is not aligned to device logical block size."
+msgstr ""
+
+#: lib/setup.c:630
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr ""
+
+#: lib/setup.c:671 lib/setup.c:2930 lib/setup.c:4275
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr ""
+
+#: lib/setup.c:676
+msgid "Illegal operation with reencryption in-progress."
+msgstr ""
+
+#: lib/setup.c:762
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr ""
+
+#: lib/setup.c:849 lib/luks1/keymanage.c:247 lib/luks1/keymanage.c:525
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1433
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr ""
+
+#: lib/setup.c:852 lib/luks1/keymanage.c:528
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "LUKS-ის მხარდაუჭერელი ვერსია %d."
+
+#: lib/setup.c:1479 lib/setup.c:2679 lib/setup.c:2761 lib/setup.c:2773
+#: lib/setup.c:2940 lib/setup.c:4752
+#, c-format
+msgid "Device %s is not active."
+msgstr "მოწყობილობა %s აქტიური არაა."
+
+#: lib/setup.c:1496
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "ქვეშმყოფი მოწყობილობა დაშიფრული მოწყობილობისთვის %s სადღაც აორთქლდა."
+
+#: lib/setup.c:1578
+msgid "Invalid plain crypt parameters."
+msgstr "უბრალოდ შიფრაციის არასწორი პარამეტრები."
+
+#: lib/setup.c:1583 lib/setup.c:2042
+msgid "Invalid key size."
+msgstr "გასაღების არასწორი ზომა."
+
+#: lib/setup.c:1588 lib/setup.c:2047 lib/setup.c:2250
+msgid "UUID is not supported for this crypt type."
+msgstr ""
+
+#: lib/setup.c:1593 lib/setup.c:2052
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr ""
+
+#: lib/setup.c:1603 lib/setup.c:1819 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr ""
+
+#: lib/setup.c:1611 lib/setup.c:1947 lib/setup.c:3024
+msgid "Device size is not aligned to requested sector size."
+msgstr ""
+
+#: lib/setup.c:1663 lib/setup.c:1787
+msgid "Can't format LUKS without device."
+msgstr ""
+
+#: lib/setup.c:1669 lib/setup.c:1793
+msgid "Requested data alignment is not compatible with data offset."
+msgstr ""
+
+#: lib/setup.c:1744 lib/setup.c:1964 lib/setup.c:1985 lib/setup.c:2262
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr ""
+
+#: lib/setup.c:1757 lib/setup.c:2024
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr ""
+
+#: lib/setup.c:1828
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr ""
+
+#: lib/setup.c:1851
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr ""
+
+#: lib/setup.c:1911
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr ""
+
+#: lib/setup.c:1937
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr ""
+
+#: lib/setup.c:1941
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr ""
+
+#: lib/setup.c:1967 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "მოწყობილობა ძალიან პატარაა %s."
+
+#: lib/setup.c:1978 lib/setup.c:2004
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr ""
+
+#: lib/setup.c:1981 lib/setup.c:2007
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr ""
+
+#: lib/setup.c:1993 lib/setup.c:2322
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr ""
+
+#: lib/setup.c:2011
+#, c-format
+msgid "Cannot format device %s."
+msgstr "მოწყობილობის ფორმატირების (%s) შეცდომა."
+
+#: lib/setup.c:2037
+msgid "Can't format LOOPAES without device."
+msgstr ""
+
+#: lib/setup.c:2082
+msgid "Can't format VERITY without device."
+msgstr ""
+
+#: lib/setup.c:2093 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr ""
+
+#: lib/setup.c:2099 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr ""
+
+#: lib/setup.c:2104 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr ""
+
+#: lib/setup.c:2109
+msgid "Unsupported VERITY FEC offset."
+msgstr ""
+
+#: lib/setup.c:2133
+msgid "Data area overlaps with hash area."
+msgstr ""
+
+#: lib/setup.c:2158
+msgid "Hash area overlaps with FEC area."
+msgstr ""
+
+#: lib/setup.c:2165
+msgid "Data area overlaps with FEC area."
+msgstr ""
+
+#: lib/setup.c:2301
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr ""
+
+#: lib/setup.c:2380
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr ""
+
+#: lib/setup.c:2687 lib/setup.c:2766 lib/setup.c:2779
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr ""
+
+#: lib/setup.c:2693 lib/setup.c:2786 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr ""
+
+#: lib/setup.c:2810
+msgid "Crypt devices mismatch."
+msgstr ""
+
+#: lib/setup.c:2847 lib/setup.c:2852 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr ""
+
+#: lib/setup.c:2858 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr ""
+
+#: lib/setup.c:2870 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr ""
+
+#: lib/setup.c:2885
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr ""
+
+#: lib/setup.c:2888 lib/setup.c:2890
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr ""
+
+#: lib/setup.c:2972
+msgid "Cannot resize loop device."
+msgstr "Loop მოწყობილობის ზომის შეცვლა შეუძლებელია."
+
+#: lib/setup.c:3015
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr ""
+
+#: lib/setup.c:3076
+msgid "Resize failed, the kernel doesn't support it."
+msgstr ""
+
+#: lib/setup.c:3108
+msgid "Do you really want to change UUID of device?"
+msgstr ""
+
+#: lib/setup.c:3200
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr ""
+
+#: lib/setup.c:3316
+#, c-format
+msgid "Volume %s is not active."
+msgstr "ტომი %s აქტიური არაა."
+
+#: lib/setup.c:3327
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr ""
+
+#: lib/setup.c:3340
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr ""
+
+#: lib/setup.c:3342
+#, c-format
+msgid "Error during suspending device %s."
+msgstr ""
+
+#: lib/setup.c:3377
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr ""
+
+#: lib/setup.c:3379
+#, c-format
+msgid "Error during resuming device %s."
+msgstr ""
+
+#: lib/setup.c:3413 lib/setup.c:3461 lib/setup.c:3532 lib/setup.c:3577
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr ""
+
+#: lib/setup.c:3547 lib/setup.c:4528 lib/setup.c:4541 lib/setup.c:4549
+#: lib/setup.c:4562 lib/setup.c:6145 lib/setup.c:6167 lib/setup.c:6216
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "ტომის გასაღები ტომს არ ემთხვევა."
+
+#: lib/setup.c:3725
+msgid "Failed to swap new key slot."
+msgstr ""
+
+#: lib/setup.c:3823
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "გასაღების სლოტი %d არასწორია."
+
+#: lib/setup.c:3829 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "გასაღების სლოტი %d აქტიური არაა."
+
+#: lib/setup.c:3848
+msgid "Device header overlaps with data area."
+msgstr ""
+
+#: lib/setup.c:4153
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr ""
+
+#: lib/setup.c:4155 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr ""
+
+#: lib/setup.c:4168 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr ""
+
+#: lib/setup.c:4340 lib/setup.c:4606
+msgid "Device type is not properly initialized."
+msgstr ""
+
+#: lib/setup.c:4388
+#, c-format
+msgid "Device %s already exists."
+msgstr "მოწყობლობა %s უკვე არსებობს."
+
+#: lib/setup.c:4395
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr ""
+
+#: lib/setup.c:4515
+msgid "Incorrect volume key specified for plain device."
+msgstr ""
+
+#: lib/setup.c:4632
+msgid "Incorrect root hash specified for verity device."
+msgstr ""
+
+#: lib/setup.c:4642
+msgid "Root hash signature required."
+msgstr ""
+
+#: lib/setup.c:4651
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr ""
+
+#: lib/setup.c:4668 lib/setup.c:6411
+msgid "Failed to load key in kernel keyring."
+msgstr ""
+
+#: lib/setup.c:4724
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr ""
+
+#: lib/setup.c:4731 lib/setup.c:4747 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "მოწყობილობა %s ჯერ კიდევ გამოიყენება."
+
+#: lib/setup.c:4756
+#, c-format
+msgid "Invalid device %s."
+msgstr "არასწორი მოწყობილობა '%s'."
+
+#: lib/setup.c:4896
+msgid "Volume key buffer too small."
+msgstr "ტომის გასაღების ბუფერი ძალიან პატარაა."
+
+#: lib/setup.c:4913
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr ""
+
+#: lib/setup.c:4922
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr ""
+
+#: lib/setup.c:4932
+msgid "Cannot retrieve volume key for plain device."
+msgstr "უბრალო მოწყობილობისთვის ტომის გასაღების მიღების შეცდომა."
+
+#: lib/setup.c:4940
+msgid "Cannot retrieve root hash for verity device."
+msgstr ""
+
+#: lib/setup.c:4947
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr ""
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr ""
+
+#: lib/setup.c:4954
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr ""
+
+#: lib/setup.c:5135 lib/setup.c:5146
+msgid "Dump operation is not supported for this device type."
+msgstr ""
+
+#: lib/setup.c:5488
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr ""
+
+#: lib/setup.c:5776
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr ""
+
+#: lib/setup.c:6086 lib/setup.c:6225
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr ""
+
+#: lib/setup.c:6110
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr ""
+
+#: lib/setup.c:6116
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr ""
+
+#: lib/setup.c:6341
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr ""
+
+#: lib/setup.c:6478
+msgid "Kernel keyring is not supported by the kernel."
+msgstr ""
+
+#: lib/setup.c:6488 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr ""
+
+#: lib/setup.c:6512
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr ""
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "გასაღების ფაილის გახსნის შეცდომა."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr ""
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "გასაღების ფაილის აღმოჩენის შეცდომა."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr ""
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:227
+#: src/utils_password.c:239
+msgid "Out of memory while reading passphrase."
+msgstr "არასაკმარისი მეხსიერება საკვანძო ფრაზის წაკითხვისას."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "საკვანძო ფრაზის წაკითხვის შეცდომა."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr ""
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr ""
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr ""
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1408
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr ""
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr ""
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr ""
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr ""
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr ""
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr ""
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr ""
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr ""
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr ""
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr ""
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr ""
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr ""
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr ""
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr ""
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr ""
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr ""
+
+#: lib/utils_benchmark.c:174
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr ""
+
+#: lib/utils_benchmark.c:193
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr ""
+
+#: lib/utils_benchmark.c:213
+msgid "Not compatible PBKDF options."
+msgstr ""
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr ""
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr ""
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr ""
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:364
+#: lib/luks1/keymanage.c:675 lib/luks1/keymanage.c:1126
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:61
+#: lib/luks2/luks2_keyslot_luks2.c:79 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:367
+#: lib/luks1/keymanage.c:628 lib/luks1/keymanage.c:678 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "მოწყობილობის გახსნის შეცდომა: '%s'."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:138
+msgid "IO error while decrypting keyslot."
+msgstr ""
+
+#: lib/luks1/keymanage.c:129
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr ""
+
+#: lib/luks1/keymanage.c:150 lib/luks1/keymanage.c:158
+#: lib/luks1/keymanage.c:170 lib/luks1/keymanage.c:181
+#: lib/luks1/keymanage.c:193
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr ""
+
+#: lib/luks1/keymanage.c:265 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr ""
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:274 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr ""
+
+#: lib/luks1/keymanage.c:319 lib/luks1/keymanage.c:591
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:327 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:337
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr ""
+
+#: lib/luks1/keymanage.c:345
+#, c-format
+msgid "Device %s %s%s"
+msgstr "მოწყობილობა %s %s%s"
+
+#: lib/luks1/keymanage.c:346
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr ""
+
+#: lib/luks1/keymanage.c:347
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr ""
+
+#: lib/luks1/keymanage.c:348 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+
+#: lib/luks1/keymanage.c:396
+msgid "Non standard key size, manual repair required."
+msgstr ""
+
+#: lib/luks1/keymanage.c:406
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr ""
+
+#: lib/luks1/keymanage.c:415
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:426
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:428 lib/luks1/keymanage.c:534
+#: lib/luks1/keymanage.c:790
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr ""
+
+#: lib/luks1/keymanage.c:442
+msgid "Repairing keyslots."
+msgstr ""
+
+#: lib/luks1/keymanage.c:461
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:469
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:478
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr ""
+
+#: lib/luks1/keymanage.c:483
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr ""
+
+#: lib/luks1/keymanage.c:500
+msgid "Writing LUKS header to disk."
+msgstr ""
+
+#: lib/luks1/keymanage.c:505
+msgid "Repair failed."
+msgstr "შეკეთების შეცდომა."
+
+#: lib/luks1/keymanage.c:560
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr ""
+
+#: lib/luks1/keymanage.c:565
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr ""
+
+#: lib/luks1/keymanage.c:572 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr ""
+
+#: lib/luks1/keymanage.c:700
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:708
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr ""
+
+#: lib/luks1/keymanage.c:784
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr ""
+
+#: lib/luks1/keymanage.c:795 lib/luks1/keymanage.c:864
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:514
+msgid "Wrong LUKS UUID format provided."
+msgstr ""
+
+#: lib/luks1/keymanage.c:817
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr ""
+
+#: lib/luks1/keymanage.c:843
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:887
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr ""
+
+#: lib/luks1/keymanage.c:893
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr ""
+
+#: lib/luks1/keymanage.c:1034
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr ""
+
+#: lib/luks1/keymanage.c:1112
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr ""
+
+#: lib/luks1/keymanage.c:1130 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr ""
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr ""
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr ""
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr ""
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "გასაღების ფაილის %s წაკითხვის შეცდომა."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr ""
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:275
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:328
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:332
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:349
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:451
+msgid "BITLK version 1 is currently not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:457
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:469
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:477
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:502
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:554
+msgid "Unknown or unsupported encryption type."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:587
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:681
+msgid "Failed to convert BITLK volume description"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:841
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:860
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:864
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:903
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:908
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:933
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1029
+msgid "This operation is not supported."
+msgstr "ეს ოპერაცია მხარდაუჭერელია."
+
+#: lib/bitlk/bitlk.c:1037
+msgid "Unexpected key data size."
+msgstr "გასაღების მონაცემების მოულოდნელი ზომა."
+
+#: lib/bitlk/bitlk.c:1163
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1168
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1175
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1216
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1343
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1347
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1351
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1355
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr ""
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr ""
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr ""
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr ""
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr ""
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "VERITY თავსართი დაზიანებულია."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr ""
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr ""
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr ""
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr ""
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr ""
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr ""
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "მოწყობილობის წანაცვლების გადავსება."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "გადამოწმების შეცდომა მდებარეობაზე %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "ჰეშის ფართის გადავსება."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "მონაცემების რეგიონის გადამოწმების შეცდომა."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr ""
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr ""
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr ""
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr ""
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr ""
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "ბუფერის გამოყოფის შეცდომა."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr ""
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr ""
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr ""
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr ""
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr ""
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr ""
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr ""
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr ""
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr ""
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:93
+#: lib/luks2/luks2_keyslot_luks2.c:115
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "მოწყობილობა %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "უცნობი ალამი იგნორირებულია %s."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:54 lib/luks2/luks2_keyslot_luks2.c:109
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:281 lib/luks2/luks2_keyslot_luks2.c:390
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:506
+msgid "No space for new keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "ცხრილის გასუფთავება შეუძლებელია."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "გაშიფვრის შეცდომა."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "მონაცემების სინქრონიზაციის შეცდომა."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr ""
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr ""
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "შეიყვანეთ კოდის PIN კოდი: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr ""
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1097 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr ""
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr ""
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr ""
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr ""
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:724
+msgid "Operation aborted.\n"
+msgstr "ოპერაცია გაუქმდა.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr ""
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr ""
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr ""
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr ""
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr ""
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr ""
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr ""
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr ""
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr ""
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr ""
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr ""
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr ""
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr ""
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/A\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr ""
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/A\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr ""
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr ""
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr ""
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s ალგორითმი | გასაღები | დაშიფვრა | გაშიფვრა\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr ""
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# ალგორითმი | გასაღები | დაშიფვრა | გაშიფვრა\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "N/A"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr ""
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr ""
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr ""
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr ""
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr ""
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr ""
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr ""
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr ""
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr ""
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "თავსართის ფაილის (%s) შექმნის შეცდომა."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr ""
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr ""
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr ""
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr ""
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr ""
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr ""
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr ""
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr ""
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr ""
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr ""
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr ""
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr ""
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr ""
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr ""
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr ""
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr ""
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "შეიყვანეთ ახალი საკვანძო ფრაზა: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr ""
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr ""
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr ""
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr ""
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr ""
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr ""
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr ""
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr ""
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr ""
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr ""
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr ""
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr ""
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr ""
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "კოდი %d არასწორია."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "კოდი %d გამოიყენება."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr ""
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr ""
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "კოდი %d არ გამოიყენება."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr ""
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr ""
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr ""
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr ""
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr ""
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr ""
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr ""
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr ""
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr ""
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr ""
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr ""
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr ""
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr ""
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr ""
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr ""
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr ""
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr ""
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr ""
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr ""
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr ""
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr ""
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr ""
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr ""
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr ""
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr ""
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr ""
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "არასწორი კოდის ქმედება."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr ""
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr ""
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr ""
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr ""
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<მოწყობილობა> [--type <ტიპი>] [<სახელი>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr ""
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<name>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr ""
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "აქტიური მოწყობილობის ზომის შეცვლა"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "მოწყობილობის მდგომარეობის ჩვენება"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <შიფრი>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr ""
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<მოწყობილობა>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr ""
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr ""
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr ""
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr ""
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr ""
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr ""
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<მოწყობილობა> [<გასაღების ფაილი>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr ""
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr ""
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr ""
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr ""
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr ""
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr ""
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr ""
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr ""
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr ""
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr ""
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr ""
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr ""
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr ""
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<ქმედება> შეიძლება იყოს:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr ""
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "გამორთულია"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr ""
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "გასაღების სლოტი არასწორია."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr ""
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr ""
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr ""
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr ""
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr ""
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr ""
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "დახმარების ამ შეტყობინების ჩვენება"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "გამოყენების მოკლე შეტყობინება"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "პაკეტის ვერსიის გამოტანა"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "დახმარების პარამეტრები:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr ""
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr ""
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "უცნობი ქმედება."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr ""
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr ""
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr ""
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr ""
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr ""
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr ""
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "მარილის მითითებული სტრიქონი არასწორია."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr ""
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr ""
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr ""
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr ""
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr ""
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr ""
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr ""
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr ""
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr ""
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr ""
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr ""
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr ""
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "მოწყობილობის ფორმატირება"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr ""
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "მოწყობილობის გადამოწმება"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr ""
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "აქტიურ მოწყობილობის სტატუსის ჩვენება"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<ჰეშის მოწყობილობა>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr ""
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr ""
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr ""
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr ""
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr ""
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr ""
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr ""
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr ""
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr ""
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr ""
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr ""
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr ""
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr ""
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr ""
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"გაფრთხილება!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "ტერმინალიდან მიღებული პასუხის წაკითხვის შეცდომა."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "ბრძანება წარმატებულია."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "ნაკლული ან არასწორი პარამეტრები"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "აკრძალული წვდომა ან არასწორი საკვანძო ფრაზა"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "მეხსიერებას გარეთ"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "მითითებული მოწყობილობა ან ფაილი არასწორია"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "მოწყობილობა უკვე არსებობს ან დაკავებულია"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "უცნობი შეცდომა"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr ""
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr ""
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr ""
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr ""
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr ""
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr ""
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr ""
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr ""
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr ""
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr ""
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr ""
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr ""
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr ""
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr ""
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr ""
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr ""
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr ""
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr ""
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr ""
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>სთ%02<PRIu64>წთ%02<PRIu64>წმ"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> დღე"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> %s ჩაწერილია"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "სიჩქარე %5.1f %s/წმ"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "მიმდინარეობა: %5.1f%%, დარჩენილია %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "დასრულდა. დრო: %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr ""
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+
+#: src/utils_password.c:81
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr ""
+
+#: src/utils_password.c:232 src/utils_password.c:246
+msgid "Error reading passphrase from terminal."
+msgstr ""
+
+#: src/utils_password.c:244
+msgid "Verify passphrase: "
+msgstr "გადაამოწმეთ საკვანძო ფრაზა: "
+
+#: src/utils_password.c:251
+msgid "Passphrases do not match."
+msgstr "საკვანძო ფრაზები არ ემთხვევა."
+
+#: src/utils_password.c:289
+msgid "Cannot use offset with terminal input."
+msgstr ""
+
+#: src/utils_password.c:293
+#, c-format
+msgid "Enter passphrase: "
+msgstr "შეიყვანეთ საკვანძო ფრაზა: "
+
+#: src/utils_password.c:296
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "შეიყვანეთ საკვანძო ფრაზა \"%s\"-სთვის: "
+
+#: src/utils_password.c:330
+msgid "No key available with this passphrase."
+msgstr ""
+
+#: src/utils_password.c:332
+msgid "No usable keyslot is available."
+msgstr ""
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr ""
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr ""
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr ""
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "JSON ფაილის წაკითხვის შეცდომა."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"წაკითხვა შეწყდა."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr ""
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"ჩაწერა შეწყდა."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "JSON ფაილი ჩაწერის შეცდომა."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr ""
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr ""
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr ""
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr ""
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr ""
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr ""
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr ""
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr ""
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:494
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr ""
+
+#: src/utils_reencrypt.c:500
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr ""
+
+#: src/utils_reencrypt.c:510
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:540
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr ""
+
+#: src/utils_reencrypt.c:542 src/utils_reencrypt.c:549
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:574
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr ""
+
+#: src/utils_reencrypt.c:611
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:621
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:657
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr ""
+
+#: src/utils_reencrypt.c:685
+msgid "Restoring original LUKS2 header."
+msgstr ""
+
+#: src/utils_reencrypt.c:693
+msgid "Original LUKS2 header restore failed."
+msgstr ""
+
+#: src/utils_reencrypt.c:719
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr ""
+
+#: src/utils_reencrypt.c:767
+msgid "Failed to add read/write permissions to exported header file."
+msgstr ""
+
+#: src/utils_reencrypt.c:820
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr ""
+
+#: src/utils_reencrypt.c:848
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr ""
+
+#: src/utils_reencrypt.c:983 src/utils_reencrypt.c:992
+msgid "Not enough free keyslots for reencryption."
+msgstr ""
+
+#: src/utils_reencrypt.c:1013 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr ""
+
+#: src/utils_reencrypt.c:1022 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr ""
+
+#: src/utils_reencrypt.c:1034
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr ""
+
+#: src/utils_reencrypt.c:1086
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:1140
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr ""
+
+#: src/utils_reencrypt.c:1242
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+
+#: src/utils_reencrypt.c:1282 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"თავიდან დაშიფვრა შეწყვეტილია."
+
+#: src/utils_reencrypt.c:1287
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr ""
+
+#: src/utils_reencrypt.c:1304
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1320 src/utils_reencrypt.c:1342
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1348
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1421
+msgid "LUKS2 decryption requires --header option."
+msgstr ""
+
+#: src/utils_reencrypt.c:1469
+msgid "Command requires device as argument."
+msgstr ""
+
+#: src/utils_reencrypt.c:1482
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr ""
+
+#: src/utils_reencrypt.c:1488
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr ""
+
+#: src/utils_reencrypt.c:1494
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr ""
+
+#: src/utils_reencrypt.c:1500
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr ""
+
+#: src/utils_reencrypt.c:1506
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr ""
+
+#: src/utils_reencrypt.c:1513
+msgid "Device reencryption not in progress."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "ჟურნალის არასწორი ფორმატი."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "მოწყობილობის ზომის მიღების შეცდომა."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "მითითებული UUID არასწორია."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr ""
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "ტომის გასაღები"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "ჰეშის დაყენება "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ""
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr ""
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr ""
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr ""
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr ""
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr ""
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr ""
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr ""
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr ""
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr ""
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr ""
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<ქმედება> <მოწყობილობა>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr ""
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "%s@%s-ის პაროლი: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "არგუმენტების დამუშავების შეცდომა.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr ""
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "SFTP სესიის შექმნის შეცდომა: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "SFTP სესიის ინიციალიზაციის შეცდომა: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "SFTP სესიის გახსნის შეცდომა: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "SFTP ფაილის აღმოჩენის შეცდომა: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "არასაკმარისი მეხსიერება.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "დაშორებული გასაღების წაკითხვის შეცდომა: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "მიერთების შეცდომა: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "სერვერი უცნობია: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr ""
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr ""
diff --git a/po/nl.po b/po/nl.po
new file mode 100644
index 0000000..3cc2930
--- /dev/null
+++ b/po/nl.po
@@ -0,0 +1,4099 @@
+# Dutch translations for cryptsetup.
+# Copyright (C) 2020 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+#
+# Koen <koen@drunkfelines.com>, 2017.
+# Benno Schulenberg <vertaling@coevern.nl>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup-2.3.0-rc0\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2020-01-12 12:33+0100\n"
+"PO-Revision-Date: 2020-01-13 20:42+0100\n"
+"Last-Translator: Benno Schulenberg <vertaling@coevern.nl>\n"
+"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: lib/libdevmapper.c:397
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Kan apparaatstoewijzer niet initialiseren, uitvoering als non-root gebruiker."
+
+#: lib/libdevmapper.c:400
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Kan apparaatstoewijzer niet initialiseren. Is kernelmodule dm_mod geladen?"
+
+#: lib/libdevmapper.c:1120
+#, fuzzy
+msgid "Requested deferred flag is not supported."
+msgstr "Aangevraagde LUKS-hash %s wordt niet ondersteund.\n"
+
+#: lib/libdevmapper.c:1187
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID voor apparaat %s werd afgekapt."
+
+#: lib/libdevmapper.c:1509
+msgid "Unknown dm target type."
+msgstr ""
+
+#: lib/libdevmapper.c:1612 lib/libdevmapper.c:1664
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Aangevraagde prestatie-opties voor dm-crypt worden niet ondersteund."
+
+#: lib/libdevmapper.c:1619
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Aangevraagde opties voor behandeling van datacorruptie van dm-verity worden niet ondersteund."
+
+#: lib/libdevmapper.c:1623
+#, fuzzy
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Aangevraagde prestatie-opties voor dm-crypt worden niet ondersteund.\n"
+
+#: lib/libdevmapper.c:1627
+#, fuzzy
+msgid "Requested data integrity options are not supported."
+msgstr "Aangevraagde prestatie-opties voor dm-crypt worden niet ondersteund.\n"
+
+#: lib/libdevmapper.c:1629
+#, fuzzy
+msgid "Requested sector_size option is not supported."
+msgstr "Aangevraagde prestatie-opties voor dm-crypt worden niet ondersteund.\n"
+
+#: lib/libdevmapper.c:1634
+#, fuzzy
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Aangevraagde opties voor behandeling van datacorruptie van dm-verity worden niet ondersteund.\n"
+
+#: lib/libdevmapper.c:1638
+#, fuzzy
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Aangevraagde opties voor behandeling van datacorruptie van dm-verity worden niet ondersteund.\n"
+
+#: lib/libdevmapper.c:1667
+#, fuzzy
+msgid "Discard/TRIM is not supported."
+msgstr "Aangevraagd hash-algoritme %s wordt niet ondersteund.\n"
+
+#: lib/libdevmapper.c:2585
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr ""
+
+#: lib/random.c:80
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Systeem heeft niet genoeg willekeurige gegevens om de sleutel tot het opslagmedium verder te genereren.\n"
+"Beweeg de muis of typ wat tekst in een nieuw venster om enkele willekeurige evenementen te verzamelen.\n"
+
+#: lib/random.c:84
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Sleutel wordt gegenereerd (%d%% afgewerkt).\n"
+
+#: lib/random.c:170
+msgid "Running in FIPS mode."
+msgstr "Uitvoering in FIPS-modus."
+
+#: lib/random.c:176
+msgid "Fatal error during RNG initialisation."
+msgstr "Fatale fout bij initialisatie van RNG."
+
+#: lib/random.c:213
+msgid "Unknown RNG quality requested."
+msgstr "Onbekende RNG-kwaliteit aangevraagd."
+
+#: lib/random.c:218
+msgid "Error reading from RNG."
+msgstr "Fout bij lezen uit RNG."
+
+#: lib/setup.c:230
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Kan RNG versleutelings-backend niet initialiseren."
+
+#: lib/setup.c:236
+msgid "Cannot initialize crypto backend."
+msgstr "Kan versleutelings-backend niet initialiseren."
+
+#: lib/setup.c:267 lib/setup.c:2044 lib/verity/verity.c:120
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Aangevraagd hash-algoritme %s wordt niet ondersteund."
+
+#: lib/setup.c:270 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Sleutelbehandelingsfout (met hash %s in gebruik)."
+
+#: lib/setup.c:336 lib/setup.c:363
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Apparaatstype kan niet bepaald worden. Incompatibele apparaatsactivering?"
+
+#: lib/setup.c:342 lib/setup.c:3048
+msgid "This operation is supported only for LUKS device."
+msgstr "Deze operatie wordt enkel ondersteund voor LUKS-apparaten."
+
+#: lib/setup.c:369
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Deze operatie wordt enkel ondersteund voor LUKS2-apparaten."
+
+#: lib/setup.c:424 lib/luks2/luks2_reencrypt.c:2345
+msgid "All key slots full."
+msgstr "Alle sleutelplaatsen zijn vol."
+
+#: lib/setup.c:435
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Sleutelplaats %d is ongeldig, selecteer een plaats tussen 0 en %d."
+
+#: lib/setup.c:441
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Sleutelplaats %d is vol, selecteer een andere."
+
+#: lib/setup.c:526 lib/setup.c:2822
+#, fuzzy
+msgid "Device size is not aligned to device logical block size."
+msgstr "Apparaat %s is geen geldig LUKS-apparaat.\n"
+
+#: lib/setup.c:622
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Koptekst gevonden maar apparaat %s is te klein."
+
+#: lib/setup.c:659
+msgid "This operation is not supported for this device type."
+msgstr "Deze operatie wordt niet ondersteund voor dit apparaatstype."
+
+#: lib/setup.c:664
+msgid "Illegal operation with reencryption in-progress."
+msgstr ""
+
+#: lib/setup.c:830 lib/luks1/keymanage.c:476
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Niet-ondersteunde LUKS-versie %d."
+
+#: lib/setup.c:847 lib/setup.c:1537 lib/setup.c:1957
+#, fuzzy
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "UUID wordt niet ondersteund voor dit encryptietype.\n"
+
+#: lib/setup.c:1425 lib/setup.c:2542 lib/setup.c:2614 lib/setup.c:2626
+#: lib/setup.c:2775 lib/setup.c:4510
+#, c-format
+msgid "Device %s is not active."
+msgstr "Apparaat %s is niet actief."
+
+#: lib/setup.c:1442
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Onderliggend apparaat van versleutelingsapparaat %s is verdwenen."
+
+#: lib/setup.c:1522
+msgid "Invalid plain crypt parameters."
+msgstr "Ongeldige normale versleutelingsparameters."
+
+#: lib/setup.c:1527 lib/setup.c:1947 src/integritysetup.c:73
+msgid "Invalid key size."
+msgstr "Ongeldige sleutelgrootte."
+
+#: lib/setup.c:1532 lib/setup.c:1952 lib/setup.c:2155
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID wordt niet ondersteund voor dit encryptietype."
+
+#: lib/setup.c:1547 lib/setup.c:1737 lib/luks2/luks2_reencrypt.c:2308
+#: src/cryptsetup.c:1232
+#, fuzzy
+msgid "Unsupported encryption sector size."
+msgstr "Kan herencryptie-logbestand niet lezen.\n"
+
+#: lib/setup.c:1555 lib/setup.c:1862 lib/setup.c:2816
+#, fuzzy
+msgid "Device size is not aligned to requested sector size."
+msgstr "Apparaat %s is geen geldig LUKS-apparaat.\n"
+
+#: lib/setup.c:1606 lib/setup.c:1725
+msgid "Can't format LUKS without device."
+msgstr "Kan LUKS niet formatteren zonder apparaat."
+
+#: lib/setup.c:1612 lib/setup.c:1731
+msgid "Requested data alignment is not compatible with data offset."
+msgstr ""
+
+#: lib/setup.c:1680 lib/setup.c:1849
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr ""
+
+#: lib/setup.c:1690 lib/setup.c:1877 lib/setup.c:1898 lib/setup.c:2167
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Kan koptekst op apparaat %s niet wissen."
+
+#: lib/setup.c:1742
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr ""
+
+#: lib/setup.c:1764
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr ""
+
+#: lib/setup.c:1819
+#, fuzzy, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Versleutelalgoritme %s is niet beschikbaar.\n"
+
+#: lib/setup.c:1852
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr ""
+
+#: lib/setup.c:1856
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr ""
+
+#: lib/setup.c:1880 lib/utils_device.c:829 lib/luks1/keyencryption.c:256
+#: lib/luks2/luks2_reencrypt.c:2356 lib/luks2/luks2_reencrypt.c:3367
+#, c-format
+msgid "Device %s is too small."
+msgstr "Apparaat %s is te klein."
+
+#: lib/setup.c:1891 lib/setup.c:1917
+#, fuzzy, c-format
+msgid "Cannot format device %s in use."
+msgstr "Kan apparaat %s niet formatteren; het is nog steeds actief.\n"
+
+#: lib/setup.c:1894 lib/setup.c:1920
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Kan apparaat %s niet formatteren: toestemming geweigerd."
+
+#: lib/setup.c:1906 lib/setup.c:2227
+#, fuzzy, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Kan apparaat %s niet beschrijven.\n"
+
+#: lib/setup.c:1924
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Kan apparaat %s niet formatteren."
+
+#: lib/setup.c:1942
+msgid "Can't format LOOPAES without device."
+msgstr "Kan LOOPAES niet formatteren zonder apparaat."
+
+#: lib/setup.c:1987
+msgid "Can't format VERITY without device."
+msgstr "Kan VERITY niet formatteren zonder apparaat."
+
+#: lib/setup.c:1998 lib/verity/verity.c:103
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Niet-ondersteund VERITY-hashtype %d."
+
+#: lib/setup.c:2004 lib/verity/verity.c:111
+msgid "Unsupported VERITY block size."
+msgstr "Niet-ondersteunde VERITY-blokgrootte."
+
+#: lib/setup.c:2009 lib/verity/verity.c:75
+msgid "Unsupported VERITY hash offset."
+msgstr "Niet-ondersteunde VERITY-hashgegevenspositie."
+
+#: lib/setup.c:2014
+msgid "Unsupported VERITY FEC offset."
+msgstr "Niet-ondersteunde VERITY-FEC-gegevenspositie."
+
+#: lib/setup.c:2038
+msgid "Data area overlaps with hash area."
+msgstr "Overlapping tussen datagedeelte en hashgedeelte."
+
+#: lib/setup.c:2063
+msgid "Hash area overlaps with FEC area."
+msgstr "Overlapping tussen hashgedeelte en FEC-gedeelte."
+
+#: lib/setup.c:2070
+msgid "Data area overlaps with FEC area."
+msgstr "Overlapping tussen datagedeelte en FEC-gedeelte."
+
+#: lib/setup.c:2206
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr ""
+
+#: lib/setup.c:2284
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Onbekend versleutelingsapparaattype %s aangevraagd."
+
+#: lib/setup.c:2548 lib/setup.c:2620 lib/setup.c:2633
+#, fuzzy, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Kan koptekst op apparaat %s niet wissen.\n"
+
+#: lib/setup.c:2554 lib/setup.c:2639 lib/luks2/luks2_reencrypt.c:2408
+#: lib/luks2/luks2_reencrypt.c:2737
+#, fuzzy, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Kan koptekst op apparaat %s niet wissen.\n"
+
+#: lib/setup.c:2659
+msgid "Crypt devices mismatch."
+msgstr ""
+
+#: lib/setup.c:2696 lib/setup.c:2701 lib/luks2/luks2_reencrypt.c:2054
+#: lib/luks2/luks2_reencrypt.c:3145
+#, fuzzy, c-format
+msgid "Failed to reload device %s."
+msgstr "Kan apparaat niet lezen: %s.\n"
+
+#: lib/setup.c:2706 lib/setup.c:2711 lib/luks2/luks2_reencrypt.c:2025
+#: lib/luks2/luks2_reencrypt.c:2032
+#, fuzzy, c-format
+msgid "Failed to suspend device %s."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: lib/setup.c:2716 lib/luks2/luks2_reencrypt.c:2039
+#: lib/luks2/luks2_reencrypt.c:3080 lib/luks2/luks2_reencrypt.c:3149
+#, fuzzy, c-format
+msgid "Failed to resume device %s."
+msgstr "Kan apparaat niet lezen: %s.\n"
+
+#: lib/setup.c:2730
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr ""
+
+#: lib/setup.c:2733 lib/setup.c:2735
+#, fuzzy, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Kan geen map voor de apparaatstoewijzer verkrijgen."
+
+#: lib/setup.c:2807
+msgid "Cannot resize loop device."
+msgstr "Kan grootte van loopback-apparaat niet aanpassen."
+
+#: lib/setup.c:2880
+msgid "Do you really want to change UUID of device?"
+msgstr "Bent u zeker dat u het UUID van het apparaat wilt wijzigen?"
+
+#: lib/setup.c:2956
+#, fuzzy
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Reservekopiebestand bevat geen geldige LUKS-koptekst.\n"
+
+#: lib/setup.c:3056
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Opslagmedium %s is niet actief."
+
+#: lib/setup.c:3067
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Opslagmedium %s is reeds geschorst."
+
+#: lib/setup.c:3080
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Opschorten wordt niet ondersteund voor apparaat %s."
+
+#: lib/setup.c:3082
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Fout bij het opschorten van apparaat %s."
+
+#: lib/setup.c:3115 lib/setup.c:3182 lib/setup.c:3265
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Opslagmedium %s is niet geschorst."
+
+#: lib/setup.c:3144
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Hervatting wordt niet ondersteund voor apparaat %s."
+
+#: lib/setup.c:3146 lib/setup.c:3214 lib/setup.c:3295
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Fout bij het hervatten van apparaat %s."
+
+#: lib/setup.c:3280 lib/setup.c:3646 lib/setup.c:4307 lib/setup.c:4320
+#: lib/setup.c:4328 lib/setup.c:4341 lib/setup.c:4691 lib/setup.c:5834
+msgid "Volume key does not match the volume."
+msgstr "Sleutel tot opslagmedium komt niet overeen met het opslagmedium."
+
+#: lib/setup.c:3341 lib/setup.c:3529
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Kan geen sleutelplaats toevoegen, alle plaatsen zijn uitgeschakeld en er is geen sleutel tot het opslagmedium voorzien."
+
+#: lib/setup.c:3481
+msgid "Failed to swap new key slot."
+msgstr "Kan nieuwe sleutelplaats niet verwisselen."
+
+#: lib/setup.c:3667
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Sleutelplaats %d is ongeldig."
+
+#: lib/setup.c:3673 src/cryptsetup.c:1577 src/cryptsetup.c:1922
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Sleutelplaats %d is niet in gebruik."
+
+#: lib/setup.c:3692
+msgid "Device header overlaps with data area."
+msgstr "Overlapping tussen apparaatskoptekst en hashgedeelte."
+
+#: lib/setup.c:3979
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr ""
+
+#: lib/setup.c:3981 lib/luks2/luks2_json_metadata.c:2239
+#: lib/luks2/luks2_reencrypt.c:2836
+#, fuzzy
+msgid "Failed to get reencryption lock."
+msgstr "Kan herencryptie-logbestand niet lezen.\n"
+
+#: lib/setup.c:3994 lib/luks2/luks2_reencrypt.c:2855
+#, fuzzy
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Kan herencryptie-logbestand niet openen.\n"
+
+#: lib/setup.c:4125 lib/setup.c:4377
+msgid "Device type is not properly initialized."
+msgstr "Apparaatstype is niet behoorlijk geïnitialiseerd."
+
+#: lib/setup.c:4169
+#, fuzzy, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Kan apparaat %s niet formatteren; het is nog steeds actief.\n"
+
+#: lib/setup.c:4172
+#, c-format
+msgid "Device %s already exists."
+msgstr "Apparaat %s bestaat reeds."
+
+#: lib/setup.c:4294
+msgid "Incorrect volume key specified for plain device."
+msgstr "Incorrecte sleutel tot het opslagmedium voor normaal apparaat verschaft."
+
+#: lib/setup.c:4403
+msgid "Incorrect root hash specified for verity device."
+msgstr "Incorrecte root-hash voor het VERITY-apparaat opgegeven."
+
+#: lib/setup.c:4410
+msgid "Root hash signature required."
+msgstr ""
+
+#: lib/setup.c:4419
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr ""
+
+#: lib/setup.c:4436 lib/setup.c:5910
+#, fuzzy
+msgid "Failed to load key in kernel keyring."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: lib/setup.c:4489 lib/setup.c:4505 lib/luks2/luks2_json_metadata.c:2292
+#: src/cryptsetup.c:2597
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Apparaat %s is nog in gebruik."
+
+#: lib/setup.c:4514
+#, c-format
+msgid "Invalid device %s."
+msgstr "Ongeldig apparaat %s."
+
+#: lib/setup.c:4630
+msgid "Volume key buffer too small."
+msgstr "Sleutelbuffer van het opslagmedium is te klein."
+
+#: lib/setup.c:4638
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Kan sleutel tot het opslagmedium voor normaal apparaat niet ophalen."
+
+#: lib/setup.c:4655
+#, fuzzy
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Incorrecte root-hash voor het VERITY-apparaat opgegeven.\n"
+
+#: lib/setup.c:4657
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Deze operatie wordt niet ondersteund voor versleutelapparaat %s."
+
+#: lib/setup.c:4863
+msgid "Dump operation is not supported for this device type."
+msgstr "Dump-operatie wordt niet ondersteund voor dit apparaatstype."
+
+#: lib/setup.c:5188
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr ""
+
+#: lib/setup.c:5470
+#, fuzzy, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Kan apparaat %s niet formatteren; het is nog steeds actief.\n"
+
+#: lib/setup.c:5767
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr ""
+
+#: lib/setup.c:5840
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr ""
+
+#: lib/setup.c:5846
+#, fuzzy, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Kan nieuwe sleutelplaats niet verwisselen.\n"
+
+#: lib/setup.c:5977
+#, fuzzy
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Deze operatie wordt niet ondersteund voor dit apparaatstype.\n"
+
+#: lib/setup.c:5987 lib/luks2/luks2_reencrypt.c:2952
+#, fuzzy, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Lezen uit sleutelopslag is mislukt.\n"
+
+#: lib/setup.c:6011
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr ""
+
+#: lib/utils.c:81
+msgid "Cannot get process priority."
+msgstr "Kan geen procesprioriteit verkrijgen."
+
+#: lib/utils.c:95
+msgid "Cannot unlock memory."
+msgstr "Kan geheugen niet ontgrendelen."
+
+#: lib/utils.c:169 lib/tcrypt/tcrypt.c:498
+msgid "Failed to open key file."
+msgstr "Openen van sleutelbestand is mislukt."
+
+#: lib/utils.c:174
+#, fuzzy
+msgid "Cannot read keyfile from a terminal."
+msgstr "Kan sleutelbestand %s niet lezen.\n"
+
+#: lib/utils.c:191
+msgid "Failed to stat key file."
+msgstr "Kan status van sleutelbestand niet opvragen."
+
+#: lib/utils.c:199 lib/utils.c:220
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Kan niet zoeken tot aan het aangevraagde sleutelbestand."
+
+#: lib/utils.c:214 lib/utils.c:229 src/utils_password.c:188
+#: src/utils_password.c:201
+msgid "Out of memory while reading passphrase."
+msgstr "Geen geheugen meer beschikbaar bij lezen van wachtwoord."
+
+#: lib/utils.c:249
+msgid "Error reading passphrase."
+msgstr "Fout bij lezen van wachtwoord."
+
+#: lib/utils.c:266
+msgid "Nothing to read on input."
+msgstr ""
+
+#: lib/utils.c:273
+msgid "Maximum keyfile size exceeded."
+msgstr "Maximum sleutelbestandsgrootte overschreden."
+
+#: lib/utils.c:278
+msgid "Cannot read requested amount of data."
+msgstr "Kan aangevraagde hoeveelheid data niet lezen."
+
+#: lib/utils_device.c:188 lib/utils_storage_wrappers.c:111
+#: lib/luks1/keyencryption.c:92
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Apparaat %s bestaat niet of toegang is geweigerd."
+
+#: lib/utils_device.c:198
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Apparaat %s is niet compatibel."
+
+#: lib/utils_device.c:643
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Apparaat %s is te klein. Minstens %<PRIu64> bytes zijn vereist."
+
+#: lib/utils_device.c:724
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Kan apparaat %s niet gebruiken; het is nog actief (reeds toegewezen of aangekoppeld)."
+
+#: lib/utils_device.c:728
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Kan apparaat %s niet gebruiken: toestemming geweigerd."
+
+#: lib/utils_device.c:731
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Kan geen informatie verkrijgen over apparaat %s."
+
+#: lib/utils_device.c:754
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Kan geen loopback-apparaat gebruiken, uitvoering als non-root gebruiker."
+
+#: lib/utils_device.c:764
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Vastmaken loopback-apparaat gefaald (loop-apparaat met autoclear-vlag is vereist)."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "De aangevraagde gegevenspositie valt buiten de werkelijke grootte van apparaat %s."
+
+#: lib/utils_device.c:818
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Apparaat %s heeft grootte nul."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr ""
+
+#: lib/utils_pbkdf.c:111
+#, fuzzy, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Aangevraagde LUKS-hash %s wordt niet ondersteund.\n"
+
+#: lib/utils_pbkdf.c:122
+#, fuzzy
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Aangevraagde LUKS-hash %s wordt niet ondersteund.\n"
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr ""
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr ""
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr ""
+
+#: lib/utils_benchmark.c:166
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr ""
+
+#: lib/utils_benchmark.c:185
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Niet-compatibele PBKDF2-opties (met hash-algoritme %s in gebruik)."
+
+#: lib/utils_benchmark.c:205
+#, fuzzy
+msgid "Not compatible PBKDF options."
+msgstr "Niet-compatibele PBKDF2-opties (met hash-algoritme %s in gebruik).\n"
+
+#: lib/utils_device_locking.c:103
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr ""
+
+#: lib/utils_device_locking.c:110
+#, c-format
+msgid "WARNING: Locking directory %s/%s is missing!\n"
+msgstr ""
+
+#: lib/utils_device_locking.c:120
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr ""
+
+#: lib/utils_wipe.c:185 src/cryptsetup_reencrypt.c:934
+#: src/cryptsetup_reencrypt.c:1018
+msgid "Cannot seek to device offset."
+msgstr "Onmogelijk te zoeken tot startplaats van apparaat."
+
+#: lib/utils_wipe.c:209
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:40
+#, fuzzy, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Kan dm-crypt sleuteltoewijzing niet instellen voor apparaat %s.\n"
+"Kijk na of de kernel versleutelalgoritme %s ondersteunt (bekijk syslog voor meer informatie).\n"
+
+#: lib/luks1/keyencryption.c:45
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "In XTS-modus moet de sleutelgrootte 256 of 512 bits zijn."
+
+#: lib/luks1/keyencryption.c:47
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:98 lib/luks1/keymanage.c:345
+#: lib/luks1/keymanage.c:636 lib/luks1/keymanage.c:1079
+#: lib/luks2/luks2_json_metadata.c:1253 lib/luks2/luks2_keyslot.c:734
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Kan apparaat %s niet beschrijven: toestemming geweigerd."
+
+#: lib/luks1/keyencryption.c:121
+msgid "Failed to open temporary keystore device."
+msgstr "Openen van het tijdelijke sleutelopslagapparaat is mislukt."
+
+#: lib/luks1/keyencryption.c:128
+msgid "Failed to access temporary keystore device."
+msgstr "Kan geen toegang verkrijgen tot tijdelijk sleutelopslagapparaat."
+
+#: lib/luks1/keyencryption.c:201 lib/luks2/luks2_keyslot_luks2.c:60
+#: lib/luks2/luks2_keyslot_luks2.c:78 lib/luks2/luks2_keyslot_reenc.c:134
+msgid "IO error while encrypting keyslot."
+msgstr "Invoer/uitvoerfout tijdens het versleutelen van de sleutelplaats."
+
+#: lib/luks1/keyencryption.c:247 lib/luks1/keymanage.c:348
+#: lib/luks1/keymanage.c:589 lib/luks1/keymanage.c:639 lib/tcrypt/tcrypt.c:661
+#: lib/verity/verity.c:81 lib/verity/verity.c:179 lib/verity/verity_hash.c:311
+#: lib/verity/verity_hash.c:322 lib/verity/verity_hash.c:342
+#: lib/verity/verity_fec.c:242 lib/verity/verity_fec.c:254
+#: lib/verity/verity_fec.c:259 lib/luks2/luks2_json_metadata.c:1256
+#: src/cryptsetup_reencrypt.c:205
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Kan apparaat %s niet openen."
+
+#: lib/luks1/keyencryption.c:258 lib/luks2/luks2_keyslot_luks2.c:137
+msgid "IO error while decrypting keyslot."
+msgstr "Invoer/uitvoerfout tijdens het ontsleutelen van de sleutelplaats."
+
+#: lib/luks1/keymanage.c:111
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Apparaat %s is te klein. (LUKS1 vereist minstens %<PRIu64> bytes.)"
+
+#: lib/luks1/keymanage.c:132 lib/luks1/keymanage.c:140
+#: lib/luks1/keymanage.c:152 lib/luks1/keymanage.c:163
+#: lib/luks1/keymanage.c:175
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "LUKS-sleutelplaats %u is ongeldig."
+
+#: lib/luks1/keymanage.c:229 lib/luks1/keymanage.c:473
+#: lib/luks2/luks2_json_metadata.c:1084 src/cryptsetup.c:1438
+#: src/cryptsetup.c:1564 src/cryptsetup.c:1621 src/cryptsetup.c:1677
+#: src/cryptsetup.c:1744 src/cryptsetup.c:1847 src/cryptsetup.c:1911
+#: src/cryptsetup.c:2071 src/cryptsetup.c:2264 src/cryptsetup.c:2324
+#: src/cryptsetup.c:2390 src/cryptsetup.c:2554 src/cryptsetup.c:3204
+#: src/cryptsetup.c:3213 src/cryptsetup_reencrypt.c:1381
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Apparaat %s is geen geldig LUKS-apparaat."
+
+#: lib/luks1/keymanage.c:247 lib/luks2/luks2_json_metadata.c:1101
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Aangevraagd reservekopiebestand %s van koptekst bestaat reeds."
+
+#: lib/luks1/keymanage.c:249 lib/luks2/luks2_json_metadata.c:1103
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Kan reservekopiebestand %s van koptekst niet aanmaken."
+
+#: lib/luks1/keymanage.c:256 lib/luks2/luks2_json_metadata.c:1110
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Kan reservekopiebestand %s van koptekst niet schrijven."
+
+#: lib/luks1/keymanage.c:287 lib/luks2/luks2_json_metadata.c:1162
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Reservekopiebestand bevat geen geldige LUKS-koptekst."
+
+#: lib/luks1/keymanage.c:300 lib/luks1/keymanage.c:550
+#: lib/luks2/luks2_json_metadata.c:1183
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Kan reservekopiebestand %s van koptekst niet openen."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1191
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Kan reservekopiebestand %s van koptekst niet lezen."
+
+#: lib/luks1/keymanage.c:318
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Verschillende gegevenspositie of sleutelgrootte in apparaat en reservekopie; herstelling is mislukt."
+
+#: lib/luks1/keymanage.c:326
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Apparaat %s %s%s"
+
+#: lib/luks1/keymanage.c:327
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "bevat geen LUKS-koptekst. Het vervangen van de koptekst kan gegevens op het apparaat vernietigen."
+
+#: lib/luks1/keymanage.c:328
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "bevat reeds een LUKS-koptekst. Het vervangen van de koptekst zal bestaande sleutelplaatsen vernietigen."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1225
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"WAARSCHUWING: originele apparaatkoptekst heeft een ander UUID dan de reservekopie!"
+
+#: lib/luks1/keymanage.c:376
+msgid "Non standard key size, manual repair required."
+msgstr "Niet-standaard sleutelgrootte, handmatige herstelling is vereist."
+
+#: lib/luks1/keymanage.c:381
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Niet-standaard sleutelplaatsuitlijning, handmatige herstelling is vereist."
+
+#: lib/luks1/keymanage.c:391
+msgid "Repairing keyslots."
+msgstr "Sleutelplaatsen worden hersteld."
+
+#: lib/luks1/keymanage.c:410
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Sleutelplaats %i: gegevenspositie hersteld (%u -> %u)."
+
+#: lib/luks1/keymanage.c:418
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Sleutelplaats %i: fragmenten hersteld (%u -> %u)."
+
+#: lib/luks1/keymanage.c:427
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Sleutelplaats %i: valse partitiehandtekening."
+
+#: lib/luks1/keymanage.c:432
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Sleutelplaats %i: salt uitgewist."
+
+#: lib/luks1/keymanage.c:449
+msgid "Writing LUKS header to disk."
+msgstr "LUKS-koptekst wordt naar schijf geschreven."
+
+#: lib/luks1/keymanage.c:454
+msgid "Repair failed."
+msgstr "Herstelling is mislukt."
+
+#: lib/luks1/keymanage.c:482 lib/luks1/keymanage.c:751
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Aangevraagde LUKS-hash %s wordt niet ondersteund."
+
+#: lib/luks1/keymanage.c:510 src/cryptsetup.c:1144
+msgid "No known problems detected for LUKS header."
+msgstr "Geen gekende problemen gevonden bij LUKS-koptekst."
+
+#: lib/luks1/keymanage.c:661
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Fout bij het bijwerken van LUKS-koptekst op apparaat %s."
+
+#: lib/luks1/keymanage.c:669
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Fout bij het herlezen van LUKS-koptekst na bijwerken van apparaat %s."
+
+#: lib/luks1/keymanage.c:745
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "De datagegevenspositie voor een aparte LUKS-koptekst moet of 0 zijn, of groter zijn dan de koptekstgrootte."
+
+#: lib/luks1/keymanage.c:756 lib/luks1/keymanage.c:826
+#: lib/luks2/luks2_json_format.c:283 lib/luks2/luks2_json_metadata.c:1002
+#: src/cryptsetup.c:2717
+msgid "Wrong LUKS UUID format provided."
+msgstr "Verkeerd LUKS UUID-formaat verschaft."
+
+#: lib/luks1/keymanage.c:779
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Kan LUKS-koptekst niet aanmaken: lezen van random salt is mislukt."
+
+#: lib/luks1/keymanage.c:805
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Kan LUKS-koptekst niet aanmaken: koptekst-extract is mislukt (met %s-hash)."
+
+#: lib/luks1/keymanage.c:849
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Sleutelplaats %d is actief; ruim eerst op."
+
+#: lib/luks1/keymanage.c:855
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Inhoud van sleutelplaats %d bevat te weinig fragmenten. Koptekstmanipulatie?"
+
+#: lib/luks1/keymanage.c:1065
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Sleutelplaats %d is ongeldig, selecteer een sleutelplaats tussen 0 en %d."
+
+#: lib/luks1/keymanage.c:1083 lib/luks2/luks2_keyslot.c:738
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Kan apparaat %s niet wissen."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Nog niet ondersteund GPG-versleuteld sleutelbestand gevonden."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Gebruik gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Onverenigbaar loop-AES-sleutelbestand gevonden."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Toewijzingen compatibel met loop-AES worden niet ondersteund door de kernel."
+
+#: lib/tcrypt/tcrypt.c:505
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Fout bij het lezen van sleutelbestand %s."
+
+#: lib/tcrypt/tcrypt.c:545
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%d) exceeded."
+msgstr "Maximum TCRYPT-wachtwoorlengte (%d) overschreden."
+
+#: lib/tcrypt/tcrypt.c:586
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "PBKDF2 hash-algoritme %s is niet beschikbaar, wordt overgeslaan."
+
+#: lib/tcrypt/tcrypt.c:602 src/cryptsetup.c:1021
+msgid "Required kernel crypto interface not available."
+msgstr "Benodigde kernel cryptografie-interface is niet beschikbaar."
+
+#: lib/tcrypt/tcrypt.c:604 src/cryptsetup.c:1023
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Kijk na of kernelmodule algif_skcipher geladen is."
+
+#: lib/tcrypt/tcrypt.c:744
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Activatie wordt niet ondersteund voor %d sectorgrootte."
+
+#: lib/tcrypt/tcrypt.c:750
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Activatie voor deze TCRYPT-legacymodus wordt niet ondersteund door de kernel."
+
+#: lib/tcrypt/tcrypt.c:784
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "TCRYPT-systeemversleuteling voor partitie %s wordt geactiveerd."
+
+#: lib/tcrypt/tcrypt.c:862
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Toewijzingen compatibel met TCRYPT worden niet ondersteund door de kernel."
+
+#: lib/tcrypt/tcrypt.c:1084
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Deze functie wordt niet ondersteund zonder TCRYPT-koptekst."
+
+#: lib/bitlk/bitlk.c:305
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:352
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:357
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:371
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:451
+#, fuzzy, c-format
+msgid "Failed to read BITLK signature from %s."
+msgstr "Lezen uit sleutelopslag is mislukt.\n"
+
+#: lib/bitlk/bitlk.c:457
+msgid "BITLK version 1 is currently not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:463
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:475
+msgid "Invalid or unknown signature for BITLK device."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:483
+#, fuzzy, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Lezen uit sleutelopslag is mislukt.\n"
+
+#: lib/bitlk/bitlk.c:499
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:543
+#, fuzzy
+msgid "Unknown or unsupported encryption type."
+msgstr "UUID wordt niet ondersteund voor dit encryptietype.\n"
+
+#: lib/bitlk/bitlk.c:576
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:863
+#, fuzzy
+msgid "This operation is not supported."
+msgstr "Deze operatie wordt niet ondersteund voor versleutelapparaat %s.\n"
+
+#: lib/bitlk/bitlk.c:871
+#, fuzzy
+msgid "Wrong key size."
+msgstr "Ongeldige sleutelgrootte.\n"
+
+#: lib/bitlk/bitlk.c:999
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1132
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr ""
+
+#: lib/bitlk/bitlk.c:1136
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr ""
+
+#: lib/verity/verity.c:69 lib/verity/verity.c:172
+#, fuzzy, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "VERITY-apparaat %s gebruikt geen on-disk koptekst.\n"
+
+#: lib/verity/verity.c:91
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Apparaat %s is geen geldig VERITY-apparaat."
+
+#: lib/verity/verity.c:98
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Niet-ondersteunde VERITY-versie %d."
+
+#: lib/verity/verity.c:129
+msgid "VERITY header corrupted."
+msgstr "VERITY-koptekst beschadigd."
+
+#: lib/verity/verity.c:166
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Verkeerd VERITY UUID-formaat verschaft op apparaat %s."
+
+#: lib/verity/verity.c:199
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Fout bij het bijwerken van VERITY-koptekst op apparaat %s."
+
+#: lib/verity/verity.c:257
+#, fuzzy
+msgid "Root hash signature verification is not supported."
+msgstr "Aangevraagd hash-algoritme %s wordt niet ondersteund.\n"
+
+#: lib/verity/verity.c:268
+msgid "Errors cannot be repaired with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:270
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:309
+#, fuzzy
+msgid "Kernel does not support dm-verity mapping."
+msgstr "dm-verity toewijzingen niet ondersteund door kernel.\n"
+
+#: lib/verity/verity.c:313
+#, fuzzy
+msgid "Kernel does not support dm-verity signature option."
+msgstr "dm-verity toewijzingen niet ondersteund door kernel.\n"
+
+#: lib/verity/verity.c:324
+msgid "Verity device detected corruption after activation."
+msgstr "VERITY-apparaat ontdekte beschadiging na activatie."
+
+#: lib/verity/verity_hash.c:59
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Reservegebied is niet ingesteld op positie %<PRIu64>."
+
+#: lib/verity/verity_hash.c:163 lib/verity/verity_hash.c:290
+#: lib/verity/verity_hash.c:303
+msgid "Device offset overflow."
+msgstr "Overloop van apparaatsgegevenspositie."
+
+#: lib/verity/verity_hash.c:203
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Controle gefaald op positie %<PRIu64>."
+
+#: lib/verity/verity_hash.c:276
+msgid "Invalid size parameters for verity device."
+msgstr "Ongeldige grootteparameters voor VERITY-apparaat."
+
+#: lib/verity/verity_hash.c:296
+msgid "Hash area overflow."
+msgstr ""
+
+#: lib/verity/verity_hash.c:373
+msgid "Verification of data area failed."
+msgstr "Controle van gegevensgebied gefaald."
+
+#: lib/verity/verity_hash.c:378
+msgid "Verification of root hash failed."
+msgstr "Controle van root-hash gefaald."
+
+#: lib/verity/verity_hash.c:384
+msgid "Input/output error while creating hash area."
+msgstr "Invoer/uitvoerfout bij het aanmaken van hash-gebied."
+
+#: lib/verity/verity_hash.c:386
+msgid "Creation of hash area failed."
+msgstr "Creatie hash-gebied gefaald."
+
+#: lib/verity/verity_hash.c:433
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "WAARSCHUWING: Kernel kan apparaat niet activeren als de gegevensblokgrootte groter is dan de paginagrootte (%u)."
+
+#: lib/verity/verity_fec.c:132
+msgid "Failed to allocate RS context."
+msgstr ""
+
+#: lib/verity/verity_fec.c:147
+#, fuzzy
+msgid "Failed to allocate buffer."
+msgstr "Kan status van sleutelbestand niet opvragen.\n"
+
+#: lib/verity/verity_fec.c:157
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr ""
+
+#: lib/verity/verity_fec.c:170
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:178
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:189
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr ""
+
+#: lib/verity/verity_fec.c:224
+msgid "Block sizes must match for FEC."
+msgstr ""
+
+#: lib/verity/verity_fec.c:230
+msgid "Invalid number of parity bytes."
+msgstr ""
+
+#: lib/verity/verity_fec.c:266
+#, fuzzy, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Openen van het tijdelijke sleutelopslagapparaat is mislukt.\n"
+
+#: lib/integrity/integrity.c:268 lib/integrity/integrity.c:339
+#, fuzzy
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "dm-verity toewijzingen niet ondersteund door kernel.\n"
+
+#: lib/integrity/integrity.c:274
+#, fuzzy
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "dm-verity toewijzingen niet ondersteund door kernel.\n"
+
+#: lib/luks2/luks2_disk_metadata.c:383 lib/luks2/luks2_json_metadata.c:959
+#: lib/luks2/luks2_json_metadata.c:1245
+#, fuzzy, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Kan geen toegang verkrijgen tot tijdelijk sleutelopslagapparaat.\n"
+
+#: lib/luks2/luks2_disk_metadata.c:392
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr ""
+
+#: lib/luks2/luks2_disk_metadata.c:691 lib/luks2/luks2_disk_metadata.c:712
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+
+#: lib/luks2/luks2_json_format.c:227
+#, fuzzy
+msgid "Requested data offset is too small."
+msgstr "Apparaat %s is te klein.\n"
+
+#: lib/luks2/luks2_json_format.c:271
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:946 lib/luks2/luks2_json_metadata.c:1075
+#: lib/luks2/luks2_json_metadata.c:1151 lib/luks2/luks2_keyslot_luks2.c:92
+#: lib/luks2/luks2_keyslot_luks2.c:114
+#, fuzzy, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Kan geen toegang verkrijgen tot tijdelijk sleutelopslagapparaat.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1168
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1209
+#, fuzzy
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Verschillende gegevenspositie of sleutelgrootte in apparaat en reservekopie; herstelling is mislukt.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1215
+#, fuzzy
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Verschillende gegevenspositie of sleutelgrootte in apparaat en reservekopie; herstelling is mislukt.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1222
+#, fuzzy, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Apparaat %s %s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1223
+#, fuzzy
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "bevat geen LUKS-koptekst. Het vervangen van de koptekst kan gegevens op het apparaat vernietigen."
+
+#: lib/luks2/luks2_json_metadata.c:1224
+#, fuzzy
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "bevat reeds een LUKS-koptekst. Het vervangen van de koptekst zal bestaande sleutelplaatsen vernietigen."
+
+#: lib/luks2/luks2_json_metadata.c:1226
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1228
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1324
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2011 lib/luks2/luks2_reencrypt.c:1746
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2023 lib/luks2/luks2_reencrypt.c:1764
+#, fuzzy
+msgid "Failed to set dm-crypt segment."
+msgstr "Kan status van sleutelbestand niet opvragen.\n"
+
+#: lib/luks2/luks2_json_metadata.c:2029 lib/luks2/luks2_reencrypt.c:1770
+msgid "Failed to set dm-linear segment."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2156
+msgid "Unsupported device integrity configuration."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2237
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2248 lib/luks2/luks2_reencrypt.c:3190
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2328
+msgid "Failed to read LUKS2 requirements."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2335
+msgid "Unmet LUKS2 requirements detected."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2343
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:2345
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot.c:547 lib/luks2/luks2_keyslot.c:584
+msgid "Not enough available memory to open a keyslot."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot.c:549 lib/luks2/luks2_keyslot.c:586
+#, fuzzy
+msgid "Keyslot open failed."
+msgstr "Sleutelplaats %d is geverifieerd.\n"
+
+#: lib/luks2/luks2_keyslot_luks2.c:53 lib/luks2/luks2_keyslot_luks2.c:108
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr ""
+
+#: lib/luks2/luks2_keyslot_luks2.c:480
+#, fuzzy
+msgid "No space for new keyslot."
+msgstr "Kan nieuwe sleutelplaats niet verwisselen.\n"
+
+#: lib/luks2/luks2_luks1_convert.c:481
+#, fuzzy, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Kan wachtwoordkwaliteit niet nakijken: %s\n"
+
+#: lib/luks2/luks2_luks1_convert.c:507
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:547
+msgid "Unable to move keyslot area. Not enough space."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:590 lib/luks2/luks2_luks1_convert.c:872
+#, fuzzy
+msgid "Unable to move keyslot area."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: lib/luks2/luks2_luks1_convert.c:682
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:690
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:702
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:710
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:724
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:729
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:734
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:892
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:897
+#, fuzzy, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Verkleiningsgrootte moet een meervoud zijn van de 512 bytes-grote sector."
+
+#: lib/luks2/luks2_reencrypt.c:941
+#, fuzzy, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Niet-ondersteunde LUKS-versie %d.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1158 lib/luks2/luks2_reencrypt.c:1313
+#: lib/luks2/luks2_reencrypt.c:1396 lib/luks2/luks2_reencrypt.c:1430
+#: lib/luks2/luks2_reencrypt.c:3030
+#, fuzzy
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1172 lib/luks2/luks2_reencrypt.c:1291
+#, fuzzy
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1340
+#, fuzzy
+msgid "Failed to read checksums for current hotzone."
+msgstr "Lezen uit sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1347 lib/luks2/luks2_reencrypt.c:3038
+#, fuzzy, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Reservegebied is niet ingesteld op positie %<PRIu64>.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1366
+#, fuzzy, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Lezen uit sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1372
+#, fuzzy, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1867
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1965
+#, fuzzy, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Kan geen toegang verkrijgen tot tijdelijk sleutelopslagapparaat.\n"
+
+#: lib/luks2/luks2_reencrypt.c:1982
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:1989
+#, fuzzy, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Openen van het tijdelijke sleutelopslagapparaat is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:2060
+msgid "Failed to refresh reencryption devices stack."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2216
+#, fuzzy
+msgid "Failed to set new keyslots area size."
+msgstr "Kan nieuwe sleutelplaats niet verwisselen.\n"
+
+#: lib/luks2/luks2_reencrypt.c:2318
+#, c-format
+msgid "Data shift is not aligned to requested encryption sector size (%<PRIu32> bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2339
+#, c-format
+msgid "Data device is not aligned to requested encryption sector size (%<PRIu32> bytes)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2360
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2366 lib/luks2/luks2_reencrypt.c:2779
+#: lib/luks2/luks2_reencrypt.c:2800
+#, fuzzy, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Kan apparaat %s niet gebruiken; het is nog actief (reeds toegewezen of aangekoppeld).\n"
+
+#: lib/luks2/luks2_reencrypt.c:2534
+#, fuzzy
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Sleutel niet wijzigen; gegevensgebied wordt niet opnieuw versleuteld."
+
+#: lib/luks2/luks2_reencrypt.c:2540 lib/luks2/luks2_reencrypt.c:3295
+msgid "Failed to load LUKS2 reencryption context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2619
+#, fuzzy
+msgid "Failed to get reencryption state."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:2623
+#, fuzzy
+msgid "Device is not in reencryption."
+msgstr "Apparaat %s is niet actief.\n"
+
+#: lib/luks2/luks2_reencrypt.c:2630
+msgid "Reencryption process is already running."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2632
+#, fuzzy
+msgid "Failed to acquire reencryption lock."
+msgstr "Kan herencryptie-logbestand niet lezen.\n"
+
+#: lib/luks2/luks2_reencrypt.c:2650
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2750
+msgid "Active device size and requested reencryption size don't match."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2764
+msgid "Illegal device size requested in reencryption parameters."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2834
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2906
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:2913
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3004
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3046
+#, fuzzy
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Kan herencryptie-logbestand niet schrijven.\n"
+
+#: lib/luks2/luks2_reencrypt.c:3053
+#, fuzzy
+msgid "Decryption failed."
+msgstr "Herstelling is mislukt."
+
+#: lib/luks2/luks2_reencrypt.c:3058
+#, fuzzy, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:3063
+#, fuzzy
+msgid "Failed to sync data."
+msgstr "Kan status van sleutelbestand niet opvragen.\n"
+
+#: lib/luks2/luks2_reencrypt.c:3071
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3138
+#, fuzzy
+msgid "Failed to write LUKS2 metadata."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: lib/luks2/luks2_reencrypt.c:3161
+msgid "Failed to wipe backup segment data."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3174
+msgid "Failed to disable reencryption requirement flag."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3182
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3191
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3240
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3246
+msgid "Missing or invalid reencrypt context."
+msgstr ""
+
+#: lib/luks2/luks2_reencrypt.c:3253
+#, fuzzy
+msgid "Failed to initialize reencryption device stack."
+msgstr "Kan versleutelings-backend niet initialiseren.\n"
+
+#: lib/luks2/luks2_reencrypt.c:3272 lib/luks2/luks2_reencrypt.c:3308
+#, fuzzy
+msgid "Failed to update reencryption context."
+msgstr "Kan herencryptie-logbestand niet openen.\n"
+
+#: lib/luks2/luks2_token.c:262
+msgid "No free token slot."
+msgstr ""
+
+#: lib/luks2/luks2_token.c:269
+#, fuzzy, c-format
+msgid "Failed to create builtin token %s."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: src/cryptsetup.c:163
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Kan geen wachtwoordverificatie uitvoeren op invoer van buiten de terminal."
+
+#: src/cryptsetup.c:216
+#, fuzzy
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Deze operatie wordt enkel ondersteund voor LUKS-apparaten.\n"
+
+#: src/cryptsetup.c:246 src/cryptsetup.c:955 src/cryptsetup.c:1275
+#: src/cryptsetup.c:3078 src/cryptsetup_reencrypt.c:716
+#: src/cryptsetup_reencrypt.c:786
+msgid "No known cipher specification pattern detected."
+msgstr "Geen bekend specificatiepatroon voor het sleutelalgoritme gevonden."
+
+#: src/cryptsetup.c:254
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "WAARSCHUWING: In normale modus met opgegeven sleutelbestand wordt de --hash-parameter genegeerd.\n"
+
+#: src/cryptsetup.c:262
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "WAARSCHUWING: De optie --keyfile-size wordt genegeerd, de leesgrootte is gelijk aan de encryptiesleutelgrootte.\n"
+
+#: src/cryptsetup.c:302
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr ""
+
+#: src/cryptsetup.c:308 src/cryptsetup.c:1101 src/cryptsetup.c:1153
+#: src/cryptsetup.c:1252 src/cryptsetup.c:1325 src/cryptsetup.c:1979
+#: src/cryptsetup.c:2615 src/cryptsetup.c:2738 src/integritysetup.c:232
+msgid "Operation aborted.\n"
+msgstr ""
+
+#: src/cryptsetup.c:376
+msgid "Option --key-file is required."
+msgstr "Optie --key-file is vereist."
+
+#: src/cryptsetup.c:429
+msgid "Enter VeraCrypt PIM: "
+msgstr ""
+
+#: src/cryptsetup.c:438
+msgid "Invalid PIM value: parse error."
+msgstr ""
+
+#: src/cryptsetup.c:441
+#, fuzzy
+msgid "Invalid PIM value: 0."
+msgstr "Ongeldig apparaat %s.\n"
+
+#: src/cryptsetup.c:444
+msgid "Invalid PIM value: outside of range."
+msgstr ""
+
+#: src/cryptsetup.c:467
+msgid "No device header detected with this passphrase."
+msgstr "Geen apparaatkoptekst beschikbaar met dit wachtwoord."
+
+#: src/cryptsetup.c:536
+#, fuzzy, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Apparaat %s is geen geldig LUKS-apparaat.\n"
+
+#: src/cryptsetup.c:571 src/cryptsetup.c:2006
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Dump van koptekst met sleutel tot het opslagmedium bevat gevoelige informatie\n"
+"die zonder wachtwoord toegang verschaft tot versleutelde partities.\n"
+"De dump zou steeds versleuteld en op een veilige plaats bewaard moeten worden."
+
+#: src/cryptsetup.c:668
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr ""
+
+#: src/cryptsetup.c:696
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr ""
+
+#: src/cryptsetup.c:833
+#, fuzzy
+msgid "Benchmark interrupted."
+msgstr "versleutelalgoritme benchmarken"
+
+#: src/cryptsetup.c:854
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr ""
+
+#: src/cryptsetup.c:856
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr ""
+
+#: src/cryptsetup.c:870
+#, c-format
+msgid "%-10s N/A\n"
+msgstr ""
+
+#: src/cryptsetup.c:872
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr ""
+
+#: src/cryptsetup.c:896
+msgid "Result of benchmark is not reliable."
+msgstr "Benchmarkresultaat is niet betrouwbaar."
+
+#: src/cryptsetup.c:947
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Tests zijn bij benadering met enkel geheugen in gebruik (geen opslag-IO).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:981
+#, fuzzy, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritme | Sleutel | Versleuteling | Ontsleuteling\n"
+
+#: src/cryptsetup.c:985
+#, c-format
+msgid "Cipher %s is not available."
+msgstr "Versleutelalgoritme %s is niet beschikbaar."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1005
+#, fuzzy
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritme | Sleutel | Versleuteling | Ontsleuteling\n"
+
+#: src/cryptsetup.c:1014
+msgid "N/A"
+msgstr "N/A"
+
+#: src/cryptsetup.c:1094
+msgid ""
+"Seems device does not require reencryption recovery.\n"
+"Do you want to proceed anyway?"
+msgstr ""
+
+#: src/cryptsetup.c:1100
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr ""
+
+#: src/cryptsetup.c:1109
+#, fuzzy
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Voer wachtwoord voor sleutelplaats %u in: "
+
+#: src/cryptsetup.c:1152
+msgid "Really try to repair LUKS device header?"
+msgstr "Bent u zeker de LUKS-apparaatkoptekst te willen herstellen?"
+
+#: src/cryptsetup.c:1171 src/integritysetup.c:145
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+
+#: src/cryptsetup.c:1193 src/integritysetup.c:167
+#, fuzzy, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Kan tijdelijk LUKS-apparaat niet openen.\n"
+
+#: src/cryptsetup.c:1237
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr ""
+
+#: src/cryptsetup.c:1242 src/cryptsetup.c:1302
+#, fuzzy
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Niet-ondersteunde LUKS-versie %d.\n"
+
+#: src/cryptsetup.c:1259
+#, fuzzy, c-format
+msgid "Cannot create header file %s."
+msgstr "Kan reservekopiebestand %s van koptekst niet aanmaken.\n"
+
+#: src/cryptsetup.c:1282 src/integritysetup.c:194 src/integritysetup.c:203
+#: src/integritysetup.c:212 src/integritysetup.c:283 src/integritysetup.c:292
+#: src/integritysetup.c:302
+#, fuzzy
+msgid "No known integrity specification pattern detected."
+msgstr "Geen bekend specificatiepatroon voor het sleutelalgoritme gevonden.\n"
+
+#: src/cryptsetup.c:1295
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Kan %s niet als on-diskkoptekst gebruiken."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:226
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Dit zal data op %s onherroepelijk overschrijven."
+
+#: src/cryptsetup.c:1360 src/cryptsetup.c:1693 src/cryptsetup.c:1760
+#: src/cryptsetup.c:1862 src/cryptsetup.c:1928 src/cryptsetup_reencrypt.c:546
+#, fuzzy
+msgid "Failed to set pbkdf parameters."
+msgstr "Kan status van sleutelbestand niet opvragen.\n"
+
+#: src/cryptsetup.c:1444
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Een verlaagde datagegevenspositie wordt enkel toegestaan voor een vrijstaande LUKS-koptekst."
+
+#: src/cryptsetup.c:1455 src/cryptsetup.c:1766
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr ""
+
+#: src/cryptsetup.c:1493
+msgid "Device activated but cannot make flags persistent."
+msgstr ""
+
+#: src/cryptsetup.c:1574 src/cryptsetup.c:1644
+#, fuzzy, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Sleutelplaats %d geselecteerd voor verwijdering.\n"
+
+#: src/cryptsetup.c:1586 src/cryptsetup.c:1647
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Dit is de laatste sleutelplaats. Apparaat zal onbruikbaar worden na het verwijderen van deze sleutel."
+
+#: src/cryptsetup.c:1587
+msgid "Enter any remaining passphrase: "
+msgstr "Voer enig overblijvend wachtwoord in: "
+
+#: src/cryptsetup.c:1588 src/cryptsetup.c:1649
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:1626
+msgid "Enter passphrase to be deleted: "
+msgstr "Voer het te verwijderen wachtwoord in: "
+
+#: src/cryptsetup.c:1707 src/cryptsetup.c:1781 src/cryptsetup.c:1815
+msgid "Enter new passphrase for key slot: "
+msgstr "Voer een nieuw wachtwoord in voor de sleutelplaats: "
+
+#: src/cryptsetup.c:1798 src/cryptsetup_reencrypt.c:1336
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Voer een bestaand wachtwoord in: "
+
+#: src/cryptsetup.c:1866
+msgid "Enter passphrase to be changed: "
+msgstr "Voer het te wijzigen wachtwoord in: "
+
+#: src/cryptsetup.c:1882 src/cryptsetup_reencrypt.c:1322
+msgid "Enter new passphrase: "
+msgstr "Voer nieuw wachtwoord in: "
+
+#: src/cryptsetup.c:1932
+#, fuzzy
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Voer wachtwoord voor sleutelplaats %u in: "
+
+#: src/cryptsetup.c:1956
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Voor de isLuks-operatie wordt slechts één apparaatsargument ondersteund."
+
+#: src/cryptsetup.c:2140 src/cryptsetup.c:2161
+msgid "Option --header-backup-file is required."
+msgstr "Optie --header-backup-file is vereist."
+
+#: src/cryptsetup.c:2191
+#, fuzzy, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s is geen LUKS-apparaat."
+
+#: src/cryptsetup.c:2202
+#, fuzzy, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Hervatting wordt niet ondersteund voor apparaat %s.\n"
+
+#: src/cryptsetup.c:2244
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Niet-herkende metadata bij apparaatstype %s."
+
+#: src/cryptsetup.c:2247
+msgid "Command requires device and mapped name as arguments."
+msgstr "Opdracht vereist apparaat en toewijzingsnaam als argumenten."
+
+#: src/cryptsetup.c:2269
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Deze operatie zal alle sleutelplaatsen op apparaat %s wissen.\n"
+"Na deze operatie wordt het apparaat onbruikbaar."
+
+#: src/cryptsetup.c:2276
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2313
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr ""
+
+#: src/cryptsetup.c:2331
+#, fuzzy, c-format
+msgid "Device is already %s type."
+msgstr "Apparaat %s bestaat reeds.\n"
+
+#: src/cryptsetup.c:2336
+#, fuzzy, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Deze operatie wordt niet ondersteund voor versleutelapparaat %s.\n"
+
+#: src/cryptsetup.c:2342
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2382
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr ""
+
+#: src/cryptsetup.c:2416 src/cryptsetup.c:2449 src/cryptsetup.c:2472
+#, fuzzy, c-format
+msgid "Token %d is invalid."
+msgstr "Sleutelplaats %d is ongeldig.\n"
+
+#: src/cryptsetup.c:2419 src/cryptsetup.c:2475
+#, c-format
+msgid "Token %d in use."
+msgstr ""
+
+#: src/cryptsetup.c:2426
+#, fuzzy, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Lezen uit sleutelopslag is mislukt.\n"
+
+#: src/cryptsetup.c:2435 src/cryptsetup.c:2497
+#, fuzzy, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: src/cryptsetup.c:2452
+#, fuzzy, c-format
+msgid "Token %d is not in use."
+msgstr "Sleutelplaats %d is niet in gebruik.\n"
+
+#: src/cryptsetup.c:2487
+#, fuzzy
+msgid "Failed to import token from file."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: src/cryptsetup.c:2512
+#, fuzzy, c-format
+msgid "Failed to get token %d for export."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: src/cryptsetup.c:2527
+msgid "--key-description parameter is mandatory for token add action."
+msgstr ""
+
+#: src/cryptsetup.c:2533 src/cryptsetup.c:2541
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr ""
+
+#: src/cryptsetup.c:2546
+#, fuzzy, c-format
+msgid "Invalid token operation %s."
+msgstr "Ongeldige sleutelgrootte %d.\n"
+
+#: src/cryptsetup.c:2601
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2605
+#, fuzzy, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Apparaat %s is geen geldig LUKS-apparaat.\n"
+
+#: src/cryptsetup.c:2607
+#, fuzzy, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Kan geen map voor de apparaatstoewijzer verkrijgen."
+
+#: src/cryptsetup.c:2609
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2689
+#, fuzzy
+msgid "Invalid LUKS device type."
+msgstr "Ongeldig apparaat %s.\n"
+
+#: src/cryptsetup.c:2694
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr ""
+
+#: src/cryptsetup.c:2699
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr ""
+
+#: src/cryptsetup.c:2708
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr ""
+
+#: src/cryptsetup.c:2712
+#, fuzzy
+msgid "Encryption is supported only for LUKS2 format."
+msgstr "Deze operatie wordt enkel ondersteund voor LUKS-apparaten.\n"
+
+#: src/cryptsetup.c:2734
+#, c-format
+msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+msgstr ""
+
+#: src/cryptsetup.c:2749
+#, fuzzy, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Aangevraagd reservekopiebestand %s van koptekst bestaat reeds.\n"
+
+#: src/cryptsetup.c:2751 src/cryptsetup.c:2758
+#, fuzzy, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Kan reservekopiebestand %s van koptekst niet aanmaken.\n"
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2986 src/cryptsetup.c:2992
+#, fuzzy
+msgid "Not enough free keyslots for reencryption."
+msgstr "Sleutel niet wijzigen; gegevensgebied wordt niet opnieuw versleuteld."
+
+#: src/cryptsetup.c:3012 src/cryptsetup_reencrypt.c:1287
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Sleutelbestand kan enkel gebruikt worden met optie --key-slot of met enkel één actieve sleutelplaats."
+
+#: src/cryptsetup.c:3021 src/cryptsetup_reencrypt.c:1334
+#: src/cryptsetup_reencrypt.c:1345
+#, fuzzy, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Voer wachtwoord voor sleutelplaats %u in: "
+
+#: src/cryptsetup.c:3029
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Voer wachtwoord voor sleutelplaats %u in: "
+
+#: src/cryptsetup.c:3196
+#, fuzzy
+msgid "Command requires device as argument."
+msgstr "Opdracht vereist apparaat en toewijzingsnaam als argumenten.\n"
+
+#: src/cryptsetup.c:3218
+msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+msgstr ""
+
+#: src/cryptsetup.c:3230
+msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+msgstr ""
+
+#: src/cryptsetup.c:3240 src/cryptsetup_reencrypt.c:178
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr ""
+
+#: src/cryptsetup.c:3248
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr ""
+
+#: src/cryptsetup.c:3252
+#, fuzzy
+msgid "LUKS2 device is not in reencryption."
+msgstr "Logbestand %s bestaat reeds, herencryptie wordt herstart.\n"
+
+#: src/cryptsetup.c:3279
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<apparaat> [--type <type>] [<naam>]"
+
+#: src/cryptsetup.c:3279 src/veritysetup.c:394 src/integritysetup.c:474
+#, fuzzy
+msgid "open device as <name>"
+msgstr "apparaat als toewijzing <naam> openen"
+
+#: src/cryptsetup.c:3280 src/cryptsetup.c:3281 src/cryptsetup.c:3282
+#: src/veritysetup.c:395 src/veritysetup.c:396 src/integritysetup.c:475
+#: src/integritysetup.c:476
+msgid "<name>"
+msgstr "<naam>"
+
+#: src/cryptsetup.c:3280 src/veritysetup.c:395 src/integritysetup.c:475
+msgid "close device (remove mapping)"
+msgstr "apparaat sluiten (toewijzingen verwijderen)"
+
+#: src/cryptsetup.c:3281
+msgid "resize active device"
+msgstr "actief apparaat vergroten of verkleinen"
+
+#: src/cryptsetup.c:3282
+msgid "show device status"
+msgstr "apparaatstatus tonen"
+
+#: src/cryptsetup.c:3283
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <versleutelalgoritme>]"
+
+#: src/cryptsetup.c:3283
+msgid "benchmark cipher"
+msgstr "versleutelalgoritme benchmarken"
+
+#: src/cryptsetup.c:3284 src/cryptsetup.c:3285 src/cryptsetup.c:3286
+#: src/cryptsetup.c:3287 src/cryptsetup.c:3288 src/cryptsetup.c:3295
+#: src/cryptsetup.c:3296 src/cryptsetup.c:3297 src/cryptsetup.c:3298
+#: src/cryptsetup.c:3299 src/cryptsetup.c:3300 src/cryptsetup.c:3301
+#: src/cryptsetup.c:3302 src/cryptsetup.c:3303
+msgid "<device>"
+msgstr "<apparaat>"
+
+#: src/cryptsetup.c:3284
+msgid "try to repair on-disk metadata"
+msgstr "on-disk metadata proberen te herstellen"
+
+#: src/cryptsetup.c:3285
+#, fuzzy
+msgid "reencrypt LUKS2 device"
+msgstr "sleutel aan LUKS-apparaat toevoegen"
+
+#: src/cryptsetup.c:3286
+msgid "erase all keyslots (remove encryption key)"
+msgstr "alle sleutelplaatsen wissen (encryptiesleutel verwijderen)"
+
+#: src/cryptsetup.c:3287
+msgid "convert LUKS from/to LUKS2 format"
+msgstr ""
+
+#: src/cryptsetup.c:3288
+msgid "set permanent configuration options for LUKS2"
+msgstr ""
+
+#: src/cryptsetup.c:3289 src/cryptsetup.c:3290
+msgid "<device> [<new key file>]"
+msgstr "<apparaat> [<nieuw sleutelbestand>]"
+
+#: src/cryptsetup.c:3289
+msgid "formats a LUKS device"
+msgstr "een LUKS-apparaat formatteren"
+
+#: src/cryptsetup.c:3290
+msgid "add key to LUKS device"
+msgstr "sleutel aan LUKS-apparaat toevoegen"
+
+#: src/cryptsetup.c:3291 src/cryptsetup.c:3292 src/cryptsetup.c:3293
+msgid "<device> [<key file>]"
+msgstr "<apparaat> [<sleutelbestand>]"
+
+#: src/cryptsetup.c:3291
+msgid "removes supplied key or key file from LUKS device"
+msgstr "verschafte sleutel of sleutelbestand van LUKS-apparaat verwijderen"
+
+#: src/cryptsetup.c:3292
+msgid "changes supplied key or key file of LUKS device"
+msgstr "wijzigt verschafte sleutel of sleutelbestand van LUKS-apparaat"
+
+#: src/cryptsetup.c:3293
+msgid "converts a key to new pbkdf parameters"
+msgstr ""
+
+#: src/cryptsetup.c:3294
+msgid "<device> <key slot>"
+msgstr "<apparaat> <sleutelplaats>"
+
+#: src/cryptsetup.c:3294
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "sleutel met nummer <sleutelplaats> van LUKS-apparaat verwijderen"
+
+#: src/cryptsetup.c:3295
+msgid "print UUID of LUKS device"
+msgstr "UUID van LUKS-apparaat tonen"
+
+#: src/cryptsetup.c:3296
+msgid "tests <device> for LUKS partition header"
+msgstr "<apparaat> op een LUKS-partitiekoptekst testen"
+
+#: src/cryptsetup.c:3297
+msgid "dump LUKS partition information"
+msgstr "LUKS-partitie-informatie dumpen"
+
+#: src/cryptsetup.c:3298
+msgid "dump TCRYPT device information"
+msgstr "TCRYPT-apparaatsinformatie dumpen"
+
+#: src/cryptsetup.c:3299
+#, fuzzy
+msgid "dump BITLK device information"
+msgstr "TCRYPT-apparaatsinformatie dumpen"
+
+#: src/cryptsetup.c:3300
+#, fuzzy
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "LUKS-apparaat schorsen en sleutel wissen (alle in-/uitvoer wordt bevroren)."
+
+#: src/cryptsetup.c:3301
+#, fuzzy
+msgid "Resume suspended LUKS device"
+msgstr "Geschorst LUKS-apparaat hervatten."
+
+#: src/cryptsetup.c:3302
+msgid "Backup LUKS device header and keyslots"
+msgstr "Reservekopie van LUKS-apparaatkoptekst en -sleutelplaatsen maken"
+
+#: src/cryptsetup.c:3303
+msgid "Restore LUKS device header and keyslots"
+msgstr "LUKS-apparaatkoptekst en -sleutelplaatsen herstellen"
+
+#: src/cryptsetup.c:3304
+msgid "<add|remove|import|export> <device>"
+msgstr ""
+
+#: src/cryptsetup.c:3304
+msgid "Manipulate LUKS2 tokens"
+msgstr ""
+
+#: src/cryptsetup.c:3322 src/veritysetup.c:412 src/integritysetup.c:492
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<actie> is één van:\n"
+
+#: src/cryptsetup.c:3328
+#, fuzzy
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+msgstr ""
+"\n"
+"U kan ook oude <actie>-syntax aliasen gebruiken:\n"
+"\topen: (plainOpen), luksOpen, loopaesOpen, tcryptOpen aanmaken\n"
+"\tclose: (plainClose), luksClose, loopaesClose, tryptClose verwijderen\n"
+
+#: src/cryptsetup.c:3332
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<naam> is het onder %s aan te maken apparaat\n"
+"<apparaat> is het versleutelde apparaat\n"
+"<sleutelplaats> is het nummer van de te wijzigen LUKS-sleutelplaats\n"
+"<sleutelbestand> optioneel sleutelbestand voor de nieuwe sleutel voor de luksAddKey-actie\n"
+
+#: src/cryptsetup.c:3339
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+
+#: src/cryptsetup.c:3344
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Standaard meegecompileerde sleutel- en wachtwoordparameters:\n"
+"\tMaximum sleutelplaatsgrootte: %dkB, maximum lengte interactief wachtwoord %d (karakters)\n"
+"Standaard PBKDF2-herhalingstijd voor LUKS: %d (ms)\n"
+
+#: src/cryptsetup.c:3355
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Standaard meegecompileerde parameters van het apparaatsversleutelingsalgoritme:\n"
+"\tloop-AES: %s, Sleutel: %d bits\n"
+"\tplain: %s, Sleutel: %d bits, Wachtwoordhashing: %s\n"
+"\tLUKS1: %s, Sleutel: %d bits, LUKS-kopteksthashing: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3364
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3380 src/veritysetup.c:569 src/integritysetup.c:634
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: vereist %s als argumenten"
+
+#: src/cryptsetup.c:3418 src/veritysetup.c:457 src/integritysetup.c:530
+#: src/cryptsetup_reencrypt.c:1600
+msgid "Show this help message"
+msgstr "Deze hulptekst tonen"
+
+#: src/cryptsetup.c:3419 src/veritysetup.c:458 src/integritysetup.c:531
+#: src/cryptsetup_reencrypt.c:1601
+msgid "Display brief usage"
+msgstr "Korte gebruikssamenvatting tonen"
+
+#: src/cryptsetup.c:3420 src/veritysetup.c:459 src/integritysetup.c:532
+#: src/cryptsetup_reencrypt.c:1602
+msgid "Print package version"
+msgstr "Pakketversie tonen"
+
+#: src/cryptsetup.c:3424 src/veritysetup.c:463 src/integritysetup.c:536
+#: src/cryptsetup_reencrypt.c:1606
+msgid "Help options:"
+msgstr "Hulpopties:"
+
+#: src/cryptsetup.c:3425 src/veritysetup.c:464 src/integritysetup.c:537
+#: src/cryptsetup_reencrypt.c:1607
+msgid "Shows more detailed error messages"
+msgstr "Gedetailleerdere foutboodschappen tonen"
+
+#: src/cryptsetup.c:3426 src/veritysetup.c:465 src/integritysetup.c:538
+#: src/cryptsetup_reencrypt.c:1608
+msgid "Show debug messages"
+msgstr "Debug-boodschappen tonen"
+
+#: src/cryptsetup.c:3427
+#, fuzzy
+msgid "Show debug messages including JSON metadata"
+msgstr "Debug-boodschappen tonen"
+
+#: src/cryptsetup.c:3428 src/cryptsetup_reencrypt.c:1610
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "Het gebruikte versleutelalgoritme om de schijf te versleutelen (zie /proc/crypto)"
+
+#: src/cryptsetup.c:3429 src/cryptsetup_reencrypt.c:1612
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "De gebruikte hash om de encryptiesleutel uit het wachtwoord aan te maken"
+
+#: src/cryptsetup.c:3430
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Het wachtwoord controleren door het twee keer te vragen"
+
+#: src/cryptsetup.c:3431 src/cryptsetup_reencrypt.c:1614
+#, fuzzy
+msgid "Read the key from a file"
+msgstr "De sleutel uit een bestand lezen."
+
+#: src/cryptsetup.c:3432
+msgid "Read the volume (master) key from file."
+msgstr "De (hoofd)sleutel tot het opslagmedium uit een bestand lezen."
+
+#: src/cryptsetup.c:3433
+#, fuzzy
+msgid "Dump volume (master) key instead of keyslots info"
+msgstr "Dump (hoofd)sleutel tot het opslagmedium in plaats van de sleutelplaatsinformatie."
+
+#: src/cryptsetup.c:3434 src/cryptsetup_reencrypt.c:1611
+msgid "The size of the encryption key"
+msgstr "De grootte van de encryptiesleutel"
+
+#: src/cryptsetup.c:3434 src/cryptsetup.c:3494 src/integritysetup.c:556
+#: src/integritysetup.c:560 src/integritysetup.c:564
+#: src/cryptsetup_reencrypt.c:1611
+msgid "BITS"
+msgstr "BITS"
+
+#: src/cryptsetup.c:3435 src/cryptsetup_reencrypt.c:1627
+msgid "Limits the read from keyfile"
+msgstr "Beperkt de lezing uit sleutelbestand"
+
+#: src/cryptsetup.c:3435 src/cryptsetup.c:3436 src/cryptsetup.c:3437
+#: src/cryptsetup.c:3438 src/cryptsetup.c:3441 src/cryptsetup.c:3491
+#: src/cryptsetup.c:3492 src/cryptsetup.c:3500 src/cryptsetup.c:3501
+#: src/veritysetup.c:468 src/veritysetup.c:469 src/veritysetup.c:470
+#: src/veritysetup.c:473 src/veritysetup.c:474 src/integritysetup.c:545
+#: src/integritysetup.c:551 src/integritysetup.c:552
+#: src/cryptsetup_reencrypt.c:1626 src/cryptsetup_reencrypt.c:1627
+#: src/cryptsetup_reencrypt.c:1628 src/cryptsetup_reencrypt.c:1629
+msgid "bytes"
+msgstr "bytes"
+
+#: src/cryptsetup.c:3436 src/cryptsetup_reencrypt.c:1626
+msgid "Number of bytes to skip in keyfile"
+msgstr "Aantal bytes over te slaan in sleutelbestand"
+
+#: src/cryptsetup.c:3437
+msgid "Limits the read from newly added keyfile"
+msgstr "Beperkt de lezing uit een nieuw toegevoegd sleutelbestand"
+
+#: src/cryptsetup.c:3438
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "Aantal bytes over te slaan in nieuwste toegevoegde sleutelbestand"
+
+#: src/cryptsetup.c:3439
+msgid "Slot number for new key (default is first free)"
+msgstr "Plaatsnummer voor nieuwe sleutel (standaard is de eerste open plaats)"
+
+#: src/cryptsetup.c:3440
+msgid "The size of the device"
+msgstr "De grootte van het apparaat"
+
+#: src/cryptsetup.c:3440 src/cryptsetup.c:3442 src/cryptsetup.c:3443
+#: src/cryptsetup.c:3449 src/integritysetup.c:546 src/integritysetup.c:553
+msgid "SECTORS"
+msgstr "SECTOREN"
+
+#: src/cryptsetup.c:3441 src/cryptsetup_reencrypt.c:1629
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "Enkel ingegeven apparaatsgrootte gebruiken (rest van apparaat wordt genegeerd). GEVAARLIJK!"
+
+#: src/cryptsetup.c:3442
+msgid "The start offset in the backend device"
+msgstr "De startplaats in het backend-apparaat"
+
+#: src/cryptsetup.c:3443
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Hoeveel sectoren van de versleutelde gegevens aan het begin over te slaan"
+
+#: src/cryptsetup.c:3444
+msgid "Create a readonly mapping"
+msgstr "Een alleen-lezen toewijzing aanmaken"
+
+#: src/cryptsetup.c:3445 src/integritysetup.c:539
+#: src/cryptsetup_reencrypt.c:1617
+msgid "Do not ask for confirmation"
+msgstr "Niet om bevestiging vragen"
+
+#: src/cryptsetup.c:3446
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Timeout voor interactieve wachtwoordprompt (in seconden)"
+
+#: src/cryptsetup.c:3446 src/cryptsetup.c:3447 src/integritysetup.c:540
+#: src/cryptsetup_reencrypt.c:1618
+msgid "secs"
+msgstr "seconden"
+
+#: src/cryptsetup.c:3447 src/integritysetup.c:540
+#: src/cryptsetup_reencrypt.c:1618
+msgid "Progress line update (in seconds)"
+msgstr ""
+
+#: src/cryptsetup.c:3448 src/cryptsetup_reencrypt.c:1619
+msgid "How often the input of the passphrase can be retried"
+msgstr "Hoe vaak de invoering van het wachtwoord opnieuw geprobeerd kan worden"
+
+#: src/cryptsetup.c:3449
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Payload uitlijnen op meervouden van <n> sectoren – voor luksFormat"
+
+#: src/cryptsetup.c:3450
+#, fuzzy
+msgid "File with LUKS header and keyslots backup"
+msgstr "Bestand met reservekopie van LUKS-koptekst en -sleutelplaatsen."
+
+#: src/cryptsetup.c:3451 src/cryptsetup_reencrypt.c:1620
+#, fuzzy
+msgid "Use /dev/random for generating volume key"
+msgstr "Gebruik /dev/random om de sleutel tot het opslagmedium te genereren."
+
+#: src/cryptsetup.c:3452 src/cryptsetup_reencrypt.c:1621
+#, fuzzy
+msgid "Use /dev/urandom for generating volume key"
+msgstr "Gebruik /dev/urandom om de sleutel tot het opslagmedium te genereren."
+
+#: src/cryptsetup.c:3453
+#, fuzzy
+msgid "Share device with another non-overlapping crypt segment"
+msgstr "Apparaat met een ander, niet-overlappend cryptsegment delen."
+
+#: src/cryptsetup.c:3454 src/veritysetup.c:477
+#, fuzzy
+msgid "UUID for device to use"
+msgstr "UUID van het te gebruiken apparaat."
+
+#: src/cryptsetup.c:3455
+#, fuzzy
+msgid "Allow discards (aka TRIM) requests for device"
+msgstr "Discardaanvragen (alias TRIM) op dit apparaat toelaten."
+
+#: src/cryptsetup.c:3456 src/cryptsetup_reencrypt.c:1638
+#, fuzzy
+msgid "Device or file with separated LUKS header"
+msgstr "Apparaat of bestand met verschillende LUKS-koptekst."
+
+#: src/cryptsetup.c:3457
+#, fuzzy
+msgid "Do not activate device, just check passphrase"
+msgstr "Apparaat niet activeren, enkel wachtwoord controleren."
+
+#: src/cryptsetup.c:3458
+#, fuzzy
+msgid "Use hidden header (hidden TCRYPT device)"
+msgstr "Verborgen koptekst gebruiken (verborgen TCRYPT-apparaat)."
+
+#: src/cryptsetup.c:3459
+#, fuzzy
+msgid "Device is system TCRYPT drive (with bootloader)"
+msgstr "Apparaat is TCRYPT-systeemschijf (met bootloader)."
+
+#: src/cryptsetup.c:3460
+#, fuzzy
+msgid "Use backup (secondary) TCRYPT header"
+msgstr "Reserve (secundaire) TCRYPT-koptekst gebruiken."
+
+#: src/cryptsetup.c:3461
+#, fuzzy
+msgid "Scan also for VeraCrypt compatible device"
+msgstr "Eveneens naar VeraCrypt-compatibel apparaat scannen."
+
+#: src/cryptsetup.c:3462
+#, fuzzy
+msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Eveneens naar VeraCrypt-compatibel apparaat scannen."
+
+#: src/cryptsetup.c:3463
+#, fuzzy
+msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Eveneens naar VeraCrypt-compatibel apparaat scannen."
+
+#: src/cryptsetup.c:3464
+#, fuzzy
+msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+msgstr "Soorten apparaat-metadata: luks, plain, loopaes, tcrypt."
+
+#: src/cryptsetup.c:3465
+#, fuzzy
+msgid "Disable password quality check (if enabled)"
+msgstr "Wachtwoordkwaliteitscontrole uitschakelen (indien ingeschakeld)."
+
+#: src/cryptsetup.c:3466
+#, fuzzy
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+msgstr "dm-crypt same_cpu_crypt prestatie-compatibiliteitsoptie gebruiken."
+
+#: src/cryptsetup.c:3467
+#, fuzzy
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+msgstr "dm-crypt submit_from_crypt_cpus prestatie-compatibiliteitsoptie gebruiken."
+
+#: src/cryptsetup.c:3468
+msgid "Device removal is deferred until the last user closes it"
+msgstr ""
+
+#: src/cryptsetup.c:3469
+msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+msgstr ""
+
+#: src/cryptsetup.c:3470
+#, fuzzy
+msgid "PBKDF iteration time for LUKS (in ms)"
+msgstr "PBKDF2 herhalingstijd voor LUKS (in ms)"
+
+#: src/cryptsetup.c:3470 src/cryptsetup_reencrypt.c:1616
+msgid "msecs"
+msgstr "milliseconden"
+
+#: src/cryptsetup.c:3471 src/cryptsetup_reencrypt.c:1634
+msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+msgstr ""
+
+#: src/cryptsetup.c:3472 src/cryptsetup_reencrypt.c:1635
+msgid "PBKDF memory cost limit"
+msgstr ""
+
+#: src/cryptsetup.c:3472 src/cryptsetup_reencrypt.c:1635
+#, fuzzy
+msgid "kilobytes"
+msgstr "bytes"
+
+#: src/cryptsetup.c:3473 src/cryptsetup_reencrypt.c:1636
+msgid "PBKDF parallel cost"
+msgstr ""
+
+#: src/cryptsetup.c:3473 src/cryptsetup_reencrypt.c:1636
+msgid "threads"
+msgstr ""
+
+#: src/cryptsetup.c:3474 src/cryptsetup_reencrypt.c:1637
+msgid "PBKDF iterations cost (forced, disables benchmark)"
+msgstr ""
+
+#: src/cryptsetup.c:3475
+msgid "Keyslot priority: ignore, normal, prefer"
+msgstr ""
+
+#: src/cryptsetup.c:3476
+#, fuzzy
+msgid "Disable locking of on-disk metadata"
+msgstr "on-disk metadata proberen te herstellen"
+
+#: src/cryptsetup.c:3477
+msgid "Disable loading volume keys via kernel keyring"
+msgstr ""
+
+#: src/cryptsetup.c:3478
+msgid "Data integrity algorithm (LUKS2 only)"
+msgstr ""
+
+#: src/cryptsetup.c:3479 src/integritysetup.c:567
+msgid "Disable journal for integrity device"
+msgstr ""
+
+#: src/cryptsetup.c:3480 src/integritysetup.c:541
+msgid "Do not wipe device after format"
+msgstr ""
+
+#: src/cryptsetup.c:3481 src/integritysetup.c:571
+msgid "Use inefficient legacy padding (old kernels)"
+msgstr ""
+
+#: src/cryptsetup.c:3482
+msgid "Do not ask for passphrase if activation by token fails"
+msgstr ""
+
+#: src/cryptsetup.c:3483
+msgid "Token number (default: any)"
+msgstr ""
+
+#: src/cryptsetup.c:3484
+msgid "Key description"
+msgstr ""
+
+#: src/cryptsetup.c:3485
+msgid "Encryption sector size (default: 512 bytes)"
+msgstr ""
+
+#: src/cryptsetup.c:3486
+msgid "Set activation flags persistent for device"
+msgstr ""
+
+#: src/cryptsetup.c:3487
+#, fuzzy
+msgid "Set label for the LUKS2 device"
+msgstr "een LUKS-apparaat formatteren"
+
+#: src/cryptsetup.c:3488
+msgid "Set subsystem label for the LUKS2 device"
+msgstr ""
+
+#: src/cryptsetup.c:3489
+msgid "Create unbound (no assigned data segment) LUKS2 keyslot"
+msgstr ""
+
+#: src/cryptsetup.c:3490
+#, fuzzy
+msgid "Read or write the json from or to a file"
+msgstr "De sleutel uit een bestand lezen."
+
+#: src/cryptsetup.c:3491
+msgid "LUKS2 header metadata area size"
+msgstr ""
+
+#: src/cryptsetup.c:3492
+#, fuzzy
+msgid "LUKS2 header keyslots area size"
+msgstr "Bestand met reservekopie van LUKS-koptekst en -sleutelplaatsen."
+
+#: src/cryptsetup.c:3493
+msgid "Refresh (reactivate) device with new parameters"
+msgstr ""
+
+#: src/cryptsetup.c:3494
+#, fuzzy
+msgid "LUKS2 keyslot: The size of the encryption key"
+msgstr "De grootte van de encryptiesleutel"
+
+#: src/cryptsetup.c:3495
+msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+msgstr ""
+
+#: src/cryptsetup.c:3496
+#, fuzzy
+msgid "Encrypt LUKS2 device (in-place encryption)."
+msgstr "Apparaat permanent ontsleutelen (encryptie verwijderen)."
+
+#: src/cryptsetup.c:3497
+#, fuzzy
+msgid "Decrypt LUKS2 device (remove encryption)."
+msgstr "Apparaat permanent ontsleutelen (encryptie verwijderen)."
+
+#: src/cryptsetup.c:3498
+msgid "Initialize LUKS2 reencryption in metadata only."
+msgstr ""
+
+#: src/cryptsetup.c:3499
+msgid "Resume initialized LUKS2 reencryption only."
+msgstr ""
+
+#: src/cryptsetup.c:3500 src/cryptsetup_reencrypt.c:1628
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "Grootte van gegevensapparaat wijzigen (gegevenspositie wijzigen). GEVAARLIJK!"
+
+#: src/cryptsetup.c:3501
+#, fuzzy
+msgid "Maximal reencryption hotzone size."
+msgstr "Blokgrootte herencryptie"
+
+#: src/cryptsetup.c:3502
+msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+msgstr ""
+
+#: src/cryptsetup.c:3503
+#, fuzzy
+msgid "Reencryption hotzone checksums hash"
+msgstr "Blokgrootte herencryptie"
+
+#: src/cryptsetup.c:3504
+msgid "Override device autodetection of dm device to be reencrypted"
+msgstr ""
+
+#: src/cryptsetup.c:3520 src/veritysetup.c:499 src/integritysetup.c:587
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPTIE…] <actie> <actie-specifiek>"
+
+#: src/cryptsetup.c:3571 src/veritysetup.c:533 src/integritysetup.c:598
+msgid "Argument <action> missing."
+msgstr "Argument <actie> ontbreekt."
+
+#: src/cryptsetup.c:3640 src/veritysetup.c:564 src/integritysetup.c:629
+msgid "Unknown action."
+msgstr "Onbekende actie."
+
+#: src/cryptsetup.c:3650
+msgid "Parameter --refresh is only allowed with open or refresh commands.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3655
+msgid "Options --refresh and --test-passphrase are mutually exclusive.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3660
+#, fuzzy
+msgid "Option --deferred is allowed only for close command.\n"
+msgstr "Optie --shared wordt enkel toegestaan voor open-opdracht op plain-apparaat.\n"
+
+#: src/cryptsetup.c:3665
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "Optie --shared wordt enkel toegestaan voor open-opdracht op plain-apparaat.\n"
+
+#: src/cryptsetup.c:3670
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "Optie --allow-discards wordt enkel toegestaan voor de open-operatie.\n"
+
+#: src/cryptsetup.c:3675
+#, fuzzy
+msgid "Option --persistent is allowed only for open operation.\n"
+msgstr "Optie --allow-discards wordt enkel toegestaan voor de open-operatie.\n"
+
+#: src/cryptsetup.c:3680
+#, fuzzy
+msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation.\n"
+msgstr "Optie --allow-discards wordt enkel toegestaan voor de open-operatie.\n"
+
+#: src/cryptsetup.c:3685
+msgid "Option --persistent is not allowed with --test-passphrase.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3695
+#, fuzzy
+msgid ""
+"Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+"open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"Optie --key-size is enkel toegestaan bij luksFormat, open en benchmark.\n"
+"Om de lezing uit een sleutelbestand te beperken, gebruik --keyfile-size=(bytes)."
+
+#: src/cryptsetup.c:3701
+#, fuzzy
+msgid "Option --integrity is allowed only for luksFormat (LUKS2).\n"
+msgstr "Optie --align-payload is enkel toegestaan voor luksFormat."
+
+#: src/cryptsetup.c:3706
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3712
+#, fuzzy
+msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations.\n"
+msgstr "Optie --allow-discards wordt enkel ondersteund voor de luksOpen-, loopaesOpen- en create-opdrachten.\n"
+
+#: src/cryptsetup.c:3718
+#, fuzzy
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT and BITLK devices.\n"
+msgstr "Optie --test-passphrase is enkel toegestaan bij open van LUKS- en TCRYPT-apparaten.\n"
+
+#: src/cryptsetup.c:3723 src/cryptsetup_reencrypt.c:1701
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Sleutelgrootte moet een meervoud zijn van 8 bits"
+
+#: src/cryptsetup.c:3729 src/cryptsetup_reencrypt.c:1387
+#: src/cryptsetup_reencrypt.c:1706
+msgid "Key slot is invalid."
+msgstr "Sleutelplaats is ongeldig."
+
+#: src/cryptsetup.c:3736
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Optie --key-file krijgt voorrang over het gespecificeerde sleutelbestandsargument."
+
+#: src/cryptsetup.c:3743 src/veritysetup.c:576 src/integritysetup.c:650
+#: src/cryptsetup_reencrypt.c:1680
+msgid "Negative number for option not permitted."
+msgstr "Een negatief getal wordt niet toegestaan voor deze optie."
+
+#: src/cryptsetup.c:3747
+msgid "Only one --key-file argument is allowed."
+msgstr "Slechts een enkel gebruik van het --key-file argument is toegestaan."
+
+#: src/cryptsetup.c:3751 src/cryptsetup_reencrypt.c:1672
+#: src/cryptsetup_reencrypt.c:1710
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Slechts een enkel gebruik van de opties --use-[u]random is toegestaan."
+
+#: src/cryptsetup.c:3755
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "OPtie --use-[u]random is enkel toegestaan bij luksFormat."
+
+#: src/cryptsetup.c:3759
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "Optie --uuid is enkel toegestaan bij luksFormat en luksUUID."
+
+#: src/cryptsetup.c:3763
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "Optie --align-payload is enkel toegestaan voor luksFormat."
+
+#: src/cryptsetup.c:3767
+msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+msgstr ""
+
+#: src/cryptsetup.c:3772
+#, fuzzy
+msgid "Invalid LUKS2 metadata size specification."
+msgstr "Ongeldig apparaatsgrootte ingegeven."
+
+#: src/cryptsetup.c:3776
+#, fuzzy
+msgid "Invalid LUKS2 keyslots size specification."
+msgstr "Ongeldig apparaatsgrootte ingegeven."
+
+#: src/cryptsetup.c:3780
+#, fuzzy
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Optie --align-payload is enkel toegestaan voor luksFormat."
+
+#: src/cryptsetup.c:3786
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "Optie --skip wordt enkel ondersteund voor open-opdracht op plain- en loopaes-apparaten.\n"
+
+#: src/cryptsetup.c:3793
+#, fuzzy
+msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption.\n"
+msgstr "Optie --offset wordt enkel ondersteund voor open-opdracht op plain- en loopaes-apparaten.\n"
+
+#: src/cryptsetup.c:3799
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "Optie --tcrypt-hidden, --tcrypt-system of --tcrypt-backup wordt enkel ondersteund voor TCRYPT-apparaten.\n"
+
+#: src/cryptsetup.c:3804
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "Optie --tcrypt-hidden kan niet met --allow-discards gecombineerd worden.\n"
+
+#: src/cryptsetup.c:3809
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "Optie --veracrypt wordt enkel ondersteund voor TCRYPT-apparaatstype.\n"
+
+#: src/cryptsetup.c:3815
+msgid "Invalid argument for parameter --veracrypt-pim supplied.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3819
+#, fuzzy
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "Optie --veracrypt wordt enkel ondersteund voor TCRYPT-apparaatstype.\n"
+
+#: src/cryptsetup.c:3827
+#, fuzzy
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "Optie --veracrypt wordt enkel ondersteund voor TCRYPT-apparaatstype.\n"
+
+#: src/cryptsetup.c:3831
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3838
+msgid "Option --priority can be only ignore/normal/prefer.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3843
+msgid "Keyslot specification is required.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3848 src/cryptsetup_reencrypt.c:1686
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3853 src/cryptsetup_reencrypt.c:1691
+msgid "PBKDF forced iterations cannot be combined with iteration time option.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3859
+#, fuzzy
+msgid "Sector size option is not supported for this command.\n"
+msgstr "Deze operatie wordt niet ondersteund voor dit apparaatstype.\n"
+
+#: src/cryptsetup.c:3865
+#, fuzzy
+msgid "Unsupported encryption sector size.\n"
+msgstr "Kan herencryptie-logbestand niet lezen.\n"
+
+#: src/cryptsetup.c:3870
+msgid "Key size is required with --unbound option.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3875
+#, fuzzy
+msgid "Option --unbound may be used only with luksAddKey action.\n"
+msgstr "Optie --new kan niet samen met --decrypt gebruikt worden."
+
+#: src/cryptsetup.c:3880
+#, fuzzy
+msgid "Option --refresh may be used only with open action.\n"
+msgstr "Optie -- keep-key kan enkel samen met --hash of --iter-time gebruikt worden."
+
+#: src/cryptsetup.c:3891
+msgid "Cannot disable metadata locking.\n"
+msgstr ""
+
+#: src/cryptsetup.c:3901
+#, fuzzy
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Ongeldig apparaatsgrootte ingegeven."
+
+#: src/cryptsetup.c:3909 src/cryptsetup_reencrypt.c:1715
+#: src/cryptsetup_reencrypt.c:1720
+msgid "Invalid device size specification."
+msgstr "Ongeldig apparaatsgrootte ingegeven."
+
+#: src/cryptsetup.c:3912
+#, fuzzy
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Maximum apparaatsverkleiningsgrootte is 64 MB."
+
+#: src/cryptsetup.c:3915 src/cryptsetup_reencrypt.c:1726
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Verkleiningsgrootte moet een meervoud zijn van de 512 bytes-grote sector."
+
+#: src/cryptsetup.c:3920
+#, fuzzy
+msgid "Invalid data size specification."
+msgstr "Ongeldig apparaatsgrootte ingegeven."
+
+#: src/cryptsetup.c:3925
+#, fuzzy
+msgid "Reduce size overflow."
+msgstr "Overloop van apparaatsgegevenspositie.\n"
+
+#: src/cryptsetup.c:3929
+msgid "LUKS2 decryption requires option --header."
+msgstr ""
+
+#: src/cryptsetup.c:3933
+#, fuzzy
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Verkleiningsgrootte moet een meervoud zijn van de 512 bytes-grote sector."
+
+#: src/cryptsetup.c:3937
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr ""
+
+#: src/cryptsetup.c:3941
+msgid "Options --device-size and --size cannot be combined."
+msgstr ""
+
+#: src/veritysetup.c:66
+msgid "Invalid salt string specified."
+msgstr "Ongeldige salt-tekenreeks opgegeven."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Kan hashafbeeling %s niet aanmaken voor beschrijving."
+
+#: src/veritysetup.c:107
+#, fuzzy, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Kan hashafbeeling %s niet aanmaken voor beschrijving.\n"
+
+#: src/veritysetup.c:179
+msgid "Invalid root hash string specified."
+msgstr "Ongeldige root-hash tekenreeks opgegeven."
+
+#: src/veritysetup.c:187
+#, fuzzy, c-format
+msgid "Invalid signature file %s."
+msgstr "Ongeldig apparaat %s.\n"
+
+#: src/veritysetup.c:194
+#, fuzzy, c-format
+msgid "Cannot read signature file %s."
+msgstr "Kan sleutelbestand %s niet lezen.\n"
+
+#: src/veritysetup.c:392
+msgid "<data_device> <hash_device>"
+msgstr "<gegevensapparaat> <hash-apparaat>"
+
+#: src/veritysetup.c:392 src/integritysetup.c:473
+msgid "format device"
+msgstr "apparaat formateren"
+
+#: src/veritysetup.c:393
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<gegevensapparaat> <hash-apparaat> <root-hash>"
+
+#: src/veritysetup.c:393
+msgid "verify device"
+msgstr "apparaat controleren"
+
+#: src/veritysetup.c:394
+#, fuzzy
+msgid "<data_device> <name> <hash_device> <root_hash>"
+msgstr "<gegevensapparaat> <hash-apparaat> <root-hash>"
+
+#: src/veritysetup.c:396 src/integritysetup.c:476
+msgid "show active device status"
+msgstr "status van actief apparaat tonen"
+
+#: src/veritysetup.c:397
+msgid "<hash_device>"
+msgstr "<hash-apparaat>"
+
+#: src/veritysetup.c:397 src/integritysetup.c:477
+msgid "show on-disk information"
+msgstr "on-disk informatie tonen"
+
+#: src/veritysetup.c:416
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<naam> is de naam van het onder %s te creëren apparaat\n"
+"<gegevensapparaat> is het de naam van het gegevensapparaat\n"
+"<hash-apparaat> is de naam van het apparaat dat de verificatiegegevens bevat\n"
+"<root-hash> is de hash van de rootnode op <hash-apparaat>\n"
+
+#: src/veritysetup.c:423
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Standaard meegecompileerde dm-verity parameters:\n"
+"\tHash: %s, Datablok (bytes): %u, Hashblock (bytes): %u, Saltgrootte: %u, Hashformaat: %u\n"
+
+#: src/veritysetup.c:466
+msgid "Do not use verity superblock"
+msgstr "VERITY-superblok niet gebruiken"
+
+#: src/veritysetup.c:467
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "Formaatstype (1 - normaal, 0 - origineel Chrome OS)"
+
+#: src/veritysetup.c:467
+msgid "number"
+msgstr "nummer"
+
+#: src/veritysetup.c:468
+msgid "Block size on the data device"
+msgstr "Blokgrootte op het gegevensapparaat"
+
+#: src/veritysetup.c:469
+msgid "Block size on the hash device"
+msgstr "Blokgrootte op het hash-apparaat"
+
+#: src/veritysetup.c:470
+msgid "FEC parity bytes"
+msgstr ""
+
+#: src/veritysetup.c:471
+msgid "The number of blocks in the data file"
+msgstr "Aantal blokken in het gegevensbestand"
+
+#: src/veritysetup.c:471
+msgid "blocks"
+msgstr "blokken"
+
+#: src/veritysetup.c:472
+msgid "Path to device with error correction data"
+msgstr ""
+
+#: src/veritysetup.c:472 src/integritysetup.c:543
+msgid "path"
+msgstr ""
+
+#: src/veritysetup.c:473
+msgid "Starting offset on the hash device"
+msgstr "De startplaats op het hash-apparaat"
+
+#: src/veritysetup.c:474
+#, fuzzy
+msgid "Starting offset on the FEC device"
+msgstr "De startplaats op het hash-apparaat"
+
+#: src/veritysetup.c:475
+msgid "Hash algorithm"
+msgstr "Hash-algoritme"
+
+#: src/veritysetup.c:475
+msgid "string"
+msgstr "tekenreeks"
+
+#: src/veritysetup.c:476
+msgid "Salt"
+msgstr "Salt"
+
+#: src/veritysetup.c:476
+msgid "hex string"
+msgstr "hex-tekenreeks"
+
+#: src/veritysetup.c:478
+#, fuzzy
+msgid "Path to root hash signature file"
+msgstr "Creatie hash-gebied gefaald.\n"
+
+#: src/veritysetup.c:479
+msgid "Restart kernel if corruption is detected"
+msgstr "Kernel herstarten bij ontdekking van corruptie"
+
+#: src/veritysetup.c:480
+msgid "Ignore corruption, log it only"
+msgstr "Datacorruptie negeren, enkel loggen"
+
+#: src/veritysetup.c:481
+msgid "Do not verify zeroed blocks"
+msgstr "Op nul ingestelde blokken niet controleren"
+
+#: src/veritysetup.c:482
+msgid "Verify data block only the first time it is read"
+msgstr ""
+
+#: src/veritysetup.c:582
+#, fuzzy
+msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation.\n"
+msgstr "Opties --ignore-corruption, --restart-on-corruption of --ignore-zero-blocks kunnen enkel bij een create-operatie gebruikt worden.\n"
+
+#: src/veritysetup.c:587
+#, fuzzy
+msgid "Option --root-hash-signature can be used only for open operation.\n"
+msgstr "Optie --allow-discards wordt enkel toegestaan voor de open-operatie.\n"
+
+#: src/veritysetup.c:592
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together.\n"
+msgstr "Opties --ignore-corruption en --restart-on-corruption kunnen niet samen gebruikt worden.\n"
+
+#: src/integritysetup.c:83 src/utils_password.c:305
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Kan sleutelbestand %s niet lezen."
+
+#: src/integritysetup.c:87 src/utils_password.c:310
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Kan %d bytes uit sleutelbestand %s niet lezen."
+
+#: src/integritysetup.c:253
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr ""
+
+#: src/integritysetup.c:473 src/integritysetup.c:477
+#, fuzzy
+msgid "<integrity_device>"
+msgstr "apparaat controleren"
+
+#: src/integritysetup.c:474
+msgid "<integrity_device> <name>"
+msgstr ""
+
+#: src/integritysetup.c:496
+#, fuzzy, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<naam> is de naam van het onder %s te creëren apparaat\n"
+"<gegevensapparaat> is het de naam van het gegevensapparaat\n"
+"<hash-apparaat> is de naam van het apparaat dat de verificatiegegevens bevat\n"
+"<root-hash> is de hash van de rootnode op <hash-apparaat>\n"
+
+#: src/integritysetup.c:501
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+msgstr ""
+
+#: src/integritysetup.c:543
+msgid "Path to data device (if separated)"
+msgstr ""
+
+#: src/integritysetup.c:545
+msgid "Journal size"
+msgstr ""
+
+#: src/integritysetup.c:546
+msgid "Interleave sectors"
+msgstr ""
+
+#: src/integritysetup.c:547
+msgid "Journal watermark"
+msgstr ""
+
+#: src/integritysetup.c:547
+msgid "percent"
+msgstr ""
+
+#: src/integritysetup.c:548
+msgid "Journal commit time"
+msgstr ""
+
+#: src/integritysetup.c:548 src/integritysetup.c:550
+msgid "ms"
+msgstr ""
+
+#: src/integritysetup.c:549
+msgid "Number of 512-byte sectors per bit (bitmap mode)."
+msgstr ""
+
+#: src/integritysetup.c:550
+msgid "Bitmap mode flush time"
+msgstr ""
+
+#: src/integritysetup.c:551
+msgid "Tag size (per-sector)"
+msgstr ""
+
+#: src/integritysetup.c:552
+msgid "Sector size"
+msgstr ""
+
+#: src/integritysetup.c:553
+msgid "Buffers size"
+msgstr ""
+
+#: src/integritysetup.c:555
+msgid "Data integrity algorithm"
+msgstr ""
+
+#: src/integritysetup.c:556
+#, fuzzy
+msgid "The size of the data integrity key"
+msgstr "De grootte van de encryptiesleutel"
+
+#: src/integritysetup.c:557
+#, fuzzy
+msgid "Read the integrity key from a file"
+msgstr "De sleutel uit een bestand lezen."
+
+#: src/integritysetup.c:559
+msgid "Journal integrity algorithm"
+msgstr ""
+
+#: src/integritysetup.c:560
+#, fuzzy
+msgid "The size of the journal integrity key"
+msgstr "De grootte van de encryptiesleutel"
+
+#: src/integritysetup.c:561
+#, fuzzy
+msgid "Read the journal integrity key from a file"
+msgstr "De sleutel uit een bestand lezen."
+
+#: src/integritysetup.c:563
+msgid "Journal encryption algorithm"
+msgstr ""
+
+#: src/integritysetup.c:564
+#, fuzzy
+msgid "The size of the journal encryption key"
+msgstr "De grootte van de encryptiesleutel"
+
+#: src/integritysetup.c:565
+#, fuzzy
+msgid "Read the journal encryption key from a file"
+msgstr "De sleutel uit een bestand lezen."
+
+#: src/integritysetup.c:568
+msgid "Recovery mode (no journal, no tag checking)"
+msgstr ""
+
+#: src/integritysetup.c:569
+msgid "Use bitmap to track changes and disable journal for integrity device"
+msgstr ""
+
+#: src/integritysetup.c:570
+msgid "Recalculate initial tags automatically."
+msgstr ""
+
+#: src/integritysetup.c:641
+#, fuzzy
+msgid "Option --integrity-recalculate can be used only for open action."
+msgstr "Optie --allow-discards wordt enkel toegestaan voor de open-operatie.\n"
+
+#: src/integritysetup.c:656
+msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action.\n"
+msgstr ""
+
+#: src/integritysetup.c:662
+#, fuzzy
+msgid "Invalid journal size specification."
+msgstr "Ongeldig apparaatsgrootte ingegeven."
+
+#: src/integritysetup.c:667
+msgid "Both key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:670
+msgid "Integrity algorithm must be specified if integrity key is used."
+msgstr ""
+
+#: src/integritysetup.c:675
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:678
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr ""
+
+#: src/integritysetup.c:683
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:686
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr ""
+
+#: src/integritysetup.c:690
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr ""
+
+#: src/integritysetup.c:694
+msgid "Journal options cannot be used in bitmap mode."
+msgstr ""
+
+#: src/integritysetup.c:698
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:172
+msgid "Reencryption already in-progress."
+msgstr "Herencryptie is al bezig"
+
+#: src/cryptsetup_reencrypt.c:201
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Kan %s niet exclusief openen, apparaat wordt gebruikt."
+
+#: src/cryptsetup_reencrypt.c:215 src/cryptsetup_reencrypt.c:1128
+msgid "Allocation of aligned memory failed."
+msgstr "Reservering van uitgelijnd geheugen gefaald."
+
+#: src/cryptsetup_reencrypt.c:222
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Kan apparaat niet lezen: %s."
+
+#: src/cryptsetup_reencrypt.c:233
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "LUKS1-apparaat %s wordt als onbruikbaar gemarkeerd."
+
+#: src/cryptsetup_reencrypt.c:237
+#, c-format
+msgid "Setting LUKS2 offline reencrypt flag on device %s."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:254
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Kan apparaat %s niet beschrijven."
+
+#: src/cryptsetup_reencrypt.c:302
+msgid "Cannot write reencryption log file."
+msgstr "Kan herencryptie-logbestand niet schrijven."
+
+#: src/cryptsetup_reencrypt.c:358
+msgid "Cannot read reencryption log file."
+msgstr "Kan herencryptie-logbestand niet lezen."
+
+#: src/cryptsetup_reencrypt.c:396
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Logbestand %s bestaat reeds, herencryptie wordt herstart.\n"
+
+#: src/cryptsetup_reencrypt.c:445
+msgid "Activating temporary device using old LUKS header."
+msgstr "Activatie van tijdelijke apparaat met oude LUKS-koptekst."
+
+#: src/cryptsetup_reencrypt.c:455
+msgid "Activating temporary device using new LUKS header."
+msgstr "Activatie van tijdelijke apparaat met nieuwe LUKS-koptekst."
+
+#: src/cryptsetup_reencrypt.c:465
+msgid "Activation of temporary devices failed."
+msgstr "Activatie van tijdelijke apparaten gefaald."
+
+#: src/cryptsetup_reencrypt.c:552
+msgid "Failed to set data offset."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:558
+msgid "Failed to set metadata size."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:566
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Nieuwe LUKS-koptekst voor apparaat %s aangemaakt."
+
+#: src/cryptsetup_reencrypt.c:626
+#, c-format
+msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:648
+msgid "Failed to read activation flags from backup header."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:652
+#, fuzzy
+msgid "Failed to write activation flags to new header."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: src/cryptsetup_reencrypt.c:656 src/cryptsetup_reencrypt.c:660
+#, fuzzy
+msgid "Failed to read requirements from backup header."
+msgstr "Lezen uit sleutelopslag is mislukt."
+
+#: src/cryptsetup_reencrypt.c:698
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Reservekopie van %s-koptekst op apparaat %s is aangemaakt."
+
+#: src/cryptsetup_reencrypt.c:761
+msgid "Creation of LUKS backup headers failed."
+msgstr "Creatie van LUKS-reservekopteksten gefaald."
+
+#: src/cryptsetup_reencrypt.c:894
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Kan %s-koptekst op apparaat %s niet herstellen."
+
+#: src/cryptsetup_reencrypt.c:896
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "%s-koptekst op apparaat %s is hersteld."
+
+#: src/cryptsetup_reencrypt.c:1100 src/cryptsetup_reencrypt.c:1106
+msgid "Cannot open temporary LUKS device."
+msgstr "Kan tijdelijk LUKS-apparaat niet openen."
+
+#: src/cryptsetup_reencrypt.c:1111 src/cryptsetup_reencrypt.c:1116
+msgid "Cannot get device size."
+msgstr "Kan apparaatgrootte niet lezen."
+
+#: src/cryptsetup_reencrypt.c:1151
+msgid "IO error during reencryption."
+msgstr "Invoer/uitvoerfout tijdens herencryptie."
+
+#: src/cryptsetup_reencrypt.c:1182
+msgid "Provided UUID is invalid."
+msgstr "Opgegeven UUID is ongeldig."
+
+#: src/cryptsetup_reencrypt.c:1416
+msgid "Cannot open reencryption log file."
+msgstr "Kan herencryptie-logbestand niet openen."
+
+#: src/cryptsetup_reencrypt.c:1422
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Er is geen ontsleutelingsproces aan de gang. Het opgegeven UUID kan enkel gebruikt worden om een geschorst ontsleutelingsproces opnieuw te starten."
+
+#: src/cryptsetup_reencrypt.c:1497
+#, c-format
+msgid "Changed pbkdf parameters in keyslot %i."
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:1609
+msgid "Reencryption block size"
+msgstr "Blokgrootte voor herencryptie"
+
+#: src/cryptsetup_reencrypt.c:1609
+msgid "MiB"
+msgstr "MiB"
+
+#: src/cryptsetup_reencrypt.c:1613
+msgid "Do not change key, no data area reencryption"
+msgstr "Sleutel niet wijzigen; gegevensgebied wordt niet opnieuw versleuteld"
+
+#: src/cryptsetup_reencrypt.c:1615
+msgid "Read new volume (master) key from file"
+msgstr "De (hoofd)sleutel tot het opslagmedium uit een bestand lezen"
+
+#: src/cryptsetup_reencrypt.c:1616
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "PBKDF2 herhalingstijd voor LUKS (in ms)"
+
+#: src/cryptsetup_reencrypt.c:1622
+msgid "Use direct-io when accessing devices"
+msgstr "'direct-io' gebruiken bij het lezen van apparaten"
+
+#: src/cryptsetup_reencrypt.c:1623
+msgid "Use fsync after each block"
+msgstr "Na elk blok 'fsync' gebruiken"
+
+#: src/cryptsetup_reencrypt.c:1624
+msgid "Update log file after every block"
+msgstr "Na elk blok het logbestand bijwerken"
+
+#: src/cryptsetup_reencrypt.c:1625
+msgid "Use only this slot (others will be disabled)"
+msgstr "Enkel deze plaats gebruiken (anderen worden uitgeschakeld)"
+
+#: src/cryptsetup_reencrypt.c:1630
+msgid "Create new header on not encrypted device"
+msgstr "Nieuwe koptekst op niet-versleuteld apparaat invoeren"
+
+#: src/cryptsetup_reencrypt.c:1631
+msgid "Permanently decrypt device (remove encryption)"
+msgstr "Apparaat permanent ontsleutelen (encryptie verwijderen)"
+
+#: src/cryptsetup_reencrypt.c:1632
+msgid "The UUID used to resume decryption"
+msgstr "Het UUID om de ontsleuteling te hervatten"
+
+#: src/cryptsetup_reencrypt.c:1633
+msgid "Type of LUKS metadata: luks1, luks2"
+msgstr "Soorten apparaat-metadata: luks, plain, loopaes, tcrypt"
+
+#: src/cryptsetup_reencrypt.c:1652
+msgid "[OPTION...] <device>"
+msgstr "[OPTIE...] <apparaat>"
+
+#: src/cryptsetup_reencrypt.c:1660
+#, fuzzy, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Herencryptie zal sleutel tot het opslagmedium %s%s%s%s wijzigen.\n"
+
+#: src/cryptsetup_reencrypt.c:1661
+msgid "volume key"
+msgstr ""
+
+#: src/cryptsetup_reencrypt.c:1663
+#, fuzzy
+msgid "set hash to "
+msgstr ", stel hash in op "
+
+#: src/cryptsetup_reencrypt.c:1664
+msgid ", set cipher to "
+msgstr ", stel sleutelalgoritme in op "
+
+#: src/cryptsetup_reencrypt.c:1668
+msgid "Argument required."
+msgstr "Argument is vereist."
+
+#: src/cryptsetup_reencrypt.c:1696
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Enkel waarden tussen 1 MB en 64 MB zijn toegestaan als herencryptieblokgrootte."
+
+#: src/cryptsetup_reencrypt.c:1723
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "Maximum apparaatsverkleiningsgrootte is 64 MB."
+
+#: src/cryptsetup_reencrypt.c:1730
+#, fuzzy
+msgid "Option --new must be used together with --reduce-device-size or --header."
+msgstr "Optie --new moet samen met --reduce-device-size gebruikt worden."
+
+#: src/cryptsetup_reencrypt.c:1734
+#, fuzzy
+msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+msgstr "Optie -- keep-key kan enkel samen met --hash of --iter-time gebruikt worden."
+
+#: src/cryptsetup_reencrypt.c:1738
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "Optie --new kan niet samen met --decrypt gebruikt worden."
+
+#: src/cryptsetup_reencrypt.c:1742
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "Optie --decrypt is niet verenigbaar met de verschafte parameters."
+
+#: src/cryptsetup_reencrypt.c:1746
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "Optie --uuid kan enkel samen met --decrypt gebruikt worden."
+
+#: src/cryptsetup_reencrypt.c:1750
+msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+msgstr ""
+
+#: src/utils_tools.c:151
+msgid "Error reading response from terminal."
+msgstr "Fout bij het lezen van antwoord uit de terminal."
+
+#: src/utils_tools.c:186
+msgid "Command successful.\n"
+msgstr "Opdracht succesvol.\n"
+
+#: src/utils_tools.c:194
+msgid "wrong or missing parameters"
+msgstr ""
+
+#: src/utils_tools.c:196
+#, fuzzy
+msgid "no permission or bad passphrase"
+msgstr "Voer enig wachtwoord in: "
+
+#: src/utils_tools.c:198
+#, fuzzy
+msgid "out of memory"
+msgstr "Kan geheugen niet ontgrendelen.\n"
+
+#: src/utils_tools.c:200
+msgid "wrong device or file specified"
+msgstr ""
+
+#: src/utils_tools.c:202
+#, fuzzy
+msgid "device already exists or device is busy"
+msgstr "Apparaat %s bestaat reeds.\n"
+
+#: src/utils_tools.c:204
+msgid "unknown error"
+msgstr ""
+
+#: src/utils_tools.c:206
+#, fuzzy, c-format
+msgid "Command failed with code %i (%s).\n"
+msgstr "Opdracht is mislukt met code %i"
+
+#: src/utils_tools.c:283
+#, fuzzy, c-format
+msgid "Key slot %i created."
+msgstr "Sleutelplaats %d werd gewijzigd.\n"
+
+#: src/utils_tools.c:285
+#, fuzzy, c-format
+msgid "Key slot %i unlocked."
+msgstr "Sleutelplaats %d is ontgrendeld.\n"
+
+#: src/utils_tools.c:287
+#, fuzzy, c-format
+msgid "Key slot %i removed."
+msgstr "Sleutelplaats %d is ontgrendeld.\n"
+
+#: src/utils_tools.c:296
+#, c-format
+msgid "Token %i created."
+msgstr ""
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "Token %i removed."
+msgstr ""
+
+#: src/utils_tools.c:464
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+
+#: src/utils_tools.c:475
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr ""
+
+#: src/utils_tools.c:483
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr ""
+
+#: src/utils_tools.c:504 src/utils_tools.c:568
+#, fuzzy
+msgid "Failed to initialize device signature probes."
+msgstr "Kan geen map voor de apparaatstoewijzer verkrijgen."
+
+#: src/utils_tools.c:548
+#, fuzzy, c-format
+msgid "Failed to stat device %s."
+msgstr "Kan status van sleutelbestand niet opvragen.\n"
+
+#: src/utils_tools.c:561
+#, c-format
+msgid "Device %s is in use. Can not proceed with format operation."
+msgstr ""
+
+#: src/utils_tools.c:563
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr ""
+
+#: src/utils_tools.c:577
+#, c-format
+msgid "Existing '%s' partition signature (offset: %<PRIi64> bytes) on device %s will be wiped."
+msgstr ""
+
+#: src/utils_tools.c:580
+#, c-format
+msgid "Existing '%s' superblock signature (offset: %<PRIi64> bytes) on device %s will be wiped."
+msgstr ""
+
+#: src/utils_tools.c:583
+#, fuzzy
+msgid "Failed to wipe device signature."
+msgstr "Schrijven naar sleutelopslag is mislukt.\n"
+
+#: src/utils_tools.c:590
+#, fuzzy, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Kan geen map voor de apparaatstoewijzer verkrijgen."
+
+#: src/utils_tools.c:629
+#, fuzzy
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr "Blokgrootte herencryptie"
+
+#: src/utils_password.c:43 src/utils_password.c:75
+#, fuzzy, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Kan wachtwoordkwaliteit niet nakijken: %s\n"
+
+#: src/utils_password.c:51
+#, fuzzy, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Wachtwoordkwaliteitscontrole gefaald:\n"
+"%s\n"
+
+#: src/utils_password.c:83
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Wachtwoordkwaliteitscontrole gefaald: wachtwoord is van slechte kwaliteit (%s)"
+
+#: src/utils_password.c:193 src/utils_password.c:208
+msgid "Error reading passphrase from terminal."
+msgstr "Fout bij het lezen van het wachtwoord uit de terminal."
+
+#: src/utils_password.c:206
+msgid "Verify passphrase: "
+msgstr "Voer wachtwoord nogmaals in: "
+
+#: src/utils_password.c:213
+msgid "Passphrases do not match."
+msgstr "Wachtwoorden komen niet overeen."
+
+#: src/utils_password.c:250
+msgid "Cannot use offset with terminal input."
+msgstr "Kan de gegevenspositie niet via terminalinvoer gebruiken."
+
+#: src/utils_password.c:253
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Voer wachtwoord in: "
+
+#: src/utils_password.c:256
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Voer wachtwoord in voor %s: "
+
+#: src/utils_password.c:287
+msgid "No key available with this passphrase."
+msgstr "Geen sleutel beschikbaar met dit wachtwoord."
+
+#: src/utils_password.c:289
+msgid "No usable keyslot is available."
+msgstr ""
+
+#: src/utils_password.c:328
+#, fuzzy, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Kan bestand %s niet openen.\n"
+
+#: src/utils_password.c:335
+#, fuzzy, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Kan sleutelbestand %s niet lezen.\n"
+
+#: src/utils_luks2.c:47
+#, fuzzy, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: src/utils_luks2.c:60
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr ""
+
+#: src/utils_luks2.c:67
+#, fuzzy
+msgid "Failed to read JSON file."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: src/utils_luks2.c:72
+#, fuzzy
+msgid ""
+"\n"
+"Read interrupted."
+msgstr "VERITY-koptekst beschadigd.\n"
+
+#: src/utils_luks2.c:113
+#, fuzzy, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#: src/utils_luks2.c:122
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+
+#: src/utils_luks2.c:126
+#, fuzzy
+msgid "Failed to write JSON file."
+msgstr "Openen van sleutelbestand is mislukt.\n"
+
+#~ msgid "Replaced with key slot %d.\n"
+#~ msgstr "Vervangen door sleutelplaats %d.\n"
+
+#~ msgid "Function not available in FIPS mode.\n"
+#~ msgstr "Functie niet beschikbaar in FIPS-modus.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Te veel niveau's in de boomstructuur voor een VERITY-volume.\n"
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "geheugentoewijzingsfout in action_luksFormat"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "Sleutel %d is niet actief. Kan niet wissen.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<naam> <gegevensapparaat> <hash-apparaat> <root-hash>"
+
+#~ msgid "create active device"
+#~ msgstr "actief apparaat aanmaken"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "apparaat verwijderen (deactiveren)"
+
+#~ msgid "Activated keyslot %i.\n"
+#~ msgstr "Sleutelplaats %d geactiveerd.\n"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Vooruitgang: %5.1f%%, geschatte voltooiïngstijd %02llu:%02llu, %4llu MB geschreven, snelheid %5.1f MiB/s%s"
+
+#~ msgid "Interrupted by a signal.\n"
+#~ msgstr "Onderbroken door een signaal.\n"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Kan geen vrij loopback-apparaat vinden.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Kan apparaat %s niet openen.\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Kan doorgegeven UUID niet gebruiken tenzij ontsleuteling al bezig is.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "LUKS-apparaat %s wordt als bruikbaar gemarkeerd.\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "Waarschuwing: deze code is nog experimenteel, het kan al uw data volledig vernielen.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "Verificatie van FIPS-controlesom gefaald.\n"
+
+#~ msgid "WARNING: device %s is a partition, for TCRYPT system encryption you usually need to use whole block device path.\n"
+#~ msgstr "WAARSCHUWING: apparaat %s is een partitie; bij TCRYPT-systeemversleuteling moet u doorgaans het volledige pad naar het blok-apparaat gebruiken.\n"
+
+#~ msgid "Kernel doesn't support plain64 IV.\n"
+#~ msgstr "Kernel ondersteunt plain64 IV niet.\n"
+
+#~ msgid "Enter LUKS passphrase: "
+#~ msgstr "Voer LUKS-wachtwoord in: "
+
+#~ msgid "Enter new LUKS passphrase: "
+#~ msgstr "Voer nieuw LUKS-wachtwoord in: "
+
+#~ msgid "Enter any LUKS passphrase: "
+#~ msgstr "Voer een LUKS-wachtwoord in: "
+
+#~ msgid "Cannot open device %s for %s%s access.\n"
+#~ msgstr "Kan apparaat %s niet openen voor %s%s-toegang.\n"
+
+#~ msgid "read-only"
+#~ msgstr "alleen-lezen"
+
+#~ msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+#~ msgstr "WAARSCHUWING!!! Mogelijk onveilig geheugen. Bent u root?\n"
+
+#~ msgid "Unable to obtain sector size for %s"
+#~ msgstr "Kan sectorgrootte van %s niet verkrijgen"
+
+#~ msgid "Backup file %s doesn't exist.\n"
+#~ msgstr "Reservekopiebestand %s bestaat niet.\n"
+
+#~ msgid "<name> <device>"
+#~ msgstr "<naam> <apparaat>"
+
+#~ msgid "create device"
+#~ msgstr "apparaat aanmaken"
+
+#~ msgid "remove device"
+#~ msgstr "apparaat verwijderen"
+
+#~ msgid "remove LUKS mapping"
+#~ msgstr "LUKS-toewijzing verwijderen"
+
+#~ msgid "open loop-AES device as mapping <name>"
+#~ msgstr "loop-AES-apparaat als toewijzing <naam> openen"
+
+#~ msgid "remove loop-AES mapping"
+#~ msgstr "loop-AES-toewijzing verwijderen"
+
+#~ msgid "Cannot use device %s (crypt segments overlaps or in use by another device).\n"
+#~ msgstr "Kan apparaat %s niet gebruiken (cryptsegmenten overlappen of worden door een ander apparaat gebruikt).\n"
+
+#~ msgid "Block mode XTS is available since kernel 2.6.24.\n"
+#~ msgstr "Blokmodus XTS is beschikbaar vanaf kernelversie 2.6.24.\n"
+
+#~ msgid "Key size in LRW mode must be 256 or 512 bits.\n"
+#~ msgstr "In LRW-modus moet de sleutelgrootte 256 of 512 bits zijn.\n"
+
+#~ msgid "Block mode LRW is available since kernel 2.6.20.\n"
+#~ msgstr "Blokmodus LRW is beschikbaar vanaf kernelversie 2.6.20.\n"
+
+#~ msgid "Negative keyfile size not permitted.\n"
+#~ msgstr "Een negatieve sleutelbestandsgrootte is niet toegestaan.\n"
+
+#~ msgid "Warning: exhausting read requested, but key file is not a regular file, function might never return.\n"
+#~ msgstr "Waarschuwing: volledige lezing aangevraagd, maar sleutelbestand is geen regulier bestand, functie zal misschien nooit terugkeren.\n"
+
+#~ msgid "Cannot find compatible device-mapper kernel modules.\n"
+#~ msgstr "Kan geen compatibele kernelmodules voor apparaatstoewijzer vinden.\n"
+
+#~ msgid "Cannot open device: %s\n"
+#~ msgstr "Kan apparaat niet openen: %s\n"
+
+#~ msgid "BLKGETSIZE failed on device %s.\n"
+#~ msgstr "BLKGETSIZE() is mislukt op apparaat %s.\n"
+
+#~ msgid "identical to luksKillSlot - DEPRECATED - see man page"
+#~ msgstr "identiek aan luksKillSlot - VEROUDERD - zie man-pagina"
+
+#~ msgid "modify active device - DEPRECATED - see man page"
+#~ msgstr "actief apparaat wijzigen - VEROUDERD - zie man-pagina"
+
+#~ msgid ""
+#~ "The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\n"
+#~ "WARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"
+#~ msgstr ""
+#~ "De herlaadactie is verouderd. Gebruik “dmsetup reload” indien u deze functionaliteit echt nodig hebt.\n"
+#~ "WAARSCHUWING: gebruik de herlaadactie niet om LUKS-apparaten te “touchen”. Indien u dat wilt doen, typ nu Ctrl-C.\n"
+
+#~ msgid "Obsolete option --non-exclusive is ignored.\n"
+#~ msgstr "Verouderde optie --non-exclusive wordt genegeerd.\n"
+
+#~ msgid "Read the key from a file (can be /dev/random)"
+#~ msgstr "De sleutel uit een bestand lezen (mag /dev/random zijn)"
+
+#~ msgid "(Obsoleted, see man page.)"
+#~ msgstr "(Verouderd, zie man-pagina.)"
+
+#~ msgid "%s is not LUKS device.\n"
+#~ msgstr "%s is geen LUKS-apparaat.\n"
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..dd3b1a8
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,3851 @@
+# Polish translation for cryptsetup.
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Jakub Bogusz <qboosh@pld-linux.org>, 2010-2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.0-rc1\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2022-11-20 12:38+0100\n"
+"PO-Revision-Date: 2022-11-20 20:45+0100\n"
+"Last-Translator: Jakub Bogusz <qboosh@pld-linux.org>\n"
+"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Nie można zainicjować device-mappera w czasie działania jako nie-root."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Nie można zainicjować device-mappera. Czy moduł jądra dm_mod jest wczytany?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Żądana flaga odroczona nie jest obsługiwana."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID dla urządzenia %s został skrócony."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Nieznany typ celu dm."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Żądane opcje dm-crypta dotyczące wydajności nie są obsługiwane."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Żądane opcje dm-verity dotyczące obsługi uszkodzenia danych nie są obsługiwane."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "Żądana opcja taskletów dm-verity nie jest obsługiwana."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Żądane opcje FEC dm-verity nie są obsługiwane."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Żądane opcje integralności danych nie są obsługiwane."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "Żądana opcja sector_size nie jest obsługiwana."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Żądane automatyczne przeliczenie znaczników integralności nie jest obsługiwane."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Porzucenie/TRIM nie jest obsługiwane."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Żądany tryb bitmapy dm-integrity nie jest obsługiwany."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Nie udało się odpytać segmentu dm-%s."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Entropia w systemie wyczerpała się w trakcie generowania klucza wolumenu.\n"
+"Proszę poruszać myszą albo wpisać trochę tekstu w innym oknie w celu zebrania zdarzeń losowych.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Generowanie klucza (gotowe %d%%).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Działanie w trybie FIPS."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "Błąd krytyczny w trakcie inicjalizacji RNG."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Nieznane żądanie jakości RNG."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Błąd odczytu z RNG."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Nie można zainicjować backendu kryptograficznego RNG."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Nie można zainicjować backendu kryptograficznego."
+
+#: lib/setup.c:268 lib/setup.c:2139 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Algorytm skrótu %s nie jest obsługiwany."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Błąd przetwarzania klucza (użyto algorytmu skrótu %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Nie można określić rodzaju urządzenia. Niezgodny sposób uaktywniania urządzenia?"
+
+#: lib/setup.c:348 lib/setup.c:3308
+msgid "This operation is supported only for LUKS device."
+msgstr "Ta operacja jest obsługiwana tylko dla urządzeń LUKS."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Ta operacja jest obsługiwana tylko dla urządzeń LUKS2."
+
+#: lib/setup.c:430 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Wszyskie miejsca na klucze są pełne."
+
+#: lib/setup.c:441
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Numer klucza %d jest błędny, proszę wybrać wartość między 0 a %d."
+
+#: lib/setup.c:447
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Miejsce na klucz %d jest pełne, proszę wybrać inne."
+
+#: lib/setup.c:532 lib/setup.c:3030
+msgid "Device size is not aligned to device logical block size."
+msgstr "Rozmiar urządzenia nie jest wyrównany do rozmiaru bloku logicznego urządzenia."
+
+#: lib/setup.c:630
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Wykryto nagłówek, ale urządzenie %s jest zbyt małe."
+
+#: lib/setup.c:671 lib/setup.c:2930 lib/setup.c:4275
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Ta operacja nie jest obsługiwana dla tego rodzaju urządzenia."
+
+#: lib/setup.c:676
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Niedozwolona operacja w trakcie ponownego szyfrowania."
+
+#: lib/setup.c:762
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Nie udało się wycofać zmian w metadanych LUKS2 w pamięci."
+
+#: lib/setup.c:849 lib/luks1/keymanage.c:247 lib/luks1/keymanage.c:525
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1433
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Urządzenie %s nie jest prawidłowym urządzeniem LUKS."
+
+#: lib/setup.c:852 lib/luks1/keymanage.c:528
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Nieobsługiwana wersja LUKS %d."
+
+#: lib/setup.c:1479 lib/setup.c:2679 lib/setup.c:2761 lib/setup.c:2773
+#: lib/setup.c:2940 lib/setup.c:4752
+#, c-format
+msgid "Device %s is not active."
+msgstr "Urządzenie %s nie jest aktywne."
+
+#: lib/setup.c:1496
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Urządzenie stojące za urządzeniem szyfrowanym %s zniknęło."
+
+#: lib/setup.c:1578
+msgid "Invalid plain crypt parameters."
+msgstr "Błędne parametry szyfru plain."
+
+#: lib/setup.c:1583 lib/setup.c:2042
+msgid "Invalid key size."
+msgstr "Błędny rozmiar klucza."
+
+#: lib/setup.c:1588 lib/setup.c:2047 lib/setup.c:2250
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID nie jest obsługiwany dla tego rodzaju szyfrowania."
+
+#: lib/setup.c:1593 lib/setup.c:2052
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Osobne urządzenie metadanych nie jest obsługiwane dla tego rodzaju szyfrowania."
+
+#: lib/setup.c:1603 lib/setup.c:1819 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Nieobsługiwany rozmiar sektora szyfrowania."
+
+#: lib/setup.c:1611 lib/setup.c:1947 lib/setup.c:3024
+msgid "Device size is not aligned to requested sector size."
+msgstr "Rozmiar urządzenia nie jest wyrównany do żądanego rozmiaru sektura."
+
+#: lib/setup.c:1663 lib/setup.c:1787
+msgid "Can't format LUKS without device."
+msgstr "Nie można sformatować LUKS-a bez urządzenia."
+
+#: lib/setup.c:1669 lib/setup.c:1793
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Żądane wyrównanie metadanych nie jest zgodne z offsetem danych."
+
+#: lib/setup.c:1744 lib/setup.c:1964 lib/setup.c:1985 lib/setup.c:2262
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Nie można wymazać nagłówka na urządzeniu %s."
+
+#: lib/setup.c:1757 lib/setup.c:2024
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Urządzenie %s jest zbyt małe do uaktywnienia, nie ma miejsca pozostałego na dane.\n"
+
+#: lib/setup.c:1828
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "UWAGA: uaktywnienie urządzenia się nie powiedzie, dm-crypt nie ma obsługi żądanego rozmiaru sektora szyfrowania.\n"
+
+#: lib/setup.c:1851
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Klucz wolumenu jest zbyt mały do szyfrowania z rozszerzeniami integralności."
+
+#: lib/setup.c:1911
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Szyfr %s-%s (rozmiar klucza w bitach: %zd) nie jest dostępny."
+
+#: lib/setup.c:1937
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "UWAGA: rozmiar metadanych LUKS2 zmienił się na %<PRIu64> (w bajtach).\n"
+
+#: lib/setup.c:1941
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "UWAGA: rozmiar obszaru kluczy LUKS2 zmienił się na %<PRIu64> (w bajtach).\n"
+
+#: lib/setup.c:1967 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Urządzenie %s jest zbyt małe."
+
+#: lib/setup.c:1978 lib/setup.c:2004
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Nie można sformatować urządzenia %s, które jest w użyciu."
+
+#: lib/setup.c:1981 lib/setup.c:2007
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Nie można sformatować urządzenia %s, brak uprawnień."
+
+#: lib/setup.c:1993 lib/setup.c:2322
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Nie można sformatować integralności dla urządzenia %s."
+
+#: lib/setup.c:2011
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Nie można sformatować urządzenia %s."
+
+#: lib/setup.c:2037
+msgid "Can't format LOOPAES without device."
+msgstr "Nie można sformatować urządzenia LUKSAES bez urządzenia."
+
+#: lib/setup.c:2082
+msgid "Can't format VERITY without device."
+msgstr "Nie można sformatować VERITY bez urządzenia."
+
+#: lib/setup.c:2093 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Nieobsługiwany typ hasza VERITY %d."
+
+#: lib/setup.c:2099 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Nieobsługiwany rozmiar bloku VERITY."
+
+#: lib/setup.c:2104 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Nieobsługiwany offset hasza VERITY."
+
+#: lib/setup.c:2109
+msgid "Unsupported VERITY FEC offset."
+msgstr "Nieobsługiwany offset FEC VERITY."
+
+#: lib/setup.c:2133
+msgid "Data area overlaps with hash area."
+msgstr "Obszar danych zachodzi na obszar skrótów."
+
+#: lib/setup.c:2158
+msgid "Hash area overlaps with FEC area."
+msgstr "Obszar skrótu zachodzi na obszar FEC."
+
+#: lib/setup.c:2165
+msgid "Data area overlaps with FEC area."
+msgstr "Obszar danych zachodzi na obszar FEC."
+
+#: lib/setup.c:2301
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "UWAGA: żądany rozmiar znacznika %d B różni się od rozmiaru wyjścia %s (%d B).\n"
+
+#: lib/setup.c:2380
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Nieznany typ żądanego urządzenia szyfrującego %s."
+
+#: lib/setup.c:2687 lib/setup.c:2766 lib/setup.c:2779
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Nieobsługiwane parametry urządzenia %s."
+
+#: lib/setup.c:2693 lib/setup.c:2786 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Niezgodne parametry dla urządzenia %s."
+
+#: lib/setup.c:2810
+msgid "Crypt devices mismatch."
+msgstr "Urządzenia szyfrowane nie zgadzają się."
+
+#: lib/setup.c:2847 lib/setup.c:2852 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Nie udało się przeładować urządzenia %s."
+
+#: lib/setup.c:2858 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Nie udało się wstrzymać urządzenia %s."
+
+#: lib/setup.c:2870 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Nie udało wznowić urządzenia %s."
+
+#: lib/setup.c:2885
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Błąd krytyczny przy przeładowywaniu urządzenia %s (w oparciu o urządzenie %s)."
+
+#: lib/setup.c:2888 lib/setup.c:2890
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Nie udało się przełączyć urządzenia %s na dm-error."
+
+#: lib/setup.c:2972
+msgid "Cannot resize loop device."
+msgstr "Nie można zmienić rozmiaru urządzenia loopback."
+
+#: lib/setup.c:3015
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "UWAGA: maksymalny rozmiar jest już ustawiony lub jądro nie obsługuje zmiany rozmiaru.\n"
+
+#: lib/setup.c:3076
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Zmiana rozmiaru nie powiodła się, jądro tego nie obsługuje."
+
+#: lib/setup.c:3108
+msgid "Do you really want to change UUID of device?"
+msgstr "Czy na pewno zmienić UUID urządzenia?"
+
+#: lib/setup.c:3200
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Plik nagłówka kopii zapasowej nie zawiera zgodnego nagłówka LUKS."
+
+#: lib/setup.c:3316
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Wolumen %s nie jest aktywny."
+
+#: lib/setup.c:3327
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Wolumen %s już został wstrzymany."
+
+#: lib/setup.c:3340
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Wstrzymywanie nie jest obsługiwane dla urządzenia %s."
+
+#: lib/setup.c:3342
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Błąd podczas wstrzymywania urządzenia %s."
+
+#: lib/setup.c:3377
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Wznawianie nie jest obsługiwane dla urządzenia %s."
+
+#: lib/setup.c:3379
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Błąd podczas wznawiania urządzenia %s."
+
+#: lib/setup.c:3413 lib/setup.c:3461 lib/setup.c:3532 lib/setup.c:3577
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Wolumen %s nie jest wstrzymany."
+
+#: lib/setup.c:3547 lib/setup.c:4528 lib/setup.c:4541 lib/setup.c:4549
+#: lib/setup.c:4562 lib/setup.c:6145 lib/setup.c:6167 lib/setup.c:6216
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Klucz wolumenu nie pasuje do wolumenu."
+
+#: lib/setup.c:3725
+msgid "Failed to swap new key slot."
+msgstr "Nie udało się podstawić nowego klucza."
+
+#: lib/setup.c:3823
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Numer klucza %d jest nieprawidłowy."
+
+#: lib/setup.c:3829 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Klucz %d nie jest aktywny."
+
+#: lib/setup.c:3848
+msgid "Device header overlaps with data area."
+msgstr "Nagłówek urządzenia zachodzi na obszar danych."
+
+#: lib/setup.c:4153
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Ponowne szyfrowanie trwa. Nie można uaktywnić urządzenia."
+
+#: lib/setup.c:4155 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Nie udało się uzyskać blokady ponownego szyfrowania."
+
+#: lib/setup.c:4168 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Odtwarzanie ponownego szyfrowania LUKS2 nie powiodło się."
+
+#: lib/setup.c:4340 lib/setup.c:4606
+msgid "Device type is not properly initialized."
+msgstr "Typ urządzenia nie został właściwie zainicjalizowany."
+
+#: lib/setup.c:4388
+#, c-format
+msgid "Device %s already exists."
+msgstr "Urządzenie %s już istnieje."
+
+#: lib/setup.c:4395
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Nie można użyć urządzenia %s, nazwa jest nieprawidłowa lub nadal w użyciu."
+
+#: lib/setup.c:4515
+msgid "Incorrect volume key specified for plain device."
+msgstr "Podano niewłaściwy klucz wolumenu dla zwykłego urządzenia."
+
+#: lib/setup.c:4632
+msgid "Incorrect root hash specified for verity device."
+msgstr "Podano niewłaściwy hasz główny dla urządzenia VERITY."
+
+#: lib/setup.c:4642
+msgid "Root hash signature required."
+msgstr "Wymagany podpis hasza głównego."
+
+#: lib/setup.c:4651
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Brak pęku kluczy w jądrze: wymagany do przekazania podpisu do jądra."
+
+#: lib/setup.c:4668 lib/setup.c:6411
+msgid "Failed to load key in kernel keyring."
+msgstr "Nie udało się załadować klucza do pęku kluczy w jądrze."
+
+#: lib/setup.c:4724
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Nie udało się anulować opóźnionego usuwania z urządzenia %s."
+
+#: lib/setup.c:4731 lib/setup.c:4747 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Urządzenie %s jest nadal w użyciu."
+
+#: lib/setup.c:4756
+#, c-format
+msgid "Invalid device %s."
+msgstr "Błędne urządzenie %s."
+
+#: lib/setup.c:4896
+msgid "Volume key buffer too small."
+msgstr "Bufor klucza wolumenu zbyt mały."
+
+#: lib/setup.c:4913
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Nie można odtworzyć klucza wolumenu dla urządzenia LUKS2."
+
+#: lib/setup.c:4922
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Nie można odtworzyć klucza wolumenu dla urządzenia LUKS1."
+
+#: lib/setup.c:4932
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Nie można odtworzyć klucza wolumenu dla zwykłego urządzenia."
+
+#: lib/setup.c:4940
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Nie można odtworzyć hasza głównego dla urządzenia VERITY."
+
+#: lib/setup.c:4947
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Nie można odtworzyć klucza wolumenu dla urządzenia BITLK."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Nie można odtworzyć klucza wolumenu dla urządzenia FVAULT2."
+
+#: lib/setup.c:4954
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Ta operacja nie jest obsługiwana dla urządzenia szyfrującego %s."
+
+#: lib/setup.c:5135 lib/setup.c:5146
+msgid "Dump operation is not supported for this device type."
+msgstr "Operacja zrzutu nie jest obsługiwana dla tego rodzaju urządzenia."
+
+#: lib/setup.c:5488
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Offset danych nie jest wielokrotnością liczby bajtów %u."
+
+#: lib/setup.c:5776
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Nie można przekonwertować urządzenia %s, które jest nadal w użyciu."
+
+#: lib/setup.c:6086 lib/setup.c:6225
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Nie udało się przypisać klucza %u jako nowego klucza wolumenu."
+
+#: lib/setup.c:6110
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Nie udało się zainicjować domyślnych parametrów klucza LUKS2."
+
+#: lib/setup.c:6116
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Nie udało się przypisać klucza %d do skrótu."
+
+#: lib/setup.c:6341
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Nie można dodać klucza, wszystkie miejsca na klucze wyłączone i nie podano klucza wolumenu."
+
+#: lib/setup.c:6478
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Pęk kluczy w jądrze nie jest obsługiwany przez jądro."
+
+#: lib/setup.c:6488 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Nie udało się odczytać hasła z pęku kluczy (błąd %d)."
+
+#: lib/setup.c:6512
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Nie udało się uzyskać globalnej blokady serializacji dostępu ciężkiego pamięciowo."
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Nie udało się otworzyć pliku klucza."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Nie można odczytać pliku klucza z terminala."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "Nie udało się wykonać stat na pliku klucza."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Nie można przemieścić się do żądanego położenia pliku klucza."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:227
+#: src/utils_password.c:239
+msgid "Out of memory while reading passphrase."
+msgstr "Brak pamięci podczas odczytu hasła."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Błąd podczas odczytu hasła."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Na wejściu nie ma nic do odczytu."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Przekroczono maksymalny rozmiar pliku klucza."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "Nie można odczytać żądanej ilości danych."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1408
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Urządzenie %s nie istnieje lub dostęp jest zabroniony."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Urządzenie %s nie jest zgodne."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Zignorowano niewłaściwy rozmiar optimal-io dla urządzenia danych (%u bajtów)."
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Urządzenie %s jest zbyt małe. Wymagane przynajmniej %<PRIu64> bajtów."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Nie można użyć urządzenia %s, które jest w użyciu (już podmapowane lub zamontowane)."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Nie można użyć urządzenia %s, brak uprawnień."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Nie można uzyskać informacji o urządzeniu %s."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Nie można użyć urządzenia loopback w czasie działania jako nie-root."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Nie udało się podłączyć urządzenia loopback (wymagane urządzenie loop z flagą autoclear)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Żądany offset jest poza rzeczywistym rozmiarem urządzenia %s."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Urządzenie %s ma zerowy rozmiar."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Żądany czas docelowy PBKDF nie może być zerowy."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Nieznany typ PBKDF %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Żądany skrót %s nie jest obsługiwany."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Żądany typ PBKDF nie jest obsługiwany dla LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Wartości maksymalnej pamięci lub liczby wątków PBKDF nie mogą być ustawione dla PBKDF2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Wymuszona liczba iteracji jest zbyt mała dla %s (minimum to %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Wymuszony koszt pamięciowy jest zbyt mały dla %s (minimum to %u kB)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Żądany maksymalny koszt pamięciowy PBKDF jest zbyt duży (maksimum to %d kB)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Żądana maksymalna pamięć PBKDF nie może być zerowa."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Żądana liczba wątków PBKDF nie może być zerowa."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "W trybie FIPS obsługiwana jest tylko PBKDF2."
+
+#: lib/utils_benchmark.c:174
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Test wydajności PBKDF jest wyłączony, ale nie ustawiono liczby iteracji."
+
+#: lib/utils_benchmark.c:193
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Niekompatybilne opcje PBKDF2 (przy użyciu algorytmu skrótu %s)."
+
+#: lib/utils_benchmark.c:213
+msgid "Not compatible PBKDF options."
+msgstr "Niekompatybilne opcje PBKDF."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Blokowanie nie powiodło się. Ścieżka blokady %s/%s jest nieużywalna (brak lub nie jest katalogiem)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Blokowanie przerwane. Ścieżka blokady %s/%s jest nieużywalna (%s nie jest katalogiem)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Nie można przemieścić się we właściwe położenie urządzenia."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Błąd wymazywania urządzenia, offset %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Nie udało się ustawić odwzorowania klucza dm-crypt dla urządzenia %s.\n"
+"Proszę sprawdzić, czy jądro obsługuje szyfr %s (więcej informacji w syslogu)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Rozmiar klucza w trybie XTS musi wynosić 256 lub 512 bitów."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Określenie szyfru powinno być w formacie [szyfr]-[tryb]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:364
+#: lib/luks1/keymanage.c:675 lib/luks1/keymanage.c:1126
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Nie można zapisać na urządzenie %s, brak uprawnień."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Nie udało się otworzyć urządzenia do tymczasowego przechowywania kluczy."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Nie udało się uzyskać dostępu do urządzenia do tymczasowego przechowywania kluczy."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:61
+#: lib/luks2/luks2_keyslot_luks2.c:79 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Błąd we/wy podczas szyfrowania klucza."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:367
+#: lib/luks1/keymanage.c:628 lib/luks1/keymanage.c:678 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Nie można otworzyć urządzenia %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:138
+msgid "IO error while decrypting keyslot."
+msgstr "Błąd we/wy podczas odszyfrowywania klucza."
+
+#: lib/luks1/keymanage.c:129
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Urządzenie %s jest zbyt małe (LUKS1 wymaga przynajmniej %<PRIu64> bajtów)."
+
+#: lib/luks1/keymanage.c:150 lib/luks1/keymanage.c:158
+#: lib/luks1/keymanage.c:170 lib/luks1/keymanage.c:181
+#: lib/luks1/keymanage.c:193
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "Numer klucza LUKS %u jest nieprawidłowy."
+
+#: lib/luks1/keymanage.c:265 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Żądany plik kopii zapasowej nagłówka %s już istnieje."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Nie można utworzyć pliku kopii zapasowej nagłówka %s."
+
+#: lib/luks1/keymanage.c:274 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Nie można zapisać pliku kopii zapasowej nagłówka %s."
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Plik kopii zapasowej nie zawiera prawidłowego nagłówka LUKS."
+
+#: lib/luks1/keymanage.c:319 lib/luks1/keymanage.c:591
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Nie można otworzyć pliku kopii zapasowej nagłówka %s."
+
+#: lib/luks1/keymanage.c:327 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Nie można odczytać pliku kopii zapasowej nagłówka %s."
+
+#: lib/luks1/keymanage.c:337
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Offset danych lub rozmiar klucza różnią się między urządzeniem a kopią zapasową; przywrócenie nie powiodło się."
+
+#: lib/luks1/keymanage.c:345
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Urządzenie %s %s%s"
+
+#: lib/luks1/keymanage.c:346
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "nie zawiera nagłówka LUKS. Nadpisanie nagłówka może zniszczyć dane na tym urządzeniu."
+
+#: lib/luks1/keymanage.c:347
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "już zawiera nagłówek LUKS. Nadpisanie nagłówka zniszczy istniejące klucze."
+
+#: lib/luks1/keymanage.c:348 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"UWAGA: nagłówek prawdziwego urządzenia ma inny UUID niż kopia zapasowa!"
+
+#: lib/luks1/keymanage.c:396
+msgid "Non standard key size, manual repair required."
+msgstr "Niestandardowy rozmiar klucza, wymagana ręczna naprawa."
+
+#: lib/luks1/keymanage.c:406
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Niestandardowe wyrównanie kluczy, wymagana ręczna naprawa."
+
+#: lib/luks1/keymanage.c:415
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Tryb szyfru poprawiony (%s -> %s)."
+
+#: lib/luks1/keymanage.c:426
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Skrót szyfru poprawiony na małe litery (%s)."
+
+#: lib/luks1/keymanage.c:428 lib/luks1/keymanage.c:534
+#: lib/luks1/keymanage.c:790
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Żądany skrót LUKS %s nie jest obsługiwany."
+
+#: lib/luks1/keymanage.c:442
+msgid "Repairing keyslots."
+msgstr "Naprawianie kluczy."
+
+#: lib/luks1/keymanage.c:461
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Klucz %i: naprawiono offset (%u -> %u)."
+
+#: lib/luks1/keymanage.c:469
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Klucz %i: naprawiono pasy (%u -> %u)."
+
+#: lib/luks1/keymanage.c:478
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Klucz %i: błędna sygnatura partycji."
+
+#: lib/luks1/keymanage.c:483
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Klucz %i: zarodek wymazany."
+
+#: lib/luks1/keymanage.c:500
+msgid "Writing LUKS header to disk."
+msgstr "Zapis nagłówka LUKS na dysk."
+
+#: lib/luks1/keymanage.c:505
+msgid "Repair failed."
+msgstr "Naprawa nie powiodła się."
+
+#: lib/luks1/keymanage.c:560
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Tryb szyfru LUKS %s jest nieprawidłowy."
+
+#: lib/luks1/keymanage.c:565
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "Skrót LUKS %s jest nieprawidłowy."
+
+#: lib/luks1/keymanage.c:572 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "W nagłówku LUKS nie wykryto żadnych znanych problemów."
+
+#: lib/luks1/keymanage.c:700
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Błąd podczas uaktualniania nagłówka LUKS na urządzeniu %s."
+
+#: lib/luks1/keymanage.c:708
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Błęd podczas ponownego odczytu nagłówka LUKS po uaktualnieniu na urządzeniu %s."
+
+#: lib/luks1/keymanage.c:784
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Offset danych dla nagłówka LUKS musi wynosić 0 lub więcej niż rozmiar nagłówka."
+
+#: lib/luks1/keymanage.c:795 lib/luks1/keymanage.c:864
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:514
+msgid "Wrong LUKS UUID format provided."
+msgstr "Podano zły format LUKS UUID."
+
+#: lib/luks1/keymanage.c:817
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Nie można utworzyć nagłówka LUKS: odczyt losowego zarodka nie powiódł się."
+
+#: lib/luks1/keymanage.c:843
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Nie można utworzyć nagłówka LUKS: uzyskanie skrótu nagłówka nie powiodło się (przy użyciu algorytmu %s)."
+
+#: lib/luks1/keymanage.c:887
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Klucz numer %d jest aktywny, należy go najpierw wyczyścić."
+
+#: lib/luks1/keymanage.c:893
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Klucz %d zawiera zbyt mało pasów. Zmieniony nagłówek?"
+
+#: lib/luks1/keymanage.c:1034
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Nie można otworzyć klucza (przy użyciu skrótu %s)."
+
+#: lib/luks1/keymanage.c:1112
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Numer klucza %d jest błędny, proszę wybrać numer od 0 do %d."
+
+#: lib/luks1/keymanage.c:1130 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Nie można wymazać urządzenia %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Wykryto jeszcze nie obsługiwany plik klucza szyfrowany GPG."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Proszę użyć gpg --decrypt <PLIK-KLUCZA> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Wykryto niekompatybilny plik klucza loop-AES."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Jądro nie obsługuje odwzorowań zgodnych z loop-AES."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Błąd odczytu pliku klucza %s."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Przekroczono maksymalną długość hasła TCRYPT (%zu)."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Algorytm skrótu PBKDF2 %s nie jest dostępny, pominięto."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "Wymagany interfejs kryptograficzny jądra nie jest dostępny."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Proszę upewnić się, że moduł jądra algif_skcipher został załadowany."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Uaktywnianie nie jest obsługiwane dla rozmiaru sektora %d."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Jądro nie obsługuje uaktywniania dla tego starego trybu TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Włączanie szyfrowania systemu TCRYPT dla partycji %s."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Jądro nie obsługuje odwzorowań zgodnych z TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Ta funkcja nie jest obsługiwana bez załadowanego nagłówka TCRYPT."
+
+#: lib/bitlk/bitlk.c:275
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Przy analizie obsługiwanego Głównego Klucza Wolumenu napotkano nieoczekiwany wpis metadanych typu '%u'."
+
+#: lib/bitlk/bitlk.c:328
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Przy analizie Głównego Klucza Wolumenu napotkano błędny ciąg znaków."
+
+#: lib/bitlk/bitlk.c:332
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Przy analizie obsługiwanego Głównego Klucza Wolumenu napotkano nieoczekiwany ciąg znaków ('%s')."
+
+#: lib/bitlk/bitlk.c:349
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Przy analizie obsługiwanego Głównego Klucza Wolumenu napotkano nieoczekiwaną wartość wpisu metadanych '%u'."
+
+#: lib/bitlk/bitlk.c:451
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK w wersji 1 nie jest obecnie obsługiwany."
+
+#: lib/bitlk/bitlk.c:457
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Błędna lub nieznana sygnatura rozruchowa urządzenia BITLK."
+
+#: lib/bitlk/bitlk.c:469
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Nieobsługiwany rozmiar sektora %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:477
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Nie udało się odczytać nagłówka BITLK z %s."
+
+#: lib/bitlk/bitlk.c:502
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Nie udało się odczytać metadanych BITLK FVE z %s."
+
+#: lib/bitlk/bitlk.c:554
+msgid "Unknown or unsupported encryption type."
+msgstr "Nieznany lub nieobsługiwany rodzaj szyfrowania."
+
+#: lib/bitlk/bitlk.c:587
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Nie udało się odczytać wpisów metadanych BITLK z %s."
+
+#: lib/bitlk/bitlk.c:681
+msgid "Failed to convert BITLK volume description"
+msgstr "Nie udało się przekonwertować opisu wolumenu BITLK"
+
+#: lib/bitlk/bitlk.c:841
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Przy analizie zewnętrznego klucza napotkano nieoczekiwany wpis metadanych typu '%u'."
+
+#: lib/bitlk/bitlk.c:860
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "GUI pliku BEK '%s' nie pasuje do GUID-a wolumenu."
+
+#: lib/bitlk/bitlk.c:864
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Przy analizie zewnętrznego klucza napotkano nieoczekiwaną wartość wpisu metadanych '%u'."
+
+#: lib/bitlk/bitlk.c:903
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Nieobsługiwana wersja metadanych BEK %<PRIu32>"
+
+#: lib/bitlk/bitlk.c:908
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Nieoczekiwany rozmiar metadanych BEK %<PRIu32> nie zgadza się z długością pliku BEK"
+
+#: lib/bitlk/bitlk.c:933
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Przy analizie klucza początkowego napotkano nieoczekiwany wpis metadanych."
+
+#: lib/bitlk/bitlk.c:1029
+msgid "This operation is not supported."
+msgstr "Ta operacja nie jest obsługiwana."
+
+#: lib/bitlk/bitlk.c:1037
+msgid "Unexpected key data size."
+msgstr "Nieoczekiwany rozmiar danych klucza."
+
+#: lib/bitlk/bitlk.c:1163
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "To urządzenie BITLK jest w nieobsługiwanym stanie i może być uaktywnione."
+
+#: lib/bitlk/bitlk.c:1168
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Urządzenia BITLK o typie '%s' nie mogą być uaktywnione."
+
+#: lib/bitlk/bitlk.c:1175
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Uaktywnianie częściowo odszyfrowanych urządzeń BITLK nie jest obsługiwane."
+
+#: lib/bitlk/bitlk.c:1216
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "UWAGA: rozmiar wolumenu BitLockera %<PRIu64> nie zgadza się z rozmiarem urządzenia %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1343
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Nie można uaktywnić urządzenia, brak obsługi BITLK IV w module dm-crypt jądra."
+
+#: lib/bitlk/bitlk.c:1347
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Nie można uaktywnić urządzenia, brak obsługi dyfuzora BITLK Elephant w module dm-crypt jądra."
+
+#: lib/bitlk/bitlk.c:1351
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Nie można uaktywnić urządzenia, brak obsługi dużego rozmiaru sektora w module dm-crypt jądra."
+
+#: lib/bitlk/bitlk.c:1355
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Nie można uaktywnić urządzenia, brak modułu jądra dm-zero."
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Nie można odczytać %u bajtów nagłówka wolumenu."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Nieobsługiwana wersja FVAULT2 %<PRIu16>."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Urządzenie Verity %s nie używa nagłówka na dysku."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Nieobsługiwana wersja VERITY %d."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "Uszkodzony nagłówek VERITY."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Podano zły format UUID-a VERITY na urządzeniu %s."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Błąd podczas uaktualniania nagłówka VERITY na urządzeniu %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Weryfikacja podpisu hasza głównego nie jest obsługiwana."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Błędów nie można naprawić z urządzeniem FEC."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Znaleziono %u błędów możliwych do naprawienia z urządzeniem FEC."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Jądro nie obsługuje odwzorowań dm-verity."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Jądro nie obsługuje opcji podpisu dm-verity."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Urządzenie VERITY wykryło uszkodzenie po uaktywnieniu."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Nie wyzerowane miejsce zapasowe na pozycji %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Przepełnienie offsetu urządzenia."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Weryfikacja nie powiodła się na pozycji %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Przepełnienie obszaru skrótu."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Weryfikacja obszaru danych nie powiodła się."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Weryfikacja głównego hasza nie powiodła się."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Błąd wejścia/wyjścia podczas tworzenia obszaru haszy."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Tworzenie obszaru haszy nie powiodło się."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "UWAGA: Jądro nie może uaktywnić urządzenia, jeśli rozmiar bloku danych przekracza rozmiar strony (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Nie udało się przydzielić kontekstu RS."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Nie udało się przydzielić bufora."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Nie udało się odczytać bloku RS %<PRIu64> bajt %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Nie udało się odczytać parzystości dla bloku RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Nie udało się naprawić parzystości dla bloku %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Nie udało się zapisać parzystości dla bloku RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Dla FEC rozmiary bloków muszą się zgadzać."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Błędna liczba bajtów parzystości."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Błędna długość segmentu FEC."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Nie udało się określić rozmiaru urządzenia %s."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Wykryto niezgodne metadane dm-integrity jądra (wersja %u) na %s."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Jądro nie obsługuje odwzorowań dm-integrity."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Jądro nie obsługuje stałego wyrównania metadanych dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Jądro odmawia uaktywnienia niebezpiecznej opcji przeliczenia (p. stare opcje aktywacji, aby wymusić)."
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Nie udało się uzyskać blokady dla zapisu na urządzeniu %s."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Wykryto próbę jednoczesnego uaktualnienia metadanych LUKS2. Przerywanie operacji."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Urządzenie zawiera niejednoznaczne sygnatury, nie można automatycznie odtworzyć LUKS2.\n"
+"W celu odtworzenia należy uruchomić \"cryptsetup repair\"."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Żądany offset danych jest zbyt mały."
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "UWAGA: obszar kluczy (%<PRIu64> bajtów) bardzo mały, dostępna liczba kluczy LUKS2 jest bardzo ograniczona.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:93
+#: lib/luks2/luks2_keyslot_luks2.c:115
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Nie udało się uzyskać blokady do odczytu na urządzeniu %s."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Wykryto zabronione wymagania LUKS2 w kopii zapasowej %s."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Offset danych różni się między urządzeniem a kopią zapasową; przywrócenie nie powiodło się."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Nagłówek binarny z rozmiarem obszarów kluczy różni się między urządzeniem a kopią zapasową; przywrócenie nie powiodło się."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Urządzenie %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "nie zawiera nagłówka LUKS2. Nadpisanie nagłówka może zniszczyć dane na tym urządzeniu."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "już zawiera nagłówek LUKS2. Nadpisanie nagłówka zniszczy istniejące klucze."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"UWAGA: wykryto nieznane wymagania LUKS2 w nagłówku prawdziwego urządzenia!\n"
+"Nadpisanie nagłówka kopią zapasową może uszkodzić dane na tym urządzeniu!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"UWAGA: wykryto nie zakończone ponowne szyfrowanie offline na urządzeniu!\n"
+"Nadpisanie nagłówka kopią zapasową może uszkodzić dane."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Zignorowano nieznaną flagę %s."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Brak klucza dla segmentu dm-crypt %u"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Nie udało się ustawić segmentu dm-crypt."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Nie udało się ustawić segmentu dm-linear."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Nieobsługiwana konfiguracja integralności urządzenia."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Podobne szyfrowanie trwa. Nie można dezaktywować urządzenia."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Nie udało się zastąpić wstrzymanego urządzenia %s celem dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Nie udało się odczytać wymagań LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Wykryto nie spełnione wymagania LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Operacja niezgodna z urządzeniem oznaczonym do ponownego szyfrowania starym szyfrem. Przerwano."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Operacja niezgodna z urządzeniem oznaczonym do ponownego szyfrowania LUKS2. Przerwano."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Za mało dostępnej pamięci, aby otworzyć klucz."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Nie udało się otworzyć klucza."
+
+#: lib/luks2/luks2_keyslot_luks2.c:54 lib/luks2/luks2_keyslot_luks2.c:109
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Nie można użyć szyfru %s-%s do szyfrowania kluczy."
+
+#: lib/luks2/luks2_keyslot_luks2.c:281 lib/luks2/luks2_keyslot_luks2.c:390
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Algorytm skrótu %s nie jest dostępny."
+
+#: lib/luks2/luks2_keyslot_luks2.c:506
+msgid "No space for new keyslot."
+msgstr "Brak miejsca na nowy klucz."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Błędne żądanie zmiany trybu odporności przy ponownym szyfrowaniu."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Nie można uaktualnić rodzaju odporności. Nowy typ zapewnia %<PRIu64> B, wymagane miejsce to %<PRIu64> B."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Nie udało się odświeżyć skrótu weryfikacji ponownego szyfrowania."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Nie można sprawdzić stanu urządzenia mającego UUID: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Nie można przekonwertować nagłówka z dodatkowymi metadanymi LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Nie można użyć określenia szyfru %s-%s dla LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Nie można przenieść obszaru kluczy. Brak miejsca."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Nie można przekonwertować do formatu LUKS1 - błędne metadane."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Nie można przenieść obszaru kluczy. Obszar kluczy LUKS2 zbyt mały."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Nie można przenieść obszaru kluczy."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Nie można przekonwertować do formatu LUKS1 - domyślny rozmiar sektora szyfrowania segmentu nie wynosi 512 bajtów."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Nie można przekonwertować formatu LUKS1 - skróty kluczy nie są zgodne z LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Nie można przekonwertować formatu LUKS1 - urządzenie używa szyfru %s z obudowanym kluczem."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Nie można przekonwertować formatu LUKS1 - urządzenie używa większej liczby segmentów."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Nie można przekonwertować do formatu LUKS1 - nagłówek LUKS2 zawiera %u token(ów)."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Nie można przekonwertować do formatu LUKS1 - klucz %u jest w błędnym stanie."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Nie można przekonwertować do formatu LUKS1 - klucz %u (powyzej maksimum) jest nadal aktywny."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Nie można przekonwertować do formatu LUKS1 - klucz %u nie jest zgodny z LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Rozmiar strefy hotzone musi być wielokrotnością wyliczonego wyrównania strefy (bajtów: %zu)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Rozmiar urządzenia musi być wielokrotnością wyliczonego wyrównania strefy (bajtów: %zu)."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Nie udało się zainicjować obudowania przestrzeni starego segmentu."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Nie udało się zainicjować obudowania przestrzeni nowego segmentu."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Nie udało się zainicjować ochrony strefy hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Nie udało się odczytać sum kontrolnych dla aktualnej strefy hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Nie udało się odczytać obszaru hotzone zaczynającego się od %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Nie udało się odszyfrować sektora %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Nie udało się odtworzyć sektora %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Rozmiary urządzenia źródłowego i docelowego różnią się. Źródłowe %<PRIu64>, docelowe: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Nie udało się uaktywnić urządzenia hotzone %s."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Nie udało się uaktywnić urządzenia nakładkowego %s z aktualną tablicą źródła."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Nie udało się załadować nowego odwzorowania dla urządzenia %s."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Nie udało się odświeżyć stosu urządzenia ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Nie udało się ustawić nowego rozmiaru obszaru kluczy."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Wartość przesunięcia danych nie jest wyrównana do rozmiaru sektora szyfrowania (%<PRIu32> B)."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Nieobsługiwany tryb odporności %s"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Rozmiar przenoszonego segmentu nie może być większy niż wartość przesunięcia danych."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Błędne parametry odporności przy ponownym szyfrowaniu."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Przenoszony segment zbyt duży. Żądany rozmiar %<PRIu64>, dostępne miejsce: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Nie udało się wyczyścić tablicy."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "Zmniejszony rozmiar danych jest większy niż rzeczywisty rozmiar urządzenia."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Urzędzenie danych nie jest wyrównane do rozmiaru sektora szyfrowania (%<PRIu32> B)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Przesunięcie danych (sektorów: %<PRIu64>) jest mniejsze niż przyszły offset danych (sektorów: %<PRIu64>)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Nie udało się otworzyć %s w trybie wyłączności (już odwzorowano lub zamontowano)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Urządzenie nie jest oznaczone do ponownego szyfrowania LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Nie udało się załadować kontekstu ponownego szyfrowania LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Nie udało się pobrać stanu ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Urządzenie nie jest w trakcie ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Proces ponownego szyfrowania już trwa."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Nie udało się uzyskać blokady dla ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Nie można kontynuować ponownego szyfrowania. Należy najpierw uruchomić odtworzenie ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Rozmiar urządzenia aktywnego oraz żądany rozmiar ponownego szyfrowania różnią się."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "W parametrach ponownego szyfrowania zażądano niedozwolonego rozmiaru urządzenia."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Ponowne szyfrowanie trwa. Nie można wykonać odzyskiwania."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "Ponowne szyfrowanie LUKS2 jest już zainicjowane w metadanych."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Nie udało się zainicjować ponownego szyfrowania LUKS2 w metadanych."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Nie udało się ustawić segmentów urządzeń dla następnej strefy hotzone ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Nie udało się zapisać metadanych odporności ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Odszyfrowanie nie powiodło się."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Nie udało się zapisać obszaru hotzone zaczynającego się od %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Nie udało się zsynchronizować danych."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Nie udało się uaktualnić metadanych po zakończeniu aktualnej strefy hotzone ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Nie udało się zapisać metadanych LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Nie udało się wymazać nie używanego obszaru urządzenia danych."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Nie udało się usunąć nie używanego (nie przypisanego) obszaru klucza %d."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Nie udało się usunąć obszaru klucza ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Błąd krytyczny podczas ponownego szyfrowania fragmentu zaczynającego się od %<PRIu64> o długości w sektorach %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Ponowne szyfrowanie online nie powiodło się."
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Proszę nie wznawiać urządzenia dopóki nie zostanie zastąpione celem błędnym ręcznie."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Nie można kontynuować ponownego szyfrowania. Nieoczekiwany stan ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Brak lub błędny kontekst ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Nie udało się zainicjować stosu urządzenia ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Nie udało się uaktualnić kontekstu ponownego szyfrowania."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Metadane ponownego szyfrowania są błędne."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Parametry szyfrowania kluczy mogą być ustawione tylko dla urządzeń LUKS2."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Proszę wprowadzić PIN: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Proszę wprowadzić PIN tokenu %d: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1097 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Nie wykryto znanego wzorca określającego szyfr."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "UWAGA: Parametr --hash jest ignorowany w trybie zwykłym z podanym plikiem klucza.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "UWAGA: Opcja --keyfile-size jest ignorowana, rozmiar odczytu jest taki sam, jak rozmiar klucza szyfrującego.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Wykryto sygnatury urządzeń na %s. Dalsze operacje mogą uszkodzić istniejące dane."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:724
+msgid "Operation aborted.\n"
+msgstr "Operacja przerwana.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Wymagana jest opcja --key-file."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Proszę wprowadzić PIM VeraCrypt: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Błędna wartość PIM: błąd składni."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Błędna wartość PIM: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Błędna wartość PIM: poza zakresem."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Nie wykryto nagłówka urządzenia z tym hasłem."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Urządzenie %s nie jest prawidłowym urządzeniem BITLK."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Nie można określić rozmiaru klucza wolumenu dla BITLK, proszę użyć opcji --key-size."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Zrzut nagłówka z kluczem wolumenu jest informacją wrażliwą,\n"
+"pozwalającą na dostęp do zaszyfrowanej partycji bez hasła.\n"
+"Zrzut ten powinien być zawsze zapisywany w postaci zaszyfrowanej\n"
+"w bezpiecznym miejscu."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Zrzut nagłówka z kluczem wolumenu jest informacją wrażliwą,\n"
+"pozwalającą na dostęp do zaszyfrowanej partycji bez hasła.\n"
+"Zrzut ten powinien być zawsze zapisywany w postaci zaszyfrowanej\n"
+"w bezpiecznym miejscu."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Urządzenie %s nie jest prawidłowym urządzeniem FVAULT2."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Nie można określić rozmiaru klucza wolumenu dla FVAULT2, proszę użyć opcji --key-size."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Urządzenie %s jest nadal aktywne i zaplanowane do odroczonego usunięcia.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Zmiana rozmiaru aktywnego urządzenia wymaga klucza wolumenu w pęku, ale ustawiono opcję --disable-keyring."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Test szybkości przerwany."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/D\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iteracji/sekundę dla klucza %zu-bitowego\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/D\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iteracji, pamięć: %5u, równoległe wątki (CPU): %1u dla klucza %zu-bitowego (żądany czas %u ms)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Wynik testu wydajności nie jest wiarygodny."
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Testy są przybliżone tylko z użyciem pamięci (bez we/wy na dysk).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algorytm | Klucz | Szyfrowanie | Odszyfrowywanie\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Szyfr %s (rozmiar klucza w bitach: %i) nie jest dostępny."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algorytm | Klucz | Szyfrowanie | Odszyfrowywanie\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "N/D"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Wybryto nie zabezpieczone metadane ponownego szyfrowania LUKS2. Proszę sprawdzić, czy operacja ponownego szyfrowania jest pożądana (p. wyjście luksDump)\n"
+"i kontynuować (uaktualnić metadane) tylko jeśli ta operacja ma być faktycznie wykonana."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Hasło do zabezpieczenia i uaktualnienia metadanych ponownego szyfrowania: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Naprawdę kontynuować odtwarzanie ponownego szyfrowania LUKS2?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Hasło do weryfikacji skrótu metadanych ponownego szyfrowania: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Hasło do odtwarzania ponownego szyfrowania: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Naprawdę próbować naprawić nagłówek urządzenia LUKS?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Wymazywanie przerwane."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Czyszczenie urządzenia w celu zainicjowania sumy kontrolnej integralności.\n"
+"Można przerwać ten proces wciskając Ctrl+C (reszta nie wymazanego urządzenia będzie zawierać błędną sumę kontrolną).\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Nie można dezaktywować urządzenia tymczasowego %s."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Opcja integralności może być używana tylko dla formatu LUKS2."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Nieobsługiwane opcje rozmiaru metadanych LUKS2."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Plik nagłówka nie istnieje, czy utworzyć go?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Nie można utworzyć pliku nagłówka %s."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Nie wykryto znanego wzorca określającego integralność."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Nie można użyć %s jako nagłówka na dysku."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "To nieodwołalnie nadpisze dane na %s."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Nie udało się ustawić parametrów PBKDF."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Offset zmniejszonych danych jest dozwolony tylko dla odłączonego nagłówka LUKS."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "Kontener plikowy LUKS %s jest zbyt mały do uaktywnienia, nie ma miejsca pozostałego na dane."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Nie można określić rozmiaru klucza wolumenu dla LUKS bez kluczy, proszę użyć opcji --key-size."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Urządzenie uaktywnione, ale nie można uczynić flag trwałymi."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Klucz %d jest wybrany do usunięcia."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "To jest ostatni klucz. Urządzenie stanie się bezużyteczne po usunięciu tego klucza."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Dowolne pozostałe hasło: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operacja przerwana, klucz NIE został wymazany.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Hasło do usunięcia: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Urządzenie %s nie jest prawidłowym urządzeniem LUKS2."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Nowe hasło dla klucza: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "UWAGA: Parametr --key-slot jest używany do numeru nowego klucza.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Dowolne istniejące hasło: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Hasło, które ma być zmienione: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Nowe hasło: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Hasło dla klucza do konwersji: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Dla operacji isLuks obsługiwany jest tylko jeden argument będący urządzeniem."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Miejsce %d nie zawiera niepowiązanego klucza."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Zrzut nagłówka z niepowiązanym kluczem jest informacją wrażliwą.\n"
+"Zrzut ten powinien być zawsze zapisywany w postaci zaszyfrowanej\n"
+"w bezpiecznym miejscu."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s nie jest nazwą aktywnego urządzenia %s."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s nie jest nazwą aktywnego urządzenia LUKS lub brak nagłówka."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "Wymagana jest opcja --header-backup-file."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s nie jest urządzeniem zarządzanym przez cryptsetup."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Odświeżanie nie jest obsługiwane dla typu urządzenia %s"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Nie rozpoznany typ urządzenia metadanych %s."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "Polecenie wymaga urządzenia i nazwy odwzorowywanej jako argumentów."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Ta operacja usunię wszystkie klucze na urządzeniu %s.\n"
+"Urządzenie po tej operacji stanie się bezużyteczne."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operacja przerwana, klucze NIE zostały wymazane.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Błędny typ LUKS, obsługiwane są tylko luks1 i luks2."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Urządzenie już ma typ %s."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Ta operacja przekonwertuje %s do formatu %s.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operacja przerwana, urządzenie NIE zostało skonwertowane.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Brak opcji --priority, --label lub --subsystem."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Token %d jest błędny."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Token %d jest w użyciu."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Nie udało się dodać tokenu %d do pęku kluczy luks2."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Nie udało się przypisać tokenu %d do klucza %d."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Token %d nie jest w użyciu."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Nie udało się zaimportować tokenu z pliku."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Nie udało się pobrać tokenu %d do eksportu."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Token %d nie jest przypisany do klucza %d."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Nie udało się usunąć przypisania tokenu %d do klucza %d."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Opcje --tcrypt-hidden, --tcrypt-system i --tcrypt-backup są obsługiwane tylko dla urządzeń TCRYPT."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Opcje --veracrypt i --disable-veracrypt są obsługiwane tylko dla typu urządzeń TCRYPT."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Opcja --veracrypt-pim jest obsługiwana tylko dla urządzeń zgodnych z VeraCryptem."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Opcja --veracrypt-query-pim jest obsługiwana tylko dla urządzeń zgodnych z VeraCryptem."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Opcje --veracrypt-pim i --veracrypt-query-pim wykluczają się wzajemnie."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Opcja --persistent nie jest dozwolona z --test-passphrase."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Opcje --refresh i --test-passphrase wykluczają się wzajemnie."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Opcja --shared jest dozwolona tylko dla operacji otwarcia zwykłego urządzenia."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Opcja --skip jest obsługiwana tylko przy otwieraniu urządzeń plain i loopaes."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Opcja --offset z akcją open jest obsługiwana tylko dla urządzeń plain i loopaes."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Opcji --tcrypt-hidden nie można łączyć z --allow-discards."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Opcja rozmiaru sektora z akcją open jest obsługiwana tylko dla urządzeń plain."
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Opcja dużych rozmiarów sektorów IV jest obsługiwana tylko przy otwieraniu urządzeń typu plain z sektorem większym niż 512 bajtów."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "Opcja --test-passphrase jest dozwolona tylko przy otwieraniu urządzeń LUKS, TRCYPT, BITLK i FVAULT2."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Opcji --device-size i --size nie można łączyć."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Opcja --unbound jest dozwolona tylko dla operacji otwarcia urządzenia LUKS."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Opcja --unbound nie może być użyta bez --test-passphrase."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Opcje --cancel-deferred i --deferred nie mogą być użyte naraz."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Opcji --reduce-device-size i --data-size nie można łączyć."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Opcja --active-name może być ustawiona tylko dla urządzenia LUKS2."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Opcji --active-name i --force-offline-reencrypt nie można łączyć."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Wymagane jest określenie klucza."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Opcji --align-payload i --offset nie można łączyć."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Opcja --integrity-no-wipe może być użyta tylko do akcji formatowania z rozszerzeniem integralności."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Dozwolona jest tylko jedna z opcji --use-[u]random."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "Przy opcji --unbound wymagany jest rozmiar klucza."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "Błędna akcja token."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Parametr --key-description jest wymagany do akcji dodania tokenu."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Akcja wymaga określonego tokenu. Należy użyć parametru --token-id."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "Opcja --unbound jest dozwolona tylko dla operacji dodania tokenu."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Opcji --key-slot i --unbound nie można łączyć."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "Akcja wymaga określonego klucza. Należy użyć parametru --key-slot."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<uządzenie> [--type <typ>] [<nazwa>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "otwarcie urządzenia jako <nazwa>"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<nazwa>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "zamknięcie urządzenia (usunięcie odwzorowania)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "zmiana rozmiaru aktywnego urządzenia"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "pokazanie stanu urządzenia"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <szyfr>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "test szybkości szyfru"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<urządzenie>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "próba naprawy metadanych na dysku"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "ponowne szyfrowanie urządzenia LUKS2"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "usunięcie wszystkich kluczy (usunięcie klucza szyfrującego)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "przekonwertowanie formatu LUKS z/do LUKS2"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "ustawienie opcji trwałej konfiguracji dla LUKS2"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<urządzenie> [<nowy plik klucza>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "sformatowanie urządzenia LUKS"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "dodanie klucza do urządzenia LUKS"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<urządzenie> [<plik klucza>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "usunięcie podanego klucza lub pliku klucza z urządzenia LUKS"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "zmiana podanego klucza lub pliku klucza urządzenia LUKS"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "konwersja klucza na nowe parametry pbkdf"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<urządzenie> <numer klucza>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "wymazanie klucza o numerze <numer klucza> z urządzenia LUKS"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "wypisanie UUID-a urządzenia LUKS"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "sprawdzenie <urządzenia> pod kątem nagłówka partycji LUKS"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "zrzut informacji o partycji LUKS"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "zrzut informacji o urządzeniu TCRYPT"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "zrzut informacji o urządzeniu BITLK"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "zrzut informacji o urządzeniu FVAULT2"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Wstrzymanie urządzenia LUKS i wymazanie klucza (zamraża wszystkie operacje we/wy)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "Wznowienie zatrzymanego urządzenia LUKS"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Kopia zapasowa nagłówka i kluczy urządzenia LUKS"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Odtworzenie nagłówka i kluczy urządzenia LUKS z kopii zapasowej"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <urządzenie>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "Operacja na tokenach LUKS2"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<akcja> to jedno z:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Można także używać starych aliasów składni <akcja>:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nazwa> to urządzenie do utworzenia wewnątrz %s\n"
+"<urządzenie> to zaszyfrowane urządzenie\n"
+"<numer klucza> to numer klucza LUKS do zmiany\n"
+"<plik klucza> to opcjonalny plik nowego klucza dla akcji luksAddKey\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Domyślny wkompilowany format metadanych to %s (dla akcji luksFormat).\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Obsługa zewnętrznych wtyczek tokenów LUKS2 jest %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "wkompilowana"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Ścieżka zewnętrznych wtyczek tokenów LUKS2: %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "wyłączona"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Domyślne wkompilowane parametry kluczy i haseł:\n"
+"\tMaksymalny rozmiar pliku klucza: %dkB, maksymalna długość hasła interaktywnego %d (znaków)\n"
+"Domyślny PBKDF dla LUKS1: %s, czas iteracji %d (ms)\n"
+"Domyślny PBKDF dla LUKS2: %s\n"
+"\tCzas iteracji: %d, wymagana pamięć: %dkB, liczba wątków: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Domyślne wkompilowane parametry szyfrowania urządzeń:\n"
+"\tloop-AES: %s, bitów klucza: %d\n"
+"\tplain: %s, bitów klucza: %d, skrót hasła: %s\n"
+"\tLUKS: %s, bitów klucza: %d, skrót nagłówka LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: Domyślny rozmiar klucza z trybem XTS (dwa klucze wewnętrzne) będzie podwojony.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: wymaga %s jako argumentów"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Numer klucza jest nieprawidłowy."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Rozmiar urządzenia musi być wielokrotnością 512-bajtowego sektora."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Błędne określenie maksymalnego rozmiaru strefy hotzone ponownego szyfrowania."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Rozmiar klucza musi być wielokrotnością 8 bitów"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Maksymalna wartość ograniczenia rozmiaru urządzenia to 1GiB."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Rozmiar ograniczenia musi być wielokrotnością 512-bajtowego sektora."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Opcja --priority może mieć wartości tylko ignore/normal/prefer."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Wyświetlenie tego opisu"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Wyświetlenie krótkiej informacji o składni"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Wypisanie wersji pakietu"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Opcje pomocnicze:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPCJA...] <akcja> <parametry-akcji>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Brak argumentu <akcja>."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Nieznana akcja."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Opcja --key-file ma priorytet nad podanym argumentem pliku klucza."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Dozwolony jest tylko jeden argument --key-file."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Funkcja pochodna klucza oparta na haśle (PBKDF) może być tylko pbkdf2 lub argon2i/argon2id."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Wymuszonych iteracji PBKDF nie można łączyć z opcją czasu iteracji."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Opcje --keyslot-cipher i --keyslot-key-size muszą być użyte łącznie."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Nie wykonano akcji. Wywołano z opcją --test-args.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Nie można wyłączyć blokowania metadanych."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Podano błędny łańcuch zarodka."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Nie można utworzyć obrazu hasza %s do zapisu."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Nie można utworzyć obrazu FEC %s do zapisu."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Nie można utworzyć pliku głównego hasza %s do zapisu."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Nie można zapisać pliku głównego hasza %s."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Urządzenie %s nie jest prawidłowym urządzeniem VERITY."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Nie można odczytać pliku głównego hasza %s."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Błędny plik głównego hasza %s."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "Podano błędny łańcuch głównego hasza."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Błędny plik podpisu %s."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Nie można odczytać pliku klucza %s."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Polecenie wymaga <głównego_hasza> lub opcji --root-hash-file jako argumentu."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<urządzenie_danych> <urządzenie_haszy>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "sformatowanie urządzenia"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<urządzenie_danych> <urządzenie_haszy> [<główny_hasz>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "weryfikacja urządzenia"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<urządzenie_danych> <nazwa> <urządzenie_haszy> [<główny_hasz>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "pokazanie stanu aktywnego urządzenia"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<urządzenie_haszy>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "wyświetlenie informacji z dysku"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nazwa> to urządzenie do utworzenia pod %s\n"
+"<urządzenie_danych> to urządzenie z danymi\n"
+"<urządzenie_haszy> to urządzenie zawierające dane weryfikacyjne\n"
+"<główny_hasz> to hasz głównego węzła na <urządzeniu_haszy>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Domyślnie wkompilowane parametry dm-verity:\n"
+"\tHasz: %s, blok danych (bajtów): %u, blok haszy (bajtów): %u, rozmiar zarodka: %u, format haszy: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Opcji --ignore-corruption oraz --restart-on-corruption nie można użyć naraz."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Opcji --panic-on-corruption oraz --restart-on-corruption nie można użyć naraz."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Ta operacja nieodwracalnie nadpisze dane na %s i %s.\n"
+"Aby zachować urządzenie danych, można użyć opcji --no-wipe (a następnie uaktywnić z --integrity-recalculate)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Sformatowano z rozmiarem znacznika %u, wewnętrzna integralność %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Ustawianie flagi recalculate nie jest obsługiwane, zamiast tego można rozważyć użycie --wipe."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Urządzenie %s nie jest prawidłowym urządzeniem INTEGRITY."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<urządzenie_integralności>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<urządzenie_integralności> <nazwa>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<nazwa> to urządzenie do utworzenia pod %s\n"
+"<urządzenie_integralności> to urządzenie zawierające dane ze znacznikami integralności\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Domyślnie wkompilowane parametry dm-integrity:\n"
+"\tAlgorytm sumy kontrolnej: %s\n"
+"\tMaksymalny rozmiar pliku klucza: %dkB\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Błędny rozmiar --%s. Maksimum w bajtach to %u."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Muszą być podane obie opcje: pliku klucza i rozmiaru klucza."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Muszą być podane obie opcje: pliku klucza integralności i rozmiaru klucza."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Algorytm integralności kroniki musi być podany, jeśli używany jest klucz integralności kroniki."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Muszą być podane obie opcje: pliku szyfrowania kroniki i rozmiaru klucza."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Algorytm szyfrowania kroniki musi być podany, jeśli używany jest klucz szyfrowania kroniki."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Opcje trybu odtwarzania i bitmapy wykluczają się wzajemnie."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Opcji kroniki nie można używać w trybie bitmapy."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Opcje bitmapy mogą być używane tylko w trybie bitmapy."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"UWAGA!\n"
+"======\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Na pewno? (należy wpisać 'yes' wielkimi literami): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Błąd podczas odczytu odpowiedzi z terminala."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Polecenie się powiodło."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "niewłaściwe lub brakujące parametry"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "brak uprawnień lub błędne hasło"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "brak pamięci"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "podano niewłaściwe urządzenie lub plik"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "urządzenie już istnieje lub jest zajęte"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "nieznany błąd"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Polecenie nie powiodło się z kodem %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Klucz numer %i utworzony."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Klucz numer %i odblokowany."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Klucz numer %i usunięty."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Token %i utworzony."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Token %i usunięty."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Przy użyciu tego PIN-u nie udało się odblokować żadnego tokenu."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Token %i wymaga PIN-u."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Token (typu %s) wymaga PIN-u."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token %i nie może odblokować przypisanych obszarów kluczy (błędne hasło klucza)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token (typu %s) nie może odblokować przypisanych obszarów kluczy (błędne hasło klucza)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Token %i wymaga dodatkowego, brakującego zasobu."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Token (typu %s) wymaga dodatkowego, brakującego zasobu."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Brak dostępnego użytecznego tokenu (typu %s)."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Brak dostępnego użytecznego tokenu."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Nie można odczytać pliku klucza %s."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Nie można odczytać %d bajtów z pliku klucza %s."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Nie można otworzyć pliku klucza %s do zapisu."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Nie można zapisać pliku klucza %s."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> d"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "zapisano %4<PRIu64> %s"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "szybkość %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Postęp: %5.1f%%, przewidywany czas zakończenia %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Zakończono, czas %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Nie można sprawdzić jakości hasła: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Sprawdzenie jakości hasła nie powiodło się:\n"
+" %s"
+
+#: src/utils_password.c:81
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Sprawdzenie jakości hasła nie powiodło się: błędne hasło (%s)"
+
+#: src/utils_password.c:232 src/utils_password.c:246
+msgid "Error reading passphrase from terminal."
+msgstr "Błąd podczas odczytu hasła z terminala."
+
+#: src/utils_password.c:244
+msgid "Verify passphrase: "
+msgstr "Weryfikacja hasła: "
+
+#: src/utils_password.c:251
+msgid "Passphrases do not match."
+msgstr "Hasła nie zgadzają się."
+
+#: src/utils_password.c:289
+msgid "Cannot use offset with terminal input."
+msgstr "Nie można użyć offsetu, jeśli wejściem jest terminal."
+
+#: src/utils_password.c:293
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Hasło: "
+
+#: src/utils_password.c:296
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Hasło dla %s: "
+
+#: src/utils_password.c:330
+msgid "No key available with this passphrase."
+msgstr "Dla tego hasła nie ma dostępnego klucza."
+
+#: src/utils_password.c:332
+msgid "No usable keyslot is available."
+msgstr "Brak dostępnego miejsca na klucz."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Nie można wykonać weryfikacji hasła, jeśli wejściem nie jest terminal."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Nie udało się otworzyć pliku %s tylko do odczytu."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Poprawny token JSON dla LUKS2:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Nie udało się odczytać pliku JSON."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Odczyt przerwany."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Nie udało się otworzyć pliku %s do zapisu."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Zapis przerwany."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Nie udało się zapisać pliku JSON."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Wykryto aktywne urządzenie dm '%s' dla urządzenia danych %s.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Nie udało się wykryć właścicieli urządzenia %s."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Urządzenie %s nie jest urządzeniem blokowym.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Nie udało się zdecydować, czy urządzenie %s jest uaktywnione, czy nie.\n"
+"Czy na pewno kontynuować ponowne szyfrowanie w trybie offline?\n"
+"Może to prowadzić do uszkodzenia danych, jeśli urządzenie jest aktywne.\n"
+"Aby uruchomić ponowne szyfrowanie w trybie online, należy użyć parametru\n"
+"--active-name.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Urządzenie %s nie jest urządzeniem blokowym. Nie można wykryć, czy jest aktywne.\n"
+"Można użyć --force-offline-reencrypt aby obejść to sprawdzenie i uruchomić w trybie offline (niebezpieczne!)."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Nie można użyć żądanej opcji --resilience do obecnej operacji ponownego szyfrowania."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Urządzenie nie jest w trybie szyfrowania LUKS2. Konflikt opcji --encrypt."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Urządzenie nie jest w trybie odszyfrowywania LUKS2. Konflikt opcji --decrypt."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Urządzenie jest w trybie ponownego szyfrowania z użyciem odporności przesunięcia danych. Nie można użyć żądanej opcji --resilience."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Urządzenie wymaga odtwarzania ponownego szyfrowania. Najpierw należy uruchomić naprawę."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Urządzenie %s jest już w trybie ponownego szyfrowania LUKS2. Czy wznowić uprzednio zainicjowaną operację?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Stara wersja ponownego szyfrowania LUKS2 nie jest już obsługiwana."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Ponowne szyfrowanie urządzenia z profilem integralności nie jest obsługiwane."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Żądany --sector-size %<PRIu32> jest niezgodny z superblokiem %s\n"
+"(rozmiar bloku: %<PRIu32> B), wykrytym na urządzeniu %s."
+
+#: src/utils_reencrypt.c:494
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Szyfrowanie bez odłączonego nagłówka (--header) jest niemożliwe bez ograniczenia rozmiaru urządzenia danych (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:500
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Żądany offset danych musi być mniejszy lub równy połowie parametru --reduce-device-size."
+
+#: src/utils_reencrypt.c:510
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Modyfikowanie wartości --reduce-device-size do dwukrotności parametru --offset %<PRIu64> (w sektorach).\n"
+
+#: src/utils_reencrypt.c:540
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Plik nagłówka %s już istnieje. Przerwano."
+
+#: src/utils_reencrypt.c:542 src/utils_reencrypt.c:549
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Nie można utworzyć pliku tymczasowego nagłówka %s."
+
+#: src/utils_reencrypt.c:574
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Rozmiar metadanych LUKS2 jest większy niż wartość przesunięcia danych."
+
+#: src/utils_reencrypt.c:611
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Nie udało się umieścić nowego nagłówka na początku urządzenia %s."
+
+#: src/utils_reencrypt.c:621
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s jest teraz aktywne i gotowe do szyfrowania w locie.\n"
+
+#: src/utils_reencrypt.c:657
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Aktywne urządzenie %s nie jest urządzeniem LUKS2."
+
+#: src/utils_reencrypt.c:685
+msgid "Restoring original LUKS2 header."
+msgstr "Odtwarzanie oryginalnego nagłówka LUKS2."
+
+#: src/utils_reencrypt.c:693
+msgid "Original LUKS2 header restore failed."
+msgstr "Odtwarzanie oryginalnego nagłówka LUKS2 nie powiodło się."
+
+#: src/utils_reencrypt.c:719
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Plik nagłówka %s nie istnieje. Czy zainicjować odszyfrowywanie LUKS2 urządzenia %s i eksport nagłówka LUKS2 do pliku %s?"
+
+#: src/utils_reencrypt.c:767
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Nie udało się dodać uprawnień odczytu/zapisu do pliku wyeksportowanego nagłówka."
+
+#: src/utils_reencrypt.c:820
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Inicjowanie ponownego szyfrowania nie powiodło się. Kopia zapasowa nagłówka jest dostępna w %s."
+
+#: src/utils_reencrypt.c:848
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "Odszyfrowanie LUKS2 jest obsługiwane tylko z urządzeniem z odłączonym nagłówkiem (z offsetem danych ustawionym na 0)."
+
+#: src/utils_reencrypt.c:983 src/utils_reencrypt.c:992
+msgid "Not enough free keyslots for reencryption."
+msgstr "Za mało wolnych kluczy do ponownego szyfrowania."
+
+#: src/utils_reencrypt.c:1013 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Rozmiaru klucza można użyć tylko z --key-slot albo przy dokładnie jednym aktywnym kluczu."
+
+#: src/utils_reencrypt.c:1022 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Hasło dla klucza %d: "
+
+#: src/utils_reencrypt.c:1034
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Hasło dla klucza %u: "
+
+#: src/utils_reencrypt.c:1086
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Zmiana szyfru do szyfrowania danych na %s.\n"
+
+#: src/utils_reencrypt.c:1140
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Nie zmieniono parametrów segmentu danych. Ponowne szyfrowanie przerwane."
+
+#: src/utils_reencrypt.c:1242
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Zwiększanie rozmiaru sektora szyfrowania na urządzeniu offline nie jest obsługiwane.\n"
+"Należy najpierw uaktywnić urządzenie lub użyć opcji --force-offline-reencrypt (niebezpieczna!)."
+
+#: src/utils_reencrypt.c:1282 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Ponowne szyfrowanie przerwane."
+
+#: src/utils_reencrypt.c:1287
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Wznawianie ponownego szyfrowania LUKS w wymuszonym trybie offline.\n"
+
+#: src/utils_reencrypt.c:1304
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Urządzenie %s zawiera uszkodzone metadane LUKS. Przerwano operację."
+
+#: src/utils_reencrypt.c:1320 src/utils_reencrypt.c:1342
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Urządzenie %s jest już urządzeniem LUKS. Przerwano operację."
+
+#: src/utils_reencrypt.c:1348
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Urządzenie %s jest już w trybie ponownego szyfrowania LUKS. Przerwano operację."
+
+#: src/utils_reencrypt.c:1421
+msgid "LUKS2 decryption requires --header option."
+msgstr "Odszyfrowanie LUKS2 wymaga opcji --header."
+
+#: src/utils_reencrypt.c:1469
+msgid "Command requires device as argument."
+msgstr "Polecenie wymaga urządzenia jako argumentu."
+
+#: src/utils_reencrypt.c:1482
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Konflikt wersji. Urządzenie %s jest urządzeniem LUKS1."
+
+#: src/utils_reencrypt.c:1488
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Konflikt wersji. Urządzenie %s jest w trybie ponownego szyfrowania LUKS1."
+
+#: src/utils_reencrypt.c:1494
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Konflikt wersji. Urządzenie %s jest urządzeniem LUKS2."
+
+#: src/utils_reencrypt.c:1500
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Konflikt wersji. Urządzenie %s jest w trybie ponownego szyfrowania LUKS2."
+
+#: src/utils_reencrypt.c:1506
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Ponowne szyfrowanie LUKS2 jest już zainicjowane. Przerywanie operacji."
+
+#: src/utils_reencrypt.c:1513
+msgid "Device reencryption not in progress."
+msgstr "Ponowne szyfrowanie urządzenia nie jest w toku."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Nie można otworzyć %s w trybie wyłącznym, urządzenie jest w użyciu."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Przydzielenie wyrównanego obszaru pamięci nie powiodło się."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Nie można odczytać urządzenia %s."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Oznaczanie urządzenia LUKS1 %s jako bezużytecznego."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Nie można zapisać na urządzenie %s."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Nie można zapisać pliku logu ponownego szyfrowania."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Nie można odczytać pliku logu ponownego szyfrowania."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Niewłaściwy format logu."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Plik logu %s istnieje, wznowienie ponownego szyfrowania.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Uaktywnianie urządzenia tymczasowego przy użyciu starego nagłówka LUKS."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Uaktywnianie urządzenia tymczasowego przy użyciu nowego nagłówka LUKS."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Uaktywnianie urządzeń tymczasowych nie powiodła się."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Nie udało się ustawić offsetu danych."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Nie udało się ustawić rozmiaru metadanych."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Utworzono nowy nagłówek LUKS dla urządzenia %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Utworzono kopię zapasową nagłówka %s urządzenia %s."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Tworzenie kopii zapasowych nagłówków LUKS nie powiodło się."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Nie można odtworzyć nagłówka %s na urządzeniu %s."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Odtworzono nagłówek %s na urządzeniu %s."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Nie można otworzyć tymczasowego urządzenia LUKS."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Nie można pobrać rozmiaru urządzenia."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "Błąd we/wy podczas ponownego szyfrowania."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Dostarczony UUID jest nieprawidłowy."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Nie można otworzyć pliku logu ponownego szyfrowania."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Nie w trakcie odszyfrowywania; dostarczony UUID może być użyty tylko do wznowienia wstrzymanego procesu odszyfrowywania."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Ponowne szyfrowanie zmieni: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "klucz wolumenu"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "hasz na "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", szyfr na"
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "UWAGA: urządzenie %s już zawiera sygnaturę partycji '%s'.\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "UWAGA: urządzenie %s już zawiera sygnaturę superbloku '%s'.\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Nie udało się zainicjować sond sygnatur urządzeń."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Nie udało się wykonać stat na urządzeniu %s."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Nie udało się otworzyć pliku %s do odczytu i zapisu."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Istniejąca sygnatura partycji '%s' na urządzeniu %s zostanie wymazana."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Istniejąca sygnatura superbloku '%s' na urządzeniu %s zostanie wymazana."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Nie udało się wymazać sygnatury urządzenia."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Nie udało się sprawdzić sygnatury urządzenia %s."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Błędne określenie rozmiaru w parametrze --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Opcja --%s nie jest dozwolona z akcją %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Nie udało się zapisać danych JSON tokenu SSH."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Eksperymentalna wtyczka cryptsetup do odblokowywania urządzeń LUKS2 przy użyciu tokenu połączonego do serwera SSH\vTa wtyczka aktualnie pozwala tylko dodawać token do istniejącego obszaru klucza.\n"
+"\n"
+"Podany serwer SSH musi zawierać plik klucza pod podaną ścieżką z hasłem do istniejącego obszaru klucza na urządzeniu.\n"
+"Przekazane dane uwierzytelniające będą użyte przez cryptsetup do uzyskania hasła przy otwieraniu urządzenia przy użyciu tokenu.\n"
+"\n"
+"Uwaga: informacje dostarczone przy dodawaniu tokenu (adres serwera SSH, użytkownik i ścieżki) zostaną zapisane w nagłówku LUKS2 czystym tekstem."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<akcja> <urządzenie>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Opcje dla akcji 'add':"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "Adres IP/URL zdalnego serwera dla tego tokenu"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Nazwa użytkownika do użycia ze zdalnym serwerem"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Ścieżka do pliku klucza na zdalnym serwerze"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Ścieżka do klucza SSH do połączenia ze zdalnym serwerem"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Obszar klucza do przypisania tokenu. Domyślnie token zostanie przypisany do pierwszego obszaru pasującego do podanego hasła."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Opcje ogólne:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Wyświetlanie bardziej szczegółowych komunikatów błędów"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Wyświetlanie komunikatów diagnostycznych"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Wyświetlanie komunikatów diagnostycznych wraz z metadanymi JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Nie udało się otworzyć i zaimportować klucza prywatnego:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Nie udało się zaimportować klucza prywatnego (zabezpieczony hasłem?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Hasło %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Nie udało się przeanalizować argumentów.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Musi być podana akcja\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Dla akcji '%s' musi być podane urządzenie.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Dla akcji '%s' musi być podany serwer SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Dla akcji '%s' musi być podany użytkownik SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Dla akcji '%s' musi być podana ścieżka SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Dla akcji '%s' musi być podana ścieżka klucza SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Nie udało się otworzyć %s przy użyciu podanych danych uwierzytelniających.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Ta wtyczka obecnie obsługuje wyłącznie akcję 'add'.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Nie można utworzyć sesji sftp: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Nie można zainicjować sesji sftp: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Nie można otworzyć sesji sftp: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Nie można wykonać stat pliku sftp: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Za mało pamięci.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Nie można odczytać klucza zdalnego: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Połączenie nie powiodło się: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Nieznany serwer: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Metoda autoryzacji klucza publicznego nie jest dozwolona przez serwer.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Błąd uwierzytelniania kluczem publicznym: "
diff --git a/po/pt_BR.po b/po/pt_BR.po
new file mode 100644
index 0000000..e0a4122
--- /dev/null
+++ b/po/pt_BR.po
@@ -0,0 +1,3217 @@
+# Brazilian Portuguese translation for cryptsetup
+# Copyright (C) 2019 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# Rafael Fontenelle <rafaelff@gnome.org>, 2016-2019.
+# ,
+# ##### Terminologia usada #####
+# ,
+# device mapper = mapeador de dispositivo
+# digest = resumo
+# key slots = slots de chave
+# plain = claro (pois "mensagem plana" é tradução incorreta)
+# passphrase = senha
+# salt = sal # https://pt.wikipedia.org/wiki/Sal_(criptografia)
+# ,
+# ##############################
+# ,
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.1.0\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2019-01-26 19:02+0100\n"
+"PO-Revision-Date: 2019-01-28 07:58-0200\n"
+"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
+"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge.net>\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+"X-Generator: Virtaal 1.0.0-beta1\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/libdevmapper.c:336
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Não foi possível inicializar o mapeador de dispositivo, executando como usuário não-root."
+
+#: lib/libdevmapper.c:339
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Não foi possível inicializar o mapeador de dispositivo. O módulo de kernel dm_mod está carregado?"
+
+#: lib/libdevmapper.c:1010
+msgid "Requested deferred flag is not supported."
+msgstr "Não há suporte ao sinalizador atrasado requisitado."
+
+#: lib/libdevmapper.c:1077
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID para o dispositivo \"%s\" estava truncada."
+
+#: lib/libdevmapper.c:1486
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Não há suporte às opções de desempenho de dm-crypt requisitadas."
+
+#: lib/libdevmapper.c:1493
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Não há suporte à tratamento de corrompimento de dados de dm-verify requisitada."
+
+#: lib/libdevmapper.c:1497
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Não há suporte às opções FEC dm-verity requisitadas."
+
+#: lib/libdevmapper.c:1501
+msgid "Requested data integrity options are not supported."
+msgstr "Não há suporte às opções de integridade de dados requisitadas."
+
+#: lib/libdevmapper.c:1503
+msgid "Requested sector_size option is not supported."
+msgstr "Não há suporte à opção sector_size requisitada."
+
+#: lib/libdevmapper.c:1508
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Não há suporte à recalculação automática de tags de integridade requisitada."
+
+#: lib/libdevmapper.c:1534
+msgid "Requested dmcrypt performance options are not supported."
+msgstr "Não há suporte às opções de desempenho de dmcrypt requisitadas."
+
+#: lib/libdevmapper.c:1537
+msgid "Discard/TRIM is not supported."
+msgstr "Não há suporte a descarte/TRIM."
+
+#: lib/libdevmapper.c:2413
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Falha ao consultar o segmento dm-%s."
+
+#: lib/random.c:80
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"O sistema sem entropia suficiente enquanto gera chave de volume.\n"
+"Por favor mova o mouse ou digite algum texto em outra janela para obter alguns eventos aleatórios.\n"
+
+#: lib/random.c:84
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Gerando chave (%d%% concluído).\n"
+
+#: lib/random.c:170
+msgid "Running in FIPS mode."
+msgstr "Executando no modo FIPS."
+
+#: lib/random.c:176
+msgid "Fatal error during RNG initialisation."
+msgstr "Erro fatal durante inicialização de RNG."
+
+#: lib/random.c:213
+msgid "Unknown RNG quality requested."
+msgstr "Qualidade RNG requisitada desconhecida."
+
+#: lib/random.c:218
+msgid "Error reading from RNG."
+msgstr "Erro na leitura de RNG."
+
+#: lib/setup.c:214
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Não foi possível inicializar o backend RNG de criptografia."
+
+#: lib/setup.c:220
+msgid "Cannot initialize crypto backend."
+msgstr "Não foi possível inicializar o backend de criptografia."
+
+#: lib/setup.c:251 lib/setup.c:1899 lib/verity/verity.c:123
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Não há suporte ao algoritmo hash %s."
+
+#: lib/setup.c:254 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Erro de processamento de chave (usando hash %s)."
+
+#: lib/setup.c:315 lib/setup.c:342
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Não foi possível determinar o tipo do dispositivo. Ativação de dispositivo incompatível?"
+
+#: lib/setup.c:321 lib/setup.c:2892
+msgid "This operation is supported only for LUKS device."
+msgstr "Há suporte a esta operação apenas para dispositivo LUKS."
+
+#: lib/setup.c:348
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Há suporte a esta operação apenas para dispositivo LUKS2."
+
+#: lib/setup.c:396
+msgid "All key slots full."
+msgstr "Todos os slots de chave estão cheios."
+
+#: lib/setup.c:407
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Slot de chave %d é inválido, por favor selecione entre 0 e %d."
+
+#: lib/setup.c:413
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Slot de chave %d está cheio, por favor selecione outro."
+
+#: lib/setup.c:589
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Cabeçalho detectado, mas o dispositivo %s é muito pequeno."
+
+#: lib/setup.c:626
+msgid "This operation is not supported for this device type."
+msgstr "Não há suporte a esta operação para este tipo de dispositivo."
+
+#: lib/setup.c:791 lib/luks1/keymanage.c:481
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Não há suporte ao LUKS versão %d."
+
+#: lib/setup.c:808 lib/setup.c:1403 lib/setup.c:1812
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Não há suporte ao dispositivo de metadados desanexado para este tipo de criptografia."
+
+#: lib/setup.c:1288 lib/setup.c:2392 lib/setup.c:2464 lib/setup.c:2476
+#: lib/setup.c:2625 lib/setup.c:4021
+#, c-format
+msgid "Device %s is not active."
+msgstr "O dispositivo \"%s\" não está ativado."
+
+#: lib/setup.c:1310
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "O dispositivo subjacente para o dispositivo de criptografia %s desapareceu."
+
+#: lib/setup.c:1388
+msgid "Invalid plain crypt parameters."
+msgstr "Parâmetros de criptografia clara inválidos."
+
+#: lib/setup.c:1393 lib/setup.c:1802 src/integritysetup.c:72
+msgid "Invalid key size."
+msgstr "Tamanho de chave inválida."
+
+#: lib/setup.c:1398 lib/setup.c:1807 lib/setup.c:2009
+msgid "UUID is not supported for this crypt type."
+msgstr "Não há suporte ao UUID para este tipo de criptografia."
+
+#: lib/setup.c:1413 lib/setup.c:1603 src/cryptsetup.c:1045
+msgid "Unsupported encryption sector size."
+msgstr "Não há suporte ao tamanho de setor de criptografia."
+
+#: lib/setup.c:1421 lib/setup.c:1720
+msgid "Device size is not aligned to requested sector size."
+msgstr "Tamanho do dispositivo não está alinhado com o tamanho de setor requisitado."
+
+#: lib/setup.c:1472 lib/setup.c:1591
+msgid "Can't format LUKS without device."
+msgstr "Não é possível formatar LUKS sem dispositivo."
+
+#: lib/setup.c:1478 lib/setup.c:1597
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Alinhamento de dados requisitado não é compatível com a posição dos dados."
+
+#: lib/setup.c:1546 lib/setup.c:1715
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr "AVISO: A posição dos dados está fora do dispositivo de dados atualmente disponível.\n"
+
+#: lib/setup.c:1556 lib/setup.c:1735 lib/setup.c:1754 lib/setup.c:2021
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Não foi possível apagar o cabeçalho no dispositivo %s."
+
+#: lib/setup.c:1608
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "AVISO: A ativação do dispositivo vai falhar, dm-crypt carece de suporte para o tamanho de setor de criptografia requisitado.\n"
+
+#: lib/setup.c:1630
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "A chave de volume é pequena demais para criptografia com extensões de integridade."
+
+#: lib/setup.c:1685
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "A cifra %s-%s (tamanho de chave %zd bits) não está disponível."
+
+#: lib/setup.c:1747
+#, c-format
+msgid "Cannot format device %s which is still in use."
+msgstr "Não foi possível formatar o dispositivo %s, o qual ainda está em uso."
+
+#: lib/setup.c:1750 lib/setup.c:1775
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Não é possível formatar o dispositivo %s, permissão negada."
+
+#: lib/setup.c:1762 lib/setup.c:2073
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Não foi possível formatar integridade para o dispositivo %s."
+
+#: lib/setup.c:1772
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Não é possível formatar dispositivo %s em uso."
+
+#: lib/setup.c:1779
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Não foi possível formatar o dispositivo %s."
+
+#: lib/setup.c:1797
+msgid "Can't format LOOPAES without device."
+msgstr "Não foi possível formatar LOOPAES sem dispositivo."
+
+#: lib/setup.c:1842
+msgid "Can't format VERITY without device."
+msgstr "Não foi possível formatar VERITY sem dispositivo."
+
+#: lib/setup.c:1853 lib/verity/verity.c:106
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Não há suporte ao tipo de hash VERITY %d."
+
+#: lib/setup.c:1859 lib/verity/verity.c:114
+msgid "Unsupported VERITY block size."
+msgstr "Não há suporte ao tamanho de bloco VERITY."
+
+#: lib/setup.c:1864 lib/verity/verity.c:75
+msgid "Unsupported VERITY hash offset."
+msgstr "Não há suporte à posição de hash VERITY."
+
+#: lib/setup.c:1869
+msgid "Unsupported VERITY FEC offset."
+msgstr "Não há suporte à posição de FEC VERITY."
+
+#: lib/setup.c:1893
+msgid "Data area overlaps with hash area."
+msgstr "A área de dados se sobrepõe à área hash."
+
+#: lib/setup.c:1918
+msgid "Hash area overlaps with FEC area."
+msgstr "Área de hash sobreposta com área de FEC."
+
+#: lib/setup.c:1925
+msgid "Data area overlaps with FEC area."
+msgstr "Área de dados sobreposta com área de FEC."
+
+#: lib/setup.c:2130
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Tipo de dispositivo de criptografia requisitado %s desconhecido."
+
+#: lib/setup.c:2398 lib/setup.c:2470 lib/setup.c:2483
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Não há suporte aos parâmetros no dispositivo %s."
+
+#: lib/setup.c:2404 lib/setup.c:2489
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Parâmetros incompatíveis no dispositivo %s."
+
+#: lib/setup.c:2657
+msgid "Cannot resize loop device."
+msgstr "Não foi possível redimensionar o dispositivo de loop."
+
+#: lib/setup.c:2666
+#, c-format
+msgid "Device %s size is not aligned to requested sector size (%u bytes)."
+msgstr "Tamanho do dispositivo %s não está alinhado com o tamanho de setor requisitado (%u bytes)."
+
+#: lib/setup.c:2725
+msgid "Do you really want to change UUID of device?"
+msgstr "Você realmente deseja alterar o UUID do dispositivo?"
+
+#: lib/setup.c:2801
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Arquivo de cópia de segurança de cabeçalho não contém um cabeçalho LUKS compatível."
+
+#: lib/setup.c:2900
+#, c-format
+msgid "Volume %s is not active."
+msgstr "O volume %s não está ativado."
+
+#: lib/setup.c:2911
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "O volume %s já está suspenso."
+
+#: lib/setup.c:2925
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "A suspensão não oferece suporte ao dispositivo %s."
+
+#: lib/setup.c:2927
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Ocorreu um erro ao suspender o dispositivo %s."
+
+#: lib/setup.c:2960 lib/setup.c:3027
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "O volume %s não estava suspenso."
+
+#: lib/setup.c:2989
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "O resumo não oferece suporte a este dispositivo %s."
+
+#: lib/setup.c:2991 lib/setup.c:3059
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Ocorreu um erro ao resumir o dispositivo %s."
+
+#: lib/setup.c:3127 lib/setup.c:3315
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Não foi possível adicionar slot de chave, todos slots desabilitados ou nenhuma chave de volume fornecida."
+
+#: lib/setup.c:3267
+msgid "Failed to swap new key slot."
+msgstr "Falha ao trocar novo slot de chave."
+
+#: lib/setup.c:3432 lib/setup.c:3865 lib/setup.c:3878 lib/setup.c:3886
+#: lib/setup.c:3899 lib/setup.c:4198 lib/setup.c:5274
+msgid "Volume key does not match the volume."
+msgstr "A chave de volume não corresponde ao volume."
+
+#: lib/setup.c:3453
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "O slot de chave %d é inválido."
+
+#: lib/setup.c:3459
+#, c-format
+msgid "Key slot %d is not used."
+msgstr "O slot de chave %d não está sendo usado."
+
+#: lib/setup.c:3478
+msgid "Device header overlaps with data area."
+msgstr "O cabeçalho do dispositivo se sobrepõe à área de dados."
+
+#: lib/setup.c:3684 lib/setup.c:3952
+msgid "Device type is not properly initialised."
+msgstr "O tipo de dispositivo não foi inicializado corretamente."
+
+#: lib/setup.c:3726
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Não foi possível usar o dispositivo %s, o nome é inválido ou ainda está em uso."
+
+#: lib/setup.c:3729
+#, c-format
+msgid "Device %s already exists."
+msgstr "O dispositivo %s já existe."
+
+#: lib/setup.c:3852
+msgid "Incorrect volume key specified for plain device."
+msgstr "Chave de volume incorreta especificada para dispositivo claro."
+
+#: lib/setup.c:3918
+msgid "Incorrect root hash specified for verity device."
+msgstr "Hash raiz incorreta especificada para o dispositivo verity."
+
+#: lib/setup.c:3995 lib/setup.c:4010
+#, c-format
+msgid "Device %s is still in use."
+msgstr "O dispositivo %s ainda está em uso."
+
+#: lib/setup.c:4025
+#, c-format
+msgid "Invalid device %s."
+msgstr "Dispositivo inválido %s."
+
+#: lib/setup.c:4134
+msgid "Function not available in FIPS mode."
+msgstr "Função não disponível no modo FIPS."
+
+#: lib/setup.c:4148
+msgid "Volume key buffer too small."
+msgstr "Buffer de chave de volume muito pequena."
+
+#: lib/setup.c:4156
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Não foi possível obter chave de volume para dispositivo claro."
+
+#: lib/setup.c:4167
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Não há suporte a esta operação para o dispositivo de criptografia %s."
+
+#: lib/setup.c:4354
+msgid "Dump operation is not supported for this device type."
+msgstr "Não há suporte à operação de despejo para este tipo de dispositivo."
+
+#: lib/setup.c:4930
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Não foi possível converter o dispositivo %s, o qual ainda está em uso."
+
+#: lib/setup.c:5213
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Falha ao atribuir o slot de chave %u como a nova chave de volume."
+
+#: lib/setup.c:5280
+msgid "Failed to initialise default LUKS2 keyslot parameters."
+msgstr "Falha ao inicializar os parâmetros padrão de slot de chave LUKS2."
+
+#: lib/setup.c:5286
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Falha ao atribuir o slot de chave %d ao resumo."
+
+#: lib/setup.c:5370
+msgid "Failed to load key in kernel keyring."
+msgstr "Falha ao carregar chave no chaveiro de kernel."
+
+#: lib/setup.c:5425
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Não há suporte a chaveiro de kernel neste kernel."
+
+#: lib/setup.c:5435
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Falha ao ler senha do chaveiro (erro %d)."
+
+#: lib/utils.c:81
+msgid "Cannot get process priority."
+msgstr "Não foi possível obter prioridade de processo."
+
+#: lib/utils.c:95
+msgid "Cannot unlock memory."
+msgstr "Não foi possível desbloquear memória."
+
+#: lib/utils.c:169 lib/tcrypt/tcrypt.c:498
+msgid "Failed to open key file."
+msgstr "Falha ao abrir arquivo de chave."
+
+#: lib/utils.c:174
+msgid "Cannot read keyfile from a terminal."
+msgstr "Não foi possível ler o arquivo de chave de um terminal."
+
+#: lib/utils.c:191
+msgid "Failed to stat key file."
+msgstr "Falha ao obter estado do arquivo."
+
+#: lib/utils.c:199 lib/utils.c:220
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Não foi possível buscar a posição do arquivo de chave requisitado."
+
+#: lib/utils.c:214 lib/utils.c:229 src/utils_password.c:188
+#: src/utils_password.c:201
+msgid "Out of memory while reading passphrase."
+msgstr "Memória insuficiente para leitura da senha."
+
+#: lib/utils.c:249
+msgid "Error reading passphrase."
+msgstr "Erro ao ler a senha."
+
+#: lib/utils.c:266
+msgid "Nothing to read on input."
+msgstr "Nada para ler na entrada."
+
+#: lib/utils.c:273
+msgid "Maximum keyfile size exceeded."
+msgstr "Tamanho máximo de arquivo de chave excedido."
+
+#: lib/utils.c:278
+msgid "Cannot read requested amount of data."
+msgstr "Não foi possível ler a quantidade requisitada de dados."
+
+#: lib/utils_device.c:184 lib/luks1/keyencryption.c:92
+#, c-format
+msgid "Device %s doesn't exist or access denied."
+msgstr "O dispositivo %s não existe ou acesso negado."
+
+#: lib/utils_device.c:194
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "O dispositivo %s não é compatível."
+
+#: lib/utils_device.c:560
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Dispositivo %s é muito pequeno. Necessita de pelo menos %<PRIu64> bytes."
+
+#: lib/utils_device.c:641
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Não foi possível usar o dispositivo %s, o qual está em uso (já mapeado ou montado)."
+
+#: lib/utils_device.c:645
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Não foi possível usar o dispositivo %s, permissão negada."
+
+#: lib/utils_device.c:648
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Não foi possível obter informação sobre o dispositivo %s."
+
+#: lib/utils_device.c:671
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Não foi possível usar um dispositivo de loopback, executando como usuário não-root."
+
+#: lib/utils_device.c:681
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Anexação de dispositivo loopback falhou (dispositivo de loop com sinalizador autoclear é necessário)."
+
+#: lib/utils_device.c:727
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "A posição requisitada está além do tamanho real do dispositivo %s."
+
+#: lib/utils_device.c:735
+#, c-format
+msgid "Device %s has zero size."
+msgstr "O dispositivo %s possui tamanho zero."
+
+#: lib/utils_device.c:746 lib/luks1/keyencryption.c:252
+#, c-format
+msgid "Device %s is too small."
+msgstr "O dispositivo %s é muito pequeno."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Tempo alvo PBKDF requisitado não pode ser zero."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Tipo %s de PBKDF desconhecido."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Não há suporte ao hash requisitado %s."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Não há suporte ao tipo de PBKDF requisitado para LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Fluxos paralelos ou memória máxima de PBKDF não pode estar definida com pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Contagem de iterações forçadas é pequena demais para %s (mínimo é %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Custo de memória forçada é pequeno demais para %s (mínimo é %u kilobytes)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Custo de memória PBKDF máximo requisitado é alto demais (o máximo é %d kilobytes)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Memória PBKDF máxima requisitada não pode ser zero."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Fluxos paralelos PBKDF requisitados não podem ser zero."
+
+#: lib/utils_benchmark.c:317
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Teste de PBKDF desabilitado, mas iterações não definidas."
+
+#: lib/utils_benchmark.c:336
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Opções PBKDF2 não compatíveis (sando algoritmo hash %s)."
+
+#: lib/utils_benchmark.c:356
+msgid "Not compatible PBKDF options."
+msgstr "Opções PBKDF2 não compatíveis."
+
+#: lib/utils_device_locking.c:80
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Trava abortada. O caminho de trava %s/%s não é usável (faltando ou não é um diretório)."
+
+#: lib/utils_device_locking.c:87
+#, c-format
+msgid "WARNING: Locking directory %s/%s is missing!\n"
+msgstr "AVISO: Diretório de trava %s/%s está faltando!\n"
+
+#: lib/utils_device_locking.c:97
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Trava abortada. O caminho de trava %s/%s não é usável (%s não é um diretório)."
+
+#: lib/luks1/keyencryption.c:40
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Falha ao configurar mapeamento de chave dm-crypt para o dispositivo %s.\n"
+"Certifique-se de que o kernel oferece suporte cifra de %s (verifique o syslog para mais informação)."
+
+#: lib/luks1/keyencryption.c:45
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Tamanho de chave no modo XTS deve ser 256 ou 512 bits."
+
+#: lib/luks1/keyencryption.c:47
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "A especificação de cifra deve estar no formato [cifra]-[modo]-[iv]."
+
+#: lib/luks1/keyencryption.c:98 lib/luks1/keymanage.c:345
+#: lib/luks1/keymanage.c:642 lib/luks1/keymanage.c:1079
+#: lib/luks2/luks2_json_metadata.c:1157 lib/luks2/luks2_keyslot.c:448
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Não foi possível escrever para o dispositivo %s, permissão negada."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Falha ao abrir o dispositivo temporário de armazenamento de chave."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Falha ao acessar o dispositivo temporário de armazenamento de chave."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:91
+msgid "IO error while encrypting keyslot."
+msgstr "Erro de E/S ao criptografar slot de chave."
+
+#: lib/luks1/keyencryption.c:243 lib/luks1/keymanage.c:348
+#: lib/luks1/keymanage.c:594 lib/luks1/keymanage.c:645 lib/tcrypt/tcrypt.c:663
+#: lib/verity/verity.c:81 lib/verity/verity.c:182 lib/verity/verity_hash.c:308
+#: lib/verity/verity_hash.c:319 lib/verity/verity_hash.c:339
+#: lib/verity/verity_fec.c:242 lib/verity/verity_fec.c:254
+#: lib/verity/verity_fec.c:259 lib/luks2/luks2_json_metadata.c:1160
+#: src/cryptsetup_reencrypt.c:208
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Não foi possível abrir o dispositivo %s."
+
+#: lib/luks1/keyencryption.c:254 lib/luks2/luks2_keyslot_luks2.c:152
+msgid "IO error while decrypting keyslot."
+msgstr "Erro de E/S ao descriptografar slot de chave."
+
+#: lib/luks1/keymanage.c:111
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Dispositivo %s é muito pequeno. (LUKS1 precisa de pelo menos %<PRIu64> bytes.)"
+
+#: lib/luks1/keymanage.c:132 lib/luks1/keymanage.c:140
+#: lib/luks1/keymanage.c:152 lib/luks1/keymanage.c:163
+#: lib/luks1/keymanage.c:175
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "O slot de chave LUKS %u é inválido."
+
+#: lib/luks1/keymanage.c:228 lib/luks1/keymanage.c:478
+#: lib/luks2/luks2_json_metadata.c:991 src/cryptsetup.c:1236
+#: src/cryptsetup.c:1355 src/cryptsetup.c:1412 src/cryptsetup.c:1468
+#: src/cryptsetup.c:1535 src/cryptsetup.c:1631 src/cryptsetup.c:1695
+#: src/cryptsetup.c:1855 src/cryptsetup.c:2044 src/cryptsetup.c:2104
+#: src/cryptsetup.c:2170 src/cryptsetup.c:2334 src/cryptsetup_reencrypt.c:1397
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "O dispositivo %s não é um dispositivo LUKS válido."
+
+#: lib/luks1/keymanage.c:247 lib/luks2/luks2_json_metadata.c:1010
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "O arquivo de cópia de segurança de cabeçalho requisitado %s já existe."
+
+#: lib/luks1/keymanage.c:249 lib/luks2/luks2_json_metadata.c:1012
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Não foi possível criar o arquivo de cópia de segurança de cabeçalho %s."
+
+#: lib/luks1/keymanage.c:254 lib/luks2/luks2_json_metadata.c:1017
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Não foi possível escrever o arquivo de cópia de segurança de cabeçalho %s."
+
+#: lib/luks1/keymanage.c:287 lib/luks2/luks2_json_metadata.c:1066
+msgid "Backup file doesn't contain valid LUKS header."
+msgstr "Arquivo de cópia de segurança não contém cabeçalho LUKS válido."
+
+#: lib/luks1/keymanage.c:300 lib/luks1/keymanage.c:555
+#: lib/luks2/luks2_json_metadata.c:1087
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Não foi possível abrir o arquivo de cópia de segurança de cabeçalho %s."
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1093
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Não foi possível ler o arquivo de cópia de segurança de cabeçalho %s."
+
+#: lib/luks1/keymanage.c:318
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Posição de dados ou tamanho de chave divergem entre dispositivo e cópia de segurança, restauração falhou."
+
+#: lib/luks1/keymanage.c:326
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Dispositivo %s %s%s"
+
+#: lib/luks1/keymanage.c:327
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "não contém cabeçalho LUKS. A substituição do cabeçalho pode destruir dados naquele dispositivo."
+
+#: lib/luks1/keymanage.c:328
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "já contém cabeçalho LUKS. A substituição do cabeçalho vai destruir slots de chave existentes."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1129
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"AVISO: o cabeçalho do dispositivo real possui um UUID diferente da cópia de segurança!"
+
+#: lib/luks1/keymanage.c:381
+msgid "Non standard key size, manual repair required."
+msgstr "Tamanho de chave fora do padrão, correção manual necessária."
+
+#: lib/luks1/keymanage.c:386
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Alinhamento de slots de chave fora do padrão, correção manual necessária."
+
+#: lib/luks1/keymanage.c:396
+msgid "Repairing keyslots."
+msgstr "Corrigindo slots de chave."
+
+#: lib/luks1/keymanage.c:415
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Slot de chave %i: posição corrigida (%u -> %u)."
+
+#: lib/luks1/keymanage.c:423
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Slot de chave %i: barras corrigidas (%u -> %u)."
+
+#: lib/luks1/keymanage.c:432
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Slot de chave %i: assinatura de partição é falsa."
+
+#: lib/luks1/keymanage.c:437
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Slot de chave %i: sal apagado."
+
+#: lib/luks1/keymanage.c:454
+msgid "Writing LUKS header to disk."
+msgstr "Escrevendo cabeçalho LUKS para disco."
+
+#: lib/luks1/keymanage.c:459
+msgid "Repair failed."
+msgstr "Correção falhou."
+
+#: lib/luks1/keymanage.c:487 lib/luks1/keymanage.c:758
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Não há suporte ao hash LUKS requisitado %s."
+
+#: lib/luks1/keymanage.c:515 src/cryptsetup.c:960
+msgid "No known problems detected for LUKS header."
+msgstr "Nenhum problema conhecido foi detectado no cabeçalho LUKS."
+
+#: lib/luks1/keymanage.c:667
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Erro durante atualização de cabeçalho LUKS no dispositivo %s."
+
+#: lib/luks1/keymanage.c:676
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Erro ao reler cabeçalho LUKS após atualização no dispositivo %s."
+
+#: lib/luks1/keymanage.c:752
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "A posição de dados para cabeçalho LUKS deve ser 0 ou maior do que o tamanho do cabeçalho."
+
+#: lib/luks1/keymanage.c:763 lib/luks1/keymanage.c:828
+#: lib/luks2/luks2_json_format.c:207 lib/luks2/luks2_json_metadata.c:909
+msgid "Wrong LUKS UUID format provided."
+msgstr "Formato de UUID LUKS incorreto foi fornecido."
+
+#: lib/luks1/keymanage.c:786
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Não foi possível criar cabeçalho LUKS: leitura de sal aleatório falhou."
+
+#: lib/luks1/keymanage.c:807
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Não foi possível criar cabeçalho LUKS: resumo de cabeçalho falhou (usando hash %s)."
+
+#: lib/luks1/keymanage.c:851
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Slot de chave %d ativado, apagar primeiro."
+
+#: lib/luks1/keymanage.c:857
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "O material do slot de chave %d inclui muito poucas barras. Manipulação do cabeçalho?"
+
+#: lib/luks1/keymanage.c:1065
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Slot de chave %d é inválido, por favor selecione um slot de chave entre 0 e %d."
+
+#: lib/luks1/keymanage.c:1083 lib/luks2/luks2_keyslot.c:452
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Não foi possível apagar o dispositivo %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Detectado arquivo de chave criptografado com GPG ainda sem suporte."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Por favor use gpg --decrypt <ARQUIVO-CHAVE> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Arquivo de chave loop-AES incompatível detectado."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel doesn't support loop-AES compatible mapping."
+msgstr "O kernel não oferece suporte a mapeamento compatível com loop-AES."
+
+#: lib/tcrypt/tcrypt.c:505
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Erro ao ler arquivo de chave %s."
+
+#: lib/tcrypt/tcrypt.c:545
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%d) exceeded."
+msgstr "Tamanho máximo de senha TCRYPT (%d) excedido."
+
+#: lib/tcrypt/tcrypt.c:586
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Algoritmo hash PBKDF2 %s não disponível, ignorando."
+
+#: lib/tcrypt/tcrypt.c:604 src/cryptsetup.c:915
+msgid "Required kernel crypto interface not available."
+msgstr "Interface necessário de criptografia do kernel não disponível."
+
+#: lib/tcrypt/tcrypt.c:606 src/cryptsetup.c:917
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Certifique-se de que você tenha o módulo de kernel algif_skcipher carregado."
+
+#: lib/tcrypt/tcrypt.c:746
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Não há suporte a ativação para o tamanho de setor %d."
+
+#: lib/tcrypt/tcrypt.c:752
+msgid "Kernel doesn't support activation for this TCRYPT legacy mode."
+msgstr "O kernel não oferece suporte a ativação para este modo legado TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:786
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Ativando criptografia de sistema TCRYPT para partição %s."
+
+#: lib/tcrypt/tcrypt.c:864
+msgid "Kernel doesn't support TCRYPT compatible mapping."
+msgstr "O kernel não oferece suporte a mapeamento compatível com TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1085
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Não há suporte a esta função sem carga de cabeçalho TCRYPT."
+
+#: lib/verity/verity.c:69 lib/verity/verity.c:175
+#, c-format
+msgid "Verity device %s doesn't use on-disk header."
+msgstr "Dispositivo verity %s não usa cabeçalho em disco."
+
+#: lib/verity/verity.c:94
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "O dispositivo %s não é um dispositivo VERITY válido."
+
+#: lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Não há suporte ao VERITY versão %d."
+
+#: lib/verity/verity.c:132
+msgid "VERITY header corrupted."
+msgstr "Cabeçalho VERITY corrompido."
+
+#: lib/verity/verity.c:169
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Formato de UUID VERITY inválido fornecido no dispositivo %s."
+
+#: lib/verity/verity.c:202
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Erro durante a atualização do cabeçalho verity no dispositivo %s."
+
+#: lib/verity/verity.c:266
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Os erros não puderam ser consertados com dispositivo FEC."
+
+#: lib/verity/verity.c:268
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Localizados %u erros corrigíveis com dispositivo FEC."
+
+#: lib/verity/verity.c:306
+msgid "Kernel doesn't support dm-verity mapping."
+msgstr "O kernel não oferece suporte a mapeamento dm-verity."
+
+#: lib/verity/verity.c:317
+msgid "Verity device detected corruption after activation."
+msgstr "O dispositivo verity detectou corrompimento após ativação."
+
+#: lib/verity/verity_hash.c:59
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Área disponível não está zerada na posição %<PRIu64>."
+
+#: lib/verity/verity_hash.c:160 lib/verity/verity_hash.c:287
+#: lib/verity/verity_hash.c:300
+msgid "Device offset overflow."
+msgstr "Excesso na posição do dispositivo."
+
+#: lib/verity/verity_hash.c:200
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Verificação falhou na posição %<PRIu64>."
+
+#: lib/verity/verity_hash.c:273
+msgid "Invalid size parameters for verity device."
+msgstr "Parâmetros de tamanho inválido para dispositivo verity."
+
+#: lib/verity/verity_hash.c:293
+msgid "Hash area overflow."
+msgstr "Estouro de área de hash."
+
+#: lib/verity/verity_hash.c:370
+msgid "Verification of data area failed."
+msgstr "Verificação da área de dados falhou."
+
+#: lib/verity/verity_hash.c:375
+msgid "Verification of root hash failed."
+msgstr "Verificação do hash raiz falhou."
+
+#: lib/verity/verity_hash.c:381
+msgid "Input/output error while creating hash area."
+msgstr "Erro de entrada/saída enquanto criava área de hash."
+
+#: lib/verity/verity_hash.c:383
+msgid "Creation of hash area failed."
+msgstr "Criação da área de hash falhou."
+
+#: lib/verity/verity_hash.c:430
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "AVISO: O kernel não pode ativar um dispositivo se o tamanho do bloco de dados exceder o tamanho da página (%u)."
+
+#: lib/verity/verity_fec.c:132
+msgid "Failed to allocate RS context."
+msgstr "Falha ao alocar contexto de RS."
+
+#: lib/verity/verity_fec.c:147
+msgid "Failed to allocate buffer."
+msgstr "Falha ao alocar buffer."
+
+#: lib/verity/verity_fec.c:157
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Falha ao ler byte %2$d de bloco RS %1$<PRIu64>."
+
+#: lib/verity/verity_fec.c:170
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Falha ao ler paridade para o bloco RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:178
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Falha ao corrigir paridade para o bloco %<PRIu64>."
+
+#: lib/verity/verity_fec.c:189
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Falha ao escrever paridade para o bloco RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:224
+msgid "Block sizes must match for FEC."
+msgstr "Tamanhos de bolcos devem corresponder para FEC."
+
+#: lib/verity/verity_fec.c:230
+msgid "Invalid number of parity bytes."
+msgstr "Número inválido de paridade de bytes."
+
+#: lib/verity/verity_fec.c:266
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Falha ao determinar o tamanho para dispositivo %s."
+
+#: lib/integrity/integrity.c:239 lib/integrity/integrity.c:304
+msgid "Kernel doesn't support dm-integrity mapping."
+msgstr "O kernel não oferece suporte a mapeamento dm-integrity."
+
+#: lib/luks2/luks2_disk_metadata.c:413
+msgid "Failed to acquire write device lock."
+msgstr "Falha ao obter trava de dispositivo de escrita."
+
+#: lib/luks2/luks2_disk_metadata.c:654 lib/luks2/luks2_disk_metadata.c:675
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"O dispositivo contém assinaturas ambíguas, falha ao autorrecuperar LUKS2.\n"
+"Por favor, execute \"cryptsetup repair\" para recuperação."
+
+#: lib/luks2/luks2_json_format.c:99
+msgid "No space for new keyslot."
+msgstr "Sem espaço para um novo slot de chave."
+
+#: lib/luks2/luks2_json_format.c:158
+msgid "Requested data offset is too small."
+msgstr "A posição dos dados requisitados é muito pequena."
+
+#: lib/luks2/luks2_json_format.c:195
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "AVISO: área de slot de chaves (%<PRIu64> bytes) é muito pequena, a contagem de slot de chaves LUKS2 disponível é muito limitada.\n"
+
+#: lib/luks2/luks2_json_metadata.c:866 lib/luks2/luks2_json_metadata.c:982
+#: lib/luks2/luks2_json_metadata.c:1055 lib/luks2/luks2_keyslot_luks2.c:105
+#: lib/luks2/luks2_keyslot_luks2.c:128
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Falha ao obter trava de leitura no dispositivo %s."
+
+#: lib/luks2/luks2_json_metadata.c:878 lib/luks2/luks2_json_metadata.c:1149
+#: lib/luks2/luks2_keyslot.c:431 lib/luks2/luks2_keyslot_luks2.c:40
+#: lib/luks2/luks2_keyslot_luks2.c:69
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Falha ao obter trava de escrita no dispositivo %s."
+
+#: lib/luks2/luks2_json_metadata.c:1072
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Requisitos LUKS2 proibidos detectados na cópia de segurança %s."
+
+#: lib/luks2/luks2_json_metadata.c:1113
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Posição de dados diverge entre dispositivo e cópia de segurança, restauração falhou."
+
+#: lib/luks2/luks2_json_metadata.c:1119
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Cabeçalho binário com áreas de slot de chave diverge entre dispositivo e cópia de segurança, restauração falhou."
+
+#: lib/luks2/luks2_json_metadata.c:1126
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Dispositivo %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1127
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "não contém cabeçalho LUKS2. A substituição do cabeçalho pode destruir dados naquele dispositivo."
+
+#: lib/luks2/luks2_json_metadata.c:1128
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "já contém cabeçalho LUKS2. A substituição do cabeçalho vai destruir slots de chave existentes."
+
+#: lib/luks2/luks2_json_metadata.c:1130
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"AVISO: requisitos LUKS2 desconhecidos detectados em cabeçalho de\n"
+"dispositivo real! Substituir cabeçalho com cópia de segurança pode\n"
+"corromper os dados naquele dispositivo!"
+
+#: lib/luks2/luks2_json_metadata.c:1132
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"AVISO: recriptografia offline não finalizada detectada no dispositivo!\n"
+"Substituir cabeçalho com cópia de segurança pode corromper os dados."
+
+#: lib/luks2/luks2_json_metadata.c:1234
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Sinalizador desconhecido %s ignorado."
+
+#: lib/luks2/luks2_json_metadata.c:1869
+msgid "Failed to read LUKS2 requirements."
+msgstr "Falha ao ler requisitos LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:1876
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Requisitos LUKS2 não atendidos detectados."
+
+#: lib/luks2/luks2_json_metadata.c:1884
+msgid "Offline reencryption in progress. Aborting."
+msgstr "Recriptografia offline em progresso. Abortando."
+
+#: lib/luks2/luks2_luks1_convert.c:474
+#, c-format
+msgid "Can not check status of device with uuid: %s."
+msgstr "Não foi possível verificar status do dispositivo com uuid: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:500
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Não foi possível converter cabeçalho com metadados adicionais LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:537
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Não foi possível mover área de slot de chave. Espaço insuficiente."
+
+#: lib/luks2/luks2_luks1_convert.c:577 lib/luks2/luks2_luks1_convert.c:854
+msgid "Unable to move keyslot area."
+msgstr "Não foi possível mover área de slot de chave."
+
+#: lib/luks2/luks2_luks1_convert.c:672
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Não foi possível converter ao formato LUKS1 - resumos de slot de chave não são compatíveis com LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:684
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Não foi possível converter para o formato LUKS1 - o dispositivo usa cifra de chave envolta %s."
+
+#: lib/luks2/luks2_luks1_convert.c:692
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Não foi possível converter para o formato LUKS1 - o cabeçalho LUKS2 contém %u token(s)."
+
+#: lib/luks2/luks2_luks1_convert.c:706
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Não foi possível converter para o formato LUKS1 - o slot de chave %u está em um estado inválido."
+
+#: lib/luks2/luks2_luks1_convert.c:711
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Não foi possível converter para o formato LUKS1 - o slot %u (acima do máximo de slots) ainda está ativo."
+
+#: lib/luks2/luks2_luks1_convert.c:716
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Não foi possível converter ao formato LUKS1 - o slot de chave %u não é compatível com LUKS1."
+
+#: lib/luks2/luks2_token.c:262
+msgid "No free token slot."
+msgstr "Nenhum slot de token livre."
+
+#: lib/luks2/luks2_token.c:269
+#, c-format
+msgid "Failed to create builtin token %s."
+msgstr "Falha ao criar um token incorporado %s."
+
+#: src/cryptsetup.c:141
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Não é possível fazer verificação de senha em entradas diferente de tty."
+
+#: src/cryptsetup.c:182
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Parâmetros de criptografia de slot de chaves só pode ser definido para dispositivo LUKS2."
+
+#: src/cryptsetup.c:212 src/cryptsetup.c:849 src/cryptsetup.c:1088
+#: src/cryptsetup_reencrypt.c:749 src/cryptsetup_reencrypt.c:814
+msgid "No known cipher specification pattern detected."
+msgstr "Nenhum padrão de especificação de cifra conhecida foi detectada."
+
+#: src/cryptsetup.c:220
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "AVISO: O parâmetro de --hash está sendo ignorado claro com o arquivo de chave especificado.\n"
+
+#: src/cryptsetup.c:228
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "AVISO: A opção --keyfile-size está sendo ignorada, o tamanho lido é o mesmo que o tamanho da chave de criptografia.\n"
+
+#: src/cryptsetup.c:268
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Detectada assinatura(s) de dispositivo em %s. Prosseguir pode danificar dados existentes."
+
+#: src/cryptsetup.c:274 src/cryptsetup.c:969 src/cryptsetup.c:1065
+#: src/cryptsetup.c:1138 src/cryptsetup.c:1763 src/integritysetup.c:230
+msgid "Operation aborted.\n"
+msgstr "Operação abortada.\n"
+
+#: src/cryptsetup.c:342
+msgid "Option --key-file is required."
+msgstr "A opção --key-file é necessária."
+
+#: src/cryptsetup.c:395
+msgid "Enter VeraCrypt PIM: "
+msgstr "Insira o PIM VeraCrypt: "
+
+#: src/cryptsetup.c:404
+msgid "Invalid PIM value: parse error."
+msgstr "Valor de PIM inválido: erro de análise."
+
+#: src/cryptsetup.c:407
+msgid "Invalid PIM value: 0."
+msgstr "Valor de PIM inválido: 0."
+
+#: src/cryptsetup.c:410
+msgid "Invalid PIM value: outside of range."
+msgstr "Valor de PIM inválido: fora do intervalo."
+
+#: src/cryptsetup.c:433
+msgid "No device header detected with this passphrase."
+msgstr "Nenhum cabeçalho de dispositivo detectado com esta senha."
+
+#: src/cryptsetup.c:495 src/cryptsetup.c:1790
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"O despejo de cabeçalho com chave de volume é uma informação sensível\n"
+"que permite acesso a uma partição criptografada sem senha.\n"
+"Este despejo deve sempre ser armazenado criptografado em um local seguro."
+
+#: src/cryptsetup.c:574
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "O dispositivo %s ainda está ativo e agendado para a remoção atrasada.\n"
+
+#: src/cryptsetup.c:602
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Redimensionamento de dispositivo ativo requer chave de volume no chaveiro, mas a opção --disable-keyring está definida."
+
+#: src/cryptsetup.c:727
+msgid "Benchmark interrupted."
+msgstr "Teste interrompido."
+
+#: src/cryptsetup.c:748
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/A\n"
+
+#: src/cryptsetup.c:750
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iterações por segundo para chave de %zu bits\n"
+
+#: src/cryptsetup.c:764
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/D\n"
+
+#: src/cryptsetup.c:766
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iterações, %5u memória, %1u threads paralelas (CPUs) para chave de %zu bits (requisitado tempo de %u ms)\n"
+
+#: src/cryptsetup.c:790
+msgid "Result of benchmark is not reliable."
+msgstr "O resultado do teste não é confiável."
+
+#: src/cryptsetup.c:841
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Testes são aproximados usando apenas memória (sem E/S de armazenamento).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:875
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algoritmo | Chave | Criptografia | Descriptografia\n"
+
+#: src/cryptsetup.c:879
+#, c-format
+msgid "Cipher %s is not available."
+msgstr "A cifra %s não está disponível."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:899
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritmo | Chave | Criptografia | Descriptografia\n"
+
+#: src/cryptsetup.c:908
+msgid "N/A"
+msgstr "N/D"
+
+#: src/cryptsetup.c:968
+msgid "Really try to repair LUKS device header?"
+msgstr "Realmente tentar corrigir o cabeçalho do dispositivo LUKS?"
+
+#: src/cryptsetup.c:984 src/integritysetup.c:144
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Apando dispositivo para inicializar a verificação de soma de integridade.\n"
+"Você pode interromper isso pressionando CTRL+C (o resto dos dispositivo não apagado conterão verificação de soma inválida).\n"
+
+#: src/cryptsetup.c:1006 src/integritysetup.c:166
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Não foi possível desativar o dispositivo temporário %s."
+
+#: src/cryptsetup.c:1050
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "A opção de integridade pode ser usada apenas para o formato LUKS2."
+
+#: src/cryptsetup.c:1055 src/cryptsetup.c:1115
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Não há suporte às opções de tamanho de metadados LUKS."
+
+#: src/cryptsetup.c:1072
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Não foi possível criar o arquivo de cabeçalho %s."
+
+#: src/cryptsetup.c:1095 src/integritysetup.c:192 src/integritysetup.c:201
+#: src/integritysetup.c:210 src/integritysetup.c:276 src/integritysetup.c:285
+#: src/integritysetup.c:295
+msgid "No known integrity specification pattern detected."
+msgstr "Nenhum padrão de especificação de integridade conhecida foi detectado."
+
+#: src/cryptsetup.c:1108
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Não foi possível usar %s como um cabeçalho em disco."
+
+#: src/cryptsetup.c:1132 src/integritysetup.c:224
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Isto vai sobrescrever dados em %s permanentemente."
+
+#: src/cryptsetup.c:1173 src/cryptsetup.c:1484 src/cryptsetup.c:1551
+#: src/cryptsetup.c:1646 src/cryptsetup.c:1712
+msgid "Failed to set pbkdf parameters."
+msgstr "Falha ao definir os parâmetros de pbkdf."
+
+#: src/cryptsetup.c:1242
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Posição de dados reduzida é permitido apenas cabeçalho LUKS desanexado."
+
+#: src/cryptsetup.c:1284
+msgid "Device activated but cannot make flags persistent."
+msgstr "Dispositivo ativado, mas não foi possível tornar os sinalizadores persistentes."
+
+#: src/cryptsetup.c:1365
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Slot de chave %d selecionado para exclusão."
+
+#: src/cryptsetup.c:1368 src/cryptsetup.c:1706
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "O slot de chave %d não está ativo."
+
+#: src/cryptsetup.c:1377 src/cryptsetup.c:1438
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Este é o último slot de chave. O dispositivo se tornará não usável após apagar esta chave."
+
+#: src/cryptsetup.c:1378
+msgid "Enter any remaining passphrase: "
+msgstr "Digite qualquer senha remanescente: "
+
+#: src/cryptsetup.c:1379 src/cryptsetup.c:1440
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operação abortada, o slot de chave NÃO foi apagado.\n"
+
+#: src/cryptsetup.c:1417
+msgid "Enter passphrase to be deleted: "
+msgstr "Digite a senha para ser excluída: "
+
+#: src/cryptsetup.c:1435
+#, c-format
+msgid "Key slot %d selected for deletion."
+msgstr "Slot de chave %d selecionado para exclusão."
+
+#: src/cryptsetup.c:1498 src/cryptsetup.c:1565 src/cryptsetup.c:1599
+msgid "Enter new passphrase for key slot: "
+msgstr "Digite uma senha para o slot de chave: "
+
+#: src/cryptsetup.c:1582 src/cryptsetup_reencrypt.c:1352
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Digite qualquer senha existente: "
+
+#: src/cryptsetup.c:1650
+msgid "Enter passphrase to be changed: "
+msgstr "Digite a senha para ser alterada: "
+
+#: src/cryptsetup.c:1666 src/cryptsetup_reencrypt.c:1338
+msgid "Enter new passphrase: "
+msgstr "Digite uma nova senha: "
+
+#: src/cryptsetup.c:1716
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Digite uma senha para slot de chave a ser convertido: "
+
+#: src/cryptsetup.c:1740
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Há suporte apenas a um argumento de dispositivo para a operação isLuks."
+
+#: src/cryptsetup.c:1924 src/cryptsetup.c:1945
+msgid "Option --header-backup-file is required."
+msgstr "A opção --header-backup-file é necessária."
+
+#: src/cryptsetup.c:1975
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s não é um dispositivo cryptsetup gerenciado."
+
+#: src/cryptsetup.c:1986
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "A renovação não oferece suporte a este tipo de dispositivo %s"
+
+#: src/cryptsetup.c:2024
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Tipo de dispositivo de metadados %s não reconhecido."
+
+#: src/cryptsetup.c:2027
+msgid "Command requires device and mapped name as arguments."
+msgstr "O comando requer um dispositivo e nome mapeado como argumentos."
+
+#: src/cryptsetup.c:2049
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Esta operação vai apagar todos os slots de chave no dispositivo %s.\n"
+"O dispositivo se tornará não usável após esta operação."
+
+#: src/cryptsetup.c:2056
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operação abortada, os slots de chave NÃO foram apagados.\n"
+
+#: src/cryptsetup.c:2093
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Tipo de LUKS inválido, há suporte apenas a luks1 e luks2."
+
+#: src/cryptsetup.c:2111
+#, c-format
+msgid "Device is already %s type."
+msgstr "O dispositivo já é do tipo %s."
+
+#: src/cryptsetup.c:2116
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Essa operação vai converter %s para o formato %s.\n"
+
+#: src/cryptsetup.c:2122
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operação abortada, o dispositivo NÃO foi convertido.\n"
+
+#: src/cryptsetup.c:2162
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Está faltando a opção --priority, --label ou --subsystem."
+
+#: src/cryptsetup.c:2196 src/cryptsetup.c:2229 src/cryptsetup.c:2252
+#, c-format
+msgid "Token %d is invalid."
+msgstr "O token %d é inválido."
+
+#: src/cryptsetup.c:2199 src/cryptsetup.c:2255
+#, c-format
+msgid "Token %d in use."
+msgstr "O token %d em uso."
+
+#: src/cryptsetup.c:2206
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Falha ao adicionar o token de chaveiro luks2 %d."
+
+#: src/cryptsetup.c:2215 src/cryptsetup.c:2277
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Falha ao atribuir o token %d ao slot de chave %d."
+
+#: src/cryptsetup.c:2232
+#, c-format
+msgid "Token %d is not in use."
+msgstr "O token %d não está em uso."
+
+#: src/cryptsetup.c:2267
+msgid "Failed to import token from file."
+msgstr "Falha ao abrir arquivo de chave."
+
+#: src/cryptsetup.c:2292
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Falha ao obter o token %d para exportação."
+
+#: src/cryptsetup.c:2307
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "O parâmetro --key-description é obrigatório para ação de adicionar token."
+
+#: src/cryptsetup.c:2313 src/cryptsetup.c:2321
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "A ação requer um token específico. Use o parâmetro --token-id."
+
+#: src/cryptsetup.c:2326
+#, c-format
+msgid "Invalid token operation %s."
+msgstr "Operação de token inválida %s."
+
+#: src/cryptsetup.c:2366
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<dispositivo> [--type <tipo>] [<nome>]"
+
+#: src/cryptsetup.c:2366
+msgid "open device as mapping <name>"
+msgstr "abre dispositivo como mapeamento <nome>"
+
+#: src/cryptsetup.c:2367 src/cryptsetup.c:2368 src/cryptsetup.c:2369
+#: src/veritysetup.c:363 src/veritysetup.c:364 src/integritysetup.c:464
+#: src/integritysetup.c:465
+msgid "<name>"
+msgstr "<nome>"
+
+#: src/cryptsetup.c:2367
+msgid "close device (remove mapping)"
+msgstr "fecha dispositivo (remove mapeamento)"
+
+#: src/cryptsetup.c:2368
+msgid "resize active device"
+msgstr "redimensiona dispositivo ativado"
+
+#: src/cryptsetup.c:2369
+msgid "show device status"
+msgstr "mostra o estado do dispositivo"
+
+#: src/cryptsetup.c:2370
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <cifra>]"
+
+#: src/cryptsetup.c:2370
+msgid "benchmark cipher"
+msgstr "testa a cifra"
+
+#: src/cryptsetup.c:2371 src/cryptsetup.c:2372 src/cryptsetup.c:2373
+#: src/cryptsetup.c:2374 src/cryptsetup.c:2381 src/cryptsetup.c:2382
+#: src/cryptsetup.c:2383 src/cryptsetup.c:2384 src/cryptsetup.c:2385
+#: src/cryptsetup.c:2386 src/cryptsetup.c:2387 src/cryptsetup.c:2388
+msgid "<device>"
+msgstr "<dispositivo>"
+
+#: src/cryptsetup.c:2371
+msgid "try to repair on-disk metadata"
+msgstr "tente corrigir os metadados em disco"
+
+#: src/cryptsetup.c:2372
+msgid "erase all keyslots (remove encryption key)"
+msgstr "apaga todos os slots de chave (remove a chave de criptografia)"
+
+#: src/cryptsetup.c:2373
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "converte formato LUKS de/para LUKS2"
+
+#: src/cryptsetup.c:2374
+msgid "set permanent configuration options for LUKS2"
+msgstr "define opções de configuração permanentes para LUKS2"
+
+#: src/cryptsetup.c:2375 src/cryptsetup.c:2376
+msgid "<device> [<new key file>]"
+msgstr "<dispositivo> [<novo arquivo de chave>]"
+
+#: src/cryptsetup.c:2375
+msgid "formats a LUKS device"
+msgstr "formata um dispositivo LUKS"
+
+#: src/cryptsetup.c:2376
+msgid "add key to LUKS device"
+msgstr "adiciona uma chave ao dispositivo LUKS"
+
+#: src/cryptsetup.c:2377 src/cryptsetup.c:2378 src/cryptsetup.c:2379
+msgid "<device> [<key file>]"
+msgstr "<dispositivo> [<arquivo de chave >]"
+
+#: src/cryptsetup.c:2377
+msgid "removes supplied key or key file from LUKS device"
+msgstr "remove a chave ou arquivo chave fornecidos do dispositivo LUKS"
+
+#: src/cryptsetup.c:2378
+msgid "changes supplied key or key file of LUKS device"
+msgstr "altera a chave ou arquivo chave fornecidos do dispositivo LUKS"
+
+#: src/cryptsetup.c:2379
+msgid "converts a key to new pbkdf parameters"
+msgstr "converte uma chave aos novos parâmetros de pbkdf"
+
+#: src/cryptsetup.c:2380
+msgid "<device> <key slot>"
+msgstr "<dispositivo> <slot de chave>"
+
+#: src/cryptsetup.c:2380
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "apaga chave com número <slot de chave> do dispositivo LUKS"
+
+#: src/cryptsetup.c:2381
+msgid "print UUID of LUKS device"
+msgstr "emite UUID do dispositivo LUKS"
+
+#: src/cryptsetup.c:2382
+msgid "tests <device> for LUKS partition header"
+msgstr "testa <dispositivo> por cabeçalho de partição LUKS"
+
+#: src/cryptsetup.c:2383
+msgid "dump LUKS partition information"
+msgstr "despeja informação da partição LUKS"
+
+#: src/cryptsetup.c:2384
+msgid "dump TCRYPT device information"
+msgstr "despeja informação do dispositivo TCRYPT"
+
+#: src/cryptsetup.c:2385
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Suspende dispositivo LUKS e apaga chave (todas E/S ficam congeladas)"
+
+#: src/cryptsetup.c:2386
+msgid "Resume suspended LUKS device"
+msgstr "Resume dispositivo LUKS suspenso"
+
+#: src/cryptsetup.c:2387
+msgid "Backup LUKS device header and keyslots"
+msgstr "Faz uma cópia de segurança de slots de chave e cabeçalho de dispositivo LUKS"
+
+#: src/cryptsetup.c:2388
+msgid "Restore LUKS device header and keyslots"
+msgstr "Restaura slots de chave e cabeçalho de dispositivo LUKS"
+
+#: src/cryptsetup.c:2389
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <dispositivo>"
+
+#: src/cryptsetup.c:2389
+msgid "Manipulate LUKS2 tokens"
+msgstr "Manipula tokens LUKS2"
+
+#: src/cryptsetup.c:2407 src/veritysetup.c:380 src/integritysetup.c:481
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<ação> é um entre:\n"
+
+#: src/cryptsetup.c:2413
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+msgstr ""
+"\n"
+"Você também pode usar apelidos de sintaxe <ação> antigos:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+
+#: src/cryptsetup.c:2417
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nome> é o dispositivo a ser criado sob %s\n"
+"<dispositivo> é o dispositivo criptografado\n"
+"<slot de chave> é o número do slot de chave LUKS a ser modificado\n"
+"<arquivo de chave> arquivo de chave opcional para a nova chave para a ação luksAddKey\n"
+
+#: src/cryptsetup.c:2424
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"O formato padrão de metadados compilados é %s (para a ação luksFormat).\n"
+
+#: src/cryptsetup.c:2429
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Parâmetros padrões de senha e chave compilados internamente:\n"
+"\tTamanho do arquivo chave máximo: %dkB, Tamanho máximo de senha interativa %d (caracteres)\n"
+"PBKDF padrão para LUKS1: %s, tempo de iteração: %d (ms)\n"
+"PBKDF padrão para LUKS2: %s\n"
+"\tTempo de iteração: %d: memória exigida: %dkB, Threads paralelas: %d\n"
+
+#: src/cryptsetup.c:2440
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Parâmetros de cifra de dispositivo pré-compilados por padrão:\n"
+"\tloop-AES: %s, Chave %d bits\n"
+"\tplain: %s, Chave: %d bits, Hash de senha: %s\n"
+"\tLUKS: %s, Chave: %d bits, Hash de cabeçalho LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:2449
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: keysize padrão com modo XTS (duas chaves internas) será duplicado.\n"
+
+#: src/cryptsetup.c:2460 src/veritysetup.c:537 src/integritysetup.c:621
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: necessita %s como argumentos"
+
+#: src/cryptsetup.c:2498 src/veritysetup.c:420 src/integritysetup.c:515
+#: src/cryptsetup_reencrypt.c:1611
+msgid "Show this help message"
+msgstr "Mostra essa mensagem de ajuda"
+
+#: src/cryptsetup.c:2499 src/veritysetup.c:421 src/integritysetup.c:516
+#: src/cryptsetup_reencrypt.c:1612
+msgid "Display brief usage"
+msgstr "Exibe instrução de uso"
+
+#: src/cryptsetup.c:2503 src/veritysetup.c:425 src/integritysetup.c:520
+#: src/cryptsetup_reencrypt.c:1616
+msgid "Help options:"
+msgstr "Opções de ajuda:"
+
+#: src/cryptsetup.c:2504 src/veritysetup.c:426 src/integritysetup.c:521
+#: src/cryptsetup_reencrypt.c:1617
+msgid "Print package version"
+msgstr "Emite a versão do pacote"
+
+#: src/cryptsetup.c:2505 src/veritysetup.c:427 src/integritysetup.c:522
+#: src/cryptsetup_reencrypt.c:1618
+msgid "Shows more detailed error messages"
+msgstr "Mostra mensagens de erro mais detalhadas"
+
+#: src/cryptsetup.c:2506 src/veritysetup.c:428 src/integritysetup.c:523
+#: src/cryptsetup_reencrypt.c:1619
+msgid "Show debug messages"
+msgstr "Mostra mensagens de depuração"
+
+#: src/cryptsetup.c:2507
+msgid "Show debug messages including JSON metadata"
+msgstr "Mostra mensagens de depuração incluindo metadados JSON"
+
+#: src/cryptsetup.c:2508 src/cryptsetup_reencrypt.c:1621
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "A cifra usada para criptografar o disco (veja /proc/crypto)"
+
+#: src/cryptsetup.c:2509 src/cryptsetup_reencrypt.c:1623
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "A hash usada para criar a chave de criptografia a partir da senha"
+
+#: src/cryptsetup.c:2510
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Verifica a senha perguntando-a duas vezes"
+
+#: src/cryptsetup.c:2511 src/cryptsetup_reencrypt.c:1625
+msgid "Read the key from a file"
+msgstr "Lê a chave de um arquivo"
+
+#: src/cryptsetup.c:2512
+msgid "Read the volume (master) key from file."
+msgstr "Lê a chave do volume (mestre) a partir do arquivo."
+
+#: src/cryptsetup.c:2513
+msgid "Dump volume (master) key instead of keyslots info"
+msgstr "Despeja a chave de volume (mestre) ao invés da informação de slots de chave"
+
+#: src/cryptsetup.c:2514 src/cryptsetup_reencrypt.c:1622
+msgid "The size of the encryption key"
+msgstr "O tamanho da chave de criptografia"
+
+#: src/cryptsetup.c:2514 src/cryptsetup.c:2571 src/integritysetup.c:539
+#: src/integritysetup.c:543 src/integritysetup.c:547
+#: src/cryptsetup_reencrypt.c:1622
+msgid "BITS"
+msgstr "BITS"
+
+#: src/cryptsetup.c:2515 src/cryptsetup_reencrypt.c:1638
+msgid "Limits the read from keyfile"
+msgstr "Limita a leitura do arquivo de chave"
+
+#: src/cryptsetup.c:2515 src/cryptsetup.c:2516 src/cryptsetup.c:2517
+#: src/cryptsetup.c:2518 src/cryptsetup.c:2568 src/cryptsetup.c:2569
+#: src/veritysetup.c:431 src/veritysetup.c:432 src/veritysetup.c:433
+#: src/veritysetup.c:436 src/veritysetup.c:437 src/integritysetup.c:530
+#: src/integritysetup.c:534 src/integritysetup.c:535
+#: src/cryptsetup_reencrypt.c:1637 src/cryptsetup_reencrypt.c:1638
+#: src/cryptsetup_reencrypt.c:1639 src/cryptsetup_reencrypt.c:1640
+msgid "bytes"
+msgstr "bytes"
+
+#: src/cryptsetup.c:2516 src/cryptsetup_reencrypt.c:1637
+msgid "Number of bytes to skip in keyfile"
+msgstr "Número de bytes a ignorar no arquivo de chave"
+
+#: src/cryptsetup.c:2517
+msgid "Limits the read from newly added keyfile"
+msgstr "Limita a leitura do arquivo de chave recém-adicionado"
+
+#: src/cryptsetup.c:2518
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "Número de bytes a ignorar em arquivo de chave recém-adicionado"
+
+#: src/cryptsetup.c:2519
+msgid "Slot number for new key (default is first free)"
+msgstr "Número de slot para a nova chave (padrão é a primeira livre)"
+
+#: src/cryptsetup.c:2520
+msgid "The size of the device"
+msgstr "O tamanho do dispositivo"
+
+#: src/cryptsetup.c:2520 src/cryptsetup.c:2521 src/cryptsetup.c:2522
+#: src/cryptsetup.c:2528 src/integritysetup.c:531 src/integritysetup.c:536
+msgid "SECTORS"
+msgstr "SETORES"
+
+#: src/cryptsetup.c:2521
+msgid "The start offset in the backend device"
+msgstr "A posição inicial do dispositivo de backend"
+
+#: src/cryptsetup.c:2522
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Quantos setores dos dados criptografados ignorar no começo"
+
+#: src/cryptsetup.c:2523
+msgid "Create a readonly mapping"
+msgstr "Cria um mapeamento somente leitura"
+
+#: src/cryptsetup.c:2524 src/integritysetup.c:524
+#: src/cryptsetup_reencrypt.c:1628
+msgid "Do not ask for confirmation"
+msgstr "Não solicitar confirmação"
+
+#: src/cryptsetup.c:2525
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Tempo limite para a solicitação interativa de senha (em segundos)"
+
+#: src/cryptsetup.c:2525 src/cryptsetup.c:2526 src/integritysetup.c:525
+#: src/cryptsetup_reencrypt.c:1629
+msgid "secs"
+msgstr "s"
+
+#: src/cryptsetup.c:2526 src/integritysetup.c:525
+#: src/cryptsetup_reencrypt.c:1629
+msgid "Progress line update (in seconds)"
+msgstr "Atualização de linha de progresso (em segundos)"
+
+#: src/cryptsetup.c:2527 src/cryptsetup_reencrypt.c:1630
+msgid "How often the input of the passphrase can be retried"
+msgstr "Com qual frequência a entrada da senha pode ser tentada novamente"
+
+#: src/cryptsetup.c:2528
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Alinha a carga em <n> limites de setores - para luksFormat"
+
+#: src/cryptsetup.c:2529
+msgid "File with LUKS header and keyslots backup"
+msgstr "Arquivo cópia de segurança de slots de chave e cabeçalho LUKS"
+
+#: src/cryptsetup.c:2530 src/cryptsetup_reencrypt.c:1631
+msgid "Use /dev/random for generating volume key"
+msgstr "Usa /dev/random para gerar chave de volume"
+
+#: src/cryptsetup.c:2531 src/cryptsetup_reencrypt.c:1632
+msgid "Use /dev/urandom for generating volume key"
+msgstr "Usa /dev/urandom para gerar chave de volume"
+
+#: src/cryptsetup.c:2532
+msgid "Share device with another non-overlapping crypt segment"
+msgstr "Compartilha o dispositivo com um outro segmento de criptografia sem sobreposição"
+
+#: src/cryptsetup.c:2533 src/veritysetup.c:440
+msgid "UUID for device to use"
+msgstr "UUID para dispositivo a ser usado"
+
+#: src/cryptsetup.c:2534
+msgid "Allow discards (aka TRIM) requests for device"
+msgstr "Permite requisições de descartes (i.e. TRIM) para dispositivo"
+
+#: src/cryptsetup.c:2535 src/cryptsetup_reencrypt.c:1649
+msgid "Device or file with separated LUKS header"
+msgstr "Dispositivo ou arquivo com cabeçalho LUKS separado"
+
+#: src/cryptsetup.c:2536
+msgid "Do not activate device, just check passphrase"
+msgstr "Não ativa o dispositivo, apenas verifica a senha"
+
+#: src/cryptsetup.c:2537
+msgid "Use hidden header (hidden TCRYPT device)"
+msgstr "Usa cabeçalho oculto (dispositivo TCRYPT oculto)"
+
+#: src/cryptsetup.c:2538
+msgid "Device is system TCRYPT drive (with bootloader)"
+msgstr "O dispositivo é uma unidade TCRYPT de sistema (com carregador de inicialização)"
+
+#: src/cryptsetup.c:2539
+msgid "Use backup (secondary) TCRYPT header"
+msgstr "Usa o cabeçalho TRCYPT secundário (cópia de segurança)"
+
+#: src/cryptsetup.c:2540
+msgid "Scan also for VeraCrypt compatible device"
+msgstr "Verifica também por dispositivo compatível com VeraCrypt"
+
+#: src/cryptsetup.c:2541
+msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Multiplicador de Iteração Pessoal (PIM) por dispositivo compatível com VeraCrypt"
+
+#: src/cryptsetup.c:2542
+msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "Consulta Multiplicador de Iteração Pessoal (PIM) por dispositivo compatível com VeraCrypt"
+
+#: src/cryptsetup.c:2543
+msgid "Type of device metadata: luks, plain, loopaes, tcrypt"
+msgstr "Tipo de metadados de dispositivo: luks, plain, loopaes, tcrypt"
+
+#: src/cryptsetup.c:2544
+msgid "Disable password quality check (if enabled)"
+msgstr "Desabilita a verificação de qualidade da senha (se habilitada)"
+
+#: src/cryptsetup.c:2545
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+msgstr "Usa a opção de compatibilidade de desempenho same_cpu_crypt do dm-crypt"
+
+#: src/cryptsetup.c:2546
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+msgstr "Usa a opção de compatibilidade de desempenho submit_from_crypt_cpus do dm-crypt"
+
+#: src/cryptsetup.c:2547
+msgid "Device removal is deferred until the last user closes it"
+msgstr "A remoção de dispositivo está adiada até o último usuário fechá-lo"
+
+#: src/cryptsetup.c:2548
+msgid "PBKDF iteration time for LUKS (in ms)"
+msgstr "Tempo de iteração PBKDF para LUKS (em ms)"
+
+#: src/cryptsetup.c:2548 src/cryptsetup_reencrypt.c:1627
+msgid "msecs"
+msgstr "ms"
+
+# argon2i, argon2id, pbkdf2 são opções, não traduzir.
+#: src/cryptsetup.c:2549 src/cryptsetup_reencrypt.c:1645
+msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+msgstr "Algoritmo PBKDF (para LUKS2): argon2i, argon2id, pbkdf2"
+
+#: src/cryptsetup.c:2550 src/cryptsetup_reencrypt.c:1646
+msgid "PBKDF memory cost limit"
+msgstr "limite de custo de memória de PBKDF"
+
+#: src/cryptsetup.c:2550 src/cryptsetup_reencrypt.c:1646
+msgid "kilobytes"
+msgstr "kilobytes"
+
+#: src/cryptsetup.c:2551 src/cryptsetup_reencrypt.c:1647
+msgid "PBKDF parallel cost"
+msgstr "Custo paralelo de PBKDF"
+
+#: src/cryptsetup.c:2551 src/cryptsetup_reencrypt.c:1647
+msgid "threads"
+msgstr "threads"
+
+#: src/cryptsetup.c:2552 src/cryptsetup_reencrypt.c:1648
+msgid "PBKDF iterations cost (forced, disables benchmark)"
+msgstr "Custo de iterações de PBKDF (forçado, desabilita teste)"
+
+# ignore, normal e prefer são opções, não traduzir.
+#: src/cryptsetup.c:2553
+msgid "Keyslot priority: ignore, normal, prefer"
+msgstr "Prioridade de slot de chave: ignore, normal, prefer"
+
+#: src/cryptsetup.c:2554
+msgid "Disable locking of on-disk metadata"
+msgstr "Desabilita travamento de metadados em disco"
+
+#: src/cryptsetup.c:2555
+msgid "Disable loading volume keys via kernel keyring"
+msgstr "Desabilita carregamento de chaves de volume via chaveiro do kernel"
+
+#: src/cryptsetup.c:2556
+msgid "Data integrity algorithm (LUKS2 only)"
+msgstr "Algoritmo de integridade de dados (LUKS2 apenas)"
+
+#: src/cryptsetup.c:2557 src/integritysetup.c:550
+msgid "Disable journal for integrity device"
+msgstr "Desabilita jornal para dispositivo de integridade"
+
+#: src/cryptsetup.c:2558 src/integritysetup.c:526
+msgid "Do not wipe device after format"
+msgstr "Não apaga o dispositivo após formatar"
+
+#: src/cryptsetup.c:2559
+msgid "Do not ask for passphrase if activation by token fails"
+msgstr "Não pede por senha se ativação por token falhar"
+
+#: src/cryptsetup.c:2560
+msgid "Token number (default: any)"
+msgstr "Número de token (padrão: qualquer)"
+
+#: src/cryptsetup.c:2561
+msgid "Key description"
+msgstr "Descrição da chave"
+
+#: src/cryptsetup.c:2562
+msgid "Encryption sector size (default: 512 bytes)"
+msgstr "Tamanho do setor de criptografia (padrão: 512 bytes)"
+
+#: src/cryptsetup.c:2563
+msgid "Set activation flags persistent for device"
+msgstr "Define sinalizadores de ativação persistentes para o dispositivo"
+
+#: src/cryptsetup.c:2564
+msgid "Set label for the LUKS2 device"
+msgstr "Define o rótulo para o dispositivo LUKS2"
+
+#: src/cryptsetup.c:2565
+msgid "Set subsystem label for the LUKS2 device"
+msgstr "Define o rótulo de subsistema para o dispositivo LUKS2"
+
+#: src/cryptsetup.c:2566
+msgid "Create unbound (no assigned data segment) LUKS2 keyslot"
+msgstr "Cria slot de chave LUKS2 não associado (nenhum segmento de dados atribuído)"
+
+#: src/cryptsetup.c:2567
+msgid "Read or write the json from or to a file"
+msgstr "Lê ou escreve o json de ou para um arquivo"
+
+#: src/cryptsetup.c:2568
+msgid "LUKS2 header metadata area size"
+msgstr "Tamanho de área de metadados de cabeçalho LUKS2"
+
+#: src/cryptsetup.c:2569
+msgid "LUKS2 header keyslots area size"
+msgstr "Tamanho de área de slots de chave de cabeçalho LUKS2"
+
+#: src/cryptsetup.c:2570
+msgid "Refresh (reactivate) device with new parameters"
+msgstr "Renova (reativa) dispositivo com novos parâmetros"
+
+#: src/cryptsetup.c:2571
+msgid "LUKS2 keyslot: The size of the encryption key"
+msgstr "Slot de chave LUKS2: O tamanho da chave de criptografia"
+
+#: src/cryptsetup.c:2572
+msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+msgstr "Slot de chave LUKS2: A cifra usada para criptografia de slot de chave"
+
+#: src/cryptsetup.c:2588 src/veritysetup.c:461 src/integritysetup.c:568
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPÇÃO...] <ação> <ação-específica>"
+
+#: src/cryptsetup.c:2645 src/veritysetup.c:501 src/integritysetup.c:585
+msgid "Argument <action> missing."
+msgstr "Faltando o argumento de <ação>."
+
+#: src/cryptsetup.c:2708 src/veritysetup.c:532 src/integritysetup.c:616
+msgid "Unknown action."
+msgstr "Ação desconhecida."
+
+#: src/cryptsetup.c:2718
+msgid "Parameter --refresh is only allowed with open or refresh commands.\n"
+msgstr "O parâmetro --refresh é apenas permitida com comandos de abrir ou renovar.\n"
+
+#: src/cryptsetup.c:2723
+msgid "Options --refresh and --test-passphrase are mutually exclusive.\n"
+msgstr "As opções --refresh e --test-passphrase são mutuamente exclusivas.\n"
+
+#: src/cryptsetup.c:2728
+msgid "Option --deferred is allowed only for close command.\n"
+msgstr "A opção --deferred é apenas permitida para o comando de fechamento.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "A opção --shared é permitida apenas para abertura de dispositivo claro.\n"
+
+#: src/cryptsetup.c:2738
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "A opção --allow-discards é permitida apenas para a operação de abertura.\n"
+
+#: src/cryptsetup.c:2743
+msgid "Option --persistent is allowed only for open operation.\n"
+msgstr "A opção --persistent é permitida apenas para a operação de abertura.\n"
+
+#: src/cryptsetup.c:2748
+msgid "Option --persistent is not allowed with --test-passphrase.\n"
+msgstr "A opção --persistent não é permitida com --test-passphrase.\n"
+
+#: src/cryptsetup.c:2757
+msgid ""
+"Option --key-size is allowed only for luksFormat, luksAddKey (with --unbound),\n"
+"open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"A opção --key-size só é permitida para luksFormat, luksAddKey (com --unbound),\n"
+"ações de abertura e teste. Para limitar a leitura do arquivo de chave,\n"
+"use --keyfile-size=(bytes)."
+
+#: src/cryptsetup.c:2763
+msgid "Option --integrity is allowed only for luksFormat (LUKS2).\n"
+msgstr "A opção --integrity é permitida apenas para luksFormat (LUKS2).\n"
+
+#: src/cryptsetup.c:2768
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension.\n"
+msgstr "A opção --integrity-no-wipe só pode ser usada para ação de formato com extensão de integridade.\n"
+
+#: src/cryptsetup.c:2774
+msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations.\n"
+msgstr "As opções --label e --subsystem são permitidas apenas para luksFormat e operações de configuração de LUKS2.\n"
+
+#: src/cryptsetup.c:2780
+msgid "Option --test-passphrase is allowed only for open of LUKS and TCRYPT devices.\n"
+msgstr "A opção --test-passphrase é permitida apenas para abertura de dispositivos LUKS e TCRYPT.\n"
+
+#: src/cryptsetup.c:2785 src/cryptsetup_reencrypt.c:1718
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Tamanho de chave deve ser um múltiplo de 8 bits"
+
+#: src/cryptsetup.c:2791 src/cryptsetup_reencrypt.c:1403
+#: src/cryptsetup_reencrypt.c:1723
+msgid "Key slot is invalid."
+msgstr "O slot de chave é inválido."
+
+#: src/cryptsetup.c:2798
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "A opção --key-file tem precedência sobre um argumento de arquivo de chave especificado."
+
+#: src/cryptsetup.c:2805 src/veritysetup.c:544 src/integritysetup.c:640
+#: src/cryptsetup_reencrypt.c:1697
+msgid "Negative number for option not permitted."
+msgstr "Número negativo para opção não permitido."
+
+#: src/cryptsetup.c:2809
+msgid "Only one --key-file argument is allowed."
+msgstr "Apenas um argumento de --key-file é permitido."
+
+#: src/cryptsetup.c:2813 src/cryptsetup_reencrypt.c:1689
+#: src/cryptsetup_reencrypt.c:1727
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Apenas uma das opções --use-[u]random são permitidas."
+
+#: src/cryptsetup.c:2817
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "A opção --use-[u]random é permitida apenas para luksFormat."
+
+#: src/cryptsetup.c:2821
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "A opção --uuid é permitida apenas para luksFormat e luksUUID."
+
+#: src/cryptsetup.c:2825
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "A opção --align-payload é permitida apenas para luksFormat."
+
+#: src/cryptsetup.c:2829
+msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+msgstr "As opçãos --luks2-metadata-size e --opt-luks2-keyslots-size são permitidas apenas para luksFormat com LUKS2."
+
+#: src/cryptsetup.c:2834
+msgid "Invalid LUKS2 metadata size specification."
+msgstr "Especificação inválida de tamanho de metadados LUKS2."
+
+#: src/cryptsetup.c:2838
+msgid "Invalid LUKS2 keyslots size specification."
+msgstr "Especificação inválida de tamanho de slots de chave LUKS2."
+
+#: src/cryptsetup.c:2842
+msgid "Option --align-payload and --offset cannot be combined."
+msgstr "As opções --align-payload e --offset não podem ser combinadas."
+
+#: src/cryptsetup.c:2848
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "Há suporte a --skip apenas para abertura de dispositivos claro e loopaes.\n"
+
+#: src/cryptsetup.c:2855
+msgid "Option --offset is supported only for open of plain and loopaes devices and for luksFormat.\n"
+msgstr "Há suporte a --offset apenas para abertura de dispositivos claro e loopaes. e para luksFormat.\n"
+
+#: src/cryptsetup.c:2861
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "Há suporte à opção --tcrypt-hidden, --tcrypt-system ou --tcrypt-backup apenas para dispositivo TCRYPT.\n"
+
+#: src/cryptsetup.c:2866
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "A opção --tcrypt-hidden não pode ser combinada com --allow-discards.\n"
+
+#: src/cryptsetup.c:2871
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "Há suporte à opção --veracrypt apenas para o tipo de dispositivo TCRYPT.\n"
+
+#: src/cryptsetup.c:2877
+msgid "Invalid argument for parameter --veracrypt-pim supplied.\n"
+msgstr "Argumento inválido para o parâmetro --veracrypt-pim fornecido.\n"
+
+#: src/cryptsetup.c:2881
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "Há suporte à opção --veracrypt-pim apenas para dispositivos compatíveis com VeraCrypt.\n"
+
+#: src/cryptsetup.c:2889
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "Há suporte à opção --veracrypt-query-pim apenas para dispositivos compatíveis com VeraCrypt.\n"
+
+#: src/cryptsetup.c:2893
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive.\n"
+msgstr "As opções --veracrypt-pim e --veracrypt-query-pim são mutuamente exclusivas.\n"
+
+# ignore, normal, prefer são opções, não traduzir.
+#: src/cryptsetup.c:2900
+msgid "Option --priority can be only ignore/normal/prefer.\n"
+msgstr "A opção --priority só pode ser ignore/normal/prefer.\n"
+
+#: src/cryptsetup.c:2905
+msgid "Keyslot specification is required.\n"
+msgstr "A especificação de slot de chave é exigido.\n"
+
+# argon2i, argon2id, pbkdf2 são opções, não traduzir.
+#: src/cryptsetup.c:2910 src/cryptsetup_reencrypt.c:1703
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id.\n"
+msgstr "A função de derivação de chave baseada em senha (PBKDF) só pode ser pbkdf2 ou argon2i/argon2id.\n"
+
+#: src/cryptsetup.c:2915 src/cryptsetup_reencrypt.c:1708
+msgid "PBKDF forced iterations cannot be combined with iteration time option.\n"
+msgstr "Iterações forçadas de PBKDF não podem ser compiladas com opção de tempo de iteração.\n"
+
+#: src/cryptsetup.c:2921
+msgid "Sector size option is not supported for this command.\n"
+msgstr "Não há suporte a opção de tamanho de setor para este comando.\n"
+
+#: src/cryptsetup.c:2927
+msgid "Unsupported encryption sector size.\n"
+msgstr "Não há suporte ao tamanho de setor de criptografia.\n"
+
+#: src/cryptsetup.c:2932
+msgid "Key size is required with --unbound option.\n"
+msgstr "Tamanho de chave é necessário com a opção --unbound.\n"
+
+#: src/cryptsetup.c:2937
+msgid "Option --unbound may be used only with luksAddKey action.\n"
+msgstr "A opção --unbound só pode ser usada com a ação luksAddKey.\n"
+
+#: src/cryptsetup.c:2942
+msgid "Option --refresh may be used only with open action.\n"
+msgstr "A opção --refresh só pode ser usada com a ação de abrir.\n"
+
+#: src/cryptsetup.c:2953
+msgid "Cannot disable metadata locking.\n"
+msgstr "Não foi possível desabilitar trava de metadados.\n"
+
+#: src/veritysetup.c:67
+msgid "Invalid salt string specified."
+msgstr "Uma string salgada inválida foi especificada."
+
+#: src/veritysetup.c:98
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Não foi possível criar imagem hash %s para escrita."
+
+#: src/veritysetup.c:108
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Não foi possível criar imagem FEC %s para escrita."
+
+#: src/veritysetup.c:178
+msgid "Invalid root hash string specified."
+msgstr "Uma string hash raiz inválida foi especificada."
+
+#: src/veritysetup.c:360
+msgid "<data_device> <hash_device>"
+msgstr "<dispositivo-dados> <dispositivo-hash>"
+
+#: src/veritysetup.c:360 src/integritysetup.c:462
+msgid "format device"
+msgstr "formata o dispositivo"
+
+#: src/veritysetup.c:361
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<dispositivo-dados> <dispositivo-hash> <hash-raiz>"
+
+#: src/veritysetup.c:361
+msgid "verify device"
+msgstr "verifica o dispositivo"
+
+#: src/veritysetup.c:362
+msgid "<data_device> <name> <hash_device> <root_hash>"
+msgstr "<dispositivo-dados> <nome> <dispositivo-hash> <hash-raiz>"
+
+#: src/veritysetup.c:362 src/integritysetup.c:463
+msgid "open device as <name>"
+msgstr "abre dispositivo como <nome>"
+
+#: src/veritysetup.c:363 src/integritysetup.c:464
+msgid "close device (deactivate and remove mapping)"
+msgstr "fecha dispositivo (desativa e remove mapeamento)"
+
+#: src/veritysetup.c:364 src/integritysetup.c:465
+msgid "show active device status"
+msgstr "mostra o estado do dispositivo ativado"
+
+#: src/veritysetup.c:365
+msgid "<hash_device>"
+msgstr "<dispositivo-hash>"
+
+#: src/veritysetup.c:365 src/integritysetup.c:466
+msgid "show on-disk information"
+msgstr "mostra informação em disco"
+
+#: src/veritysetup.c:384
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nome> é o dispositivo a ser criado sob %s\n"
+"<dispositivo-dados> é o dispositivo de dados\n"
+"<dispositivo-hash> é o dispositivo contendo dados de verificação\n"
+"<hash-raiz> hash do nó raiz no <dispositivo-hash>\n"
+
+#: src/veritysetup.c:391
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Parâmetros dm-verity pré-compilados por padrão:\n"
+"\tHash: %s, Bloco de dados (bytes): %u, Bloco de hash (bytes): %u, Tamanho salgado: %u, Formato hash: %u\n"
+
+#: src/veritysetup.c:429
+msgid "Do not use verity superblock"
+msgstr "Não usa superbloco verity"
+
+#: src/veritysetup.c:430
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "Tipo de formato (1 - normal, 0 - Chrome OS original)"
+
+#: src/veritysetup.c:430
+msgid "number"
+msgstr "número"
+
+#: src/veritysetup.c:431
+msgid "Block size on the data device"
+msgstr "Tamanho de bloco no dispositivo de dados"
+
+#: src/veritysetup.c:432
+msgid "Block size on the hash device"
+msgstr "Tamanho de bloco no dispositivo de hash"
+
+#: src/veritysetup.c:433
+msgid "FEC parity bytes"
+msgstr "Bytes de paridade FEC"
+
+#: src/veritysetup.c:434
+msgid "The number of blocks in the data file"
+msgstr "O número de blocos no arquivo de dados"
+
+#: src/veritysetup.c:434
+msgid "blocks"
+msgstr "blocos"
+
+#: src/veritysetup.c:435
+msgid "Path to device with error correction data"
+msgstr "Caminho para dispositivo com dados de correção de erro"
+
+#: src/veritysetup.c:435 src/integritysetup.c:528
+msgid "path"
+msgstr "caminho"
+
+#: src/veritysetup.c:436
+msgid "Starting offset on the hash device"
+msgstr "Posição inicial no dispositivo de hash"
+
+#: src/veritysetup.c:437
+msgid "Starting offset on the FEC device"
+msgstr "Posição inicial no dispositivo FEC"
+
+#: src/veritysetup.c:438
+msgid "Hash algorithm"
+msgstr "Algoritmo hash"
+
+#: src/veritysetup.c:438
+msgid "string"
+msgstr "string"
+
+#: src/veritysetup.c:439
+msgid "Salt"
+msgstr "Sal"
+
+#: src/veritysetup.c:439
+msgid "hex string"
+msgstr "string hexa"
+
+#: src/veritysetup.c:441
+msgid "Restart kernel if corruption is detected"
+msgstr "Reinicia o kernel, se um corrompimento for detectado"
+
+#: src/veritysetup.c:442
+msgid "Ignore corruption, log it only"
+msgstr "Ignora corrompimento, apenas registra no log"
+
+#: src/veritysetup.c:443
+msgid "Do not verify zeroed blocks"
+msgstr "Não verifica por blocos zerados"
+
+#: src/veritysetup.c:444
+msgid "Verify data block only the first time it is read"
+msgstr "Verifica bloco de dados apenas na primeira vez que é lido"
+
+#: src/veritysetup.c:550
+msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation.\n"
+msgstr "O uso da opção --ignore-corruption, --restart-on-corruption ou --ignore-zero-blocks é permitido apenas para operação de abertura.\n"
+
+#: src/veritysetup.c:555
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together.\n"
+msgstr "As opções --ignore-corruption e --restart-on-corruption não podem ser usadas em conjunto.\n"
+
+#: src/integritysetup.c:82 src/utils_password.c:298
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Não foi possível ler o arquivo de chave %s."
+
+#: src/integritysetup.c:86 src/utils_password.c:302
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Não foi possível ler %d bytes do arquivo de chave %s."
+
+#: src/integritysetup.c:248
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formatado com tamanho de tag %u, integridade interna %s.\n"
+
+#: src/integritysetup.c:462 src/integritysetup.c:466
+msgid "<integrity_device>"
+msgstr "<dispositivo_integridade>"
+
+#: src/integritysetup.c:463
+msgid "<integrity_device> <name>"
+msgstr "<dispositivo_integridade> <nome>"
+
+#: src/integritysetup.c:485
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<nome> é o dispositivo a ser criado sob %s\n"
+"<dispositivo_integridade> é o dispositivo com dados com tags de integridade\n"
+
+#: src/integritysetup.c:490
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tTag size: %u bytes, Checksum algorithm: %s\n"
+msgstr ""
+"\n"
+"Parâmetros dm-integrity compilados por padrão:\n"
+"\tTamanho Tag: %u bytes, Algoritmo de soma de verificação: %s\n"
+
+#: src/integritysetup.c:528
+msgid "Path to data device (if separated)"
+msgstr "Caminho para dispositivo de dados (se separado)"
+
+#: src/integritysetup.c:530
+msgid "Journal size"
+msgstr "Tamanho do journal"
+
+#: src/integritysetup.c:531
+msgid "Interleave sectors"
+msgstr "Intercalar setores"
+
+#: src/integritysetup.c:532
+msgid "Journal watermark"
+msgstr "Marca d'água do jornal"
+
+#: src/integritysetup.c:532
+msgid "percent"
+msgstr "porcentagem"
+
+#: src/integritysetup.c:533
+msgid "Journal commit time"
+msgstr "Tempo de commit do journal"
+
+#: src/integritysetup.c:533
+msgid "ms"
+msgstr "ms"
+
+#: src/integritysetup.c:534
+msgid "Tag size (per-sector)"
+msgstr "Tamanho de tag (por setor)"
+
+#: src/integritysetup.c:535
+msgid "Sector size"
+msgstr "Tamanho do setor"
+
+#: src/integritysetup.c:536
+msgid "Buffers size"
+msgstr "Tamanho de buffers"
+
+#: src/integritysetup.c:538
+msgid "Data integrity algorithm"
+msgstr "Algoritmo de integridade de dados"
+
+#: src/integritysetup.c:539
+msgid "The size of the data integrity key"
+msgstr "O tamanho da chave de integridade de dados"
+
+#: src/integritysetup.c:540
+msgid "Read the integrity key from a file"
+msgstr "Lê a chave de integridade de um arquivo"
+
+#: src/integritysetup.c:542
+msgid "Journal integrity algorithm"
+msgstr "Algoritmo de integridade de journal"
+
+#: src/integritysetup.c:543
+msgid "The size of the journal integrity key"
+msgstr "O tamanho da chave de integridade de journal"
+
+#: src/integritysetup.c:544
+msgid "Read the journal integrity key from a file"
+msgstr "Lê a chave de integridade de journal de um arquivo"
+
+#: src/integritysetup.c:546
+msgid "Journal encryption algorithm"
+msgstr "Algoritmo de criptografia de journal"
+
+#: src/integritysetup.c:547
+msgid "The size of the journal encryption key"
+msgstr "O tamanho da chave de criptografia de journal"
+
+#: src/integritysetup.c:548
+msgid "Read the journal encryption key from a file"
+msgstr "Lê a chave de criptografia de journal de um arquivo"
+
+#: src/integritysetup.c:551
+msgid "Recovery mode (no journal, no tag checking)"
+msgstr "Modo de recuperação (sem journal, sem verificação de tag)"
+
+#: src/integritysetup.c:552
+msgid "Recalculate initial tags automatically."
+msgstr "Recalcula tags iniciais automaticamente."
+
+#: src/integritysetup.c:631
+msgid "Option --integrity-recalculate can be used only for open action."
+msgstr "A opção --integrity-recalculate só pode ser usada para ação de abrir."
+
+#: src/integritysetup.c:646
+msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action.\n"
+msgstr "As opções --journal-size, --interleave-sectors, --sector-size, --tag-size e --no-wipe só podem ser usadas para ação de formatação.\n"
+
+#: src/integritysetup.c:652
+msgid "Invalid journal size specification."
+msgstr "Especificação inválida de tamanho de journal."
+
+#: src/integritysetup.c:657
+msgid "Both key file and key size options must be specified."
+msgstr "As opções de arquivo de chave e tamanho de chave devem ser especificadas."
+
+#: src/integritysetup.c:660
+msgid "Integrity algorithm must be specified if integrity key is used."
+msgstr "Um algoritmo de integridade deve ser especificado se uma chave de integridade é usada."
+
+#: src/integritysetup.c:665
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "As opções de arquivo de chave de integridade de journal e tamanho de chave devem ser especificadas."
+
+#: src/integritysetup.c:668
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Um algoritmo de integridade de journal deve ser especificado se uma chave de integridade de journal é usada."
+
+#: src/integritysetup.c:673
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "As opções de arquivo de chave de criptografia de journal e tamanho de chave devem ser especificadas."
+
+#: src/integritysetup.c:676
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Um algoritmo de criptografia de journal deve ser especificado se uma chave de criptografia de journal é usada."
+
+#: src/cryptsetup_reencrypt.c:175
+msgid "Reencryption already in-progress."
+msgstr "Recriptografia já está em progresso."
+
+#: src/cryptsetup_reencrypt.c:181
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Não há suporte a recriptografia de dispositivo com perfil de integridade."
+
+#: src/cryptsetup_reencrypt.c:204
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Não foi possível abrir exclusivamente %s, dispositivo em uso."
+
+#: src/cryptsetup_reencrypt.c:218 src/cryptsetup_reencrypt.c:1148
+msgid "Allocation of aligned memory failed."
+msgstr "A alocação de memória alinhada falhou."
+
+#: src/cryptsetup_reencrypt.c:225
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Não foi possível ler o dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:236
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Marcando o dispositivo LUKS1 %s como não usável."
+
+#: src/cryptsetup_reencrypt.c:240
+#, c-format
+msgid "Setting LUKS2 offline reencrypt flag on device %s."
+msgstr "Definindo o sinalizador de recriptografia offline do LUKS2 no dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:257
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Não foi possível escrever o dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:345
+msgid "Cannot write reencryption log file."
+msgstr "Não foi possível escrever o arquivo log de recriptografia."
+
+#: src/cryptsetup_reencrypt.c:401
+msgid "Cannot read reencryption log file."
+msgstr "Não foi possível abrir o arquivo log de recriptografia."
+
+#: src/cryptsetup_reencrypt.c:439
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Arquivo log %s existe, resumindo recriptografia.\n"
+
+#: src/cryptsetup_reencrypt.c:488
+msgid "Activating temporary device using old LUKS header."
+msgstr "Ativando dispositivo temporário usando antigo cabeçalho LUKS."
+
+#: src/cryptsetup_reencrypt.c:498
+msgid "Activating temporary device using new LUKS header."
+msgstr "Ativando dispositivo temporário usando novo cabeçalho LUKS."
+
+#: src/cryptsetup_reencrypt.c:508
+msgid "Activation of temporary devices failed."
+msgstr "A ativação de dispositivos temporários falhou."
+
+#: src/cryptsetup_reencrypt.c:586
+msgid "Failed to set PBKDF parameters."
+msgstr "Falha ao definir os parâmetros de sessão PBKDF."
+
+#: src/cryptsetup_reencrypt.c:592
+msgid "Failed to set data offset."
+msgstr "Falha ao definir a posição de dados."
+
+#: src/cryptsetup_reencrypt.c:600
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Novo cabeçalho LUKS para dispositivo %s criado."
+
+# "cryptsetup-reencrypt" é o nome do programa, não traduzir.
+#: src/cryptsetup_reencrypt.c:660
+#, c-format
+msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+msgstr "Essa versão de cryptsetup-reencrypt não sabe lidar com o novo tipo de token interno %s."
+
+#: src/cryptsetup_reencrypt.c:682
+msgid "Failed to read activation flags from backup header."
+msgstr "Falha ao ler sinalizadores de ativação do cabeçalho de cópia de segurança."
+
+#: src/cryptsetup_reencrypt.c:686
+msgid "Failed to write activation flags to new header."
+msgstr "Falha ao escrever sinalizadores de ativação para novo cabeçalho."
+
+#: src/cryptsetup_reencrypt.c:690 src/cryptsetup_reencrypt.c:694
+msgid "Failed to read requirements from backup header."
+msgstr "Falha ao ler requisitos do cabeçalho de cópia de segurança."
+
+#: src/cryptsetup_reencrypt.c:731
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Cópia de segurança de cabeçalho %s para dispositivo %s criado."
+
+#: src/cryptsetup_reencrypt.c:789
+msgid "Creation of LUKS backup headers failed."
+msgstr "A criação de cópia de segurança de cabeçalhos LUKS falhou."
+
+#: src/cryptsetup_reencrypt.c:918
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Não foi possível restaurar o cabeçalho %s no dispositivo %s."
+
+#: src/cryptsetup_reencrypt.c:920
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Cabeçalho %s no dispositivo %s restaurado."
+
+#: src/cryptsetup_reencrypt.c:958 src/cryptsetup_reencrypt.c:1038
+msgid "Cannot seek to device offset."
+msgstr "Não foi possível ir à posição do dispositivo."
+
+#: src/cryptsetup_reencrypt.c:1081
+msgid "Cannot seek to device offset.\n"
+msgstr "Não foi possível ir à posição do dispositivo.\n"
+
+#: src/cryptsetup_reencrypt.c:1120 src/cryptsetup_reencrypt.c:1126
+msgid "Cannot open temporary LUKS device."
+msgstr "Não foi possível abrir o dispositivo LUKS temporário."
+
+#: src/cryptsetup_reencrypt.c:1131 src/cryptsetup_reencrypt.c:1136
+msgid "Cannot get device size."
+msgstr "Não foi possível obter o tamanho do dispositivo."
+
+#: src/cryptsetup_reencrypt.c:1173
+msgid "Interrupted by a signal."
+msgstr "Interrompido por um sinal."
+
+#: src/cryptsetup_reencrypt.c:1175
+msgid "IO error during reencryption."
+msgstr "Erro de E/S durante a recriptografia."
+
+#: src/cryptsetup_reencrypt.c:1206
+msgid "Provided UUID is invalid."
+msgstr "O UUID fornecido é inválido."
+
+#: src/cryptsetup_reencrypt.c:1309
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "O arquivo de chave pode ser usado apenas com --key-slot ou com exatamente um slot de chave ativado."
+
+#: src/cryptsetup_reencrypt.c:1350 src/cryptsetup_reencrypt.c:1361
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Digite uma senha para o slot de chave %u: "
+
+#: src/cryptsetup_reencrypt.c:1432
+msgid "Cannot open reencryption log file."
+msgstr "Não foi possível abrir o arquivo log de recriptografia."
+
+#: src/cryptsetup_reencrypt.c:1438
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Nenhuma descriptografia em progresso, UUID fornecido pode ser usado apenas para resumir um processo de descriptografia suspendido."
+
+#: src/cryptsetup_reencrypt.c:1513
+#, c-format
+msgid "Changed pbkdf parameters in keyslot %i."
+msgstr "Alterados os parâmetros de pbkdf no slot de chave %i."
+
+#: src/cryptsetup_reencrypt.c:1620
+msgid "Reencryption block size"
+msgstr "Tamanho do bloco de recriptografia"
+
+#: src/cryptsetup_reencrypt.c:1620
+msgid "MiB"
+msgstr "MB"
+
+#: src/cryptsetup_reencrypt.c:1624
+msgid "Do not change key, no data area reencryption"
+msgstr "Não altera chave, nenhuma área de dados de recriptografia"
+
+#: src/cryptsetup_reencrypt.c:1626
+msgid "Read new volume (master) key from file"
+msgstr "Lê nova chave do volume (mestre) a partir do arquivo"
+
+#: src/cryptsetup_reencrypt.c:1627
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "Tempo de iteração PBKDF2 para LUKS (em ms)"
+
+#: src/cryptsetup_reencrypt.c:1633
+msgid "Use direct-io when accessing devices"
+msgstr "Usa direct-io ao acessar dispositivos"
+
+#: src/cryptsetup_reencrypt.c:1634
+msgid "Use fsync after each block"
+msgstr "Usa fsync após cada bloco"
+
+#: src/cryptsetup_reencrypt.c:1635
+msgid "Update log file after every block"
+msgstr "Atualiza o arquivo log após todo bloco"
+
+#: src/cryptsetup_reencrypt.c:1636
+msgid "Use only this slot (others will be disabled)"
+msgstr "Usa apenas este slot (outros serão desabilitados)"
+
+#: src/cryptsetup_reencrypt.c:1639
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "Reduz tamanho do dispositivo de dados (move opção dos dados). PERIGOSO!"
+
+#: src/cryptsetup_reencrypt.c:1640
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "Usa apenas o tamanho de dispositivo especificado (ignora o resto do dispositivo). PERIGOSO!"
+
+#: src/cryptsetup_reencrypt.c:1641
+msgid "Create new header on not encrypted device"
+msgstr "Cria um novo cabeçalho em dispositivo não criptografado"
+
+#: src/cryptsetup_reencrypt.c:1642
+msgid "Permanently decrypt device (remove encryption)"
+msgstr "Descriptografa permanentemente o dispositivo (remove criptografia)"
+
+#: src/cryptsetup_reencrypt.c:1643
+msgid "The UUID used to resume decryption"
+msgstr "A UUID usada para resumir a descriptografia"
+
+#: src/cryptsetup_reencrypt.c:1644
+msgid "Type of LUKS metadata: luks1, luks2"
+msgstr "Tipo de metadados LUKS: luks1, luks2"
+
+#: src/cryptsetup_reencrypt.c:1663
+msgid "[OPTION...] <device>"
+msgstr "[OPÇÃO...] <dispositivo>"
+
+#: src/cryptsetup_reencrypt.c:1677
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Recriptografia vai alterar: %s%s%s%s%s%s."
+
+#: src/cryptsetup_reencrypt.c:1678
+msgid "volume key"
+msgstr "chave de volume"
+
+#: src/cryptsetup_reencrypt.c:1680
+msgid "set hash to "
+msgstr "definir hash para "
+
+#: src/cryptsetup_reencrypt.c:1681
+msgid ", set cipher to "
+msgstr ", definir cifra para "
+
+#: src/cryptsetup_reencrypt.c:1685
+msgid "Argument required."
+msgstr "Argumento necessário."
+
+#: src/cryptsetup_reencrypt.c:1713
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Apenas valores entre 1 MB e 64 MB são permitidos para tamanho de bloco de recriptografia."
+
+#: src/cryptsetup_reencrypt.c:1732 src/cryptsetup_reencrypt.c:1737
+msgid "Invalid device size specification."
+msgstr "Especificação inválida de tamanho de dispositivo."
+
+#: src/cryptsetup_reencrypt.c:1740
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "Tamanho máximo de redução do dispositivo é 64 MB."
+
+#: src/cryptsetup_reencrypt.c:1743
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Tamanho da redução deve ser múltiplo de 512 bytes (setores)."
+
+#: src/cryptsetup_reencrypt.c:1747
+msgid "Option --new must be used together with --reduce-device-size or --header."
+msgstr "A opção --new deve ser usada junto de --reduce-device-size ou --header."
+
+#: src/cryptsetup_reencrypt.c:1751
+msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+msgstr "A opção --keep-key pode ser usada apenas com --hash, --iter-time ou --pbkdf-force-iterations."
+
+#: src/cryptsetup_reencrypt.c:1755
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "A opção --new não pode ser usada junto de --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1759
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "A opção --decrypt é incompatível com os parâmetros especificados."
+
+#: src/cryptsetup_reencrypt.c:1763
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "A opção --uuid é permitida apenas junto de --decrypt."
+
+#: src/cryptsetup_reencrypt.c:1767
+msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+msgstr "Tipo de luks inválido. Use um desses: \"luks\", \"luks1\" ou \"luks2\"."
+
+#: src/utils_tools.c:150
+msgid "Error reading response from terminal."
+msgstr "Erro ao ler resposta do terminal."
+
+#: src/utils_tools.c:175
+msgid "Command successful.\n"
+msgstr "Comando executado com sucesso.\n"
+
+#: src/utils_tools.c:183
+msgid "wrong or missing parameters"
+msgstr "parâmetros errados ou faltando"
+
+#: src/utils_tools.c:185
+msgid "no permission or bad passphrase"
+msgstr "sem permissão ou senha incorreta"
+
+#: src/utils_tools.c:187
+msgid "out of memory"
+msgstr "memória insuficiente"
+
+#: src/utils_tools.c:189
+msgid "wrong device or file specified"
+msgstr "dispositivo ou arquivo errado especificado"
+
+#: src/utils_tools.c:191
+msgid "device already exists or device is busy"
+msgstr "o dispositivo já existe ou está ocupado"
+
+#: src/utils_tools.c:193
+msgid "unknown error"
+msgstr "erro desconhecido"
+
+#: src/utils_tools.c:195
+#, c-format
+msgid "Command failed with code %i (%s).\n"
+msgstr "O comando falhou com código %i (%s).\n"
+
+#: src/utils_tools.c:272
+#, c-format
+msgid "Key slot %i created."
+msgstr "Slot de chave %i criado."
+
+#: src/utils_tools.c:274
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Slot de chave %i desbloqueado."
+
+#: src/utils_tools.c:276
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Slot de chave %i removido."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token %i created."
+msgstr "Token %i criado."
+
+#: src/utils_tools.c:287
+#, c-format
+msgid "Token %i removed."
+msgstr "Token %i removido."
+
+#: src/utils_tools.c:453
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "AVISO: O dispositivo %s já contém uma assinatura de partição \"%s\".\n"
+
+#: src/utils_tools.c:461
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "AVISO: O dispositivo %s já contém uma assinatura de superbloco \"%s\".\n"
+
+#: src/utils_tools.c:482 src/utils_tools.c:546
+msgid "Failed to initialize device signature probes."
+msgstr "Falha ao inicializar as sondas de assinatura de dispositivo."
+
+#: src/utils_tools.c:526
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Falha ao obter estado do dispositivo %s."
+
+#: src/utils_tools.c:539
+#, c-format
+msgid "Device %s is in use. Can not proceed with format operation."
+msgstr "O dispositivo %s está em uso. Não é possível proceder com a operação de formatação."
+
+#: src/utils_tools.c:541
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Falha ao abrir o arquivo %s no modo leitura/escrita."
+
+#: src/utils_tools.c:561
+msgid "Failed to wipe device signature."
+msgstr "Falha ao apagar assinatura do dispositivo."
+
+#: src/utils_tools.c:568
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Falha ao sondar o dispositivo %s por uma assinatura."
+
+#: src/utils_password.c:43 src/utils_password.c:75
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Não foi possível verificar qualidade da senha: %s"
+
+#: src/utils_password.c:51
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Verificação de qualidade da senha falhou:\n"
+" %s"
+
+#: src/utils_password.c:83
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Verificação de qualidade da senha falhou: Senha incorreta (%s)"
+
+#: src/utils_password.c:193 src/utils_password.c:208
+msgid "Error reading passphrase from terminal."
+msgstr "Erro ao ler senha do terminal."
+
+#: src/utils_password.c:206
+msgid "Verify passphrase: "
+msgstr "Verificar senha: "
+
+#: src/utils_password.c:213
+msgid "Passphrases do not match."
+msgstr "As senhas não conferem."
+
+#: src/utils_password.c:250
+msgid "Cannot use offset with terminal input."
+msgstr "Não foi possível usar posição com a entrada do terminal."
+
+#: src/utils_password.c:253
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Digite a senha: "
+
+#: src/utils_password.c:255
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Digite a senha para %s: "
+
+#: src/utils_password.c:285
+msgid "No key available with this passphrase."
+msgstr "Nenhuma chave disponível com esta senha."
+
+#: src/utils_password.c:320
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Não foi possível abrir o arquivo de chave %s para escrita."
+
+#: src/utils_password.c:327
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Não foi possível escrever no arquivo de chave %s."
+
+#: src/utils_luks2.c:47
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Falha ao abrir o arquivo %s no modo somente leitura."
+
+#: src/utils_luks2.c:60
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Forneça um JSON de token LUKS2 válido:\n"
+
+#: src/utils_luks2.c:67
+msgid "Failed to read JSON file."
+msgstr "Falha ao ler o arquivo JSON."
+
+#: src/utils_luks2.c:72
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Leitura interrompida."
+
+#: src/utils_luks2.c:113
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Falha ao abrir o arquivo %s no modo escrita."
+
+#: src/utils_luks2.c:122
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Escrita interrompida."
+
+#: src/utils_luks2.c:126
+msgid "Failed to write JSON file."
+msgstr "Falha ao escrever arquivo JSON."
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Dispositivo %s é muito pequeno. (LUKS2 precisa de pelo menos %<PRIu64> bytes.)"
+
+#, fuzzy
+#~| msgid "Replaced with key slot %d.\n"
+#~ msgid "Replaced with key slot %d."
+#~ msgstr "Substituído com o slot de chave %d.\n"
+
+#, fuzzy
+#~| msgid "Missing LUKS target type, option --type is required.\n"
+#~ msgid "Missing LUKS target type, option --type is required."
+#~ msgstr "Faltando o tipo de alvo LUKS, a opção --type é necessária.\n"
+
+#, fuzzy
+#~| msgid "Missing --token option specifying token for removal.\n"
+#~ msgid "Missing --token option specifying token for removal."
+#~ msgstr "Faltando a opção --token especificando token para remoção.\n"
+
+#, fuzzy
+#~| msgid "Failed to remove token %d.\n"
+#~ msgid "Failed to remove token %d."
+#~ msgstr "Falha ao remover o token %d.\n"
+
+#~ msgid "Add or remove keyring token"
+#~ msgstr "Adiciona ou remove o token de chaveiro"
+
+#, fuzzy
+#~| msgid "Activated keyslot %i.\n"
+#~ msgid "Activated keyslot %i."
+#~ msgstr "Slot de chave %i ativado.\n"
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "erro de alocação de memória em action_luksFormat"
+
+#, fuzzy
+#~| msgid "Key slot is invalid."
+#~ msgid "Key slot is invalid.\n"
+#~ msgstr "O slot de chave é inválido."
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Número excessivo de níveis de árvore para volume verity.\n"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "Chave %d não ativada. Não é possível apagar.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<nome> <dispositivo-dados> <dispositivo-hash> <hash-raiz>"
+
+#~ msgid "create active device"
+#~ msgstr "cria um dispositivo ativado"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "remove (desativa) o dispositivo"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Progresso: %5.1f%%, ETA %02llu:%02llu, %4llu MB escrito, vel. %5.1f MB/s%s"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Não foi possível localizar um dispositivo de loop livre.\n"
+
+# Ponto final acrescentado, pois as mensagens em volta possível, sugerindo ser necessário aqui também.
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Não foi possível abrir o dispositivo %s.\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Não é possível usar o UUID passado a menos que descriptografia estiver em progresso.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "Marcando o dispositivo LUKS %s como usável.\n"
diff --git a/po/ro.po b/po/ro.po
new file mode 100644
index 0000000..c12b283
--- /dev/null
+++ b/po/ro.po
@@ -0,0 +1,3874 @@
+# Mesajele în limba română pentru pachetul cryptsetup.
+# Copyright © 2023 Free Software Foundation, Inc.
+# This file is put in the public domain.
+# This file is distributed under the same license as the cryptsetup package.
+#
+# Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>, 2023.
+#
+# Cronologia traducerii fișierului „cryptsetup”:
+# Traducerea inițială, făcută de R-GC, pentru versiunea cryptsetup 2.6.0-rc1.
+# Actualizare a traducerii pentru versiunea 2.6.1-rc0, făcută de R-GC, ian-2023.
+# Actualizare a traducerii pentru versiunea Y, făcută de X, Y(luna-anul).
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-02 10:02+0100\n"
+"Last-Translator: Remus-Gabriel Chelu <remusgabriel.chelu@disroot.org>\n"
+"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || ((n%100) > 0 && (n%100) < 20)) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 3.2.2\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Nu se poate inițializa device-mapper, rulând ca utilizator non-root."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Nu se poate inițializa device-mapper. Este încărcat modulul nucleului, «dm_mod»?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Fanionul de întârziere solicitat nu este acceptat."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID pentru dispozitivul %s a fost trunchiat."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Tip de țintă dm necunoscut."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Opțiunile de performanță dm-crypt solicitate nu sunt acceptate."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Opțiunile de gestionare a corupției datelor dm-verity solicitate nu sunt acceptate."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "Opțiunea de tasklets dm-verity solicitată nu este acceptată."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Opțiunile FEC dm-verity solicitate nu sunt acceptate."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Opțiunile de integritate a datelor solicitate nu sunt acceptate."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "Opțiunea sector_size solicitată nu este acceptată."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Recalcularea automată a etichetelor de integritate solicitată nu este acceptată."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Înlăturarea/Decuparea(TRIM) nu este acceptată."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Modul de hartă de biți dm-integrity solicitat nu este acceptat."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Nu s-a putut interoga segmentul dm-%s."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Sistemul este în afara entropiei în timp ce generează cheia de volum.\n"
+"Mișcați mouse-ul sau tastați ceva text într-o altă fereastră pentru a genera și colecta câteva evenimente aleatorii.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Se generează cheia (%d%% finalizată).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Rulează în modul FIPS."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "Eroare fatală în timpul inițializării generatorului de numere aleatorii(RNG)."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Calitatea solicitată pentru generatorul de numere aleatoare(RNG) este necunoscută."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Eroare la citirea din generatorul de numere aleatorii(RNG)."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Nu s-a putut inițializa utilitarul de criptare al generatorului de numere aleatorii(RNG)."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Nu s-a putut inițializa utilitarul de criptare ."
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Algoritmul sumei de control %s nu este acceptat."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Eroare de procesare a cheii (folosind suma de control %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Nu se poate determina tipul de dispozitiv. Activare a dispozitivului incompatibilă?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "Această operație este acceptată doar pentru dispozitive LUKS."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Această operație este acceptată doar pentru dispozitive LUKS2."
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Toate sloturile pentru chei sunt ocupate."
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Slotul de cheie %d este nu este valid, selectați între 0 și %d."
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Slotul pentru chei %d este ocupat, selectați altul."
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "Dimensiunea dispozitivului nu este aliniată la dimensiunea blocului logic al dispozitivului."
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Antet detectat, dar dispozitivul %s este prea mic."
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Această operație nu este suportată pentru acest tip de dispozitiv."
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Operație ilegală cu recriptare în curs."
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Nu s-au putut reîncărca metadatele LUKS2 în memorie."
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Dispozitivul %s nu este un dispozitiv LUKS valid."
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Versiunea %d de LUKS nu este acceptată."
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "Dispozitivul %s nu este activ."
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Dispozitivul subiacent pentru dispozitivul criptat %s a dispărut."
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "Parametrii de criptare simplă sunt incorecți."
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "Dimensiunea cheii este nevalidă."
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID-ul nu este acceptat pentru acest tip de criptare."
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Dispozitivul cu metadate detașate nu este acceptat pentru acest tip de criptare."
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Dimensiunea sectorului de criptare nu este acceptată."
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "Dimensiunea dispozitivului nu este aliniată la dimensiunea sectorului solicitată."
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "Formatarea LUKS fără dispozitiv nu este posibilă."
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Alinierea datelor solicitată nu este compatibilă cu poziția datelor."
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Nu se poate șterge antetul pe dispozitivul %s."
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Dispozitivul %s este prea mic pentru activare, nu a mai rămas spațiu pentru date.\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "AVERTISMENT: Activarea dispozitivului va eșua, dm-crypt nu are suport pentru dimensiunea sectorului de criptare solicitată.\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Cheia de volum este prea mică pentru criptare cu extensii de integritate."
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Cifrul %s-%s (dimensiunea cheii %zd biți) nu este disponibil."
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "AVERTISMENT: dimensiunea metadatelor LUKS2 s-a schimbat la %<PRIu64> octeți.\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "AVERTISMENT: dimensiunea zonei sloturilor de chei LUKS2 s-a schimbat la %<PRIu64> octeți.\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Dispozitivul %s este prea mic."
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Nu se poate formata dispozitivul %s, este în uz."
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Nu se poate formata dispozitivul %s; permisiune refuzată."
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Nu se poate formata integritatea pentru dispozitivul %s."
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Nu se poate formata dispozitivul %s."
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "Nu se poate formata LOOPAES fără dispozitiv."
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "Nu se poate formata VERITY fără dispozitiv."
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Tip de sumă de control VERITY neacceptat %d."
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Dimensiunea blocului VERITY nu este acceptată."
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Decalajul sumei de control VERITY nu este acceptat."
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "Decalajul FEC VERITY nu este acceptat."
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "Zona de date se suprapune cu zona de sume de control."
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "Zona sumelor de control se suprapune cu zona FEC."
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "Zona de date se suprapune cu zona FEC."
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "AVERTISMENT: Dimensiunea solicitată a etichetei %d octeți diferă de dimensiunea %s de ieșire (%d octeți).\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "A fost solicitat un tip de dispozitiv de criptare necunoscut %s."
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Parametri neacceptați pentru dispozitivul %s."
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Parametrii nepotriviți în dispozitivul %s."
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Dispozitivele de criptare nu se potrivesc."
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Nu s-a putut reîncărca dispozitivul %s."
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Nu s-a putut suspenda dispozitivul %s."
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Nu s-a putut reîncărca dispozitivul %s."
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Eroare fatală la reîncărcarea dispozitivului %s (în partea superioară a dispozitivului %s)."
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Nu s-a putut comuta dispozitivul %s la dm-error."
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "Nu se poate redimensiona dispozitivul de buclă."
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "AVERTISMENT: Dimensiunea maximă a fost deja stabilită sau nucleul nu acceptă redimensionarea.\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Redimensionarea nu a reușit, nucleul nu acceptă redimensionarea."
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "Chiar doriți să schimbați UUID-ul dispozitivului?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Fișierul de copie de rezervă pentru antet nu conține un antet LUKS compatibil."
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Volumul %s nu este activ."
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Volumul %s este deja suspendat."
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Suspendarea nu este acceptată pentru dispozitivul %s."
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Eroare la suspendarea dispozitivului %s."
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Reluarea activității nu este acceptată pentru dispozitivul %s."
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Eroare la reluarea activității dispozitivului %s."
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Volumul %s nu este suspendat."
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Cheia de volum nu se potrivește cu volumul."
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "Nu s-a putut efectua interschimbarea cu noul slot pentru cheie."
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Slotul de cheie %d nu este valid."
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Slotul de cheie %d nu este activ."
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "Antetul dispozitivului se suprapune cu zona de date."
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Recriptare în curs. Nu se poate activa dispozitivul."
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Nu s-a putut obține blocarea pentru recriptare."
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Recuperarea recriptării LUKS2 a eșuat."
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "Tipul de dispozitiv nu este inițializat corect."
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "Dispozitivul %s există deja."
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Nu se poate folosi dispozitivul %s, numele este nevalid sau este încă în uz."
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "Este specificată o cheie de volum incorectă pentru un dispozitiv cu criptare normală."
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "Sumă de control rădăcină incorectă specificată pentru dispozitivul verity."
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "Este necesară semnătura de sumă de control rădăcină."
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Lipsește inelul de chei pentru nucleu: este necesar pentru transmiterea semnăturii către nucleu."
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "Nu s-a putut încărca cheia în inelul de chei al nucleului."
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Nu s-a putut anula eliminarea întârziată din dispozitivul %s."
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Dispozitivul %s este încă în uz."
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "Dispozitiv nevalid %s."
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "Memoria tampon a cheii de volum este prea mică."
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Nu se poate recupera cheia de volum pentru dispozitivul LUKS2."
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Nu se poate recupera cheia de volum pentru dispozitivul LUKS1."
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Nu se poate recupera tasta de volum pentru dispozitivul normal."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Nu se poate recupera suma de control rădăcină pentru dispozitivul verity."
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Nu se poate recupera cheia de volum pentru dispozitivul BITLK."
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Nu se poate recupera cheia de volum pentru dispozitivul FVAULT2."
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Această operație nu este acceptată pentru dispozitivul criptat %s."
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "Operația de descărcare nu este acceptată pentru acest tip de dispozitiv."
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Decalajul datelor nu este multiplu de %u octeți."
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Nu se poate converti dispozitivul %s care este încă în uz."
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Nu s-a putut atribui slotul %u ca nouă cheie de volum."
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Nu s-au putut inițializa parametrii impliciți pentru slotul de cheie LUKS2."
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Nu s-a putut aloca slotul de cheie %d pentru a digera."
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Nu se poate adăuga slotul pentru cheie, toate sloturile sunt dezactivate și nu este furnizată nicio cheie pentru volum."
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Inelul de chei pentru nucleu nu este acceptat de nucleu actual."
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Nu s-a putut citi expresia de acces din inelul de chei (eroarea %d)."
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Nu s-a putut obține blocarea de serializare a accesului la memoria-hardwarw globală."
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Nu s-a putut deschide fișierul cheii."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Nu se poate citi fișierul de cheie de la un terminal."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "Nu s-a putut obține starea fișierului de cheie."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Nu se poate căuta poziția fișierului de cheie solicitat."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "Memoria epuizată în timpul citirii frazei de acces."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Eroare la citirea frazei de acces."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Nimic de citit la intrare."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Dimensiunea maximă a fișierului de cheie a fost depășită."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "Nu se poate citi cantitatea de date solicitată."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Dispozitivul %s nu există sau accesul a fost refuzat."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Dispozitivul %s nu este compatibil."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Se ignoră dimensiunea optimă de transfer de date falsă pentru dispozitivul de date (%u octeți)."
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Dispozitivul %s este prea mic. Aveți nevoie de cel puțin %<PRIu64> octeți."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Nu se poate utiliza dispozitivul %s care este în uz (deja cartografiat sau montat)."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Nu se poate utiliza dispozitivul %s, permisiune refuzată."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Nu se pot obține informații despre dispozitivul %s."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Nu se poate utiliza un dispozitiv loopback, deoarece programul nu rulează cu privilegii de root."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Atașarea dispozitivului de loopback a eșuat (este necesar un dispozitiv de buclă cu fanion de ștergere automată)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Decalajul solicitat depășește dimensiunea reală a dispozitivului %s."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Dispozitivul %s are dimensiune zero."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Ora specificată pentru PBKDF nu poate fi zero."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Tip PBKDF necunoscut %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Suma de control solicitată %s nu este acceptată."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Tipul PBKDF solicitat nu este acceptat pentru LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Memoria maximă PBKDF sau firele de execuție paralele nu trebuie definite cu pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Numărul de iterații forțate este prea mic pentru %s (minimul este %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Costul memoriei forțate este prea mic pentru %s (minimul este de %u kiloocteți)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Costul maxim de memorie PBKDF solicitat este prea mare (maximul este de %d kiloocteți)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Memoria PBKDF maximă solicitată nu poate fi zero."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Firele paralele de execuție PBKDF solicitate nu pot fi zero."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Doar PBKDF2 este acceptat în modul FIPS."
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Testarea PBKDF este dezactivată, dar numărul de iterații nu este definit."
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Opțiuni PBKDF2 incompatibile (folosind algoritmul de sumă de control %s)."
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "Opțiuni PBKDF2 incompatibile."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Blocarea a fost anulată. Calea de blocare %s/%s este inutilizabilă (nu este un director sau lipsește)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Blocarea a fost anulată. Calea de blocare %s/%s este inutilizabilă (%s nu este un director)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Nu se poate căuta la poziția dispozitivului."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Eroare de ștergere a dispozitivului, decalaj %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Nu s-a putut configura asocierea cheii dm-crypt la dispozitivul %s.\n"
+"Verificați dacă nucleul acceptă cifrul %s (verificați syslog pentru mai multe informații)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Dimensiunea cheii în modul XTS trebuie să fie de 256 sau 512 biți."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Specificațiile de cifrare ar trebui să fie în formatul [cifrarea]-[mod]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Nu se poate scrie în dispozitivul %s, permisiune refuzată."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Nu s-a putut deschide dispozitivul pentru stocarea temporară a cheilor."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Nu s-a putut accesa dispozitivul pentru stocarea temporară a cheilor."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Eroare de In/Ieș în timpul criptării slotului de cheie."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Nu s-a putut deschide dispozitivul %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "Eroare de In/Ieș la decriptarea slotului de cheie."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Dispozitivul %s este prea mic. (LUKS1 necesită cel puțin %<PRIu64> octeți.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "Slotul de cheie LUKS %u nu este valid."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Fișierul de copie de rezervă pentru antetul solicitat %s există deja."
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Nu se poate crea fișierul de copie de rezervă al antetului %s."
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Nu se poate scrie fișierul de copie de rezervă al antetului %s."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Fișierul de copie de rezervă nu conține antet LUKS valid."
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Nu se poate deschide fișierul de copie de rezervă al antetului %s."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Nu se poate citi fișierul de copie de rezervă al antetului %s."
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Poziția datelor sau dimensiunea cheii diferă între dispozitiv și copia de rezervă, restaurarea a eșuat."
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Dispozitiv %s %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "nu conține antetul LUKS. Înlocuirea antetului poate distruge datele de pe acest dispozitiv."
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "conține deja antetul LUKS. Înlocuirea antetului va distruge sloturile de chei existente."
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"AVERTISMENT: antetul dispozitivului real are un UUID diferit de cel al copiei de rezervă!"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "Dimensiunea cheii nu este standard, este necesară repararea manuală."
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Alinierea sloturilor pentru chei nu este standard , este necesară repararea manuală."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Modul de cifrare reparat (%s -> %s)."
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Cifrul sumei de control(hash) reparat la minuscule (%s)."
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Suma de control(hash) LUKS solicitată %s nu este acceptată."
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "Se repară sloturile pentru chei."
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Slotul de cheie %i: poziție reparată (%u -> %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Slotul de cheie %i: benzi reparate (%u -> %u)."
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Slotul de cheie %i: semnătură falsă a partiției."
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Slotul de cheie %i: «salt» șters."
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "Se scrie antetul LUKS pe disc."
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "Repararea a eșuat."
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Modul de cifrare LUKS %s este nevalid."
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "Suma de control(hash) LUKS %s nu este validă."
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "Nu s-a detectat nicio problemă cunoscută pentru antetul LUKS."
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Eroare în timpul actualizării antetului LUKS pe dispozitivul %s."
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Eroare la recitirea antetului LUKS după actualizare pe dispozitivul %s."
+
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Decalajul datelor pentru antetul LUKS trebuie să fie 0 sau mai mare decât dimensiunea antetului."
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "Formatul UUID LUKS furnizat este greșit."
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Nu se poate crea antetul LUKS: citirea datelor «salt» aleatoare a eșuat."
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Nu se poate crea antetul LUKS: calcularea sumei de control a antetului a eșuat (folosind suma de control(hash) %s)."
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Slot de cheie %d activ, curățați mai întâi."
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Materialul de la slotul de cheie %d nu are suficiente benzi. Antetul a fost manipulat?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "Depășire a valorii de iterație a PBKDF2."
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Nu se poate deschide slotul de cheie (folosind suma de control(hash) %s)."
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Slotul de cheie %d nu este valid, selectați slotul de cheie între 0 și %d."
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Nu se poate șterge dispozitivul %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Fișierul cheie criptat GPG, detectat, nu este încă acceptat."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Utilizați «gpg --decrypt <fișier_cheie>» | «cryptsetup --keyfile=-...»\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "S-a detectat un fișier de cheie loop-AES incompatibil."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Nucleul nu acceptă asocierea compatibilă cu bucla loop-AES."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Eroare la citirea fișierului de cheie %s."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Lungimea maximă a frazei de acces TCRYPT (%zu) a fost depășită."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Algoritmul sumei de control(hash) PBKDF2 %s nu este disponibil, se omite."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "Interfața necesară de criptare a nucleului nu este disponibilă."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Asigurați-vă că aveți modulul nucleului «algif_skcipher», încărcat."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Activarea nu este acceptată pentru dimensiunea sectorului de %d."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Nucleul nu acceptă activarea pentru acest mod vechi TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Se activează criptarea sistemului TCRYPT pentru partiția %s."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Nucleul nu acceptă asocierea compatibilă cu TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Această funcție nu este acceptată fără încărcarea antetului TCRYPT."
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Tip neașteptat de intrare de metadate „%u” găsit la analizarea cheii master de volum acceptate."
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "S-a găsit șir nevalid la analizarea cheii master de volum."
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Șir neașteptat („%s”) găsit la analizarea cheii master de volum acceptate."
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Valoare neașteptată a intrării de metadate „%u” a fost găsită la analizarea cheii master de volum acceptate."
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "Versiunea 1 BITLK nu este acceptată în prezent."
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Semnătură de pornire nevalidă sau necunoscută pentru dispozitivul BITLK."
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Dimensiunea sectorului neacceptată, %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Nu s-a putut citi antetul BITLK de la %s."
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Nu s-au putut citi metadatele BITLK FVE de la %s."
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "Tip de criptare necunoscut sau neacceptat."
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Nu s-au putut citi intrările de metadate BITLK de la %s."
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "Nu s-a putut converti descrierea volumului BITLK"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Tip neașteptat de intrare de metadate „%u” găsit la analizarea cheii externe."
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "GUID-ul fișierului BEK „%s”, nu se potrivește cu GUID-ul volumului."
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Valoare neașteptată a intrării metadatelor „%u”, a fost găsită la analizarea cheii externe."
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Versiune neacceptată de metadate BEK %<PRIu32>"
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Dimensiune neașteptată a metadatelor BEK %<PRIu32>, nu se potrivește cu lungimea fișierului BEK"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Intrare neașteptată de metadate găsită la analizarea cheii de pornire."
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "Această operație nu este acceptată."
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "Dimensiune neașteptată a datelor cheii."
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Acest dispozitiv BITLK este într-o stare neacceptată și nu poate fi activat."
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Dispozitivele BITLK de tip „%s” nu pot fi activate."
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Activarea dispozitivului BITLK parțial decriptat nu este acceptată."
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "AVERTISMENT: dimensiunea volumului BitLocker %<PRIu64> nu se potrivește cu dimensiunea dispozitivului subiacent %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Nu se poate activa dispozitivul, modulul nucleului «dm-crypt» nu are suport pentru BITLK IV."
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Dispozitivul nu poate fi activat, modulul nucleului «dm-crypt» nu are suport pentru difuzorul BITLK Elephant."
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Dispozitivul nu poate fi activat, kernel-ul dm-crypt nu are suport pentru dimensiune mare a sectorului."
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Dispozitivul nu se poate activa, modulul nucleului, «dm-zero», lipsește."
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Nu s-au putut citi %u octeți din antetul volumului."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Versiune FVAULT2 neacceptată %<PRIu16>."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Dispozitivul verity %s nu utilizează antetul de pe disc."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Versiunea VERITY %d nu este acceptată."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "Antetul VERITY este corupt."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Formatul UUID VERITY furnizat pe dispozitivul %s este greșit."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Eroare la actualizarea antetului Verity pe dispozitivul %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Verificarea semnăturii sumei de verificare(hash) rădăcină nu este acceptată."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Erorile nu pot fi reparate cu dispozitivul FEC."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "S-au găsit %u erori reparabile cu dispozitivul FEC."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Nucleul nu acceptă asocierea dm-verity."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Nucleul nu acceptă opțiunea de semnătură dm-verity."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Dispozitivul verity a detectat corupție după activare."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Zona de rezervă nu este pusă la zero la poziția %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Depășire a poziției de pe dispozitiv."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Verificarea a eșuat la poziția %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Debordare a zonei sumei de control(hash)."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Verificarea zonei de date a eșuat."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Verificarea sumei de control(hash) rădăcină a eșuat."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Eroare de intrare/ieșire la crearea zonei de sumă de control(hash)."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Crearea zonei de sumă de control(hash) a eșuat."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "AVERTISMENT: Nucleul nu poate activa dispozitivul dacă dimensiunea blocului de date depășește dimensiunea paginii (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Nu s-a putut aloca contextul RS."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Nu s-a putut aloca memoria tampon."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Nu s-a putut citi blocul RS %<PRIu64> octetul %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Nu s-a putut citi paritatea pentru blocul RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Nu s-a putut repara paritatea pentru blocul %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Nu s-a putut scrie paritatea pentru blocul RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Dimensiunile blocurilor trebuie să se potrivească pentru FEC."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Număr nevalid de octeți de paritate."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Lungimea segmentului FEC nu este validă."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Nu s-a putut determina dimensiunea pentru dispozitivul %s."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Metadate incompatibile cu modulul nucleului «dm-integrity» (versiunea %u) detectate pe %s."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Nucleul nu acceptă asocierea dm-integrity."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Nucleul nu acceptă alinierea metadatelor fixe dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Nucleul refuză să activeze opțiunea de recalculare nesigură (consultați opțiunile de activare vechi pentru a le înlocui)."
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Nu s-a putut obține blocarea la scriere pe dispozitivul %s."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "S-a detectat o încercare de actualizare concomitentă a metadatelor LUKS2. Se abandonează operația."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Dispozitivul conține semnături ambigue, nu se poate recupera automat LUKS2.\n"
+"Rulați «cryptsetup repair» pentru recuperare."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Decalajul de date solicitat este prea mic."
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "AVERTISMENT: zona sloturilor de chei (%<PRIu64> octeți) este foarte mică, numărul de sloturi de chei LUKS2 disponibil este foarte limitat.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Nu s-a putut obține blocarea pentru citire pe dispozitivul %s."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Cerințe LUKS2 interzise detectate în copia de rezervă %s."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Decalajul datelor diferă între dispozitiv și copia de rezervă, restaurare eșuată."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Antetul binar cu dimensiunea zonelor sloturilor pentru chei diferă între dispozitiv și copia de rezervă, restaurare eșuată."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Dispozitiv %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "nu conține antetul LUKS2. Înlocuirea antetului poate distruge datele de pe acest dispozitiv."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "conține deja antetul LUKS2. Înlocuirea antetului va distruge sloturile de chei existente."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"AVERTISMENT: cerințe necunoscute LUKS2 detectate în antetul dispozitivului real!\n"
+"Înlocuirea antetului cu copia de rezervă poate deteriora datele de pe acest dispozitiv!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"AVERTISMENT: Recriptare „offline” nefinalizată detectată pe dispozitiv!\n"
+"Înlocuirea antetului cu copia de rezervă poate deteriora datele."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "S-a ignorat fanionul necunoscut %s."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Lipsește cheia pentru segmentul dm-crypt %u"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Nu s-a putut definii segmentul dm-crypt."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Nu s-a putut definii segmentul dm-linear."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Configurație de integritate a dispozitivului neacceptată."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Recriptare în curs. Nu se poate dezactiva dispozitivul."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Nu s-a putut înlocui dispozitivul suspendat %s cu ținta dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Nu s-au putut citi cerințele LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Au fost detectate cerințe LUKS2 neîndeplinite."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Operație incompatibilă cu dispozitivul marcat pentru recriptare învechită. Se abandonează."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Operație incompatibilă cu dispozitivul marcat pentru recriptare LUKS2. Se abandonează."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Nu există suficientă memorie disponibilă pentru a deschide un slot de cheie."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Deschiderea slotului de cheie a eșuat."
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Nu se poate utiliza cifrul %s-%s pentru criptarea slotului de cheie."
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Algoritmul sumei de control(hash) %s nu este disponibil."
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "Nu există spațiu pentru noul slot de cheie."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "A fost solicitată o schimbare incorectă a modului de adaptabilitate pentru recriptare."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Nu se poate actualiza tipul de adaptabilitate. Tipul nou oferă numai %<PRIu64> octeți, spațiul necesar este: %<PRIu64> octeți."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Nu s-a putut reîmprospăta calcularea sumei de control de verificare a recriptării."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Nu se poate verifica starea dispozitivului cu uuid: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Nu s-a putut converti antetul cu metadate suplimentare LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Nu se poate utiliza specificația de cifrare %s-%s pentru LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Nu se poate muta zona slotului pentru chei. Spațiu insuficient."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Nu se poate converti în format LUKS2 - metadate nevalide."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Nu se poate muta zona slotului pentru chei. Zona sloturilor pentru chei LUKS2 este prea mică."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Nu se poate muta zona slotului pentru chei."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Nu se poate converti în format LUKS1 - dimensiunea implicită a sectorului de criptare al segmentului nu este de 512 octeți."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Nu se poate converti în formatul LUKS1 - calcularea sumelor de control ale slotului de cheie nu este compatibilă cu LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Nu se poate converti în formatul LUKS1 - dispozitivul folosește cifrul de cheie încapsulat %s."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Nu se poate converti în formatul LUKS1 - dispozitivul utilizează mai multe segmente."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Nu se poate converti în formatul LUKS1 - antetul LUKS2 conține %u jetoane(tokens)."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Nu se poate converti în formatul LUKS1 - slotul de cheie %u este într-o stare nevalidă."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Nu se poate converti în formatul LUKS1 - slotul %u (peste sloturile maxime) este încă activ."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Nu se poate converti în formatul LUKS1 - slotul de cheie %u nu este compatibil cu LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Dimensiunea zonei „fierbinți” (active) trebuie să fie multiplu al alinierii zonei calculate (%zu octeți)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Dimensiunea dispozitivului trebuie să fie multiplu al alinierii zonei calculate (%zu octeți)."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Nu s-a putut inițializa vechea încapsulare de stocare a segmentului."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Nu s-a putut inițializa noua încapsulare de stocare a segmentului."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Nu s-a putut inițializa protecția zonei „fierbinți” (active)."
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Nu s-au putut citii sumele de control pentru zona „fierbinte” (activă) actuală."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Nu s-a putut citi zona „fierbinte” (activă) începând cu %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Nu s-a putut decripta sectorul %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Nu s-a putut recupera sectorul %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Dimensiunile dispozitivelor sursă și țintă nu se potrivesc. Sursa %<PRIu64>, ținta: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Nu s-a putut activa zona „fierbinte” (activă) a dispozitivului %s."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Nu s-a putut activa dispozitivul de suprapunere %s cu tabelul de origine actual."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Nu s-a putut încărca noua asociere pentru dispozitivul %s."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Nu s-a putut reîmprospăta stiva de dispozitive de recriptare."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Nu s-a putut definii dimensiunea zonei noilor sloturi pentru chei."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Valoarea deplasării datelor nu este aliniată la dimensiunea sectorului de criptare (%<PRIu32> octeți)."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Modul de adaptabilitate neacceptat %s"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Dimensiunea segmentului mutat nu poate fi mai mare decât valoarea deplasării de date."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Parametri de adaptabilitate de recriptare nevalizi."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Segmentul mutat este prea mare. Dimensiunea solicitată este de %<PRIu64>, iar spațiul disponibil pentru aceasta este de: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Nu s-a putut șterge tabelul."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "Dimensiunea redusă a datelor este mai mare decât dimensiunea dispozitivului real."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Dispozitivul de date nu este aliniat la dimensiunea sectorului de criptare (%<PRIu32> octeți)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Deplasarea datelor (%<PRIu64> sectoare) este mai mică decât decalajul viitor al datelor (%<PRIu64> sectoare)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Nu s-a putut deschide %s în modul exclusiv (deja cartografiat sau montat)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Dispozitivul nu este marcat pentru recriptarea LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Nu s-a putut încărca contextul de recriptare LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Nu s-a putut obține stadiul recriptării."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Dispozitivul nu se află în recriptare."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Procesul de recriptare rulează deja."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Nu s-a putut obține blocarea pentru recriptare."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Nu se poate continua cu recriptarea. Rulați mai întâi recuperarea recriptării."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Dimensiunea dispozitivului activ și dimensiunea de recriptare solicitată nu se potrivesc."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "Dimensiunea dispozitivului solicitată în parametrii de recriptare este incorectă."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Recriptare în curs. Nu se poate efectua recuperarea."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "Recriptare LUKS2 deja inițializată în metadate."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Nu s-a putut inițializa recriptarea LUKS2 în metadate."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Nu s-au putut definii segmentele dispozitivului pentru următoarea zonă „fierbinte” (activă) de recriptare."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Nu s-au putut scrie metadatele adaptabilității recriptării."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Decriptarea a eșuat."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Nu s-a putut scrie zona „fierbinte” (activă) începând de la %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Nu s-au putut sincroniza datele."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Nu s-au putut actualiza metadatele după finalizarea zonei „fierbinți” (active) de recriptare actuală."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Nu s-au putut scrie metadatele LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Nu s-a putut șterge zona nefolosită a dispozitivului de date."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Nu s-a putut elimina slotul de cheie neutilizat (neasociat) %d."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Nu s-a putut elimina slotul de cheie de recriptare."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Eroare fatală la recriptarea porțiunii începând de la %<PRIu64>, %<PRIu64> sectoare lungi."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Recriptarea «online» a eșuat."
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Nu reluați dispozitivul decât dacă este înlocuit manual cu ținta erorii."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Nu se poate continua cu recriptarea. Stare neașteptată a recriptării."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Context de recriptare lipsă sau nevalid."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Nu s-a putut inițializa stiva dispozitivului de recriptare."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Nu s-a putut actualiza contextul de recriptare."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Metadatele de recriptare sunt nevalide."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Parametrii de criptare a slotului de cheie pot fi stabiliți numai pentru dispozitivul LUKS2."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Introduceți codul PIN al jetonului: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Introduceți codul PIN al jetonului(token) %d: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Nu s-a detectat niciun model de specificație de cifrare cunoscut."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "AVERTISMENT: Parametrul „--hash” este ignorat în modul simplu, cu fișierul de cheie specificat.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "AVERTISMENT: Opțiunea „--keyfile-size” este ignorată, dimensiunea de citire este aceeași cu dimensiunea cheii de criptare.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "S-au detectat semnături de dispozitiv pe %s. Continuarea operației, riscă să deterioreze datele existente."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "Operația se întrerupe.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Opțiunea „--key-file” este necesară."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Introduceți PIM-ul VeraCrypt: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Valoare PIM nevalidă: eroare de analizare."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Valoare PIM nevalidă: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Valoare PIM nevalidă: în afara intervalului."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Nu a fost detectat niciun antet de dispozitiv cu această frază de acces."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Dispozitivul %s nu este un dispozitiv BITLK valid."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Nu se poate determina dimensiunea cheii de volum pentru BITLK; utilizați opțiunea „--key-size” pentru a o furniza."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Conținutul antetului cu cheia de volum este o informație sensibilă\n"
+"care permite accesul la partiția criptată fără fraza de acces.\n"
+"Acest conținut ar trebui să fie întotdeauna stocat criptat într-un loc sigur."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Conținutul antetului cu cheia de volum este o informație sensibilă\n"
+"care permite accesul la partiția criptată fără fraza de acces.\n"
+"Acest conținut ar trebui să fie întotdeauna stocat criptat într-un loc sigur."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Dispozitivul %s nu este un dispozitiv FVAULT2 valid."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Nu se poate determina dimensiunea cheii de volum pentru FVAULT2; utilizați opțiunea „--key-size” pentru a o furniza."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Dispozitivul %s este încă activ și programat pentru eliminare temporizată.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Redimensionarea dispozitivului activ necesită cheia de volum în inelul de chei, dar opțiunea „--disable-keyring” este furnizată."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Testarea pentru evaluarea performanței a fost întreruptă."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s (neaplicabil)\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iterații pe secundă pentru cheia %zu-bit\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s (neaplicabil)\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iterații, %5u memorie, %1u fire paralele (CPU-uri) pentru cheia %zu-bit (timpul necesitat %u ms)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Rezultatul testului de evaluare a performanței nu este fiabil."
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Testele sunt aproximative folosind doar memoria (fără In/Ieș de stocare).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algoritm | Cheie | Criptare | Decriptare\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Cifrarea %s (cu cheie de %i biți) nu este disponibilă."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritm | Cheie | Criptare | Decriptare\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "nedisponibil"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr "Au fost detectate metadate neprotejate de recriptare LUKS2. Verificați că operațiunea de recriptare este de dorit (consultați ieșirea luksDump) și continuați (să actualizați metadatele) numai dacă recunoașteți operația ca fiind autentică."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Introduceți fraza de acces pentru a proteja și actualiza metadatele de recriptare: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Continuați cu adevărat cu recuperarea recriptării LUKS2?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Introduceți fraza de acces pentru a verifica calcularea sumele de control a metadatelor de recriptare: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Introduceți fraza de acces pentru recuperarea recriptării: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Încercați cu adevărat să reparați antetul dispozitivului LUKS?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Ștergere întreruptă."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Se șterge dispozitivul pentru a inițializa calcularea sumei de control a integrității.\n"
+"Puteți întrerupe acest lucru apăsând CTRL+c (restul dispozitivului care nu este șters va conține o sumă de control nevalidă).\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Nu se poate dezactiva dispozitivul temporar %s."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Opțiunea de integritate poate fi utilizată numai pentru formatul LUKS2."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Opțiuni de dimensiune a metadatelor LUKS2 neacceptate."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Fișierul antet nu există, doriți să îl creați?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Nu se poate crea fișierul antet %s."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Nu a fost detectat niciun model de specificație de integritate cunoscut."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Nu se poate folosi %s ca antet pe disc."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Acest lucru va suprascrie datele de pe %s în mod irevocabil."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Nu s-au putut definii parametrii pbkdf."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Decalajul redus de date este permis numai pentru antetul LUKS detașat."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "Containerul de fișiere LUKS %s este prea mic pentru activare, nu mai rămâne spațiu pentru date."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Nu se poate determina dimensiunea cheii de volum pentru LUKS fără sloturi de chei; folosiți opțiunea „--key-size” pentru a furniza aceste date."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Dispozitivul a fost activat, dar nu se poate face ca fanioanele să fie persistente."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Slotul de cheie %d este selectat pentru ștergere."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Acesta este ultimul slot de cheie. Dispozitivul va deveni inutilizabil după eliminarea acestei chei."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Introduceți orice frază de acces rămasă: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Operația a fost întreruptă, slotul de cheie NU a fost șters.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Introduceți fraza de acces pentru a fi ștearsă: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Dispozitivul %s nu este un dispozitiv LUKS2 valid."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Introduceți noua frază de acces pentru slotul de cheie: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "AVERTISMENT: Parametrul „--key-slot” este utilizat pentru noul număr de slot de cheie.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Introduceți orice frază de acces existentă: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Introduceți fraza de acces pentru a fi schimbată: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Introduceți nouă frază de acces: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Introduceți fraza de acces pentru slotul de cheie care urmează să fie convertit: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Doar un singur dispozitiv este admis ca argument pentru operația isLuks."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Slotul de cheie %d nu conține o cheie neasociată."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Conținutul antetului cu cheia neasociată este o informație sensibilă.\n"
+"Acest conținut ar trebui să fie stocat criptat într-un loc sigur."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s nu este numele dispozitivului activ %s."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s nu este numele unui dispozitiv LUKS activ sau antetul lipsește."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "Este necesară opțiunea „--header-backup-file”."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s nu este un dispozitiv gestionat de «cryptsetup»."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Reîmprospătarea nu este disponibilă pentru tipul de dispozitiv %s"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Tip de dispozitiv de metadate nerecunoscut %s."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "Comanda necesită un dispozitiv și numele asociat acestuia ca argumente."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Această operație va șterge toate sloturile de chei de pe dispozitivul %s.\n"
+"Dispozitivul va deveni inutilizabil după această operație."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Operația a fost întreruptă, sloturile de chei NU au fost șterse.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Tip LUKS nevalid, numai luks1 și luks2 sunt acceptate."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Dispozitivul este deja de tip %s."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Această operație va converti %s în formatul %s.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Operația a fost întreruptă, dispozitivul NU a fost convertit.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Opțiunea „--priority”, „--label” sau „--subsystem” lipsește."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Jetonul(token) %d nu este valid."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Jetonul(token) %d este în uz."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Nu s-a putut adăuga jetonul(token) %d la inelul de chei luks2."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Nu s-a putut atribui jetonul(token) %d slotului pentru cheie %d."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Jetonul %d nu este în uz."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Nu s-a putut importa jetonul din fișier."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Nu s-a putut obține jetonul %d pentru export."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Jetonul %d nu este alocat slotului de cheie %d."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Nu s-a putut anula atribuirea jetonului %d din slotul de cheie %d."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Opțiunea „--tcrypt-hidden”, „--tcrypt-system” sau „--tcrypt-backup” este acceptată doar pentru dispozitivele TCRYPT."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Opțiunea „--veracrypt” sau „--disable-veracrypt” este acceptată numai pentru tipul de dispozitiv TCRYPT."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Opțiunea „--veracrypt-pim” este acceptată numai pentru dispozitivele compatibile cu VeraCrypt."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Opțiunea „--veracrypt-query-pim” este acceptată numai pentru dispozitivele compatibile cu VeraCrypt."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Opțiunile „--veracrypt-pim” și „--veracrypt-query-pim” se exclud reciproc."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Opțiunea „--persistent” nu este permisă cu opțiunea „--test-passphrase”."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Opțiunile „--refresh” și „--test-passphrase” se exclud reciproc."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Opțiunea „--shared” este permisă numai pentru deschiderea unui dispozitiv simplu."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Opțiunea „--skip” este acceptată numai pentru deschiderea dispozitivelor simple și a dispozitivelor loopaes."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Opțiunea „--offset” cu acțiune de deschidere este acceptată numai pentru dispozitivele simple și dispozitivele loopaes."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Opțiunea „--tcrypt-hidden” nu poate fi combinată cu opțiunea „--allow-discards”."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Opțiunea de dimensiune a sectorului cu acțiune de deschidere este acceptată numai pentru dispozitivele simple."
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Opțiunea sectoare IV (vector de inițializare) mari este acceptată numai pentru deschiderea dispozitivelor de tip simplu, cu dimensiunea sectorului mai mare de 512 de octeți."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "Opțiunea „--test-passphrase” este permisă numai pentru deschiderea dispozitivelor LUKS, TCRYPT, BITLK și FVAULT2."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Opțiunile „--device-size” și „--size” nu pot fi combinate."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Opțiunea „--unbound” este permisă numai pentru deschiderea dispozitivelor luks."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Opțiunea „--unbound” nu poate fi utilizată fără opțiunea „--test-passphrase”."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Opțiunile „--cancel-deferred” și „--deferred” nu pot fi utilizate în același timp."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Opțiunile „--reduce-device-size” și „--data-size” nu pot fi combinate."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Opțiunea „--active-name” poate fi utilizată numai pentru dispozitivele LUKS2."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Opțiunile „--active-name” și „--force-offline-reencrypt” nu pot fi combinate."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Este necesară specificarea slotului de cheie."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Opțiunile „--align-payload” și „--offset” nu pot fi combinate."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Opțiunea „--integrity-no-wipe” poate fi utilizată numai pentru acțiuni de formatare cu extensie de integritate."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Numai una dintre opțiunile „--use-[u]random” este permisă."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "Dimensiunea cheii este necesară cu opțiunea „--unbound”."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "Operație cu jeton(token) nevalidă."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Parametrul „--key-description” este obligatoriu pentru acțiunea de adăugare a jetonului."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Acțiunea necesită un jeton(token)l specific. Utilizați parametrul „--token-id”."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "Opțiunea „--unbound” este validă numai cu acțiunea de adăugare a jetonului."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Opțiunile „--key-slot” și „--unbound” nu pot fi combinate."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "Acțiunea necesită un slot de cheie specific. Utilizați parametrul „--key-slot”."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<dispozitiv> [--type <tip>] [<nume>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "deschide dispozitivul ca <nume>"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<nume>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "închide dispozitivul (elimină asocierea)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "redimensionează dispozitivul activ"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "afișează starea dispozitivului"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <cifrarea>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "evaluează performanța cifrului"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<dispozitiv>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "încearcă să repare metadatele de pe disc"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "recriptează dispozitivul LUKS2"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "șterge toate sloturile de chei (elimină cheia de criptare)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "convertește LUKS din/în formatul LUKS2"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "definește opțiunile permanente de configurare pentru LUKS2"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<dispozitiv> [<fișier cheie nou>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "formatează un dispozitiv LUKS"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "adaugă o cheie la dispozitivul LUKS"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<dispozitiv> [<fișier cheie>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "elimină cheia sau fișierul cheie furnizat de pe dispozitivul LUKS"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "modifică cheia furnizată sau fișierul cheie al dispozitivului LUKS"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "convertește o cheie în noii parametri pbkdf"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<dispozitiv> <slot cheie>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "șterge cheia cu numărul <slot cheie> de pe dispozitivul LUKS"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "afișează UUID-ul dispozitivului LUKS"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "testează <dispozitivul> pentru antetul partiției LUKS"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "afișează informațiile despre partiția LUKS"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "afișează informațiile despre dispozitivul TCRYPT"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "afișează informațiile despre dispozitivul BITLK"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "afișează informațiile despre dispozitivul FVAULT2"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Suspendă dispozitivul LUKS și șterge cheia (toate In/Ieșirile sunt înghețate)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "Repune în funcțiune dispozitivul LUKS suspendat"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Face copie de rezervă pentru antetul dispozitivului LUKS și pentru sloturile de chei"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Restaurează antetul dispozitivului LUKS și sloturile de chei"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <dispozitiv>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "Manipulează jetoanele LUKS2"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<acțiune> este una dintre:\n"
+
+# R-GC, scrie:
+# «open» și «close», sunt noile nume
+# pentru <acțiune>, iar:
+# «create» și «remove», sunt vechile
+# nume, sau alias pentru primele.
+# A se vedea ieșirea comenzii:
+# «cryptsetup -?|--help»
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Puteți utiliza, de asemenea, vechile alias de sintaxă <acțiune>:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<nume> este dispozitivul de creat sub %s\n"
+"<dispozitiv> este dispozitivul criptat\n"
+"<slot cheie> este numărul slotului de cheie LUKS de modificat\n"
+"<fișier cheie> fișier cheie opțional pentru noua cheie pentru acțiunea luksAddKey\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Formatul implicit de metadate compilate este %s (pentru acțiunea luksFormat).\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Suportul pentru modulul de jeton(token) extern LUKS2 este %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "integrat în compilare"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Calea modulului pentru jetonul(token) extern LUKS2: %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "dezactivat"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Parametrii impliciti pentru cheia și fraza de acces compilați:\n"
+"\tDimensiunea maximă a fișierului cheie: %dko, Lungimea maximă a frazei de acces interactivă %d (caractere)\n"
+"PBKDF implicit pentru LUKS1: %s, timp de iterație: %d (ms)\n"
+"PBKDF implicit pentru LUKS2: %s\n"
+"\tTimp de iterare: %d, Memorie necesară: %dko, Fire de execuție paralele: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Parametrii de cifrare ai dispozitivului compilați implicit:\n"
+"\tloop-AES: %s, cheie %d biți\n"
+"\tsimplu: %s, Cheie: %d biți, Suma de control a parolei: %s\n"
+"\tLUKS: %s, Cheie: %d biți, Suma de control a antetului LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: Dimensiunea implicită a cheii cu modul XTS (două chei interne) va fi dublată.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: necesită %s ca argumente"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Slotul de cheie nu este valid."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Dimensiunea dispozitivului trebuie să fie multiplu al sectorului de 512 octeți."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Specificația pentru dimensiunea zonei fierbinți(active) pentru recriptare maximă nu este validă."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Dimensiunea cheii trebuie să fie multiplu de 8 biți"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Dimensiunea maximă de reducere a dispozitivului este de 1 GiB."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Dimensiunea redusă trebuie să fie multiplu al sectorului de 512 octeți."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Argumentul opțiuni „--priority” poate fi doar «ignore/normal/prefer»."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Afișează acest mesaj de ajutor"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Afișează modul de utilizare pe scurt"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Afișează versiunea pachetului"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Opțiuni de ajutor:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[OPȚIUNE...] <acțiune> <parametri_acțiune>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Argumentul <acțiune> lipsește."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Acțiune necunoscută."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Opțiunea „--key-file” are prioritate față de argumentul specificat pentru fișierul cheie."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Numai un argument „--key-file” este permis."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Funcția de derivare a unei chei bazată pe parolă (PBKDF=Password-Based Key Derivation Function) poate fi doar pbkdf2 sau argon2i/argon2id."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Iterațiile forțate PBKDF nu pot fi combinate cu opțiunea de timp de iterație."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Opțiunile „--keyslot-cipher” și „--keyslot-key-size” trebuie să fie folosite împreună."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Nu s-a executat nicio acțiune. Programul a fost invocat cu opțiunea „--test-args”.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Nu se poate dezactiva blocarea metadatelor."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "S-a specificat un șir de date «salt» nevalid."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Nu s-a putut crea imaginea sumei de control(hash) %s pentru scriere."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Nu s-a putut crea imaginea FEC %s pentru scriere."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Nu s-a putut crea fișierul sumei de control(hash) rădăcină %s pentru scriere."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Nu se poate scrie în fișierul sumei de control (hash) rădăcină %s."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Dispozitivul %s nu este un dispozitiv VERITY valid."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Nu se poate citii din fișierul sumei de control (hash) rădăcină %s."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Fișierul sumei de control (hash) rădăcină %s nu este valid."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "S-a specificat un șir de sumă de control (hash) rădăcină nevalid."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Fișierul de semnătură %s nu este valid."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Nu se poate citi fișierul de semnătură %s."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Comanda necesită ca argument opțiunea <suma-de-control(hash)_rădăcină> sau „--root-hash-file”."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<dispozitiv_date> <dispozitiv_sumă-de-control(hash)>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "formatează dispozitivul"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<dispozitiv_date> <dispozitiv_sumă-de-control(hash)> [<sumă-de-control(hash)_rădăcină>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "verifică dispozitivul"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<dispozitiv_date> <nume> <dispozitiv_sumă-de-control(hash)> [<sumă-de-control(hash)_rădăcină>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "afișează starea dispozitivului activ"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<dispozitiv_sumă-de-control(hash)>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "afișează informațiile de pe disc"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<nume> este dispozitivul de creat sub %s\n"
+"<dispozitiv_date> este dispozitivul de date\n"
+"<dispozitiv_sumă-de-control(hash)> este dispozitivul care conține datele de verificare\n"
+"<sumă-de-control(hash)_rădăcină> suma-de-control(hash) a nodului rădăcină de pe <dispozitiv_sumă-de-control(hash)>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Parametrii dm-verity compilați implicit:\n"
+"\tAlgoritmul sumei de control(hash): %s, Bloc de date (octeți): %u, Bloc sumă de control(hash) (octeți): %u,\n"
+"\tDimensiune date «salt»: %u, Formatul sumei de control(hash): %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Opțiunile „--ignore-corruption” și „--restart-on-corruption” nu pot fi utilizate împreună."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Opțiunile „--panic-on-corruption” și „--restart-on-corruption” nu pot fi utilizate împreună."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Acest lucru va suprascrie datele de pe %s și %s în mod irevocabil.\n"
+"Pentru a păstra datele dispozitivului de date, utilizați opțiunea „--no-wipe” (și apoi activați-l cu „--integrity-recalculate”)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formatat cu dimensiunea etichetei %u, integritate internă %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Utilizarea fanionului pentru recalculare(...-recalculate) nu este acceptată, luați în considerare utilizarea opțiunii „--wipe” în schimb."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Dispozitivul %s nu este un dispozitiv INTEGRITY valid."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<dispozitiv_integritate>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<dispozitiv_integritate> <nume>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<nume> este dispozitivul de creat sub %s\n"
+"<dispozitiv_integritate> este dispozitivul care conține date cu etichete de integritate\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Parametrii dm-integrity compilați implicit:\n"
+"\tAlgoritmul sumei de control: %s\n"
+"\tDimensiunea maximă a fișierului cheie: %dko\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Dimensiune nevalidă --%s. Maximul este de %u octeți."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Trebuie specificată atât opțiunea pentru fișierul cheie, cât și opțiunea pentru dimensiunea cheii."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Trebuie specificată atât opțiunea pentru fișierul cheii de integritate a jurnalului, cât și opțiunea pentru dimensiunea cheii."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Algoritmul de integritate a jurnalului trebuie să fie specificat dacă este utilizată cheia de integritate a jurnalului."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Trebuie specificată atât opțiunea pentru fișierul cheii de criptare a jurnalului, cât și opțiunea pentru dimensiunea cheii."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Algoritmul de criptare a jurnalului trebuie să fie specificat dacă este utilizată cheia de criptare a jurnalului."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Opțiunile de recuperare și modul de hartă de biți(bitmap) se exclud reciproc."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Opțiunile jurnalului nu pot fi utilizate în modul de hartă de biți(bitmap)."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Opțiunile de hartă de biți(bitmap) pot fi utilizate numai în modul de hartă de biți(bitmap)."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"AVERTISMENT!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Sunteți sigur? (Tastați „yes” cu litere mari): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Eroare la citirea răspunsului de la terminal."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Comandă reușită."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "parametri greșiți sau lipsă"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "fără permisiune sau expresie de acces incorectă"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "memorie insuficientă"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "dispozitiv sau fișier specificat greșit"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "dispozitivul există deja sau dispozitivul este ocupat"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "eroare necunoscută"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Comanda a eșuat cu codul %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Slotul de cheie %i a fost creat."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Slotul de cheie %i a fost deblocat."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Slotul de cheie %i a fost eliminat."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Jetonul %i a fost creat."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Jetonul %i a fost eliminat."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Niciun jeton(token) nu a putut fi deblocat cu acest cod PIN."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Jetonul %i necesită un cod PIN."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Jetonul (tip %s) necesită un cod PIN."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Jetonul %i nu poate debloca slotul de cheie alocat (frază de acces greșită pentru slotul de cheie)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Jetonul (tip %s) nu poate debloca slotul de cheie alocat (frază de acces greșită pentru slotul de cheie)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Jetonul %i necesită o resursă suplimentară lipsă."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Jetonul (tip %s) necesită o resursă suplimentară lipsă."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Nu este disponibil niciun jeton utilizabil (tip %s)."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Nu este disponibil niciun jeton utilizabil."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Nu se poate citi fișierul de chei %s."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Nu se pot citi %d octeți din fișierul de chei %s."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Nu se poate deschide fișierul de chei %s pentru scriere."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Nu se poate scrie în fișierul de chei %s."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> zile"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> %s scris"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "viteza %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Progres: %5.1f%%, AMR %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Terminat în: %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Nu se poate verifica calitatea parolei: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Verificarea calității parolei a eșuat:\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Verificarea calității parolei a eșuat: frază de acces greșită (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "Eroare la citirea frazei de acces de la terminal."
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "Verifică fraza de acces: "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "Frazele de acces nu se potrivesc."
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "Nu se poate utiliza decalajul cu intrarea terminalului."
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Introduceți fraza de acces: "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Introduceți fraza de acces pentru %s: "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "Nu este disponibilă nicio cheie cu această frază de acces."
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "Nu este disponibil niciun slot de cheie utilizabil."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Nu se poate face verificarea frazei de acces pe intrări non-tty."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Nu s-a putut deschide fișierul %s în modul numai-pentru-citire."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Furnizați un jeton(token) JSON LUKS2 valid:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Nu s-a putut citi fișierul JSON."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Citire întreruptă."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Nu s-a putut deschide fișierul %s în modul de scriere."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Scriere întreruptă."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Nu s-a putut scrie fișierul JSON."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Dispozitiv dm activ „%s” detectat automat pentru dispozitivul de date %s.\n"
+
+# R-GC, scrie:
+# ceva mă face să cred că:
+# „holders”, ar trebui tradus de fapt,
+# ca „locatarii” (ghilimelele inclusiv).
+# Cred că de fapt autorii se referă
+# la ocupanții dispozitivului:
+# date normale, fișiere de antete de...,
+# fișiere de chei, fișiere de sume
+# de control, fișiere de draci și laci....
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Nu s-au putut detecta automat deținătorii dispozitivului %s."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Dispozitivul %s nu este un dispozitiv de blocuri.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Nu se poate decide dacă dispozitivul %s este activat sau nu.\n"
+"Sunteți sigur că doriți să continuați cu recriptarea în modul offline?\n"
+"Poate duce la coruperea datelor dacă dispozitivul este activat în acest moment.\n"
+"Pentru a rula recriptarea în modul online, utilizați în schimb parametrul „--active-name”.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Dispozitivul %s nu este un dispozitiv de blocuri. Nu se poate detecta automat dacă este activ sau nu.\n"
+"Utilizați „--force-offline-reencrypt” pentru a ocoli verificarea și rulați în modul offline (periculos!)."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Opțiunea „--resilience” solicitată nu poate fi aplicată operațiunii curente de recriptare."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Dispozitivul nu este în criptare LUKS2. Opțiune în conflict „--encrypt”."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Dispozitivul nu este în decriptare LUKS2. Opțiune în conflict „--decrypt”."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Dispozitivul este în recriptare folosind adaptabilitatea la transferul de date. Opțiunea „--resilience” solicitată nu poate fi aplicată."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Dispozitivul necesită recuperarea recriptării. Rulați mai întâi operația de reparare."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Dispozitivul %s este deja în recriptare LUKS2. Doriți să reluați operația inițializată anterior?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Recriptarea veche LUKS2 nu mai este acceptată."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Recriptarea dispozitivului cu profil de integritate nu este acceptată."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Solicitarea făcută cu opțiunea „--sector-size %<PRIu32>” este incompatibilă cu superblocul %s\n"
+"(dimensiunea blocului: %<PRIu32> octeți) detectat pe dispozitivul %s."
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Criptarea fără antet detașat (--header) nu este posibilă fără reducerea dimensiunii dispozitivului de date (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Decalajul de date solicitat trebuie să fie mai mic sau egal cu jumătate din parametrul opțiunii „--reduce-device-size”."
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Ajustarea valorii „--reduce-device-size” la de două ori față de „--offset %<PRIu64> (sectoare)”.\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Fișierul antet temporar %s există deja. Se abandonează."
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Nu se poate crea fișierul antet temporar %s."
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Dimensiunea metadatelor LUKS2 este mai mare decât valoarea decalajului de date."
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Nu s-a putut plasa antetul nou la începutul dispozitivului %s."
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s este acum activ și pregătit pentru criptarea online.\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Dispozitivul activ %s nu este LUKS2."
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "Se restabilește antetul LUKS2 original."
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "Restaurarea antetului LUKS2 original a eșuat."
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Fișierul antet %s nu există. Doriți să inițializați decriptarea LUKS2 a dispozitivului %s și să exportați antetul LUKS2 în fișierul %s?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Nu s-au putut adăuga permisiuni de citire/scriere la fișierul antet exportat."
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Inițializarea recriptării a eșuat. Copia de rezervă a antetului este disponibilă în %s."
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "Decriptarea LUKS2 este acceptată numai cu dispozitivul antet detașat (cu decalajul de date fixat la 0)."
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "Nu sunt suficiente sloturi de chei liberee pentru recriptare."
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Fișierul de cheie poate fi utilizat numai cu opțiunea „--key-slot” sau cu exact un slot de cheie activ."
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Introduceți fraza de acces pentru slotul de cheie %d: "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Introduceți fraza de acces pentru slotul de cheie %u: "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Se comută cifrul de criptare a datelor la %s.\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Nu s-au modificat parametrii de segment de date. Recriptarea a fost abandonată."
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Creșterea dimensiunii sectorului de criptare pe dispozitivul offline nu este acceptată.\n"
+"Activați mai întâi dispozitivul sau utilizați opțiunea „--force-offline-reencrypt” (periculos!)."
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Recriptarea a fost întreruptă."
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Reluarea recriptării LUKS în modul offline forțat.\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Dispozitivul %s conține metadate LUKS deteriorate. Se abandonează operația."
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Dispozitivul %s este deja un dispozitiv LUKS. Se abandonează operația."
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Dispozitivul %s este deja în recriptare LUKS. Se abandonează operația."
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "Decriptarea LUKS2 necesită opțiunea „--header”."
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "Comanda necesită un dispozitiv ca argument."
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Versiuni în conflict. Dispozitivul %s este LUKS1."
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Versiuni în conflict. Dispozitivul %s este în recriptare LUKS1."
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Versiuni în conflict. Dispozitivul %s este LUKS2."
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Versiuni în conflict. Dispozitivul %s este în recriptare LUKS2."
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Recriptarea LUKS2 a fost deja inițializată. Se abandonează operația."
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "Recriptarea dispozitivului nu este în curs de desfășurare."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Nu se poate deschide exclusiv %s, dispozitiv în uz."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Alocarea memoriei aliniate a eșuat."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Nu se poate citi dispozitivul %s."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Se marchează dispozitivul LUKS1 %s ca neutilizabil."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Nu se poate scrie dispozitivul %s."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Nu se poate scrie fișierul jurnalului de recriptare."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Nu se poate citii fișierul jurnalului de recriptare."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Format de jurnal greșit."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Fișierul jurnal %s există, reluând recriptarea.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Se activează dispozitivul temporar folosind antetul LUKS vechi."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Se activează dispozitivul temporar folosind antetul LUKS nou."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Activarea dispozitivelor temporare a eșuat."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Nu s-a putut definii decalajul de date."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Nu s-a putut definii dimensiunea metadatelor."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "A fost creat un nou antet LUKS pentru dispozitivul %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "A fost creată o copie de rezervă a antetului %s pentru dispozitivul %s."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Crearea antetelor de rezervă LUKS a eșuat."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Nu se poate restabili antetul %s pe dispozitivul %s."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Antetul %s de pe dispozitivul %s a fost restaurat."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Nu se poate deschide dispozitivul LUKS temporar."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Nu se poate obține dimensiunea dispozitivului."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "Eroare de In/Ieș în timpul recriptării."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "UUID-ul furnizat nu este valid."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Nu se poate deschide fișierul jurnalului de recriptare."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Nicio decriptare nu este în curs de desfășurare, UUID-ul furnizat poată să fie utilizat doar pentru a relua procesul de decriptare suspendat."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Recriptarea se va modifica: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "cheia de volum"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "stabilește suma de control(hash) la "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", stabilește cifrarea la "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "AVERTISMENT: Dispozitivul %s conține deja o semnătură de partiție „%s”.\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "AVERTISMENT: Dispozitivul %s conține deja o semnătură superbloc „%s”.\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Nu s-au inițializat probele de semnătură a dispozitivului."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Nu s-a putut obține starea dispozitivului %s."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Nu s-a putut deschide fișierul %s în modul citire/scriere."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Semnătura partiției „%s” existentă pe dispozitivul %s va fi ștearsă."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Semnătura superblocului „%s” existentă pe dispozitivul %s va fi ștearsă."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Nu s-a putut șterge semnătura dispozitivului."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Nu s-a putut verifica dispozitivul %s pentru o semnătură."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Specificație de dimensiune nevalidă în parametrul „--%s”."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Opțiunea „--%s” nu este permisă cu acțiunea %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Nu s-a putut scrie jetonul ssh în format JSON."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Modul de criptare experimentală pentru deblocarea dispozitivelor LUKS2 cu jeton(token) conectat la un server SSH\v Acest modul permite în prezent doar adăugarea unui jeton(token) la un slot de cheie existent.\n"
+"\n"
+"Serverul SSH specificat trebuie să conțină un fișier cheie în calea specificată, cu o frază de acces pentru un slot de cheie existent pe dispozitiv.\n"
+"Acreditările furnizate vor fi folosite de «cryptsetup» pentru a obține parola atunci când deschideți dispozitivul folosind jetonul(token).\n"
+"\n"
+"Notă: Informațiile furnizate la adăugarea jetonului(token) (adresa serverului SSH, utilizatorul și căile) vor fi stocate în antetul LUKS2 în text clar."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<acțiune> <dispozitiv>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Opțiuni pentru acțiunea „add”:"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "Adresa IP/URL a serverului de la distanță pentru acest jeton(token)"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Nume de utilizator folosit pentru serverul de la distanță"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Calea către fișierul de cheie din serverul de la distanță"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Calea către cheia SSH pentru conectarea la serverul de la distanță"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Slotul de cheie căruia să îi atribuiți jetonul. Dacă nu este specificat, jetonul va fi atribuit primei fraze de acces furnizate care se potrivește cu slotul de cheie."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Opțiuni generice:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Afișează mesaje de eroare mult mai detaliate"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Afișează mesajele de depanare"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Afișează mesajele de depanare, inclusiv metadate JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Nu s-a putut deschide și importa cheia privată:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Nu s-a putut importa cheia privată (protejată prin parolă?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Parola pentru %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Argumentele nu au putut fi analizate.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Trebuie specificată o acțiune\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Trebuie specificat dispozitivul pentru acțiunea „%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Serverul SSH trebuie să fie specificat pentru acțiunea „%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Trebuie specificat utilizatorul SSH pentru acțiunea „%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Trebuie specificată calea SSH pentru acțiunea „%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Trebuie specificată calea cheii SSH pentru acțiunea „%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Nu s-a putut deschide %s folosind acreditările furnizate.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Doar acțiunea „addi” este suportată în prezent de acest modul.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Nu se poate crea sesiunea sftp: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Nu se poate iniția sesiunea sftp: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Nu se poate deschide sesiunea sftp: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Nu se poate stabili starea fișierului sftp: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Nu este suficientă memorie.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Nu se poate citi cheia de la distanță: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Conexiunea a eșuat: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Server necunoscut: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Metoda de autentificare cu cheie publică nu este permisă pe gazdă.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Eroare la autentificarea cu cheia publică: "
diff --git a/po/ru.po b/po/ru.po
new file mode 100644
index 0000000..1133486
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,4964 @@
+# Russian translation for cryptsetup
+# Copyright (C) 2018 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+#
+# Rosetta Contributors and Canonical Ltd <EMAIL@ADDRESS>, 2007.
+# Eugene Roskin <Unknown>, 2016.
+# Yuri Kozlov <yuray@komyakino.ru>, 2018, 2019, 2020, 2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-04 15:38+0300\n"
+"Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n"
+"Language-Team: Russian <gnu@d07.ru>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Launchpad-Export-Date: 2018-12-03 15:52+0000\n"
+"X-Generator: Lokalize 20.12.0\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Не удалось инициализировать device-mapper, выполняется без прав суперпользователя."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Не удалось инициализировать device-mapper. Загружен ли модуль ядра dm_mod?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Запрошенный флаг отсрочки не поддерживается."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "У устройства %s был обрезан DM-UUID."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Неизвестный тип цели dm."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Запрошенные параметры производительности dm-crypt не поддерживаются."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Запрошенные параметры обработки повреждённых данных dm-verify не поддерживаются."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "Запрошенный параметр tasklets dm-verify не поддерживается."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Запрошенные параметры FEC dm-verify не поддерживаются."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Запрошенные параметры целостности данных не поддерживаются."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "Запрошенный параметр sector_size не поддерживается."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Запрошенный автоматический пересчёт тегов целостности не поддерживается."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM не поддерживается."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Запрошенный режим битовой карты dm-integrity не поддерживается."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Ошибка при запросе сегмента dm-%s."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"При генерации ключа тома в системе закончились данные энтропии.\n"
+"Подвигайте мышь или наберите любой текст в другом окне, чтобы возникли случайные события.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Генерация ключа (выполнена на %d%%).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Выполнение в режиме FIPS."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "При инициализации RNG возникла критическая ошибка."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Запрошено неизвестное качество RNG."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Ошибка чтения из RNG."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Невозможно инициализировать внутренний интерфейс crypto RNG."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Невозможно инициализировать внутренний интерфейс crypto."
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Алгоритм хэширования %s не поддерживается."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Ошибка обработки ключа (используется хэш %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Невозможно определить тип устройства. Несовместимая активация устройства?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "Эта операция поддерживается только для устройства LUKS."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Эта операция поддерживается только для устройства LUKS2."
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Заполнены все слоты ключей."
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Некорректный слот ключа %d, укажите значение между 0 и %d."
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Слот ключа %d заполнен, выберите другой."
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "Размер устройства не выровнен к размеру логического блока устройства."
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Обнаружен заголовок, но устройство %s слишком маленькое."
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Эта операция не поддерживается для этого типа устройств."
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Недопустимая операция во время работы перешифрования."
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Не удалось откатиться на метаданные LUKS2 в памяти."
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Устройство %s не является корректным устройством LUKS."
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Неподдерживаемая версия LUKS %d."
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "Устройство %s не активно."
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Исчезло нижележащее устройство у устройства crypt %s."
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "Неверные параметры plain crypt."
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "Неверный размер ключа."
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "Для данного типа crypt UUID не поддерживается."
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Устройство с отсоединёнными метаданными не поддерживается для этого типа crypt."
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Неподдерживаемый размер сектора шифрования."
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "Размер устройства не выровнен к запрошенному размеру сектора."
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "Невозможно отформатировать LUKS без устройства."
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Запрошенный тип выравнивания данных не совместим со смещением данных."
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "невозможно затереть заголовок на устройстве %s."
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Устройство %s слишком маленькое для активации, не хватает места для данных.\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: Активация устройства завершится ошибкой, так как отсутствует поддержка dm-crypt для запрошенного размера сектора шифрования.\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Ключ тома слишком мал для шифрования с целостными расширениями."
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Шифр %s-%s (размер ключа %zd бит) недоступен."
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: размер метаданных LUKS2 изменился и стал %<PRIu64> байт.\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: размер слотов ключа LUKS2 изменился и стал %<PRIu64> байт.\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Устройство %s слишком маленькое."
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Невозможно отформатировать устройство %s, которое используется."
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Невозможно отформатировать устройство %s, недостаточно прав."
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Невозможно отформатировать целостность для устройства %s."
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Невозможно отформатировать устройство %s."
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "Невозможно отформатировать LOOPAES без устройства."
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "Невозможно отформатировать VERITY без устройства."
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Неподдерживаемый тип хэша %d для VERITY."
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Неподдерживаемый размер блока для VERITY."
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Неподдерживаемое смещение хэша для VERITY."
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "Неподдерживаемое смещение FEC для VERITY."
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "Область данных перекрывает области хэша."
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "Область хэша перекрывает область FEC."
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "Область данных перекрывает область FEC."
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: запрошенный размер тега в %d байт отличается от выходного размера %s (%d байт).\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Запрошен неизвестный тип устройства crypt %s."
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Неподдерживаемые параметры для устройства %s."
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Несовпадение параметров для устройства %s."
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Несоответствие устройств crypt."
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Ошибка при перезагрузке устройства %s."
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Ошибка при приостановке устройства %s."
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Ошибка при возобновлении работы устройства %s."
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Критическая ошибка при перезагрузке устройства %s (поверх устройства %s)."
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Ошибка при переключении устройства %s на dm-error."
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "Невозможно изменить размер закольцованного (loop) устройства."
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: максимальный размер уже задан или ядро не поддерживает изменение размера.\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Изменение размера невозможно, не поддерживается ядром."
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "Вы действительно хотите изменить UUID устройства?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Файл резервного заголовка не содержит заголовка совместимого с LUKS."
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Том %s не активен."
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Том %s уже приостановлен."
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Приостановка не поддерживается устройством %s."
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Ошибка во время приостановки устройства %s."
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Возобновление не поддерживается устройством %s."
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Ошибка во время возобновления устройства %s."
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Том %s не приостановлен."
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Ключ тома не подходит к тому."
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "Ошибка при переключении на новый слот ключа."
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Некорректный слот ключа %d."
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Слот ключа %d не активен."
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "Заголовок устройства перекрывает область данных."
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Выполняется перешифрование. Невозможно активировать устройство."
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Ошибка при получении блокировки перешифрования."
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Ошибка восстановления перешифрования LUKS2."
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "Тип устройства инициализирован неправильно."
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "Устройство %s уже существует."
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Невозможно использовать устройство %s, некорректное имя или оно всё ещё используется."
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "Для устройства plain указан некорректный ключ тома."
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "Некорректный корневой хэш для указанного устройства verity."
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "Требуется подпись корневого хэша."
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Отсутствует связка ключей ядра: требуется для передачи подписи в ядро."
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "Ошибка при загрузке ключа в связку ключей ядра."
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Не удалось отменить отложенное удаление с устройства %s."
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Устройство %s всё ещё используется."
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "Неверное устройство %s."
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "Буфер ключа тома слишком мал."
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Невозможно получить ключ тома для устройства LUKS2."
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Невозможно получить ключ тома для устройства LUKS1."
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Невозможно получить ключ тома для устройства plain."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Невозможно получить корневой хэш для устройства verity."
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Невозможно получить ключ тома для устройства BITLK."
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Невозможно получить ключ тома для устройства FVAULT2."
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Эта операция не поддерживается для устройства crypt %s."
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "Операция дампа не поддерживается для устройства этого типа."
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Смещение данных не кратно %u байтам."
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Невозможно преобразовать устройство %s, которое всё ещё используется."
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Ошибка при назначении слота ключа %u в качестве нового ключа тома."
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Ошибка при инициализации параметров слота ключа по умолчанию LUKS2."
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Ошибка при назначении слота ключа %d дайджесту."
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Невозможно добавить слот ключа, все слоты отключены и не предоставлен ключ тома."
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Связка ключей ядра не поддерживается ядром."
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Не удалось прочитать парольную фразу из связки ключей (ошибка %d)."
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Не удалось захватить глобальную блокировку сериализации доступа на скорости памяти (memory-hard)."
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Не удалось открыть файл ключа."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Невозможно прочитать файл ключа с терминала."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "Не удалось выполнить stat для файла ключа."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Невозможно переместиться по запрошенному смещению в файле ключа."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "Не хватило памяти при чтении парольной фразы."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Ошибка чтения парольной фразы."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Нет ничего для чтения со стандартного ввода."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Превышен максимальный размер файла ключа."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "невозможно прочитать запрошенное количество данных."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Устройство %s не существует или отказано в доступе."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Устройство %s несовместимо."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Игнорируется фиктивный размер optimal-io для устройства данных (%u байт)."
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Устройство %s слишком маленькое. Требуется не менее %<PRIu64> байт."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Невозможно использовать устройство %s, которое используется (отображено или примонтировано)."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Невозможно использовать устройство %s, недостаточно прав."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Невозможно получить информацию об устройстве %s."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Невозможно использовать закольцованное устройство, выполняется без прав суперпользователя."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Ошибка при присоединении закольцованного устройства (требуется закольцованное устройство с флагом autoclear)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Запрошенный размер вне реального размера устройства %s."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Устройство %s имеет нулевой размер."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Запрошенное время цели PBKDF не может быть нулевым."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Неизвестный тип PBKDF %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Запрошенный хэш %s не поддерживается."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Запрошенный тип PBKDF %s не поддерживается в LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Максимальный размер памяти PBKDF и количество параллельных нитей нельзя задавать вместе с pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Навязанный счётчик итераций слишком мал для %s (минимальное значение равно %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Навязанная стоимость памяти слишком мала для %s (минимальное значение равно %u килобайт)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Запрошенная максимальная стоимость памяти PBKDF слишком высока (максимальное значение равно %d килобайт)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Запрошенная максимальная стоимость памяти PBKDF не может быть равна нулю."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Запрошенное количество параллельных нитей PBKDF не может быть нулевым."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "В режиме FIPS поддерживается только PBKDF2."
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Оценка производительности PBKDF выключена, но не задано количество итераций."
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Несовместимые параметры PBKDF2 (используется алгоритм хэширования %s)."
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "Несовместимые параметры PBKDF."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Блокировка прервана. Путь блокировки %s/%s использовать невозможно (не является каталогом или отсутствует)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Блокировка прервана. Путь блокировки %s/%s использовать невозможно (%s не является каталогом)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Невозможно перемещаться по устройству."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Ошибка затирания устройства, смещение %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Ошибка при настройке отображения ключей dm-crypt для устройства %s.\n"
+"Убедитесь, что ядро поддерживает шифр %s (подробности смотрите в syslog)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Размер ключа в режиме XTS должен быть 256 или 512 бит."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Шифр должен указываться в формате [шифр]-[режим]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Невозможно записать на устройство %s, недостаточно прав."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Не удалось открыть временное устройство keystore."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Не удалось получить доступ к временному устройству keystore."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Ошибка ввода-вывода при шифровании слота ключа."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Невозможно открыть устройство %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "Ошибка ввода-вывода при расшифровке слота ключа."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Устройство %s слишком маленькое (для LUKS1 требуется не менее %<PRIu64> байт)."
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "Некорректный слот ключа LUKS %u."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Запрошенный файл резервного заголовка %s уже существует."
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Невозможно создать файл резервного заголовка %s."
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Невозможно записать файл резервного заголовка %s."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Резервный файл не содержит корректный заголовок LUKS."
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Невозможно открыть файл резервного заголовка %s."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Невозможно прочитать файл резервного заголовка %s."
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Смещение данных или размер ключа различаются на устройстве и в резервной копии, восстановление невозможно."
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Устройство %s %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "не содержит заголовка LUKS. Замена заголовка может уничтожить данные на этом устройстве."
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "уже содержит заголовок LUKS. Замена заголовка уничтожит существующие слоты ключей."
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"ПРЕДУПРЕЖДЕНИЕ: заголовок устройства и резервная копия содержат разные UUID!"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "Нестандартный размер ключа, требуется исправление вручную."
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Нестандартное выравнивание слотов ключей, требуется исправление вручную."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Исправлен режим шифра (%s -> %s)."
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Хэш шифра приведён к нижнему регистру (%s)."
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Запрошенный хэш LUKS %s не поддерживается."
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "Исправление слотов ключей."
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Слот ключа %i: исправлено смещение (%u -> %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Слот ключа %i: исправлены полосы (%u -> %u)."
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Слот ключа %i: фиктивная подпись раздела."
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Слот ключа %i: соль затёрта."
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "Запись заголовка LUKS на диск."
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "Ошибка при исправлении."
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Некорректный режим шифра LUKS %s."
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "Некорректный хэш LUKS %s."
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "Известных неполадок в заголовке LUKS не обнаружено."
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Ошибка при обновлении заголовка LUKS на устройстве %s."
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Ошибка при повторном считывании заголовка LUKS после обновления на устройстве %s."
+
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Смещение данных заголовка LUKS должно быть равно 0 или быть больше размера заголовка."
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "Указан неправильный формат LUKS UUID."
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Невозможно создать заголовок LUKS: ошибка при чтении случайной соли."
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Невозможно создать заголовок LUKS: ошибка подсчёта дайджеста заголовка (используйте хэш %s)."
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Активен слот ключа %d, сначала нужна вычистка."
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Данный слота ключа %d содержат несколько полос. Подделка заголовка?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "Переполнение значения итерации PBKDF2."
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Невозможно открыть слот ключа (используется хэш %s)."
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Некорректный слот ключа %d, значение слота ключа должно быть между 0 и %d."
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Невозможно затереть устройство %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Обнаружен пока не поддерживаемый зашифрованный файл ключа GPG."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Используйте gpg --decrypt <ФАЙЛ_КЛЮЧА> | cryptsetup --keyfile=- …\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Обнаружен несовместимый файл ключа loop-AES."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Ядро не поддерживает совместимое отображение loop-AES."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Ошибка при чтении файла ключа %s."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Превышена максимальная длина парольной фразы TCRYPT (%zu)."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Алгоритм хэширования PBKDF2 %s недоступен, пропускается."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "Требуемый интерфейс ядра crypto недоступен."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Убедитесь, что загружен ядерный модуль algif_skcipher."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Активация не поддерживается при размере сектора %d."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Ядро не поддерживает активацию для данного устаревшего режима TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Активируется система шифрования TCRYPT для раздела %s."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Ядро не поддерживает совместимое отображение TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "эта функция не поддерживается без загрузки заголовка TCRYPT."
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "При анализе поддерживаемого главного ключа тома обнаружен неожиданный тип элемента метаданных «%u»."
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "При анализе поддерживаемого главного ключа тома обнаружена некорректная строка."
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "При анализе поддерживаемого главного ключа тома обнаружена неожиданная строка («%s»)."
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "При анализе поддерживаемого главного ключа тома обнаружено неожиданное значение элемента метаданных «%u»."
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK версии 1 пока не поддерживается."
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Некорректная или неизвестная подпись загрузчика устройства BITLK."
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Неподдерживаемый размер сектора %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Ошибка чтения заголовка BITLK из %s."
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Ошибка чтения метаданных BITLK FVE из %s."
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "Неизвестный или неподдерживаемый тип шифрования."
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Ошибка чтения элементов метаданных BITLK из %s."
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "Ошибка преобразования описания тома BITLK"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "При анализе внешнего ключа обнаружен неожиданный тип элемента метаданных «%u»."
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "GUID «%s» BEK-файла не совпадает с GUID тома."
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "При анализе внешнего ключа обнаружено неожиданное значение элемента метаданных «%u»."
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Неподдерживаемая версия %<PRIu32> метаданных BEK"
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Неожиданный размер %<PRIu32> метаданных BEK не совпадает с длиной файла BEK"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "При анализе ключа запуска обнаружен неожиданный элемент метаданных."
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "Эта операция не поддерживается."
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "Неожиданный размер ключа данных."
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Данное устройство BITLK находится в неподдерживаемом состоянии и не может быть включено."
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Устройства BITLK с типом «%s» не могут быть включены."
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Активация частично расширенного устройства BITLK не поддерживается."
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: размер тома BitLocker %<PRIu64> не совпадает с размером нижележащего устройства %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Невозможно активировать устройство, в ядерном dm-crypt отсутствует поддержка BITLK IV."
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Невозможно активировать устройство, в ядерном dm-crypt отсутствует поддержка BITLK Elephant diffuser."
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Невозможно активировать устройство, в ядерном dm-crypt отсутствует поддержка секторов большого размера."
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Невозможно активировать устройство, отсутствует модуль ядра dm-zero."
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Невозможно прочитать %u байт из заголовка тома."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Неподдерживаемая версия FVAULT2 %<PRIu16>."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Устройство verity %s не использует заголовок на диске."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Неподдерживаемая версия VERITY %d."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "Повреждён заголовок VERITY."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Указан неправильный формат VERITY UUID на устройстве %s."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Ошибка при обновлении заголовка verity на устройстве %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Проверка подписи корневого хэша не поддерживается."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Невозможно исправить ошибки с устройством FEC."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Найдено %u исправимых ошибок с устройством FEC."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Ядро не поддерживает отображение dm-verity."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Ядро не поддерживает параметр подписи dm-verity."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "После активации обнаружено повреждение устройства verity."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Резервная область не заполнена нулями по адресу %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Переполнение смещения устройства."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Ошибка при проверке по адресу %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Переполнение области хэша."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Ошибка при сверке области данных."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Ошибка при сверке корневого хэша."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Ошибка ввода-вывода при создании области хэша."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Ошибка при создании области хэша."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "ПРЕДУПРЕЖДЕНИЕ: ядро не сможет активировать устройство, если размер блока данных превышает размер страницы (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Ошибка при выделении контекста RS."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Ошибка при выделении буфера."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Не удалось прочитать блок RS %<PRIu64>, байт %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Не удалось прочитать чётность для блока RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Не удалось исправить чётность для блока %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Не удалось записать чётность для блока RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Для FEC размеры блока должны совпадать."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Неверное количество байт чётности."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Неправильная длина сегмента FEC."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Не удалось определить размер устройства %s."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "На %2$s обнаружены несовместимые с ядерным dm-integrity метаданные (версия %1$u)."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Ядро не поддерживает отображение dm-integrity."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Ядро не поддерживает выравнивание фиксированных метаданных dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Ядро не позволяет задействовать небезопасный параметр пересчёта (для отключения ищите параметры включения старого режима)."
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Не удалось захватить блокировку на запись на устройстве %s."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Обнаружена попытка одновременного обновления метаданных LUKS2. Отмена операции."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Устройство содержит двусмысленные подписи, невозможно провести автоматическое\n"
+"восстановление LUKS2. Для восстановления запустите «cryptsetup repair»."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Запрошенное смещение данных слишком мало."
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: очень маленькая область слотов ключа (%<PRIu64> байт), количество доступных слотов ключа LUKS2 очень ограничено.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Не удалось захватить блокировку устройства %s на чтение."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "В резервной копии %s обнаружены запрещённые требования LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Смещение данных различается на устройстве и в резервной копии, восстановление невозможно."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Двоичный заголовок с областями слота ключа различается на устройстве и в резервной копии, восстановление невозможно."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Устройство %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "не содержит заголовка LUKS2. Замена заголовка может уничтожить данные на этом устройстве."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "уже содержит заголовок LUKS2. Замена заголовка уничтожит существующие слоты ключей."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"ПРЕДУПРЕЖДЕНИЕ: обнаружены неизвестные требования LUKS2 в заголовке\n"
+"действующего устройства! Замена заголовка из резервной копии может повредить\n"
+"данные на этом устройстве!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"ПРЕДУПРЕЖДЕНИЕ: на устройстве обнаружено незаконченное отложенное (offline)\n"
+"перешифрование! Замена заголовка из резервной копии может повредить данные."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Неизвестный флаг %s игнорируется."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Отсутствует ключ для сегмента dm-crypt %u"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Ошибка при задании сегмента dm-crypt."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Ошибка при задании сегмента dm-linear."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Неподдерживаемые настройки целостности устройства."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Выполняется перешифрование. Невозможно деактивировать устройство."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Не удалось заменить приостановленное устройство %s на цель dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Ошибка при чтении требований LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Обнаружены неудовлетворяемые требования LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Операция не совместима с устройством, отмеченным для устаревшего перешифрования. Прерываемся."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Операция не совместима с устройством, отмеченным для перешифрования LUKS2. Прерываемся."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Недостаточно памяти для открытия слота ключа."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Ошибка открытия слота ключа."
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Невозможно использовать шифр %s-%s для шифрования слота ключа."
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Алгоритм хэширования %s недоступен."
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "Нет места для нового слота ключа."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Запрошена некорректная смена режима устойчивости перешифрования."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Невозможно обновить тип устойчивости. Новый тип предоставляет только %<PRIu64> байт, требуемое место: %<PRIu64> байт."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Ошибка при обновлении сверки дайджеста перешифрования."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Невозможно определить состояние устройства с uuid: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Невозможно преобразовать заголовок с дополнительными метаданными LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Невозможно использовать шаблон шифра %s-%s для LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Невозможно переместить область слота ключа. Недостаточно места."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Невозможно преобразовать в формат LUKS2 — некорректные метаданные."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Невозможно переместить область слота ключа. Слишком маленькие слоты ключа LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Невозможно переместить область слота ключа."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Невозможно преобразовать в формат LUKS1 — размер сектора шифрования сегмента по умолчанию не равно 512 байтам."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Невозможно преобразовать в формат LUKS1 — дайджесты слота ключа несовместимы с LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Невозможно преобразовать в формат LUKS1 — устройство использует шифр %s с обёрточным ключом."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Невозможно преобразовать в формат LUKS1 — устройство использует несколько сегментов."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Невозможно преобразовать в формат LUKS1 — заголовок LUKS2 содержит %u токенов."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Невозможно преобразовать в формат LUKS1 — слот ключа %u находится в некорректном состоянии."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Невозможно преобразовать в формат LUKS1 — слот %u (больше максимального количества слотов) всё ещё активен."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Невозможно преобразовать в формат LUKS1 — слот ключа %u несовместим с LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Размер hotzone должен быть кратен вычисленному выравниванию зоны (%zu байт)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Размер устройства должен быть кратен вычисленному выравниванию зоны (%zu байт)."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Ошибка при инициализации старой сегментной обёртки хранилища."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Ошибка при инициализации новой сегментной обёртки хранилища."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Ошибка при инициализации защиты hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Ошибка чтения контрольных сумм текущей hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Не удалось прочитать область hotzone начиная с %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Не удалось расшифровать сектор %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Не удалось восстановить сектор %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Размеры устройств источника и назначения не совпадают. Источник %<PRIu64>, назначение: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Ошибка при активации устройства hotzone %s."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Ошибка при активации оверлейного устройства %s с действительной исходной таблицей."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Ошибка при загрузке нового отображения устройства %s."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Ошибка при обновлении стека устройств перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Ошибка при задании нового размера области слотов ключей."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Значение сдвига данных не выровнено к размеру сектора шифрования (%<PRIu32> байт)."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Неподдерживаемый режим устойчивости %s."
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Размер перемещаемого сегмента не может быть больше значения сдвига данных."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Некорректные параметры устойчивости перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Слишком большой перемещаемый сегмент. Запрошенный размер %<PRIu64>, доступно место: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Ошибка очистки таблицы."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "Размер сокращённых данных больше размера устройства."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Устройство данных не выровнено к размеру сектора шифрования (%<PRIu32> байт)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Сдвиг данных (%<PRIu64> секторов) меньше чем будущее смещение данных (%<PRIu64> секторов)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Ошибка при открытии %s в монопольном режиме (уже отображено или примонтировано)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Устройство не отмечено для перешифрования LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Ошибка при загрузке контекста перешифрования LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Ошибка при получении состояния перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Устройство не перешифровывается."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Процесс перешифрования уже запущен."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Ошибка при захвате блокировки перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Невозможно продолжить с перешифрованием. Сначала запустите восстановление перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Активный размер устройства и запрошенный размер перешифрования не совпадают."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "В параметрах перешифрования запрошен некорректный размер устройства."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Выполняется перешифрование. Восстановление выполнить невозможно."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "Перешифрование LUKS2 уже инициализировано в метаданных."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Не удалось инициализировать перешифрование LUKS2 в метаданных."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Ошибка при назначении сегментов устройства для следующей hotzone перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Ошибка при записи метаданных устойчивости перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Не удалось расшифровать."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Не удалось записать область hotzone начиная с %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Ошибка синхронизации данных."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Ошибка при обновлении метаданных после завершения текущей hotzone перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Ошибка при записи метаданных LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Ошибка при затирании неиспользуемой области данных устройства."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Ошибка при удалении неиспользуемого (непривязанного) слота ключа %d."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Ошибка при удалении слота ключа перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Критическая ошибка при перешифровании куска начиная с %<PRIu64>, длиной в %<PRIu64> секторов."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Оперативное перешифрование завершилось ошибкой."
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Устройство не возобновит работу пока не будет заменено вручную с целью error."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Невозможно продолжить с перешифрованием. Неожиданное состояние перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Контекст перешифрования отсутствует или неверен."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Ошибка при инициализации стека устройства перешифрования."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Ошибка при обновлении контекста перешифрования."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Некорректные метаданные перешифрования."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Параметры шифрования слота ключа могут задаваться только для устройства LUKS2."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Введите PIN токена: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Введите %d PIN токена: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Обнаружено указание неизвестного шаблона шифра."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: параметр --hash игнорируется в режиме plain с указанным файлом ключа.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: параметр --keyfile-size игнорируется, размер для чтения приравнивается размеру ключа шифрования.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Обнаружены подпись(и) устройства на %s. Продолжение работы может повредить существующие данные."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "Операция прервана.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Параметр --key-file является обязательным."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Введите VeraCrypt PIM: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Недопустимое значение PIM: ошибка при разборе."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Недопустимое значение PIM: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Недопустимое значение PIM: вышло за границы диапазона."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "С этой парольной фразой заголовка устройства не обнаружено."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Устройство %s не является корректным устройством BITLK."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Невозможно определить размер ключа тома BITLK, укажите параметр --key-size."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Дамп заголовка с ключом тома является секретной информацией,\n"
+"обеспечивающей доступ к зашифрованному разделу без парольной фразы.\n"
+"Этот дамп следует всегда хранить зашифрованным в надёжном месте."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Дамп заголовка с ключом тома является секретной информацией,\n"
+"обеспечивающей доступ к зашифрованному разделу без парольной фразы.\n"
+"Этот дамп нужно хранить зашифрованным в надёжном месте."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Устройство %s не является корректным устройством FVAULT2."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Невозможно определить размер ключа тома FVAULT2, укажите параметр --key-size."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Устройство %s всё ещё активно и запланировано к отложенному удалению.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Для изменения размера активного устройства требуется ключ тома в связке ключей, но указан параметр --disable-keyring."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Оценка производительности прервана."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s Н/Д\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u итераций в секунду для %zu-битного ключа\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s Н/Д\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u итераций, %5u памяти, %1u параллельных нитей (ЦП) для %zu-битного ключа (запрашивался %u мс)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Результат оценки производительности ненадёжен."
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Тесты, использующие практически только память (без ввода-вывода на хранилище).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Алгоритм | Ключ | Шифрование | Расшифровка\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Шифр %s (%i-битный ключ) недоступен."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr ""
+"# Algorithm | Key | Encryption | Decryption\n"
+"# Алгоритм | Ключ | Шифрование | Расшифровка\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "Н/Д"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Обнаружены незащищённые метаданные перешифрования LUKS2. Убедитесь,\n"
+"что операция перешифрования желательна (смотрите вывод luksDump) и продолжайте\n"
+"(обновление метаданных) только, если это действительно ваше решение."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Введите пароль защиты и обновления метаданных перешифрования: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Действительно продолжить восстановление перешифрования LUKS2?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Введите пароль проверки дайджеста перешифрования метаданных: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Введите пароль восстановления перешифрования: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Действительно попробовать восстановить заголовок устройства LUKS?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Затирание прервано."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Затирается устройство для инициализации целостности контрольной суммы.\n"
+"Вы можете прервать процесс нажав CTRL+c (остаток незатёртого устройства будет содержать некорректную контрольную сумму).\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Невозможно деактивировать временное устройство %s."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Параметр целостности можно использовать только в формате LUKS2."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Неподдерживаемый размер параметров метаданных LUKS2."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Файл заголовка не существует, создать?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Невозможно создать файл заголовка %s."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Обнаружено указание неизвестного шаблона целостности."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Невозможно использовать %s в качестве заголовка для диска."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Данные на %s будут перезаписаны без возможности восстановления."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Ошибка при задании параметров pbkdf."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Сокращение смещения данных допускается только для отсоединённого заголовка LUKS."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "Файл контейнера LUKS %s слишком мал для активации, не хватает места для данных."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Невозможно определить размер ключа тома LUKS без слотов ключа, укажите параметр --key-size."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Устройство активировано, но нельзя сделать флаги постоянными."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Для удаления выбран слот ключа %d."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Это последний слот ключа. Устройство станет неработоспособным после вычистки этого ключа."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Введите любую оставшуюся парольную фразу: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Операция прервана, слот ключа НЕ затёрт.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Введите удаляемую парольную фразу: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Устройство %s не является корректным устройством LUKS2."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Введите новую парольную фразу для слота ключа: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: для нового номера слота ключа используется параметр --key-slot.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Введите любую существующую парольную фразу: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Введите изменяемую парольную фразу: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Введите новую парольную фразу: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Введите парольную фразу для преобразуемого слота ключа: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Только одно устройство можно указать для операции isLuks."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Слот ключа %d не содержит непривязанного ключа."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Дамп заголовка с непривязанным ключом является секретной информацией,\n"
+"обеспечивающей доступ к зашифрованному разделу без парольной фразы.\n"
+"Этот дамп нужно хранить зашифрованным в надёжном месте."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s не является именем активного устройства %s."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s не является именем активного устройства LUKS или отсутствует заголовок."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "Параметр --header-backup-file является обязательным."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s не является управляемым устройством cryptsetup."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Обновление не поддерживается для устройств типа %s"
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Нераспознанный тип метаданных устройства %s."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "Для команды требуется задать устройство и имя отображения."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Эта операция сотрёт все слоты ключей на устройстве %s.\n"
+"Устройство станет неработоспособным после этой операции."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Операция прервана, слоты ключа НЕ затёрты.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Некорректный тип LUKS, поддерживаются только luks1 и luks2."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Устройство уже имеет тип %s."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Данная операция преобразует формат %s в %s.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Операция прервана, устройство НЕ преобразовано.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Отсутствует параметр --priority, --label или --subsystem."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Некорректный токен %d."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Используется токен %d."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Ошибка при добавлении токена luks2-keyring %d."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Ошибка при назначении токена %d слоту ключа %d."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Токен %d не используется."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Ошибка при импорте токена из файла."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Ошибка при получении токена %d для экспорта."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Токен %d не назначен слоту ключа %d."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Ошибка при отмене назначения токена %d слоту ключа %d."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Параметр --tcrypt-hidden, --tcrypt-system или --tcrypt-backup поддерживается только для устройства TCRYPT."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Параметр --veracrypt или --disable-veracrypt поддерживается только для устройств с типом TCRYPT."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Параметр --veracrypt-pim поддерживается только для устройств, совместимых с VeraCrypt."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Параметр --veracrypt-query-pim поддерживается только для устройств, совместимых с VeraCrypt."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Параметры --veracrypt-pim и --veracrypt-query-pim взаимно исключают друг друга."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Параметр --persistent не допускается одновременно указывать с --test-passphrase."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Параметры --refresh и --test-passphrase взаимно исключают друг друга."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Параметр --shared допускается только для открытия устройства plain."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Параметр --skip поддерживается только для открытия устройств plain и loopaes."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Параметр --offset с действием open поддерживается только для устройств plain и loopaes."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Параметр --tcrypt-hidden нельзя указывать вместе с --allow-discards."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Параметр размера сектора с действием open поддерживается только для устройств plain."
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Параметр больших секторов IV поддерживается только для открытия устройств типа plain с размером сектора более 512 байт."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "Параметр --test-passphrase допускается только для открытия устройств LUKS, TCRYPT, BITLK и FVAULT2."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Параметры --device-size и --size не допускается указывать вместе."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Параметр --unbound допускается только для открытия устройства luks."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Параметр --unbound не допускается одновременно указывать с --test-passphrase."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Параметры --cancel-deferred и --deferred не могут быть использованы одновременно."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Параметры ---reduce-device-size и --data-size не допускается указывать вместе."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Параметр --active-name может задаваться только для устройства LUKS2."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Параметры --active-name и --force-offline-reencrypt не допускается указывать вместе."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Требуется указать слот ключа."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Параметры --align-payload и --offset не допускается указывать вместе."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Параметр --integrity-no-wipe можно использовать только для действия format с расширением целостности."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Разрешено использовать только один параметр --use-[u]random."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "С параметром --unbound требуется задать размер ключа."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "Некорректный токен действия."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Для добавления токена требуется параметр --key-description."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Для действия требуется указать токен. Используйте параметр --token-id."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "Параметр --unbound можно использовать только при добавлении."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Параметры --key-slot и --unbound не допускается указывать вместе."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "Для действия требуется указать слот ключа. Используйте параметр --key-slot."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<устройство> [--type <тип>] [<имя>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "открыть устройство как <имя>"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<имя>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "закрыть устройство (удалить отображение)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "изменить размер активного устройства"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "показать состояние устройства"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <шифр>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "оценка производительности шифра"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<устройство>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "попытаться исправить метаданные на диске"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "перешифровать устройство LUKS2"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "стереть все слоты ключей (удалить ключ шифрования)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "преобразовать LUKS из/в формат LUKS2"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "задать постоянные параметры настройки LUKS2"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<устройство> [<новый файл ключа>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "форматировать устройство LUKS"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "добавить ключ к устройству LUKS"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<устройство> [<файл ключа>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "удалить заданный ключ или файл ключа с устройства LUKS"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "изменить заданный ключ или файл ключа устройства LUKS"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "преобразовать ключ в новые параметры pbkdf"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<устройство> <слот ключа>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "затереть ключ с номером <слот ключа> с устройства LUKS"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "напечатать UUID устройства LUKS"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "проверить <устройство> на наличие заголовка раздела LUKS"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "выгрузить в дамп информацию о разделе LUKS"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "выгрузить в дамп информацию об устройстве TCRYPT"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "выгрузить в дамп информацию об устройстве BITLK"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "выгрузить в дамп информацию об устройстве FVAULT2"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Приостановить устройство LUKS и затереть ключ (заморозка операций ввода-вывода)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "Возобновить работу приостановленного устройства LUKS"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Сделать резервную копию заголовка и слотов ключей устройства LUKS"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Восстановить заголовок и слоты ключей устройства LUKS"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <устройство>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "Управление токенами LUKS2"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<действие> может быть:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Также можно использовать псевдонимы старого синтаксиса <действия>:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<имя> - имя устройства для создания под %s\n"
+"<устройство> - зашифрованное устройство\n"
+"<слот ключа> - номер слота ключа LUKS для изменения\n"
+"<файл ключа> - необязательный файл ключа для нового ключа для действия luksAddKey\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Встроенным форматом по умолчанию для метаданных является %s (для действия luksFormat).\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Модуль поддержки внешнего токена LUKS2 %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "скомпилирован"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Путь к модулю поддержки внешнего токена LUKS2: %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "выключен"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Встроенные параметры ключа и парольной фразы по умолчанию:\n"
+"\tМаксимальный размер файла ключа: %dКБ, Максимальная длина парольной фразы при вводе вручную: %d (символов)\n"
+"PBKDF по умолчанию для LUKS1: %s, Время итерации: %d (мс)\n"
+"PBKDF по умолчанию для LUKS2: %s\n"
+"\tВремя итерации: %d, Требуемая память: %dКБ, Кол-во параллельных нитей: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Встроенные параметры шифра по умолчанию:\n"
+"\tloop-AES: %s, Ключ: %d бит\n"
+"\tplain: %s, Ключ: %d бит, хэширование пароля: %s\n"
+"\tLUKS: %s, Ключ: %d бит, хэширование заголовка LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: Размер ключа по умолчанию в режиме XTS (два внутренних ключа) будет удвоен.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: требуется %s в качестве аргументов"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Некорректный слот ключа."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Размер устройства должен быть кратен 512 байтовому сектору."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Неправильный максимальный размер перешифрования hotzone."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Размер ключа должен быть кратен 8-ми битам"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Максимальный размер сокращения устройства равен 1 ГиБ."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Размер сокращения должен быть кратен 512 байтовому сектору."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Значением параметра --priority может быть только ignore/normal/prefer."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Показать это сообщение"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Показать краткие инструкции"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Показать версию пакета"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Параметры справки:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[ПАРАМЕТР…] <действие> <данные для действия>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Не задан параметр <действие>."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Неизвестное действие."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Параметр --key-file имеет приоритет над указанным значением файла ключа."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Разрешено указывать только один параметр --key-file."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Производной функцией на основе пароля для ключа (PBKDF) может быть только pbkdf2 или argon2i/argon2id."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Принудительные итерации PBKDF нельзя объединять вместе с параметром времени итерации."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Параметры --keyslot-cipher и --keyslot-key-size нельзя использовать вместе."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Без выполнения. Вызвано с параметром --test-args.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Невозможно выключить блокировку метаданных."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Указана недопустимая строка соли."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Невозможно создать образ хэша %s для записи."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Невозможно создать образ FEC %s для записи."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Невозможно создать файл корневого хэша %s для записи."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Невозможно записать файл корневого хэша %s."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Устройство %s не является корректным устройством VERITY."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Невозможно прочитать файл корневого хэша %s."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Некорректный файл корневого хэша %s."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "Указана недопустимая строка корневого хэша."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Неверный файл подписи %s."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Невозможно прочитать файл подписи %s."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Для параметра <корневой_хэш> или --root-hash-file требуется указать команду."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<устройство_данных> <устройство_хэша>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "отформатировать устройство"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<устройство_данных> <устройство_хэша> [<корневой_хэш>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "проверить устройство"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<устройство_данных> <имя> <устройство_хэша> [<корневой_хэш>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "показать состояние активного устройства"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<устройство_хэша>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "показать информацию на диске"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<имя> — устройство, создаваемое на %s\n"
+"<устройство_данных> — устройство данных\n"
+"<устройство_хэша> — устройство, содержащее проверочные данные\n"
+"<корневой_хэш> — хэш корневого узла на <устройстве_хэша>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Встроенные параметры dm-verity по умолчанию:\n"
+"\tХэш: %s, Блок данных (байт): %u, Блок хэша (байт): %u, Размер соли: %u, Формат хэша: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Параметры --ignore-corruption и --restart-on-corruption нельзя использовать вместе."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Параметры ---panic-on-corruption и --restart-on-corruption нельзя использовать вместе."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Будут перезаписаны данные на %s и %s необратимо.\n"
+"Чтобы сохранить данные на устройстве укажите параметр --no-wipe\n"
+"(и он включит --integrity-recalculate)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Отформатирован с размером тега %u, внутренняя целостность %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Задание флага пересчёта не поддерживается, вместо этого используйте параметр --wipe."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Устройство %s не является корректным устройством INTEGRITY."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<устройство_целостности>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<устройство_целостности> <имя>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<имя> — устройство, создаваемое на %s\n"
+"<устройство_целостности> — устройство, содержащее данные с тегами целостности\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Встроенные параметры dm-integrity:\n"
+"\tАлгоритм контрольной суммы: %s\n"
+"\tМаксимальный размер файла ключа: %dКБ\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Неверный размер --%s. Максимальное значение (в байтах) равно %u."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Должны быть указаны параметры файла ключа и размер ключа одновременно."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Должны быть указаны параметры файла ключа целостности и размер ключа одновременно."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Если используется ключ целостности журнала, то должен быть указан алгоритм целостности журнала."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Должны быть указаны параметры файла ключа шифрования и размер ключа одновременно."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Если используется ключ шифрования журнала, то должен быть указан алгоритм шифрования журнала."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Параметры восстановления и режима битовой карты взаимно исключают друг друга."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Параметры журнала нельзя использовать в режиме битовой карты."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Параметр битовой карты можно использовать только в режиме битовой карты."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"ПРЕДУПРЕЖДЕНИЕ!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Вы уверены? (введите «yes» заглавными буквами): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Ошибка чтения ответа с терминала."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Команда выполнена успешно."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "некорректные или отсутствующие параметры"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "нет прав или некорректная парольная фраза"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "недостаточно памяти"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "указано некорректное устройство или файл"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "устройство уже существует или занято"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "неизвестная ошибка"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Сбой команды, код %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Создан слот ключа %i."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Слот ключа %i разблокирован."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Слот ключа %i удалён."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Создан токен %i."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Токен %i удалён."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "С этим PIN невозможно разблокировать токен."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Для токена %i требуется PIN."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Для токена (тип %s) требуется PIN."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Токен %i невозможно разблокировать назначенным слотом ключа (некорректная парольная фраза для слота ключа)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Токен (тип %s) невозможно разблокировать назначенным слотом ключа (некорректная парольная фраза для слота ключа)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Для токена %i дополнительно требуется отсутствующий ресурс."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Для токена (тип %s) дополнительно требуется отсутствующий ресурс."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Не найдено подходящего токена (тип %s)."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Не найдено подходящего токена."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Невозможно прочитать файл ключа %s."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Невозможно прочитать %d байт из файл ключа %s."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Невозможно открыть файл ключа %s для записи."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Невозможно записать в файл ключа %s."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>м%02<PRIu64>с"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>ч%02<PRIu64>м%02<PRIu64>с"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> дней"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> %s записано"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "скорость %5.1f %s/с"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Ход выполнения: %5.1f%%, ОВЗ %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Выполнено, время %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Невозможно проверить стойкость пароля: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Ошибка при проверке стойкости пароля:\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Ошибка при проверке стойкости пароля: некорректная парольная фраза (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "Ошибка чтения парольной фразы с терминала."
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "Парольная фраза повторно: "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "Парольные фразы не совпадают."
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "Невозможно использовать смещение при вводе с терминала."
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Введите парольную фразу: "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Введите парольную фразу для %s: "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "Ключ недоступен с этой парольной фразой."
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "Не найдено подходящего слота ключа."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Невозможно проверить парольную фразу не с входных tty."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Ошибка при открытии файла %s в режиме только для чтения."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Укажите корректный токен LUKS2 в формате JSON:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Ошибка чтения файла JSON."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Чтение прервано."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Ошибка при открытии файла %s в режиме записи."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Запись прервана."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Ошибка записи в файл JSON."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Автоматически обнаруженное активное устройство dm «%s» для устройства данных %s.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Не удалось автоматически обнаружить держателей устройства %s."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Устройство %s не является блочным.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Невозможно понять, активно устройство %s или нет.\n"
+"Вы действительно хотите продолжить перешифрование в отложенном режиме?\n"
+"Это может привести к потере данных, если устройство всё же активно.\n"
+"Для запуска перешифрования в оперативном режиме укажите параметр --active-name.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Устройство %s не является блочным. Невозможно автоматически определить активно\n"
+"оно или нет. Используйте --force-offline-reencrypt чтобы пропустить проверку и\n"
+"запустить отложенный режим (опасно!)."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Запрошенный параметр --resilience не может быть применён к текущей операции перешифрования."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Устройство зашифровывается не в LUKS2. Конфликт с параметром --encrypt."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Устройство расшифровывается не в LUKS2. Конфликт с параметром --dencrypt."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Устройство перешифровывается с использованием устойчивости datashift. Запрошенный параметр --resilience не может быть применён."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Устройству требуется восстановление перешифрования. Сначала запустите ремонт."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Устройство %s уже в режиме перешифрования LUKS2. Хотите продолжить предыдущую операцию инициализации?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Устаревшее перешифрование LUKS2 больше не поддерживается."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Перешифрование устройства с профилем целостности не поддерживается."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Запрошенный --sector-size %<PRIu32> несовместим с суперблоком %s\n"
+"(размер блока: %<PRIu32> байт), который обнаружен на устройстве %s."
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Шифрование без отсоединённого заголовка (--header) невозможно без сокращения размера устройства данных (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Запрошенное смещение данных должно быть меньше или равно половине значения параметра --reduce-device-size."
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Подгоняется значение --reduce-device-size под двукратный размер --offset %<PRIu64> (секторов).\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Временный файл заголовка %s уже существует. Прекращение работы."
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Невозможно создать временный файл заголовка %s."
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Размер метаданных LUKS2 больше значения сдвига данных."
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Не удалось поместить новый заголовок в начало устройства %s."
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s теперь активен и готов для оперативного шифрования.\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Активное устройство %s не является LUKS2."
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "Восстановление первоначального заголовка LUKS2."
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "Не удалось восстановить первоначальный заголовок LUKS2."
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Файл заголовка %s не существует. Инициализировать расшифровку LUKS2 с устройства %s и экспортировать заголовок LUKS2 в файл %s?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Не удалось добавить/записать права в экспортируемый файл заголовка."
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Ошибка при инициализации перешифрования. Резервный заголовок доступен в %s."
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "Расшифровка LUKS2 поддерживается только для устройства с отсоединённым заголовком (смещение данных равно 0)."
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "Для шифрования недостаточно свободных слотов ключей."
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Файл ключа можно использовать только с --key-slot или только при одном активном слоте."
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Введите парольную фразу для слота ключа %d: "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Введите парольную фразу для слота ключа %u: "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Переходим на алгоритм шифрования данных %s.\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Параметры сегмента данные не изменились. Перешифрование прервано."
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Увеличение размера сектора шифрования на выключенном устройстве не поддерживается.\n"
+"Сначала включите устройство или используйте параметр --force-offline-reencrypt (опасно!)."
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Перешифрование прервано."
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Продолжение перешифрования LUKS в принудительном отложенном режиме.\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Устройство %s содержит повреждённые метаданные LUKS. Прерывание операции."
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Устройство %s уже является устройством LUKS. Прерывание операции."
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Устройство %s уже находится в режиме перешифрования LUKS. Прерывание операции."
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "Для расшифровки LUKS2 требуется параметр --header."
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "Для команды требуется в аргументе указать устройство."
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Конфликтующие версии. Устройство %s использует LUKS1."
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Конфликтующие версии. Устройство %s в режиме перешифрования LUKS1."
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Конфликтующие версии. Устройство %s использует LUKS2."
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Конфликтующие версии. Устройство %s в режиме перешифрования LUKS2."
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Перешифрование LUKS2 уже инициализировано. Прекращение работы."
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "Перешифрование устройства в данный момент не выполняется."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Невозможно монопольно открыть устройство %s, оно уже используется."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Не удалось выделить выровненную память."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Невозможно прочитать с устройства %s."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Отметка устройства LUKS1 %s бесполезна."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Невозможно записать на устройство %s."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Невозможно записать в файл протокола перешифрования."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Невозможно прочитать файл протокола перешифрования."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Неверный формат журнала."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Файл протокола %s существует, подразумевается перешифрование.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Активируется временное устройство, задействуется старый заголовок LUKS."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Активируется временное устройство, задействуется новый заголовок LUKS."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Ошибка при активации временного устройства."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Не удалось задать смещение данных."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Не удалось задать размер метаданных."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Создан новый заголовок LUKS для устройства %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Создана резервная копия заголовка %s для устройства %s."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Ошибка при создании резервных копий заголовка LUKS."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Невозможно восстановить заголовок %s устройства %s."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Заголовок %s устройства %s восстановлен."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Невозможно открыть временное устройство LUKS."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Невозможно получить размер устройства."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "Ошибка ввода-вывода при перешифровании."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Указан некорректный UUID."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Невозможно открыть файл протокола перешифрования."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Расшифровка не выполняется, указанный UUID можно использовать только для возобновления приостановленного процесса расшифровки."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Перешифрование изменит: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "ключ тома"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "установить хэш равным"
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", установить шифр равным"
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: Устройство %s уже содержит подпись раздела «%s».\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "ПРЕДУПРЕЖДЕНИЕ: Устройство %s уже содержит подпись суперблока «%s».\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Ошибка при инициализации определения подписей устройства."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Ошибка выполнения stat для устройства %s."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Ошибка при открытии файла %s в режиме чтения-записи."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Существующая подпись раздела «%s» на устройстве %s будет затёрта."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Существующая подпись суперблока «%s» на устройстве %s будет затёрта."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Ошибка при затирании подписи устройства."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Ошибка при определении подписи устройства %s."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Неправильный формат размера в параметре --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Параметр --%s не допускается одновременно указывать с действием %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Ошибка записи ssh-токена json."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Экспериментальный модуль cryptsetup для разблокировки устройств LUKS2 токеном\n"
+"с подключённого сервера SSH. В настоящее время этот модуль\n"
+"позволяет только добавление токена в существующий слот ключа.\n"
+"\n"
+"Указываемый сервер SSH должен содержать файл ключа в задаваемом пути\n"
+"с парольной фразой для существующего слота ключа на устройстве.\n"
+"Предоставленные идентификационные данные будут использованы cryptsetup для\n"
+"получения пароля при открытии устройства с помощью токена.\n"
+"\n"
+"Замечание: при добавлении токена предоставляемая информация (адрес сервера\n"
+"SSH, пользователь и пути) будет сохранена в заголовке LUKS2 в открытом виде."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<действие> <устройство>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Параметры для действия «add»:"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "IP-адрес/URL удалённого сервера для этого токена"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Имя пользователя, используемого на удалённом сервере"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Путь к файлу ключа на удалённом сервере"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Путь к ключу SSH для подключения к удалённому серверу"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Слот ключа, назначаемого токену. Если не указан, то токен будет назначен в первый слот ключа, который соответствует парольной фразе."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Общие параметры:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Показывать подробные сообщения об ошибках"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Показывать отладочные сообщения"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Показывать отладочные сообщения включая метаданные JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Ошибка при открытии и импорте закрытого ключа:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Ошибка при импорте закрытого ключа (защищён паролем?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Пароль к %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Не удалось разобрать аргументы.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Должно быть указано действие\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Для действия «%s» должно быть указано устройство.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Для действия «%s» должен быть указан сервер SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Для действия «%s» должен быть указан пользователь сервера SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Для действия «%s» должен быть указан путь на сервере SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Для действия «%s» должен быть указан путь к ключу сервера SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Не удалось открыть %s с помощью предоставленных идентификационных данных.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "В настоящее время этот модуль поддерживает только действие «add».\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Не удалось создать сеанс sftp: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Не удалось инициализировать сеанс sftp: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Не удалось открыть сеанс sftp: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Не удалось выполнить функцию stat для файла по sftp: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Недостаточно памяти.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Не удалось прочитать удалённый ключ: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Сбой подключения: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Неизвестный сервер: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Способ аутентификации по открытому ключу запрещён на узле.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Ошибка при аутентификации по открытому ключу: "
+
+#~ msgid "WARNING: Data offset is outside of currently available data device.\n"
+#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: смещение данных находится за пределами доступного в данный момент устройства данных.\n"
+
+#~ msgid "Cannot get process priority."
+#~ msgstr "Невозможно получить приоритет процесса."
+
+#~ msgid "Cannot unlock memory."
+#~ msgstr "Невозможно разблокировать память."
+
+#~ msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+#~ msgstr "Будет создан блокирующий каталог %s/%s с правами по умолчанию, заданными при сборке программы."
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Ошибка чтения подписи BITLK из %s."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Некорректная или неизвестная подпись устройства BITLK."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Ошибка при затирании резервной копии сегмента данных."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Не удалось выключить флаг требования перешифрования."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Шифрование поддерживается только для формата LUKS2."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "На %s обнаружено устройство LUKS. Хотите снова зашифровать это устройство LUKS?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "В настоящий момент поддерживается только формат LUKS2. Для LUKS1 используйте программу cryptsetup-reencrypt."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Уже выполняется устаревшее внесистемное (offline) перешифрование. Используйте программу cryptsetup-reencrypt."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "Устройство LUKS2 не перешифровывается."
+
+#~ msgid "Reencryption already in-progress."
+#~ msgstr "Уже выполняется перешифрование."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "Установка внесистемного (offline) флага перешифрования LUKS2 на устройстве %s."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Эта версия cryptsetup-reencrypt не работает с новым типом внутреннего токена %s."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Ошибка чтения флагов активации из резервной копии заголовка."
+
+#~ msgid "Failed to read requirements from backup header."
+#~ msgstr "Ошибка чтения требований из резервной копии заголовка."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "Изменённые параметры pbkdf в слоте ключа %i."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Значение размера блока перешифрования должно быть в диапазоне от 1 МиБ до 64 МиБ."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "Максимальный размер сокращения устройства равен 64 МиБ."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[ПАРАМЕТР…] <устройство>"
+
+#~ msgid "Argument required."
+#~ msgstr "Требуется аргумент."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "Параметр --new должен использоваться вместе с --reduce-device-size или --header."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "Параметр --keep-key можно использовать только с --hash, --iter-time или --pbkdf-force-iterations."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "Параметр --new нельзя использовать вместе с --decrypt."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "Параметр --decrypt несовместим с указанными параметрами."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "Параметр --uuid можно использовать только вместе с --decrypt."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Некорректный тип luks. Возможные значения: «luks», «luks1» или «luks2»."
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Устройство %s уже используется. Невозможно продолжить выполнение операции форматирования."
+
+#~ msgid "No free token slot."
+#~ msgstr "Нет свободного слота под токен."
+
+#~ msgid "Failed to create builtin token %s."
+#~ msgstr "Ошибка при создании встроенного токена %s."
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Неверный тип устройства LUKS."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Шифр, используемый для шифрования диска (смотрите /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Хэш, используемый для создания ключа шифрования из парольной фразы"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Проверить правильность парольной фразы, запрашивая её дважды"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Прочитать ключ из файла"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Прочитать (главный) ключ тома из файла."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Создать дамп (главного) ключа, а не информации слотов ключей"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Размер ключа шифрования"
+
+#~ msgid "BITS"
+#~ msgstr "БИТ"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Ограничить чтение из файла ключа"
+
+#~ msgid "bytes"
+#~ msgstr "байт"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Количество пропускаемых байтов в файле ключа"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Ограничить чтение из только что добавленного файла ключа"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Количество пропускаемых байтов в только что добавленном файле ключа"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Номер слота для нового ключа (по умолчанию первый свободный)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Размер устройства"
+
+#~ msgid "SECTORS"
+#~ msgstr "СЕКТОРОВ"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Использовать только заданный размер устройства (игнорировать остаток устройства). ОПАСНО!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Начальное смещение в нижележащем (backend) устройстве"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Сколько секторов зашифрованных данных пропускать от начала"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Создать отображение в режиме только для чтения"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Не запрашивать подтверждение"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Время ожидания при ручном вводе парольной фразы (в секундах)"
+
+#~ msgid "secs"
+#~ msgstr "сек"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Обновление строки хода выполнения (в секундах)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Как часто можно повторять попытку ввода парольной фразы"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Выравнивать полезные данные по границам <n> секторов — для luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Файл резервной копии заголовка и слотов ключей LUKS"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Использовать /dev/random для генерации ключа тома"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Использовать /dev/urandom для генерации ключа тома"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Совместно использовать устройство с другим неперекрывающимся шифрованным сегментом"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "Используемый для устройства UUID"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Разрешить отбрасывать запросы (так называемые TRIM) к устройству"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Устройство или файл с отдельным заголовком LUKS"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Не активировать устройство, только проверить парольную фразу"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Использовать скрытый заголовок (спрятанное устройство TCRYPT)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Устройство является системным диском TCRYPT (с загрузчиком)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Использовать резервный (вторичный) заголовок TCRYPT"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Также искать устройство совместимое с VeraCrypt"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Персональный умножитель итерации для устройства, совместимого с VeraCrypt"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Запрос персонального умножителя итерации для устройства, совместимого с VeraCrypt"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Тип метаданных устройства: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Выключить проверку качество пароля (если включена)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Использовать параметр производительности same_cpu_crypt для dm-crypt"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Использовать параметр производительности submit_from_crypt_cpus для dm-crypt"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Пропускать dm-crypt workqueue и обрабатывать запросы чтения одновременно"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Пропускать dm-crypt workqueue и обрабатывать запросы записи одновременно"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "Удаление устройства отложено, пока его не закроет последний пользователь"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Использовать глобальную блокировку для сериализации доступа на скорости памяти (memory-hard) PBKDF (для обхода OOM)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "Время итерации PBKDF для LUKS (в мс)"
+
+#~ msgid "msecs"
+#~ msgstr "мс"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "Алгоритм PBKDF (для LUKS2): argon2i, argon2id, pbkdf2"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "Ограничение стоимости памяти PBKDF"
+
+#~ msgid "kilobytes"
+#~ msgstr "килобайт"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "Стоимость параллельности PBKDF"
+
+#~ msgid "threads"
+#~ msgstr "нити"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "Стоимость итераций PBKDF (принудительная, оценка производительности отключена)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Приоритет слота ключа: ignore, normal, prefer"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Выключить блокировку метаданных на диске"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Выключить загрузку ключей томов через связку ключей ядра"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Алгоритм целостности данных (только для LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Выключить журналирование для устройства целостности"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Не затирать устройство после форматирования"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Использовать неэффективное устаревшее дополнение (старые ядра)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Не запрашивать парольную фразу, если активация токеном завершилась ошибкой"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Номер токена (по умолчанию: любой)"
+
+#~ msgid "Key description"
+#~ msgstr "Описание ключа"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Размер сектора шифрования (по умолчанию: 512 байт)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Использовать вычисленное IV как размер сектора (не 512 байт)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Задать набор постоянных флагов активации устройства"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Задать метку устройства LUKS2"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Задать метку подсистемы устройства LUKS2"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Создать или сделать дапм непривязанного (без назначенного сегмента данных) слота ключа LUKS2"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Прочитать или записать json в файл"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Размер области метаданных заголовка LUKS2"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Размер области слотов ключей заголовка LUKS2"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Обновить (реактивировать) устройство с новыми параметрами"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "Слот ключа LUKS2: Размер ключа шифрования"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "Слот ключа LUKS2: Шифр, используемый для шифрования слота ключа"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Зашифровать устройство LUKS2 (шифрование по месту (in-place))"
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Расшифровать устройство LUKS2 (удалить шифрование)"
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Инициализировать перешифрование LUKS2 только метаданных."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Возобновить только инициализированное перешифрование LUKS2."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Сократить размер данных устройства (переместить смещение данных). ОПАСНО!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Максимальный размер hotzone перешифрования."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Тип устойчивости перешифрования hotzone (checksum,journal,none)"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Контрольные хэш-суммы hotzone перешифрования"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Заменить автоопределение устройства dm для перешифруемого устройства"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "Параметр --deferred допускается только для команды close."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "Параметр --allow-discards допускается только для операции open."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "Параметр --persistent допускается только для операции open."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "Параметр --serialize-memory-hard-pbkdf допускается только для операции open."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Параметр --key-size допускается только для luksFormat, luksAddKey,\n"
+#~ "действий open и benchmark. Для ограничения чтения из файла ключа используйте --keyfile-size=(байт)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "Параметр --integrity допускается только для luksFormat (LUKS2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Параметры --label и --subsystem допускаются только для операций LUKS2 luksFormat и config."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "В параметре нельзя использовать отрицательные числа."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "Параметр --use-[u]random допускается только для luksFormat."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "Параметр --uuid допускается только для luksFormat и luksUUID."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "Параметр --align-payload допускается только для luksFormat."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Параметры --luks2-metadata-size и --opt-luks2-keyslots-size допускаются только для операции luksFormat с LUKS2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Неправильно указан размер метаданных LUKS2."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Неправильно указан размер слота ключа LUKS2."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "Параметр --offset поддерживается только для открытия устройств plain и loopaes, luksFormat и перешифрования устройства."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Указано некорректное значение параметра --veracrypt-pim."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "Параметр размера сектора не поддерживается этой командой."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "Параметр --refresh можно использовать только при действии open."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "Неправильно указан размер устройства."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Переполнение размера сокращения."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Не использовать проверочный суперблок"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Тип форматирования (1 - обычное, 0 - как в Chrome OS)"
+
+#~ msgid "number"
+#~ msgstr "число"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Размер блока устройства данных"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Размер блока устройства хэша"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "байты чётности FEC"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Количество блоков в файле данных"
+
+#~ msgid "blocks"
+#~ msgstr "блоков"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Путь к устройству с данными коррекции ошибок"
+
+#~ msgid "path"
+#~ msgstr "путь"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Начальное смещение на устройстве хэша"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Начальное смещение на устройстве FEC"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Алгоритм хэширования"
+
+#~ msgid "string"
+#~ msgstr "строка"
+
+#~ msgid "Salt"
+#~ msgstr "Соль"
+
+#~ msgid "hex string"
+#~ msgstr "шестн. строка"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Путь к файлу с подписью корневого хэша"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Перезапустить ядро, если обнаружится повреждение"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Включить панику в ядре, если обнаружится повреждение"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Игнорировать повреждение, только запротоколировать"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Не проверять обнулённые блоки"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Проверять блок данных только при первом чтении"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Параметр --ignore-corruption, --restart-on-corruption или --ignore-zero-blocks допускается только для операции open."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "Параметр --root-hash-signature можно использовать только для действия open."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Путь к устройству данных (при разделении устройств)"
+
+#~ msgid "Journal size"
+#~ msgstr "Размер журнала"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Чередующиеся секторы"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Отметка журнала"
+
+#~ msgid "percent"
+#~ msgstr "процент"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Время фиксации журнала"
+
+#~ msgid "ms"
+#~ msgstr "мс"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Количество 512-байтовых секторов на бит (режим битовой карты)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Время стирания в режиме битовой карты"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Размер тега (на сектор)"
+
+#~ msgid "Sector size"
+#~ msgstr "Размер сектора"
+
+#~ msgid "Buffers size"
+#~ msgstr "Размер буфера"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Алгоритм целостности данных"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Размер ключа целостности данных"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Прочитать ключ целостности из файла"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Алгоритм целостности журнала"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Размер ключа целостности журнала"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Прочитать ключ целостности журнала из файла"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Алгоритм шифрования журнала"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Размер ключа шифрования журнала"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Прочитать ключ шифрования журнала из файла"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Режим восстановления (без проверки журнала и тегов)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Использовать битовую карту для отслеживания изменений и выключить журналирование для устройства целостности"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Автоматически пересчитывать начальные теги."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Не защищать суперблок с помощью HMAC (старые ядра)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Разрешить пересчёт томов с помощью ключей HMAC (старые ядра)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "Параметр --integrity-recalculate можно использовать только для действия open."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Параметры --journal-size, --interleave-sectors, --sector-size, --tag-size и --no-wipe можно использовать только для действия format."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "Неправильное задание размера журнала."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Размер блока перешифрования"
+
+#~ msgid "MiB"
+#~ msgstr "МиБ"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Не изменять ключ, нет области перешифрования данных"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Прочитать новый (главный) ключ тома из файла"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Использовать direct-io для доступа к устройствам"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Вызывать fsync после каждого блока"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Обновлять файл протокола после каждого блока"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Использовать только этот слот (остальные будут выключены)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Создать новый заголовок на не шифрованном устройстве"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Окончательно расшифровать устройство (удалить шифрование)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "Используемый для возобновления шифрования UUID"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Тип метаданных LUKS: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: Каталог блокировки %s/%s отсутствует!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Неправильный размер параметров для устройства verity."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "Если используется ключ целостности, то должен быть указан алгоритм целостности."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Неверный размер ключа."
+
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands."
+#~ msgstr "Параметр --refresh допускается только с командами open и refresh."
+
+#~ msgid "Unsupported encryption sector size.\n"
+#~ msgstr "Неподдерживаемый размер сектора шифрования.\n"
+
+#~ msgid "Offline reencryption in progress. Aborting."
+#~ msgstr "Ведётся внесистемное (offline) перешифрование. Прерываемся."
+
+#~ msgid "Online reencryption in progress. Aborting."
+#~ msgstr "Ведётся оперативное (online) перешифрование. Прерываемся."
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Прервано сигналом."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "Функция не доступна в режиме FIPS."
+
+#~ msgid "Failed to finalize hash."
+#~ msgstr "Ошибка завершения хэша."
+
+#~ msgid "Invalid resilience parameters (internal error)."
+#~ msgstr "Неправильные параметры устойчивости (внутренняя ошибка)."
+
+#~ msgid "Failed to assign new enc segments."
+#~ msgstr "Ошибка при назначении новых сегментов enc."
+
+#~ msgid "Failed to assign digest %u to segment %u."
+#~ msgstr "Ошибка при назначении дайджеста %u в сегмент %u."
+
+#~ msgid "Failed to assign reencrypt previous backup segment."
+#~ msgstr "Ошибка при назначении предыдущей резервной копии сегмента reencrypt."
+
+#~ msgid "Failed to assign reencrypt final backup segment."
+#~ msgstr "Ошибка при назначении конечной резервной копии сегмента reencrypt."
+
+#~ msgid "Failed generate 2nd segment."
+#~ msgstr "Ошибка при генерации 2-го сегмента."
+
+#~ msgid "Failed generate 1st segment."
+#~ msgstr "Ошибка при генерации 1-го сегмента."
+
+#~ msgid "Failed to allocate device %s."
+#~ msgstr "Ошибка при выделении устройства %s."
+
+#~ msgid "Failed to allocate dm segments."
+#~ msgstr "Ошибка при выделении сегментов dm."
+
+#~ msgid "Failed to create dm segments."
+#~ msgstr "Ошибка при создании сегментов dm."
+
+#~ msgid "Failed to allocate device for new backing device."
+#~ msgstr "Ошибка при выделении устройства для нового опорного устройства."
+
+#~ msgid "Failed to reload overlay device %s."
+#~ msgstr "Ошибка при перезагрузке оверлейного устройства %s."
+
+#~ msgid "Failed to refresh helper devices."
+#~ msgstr "Не удалось обновить вспомогательное устройство %s."
+
+#~ msgid "Failed to create reencryption backup segments."
+#~ msgstr "Ошибка при создании резервных сегментов перешифрования."
+
+#~ msgid "Failed to set online-reencryption requirement."
+#~ msgstr "Ошибка при задании требований оперативного перешифрования."
+
+#~ msgid "Failed to hash sector at offset %zu."
+#~ msgstr "Ошибка хэширования сектора по смещению %zu."
+
+#~ msgid "Failed to read sector hash."
+#~ msgstr "Ошибка чтения хэша сектора."
+
+#~ msgid "Error: Calculated reencryption offset %<PRIu64> is beyond device size %<PRIu64>."
+#~ msgstr "Ошибка: вычисленное смещение перешифрования %<PRIu64> находится за границей размера устройства %<PRIu64>."
+
+#~ msgid "Failed to calculate new segments."
+#~ msgstr "Ошибка при вычислении новых сегментов."
+
+#~ msgid "Failed finalize hotzone resilience, retval = %d"
+#~ msgstr "Ошибка завершения устойчивости hotzone, retval = %d"
+
+#~ msgid "Failed to write data."
+#~ msgstr "Ошибка записи данных."
+
+#~ msgid "Failed to update metadata or reassign device segments."
+#~ msgstr "Не удалось обновить метаданные или переназначить сегменты устройства."
+
+#~ msgid "Failed to reload %s device."
+#~ msgstr "Ошибка при перезагрузке устройства %s."
+
+#~ msgid "Failed to erase backup segments"
+#~ msgstr "Ошибка при стирании резервных копий сегментов."
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Запрошенные параметры производительности dmcrypt не поддерживаются."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "Невозможно отформатировать устройство %s, которое всё ещё используется."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "Слот ключа %d не используется."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "Для удаления выбрал слот ключа %d."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "открыть устройство как отображение с <именем>"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "закрыть устройство (деактивировать и удалить отображение)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "Ошибка при задании параметров PBKDF."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "Невозможно перемещаться по устройству.\n"
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+#~ msgstr "Устройство %s слишком маленькое (для LUKS2 требуется не менее %<PRIu64> байт)."
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "Ошибка 'memory allocation error' при выполнении action_luksFormat"
+
+#~ msgid "Cannot get info about device %s.\n"
+#~ msgstr "Невозможно получить информацию об устройстве %s.\n"
+
+#~ msgid "Device %s has zero size.\n"
+#~ msgstr "Устройство %s имеет нулевой размер.\n"
+
+#~ msgid "Device %s is too small.\n"
+#~ msgstr "Устройство %s слишком маленькое.\n"
+
+#~ msgid "Device %s already exists.\n"
+#~ msgstr "Устройство %s уже существует.\n"
+
+#~ msgid "Volume %s is not active.\n"
+#~ msgstr "Раздел %s не активен.\n"
+
+#~ msgid "Invalid key size.\n"
+#~ msgstr "Неверный размер ключа.\n"
+
+#~ msgid "Key slot %d is not used.\n"
+#~ msgstr "Ключевой слот %d не используется.\n"
+
+#~ msgid "Key slot %d is invalid.\n"
+#~ msgstr "Неправильный ключевой слот %d.\n"
+
+#~ msgid "Invalid device %s.\n"
+#~ msgstr "Неверное устройство %s.\n"
+
+#~ msgid "Volume key buffer too small.\n"
+#~ msgstr "Буфер ключей раздела слишком мал.\n"
+
+#~ msgid "Cannot read device %s.\n"
+#~ msgstr "Невозможно прочитать устройство %s.\n"
+
+#~ msgid "This operation is not supported for %s crypt device.\n"
+#~ msgstr "Данная операция не поддерживается для устройства шифрования %s.\n"
+
+#~ msgid "Device %s doesn't exist or access denied.\n"
+#~ msgstr "Устройство %s не существует или доступ к нему запрещён.\n"
+
+#~ msgid "Failed to open temporary keystore device.\n"
+#~ msgstr "Не удалось открыть устройство временного хранения ключей.\n"
+
+#~ msgid "Failed to access temporary keystore device.\n"
+#~ msgstr "Не удалось получить доступ к устройству временного хранения ключей.\n"
+
+#~ msgid "Cannot get process priority.\n"
+#~ msgstr "Невозможно получить приоритет процесса.\n"
+
+#~ msgid "Data offset or key size differs on device and backup, restore failed.\n"
+#~ msgstr "Смещение данных или размер ключа не совпадают на устройстве и в резервной копии, восстановление не удалось.\n"
+
+#~ msgid "Cannot open device %s.\n"
+#~ msgstr "Невозможно открыть устройство %s.\n"
+
+#~ msgid "Key slot %d is invalid, please select keyslot between 0 and %d.\n"
+#~ msgstr "Неверный ключевой слот %d, пожалуйста, выберите ключевой слот между 0 и %d.\n"
+
+#~ msgid "No key available with this passphrase.\n"
+#~ msgstr "Нет доступных ключей для данного пароля.\n"
+
+#~ msgid "Key slot %d unlocked.\n"
+#~ msgstr "Ключевой слот %d разблокирован.\n"
+
+#~ msgid "Key slot %d is full, please select another one.\n"
+#~ msgstr "Ключевой слот %d полон, пожалуйста, выберите другой.\n"
+
+#~ msgid "All key slots full.\n"
+#~ msgstr "Все ключевые слоты полны.\n"
+
+#~ msgid "Key slot %d is invalid, please select between 0 and %d.\n"
+#~ msgstr "Неправильный ключевой слот %d, пожалуйста, выберите между 0 и %d.\n"
+
+#~ msgid "This operation is supported only for LUKS device.\n"
+#~ msgstr "Данная операция поддерживается только для устройств LUKS.\n"
+
+#~ msgid "Cannot write header backup file %s.\n"
+#~ msgstr "Невозможно записать файл резервной копии заголовка %s.\n"
+
+#~ msgid "Cannot read header backup file %s.\n"
+#~ msgstr "Невозможно прочитать файл резервной копии заголовка %s.\n"
+
+#~ msgid "Cannot open header backup file %s.\n"
+#~ msgstr "Невозможно открыть файл резервной копии заголовка %s.\n"
+
+#~ msgid "Unsupported LUKS version %d.\n"
+#~ msgstr "Неподдерживаемая версия LUKS %d.\n"
+
+#~ msgid "Error during update of LUKS header on device %s.\n"
+#~ msgstr "Ошибка обновления заголовка LUKS на устройстве %s.\n"
+
+#~ msgid "Error re-reading LUKS header after update on device %s.\n"
+#~ msgstr "Ошибка перечитывания заголовка LUKS после обновления на устройстве %s.\n"
+
+#~ msgid "Cannot wipe device %s.\n"
+#~ msgstr "Невозможно очистить устройство %s.\n"
+
+#~ msgid "Option --header-backup-file is required.\n"
+#~ msgstr "Необходима опция --header-backup-file.\n"
+
+#~ msgid "File with LUKS header and keyslots backup."
+#~ msgstr "Файл с резервной копией заголовка и ключевых слотов LUKS."
+
+#~ msgid "DM-UUID for device %s was truncated.\n"
+#~ msgstr "DM-UUID для устройства %s был усечён.\n"
+
+#~ msgid "Key slot %d active, purge first.\n"
+#~ msgstr "Ключевой слот %d активен, сначала очистите.\n"
+
+#~ msgid "Volume key does not match the volume.\n"
+#~ msgstr "Ключ раздела не совпадает с разделом.\n"
+
+#~ msgid "Cannot initialize crypto backend.\n"
+#~ msgstr "Невозможно инициализировать внутренний интерфейс crypto.\n"
+
+#~ msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"
+#~ msgstr "Невозможно инициализировать device-mapper. Загружен ли модуль ядра dm_mod?\n"
+
+#~ msgid "Volume %s is not suspended.\n"
+#~ msgstr "Том %s не в режим приостановки.\n"
+
+#~ msgid "Volume %s is already suspended.\n"
+#~ msgstr "Том %s уже в режим приостановки.\n"
+
+#~ msgid "Error reading passphrase from terminal.\n"
+#~ msgstr "Ошибка чтения кодовой фразы из терминала.\n"
+
+#~ msgid "Passphrases do not match.\n"
+#~ msgstr "Кодовые фразы не совпадают.\n"
+
+#~ msgid "Key size in XTS mode must be 256 or 512 bits.\n"
+#~ msgstr "Размер ключа в режиме XTS должен быть 256 или 512-разрядный.\n"
+
+#~ msgid "Error reading passphrase.\n"
+#~ msgstr "Ошибка чтения кодовой фразы.\n"
+
+#~ msgid "Out of memory while reading passphrase.\n"
+#~ msgstr "Недостаточно памяти для считывания кодовой фразы.\n"
+
+#~ msgid "Cannot format device %s which is still in use.\n"
+#~ msgstr "Нельзя отформатировать устройство %s, которое ещё используется.\n"
+
+#~ msgid "This operation is not supported for this device type.\n"
+#~ msgstr "Это действие не поддерживается для данного типа устройств.\n"
+
+#~ msgid "Fatal error during RNG initialisation.\n"
+#~ msgstr "Критическая ошибка во время инициализации RNG.\n"
+
+#~ msgid "Option --key-file is required.\n"
+#~ msgstr "Требуется параметр --key-file.\n"
+
+#~ msgid "Hash algorithm %s not supported.\n"
+#~ msgstr "Алгоритм хэширования %s не поддерживается.\n"
+
+#~ msgid "Key processing error (using hash %s).\n"
+#~ msgstr "Ошибка обработки ключа (используется хэш %s).\n"
+
+#~ msgid "Failed to open key file.\n"
+#~ msgstr "Не удалось открыть ключевой файл.\n"
+
+#~ msgid "Cannot read requested amount of data.\n"
+#~ msgstr "Не удалось считать запрошенное количество данных.\n"
+
+#~ msgid "Writing LUKS header to disk.\n"
+#~ msgstr "Запись заголовка LUKS на диск.\n"
+
+#~ msgid "Key slot %d selected for deletion.\n"
+#~ msgstr "Слот ключа %d выбран для удаления.\n"
+
+#~ msgid "Key slot %d changed.\n"
+#~ msgstr "Слот ключа %d изменён.\n"
+
+#~ msgid "Read the key from a file."
+#~ msgstr "Читать ключ из файла."
+
+#~ msgid "Use /dev/random for generating volume key."
+#~ msgstr "Использовать /dev/random для генерации ключа тома."
+
+#~ msgid "Use /dev/urandom for generating volume key."
+#~ msgstr "Использовать /dev/urandom для генерации ключа тома."
+
+#~ msgid "Device type is not properly initialised.\n"
+#~ msgstr "Тип устройства некорректно инициализирован.\n"
+
+#~ msgid "Error during resuming device %s.\n"
+#~ msgstr "Ошибка при возобновлении работы устройства %s.\n"
+
+#~ msgid "Device %s is still in use.\n"
+#~ msgstr "Устройство %s всё ещё используется.\n"
+
+#~ msgid "Cannot unlock memory.\n"
+#~ msgstr "Не удалось разблокировать память.\n"
+
+#~ msgid "Maximum keyfile size exceeded.\n"
+#~ msgstr "Максимальный размер ключевого файла превышен.\n"
+
+#~ msgid "Running in FIPS mode.\n"
+#~ msgstr "Выполняется в режиме FIPS.\n"
+
+#~ msgid "Error reading keyfile %s.\n"
+#~ msgstr "Ошибка при чтении файла ключа %s.\n"
+
+#~ msgid "Maximum TCRYPT passphrase length (%d) exceeded.\n"
+#~ msgstr "Максимальная длина кодовой фразы TCRYPT (%d) превышена.\n"
+
+#~ msgid "Unsupported VERITY version %d.\n"
+#~ msgstr "Неподдерживаемая версия VERITY %d.\n"
+
+#~ msgid "VERITY header corrupted.\n"
+#~ msgstr "Заголовок VERITY повреждён.\n"
+
+#~ msgid "Cannot format device %s, permission denied.\n"
+#~ msgstr "Невозможно отформатировать устройство %s, отказано в доступе.\n"
+
+#~ msgid "Resume is not supported for device %s.\n"
+#~ msgstr "Возобновление не поддерживается для устройства %s.\n"
+
+#~ msgid "Unsupported VERITY block size.\n"
+#~ msgstr "Неподдерживаемый размер блока VERITY.\n"
+
+#~ msgid "Function not available in FIPS mode.\n"
+#~ msgstr "Функция недоступна в режиме FIPS.\n"
+
+#~ msgid "Requested offset is beyond real size of device %s.\n"
+#~ msgstr "Запрошенное смещение за пределами реального размера устройства %s.\n"
+
+#~ msgid "Cannot write to device %s, permission denied.\n"
+#~ msgstr "Запись на устройство %s невозможна, отказано в доступе.\n"
+
+#~ msgid "Cannot seek to requested keyfile offset.\n"
+#~ msgstr "Не удалось перейти к запрошенному смещению в ключевом файле.\n"
+
+#~ msgid "Non standard key size, manual repair required.\n"
+#~ msgstr "Нестандартный размер ключа, требуется исправление вручную.\n"
+
+#~ msgid "Required kernel crypto interface not available.\n"
+#~ msgstr "Запрошенный криптоинтерфейс ядра недоступен.\n"
+
+#~ msgid "Ensure you have algif_skcipher kernel module loaded.\n"
+#~ msgstr "Убедитесь, что загружен модуль ядра algif_skcipher.\n"
+
+#~ msgid "Activation is not supported for %d sector size.\n"
+#~ msgstr "Активация не поддерживается для размера сектора %d.\n"
+
+#~ msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u).\n"
+#~ msgstr "ПРЕДУПРЕЖДЕНИЕ: Ядро не может активировать устройство, если размер блока данных превышает размер страницы (%u).\n"
+
+#~ msgid "Cannot read keyfile %s.\n"
+#~ msgstr "Не удалось прочитать ключевой файл %s.\n"
+
+#~ msgid "Cannot read %d bytes from keyfile %s.\n"
+#~ msgstr "Не удалось прочитать %d байт из ключевого файла %s.\n"
+
+#~ msgid "UUID for device to use."
+#~ msgstr "UUID используемого устройства."
+
+#~ msgid "Do not activate device, just check passphrase."
+#~ msgstr "Не активировать устройство, просто проверить парольную фразу."
+
+#~ msgid "Cannot wipe header on device %s.\n"
+#~ msgstr "Не удалось стереть заголовок на устройстве %s.\n"
+
+#~ msgid "Dump operation is not supported for this device type.\n"
+#~ msgstr "Создание дампа не поддерживается для этого типа устройств.\n"
+
+#~ msgid "Cannot create header backup file %s.\n"
+#~ msgstr "Не удалось создать файл резервной копии заголовка %s.\n"
+
+#~ msgid "Requested header backup file %s already exists.\n"
+#~ msgstr "Запрошенный файл резервной копии заголовка %s уже существует.\n"
+
+#~ msgid "Disable password quality check (if enabled)."
+#~ msgstr "Отключить проверку качества пароля (если включена)."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, open and benchmark.\n"
+#~ "To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Опция --key-size разрешена только для luksFormat, open и benchmark.\n"
+#~ "Чтобы ограничить чтение из ключевого файла, используйте --keyfile-size=(количество байтов)."
+
+#~ msgid "Cannot write device %s.\n"
+#~ msgstr "Не удалось выполнить запись на устройство %s.\n"
+
+#~ msgid "New LUKS header for device %s created.\n"
+#~ msgstr "Создан новый заголовок LUKS для устройства %s.\n"
+
+#~ msgid "Activated keyslot %i.\n"
+#~ msgstr "Активирован слот ключей %i.\n"
+
+#~ msgid "Cannot get device size.\n"
+#~ msgstr "Не удалось получить размер устройства.\n"
+
+#~ msgid "Option --new must be used together with --reduce-device-size."
+#~ msgstr "Опция --new должна использоваться совместно с --reduce-device-size."
+
+#~ msgid "Cannot check password quality: %s\n"
+#~ msgstr "Не удалось проверить качество пароля: %s\n"
+
+#~ msgid "Interrupted by a signal.\n"
+#~ msgstr "Прервано по сигналу.\n"
+
+#~ msgid "Cannot determine device type. Incompatible activation of device?\n"
+#~ msgstr "Невозможно определить тип устройства. Несовместимая активация устройства?\n"
+
+#~ msgid "Requested dm-crypt performance options are not supported.\n"
+#~ msgstr "Запрошенные параметры производительности dm-crypt не поддерживаются.\n"
+
+#~ msgid "Requested dm-verity data corruption handling options are not supported.\n"
+#~ msgstr "Запрошенные параметры обработки повреждённых данных dm-verity не поддерживаются.\n"
+
+#~ msgid "Cannot initialize crypto RNG backend.\n"
+#~ msgstr "Невозможно инициализировать выходной буфер crypto RNG.\n"
+
+#~ msgid "Cannot initialize device-mapper, running as non-root user.\n"
+#~ msgstr "Невозможно инициализировать device-mapper, выполнение не от имени администратора.\n"
+
+#~ msgid "Can't format LUKS without device.\n"
+#~ msgstr "Невозможно отформатировать LUKS без устройства.\n"
+
+#~ msgid "Unsupported VERITY hash offset.\n"
+#~ msgstr "Неподдерживаемое смещение хэша VERITY.\n"
+
+#~ msgid "Suspend is not supported for device %s.\n"
+#~ msgstr "Приостановка не поддерживается для устройства %s.\n"
+
+#~ msgid "Error during suspending device %s.\n"
+#~ msgstr "Ошибка во время приостановки устройства %s.\n"
+
+#~ msgid "Can't format LOOPAES without device.\n"
+#~ msgstr "Невозможно отформатировать LOOPAES без устройства.\n"
+
+#~ msgid "Unsupported VERITY hash type %d.\n"
+#~ msgstr "Неподдерживаемый тип хэша VERITY %d.\n"
+
+#~ msgid "Can't format VERITY without device.\n"
+#~ msgstr "Невозможно отформатировать VERITY без устройства.\n"
+
+#~ msgid "UUID is not supported for this crypt type.\n"
+#~ msgstr "UUID не поддерживается для этого типа шифрования.\n"
+
+#~ msgid "Cannot use device %s which is in use (already mapped or mounted).\n"
+#~ msgstr "Невозможно использовать устройство %s, которое уже используется (уже внесено в схему или подключено).\n"
diff --git a/po/sr.po b/po/sr.po
new file mode 100644
index 0000000..5ca41d8
--- /dev/null
+++ b/po/sr.po
@@ -0,0 +1,4435 @@
+# Serbian translation for cryptsetup.
+# Copyright © 2014 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Мирослав Николић <miroslavnikolic@rocketmail.com>, 2014–2022.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup-2.5.0-rc1\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2022-07-14 14:04+0200\n"
+"PO-Revision-Date: 2022-09-08 05:02+0200\n"
+"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
+"Language-Team: Serbian <(nothing)>\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+
+#: lib/libdevmapper.c:417
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Не могу да покренем мапера уређаја, радим као обичан корисник."
+
+#: lib/libdevmapper.c:420
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Не могу да покренем мапера уређаја. Да ли је учитан модул кернела „dm_mod“?"
+
+#: lib/libdevmapper.c:1171
+msgid "Requested deferred flag is not supported."
+msgstr "Затражена одложена заставица није подржана."
+
+#: lib/libdevmapper.c:1240
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "ДМ-УЈИБ за уређај „%s“ је скраћен."
+
+#: lib/libdevmapper.c:1570
+msgid "Unknown dm target type."
+msgstr "Непозната врста „dm“ мете."
+
+#: lib/libdevmapper.c:1694 lib/libdevmapper.c:1699 lib/libdevmapper.c:1763
+#: lib/libdevmapper.c:1766
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Затражене опције перформанси дм-шифровања нису подржане."
+
+#: lib/libdevmapper.c:1706 lib/libdevmapper.c:1710
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Затражене опције рада оштећених података дм-веритија нису подржане."
+
+#: lib/libdevmapper.c:1714
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Затражене „dm-verity FEC“ опције нису подржане."
+
+#: lib/libdevmapper.c:1718
+msgid "Requested data integrity options are not supported."
+msgstr "Затражене опције целовитости података нису подржане."
+
+#: lib/libdevmapper.c:1720
+msgid "Requested sector_size option is not supported."
+msgstr "Затражене опције величине одељка нису подржане."
+
+#: lib/libdevmapper.c:1725 lib/libdevmapper.c:1729
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Затражене опције самосталног прерачунавања ознака целовитости нису подржане."
+
+#: lib/libdevmapper.c:1733 lib/libdevmapper.c:1769 lib/libdevmapper.c:1772
+#: lib/luks2/luks2_json_metadata.c:2552
+msgid "Discard/TRIM is not supported."
+msgstr "Одбацивање/ОДСЕЦАЊЕ није подржано."
+
+#: lib/libdevmapper.c:1737
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Затражени режим битмапе дм-целовитости није подржан."
+
+#: lib/libdevmapper.c:2763
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Нисам успео да пропитам „dm-%s“ подеок."
+
+#: lib/random.c:74
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Систем је ван ентропије приликом стварања кључа волумена.\n"
+"Померите миша или откуцајте неки текст у другом прозору да прикупите неке насумичне догађаје.\n"
+
+#: lib/random.c:78
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Стварам кључ (%d %% је урађено).\n"
+
+#: lib/random.c:164
+msgid "Running in FIPS mode."
+msgstr "Ради у „FIPS“ режиму."
+
+#: lib/random.c:170
+msgid "Fatal error during RNG initialisation."
+msgstr "Кобна грешка за време покретања „RNG“-а."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Затражен је непознат квалитет „RNG“-а."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Грешка читања из „RNG“-а."
+
+#: lib/setup.c:226
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Не могу да покренем „RNG“ позадинца криптографије."
+
+#: lib/setup.c:232
+msgid "Cannot initialize crypto backend."
+msgstr "Не могу да покренем позадинца криптографије."
+
+#: lib/setup.c:263 lib/setup.c:2080 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Хеш алгоритам „%s“ није подржан."
+
+#: lib/setup.c:266 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Грешка обраде кључа (користим хеш %s)."
+
+#: lib/setup.c:332 lib/setup.c:359
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Не могу да одредим врсту уређаја. Несагласно покретање уређаја?"
+
+#: lib/setup.c:338 lib/setup.c:3221
+msgid "This operation is supported only for LUKS device."
+msgstr "Ова радња је подржана само за ЛУКС уређај."
+
+#: lib/setup.c:365
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Ова радња је подржана само за ЛУКС2 уређај."
+
+#: lib/setup.c:420 lib/luks2/luks2_reencrypt.c:2985
+msgid "All key slots full."
+msgstr "Сви утори кључева су пуни."
+
+#: lib/setup.c:431
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Утор кључа %d није исправан, изаберите између 0 и %d."
+
+#: lib/setup.c:437
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Утор кључа %d је пун, изаберите неки други."
+
+#: lib/setup.c:522 lib/setup.c:2946
+msgid "Device size is not aligned to device logical block size."
+msgstr "Величина уређаја није поравната на величину логичког блока уређаја."
+
+#: lib/setup.c:620
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Заглавље је откривено али уређај „%s“ је премали."
+
+#: lib/setup.c:661 lib/setup.c:2851 lib/setup.c:4335
+#: lib/luks2/luks2_reencrypt.c:3757 lib/luks2/luks2_reencrypt.c:4159
+msgid "This operation is not supported for this device type."
+msgstr "Ова радња није подржана за ову врсту уређаја."
+
+#: lib/setup.c:666
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Неисправна радња са поновним шифровањем је у току."
+
+#: lib/setup.c:833 lib/luks1/keymanage.c:248 lib/luks1/keymanage.c:524
+#: lib/luks2/luks2_json_metadata.c:1267 src/cryptsetup.c:1449
+#: src/cryptsetup.c:1581 src/cryptsetup.c:1636 src/cryptsetup.c:1756
+#: src/cryptsetup.c:1861 src/cryptsetup.c:2142 src/cryptsetup.c:2380
+#: src/cryptsetup.c:2440 src/utils_reencrypt.c:1378
+#: src/utils_reencrypt_luks1.c:1188 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Уређај „%s“ није исправан ЛУКС уређај."
+
+#: lib/setup.c:836 lib/luks1/keymanage.c:527
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Неподржано ЛУКС издање %d."
+
+#: lib/setup.c:1431 lib/setup.c:2602 lib/setup.c:2682 lib/setup.c:2694
+#: lib/setup.c:2859 lib/setup.c:4807
+#, c-format
+msgid "Device %s is not active."
+msgstr "Уређај „%s“ није радан."
+
+#: lib/setup.c:1448
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Основни уређај за криптографски уређај „%s“ је нестао."
+
+#: lib/setup.c:1528
+msgid "Invalid plain crypt parameters."
+msgstr "Неисправни параметри обичне криптографије."
+
+#: lib/setup.c:1533 lib/setup.c:1983
+msgid "Invalid key size."
+msgstr "Неисправна величина кључа."
+
+#: lib/setup.c:1538 lib/setup.c:1988 lib/setup.c:2191
+msgid "UUID is not supported for this crypt type."
+msgstr "УЈИБ није подржан за ову врсту криптографије."
+
+#: lib/setup.c:1543 lib/setup.c:1993
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Откачени уређај метаподатака није подржан за ову врсту криптографије."
+
+#: lib/setup.c:1553 lib/setup.c:1765 lib/luks2/luks2_reencrypt.c:2941
+#: src/cryptsetup.c:1250 src/cryptsetup.c:3072
+msgid "Unsupported encryption sector size."
+msgstr "Неподржана величина одељка шифровања."
+
+#: lib/setup.c:1561 lib/setup.c:1896 lib/setup.c:2940
+msgid "Device size is not aligned to requested sector size."
+msgstr "Величина уређаја није поравната на затражену величину одељка."
+
+#: lib/setup.c:1613 lib/setup.c:1733
+msgid "Can't format LUKS without device."
+msgstr "Не могу да обликујем ЛУКС без уређаја."
+
+#: lib/setup.c:1619 lib/setup.c:1739
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Затражено поравнање података није сагласно са померајем података."
+
+#: lib/setup.c:1687 lib/setup.c:1883
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr "УПОЗОРЕЊЕ: Померај података је ван тренутно доступног уређаја података.\n"
+
+#: lib/setup.c:1697 lib/setup.c:1913 lib/setup.c:1934 lib/setup.c:2203
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Не могу да обришем заглавље на уређају „%s“."
+
+#: lib/setup.c:1774
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "УПОЗОРЕЊЕ: Покретање уређаја неће успети, „dm-crypt“-у недостаје подршка за затражену величину одељка шифровања.\n"
+
+#: lib/setup.c:1797
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Кључ волумена је премали за шифровање са проширењима целовитости."
+
+#: lib/setup.c:1857
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Шифрер %s-%s (величина кључа %zd бита) није доступан."
+
+#: lib/setup.c:1886
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "УПОЗОРЕЊЕ: Величина ЛУКС2 метаподатака је промењена на %<PRIu64> бајта.\n"
+
+#: lib/setup.c:1890
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "УПОЗОРЕЊЕ: Величина области ЛУКС2 утора кључева је промењена на %<PRIu64> бајта.\n"
+
+#: lib/setup.c:1916 lib/utils_device.c:909 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3009 lib/luks2/luks2_reencrypt.c:4254
+#, c-format
+msgid "Device %s is too small."
+msgstr "Уређај „%s“ је премали."
+
+#: lib/setup.c:1927 lib/setup.c:1953
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Не могу да обликујем уређај „%s“ у употреби."
+
+#: lib/setup.c:1930 lib/setup.c:1956
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Не могу да обликујем уређај „%s“, овлашћење је одбијено."
+
+#: lib/setup.c:1942 lib/setup.c:2263
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Не могу да обликујем целовитост за уређај „%s“."
+
+#: lib/setup.c:1960
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Не могу да обликујем уређај „%s“."
+
+#: lib/setup.c:1978
+msgid "Can't format LOOPAES without device."
+msgstr "Не могу да обликујем „LOOPAES“ без уређаја."
+
+#: lib/setup.c:2023
+msgid "Can't format VERITY without device."
+msgstr "Не могу да обликујем „VERITY“ без уређаја."
+
+#: lib/setup.c:2034 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Неподржана врста „VERITY“ хеша %d."
+
+#: lib/setup.c:2040 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Неподржана величина блока „VERITY“."
+
+#: lib/setup.c:2045 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Неподржан померај хеша „VERITY“."
+
+#: lib/setup.c:2050
+msgid "Unsupported VERITY FEC offset."
+msgstr "Неподржан „VERITY FEC“ померај."
+
+#: lib/setup.c:2074
+msgid "Data area overlaps with hash area."
+msgstr "Област података се преклапа са облашћу хеша."
+
+#: lib/setup.c:2099
+msgid "Hash area overlaps with FEC area."
+msgstr "Област хеша се преклапа са „FEC“ облашћу."
+
+#: lib/setup.c:2106
+msgid "Data area overlaps with FEC area."
+msgstr "Област података се преклапа са „FEC“ облашћу."
+
+#: lib/setup.c:2242
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "УПОЗОРЕЊЕ: Затражена величина ознаке %d бајта се разликује од излаза величине „%s“ (%d бајта).\n"
+
+#: lib/setup.c:2321
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Затражена је непозната врста „%s“ криптографског уређаја."
+
+#: lib/setup.c:2608 lib/setup.c:2687 lib/setup.c:2700
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Неподржани параметри на уређају „%s“."
+
+#: lib/setup.c:2614 lib/setup.c:2707 lib/luks2/luks2_reencrypt.c:2837
+#: lib/luks2/luks2_reencrypt.c:3074 lib/luks2/luks2_reencrypt.c:3459
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Неодговарајући параметри на уређају „%s“."
+
+#: lib/setup.c:2731
+msgid "Crypt devices mismatch."
+msgstr "Криптографски уређаји се не поклапају."
+
+#: lib/setup.c:2768 lib/setup.c:2773 lib/luks2/luks2_reencrypt.c:2315
+#: lib/luks2/luks2_reencrypt.c:2853 lib/luks2/luks2_reencrypt.c:4007
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Нисам успео поново да учитам уређај „%s“."
+
+#: lib/setup.c:2779 lib/setup.c:2785 lib/luks2/luks2_reencrypt.c:2286
+#: lib/luks2/luks2_reencrypt.c:2293 lib/luks2/luks2_reencrypt.c:2867
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Нисам успео да обуставим уређај „%s“."
+
+#: lib/setup.c:2791 lib/luks2/luks2_reencrypt.c:2300
+#: lib/luks2/luks2_reencrypt.c:2888 lib/luks2/luks2_reencrypt.c:3920
+#: lib/luks2/luks2_reencrypt.c:4011
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Нисам успео да наставим са уређајем „%s“."
+
+#: lib/setup.c:2806
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Кобна грешка приликом поновног учитавања уређаја „%s“ (на врху уређаја „%s“)."
+
+#: lib/setup.c:2809 lib/setup.c:2811
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Нисам успео да променим уређај „%s“ на дм-грешку."
+
+#: lib/setup.c:2891
+msgid "Cannot resize loop device."
+msgstr "Не могу да променим величину уређаја петље."
+
+#: lib/setup.c:2931
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr ""
+"УПОЗОРЕЊЕ: Највећа величина је већ постављена или кернел не подржава промену величине.\n"
+"\n"
+
+#: lib/setup.c:2989
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Промена величине није успела, кернел је не подржава."
+
+#: lib/setup.c:3021
+msgid "Do you really want to change UUID of device?"
+msgstr "Да ли стварно желите да измените УЈИБ уређаја?"
+
+#: lib/setup.c:3113
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Датотека резерве заглавља не садржи сагласно ЛУКС заглавље."
+
+#: lib/setup.c:3229
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Волумен „%s“ није радан."
+
+#: lib/setup.c:3240
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Волумен „%s“ је већ обустављен."
+
+#: lib/setup.c:3253
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Обустављање није подржано за уређај „%s“."
+
+#: lib/setup.c:3255
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Грешка за време обустављања уређаја „%s“."
+
+#: lib/setup.c:3290
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Настављање није подржано за уређај „%s“."
+
+#: lib/setup.c:3292
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Грешка за време настављања уређаја „%s“."
+
+#: lib/setup.c:3326 lib/setup.c:3374 lib/setup.c:3444 lib/setup.c:3489
+#: src/cryptsetup.c:2207
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Волумен „%s“ није обустављен."
+
+#: lib/setup.c:3459 lib/setup.c:3862 lib/setup.c:4584 lib/setup.c:4597
+#: lib/setup.c:4605 lib/setup.c:4618 lib/setup.c:6142 src/cryptsetup.c:1790
+msgid "Volume key does not match the volume."
+msgstr "Кључ волумена не одговара волумену."
+
+#: lib/setup.c:3540 lib/setup.c:3745
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Не могу да додам утор кључа, сви утори су искључени а није обезбеђен ниједан кључ волумена."
+
+#: lib/setup.c:3697
+msgid "Failed to swap new key slot."
+msgstr "Нисам успео да разменим нови утор кључа."
+
+#: lib/setup.c:3883
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Утор кључа „%d“ није исправан."
+
+#: lib/setup.c:3889 src/cryptsetup.c:1594 src/cryptsetup.c:1936
+#: src/cryptsetup.c:2540 src/cryptsetup.c:2597
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Утор кључа „%d“ није радан."
+
+#: lib/setup.c:3908
+msgid "Device header overlaps with data area."
+msgstr "Заглавље уређаја се преклапа са облашћу података."
+
+#: lib/setup.c:4213
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Поновно шифровање је у току. Не могу да активирам уређај."
+
+#: lib/setup.c:4215 lib/luks2/luks2_json_metadata.c:2635
+#: lib/luks2/luks2_reencrypt.c:3565
+msgid "Failed to get reencryption lock."
+msgstr "Нисам успео да добавим закључавање поновног шифровања."
+
+#: lib/setup.c:4228 lib/luks2/luks2_reencrypt.c:3584
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Опоравак ЛУКС2 поновног шифровања није успело."
+
+#: lib/setup.c:4396 lib/setup.c:4661
+msgid "Device type is not properly initialized."
+msgstr "Врста уређаја није исправно покренута."
+
+#: lib/setup.c:4444
+#, c-format
+msgid "Device %s already exists."
+msgstr "Већ постоји уређај „%s“."
+
+#: lib/setup.c:4451
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Не могу да користим уређај „%s“, назив није исправан или је још у употреби."
+
+#: lib/setup.c:4571
+msgid "Incorrect volume key specified for plain device."
+msgstr "Наведен је неисправан кључ волумена за обичан уређај."
+
+#: lib/setup.c:4687
+msgid "Incorrect root hash specified for verity device."
+msgstr "Наведен је неисправан хеш корена за уређај тачности."
+
+#: lib/setup.c:4697
+msgid "Root hash signature required."
+msgstr "Потпис хеша корена је потребан."
+
+#: lib/setup.c:4706
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Привезак кључева кернела недостаје: потребан је за прослеђивање потписа кернелу."
+
+#: lib/setup.c:4723 lib/setup.c:6218
+msgid "Failed to load key in kernel keyring."
+msgstr "Нисам успео да учитам кључ у привеску кључева кернела."
+
+#: lib/setup.c:4779
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Не могу да откажем различно уклањање из уређаја „%s“."
+
+#: lib/setup.c:4786 lib/setup.c:4802 lib/luks2/luks2_json_metadata.c:2688
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Уређај „%s“ је још увеку употреби."
+
+#: lib/setup.c:4811
+#, c-format
+msgid "Invalid device %s."
+msgstr "Неисправан уређај „%s“."
+
+#: lib/setup.c:4927
+msgid "Volume key buffer too small."
+msgstr "Међумеморија кључа волумена је премала."
+
+#: lib/setup.c:4935
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Не могу да довучем кључ волумена за обичан уређај."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Не могу да довучем хеш корена за уређај тачности."
+
+#: lib/setup.c:4956
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Ова радња није подржана за криптографски уређај „%s“."
+
+#: lib/setup.c:5130 lib/setup.c:5141
+msgid "Dump operation is not supported for this device type."
+msgstr "Радња исписа није подржана за ову врсту уређаја."
+
+#: lib/setup.c:5471
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Померај података није умножак %u бајта."
+
+#: lib/setup.c:5756
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Не могу да преобратим уређај „%s“ који је још увек у употреби."
+
+#: lib/setup.c:6075
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Нисам успео да доделим утор кључа „%u“ као нови кључ волумена."
+
+#: lib/setup.c:6148
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Нисам успео да покренем основне параметре ЛУКС2 утора кључа."
+
+#: lib/setup.c:6154
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Нисам успео да доделим утор кључа „%d“ за преглед."
+
+#: lib/setup.c:6285
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Привезак кључева кернела није подржан кернелом."
+
+#: lib/setup.c:6295 lib/luks2/luks2_reencrypt.c:3782
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Нисам успео да прочитам пропусну реч из привеска кључа (грешка %d)."
+
+#: lib/setup.c:6319
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Нисам успео да остварим опште закључавање серијализације приступа чврстој меморији."
+
+#: lib/utils.c:80
+msgid "Cannot get process priority."
+msgstr "Не могу да добавим хитност процеса."
+
+#: lib/utils.c:94
+msgid "Cannot unlock memory."
+msgstr "Не могу да откључам меморију."
+
+#: lib/utils.c:168 lib/tcrypt/tcrypt.c:502
+msgid "Failed to open key file."
+msgstr "Нисам успео да отворим датотеку кључа."
+
+#: lib/utils.c:173
+msgid "Cannot read keyfile from a terminal."
+msgstr "Не могу да прочитам датотеку кључа из терминала."
+
+#: lib/utils.c:189
+msgid "Failed to stat key file."
+msgstr "Нисам успео да добавим податке датотеке кључа."
+
+#: lib/utils.c:197 lib/utils.c:218
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Не могу да премотам на затражени померај датотеке кључа."
+
+#: lib/utils.c:212 lib/utils.c:227 src/utils_password.c:226
+#: src/utils_password.c:238
+msgid "Out of memory while reading passphrase."
+msgstr "Нестало је меморије приликом читања пропусне речи."
+
+#: lib/utils.c:247
+msgid "Error reading passphrase."
+msgstr "Грешка читања пропусне речи."
+
+#: lib/utils.c:264
+msgid "Nothing to read on input."
+msgstr "Нема ничега за читање на улазу."
+
+#: lib/utils.c:271
+msgid "Maximum keyfile size exceeded."
+msgstr "Премашена је највећа величина датотеке кључа."
+
+#: lib/utils.c:276
+msgid "Cannot read requested amount of data."
+msgstr "Не могу да прочитам затражену количину података."
+
+#: lib/utils_device.c:208 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1353
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Уређај „%s“ не постоји или је приступ одбијен."
+
+#: lib/utils_device.c:218
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Уређај „%s“ није сагласан."
+
+#: lib/utils_device.c:562
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Занемарујем лажну оптималну-уи величину за уређај података (%u бајта)."
+
+#: lib/utils_device.c:720
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Уређај „%s“ је премали. Захтева барем %<PRIu64> бајта."
+
+#: lib/utils_device.c:801
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Не могу да користим уређај „%s“ који је у употреби (већ мапиран или прикачен)."
+
+#: lib/utils_device.c:805
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Не могу да користим уређај „%s“, овлашћење је одбијено."
+
+#: lib/utils_device.c:808
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Не могу да добавим податке о уређају „%s“."
+
+#: lib/utils_device.c:831
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Не могу да користим уређај повратне петље, радим као обичан корисник."
+
+#: lib/utils_device.c:842
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Прикачињање уређаја повратне петље није успело (потребан је уређај петље са опцијом самочишћења)."
+
+#: lib/utils_device.c:890
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Захтевани померај је изван стварне величине уређаја „%s“."
+
+#: lib/utils_device.c:898
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Уређај „%s“ има нулту величину."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Затражено време „PBKDF“ мете не може бити нула."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Непозната „PBKDF“ врста „%s“."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Затражени хеш „%s“ није подржан."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Затражена „PBKDF“ врста није подржана за ЛУКС1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Највећа „PBKDF“ меморија или паралелне нити не смеју бити подешене са „pbkdf2“."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Присиљени број понављања је премали за „%s“ (минимум је %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Присиљени трошак меморије је премали за „%s“ (минимум је %u килобајта)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Затражени највећи трошак „PBKDF“ меморије је превисок (максимум је %d килобајта)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Затражени максимум „PBKDF“ меморије не може бити нула."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Затражене „PBKDF“ паралелне нити не могу бити нула."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Само „PBKDF2“ је подржано у „FIPS“ режиму."
+
+#: lib/utils_benchmark.c:172
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "„PBKDF“ оцењивање је искључено али понављања нису постављена."
+
+#: lib/utils_benchmark.c:191
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Нису сагласне „PBKDF2“ опције (користим хеш алгоритам %s)."
+
+#: lib/utils_benchmark.c:211
+msgid "Not compatible PBKDF options."
+msgstr "Несагласне „PBKDF“ опције."
+
+#: lib/utils_device_locking.c:102
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Закључавање је прекинуто. Путања закључавања „%s/%s“ је неискористива (није директоријум или недостаје)."
+
+#: lib/utils_device_locking.c:109
+#, c-format
+msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+msgstr "Директоријум закључавања „%s/%s“ биће направљен са основним преведеним овлашћењима."
+
+#: lib/utils_device_locking.c:119
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Закључавање је прекинуто. Путања закључавања „%s/%s“ је неискористива („%s“ није директоријум)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Не могу да премотам на померај уређаја."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Грешка брисања уређаја, померај %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Нисам успео да подесим мапирање кључа „dm-crypt“ за уређај %s.\n"
+"Проверите да ли кернел подржава „%s“ шифрера (проверите дневник система за више података)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Величина кључа у „XTS“ режиму мора да буде 256 или 512 бита."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Спецификација шифрера треба бити у запису „[шифрер]-[режим]-[ив]“."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:364
+#: lib/luks1/keymanage.c:674 lib/luks1/keymanage.c:1125
+#: lib/luks2/luks2_json_metadata.c:1421 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Не могу да пишем на уређај „%s“, овлашћење је одбијено."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Нисам успео да отворим привремени уређај смештаја кључа."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Нисам успео да приступм привременом уређају смештаја кључа."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:60
+#: lib/luks2/luks2_keyslot_luks2.c:78 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Грешка УИ приликом шифровања утора кључа."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:367
+#: lib/luks1/keymanage.c:627 lib/luks1/keymanage.c:677 lib/tcrypt/tcrypt.c:680
+#: lib/verity/verity.c:80 lib/verity/verity.c:196 lib/verity/verity_hash.c:320
+#: lib/verity/verity_hash.c:329 lib/verity/verity_hash.c:349
+#: lib/verity/verity_fec.c:260 lib/verity/verity_fec.c:272
+#: lib/verity/verity_fec.c:277 lib/luks2/luks2_json_metadata.c:1424
+#: src/utils_reencrypt_luks1.c:121 src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Не могу да отворим уређај „%s“."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:137
+msgid "IO error while decrypting keyslot."
+msgstr "Грешка УИ приликом дешифровања утора кључа."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Уређај „%s“ је премали. (ЛУКС1 захтева барем %<PRIu64> бајта.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "ЛУКС утор кључа „%u“ није исправан."
+
+#: lib/luks1/keymanage.c:266 lib/luks2/luks2_json_metadata.c:1284
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Затражена датотека резерве заглавља „%s“ већ постоји."
+
+#: lib/luks1/keymanage.c:268 lib/luks2/luks2_json_metadata.c:1286
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Не могу да направим резервну датотеку заглавља „%s“."
+
+#: lib/luks1/keymanage.c:275 lib/luks2/luks2_json_metadata.c:1293
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Не могу да запишем резервну датотеку заглавља „%s“."
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1330
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Датотека резерве не садржи исправно ЛУКС заглавље."
+
+#: lib/luks1/keymanage.c:319 lib/luks1/keymanage.c:590
+#: lib/luks2/luks2_json_metadata.c:1351
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Не могу да отворим резервну датотеку заглавља „%s“."
+
+#: lib/luks1/keymanage.c:327 lib/luks2/luks2_json_metadata.c:1359
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Не могу да прочитам резервну датотеку заглавља „%s“."
+
+#: lib/luks1/keymanage.c:337
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Померај датума или величина кључа се разликују на уређају и резерви, враћање није успело."
+
+#: lib/luks1/keymanage.c:345
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Уређај %s %s%s"
+
+#: lib/luks1/keymanage.c:346
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "не садржи ЛУКС заглавље. Замена заглавља може да уништи податке на том уређају."
+
+#: lib/luks1/keymanage.c:347
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "већ садржи ЛУКС заглавље. Замена заглавља ће уништити постојеће уторе кључева."
+
+#: lib/luks1/keymanage.c:348 lib/luks2/luks2_json_metadata.c:1393
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"УПОЗОРЕЊЕ: право заглавље уређаја има другачији УЈИБ од резерве!"
+
+#: lib/luks1/keymanage.c:395
+msgid "Non standard key size, manual repair required."
+msgstr "Неуобичајена величина кључа, потребна је ручна поправка."
+
+#: lib/luks1/keymanage.c:405
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Неуобичајено поравнање утора кључева, потребна је ручна поправка."
+
+#: lib/luks1/keymanage.c:414
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Режим шифрера је оправљен (%s → %s)."
+
+#: lib/luks1/keymanage.c:425
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Хеш шифрера је преправљен на мала слова (%s)."
+
+#: lib/luks1/keymanage.c:427 lib/luks1/keymanage.c:533
+#: lib/luks1/keymanage.c:789
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Затражени ЛУКС хеш „%s“ није подржан."
+
+#: lib/luks1/keymanage.c:441
+msgid "Repairing keyslots."
+msgstr "Поправљам уторе кључева."
+
+#: lib/luks1/keymanage.c:460
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Утор кључа %i: померај је оправљен (%u —> %u)."
+
+#: lib/luks1/keymanage.c:468
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Утор кључа %i: траке су оправљене (%u —> %u)."
+
+#: lib/luks1/keymanage.c:477
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Утор кључа %i: лажан потпис партиције."
+
+#: lib/luks1/keymanage.c:482
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Утор кључа %i: присолак је обрисан."
+
+#: lib/luks1/keymanage.c:499
+msgid "Writing LUKS header to disk."
+msgstr "Записујем ЛУКС заглавље на диск."
+
+#: lib/luks1/keymanage.c:504
+msgid "Repair failed."
+msgstr "Поправка није успела."
+
+#: lib/luks1/keymanage.c:559
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Режим ЛУКС шифрера „%s“ није исправан."
+
+#: lib/luks1/keymanage.c:564
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "ЛУКС хеш „%s“ није исправан."
+
+#: lib/luks1/keymanage.c:571 src/cryptsetup.c:1144
+msgid "No known problems detected for LUKS header."
+msgstr "Нису откривени познати проблеми за ЛУКС заглавље."
+
+#: lib/luks1/keymanage.c:699
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Грешка приликом освежавања ЛУКС заглавља на уређају „%s“."
+
+#: lib/luks1/keymanage.c:707
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Грешка поновног читања ЛУКС заглавља након освежења на уређају „%s“."
+
+#: lib/luks1/keymanage.c:783
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Померај података за ЛУКС заглавље мора бити или 0 или већи од величине заглавља."
+
+#: lib/luks1/keymanage.c:794 lib/luks1/keymanage.c:863
+#: lib/luks2/luks2_json_format.c:287 lib/luks2/luks2_json_metadata.c:1175
+#: src/utils_reencrypt.c:475
+msgid "Wrong LUKS UUID format provided."
+msgstr "Достављен је погрешан запис ЛУКС УЈИБ-а."
+
+#: lib/luks1/keymanage.c:816
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Не могу да направим ЛУКС заглавље: није успело читање насумичног присолка."
+
+#: lib/luks1/keymanage.c:842
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Не могу да направим ЛУКС заглавље: није успео преглед заглавља (користим хеш „%s“)."
+
+#: lib/luks1/keymanage.c:886
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Утор кључа „%d“ је радан, прво прочистите."
+
+#: lib/luks1/keymanage.c:892
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Материјал утора кључа „%d“ обухвата премало трака. Да управљам заглављем?"
+
+#: lib/luks1/keymanage.c:1033
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Не могу да отворим утор кључа (користим хеш %s)."
+
+#: lib/luks1/keymanage.c:1111
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Утор кључа %d није исправан, изаберите га између 0 и %d."
+
+#: lib/luks1/keymanage.c:1129 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Не могу да обришем уређај „%s“."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Откривена је још увек неподржана ГПГ-ом шифрована датотека кључа."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Користите „gpg --decrypt <ДАТОТЕКА_КЉУЧА> | cryptsetup --keyfile=- ...“\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Откривена је несагласна датотека кључа „AES“ петље."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Језгро не подржава мапирање сагласно са „AES“ петљом."
+
+#: lib/tcrypt/tcrypt.c:509
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Грешка читања датотеке кључа „%s“."
+
+#: lib/tcrypt/tcrypt.c:559
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Премашена је највећа дужина „TCRYPT“ пропусне речи (%zu)."
+
+#: lib/tcrypt/tcrypt.c:601
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "„PBKDF2“ алгоритам хеша „%s“ није доступан, прескачем."
+
+#: lib/tcrypt/tcrypt.c:620 src/cryptsetup.c:1019
+msgid "Required kernel crypto interface not available."
+msgstr "Није доступно затражено сучеље криптографије језгра."
+
+#: lib/tcrypt/tcrypt.c:622 src/cryptsetup.c:1021
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Уверите се да је учитан модул кернела „algif_skcipher“."
+
+#: lib/tcrypt/tcrypt.c:763
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Покретање није подржано за величину %d области."
+
+#: lib/tcrypt/tcrypt.c:769
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Језгро не подржава покретање за овај стари „TCRYPT“ режим."
+
+#: lib/tcrypt/tcrypt.c:800
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Покрећем „TCRYPT“ систем шифровања за партицију „%s“."
+
+#: lib/tcrypt/tcrypt.c:883
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Кернел не подржава мапирање сагласно са „TCRYPT“-ом."
+
+#: lib/tcrypt/tcrypt.c:1096
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Ова функција није подржана без учитавања „TCRYPT“ заглавља."
+
+#: lib/bitlk/bitlk.c:275
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Нађох неочекивану врсту уноса метаподатака „%u“ приликом обраде подржаног главног кључа волумена."
+
+#: lib/bitlk/bitlk.c:328
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Нађох неисправну ниску приликом обраде главног кључа волумена."
+
+#: lib/bitlk/bitlk.c:332
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Нађох неочекивану ниску („%s“) приликом обраде подржаног главног кључа волумена."
+
+#: lib/bitlk/bitlk.c:349
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Нађох неочекивану вредност уноса метаподатака „%u“ приликом обраде подржаног главног кључа волумена."
+
+#: lib/bitlk/bitlk.c:451
+msgid "BITLK version 1 is currently not supported."
+msgstr "„BITLK“ издање 1 тренутно није подржано."
+
+#: lib/bitlk/bitlk.c:457
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Неисправан или непознат потпис учитавања за „BITLK“ уређај."
+
+#: lib/bitlk/bitlk.c:469
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Неподржана величина одељка „%<PRIu16>“."
+
+#: lib/bitlk/bitlk.c:477
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Нисам успео да прочитам „BITLK“ заглавље из „%s“."
+
+#: lib/bitlk/bitlk.c:502
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Нисам успео да прочитам „BITLK FVE“ метаподатаке из „%s“."
+
+#: lib/bitlk/bitlk.c:554
+msgid "Unknown or unsupported encryption type."
+msgstr "Непозната или неподржана врста криптографије."
+
+#: lib/bitlk/bitlk.c:587
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Нисам успео да прочитам уносе „BITLK“ метаподатака из „%s“."
+
+#: lib/bitlk/bitlk.c:681
+msgid "Failed to convert BITLK volume description"
+msgstr "Нисам успео да претворим опис „BITLK“ волумена"
+
+#: lib/bitlk/bitlk.c:841
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Нађох неочекивану врсту уноса метаподатака „%u“ приликом обраде спољног кључа."
+
+#: lib/bitlk/bitlk.c:860
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "ГУИД „%s“ датотеке „BEK“ не одговара ГУИД-у волумена."
+
+#: lib/bitlk/bitlk.c:864
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Нађох неочекивану вредност уноса метаподатака „%u“ приликом обраде спољног кључа."
+
+#: lib/bitlk/bitlk.c:903
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Неподржани „BEK“ метаподаци издање %<PRIu32>"
+
+#: lib/bitlk/bitlk.c:908
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Неочекивана величина „BEK“ метаподатака %<PRIu32> не одговара величини „BEK“ датотеке"
+
+#: lib/bitlk/bitlk.c:933
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Нађох неочекивану врсту уноса метаподатака приликом обраде кључа почретања."
+
+#: lib/bitlk/bitlk.c:1029
+msgid "This operation is not supported."
+msgstr "Радња није подржана."
+
+#: lib/bitlk/bitlk.c:1037
+msgid "Unexpected key data size."
+msgstr "Неочекивана величина података кључа."
+
+#: lib/bitlk/bitlk.c:1163
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Овај „BITLK“ уређај је у неподржаном стању и не може бити активиран."
+
+#: lib/bitlk/bitlk.c:1168
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "„BITLK“ уређај са врстом „%s“ се не може активирати."
+
+#: lib/bitlk/bitlk.c:1175
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Активирање делимично дешифрованог „BITLK“ уређаја није подржано."
+
+#: lib/bitlk/bitlk.c:1216
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "УПОЗОРЕЊЕ: Величина волумена закључавача бита %<PRIu64> не одговара величини садржаног уређаја %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1343
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Не могу да активирам уређај, „dm-crypt“-у кернела недостаје подршка за „BITLK IV“."
+
+#: lib/bitlk/bitlk.c:1347
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Не могу да активирам уређај, „dm-crypt“-у кернела недостаје подршка за „BITLK Elephant“ дифузера."
+
+#: lib/bitlk/bitlk.c:1351
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Не могу да активирам уређај, „dm-crypt“-у кернела недостаје подршка за велику величину сектора."
+
+#: lib/bitlk/bitlk.c:1355
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Не могу да активирам уређај, недостаје „dm-zero“ модул кернела."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Уређај тачности %s не користи заглавље на-диску."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Неподржано издање „VERITY“ %d."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "Заглавље „VERITY“ је оштећено."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Достављен је погрешан УЈИБ „VERITY“ запис на уређају „%s“."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Грешка приликом освежавања заглавља тачности на уређају „%s“."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Провера хеш потписа корена није подржана."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Грешке се не могу поправити са „FEC“ уређајем."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Нађох поправљиве грешке (%u) са „FEC“ уређајем."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Кернел не подржава мапирање дм-тачности."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Кернел не подржава опцију потписа дм-тачности."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Уређај тачности је открио оштећење након покретања."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Сувишна област није нулирана на положају %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Прекорачење помераја уређаја."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Провера није успела на положају %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Прекорачење области хеша."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Провера области података није успела."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Провера хеша корена није успела."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Улазно/излазна грешка приликом стварања области хеша."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Стварање области хеша није успело."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "УПОЗОРЕЊЕ: Језгро не може да покрене уређајако величина блока података премашује величину странице (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Нисам успео да доделим „RS“ контекст."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Нисам успео да доделим међумеморију."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Нисам успео да прочитам „RS“ блок %<PRIu64> бајта %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Нисам успео да прочитам паритет „RS“ блока %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Нисам успео да поправим паритет за блок %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Нисам успео да запишем паритет „RS“ блока %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Величине блокова морају одговарати за „FEC“."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Неисправан број бајтова паритета."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Неисправна дужина „FEC“ сегмента."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Нисам успео да одредим величину за уређај „%s“."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Недоследни „dm-integrity“ метаподаци кернела (издање %u) су откривени на „%s“."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Кернел не подржава мапирање дм-целовитости."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Кернел не подржава поравнање фиксних метаподатака дм-целовитости."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Кернел одбија да покрене небезбедну опцију поновног израчунавања (видите старе опције покретања да избегнете ово)."
+
+#: lib/luks2/luks2_disk_metadata.c:393 lib/luks2/luks2_json_metadata.c:1133
+#: lib/luks2/luks2_json_metadata.c:1413
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Нисам успео да остварим закључавање писања на уређају „%s“."
+
+#: lib/luks2/luks2_disk_metadata.c:402
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Открих покушај истовременог ажурирања ЛУКС2 метаподатака. Прекидам."
+
+#: lib/luks2/luks2_disk_metadata.c:701 lib/luks2/luks2_disk_metadata.c:722
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Уређај садржи нејасне потписе, не могу сам да поправим ЛУКС2.\n"
+"Покрените „cryptsetup repair“ за опорављање."
+
+#: lib/luks2/luks2_json_format.c:230
+msgid "Requested data offset is too small."
+msgstr "Затражени померај података је премали."
+
+#: lib/luks2/luks2_json_format.c:275
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "УПОЗОРЕЊЕ: област утора кључа (%<PRIu64> бајта) је врло мала, доступан број ЛУКС2 утора кључа врло ограничен.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1120 lib/luks2/luks2_json_metadata.c:1258
+#: lib/luks2/luks2_json_metadata.c:1319 lib/luks2/luks2_keyslot_luks2.c:92
+#: lib/luks2/luks2_keyslot_luks2.c:114
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Нисам успео да остварим закључавање читања на уређају „%s“."
+
+#: lib/luks2/luks2_json_metadata.c:1336
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Забрањени ЛУКС2 захтеви су откривени у резерви „%s“."
+
+#: lib/luks2/luks2_json_metadata.c:1377
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Померај података се разликује на уређају и резерви, враћање није успело."
+
+#: lib/luks2/luks2_json_metadata.c:1383
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Бинарно заглавље са областима утора кључа се разликује на уређају и резерви, враћање није успело."
+
+#: lib/luks2/luks2_json_metadata.c:1390
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Уређај %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1391
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "не садржи ЛУКС2 заглавље. Замена заглавља може да уништи податке на том уређају."
+
+#: lib/luks2/luks2_json_metadata.c:1392
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "већ садржи „LUKS2“ заглавље. Замена заглавља ће уништити постојеће уторе кључева."
+
+#: lib/luks2/luks2_json_metadata.c:1394
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"УПОЗОРЕЊЕ: непознати ЛУКС2 захтеви су откривени у стварном заглављу уређаја!\n"
+"Замена заглавља резервом може оштетити податке на том уређају!"
+
+#: lib/luks2/luks2_json_metadata.c:1396
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"УПОЗОРЕЊЕ: Недовршено ван мрежно поновно шифровање је откривено на уређају!\n"
+"Замена заглавља резервом може оштетити податке."
+
+#: lib/luks2/luks2_json_metadata.c:1494
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Занемарена непозната заставица „%s“."
+
+#: lib/luks2/luks2_json_metadata.c:2402 lib/luks2/luks2_reencrypt.c:2015
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Недостаје кључ за „dm-crypt“ подеок %u"
+
+#: lib/luks2/luks2_json_metadata.c:2414 lib/luks2/luks2_reencrypt.c:2029
+msgid "Failed to set dm-crypt segment."
+msgstr "Нисам успео да подесим „dm-crypt“ подеок."
+
+#: lib/luks2/luks2_json_metadata.c:2420 lib/luks2/luks2_reencrypt.c:2035
+msgid "Failed to set dm-linear segment."
+msgstr "Нисам успео да подесим „dm-linear“ подеок."
+
+#: lib/luks2/luks2_json_metadata.c:2547
+msgid "Unsupported device integrity configuration."
+msgstr "Неподржано подешавање целовитости уређаја."
+
+#: lib/luks2/luks2_json_metadata.c:2633
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Поновно шифровање је у току. Не могу да деактивирам уређај."
+
+#: lib/luks2/luks2_json_metadata.c:2644 lib/luks2/luks2_reencrypt.c:4057
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Нисам успео да заменим обустављени уређај „%s“ са метом „dm-error“."
+
+#: lib/luks2/luks2_json_metadata.c:2724
+msgid "Failed to read LUKS2 requirements."
+msgstr "Нисам успео да прочитам ЛУКС2 захтеве."
+
+#: lib/luks2/luks2_json_metadata.c:2731
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Неоствариви ЛУКС2 захтеви су откривени."
+
+#: lib/luks2/luks2_json_metadata.c:2739
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Радња је несагласна са уређајем означеним за старо поновно шифровање. Прекидам."
+
+#: lib/luks2/luks2_json_metadata.c:2741
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Радња је несагласна са уређајем означеним за ЛУКС2 поновно шифровање. Прекидам."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Нема довољно доступне меморије за отварање утора кључа."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Отварање утора кључа није успело."
+
+#: lib/luks2/luks2_keyslot_luks2.c:53 lib/luks2/luks2_keyslot_luks2.c:108
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Не могу користити шифрер „%s-%s“ за шифровање утора кључа."
+
+#: lib/luks2/luks2_keyslot_luks2.c:496
+msgid "No space for new keyslot."
+msgstr "Нема простора за нови утор кључа."
+
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2615
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Алгоритам хеша „%s“ није доступан."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Затражена је неисправна промена режима гипкости поновног шифровања."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Не могу да освежим врсту гипкости. Нова врста обезбеђује само %<PRIu64> бајт(а), захтеван простор је: %<PRIu64> бајт(а)."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Нисам успео да освежим упит потврђивања поновног шифровања."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Не могу да проверим стање уређаја са ујиб-ом: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Не могу да претворим заглавље са „LUKSMETA“ додатним метаподацима."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3715
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Не могу да користим спецификацију шифрера „%s-%s“ за ЛУКС2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Не могу да преместим област утора кључа. Нема довољно простора."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Не могу да претворим у ЛУКС2 запис – неисправни метаподаци."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Не могу да преместим област утора кључа. Област ЛУКС2 утора кључа је премала."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Не могу да преместим област утора кључа."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Не могу да претворим у ЛУКС1 запис – основна величина подеока 512 bytes."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Не могу да претворим у ЛУКС1 запис – прегледи утора кључа нису ЛУКС1 сагласни."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Не могу да претворим у ЛУКС1 запис – уређај користи умотаног шифрера кључа „%s“."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Не могу да претворим у ЛУКС2 запис – уређај користи више подеока."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Не могу да претворим у ЛУКС1 запис – ЛУКС2 заглавље садржи %u скупину(е)."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Не могу да претворим у ЛУКС1 запис – утор кључа %u је у неисправном стању."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Не могу да претворим у ЛУКС1 запис – утор %u (преко максимума утора) је још активан."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Не могу да претворим у ЛУКС1 запис – утор кључа %u није ЛУКС1 сагласан."
+
+#: lib/luks2/luks2_reencrypt.c:1107
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Величина вруће зоне мора бити умножак прорачунатог поравнања зоне (%zu бајта)."
+
+#: lib/luks2/luks2_reencrypt.c:1112
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Величина уређаја мора бити производ прорачунатог поравнања зоне (%zu бајта)."
+
+#: lib/luks2/luks2_reencrypt.c:1319 lib/luks2/luks2_reencrypt.c:1505
+#: lib/luks2/luks2_reencrypt.c:1588 lib/luks2/luks2_reencrypt.c:1630
+#: lib/luks2/luks2_reencrypt.c:3852
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Нисам успео да покренем старог увијача смештаја подеока."
+
+#: lib/luks2/luks2_reencrypt.c:1333 lib/luks2/luks2_reencrypt.c:1483
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Нисам успео да покренем новог увијача смештаја подеока."
+
+#: lib/luks2/luks2_reencrypt.c:1460 lib/luks2/luks2_reencrypt.c:3864
+msgid "Failed to initialize hotzone protection."
+msgstr "Нисам успео да покренем заштиту вруће зоне."
+
+#: lib/luks2/luks2_reencrypt.c:1532
+msgid "Failed to read checksums for current hotzone."
+msgstr "Нисам успео да прочитам суму провере за текућу врућу зону."
+
+#: lib/luks2/luks2_reencrypt.c:1539 lib/luks2/luks2_reencrypt.c:3878
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Нисам успео да прочитам област вруће зоне са почетком на %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1558
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Нисам успео да дешифрујем област %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1564
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Нисам успео да опоравим област %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2128
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Величине изворног и циљног уређаја не одговарају. Извор %<PRIu64>, мета: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2226
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Нисам успео да активирам уређај вруће зоне „%s“."
+
+#: lib/luks2/luks2_reencrypt.c:2243
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Нисам успео да активирам уређај преклапања „%s“ са стварном табелом порекла."
+
+#: lib/luks2/luks2_reencrypt.c:2250
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Нисам успео да учитам ново мапирање за уређај „%s“."
+
+#: lib/luks2/luks2_reencrypt.c:2321
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Нисам успео да освежим спремник уређаја поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:2497
+msgid "Failed to set new keyslots area size."
+msgstr "Нисам успео да подесим нову величину области утора кључа."
+
+#: lib/luks2/luks2_reencrypt.c:2633
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Вредност помака података није поравната на величину одељка шифровања (%<PRIu32> бајта)."
+
+#: lib/luks2/luks2_reencrypt.c:2664
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Неподржан режим гипкости „%s“"
+
+#: lib/luks2/luks2_reencrypt.c:2741
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Величина премештеног подеока не може бити већа од вредности помака података."
+
+#: lib/luks2/luks2_reencrypt.c:2799
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Премештени подеок је превелик. Захтевана величина је %<PRIu64>, доступан простор за: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2886
+msgid "Failed to clear table."
+msgstr "Нисам успео да очистим табелу."
+
+#: lib/luks2/luks2_reencrypt.c:2972
+msgid "Reduced data size is larger than real device size."
+msgstr "Величина умањених података је већа од стварне величине уређаја."
+
+#: lib/luks2/luks2_reencrypt.c:2979
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Уређај података није поравнат на величину одељка шифровања (%<PRIu32> бајта)."
+
+#: lib/luks2/luks2_reencrypt.c:3013
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Помак података (%<PRIu64> одељка) је мањи од будућег помераја података (%<PRIu64> одељка)."
+
+#: lib/luks2/luks2_reencrypt.c:3020 lib/luks2/luks2_reencrypt.c:3508
+#: lib/luks2/luks2_reencrypt.c:3529
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Нисам успео да отворим „%s“ у искључивом режиму (већ мапиран или прикачен)."
+
+#: lib/luks2/luks2_reencrypt.c:3209
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Уређај није означен за ЛУКС2 поновно шифровање."
+
+#: lib/luks2/luks2_reencrypt.c:3226 lib/luks2/luks2_reencrypt.c:4181
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Нисам успео да учитам контекст ЛУКС2 поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3306
+msgid "Failed to get reencryption state."
+msgstr "Нисам успео да добавим стање поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3310 lib/luks2/luks2_reencrypt.c:3624
+msgid "Device is not in reencryption."
+msgstr "Уређај није у поновном шифровању."
+
+#: lib/luks2/luks2_reencrypt.c:3317 lib/luks2/luks2_reencrypt.c:3631
+msgid "Reencryption process is already running."
+msgstr "Процес поновног шифровања је већ покренут."
+
+#: lib/luks2/luks2_reencrypt.c:3319 lib/luks2/luks2_reencrypt.c:3633
+msgid "Failed to acquire reencryption lock."
+msgstr "Нисам успео да остварим закључавање поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3337
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Не могу да наставим са поновним шифровањем. Прво покрените опоравак поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3472
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Активна величина уређаја и величина затраженог поновног шифровања не одговарају."
+
+#: lib/luks2/luks2_reencrypt.c:3486
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "Неисправна величина уређаја је затражена у параметрима поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3563
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Поновно шифровање је у току. Не могу да обавим опоравак."
+
+#: lib/luks2/luks2_reencrypt.c:3732
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "ЛУКС2 поновно шифровање је већ покренуто у метаподацима."
+
+#: lib/luks2/luks2_reencrypt.c:3739
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Нисам успео да покренем ЛУКС2 поновно шифровање у метаподацима."
+
+#: lib/luks2/luks2_reencrypt.c:3834
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Нисам успео да поставим подеоке уређаја за следећу врућу зону поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3886
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Нисам успео да запишем метаподатаке гипкости поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:3893
+msgid "Decryption failed."
+msgstr "Дешифровање није успело."
+
+#: lib/luks2/luks2_reencrypt.c:3898
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Нисам успео да запишем област вруће зоне са почетком на %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3903
+msgid "Failed to sync data."
+msgstr "Нисам успео да усагласим податке."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Нисам успео да освежим метаподатке након тренутно завршеног поновног шифровања вруће зоне."
+
+#: lib/luks2/luks2_reencrypt.c:4000
+msgid "Failed to write LUKS2 metadata."
+msgstr "Нисам успео да запишем ЛУКС2 метаподатке."
+
+#: lib/luks2/luks2_reencrypt.c:4023
+msgid "Failed to wipe unused data device area."
+msgstr "Нисам успео да обришем област уређаја података."
+
+#: lib/luks2/luks2_reencrypt.c:4029
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Нисам успео да уклоним некоришћени (несвезани) утор кључа %d."
+
+#: lib/luks2/luks2_reencrypt.c:4039
+msgid "Failed to remove reencryption keyslot."
+msgstr "Нисам успео да уклоним утор кључа поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:4049
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Кобна грешка приликом поновног шифровања комада који почиње на %<PRIu64>, %<PRIu64> подеока дуг."
+
+#: lib/luks2/luks2_reencrypt.c:4053
+msgid "Online reencryption failed."
+msgstr "Поновно шифровање на мрежи није успело."
+
+#: lib/luks2/luks2_reencrypt.c:4058
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Не наставља са уређајем осим ако није ручно замењен метом грешке."
+
+#: lib/luks2/luks2_reencrypt.c:4112
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Не могу да наставим са поновним шифровањем. Неочекивано стање поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:4118
+msgid "Missing or invalid reencrypt context."
+msgstr "Недостаје или неисправан контекст поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt.c:4125
+msgid "Failed to initialize reencryption device stack."
+msgstr "Нисам успео да покренем поновно шифровање спремника уређаја."
+
+#: lib/luks2/luks2_reencrypt.c:4147 lib/luks2/luks2_reencrypt.c:4194
+msgid "Failed to update reencryption context."
+msgstr "Нисам успео да освежим контекст поновног шифровања."
+
+#: lib/luks2/luks2_reencrypt_digest.c:406
+msgid "Reencryption metadata is invalid."
+msgstr "Метаподаци поновног шифровања нису исправни."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Параметри шифровања утора кључа се могу поставити само за ЛУКС2 уређај."
+
+#: src/cryptsetup.c:108
+#, c-format
+msgid "Enter token PIN:"
+msgstr "Унесите ПИН скупине:"
+
+#: src/cryptsetup.c:110
+#, c-format
+msgid "Enter token %d PIN:"
+msgstr "Унесите %d ПИН скупине:"
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:966 src/cryptsetup.c:1293
+#: src/utils_reencrypt.c:1048 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Није откривен познат образац одреднице шифрера."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "УПОЗОРЕЊЕ: Параметар „--hash“ је занемарен у обичном режиму са наведеном кључном датотеком.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "УПОЗОРЕЊЕ: Опција „--keyfile-size“ је занемарена, величина читања је иста као величина кључа шифровања.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Открих потпис(е) уређаја на „%s“. Даље настављање може оштетити постојеће податке."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1040 src/cryptsetup.c:1088
+#: src/cryptsetup.c:1154 src/cryptsetup.c:1270 src/cryptsetup.c:1343
+#: src/cryptsetup.c:1994 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:275
+msgid "Operation aborted.\n"
+msgstr "Радња је обустављена.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Захтевана је опција „--key-file“."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Унесите „VeraCrypt PIM“: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Неисправна „PIM“ вредност: грешка обраде."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Неисправна „PIM“ вредност: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Неисправна „PIM“ вредност: изван опсега."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Није откривено заглавље уређаја са овом пропусном речи."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Уређај „%s“ није исправан „BITLK“ уређај."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Не могу да одредим величину кључа за „BITLK“, користите „--key-size“ опцију."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Избачај заглавља са кључем волумена је осетљив податак\n"
+"који омогућава приступ шифрованој партицији без лозинке.\n"
+"Овај избачај треба увек бити смештен шифрован на безбедном месту."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:2019
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Избачај заглавља са кључем волумена је осетљив податак\n"
+"који омогућава приступ шифрованој партицији без лозинке.\n"
+"Овај избачај треба бити смештен шифрован на безбедном месту."
+
+#: src/cryptsetup.c:664 src/veritysetup.c:321 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Уређај „%s“ је још увек активан и заказан за одложено уклањање.\n"
+
+#: src/cryptsetup.c:698
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Сразмеравање активног уређаја захтева кључ волумена у привеску кључева али је постављена „--disable-keyring“ опција."
+
+#: src/cryptsetup.c:845
+msgid "Benchmark interrupted."
+msgstr "Оцењивање је прекинуто."
+
+#: src/cryptsetup.c:866
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "„PBKDF2-%-9s“ Н/Д\n"
+
+#: src/cryptsetup.c:868
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "„PBKDF2-%-9s“ %7u понављања у секунди за %zu-битни кључ\n"
+
+#: src/cryptsetup.c:882
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s Н/Д\n"
+
+#: src/cryptsetup.c:884
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u понављања, %5u меморије, %1u паралелних нити (процесора) за %zu-битни кључ (захтева се %u ms време)\n"
+
+#: src/cryptsetup.c:908
+msgid "Result of benchmark is not reliable."
+msgstr "Резултат оцењивања није поуздан."
+
+#: src/cryptsetup.c:958
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Пробе су приближне користећи само меморију (без УИ смештаја).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:978
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Алгоритам | Кључ | Шифровање | Дешифровање\n"
+
+#: src/cryptsetup.c:982
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Шифрер „%s“ (са %i битним кључем) није доступан."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1001
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Алгоритам | Кључ | Шифровање | Дешифровање\n"
+
+#: src/cryptsetup.c:1012
+msgid "N/A"
+msgstr "Недоступно"
+
+#: src/cryptsetup.c:1037
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Откривени су незаштићени ЛУКС2 метаподаци поновног шифровања. Проверите да ли је радња поновног шифровања пожељна (видите „luksDump“ излаз)\n"
+"и наставите (са надоградњом метаподатака само ако знате да је радња безопасна."
+
+#: src/cryptsetup.c:1043
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Унесите пропусну реч да заштитите и надоградите метаподатке поновног шифровања: "
+
+#: src/cryptsetup.c:1087
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Да наставим са опоравком ЛУКС2 поновног шифровања?"
+
+#: src/cryptsetup.c:1096
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Унесите пропусну реч да проверите упит метаподатака поновног шифровања: "
+
+#: src/cryptsetup.c:1098
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Унесите пропусну реч за опоравак поновног шифровања: "
+
+#: src/cryptsetup.c:1153
+msgid "Really try to repair LUKS device header?"
+msgstr "Стварно да покушам да поправим заглавље ЛУКС уређаја?"
+
+#: src/cryptsetup.c:1177 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Брисање је прекинуто."
+
+#: src/cryptsetup.c:1182 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Бришем уређај да бих започео суму провере целовитости.\n"
+"Можете прекинути ово притиском на „CTRL+c“ (остатак необрисаног уређаја садржаће неисправну суму провере).\n"
+
+#: src/cryptsetup.c:1204 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Не могу да деактивирам привремени уређај „%s“."
+
+#: src/cryptsetup.c:1255
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Опција целовитости се може користити само за ЛУКС2 запис."
+
+#: src/cryptsetup.c:1260 src/cryptsetup.c:1320
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Неподржана опција величине ЛУКС2 метаподатака."
+
+#: src/cryptsetup.c:1269
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Датотека заглавља не постоји, да ли желите да је направите?"
+
+#: src/cryptsetup.c:1277
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Не могу да направим датотеку заглавља „%s“."
+
+#: src/cryptsetup.c:1300 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Није откривен познат образац одреднице целовитости."
+
+#: src/cryptsetup.c:1313
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Не могу да користим „%s“ као заглавље на-диску."
+
+#: src/cryptsetup.c:1337 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Ово ће неповратно да препише податке на „%s“."
+
+#: src/cryptsetup.c:1370 src/cryptsetup.c:1707 src/cryptsetup.c:1772
+#: src/cryptsetup.c:1876 src/cryptsetup.c:1942 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Нисам успео да подесим „pbkdf“ параметре."
+
+#: src/cryptsetup.c:1455
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Смањени померај података је допуштен само за откачена ЛУКС заглавља."
+
+#: src/cryptsetup.c:1466 src/cryptsetup.c:1778
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Не могу да одредим величину кључа за ЛУКС без утора кључа, користите „--key-size“ опцију."
+
+#: src/cryptsetup.c:1512
+msgid "Device activated but cannot make flags persistent."
+msgstr "Уређај је активиран али не могу да учиним заставице трајним."
+
+#: src/cryptsetup.c:1591 src/cryptsetup.c:1659
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Утор кључа „%d“ је изабран за брисање."
+
+#: src/cryptsetup.c:1603 src/cryptsetup.c:1663
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Ово је последњи утор кључа. Уређај ће постати неупотребљив након чишћења овог кључа."
+
+#: src/cryptsetup.c:1604
+msgid "Enter any remaining passphrase: "
+msgstr "Унесите неку преосталу пропусну реч: "
+
+#: src/cryptsetup.c:1605 src/cryptsetup.c:1665
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Радња је прекинута, утор кључа НИЈЕ обрисан.\n"
+
+#: src/cryptsetup.c:1641
+msgid "Enter passphrase to be deleted: "
+msgstr "Унесите пропусну реч за брисање: "
+
+#: src/cryptsetup.c:1691 src/cryptsetup.c:1925 src/cryptsetup.c:2505
+#: src/cryptsetup.c:2649
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Уређај „%s“ није исправан ЛУКС2 уређај."
+
+#: src/cryptsetup.c:1721 src/cryptsetup.c:1795 src/cryptsetup.c:1829
+msgid "Enter new passphrase for key slot: "
+msgstr "Унесите нову пропусну реч за утор кључа: "
+
+#: src/cryptsetup.c:1812 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Унесите неку постојећу пропусну реч: "
+
+#: src/cryptsetup.c:1880
+msgid "Enter passphrase to be changed: "
+msgstr "Унесите пропусну реч за мењање: "
+
+#: src/cryptsetup.c:1896 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Унесите нову пропусну реч: "
+
+#: src/cryptsetup.c:1946
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Унесите пропусну реч за утор кључа за претварање: "
+
+#: src/cryptsetup.c:1970
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Подржан је само један аргумент уређаја за радњу „isLuks“."
+
+#: src/cryptsetup.c:2078
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Утор кључа %d не садржи несвезани кључ."
+
+#: src/cryptsetup.c:2083
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Избачај заглавља са кључем волумена је осетљив податак\n"
+"Овај избачај треба увек бити смештен шифрован на безбедном месту."
+
+#: src/cryptsetup.c:2169 src/cryptsetup.c:2198
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "„%s“ није назив активног „%s“ уређаја."
+
+#: src/cryptsetup.c:2193
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "„%s“ није назив активног ЛУКС уређаја или недостаје заглавље."
+
+#: src/cryptsetup.c:2255 src/cryptsetup.c:2274
+msgid "Option --header-backup-file is required."
+msgstr "Захтевана је опција „--header-backup-file“."
+
+#: src/cryptsetup.c:2305
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "„%s“ није уређај управљан криптоподешавањем."
+
+#: src/cryptsetup.c:2316
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Освежавање није подржано за врсту уређаја „%s“"
+
+#: src/cryptsetup.c:2362
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Непозната врста уређаја метаподатака „%s“."
+
+#: src/cryptsetup.c:2364
+msgid "Command requires device and mapped name as arguments."
+msgstr "Наредба захтева уређај и мапирани назив као аргумент."
+
+#: src/cryptsetup.c:2385
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Ова радња ће обрисати све уторе кључева на уређају „%s“.\n"
+"Уређај ће постати неупотребљив након ове радње."
+
+#: src/cryptsetup.c:2392
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Радња је прекинута, утори кључева НИСУ обрисани.\n"
+
+#: src/cryptsetup.c:2431
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Неисправна ЛУКС врста, само „luks1“ и „luks2“ су подржане."
+
+#: src/cryptsetup.c:2447
+#, c-format
+msgid "Device is already %s type."
+msgstr "Уређај је већ „%s“ врсте."
+
+#: src/cryptsetup.c:2454
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Ова радња ће претворити „%s“ у „%s“ запис.\n"
+
+#: src/cryptsetup.c:2457
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Радња је прекинута, уређај НИЈЕ претворен.\n"
+
+#: src/cryptsetup.c:2497
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Недостаје опција „--priority“, „--label“ или „--subsystem“."
+
+#: src/cryptsetup.c:2531 src/cryptsetup.c:2568 src/cryptsetup.c:2588
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Скупина „%d“ није исправна."
+
+#: src/cryptsetup.c:2534 src/cryptsetup.c:2591
+#, c-format
+msgid "Token %d in use."
+msgstr "Скупина „%d“ је у употреби."
+
+#: src/cryptsetup.c:2546
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Нисам успео да додам „luks2-keyring“ скупину „%d“."
+
+#: src/cryptsetup.c:2554 src/cryptsetup.c:2617
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Нисам успео да доделим скупину „%d“ утору кључа %d."
+
+#: src/cryptsetup.c:2571
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Скупина „%d“ није у употреби."
+
+#: src/cryptsetup.c:2608
+msgid "Failed to import token from file."
+msgstr "Нисам успео да увезем скупину из датотеке."
+
+#: src/cryptsetup.c:2633
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Нисам успео да добавим скупину „%d“ за извоз."
+
+#: src/cryptsetup.c:2682
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Опција „--tcrypt-hidden“, „--tcrypt-system“ или „--tcrypt-backup“ је подржана само за ТКРИПТ уређај."
+
+#: src/cryptsetup.c:2685
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Опција „--veracrypt“ или „--disable-veracrypt“ је подржана само за ТКРИПТ врсту уређаја."
+
+#: src/cryptsetup.c:2688
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Опција „--veracrypt-pim“ је подржана само за „VeraCrypt“ сагласне уређаје."
+
+#: src/cryptsetup.c:2692
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Опција „--veracrypt-query-pim“ је подржана само за „VeraCrypt“ сагласне уређаје."
+
+#: src/cryptsetup.c:2694
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Опције „--veracrypt-pim“ и „--veracrypt-query-pim“ се узајамно искључују."
+
+#: src/cryptsetup.c:2703
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Опција „--persistent“ није допуштена са опцијом „--test-passphrase“."
+
+#: src/cryptsetup.c:2706
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Опције „--refresh“ и „--test-passphrase“ се узајамно искључују."
+
+#: src/cryptsetup.c:2709
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Опција „--shared“ је допуштена само за отварање обичног уређаја."
+
+#: src/cryptsetup.c:2712
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Опција „--skip“ је подржана само за отварање обичних и упетљаних уређаја."
+
+#: src/cryptsetup.c:2715
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Опција „--offset“ са отвореном радњом је подржана само за обичне и упетљане уређаје."
+
+#: src/cryptsetup.c:2718
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Опција „--tcrypt-hidden“ не може бити обједињена са „--allow-discards“."
+
+#: src/cryptsetup.c:2722
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Опција величине одељка са отвореном радњом је подржана само за обичне уређаје."
+
+#: src/cryptsetup.c:2726
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Опција великих IV одељака је подржана само за отварање обичних уређаја са величином одељка већом од 512 бајта."
+
+#: src/cryptsetup.c:2730
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT and BITLK devices."
+msgstr "Опција „--test-passphrase“ је допуштена само за отварање ЛУКС, „TCRYPT“ и „BITLK“ уређаја."
+
+#: src/cryptsetup.c:2733 src/cryptsetup.c:2756
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Опције „--device-size“ и „--size“ се не могу комбиновати."
+
+#: src/cryptsetup.c:2736
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Опција „--unbound“ је допуштена само за отварање лукс уређаја."
+
+#: src/cryptsetup.c:2739
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Опција „--unbound“ се не може користити без „--test-passphrase“."
+
+#: src/cryptsetup.c:2748 src/veritysetup.c:664 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Опције „--cancel-deferred“ и „--deferred“ се не могу користити у исто време."
+
+#: src/cryptsetup.c:2764
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Опције „--reduce-device-size“ и „--data-size“ се не могу комбиновати."
+
+#: src/cryptsetup.c:2767
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Опција „--active-name“ се може поставити само за ЛУКС2 уређај."
+
+#: src/cryptsetup.c:2770
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Опције „--active-name“ и „--force-offline-reencrypt“ се не могу комбиновати."
+
+#: src/cryptsetup.c:2778 src/cryptsetup.c:2808
+msgid "Keyslot specification is required."
+msgstr "Одредба утора кључа је потребна."
+
+#: src/cryptsetup.c:2786
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Опције „--align-payload“ и „--offset“ се не могу комбиновати."
+
+#: src/cryptsetup.c:2789
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Опција „--integrity-no-wipe“ се може користити само за радњу форматирања са проширењем целовитости."
+
+#: src/cryptsetup.c:2792
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Дозвољена је само једна опција „--use-[u]random“."
+
+#: src/cryptsetup.c:2800
+msgid "Key size is required with --unbound option."
+msgstr "Величина кључа је потребна са опцијом „--unbound“."
+
+#: src/cryptsetup.c:2819
+msgid "Invalid token action."
+msgstr "Неисправна радња скупине."
+
+#: src/cryptsetup.c:2822
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "„--key-description“ параметар је обавезан за радњу додавања скупине."
+
+#: src/cryptsetup.c:2826
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Радња захтева нарочиту скупину. Користите параметар „--token-id“."
+
+#: src/cryptsetup.c:2840
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<уређај> [--type <врста>] [<назив>]"
+
+#: src/cryptsetup.c:2840 src/veritysetup.c:487 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "отвара уређај као <назив>"
+
+#: src/cryptsetup.c:2841 src/cryptsetup.c:2842 src/cryptsetup.c:2843
+#: src/veritysetup.c:488 src/veritysetup.c:489 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<назив>"
+
+#: src/cryptsetup.c:2841 src/veritysetup.c:488 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "затвара уређај (уклања мапирање)"
+
+#: src/cryptsetup.c:2842 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "мења величину радног уређаја"
+
+#: src/cryptsetup.c:2843
+msgid "show device status"
+msgstr "показује стање уређаја"
+
+#: src/cryptsetup.c:2844
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <шифрер>]"
+
+#: src/cryptsetup.c:2844
+msgid "benchmark cipher"
+msgstr "шифрер оцењивања"
+
+#: src/cryptsetup.c:2845 src/cryptsetup.c:2846 src/cryptsetup.c:2847
+#: src/cryptsetup.c:2848 src/cryptsetup.c:2849 src/cryptsetup.c:2856
+#: src/cryptsetup.c:2857 src/cryptsetup.c:2858 src/cryptsetup.c:2859
+#: src/cryptsetup.c:2860 src/cryptsetup.c:2861 src/cryptsetup.c:2862
+#: src/cryptsetup.c:2863 src/cryptsetup.c:2864
+msgid "<device>"
+msgstr "<уређај>"
+
+#: src/cryptsetup.c:2845
+msgid "try to repair on-disk metadata"
+msgstr "покушава да поправи метаподатке на-диску"
+
+#: src/cryptsetup.c:2846
+msgid "reencrypt LUKS2 device"
+msgstr "ЛУКС2 уређај поновног шифровања"
+
+#: src/cryptsetup.c:2847
+msgid "erase all keyslots (remove encryption key)"
+msgstr "брише све уторе кључева (уклања кључ шифровања)"
+
+#: src/cryptsetup.c:2848
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "претвара ЛУКС из/у ЛУКС2 запис"
+
+#: src/cryptsetup.c:2849
+msgid "set permanent configuration options for LUKS2"
+msgstr "поставља трајне опције подешавања за ЛУКС2"
+
+#: src/cryptsetup.c:2850 src/cryptsetup.c:2851
+msgid "<device> [<new key file>]"
+msgstr "<уређај> [<нова датотека кључа>]"
+
+#: src/cryptsetup.c:2850
+msgid "formats a LUKS device"
+msgstr "форматира ЛУКС уређај"
+
+#: src/cryptsetup.c:2851
+msgid "add key to LUKS device"
+msgstr "додаје кључ у ЛУКС уређај"
+
+#: src/cryptsetup.c:2852 src/cryptsetup.c:2853 src/cryptsetup.c:2854
+msgid "<device> [<key file>]"
+msgstr "<уређај> [<датотека кључа>]"
+
+#: src/cryptsetup.c:2852
+msgid "removes supplied key or key file from LUKS device"
+msgstr "уклања достављени кључ или датотеку кључа из ЛУКС уређаја"
+
+#: src/cryptsetup.c:2853
+msgid "changes supplied key or key file of LUKS device"
+msgstr "мења достављени кључ или датотеку кључа ЛУКС уређаја"
+
+#: src/cryptsetup.c:2854
+msgid "converts a key to new pbkdf parameters"
+msgstr "претвара кључ у нове „pbkdf“ параметре"
+
+#: src/cryptsetup.c:2855
+msgid "<device> <key slot>"
+msgstr "<уређај> <утор кључа>"
+
+#: src/cryptsetup.c:2855
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "брише кључ са бројем <утор кључа> са ЛУКС уређаја"
+
+#: src/cryptsetup.c:2856
+msgid "print UUID of LUKS device"
+msgstr "исписује УЈИБ ЛУКС уређаја"
+
+#: src/cryptsetup.c:2857
+msgid "tests <device> for LUKS partition header"
+msgstr "испробава <уређај> за заглављем ЛУКС партиције"
+
+#: src/cryptsetup.c:2858
+msgid "dump LUKS partition information"
+msgstr "исписује податке ЛУКС партиције"
+
+#: src/cryptsetup.c:2859
+msgid "dump TCRYPT device information"
+msgstr "исписује податке ТКРИПТ уређаја"
+
+#: src/cryptsetup.c:2860
+msgid "dump BITLK device information"
+msgstr "исписује податке „BITLK“ уређаја"
+
+#: src/cryptsetup.c:2861
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Обуставља ЛУКС уређај и брише кључ (сви УИ су замрзнути)"
+
+#: src/cryptsetup.c:2862
+msgid "Resume suspended LUKS device"
+msgstr "Наставља са обустављеним ЛУКС уређајем"
+
+#: src/cryptsetup.c:2863
+msgid "Backup LUKS device header and keyslots"
+msgstr "Прави резерву заглавља „LUKS“ уређаја и утора кључева"
+
+#: src/cryptsetup.c:2864
+msgid "Restore LUKS device header and keyslots"
+msgstr "Враћа заглавље „LUKS“ уређаја и уторе кључева"
+
+#: src/cryptsetup.c:2865
+msgid "<add|remove|import|export> <device>"
+msgstr "<додај|уклони|увези|извези> <уређај>"
+
+#: src/cryptsetup.c:2865
+msgid "Manipulate LUKS2 tokens"
+msgstr "Управља ЛУКС2 скупинама"
+
+#: src/cryptsetup.c:2884 src/veritysetup.c:505 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<радња> је једна од следећих:\n"
+
+#: src/cryptsetup.c:2890
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+msgstr ""
+"\n"
+"Можете такође да користите старе надимке синтаксе <радње>:\n"
+"\tотварање: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tзатвори: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+
+#: src/cryptsetup.c:2894
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<назив> је уређај за стварање под „%s“\n"
+"<уређај> је шифровани уређај\n"
+"<утор кључа> је број ЛУКС утора кључа за мењање\n"
+"<датотека кључа> изборна датотека кључа за нови кључ за радњу „luksAddKey“\n"
+
+#: src/cryptsetup.c:2901
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Основни уграђени запис метаподатака је „%s“ (за „luksFormat“ радњу).\n"
+
+#: src/cryptsetup.c:2906 src/cryptsetup.c:2909
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Подршка прикључка спољне скупине за „LUKS2“ је „%s“.\n"
+
+#: src/cryptsetup.c:2906
+msgid "compiled-in"
+msgstr "преведено"
+
+#: src/cryptsetup.c:2907
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Путања прикључка спољне скупине за „LUKS2“: %s.\n"
+
+#: src/cryptsetup.c:2909
+msgid "disabled"
+msgstr "искључено"
+
+#: src/cryptsetup.c:2913
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Основни параметри уграђеног кључа и пропусне речи:\n"
+"\tНајвећа величина датотеке кључа: %dkB, Највећа дужина међудејствене пропусне речи %d (знака)\n"
+"Основни „PBKDF“ за ЛУКС1: %s, време понављања: %d (ms)\n"
+"Основни „PBKDF“ за ЛУКС2: %s\n"
+"\tВреме понављања: %d, Захтевана меморија: %dkB, Паралелне нити: %d\n"
+
+#: src/cryptsetup.c:2924
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Основни преведени параметри шифрера уређаја:\n"
+"\tпетља-АЕС: %s, Кључ %d бита\n"
+"\tобично: %s, Кључ: %d бита, Хеширање лозинке: %s\n"
+"\tЛУКС: %s, Кључ: %d бита, Хеширање ЛУКС заглавља: %s, РНГ: %s\n"
+
+#: src/cryptsetup.c:2933
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tЛУКС: Основна величина кључа са „XTS“ режимом (два унутрашња кључа) биће удвостручена.\n"
+
+#: src/cryptsetup.c:2951 src/veritysetup.c:644 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: захтева „%s“ као аргумент"
+
+#: src/cryptsetup.c:2997 src/utils_reencrypt_luks1.c:1194
+msgid "Key slot is invalid."
+msgstr "Утор кључа није исправан."
+
+#: src/cryptsetup.c:3024
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Величина уређаја мора бити умножак одељка од 512 бајта."
+
+#: src/cryptsetup.c:3029
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Неисправна одредба највеће величине вруће зоне поновног шифровања."
+
+#: src/cryptsetup.c:3043 src/cryptsetup.c:3055
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Величина кључа мора бити умножак од 8 бита"
+
+#: src/cryptsetup.c:3060
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Највећа величина смањења уређаја је 1 GiB."
+
+#: src/cryptsetup.c:3063
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Величина смањивања мора бити умножак одељка од 512 бајта."
+
+#: src/cryptsetup.c:3080
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Опција „--priority“ може бити само „ignore/normal/prefer“."
+
+#: src/cryptsetup.c:3099 src/veritysetup.c:568 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Приказује ову поруку помоћи"
+
+#: src/cryptsetup.c:3100 src/veritysetup.c:569 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Прикажите кратку поруку о коришћењу"
+
+#: src/cryptsetup.c:3101 src/veritysetup.c:570 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Исписује издање пакета"
+
+#: src/cryptsetup.c:3112 src/veritysetup.c:581 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Опције помоћи:"
+
+#: src/cryptsetup.c:3132 src/veritysetup.c:599 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[ОПЦИЈА...] <радња> <посебност-радње>"
+
+#: src/cryptsetup.c:3141 src/veritysetup.c:608 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Недостаје аргумент <радња>."
+
+#: src/cryptsetup.c:3211 src/veritysetup.c:639 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Непозната радња."
+
+#: src/cryptsetup.c:3229
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Опција „--key-file“ има првенство над наведеним аргументом датотеке кључа."
+
+#: src/cryptsetup.c:3235
+msgid "Only one --key-file argument is allowed."
+msgstr "Дозвољен је само један аргумент „--key-file“."
+
+#: src/cryptsetup.c:3240
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Функција произилажења кључа заснованог на пропусној речи (PBKDF) може бити само „pbkdf2“ или „argon2i/argon2id“."
+
+#: src/cryptsetup.c:3245
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "„PBKDF“ присиљена понављања се не могу комбиновати са опцијом времена понављања."
+
+#: src/cryptsetup.c:3256
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Опције „--keyslot-cipher“ и „--keyslot-key-size“ се морају користити заједно."
+
+#: src/cryptsetup.c:3264
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Није предузета никаква радња. Призвана опцијом „--test-args“.\n"
+
+#: src/cryptsetup.c:3277
+msgid "Cannot disable metadata locking."
+msgstr "Не могу да искључим закључавање метаподатака."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Наведена је неисправна ниска присолка."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Не могу да направим хеш слику „%s“ ради уписа."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Не могу да направим „FEC“ слику „%s“ ради уписа."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Не могу да направим корену хеш датотеку „%s“ ради уписа."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Не могу да пишем у корену хеш датотеку „%s“."
+
+#: src/veritysetup.c:196 src/veritysetup.c:472
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Уређај „%s“ није исправан „VERITY“ уређај."
+
+#: src/veritysetup.c:213 src/veritysetup.c:230
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Не могу да читам корену хеш датотеку „%s“."
+
+#: src/veritysetup.c:218
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Неисправна корена хеш датотека „%s“."
+
+#: src/veritysetup.c:239
+msgid "Invalid root hash string specified."
+msgstr "Наведена је неисправна ниска хеша корена."
+
+#: src/veritysetup.c:247
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Неисправна датотека потписа „%s“."
+
+#: src/veritysetup.c:254
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Не могу да прочитам датотеку потписа „%s“."
+
+#: src/veritysetup.c:277 src/veritysetup.c:291
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Наредба захтева „<root_hash>“ или „--root-hash-file“ опцију као аргумент."
+
+#: src/veritysetup.c:485
+msgid "<data_device> <hash_device>"
+msgstr "<уређај_података> <уређај_хеша>"
+
+#: src/veritysetup.c:485 src/integritysetup.c:534
+msgid "format device"
+msgstr "форматира уређај"
+
+#: src/veritysetup.c:486
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<уређај_података> <уређај_хеша> [<хеш_корена>]"
+
+#: src/veritysetup.c:486
+msgid "verify device"
+msgstr "проверава уређај"
+
+#: src/veritysetup.c:487
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<уређај_података> <назив> <уређај_хеша> [<хеш_корена>]"
+
+#: src/veritysetup.c:489 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "показује стање радног уређаја"
+
+#: src/veritysetup.c:490
+msgid "<hash_device>"
+msgstr "<уређај_хеша>"
+
+#: src/veritysetup.c:490 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "приказује податке на-диску"
+
+#: src/veritysetup.c:509
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<назив> јесте уређај за стварање под „%s“\n"
+"<уређај_података> јесте уређај података\n"
+"<уређај_хеша> јесте уређај који садржи податке проверавања\n"
+"<хеш_корена> хеш кореног чвора на <уређају_хеша>\n"
+
+#: src/veritysetup.c:516
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Основни преведени параметри дм-тачности:\n"
+"\tХеш: %s, Блок података (бајта): %u, Блок хеша (бајта): %u, Величина присолка: %u, Запис хеша: %u\n"
+
+#: src/veritysetup.c:654
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Опције „--ignore-corruption“ и „--restart-on-corruption“ се не могу користити заједно."
+
+#: src/veritysetup.c:659
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Опције „--panic-on-corruption“ и „--restart-on-corruption“ се не могу користити заједно."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Ово ће неповратно преписати податке на „%s“ и „%s“.\n"
+"Да задржите уређај података користите опцију „--no-wipe“ (а затим активирајте са „--integrity-recalculate“)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Форматирано ознаком величине %u, унутрашња целовитост „%s“.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Постављање заставице поновног рачунањ није подржано, можете узети у обзир коришћење опције „--wipe“."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Уређај „%s“ није исправан „INTEGRITY“ уређај."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<уређај_целовитости>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<уређај_целовитости> <назив>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<назив> јесте уређај за стварање под „%s“\n"
+"<уређај_целовитости> јесте уређај који садржи податке са ознакама целовитости\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Основни уграђени параметри дм-целовитости:\n"
+"\tАлгоритам провере суме: %s\n"
+" Највећа величина датотеке кључа: %dkB\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Неисправна величина „--%s“. Највећа је %u бајта."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Мора бити наведена и опција датотеке кључа и опција величине кључа."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Мора бити наведена и опција датотеке кључа целовитости журнала и опција величине кључа."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Алгоритам целовитости журнала мора бити наведен ако се користи кључ целовитости журнала."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Мора бити наведена и опција датотеке кључа шифровања журнала и опција величине кључа."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Алгоритам шифровања журнала мора бити наведен ако се користи кључ шифровања журнала."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Опције режима опоравка и битмапе се узајамно искључују."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Опције журнала се не могу користити у режиму битмапе."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Опције битмапе се могу користити само у режиму битмапе."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"УПОЗОРЕЊЕ!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Да ли сте сигурни? (Упишите „yes“ великим словима): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Грешка читања одговора из терминала."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Наредба је успела."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "погрешни или недостајући параметри"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "нема овлашћења или је лоша пропусна реч"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "нема више меморије"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "наведен је погрешан уређај или датотека"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "уређај већ постоји или је заузет"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "непозната грешка"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Наредба није успела са кодом %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Утор кључа „%i“ је направљен."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Утор кључа „%i“ је откључан."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Утор кључа „%i“ је уклоњен."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Скупина „%i“ је направљена."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Скупина „%i“ је уклоњена."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Ниједна скупина неће бити откључана овим ПИН-ом."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Скупина „%i“ захтева ПИН."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Скупина (врста „%s“) захтева ПИН."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Скупина „%i“ не може да откључа додељени утор кључа (погрешна лозинка)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Скупина (врста „%s“) не може да откључа додељени утор кључа (погрешна лозинка)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Скупина „%i“ захтева додтни ресурс који недостаје."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Скупина (врста „%s“) захтева додтни ресурс који недостаје."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Нема доступне употребљиве скупине (врста „%s“)."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Нема доступне употребљиве скупине."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Не могу да прочитам датотеку кључа „%s“."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Не могу да прочитам %d бајта из датотеке кључа „%s“."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Не могу да отворим датотеку кључа „%s“ за упис."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Не могу да пишем у датотеку кључа „%s“."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> дана"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "%4<PRIu64> „%s“ је записано"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "брзина %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Напредовање: %5.1f%%, ETA %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Завршено, време %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Не могу да проверим квалитет лозинке: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Провера квалитета лозинке није успела:\n"
+" %s"
+
+#: src/utils_password.c:81
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Провера квалитета лозинке није успела: Лоша шифра (%s)"
+
+#: src/utils_password.c:231 src/utils_password.c:245
+msgid "Error reading passphrase from terminal."
+msgstr "Грешка читања пропусне речи из терминала."
+
+#: src/utils_password.c:243
+msgid "Verify passphrase: "
+msgstr "Провери пропусну реч: "
+
+#: src/utils_password.c:250
+msgid "Passphrases do not match."
+msgstr "Пропусне речи се не подударају."
+
+#: src/utils_password.c:288
+msgid "Cannot use offset with terminal input."
+msgstr "Не могу да користим померај са улазом терминала."
+
+#: src/utils_password.c:292
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Унесите пропусну реч: "
+
+#: src/utils_password.c:295
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Унесите пропусну реч за „%s“: "
+
+#: src/utils_password.c:329
+msgid "No key available with this passphrase."
+msgstr "Нема доступног кључа са овом пропусном речју."
+
+#: src/utils_password.c:331
+msgid "No usable keyslot is available."
+msgstr "Нема доступног употребљивог утора кључа."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Не могу да одрадим проверу пропусне речи на не-конзолним улазима."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Нисам успео да отворим датотеку „%s“ у режиму само за читање."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Обезбеђује исправан „JSON“ ЛУКС2 скупине:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Нисам успео да прочитам „JSON“ датотеку."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Читање је прекинуто."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Нисам успео да отворим датотеку „%s“ у режиму писања."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Писање је прекинуто."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Нисам успео да упишем „JSON“ датотеку."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Самооткривени активан дм уређај „%sд за уређај података „%s“.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Нисам успео да самооткријем држаче „%s“ уређаја."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Уређај „%s“ није блок уређај.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Не могу да одлучим да ли је уређај „%s“ активиран или није.\n"
+"Да ли сигурно желите да наставите са поновним шифровањем у режиму ван мреже?\n"
+"То може довести до оштећења података ако је уређај заправо активиран.\n"
+"Да покренете поновно шифровање у режиму на мрежи, користите параметар „--active-name“.\n"
+
+#: src/utils_reencrypt.c:175
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Уређај није у ЛУКС2 шифровању. Сукобљавајућа опција „--encrypt“."
+
+#: src/utils_reencrypt.c:180
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Уређај није у ЛУКС2 шифровању. Сукобљавајућа опција „--decrypt“."
+
+#: src/utils_reencrypt.c:187
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Уређај је у поновном шифровању користећи гипкост помака података. Захтевана опција „--resilience“ се не може применити."
+
+#: src/utils_reencrypt.c:193 src/utils_reencrypt.c:199
+#: src/utils_reencrypt.c:205 src/utils_reencrypt.c:681
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Захтевана опција „--resilience“ се не може применити на текућој радњи поновног шифровања."
+
+#: src/utils_reencrypt.c:258
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Уређај захтева опоравак поновног шифровања. Прво покрените поправку."
+
+#: src/utils_reencrypt.c:268
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Уређај „%s“ је већ у ЛУКС2 поновном шифровању. Да ли желите да наставите са претходно започетом радњом?"
+
+#: src/utils_reencrypt.c:314
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Старо ЛУКС2 поновно шифровања више није подржано."
+
+#: src/utils_reencrypt.c:379
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Поновно шифровање уређаја са профилом целовитости није подржано."
+
+#: src/utils_reencrypt.c:410
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Захтевано „--sector-size“ %<PRIu32> је несагласно са „%s“ суперблоком\n"
+"(величина блока: %<PRIu32> бајта) је откривено на уређају „%s“."
+
+#: src/utils_reencrypt.c:455
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Шифровање без откаченог заглавља (--header) није могуће без смањења величине уређаја података (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:461
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Затражени померај података мора бити мањи или једнак половини параметра „--reduce-device-size“."
+
+#: src/utils_reencrypt.c:471
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Подешавам „--reduce-device-size“ вредност на двоструко од „--offset“ %<PRIu64> (подеока).\n"
+
+#: src/utils_reencrypt.c:501
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Привремена датотека заглавља „%s“ већ постоји. Прекидам."
+
+#: src/utils_reencrypt.c:503 src/utils_reencrypt.c:510
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Не могу да направим привремену датотеку заглавља „%s“."
+
+#: src/utils_reencrypt.c:535
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Величина ЛУКС2 метаподатака је већа од вредности помака података."
+
+#: src/utils_reencrypt.c:572
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Нисам успео да ставим ново заглавље на главу уређаја „%s“."
+
+#: src/utils_reencrypt.c:582
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "„%s/%s“ је сада активно и спремно за шифровање на мрежи.\n"
+
+#: src/utils_reencrypt.c:618
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Радни уређај „%s“ није ЛУКС2."
+
+#: src/utils_reencrypt.c:646
+msgid "Restoring original LUKS2 header."
+msgstr "Враћам изворно ЛУКС2 заглавље."
+
+#: src/utils_reencrypt.c:654
+msgid "Original LUKS2 header restore failed."
+msgstr "Враћање изворног ЛУКС2 заглавља није успело."
+
+#: src/utils_reencrypt.c:722
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Нисам успео да додам дозволе за читање/писање у извезену датотеку заглавља."
+
+#: src/utils_reencrypt.c:775
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Покретање поновног шифровања није успело. Резерва заглавља је доступна у „%s“."
+
+#: src/utils_reencrypt.c:803
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "ЛУКС2 дешифровање је подржано само са откаченим уређајем заглавља (са померајем података постављеним на 0)."
+
+#: src/utils_reencrypt.c:934 src/utils_reencrypt.c:943
+msgid "Not enough free keyslots for reencryption."
+msgstr "Нема довољно слободних утора кључева за поновно шифровање."
+
+#: src/utils_reencrypt.c:964 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Датотека кључа може бити коришћена само са „--key-slot“ или са тачно једним активним утором кључа."
+
+#: src/utils_reencrypt.c:973 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Унесите пропусну реч за утор кључа %d: "
+
+#: src/utils_reencrypt.c:985
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Унесите пропусну реч за утор кључа %u: "
+
+#: src/utils_reencrypt.c:1037
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Пребацујем шифрера података на „%s“.\n"
+
+#: src/utils_reencrypt.c:1091
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Никакви параметри подеока података нису измењени. Поновно шифровање је прекинуто."
+
+#: src/utils_reencrypt.c:1187
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Повећање величине одељка шифровања на не прикљученом уређају није подржано.\n"
+"Прво покрените уређај или користите опцију „--force-offline-reencrypt“ (опасно, вруће!!)."
+
+#: src/utils_reencrypt.c:1227 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Поновно шифровање је прекинуто."
+
+#: src/utils_reencrypt.c:1232
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Настављам са ЛУКС2 поновним шифровањем у насилном ванмрежном режиму.\n"
+
+#: src/utils_reencrypt.c:1249
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Уређај „%s“ садржи оштећене ЛУКС2 метаподатке. Прекидам радњу."
+
+#: src/utils_reencrypt.c:1265 src/utils_reencrypt.c:1287
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Уређај „%s“ већ јесте ЛУКС уређај. Прекидам радњу."
+
+#: src/utils_reencrypt.c:1293
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Уређај „%s“ је већ у ЛУКС2 поновном шифровању. Прекидам радњу."
+
+#: src/utils_reencrypt.c:1366
+msgid "LUKS2 decryption requires --header option."
+msgstr "ЛУКС2 дешифровање захтева опцију „--header“."
+
+#: src/utils_reencrypt.c:1414
+msgid "Command requires device as argument."
+msgstr "Наредба захтева уређај као аргумент."
+
+#: src/utils_reencrypt.c:1427
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Сукобљавајућа издања. Уређај „%s“ је ЛУКС1."
+
+#: src/utils_reencrypt.c:1433
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Сукобљавајућа издања. Уређај „%s“ је у ЛУКС1 поновном шифровању."
+
+#: src/utils_reencrypt.c:1439
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Сукобљавајућа издања. Уређај „%s“ је ЛУКС2."
+
+#: src/utils_reencrypt.c:1445
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Сукобљавајућа издања. Уређај „%s“ је у ЛУКС2 поновном шифровању."
+
+#: src/utils_reencrypt.c:1451
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "ЛУКС2 поновно шифровање је већ покренуто. Прекидам радњу."
+
+#: src/utils_reencrypt.c:1458
+msgid "Device reencryption not in progress."
+msgstr "Поновно шифровање уређаја није у току."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Не могу изричито да отворим „%s“, уређај је у употреби."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Додела поређане меморије није успела."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Не могу да читам уређај „%s“."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Означавам ЛУКС1 уређај „%s“ неупотребљивим."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Не могу да пишем на уређају „%s“."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Не могу да запишем датотеку дневника поновног шифровања."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Не могу да прочитам датотеку дневника поновног шифровања."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Погрешан формат дневника."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Датотека дневника „%s“ постоји, настављам поновно шифровање.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Покрећем привремени уређај користећи старо ЛУКС заглавље."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Покрећем привремени уређај користећи ново ЛУКС заглавље."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Покретање привременог уређаја није успело."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Нисам успео да поставим померај података."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Нисам успео да поставим величину метаподатака."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Направљено је ново ЛУКС заглавље за уређај „%s“."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Направљена је резерва „%s“ заглавља за уређај „%s“."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Није успело прављење резерве ЛУКС заглавља."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Не могу да повратим „%s“ заглавље на уређају „%s“."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Повраћено је „%s“ заглавље на уређају „%s“."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Не могу да отворим привремени ЛУКС уређај."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Не могу да добавим величину уређаја."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "УИ грешка за време поновног шифровања."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Достављени УУИД није исправан."
+
+#: src/utils_reencrypt_luks1.c:1220
+msgid "Cannot open reencryption log file."
+msgstr "Не могу да отворим датотеку дневника поновног шифровања."
+
+#: src/utils_reencrypt_luks1.c:1226
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Нема описа у напретку, достављени УУИД се може користити само за настављање заустављеног процеса дешифровања."
+
+#: src/utils_reencrypt_luks1.c:1280
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Поновно шифровање ће изменити: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1281
+msgid "volume key"
+msgstr "кључ волумена"
+
+#: src/utils_reencrypt_luks1.c:1283
+msgid "set hash to "
+msgstr "поставља хеш на "
+
+#: src/utils_reencrypt_luks1.c:1284
+msgid ", set cipher to "
+msgstr ", поставља шифрера на "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "УПОЗОРЕЊЕ: Уређај „%s“ већ садржи „%s“ потпис партиције.\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "УПОЗОРЕЊЕ: Уређај „%s“ већ садржи „%s“ потпис суперблока.\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Нисам успео да покренем пробе потписа уређаја."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Нисам успео да добавим податке уређаја „%s“."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Нисам успео да отворим датотеку „%s“ у режиму читања/писања."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Постојећи потпис „%s“ партиције на уређају „%s“ биће обрисан."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Постојећи потпис „%s“ суперблока на уређају „%s“ биће обрисан."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Нисам успео да обришем потпис уређаја."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Нисам успео да испробам уређај „%s“ за потписом."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Неисправна одредба величине у параметру „--%s“."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Опција „--%s“ није дозвољена са радњом „%s“."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Нисам успео да запишем „json“ скупине безбедне шкољке."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Експериментални прикључак „cryptsetup“ прикључка за откључавање ЛУКС\" уређаја са скупином повезаномна сервер безбедне шкољке\\vОвај прикључак тренутно омогућава само додавање скупине постојећем утору кључа.\n"
+"\n"
+"Наведени сервер безбедне шкољке мора да садржи датотеку кључа на наведеној путањи са лозинком за постојећи утор кључа на уређају.\n"
+"Достављене креденцијале ће користити „cryptsetup“ да добави лозинку приликом отварања уређаја користећи скупину.\n"
+"\n"
+"Напомена: Информација достављена приликом додавања скупине (адреса сервера безбедне шкољке, корисник и путање) биће смештена у ЛУКС2 заглављу у обичном тексту."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<радња> <уређај>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Опције за радњу „add“ (додај):"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "ИП адреса/УРЛ удаљеног сервера за ову скупину"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Корисничко име коришћено за удаљени сервер"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Путања до датотеке кључа на удаљеном серверу"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Путања до кључа безбедне шкољке за повезивање на удаљени сервер"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Утор кључа коме се додељује скупина. Ако није наведено, скупина ће бити додељена првом утору кључа који поклопи достављену лозинку."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Опште опције:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Приказује опширније поруке о грешкама"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Приказује поруке прочишћавања"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Приказује поруке прочишћавања укључујући „JSON“ метаподатке"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Нисам успео да отворим и увезем приватни кључ:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Нисам успео да увезем приватни кључ (заштићен лозинком?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "„%s@%s“ лозинка: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Нисам успео да обрадим аргументе.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Мора бити наведена радња\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Уређај мора бити наведен за радњу „%s“.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Сервер безбедне шкољке мора бити наведен за радњу „%s“.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Корисник безбедне шкољке мора бити наведен за радњу „%s“.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Путања безбедне шкољке мора бити наведена за радњу „%s“.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Путања кључа безбедне шкољке мора бити наведена за радњу „%s“.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Нисам успео да отворим „%s“ користећи достављена уверења.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Само радња „add“ (додај) је тренутно подржана овим прикључком.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Не могу да направим сфтп сесију: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Не могу да покренем сфтп сесију: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Не могу да отворим сфтп сесију: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Не могу да добавим податке сфтп датотеке: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Нема довољно меморије.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Не могу да прочитам удаљени кључ: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Повезивање није успело: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Сервер није познат: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Метода потврђивања идентитета јавног кључа није допуштена на домаћину.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Грешка потврђивања идентитета јавног кључа: "
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Нисам успео да прочитам „BITLK“ потпис из „%s“."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Неисправан или непознат потпис за „BITLK“ уређај."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Нисам успео да очистим податке подеока резерве."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Нисам успео да искључим заставицу захтева поновног шифровања."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Шифровање је подржано само за ЛУКС2 запис."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "Откривен је ЛУКС уређај на „%s“. Да ли желите опет да шифрујете тај ЛУКС уређај?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "Само је ЛУКС2 запис тренутно подржан. Користите алат „cryptsetup-reencrypt“ за ЛУКС1."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Старо ванмрежно поновно шифровање је већ у току. Користите помагало „cryptsetup-reencrypt“."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "ЛУКС2 уређај није у поновном шифровању."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "Постављам заставицу ЛУКС2 ванмрежног поновног шифровања на уређају „%s“."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Ово издање „cryptsetup-reencrypt“ не може да ради са новом унутрашњом врстом скупине „%s“."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Нисам успео да прочитам заставице активирања из заглавља резерве."
+
+#~ msgid "Failed to read requirements from backup header."
+#~ msgstr "Нисам успео да прочитам потрепштине из заглавља резерве."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "Измењени су „pbkdf“ параметри у утору кључа %i."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Само вредности између 1 MiB и 64 MiB су допуштене завеличину блока поновног шифровања."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "Највећа величина смањења уређаја је 64 MiB."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[ОПЦИЈА...] <уређај>"
+
+#~ msgid "Argument required."
+#~ msgstr "Потребан је аргумент."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "Опција „--new“ се мора користити са „--reduce-device-size“ или „--header“."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "Опција „--keep-key“ може да се користи само са „--hash“, „--iter-time“ или „--pbkdf-force-iterations“."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "Опција „--new“ не може да се користи са „--decrypt“."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "Опција „--decrypt“ није сагласна са наведеним параметрима."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "Опција „--uuid“ је дозвољена само заједно са „--decrypt“."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Неисправна лукс врста. Користите: „luks“, „luks1“ или „luks2“."
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Уређај „%s“ је у употреби. Не могу да наставим са радњом форматирања."
+
+#~ msgid "No free token slot."
+#~ msgstr "Нема слободног утора скупине."
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Неисправна врста ЛУКС уређаја."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Шифрер коришћен за шифровање диска (видите „/proc/crypto“)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Хеш коришћен за стварање кључа шифровања из лозинке"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Проверава лозинку тражећи је два пута"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Чита кључ из датотеке"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Чита (главни) кључ вочумена из датотеке."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Даје (главни) кључ волумена уместо података утора кључева"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Величина кључа шифровања"
+
+#~ msgid "BITS"
+#~ msgstr "БИТА"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Ограничава читање из датотеке кључа"
+
+#~ msgid "bytes"
+#~ msgstr "бајта"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Број бајтова за прескакање у датотеци кључа"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Ограничава читање из новододате датотеке кључа"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Број бајтова за прескакање у новододатој датотеци кључа"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Број утора за нови кључ (основно је први слободан)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Величина уређаја"
+
+#~ msgid "SECTORS"
+#~ msgstr "ОДЕЉЦИ"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Користи само наведену величину уређаја (занемарује остатак уређаја). ОВО ЈЕ ОПСАНО!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Почетни померај у позадинском уређају"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Број одељака шифрованих података за прескакање на почетку"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Прави мапирање само за читање"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Не тражи потврђивање"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Време за упит међудејствене лозинке (у секундама)"
+
+#~ msgid "secs"
+#~ msgstr "секунде"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Напредак освежења реда (у секундама)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Колико често унос лозинке може бити покушан"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Поравнава утовар на границе <n> одељка — за „luksFormat“"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Датотека са резервом „LUKS“ заглавља и уторима кључева"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Користи „/dev/random“ за стварање кључа волумена"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Користи „/dev/urandom“ за стварање кључа волумена"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Дели уређај са другим не-преклапајућим подеоком шифрера"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "УЈИБ уређаја за коришћење"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Допушта одбацивања (тј. СКРАЋЕЊЕ) захтева за уређај"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Уређај или датотека са одвојеним ЛУКС заглављем"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Не покреће уређај, само проверава лозинку"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Користи скривено заглавље (скривени ТКРИПТ уређај)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Уређај је ТКРИПТ диск система (са подизачем система)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Користи резервно (другоразредно) ТКРИПТ заглавље"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Такође обавља преглед за уређајима сагласним са Веракриптом"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Лични умножавач понављања за „VeraCrypt“ сагласан уређај"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Пропитује лични умножавач понављања за „VeraCrypt“ сагласан уређај"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Врста метаподатака уређаја: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Искључује проверу квалитета лозинке (ако је укључена)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Користи опцију сагласности перформансе „same_cpu_crypt“ дм-крипта"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Користи опцију сагласности перформансе „submit_from_crypt_cpus“ дм-крипта"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Заобилази радни ред „dm-crypt“ и захтев читања процеса истовремено"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Заобилази радни ред „dm-crypt“ и захтев писања процеса истовремено"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "Уклањање уређаја је одложено све док га последњи корисник не затвори"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Користи опште закључавање за серијализацију меморије чврстог „PBKDF“ („OOM“ заобилазница)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "Време „PBKDF“ понављања за ЛУКС (у милисекундама)"
+
+#~ msgid "msecs"
+#~ msgstr "милисекунде"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "„PBKDF“ алгоритам (за ЛУКС2): argon2i, argon2id, pbkdf2"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "Ограничење трошка „PBKDF“ меморије"
+
+#~ msgid "kilobytes"
+#~ msgstr "килобајта"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "Трошак „PBKDF“ паралеле"
+
+#~ msgid "threads"
+#~ msgstr "нити"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "Трошак „PBKDF“ понављања (присилно, искључује оцењивање)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Првенство утора кључа: ignore, normal, prefer"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Искључује закључавање метаподатака на-диску"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Искључује учитавање кључева волумена путем привеска кернела"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Алгоритам целовитости података (само ЛУКС2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Искључује журнал за уређај целовитости"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Не брише уређај након форматирања"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Користи неделотворно застарело допуњавање (стари кернели)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Не тражи пропусну реч ако активација скупином не успе"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Број скупине (основно: било који)"
+
+#~ msgid "Key description"
+#~ msgstr "Опис кључа"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Величина одељка шифровања (основно: 512 бајта)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Употреба IV је убројано у величину одељка (не у 512 бајта)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Поставља трајним заставице активирања за уређај"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Поставља натпис за ЛУКС2 уређај"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Поставља натпис подсистема за ЛУКС2 уређај"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Ствара или избацује неувезане (не додељене подеоке података) ЛУКС2 уторе кључа"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Чита или записује „json“ из или у датотеку"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Величина области метаподатака ЛУКС2 заглавља"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Величина области утора кључева ЛУКС2 заглавља"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Освежава (поново активира) уређај са новим параметрима"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "ЛУКС2 утор кључа: Величина кључа шифровања"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "ЛУКС2 утор кључа: Шифрер коришћен за шифровање исека кључа"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Шифрује ЛУКС2 уређај (у месту шифровање)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Дешифрује ЛУКС2 уређај (уклања шифровање)."
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Покреће ЛУКС2 поновно шифровање само у метаподацима."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Наставља само са започетим ЛУКС2 поновним шифровањем."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Смањује величину уређаја података (премешта померај података). ОВО ЈЕ ОПАСНО!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Највећа величина вруће зоне поновног шифровања."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Врста гипкости вруће зоне поновног шифровања (checksum,journal,none)"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Хеш суме првере вруће зоне поновног шифровања"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Заобилази самооткривање уређаја дм уређаја за поновно шифровање"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "Опција „--deferred“ је допуштена само за наредбу затварања."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "Опција „--allow-discards“ је допуштена само за радњу отварања."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "Опција „--persistent“ је допуштена само за радњу отварања."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "Опција „--serialize-memory-hard-pbkdf“ је допуштена само за радњу отварања."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Опција „--key-size“ је допуштена само за „luksFormat“, „luksAddKey“, отварање\n"
+#~ "и оцењивање. Да ограничите читање из датотеке кључа користите „--keyfile-size=(бајтова)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "Опција „--integrity“ је допуштена само за „luksFormat“ (ЛУКС2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Опције „--label“ и „--subsystem“ су допуштене само за „luksFormat“ и „config LUKS2“."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "Негативан број за опцију није допуштен."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "Опција „--use-[u]random“ је допуштена само за „luksFormat“."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "Опција „--uuid“ је допуштена само за „luksFormat“ и „luksUUID“."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "Опција „--align-payload“ је допуштена само за „luksFormat“."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Опције „--luks2-metadata-size“ и „--opt-luks2-keyslots-size“ су допуштене само за „luksFormat“ са ЛУКС-ом2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Неисправна одредба величине ЛУКС2 метаподатака."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Неисправна одредба величине ЛУКС2 утора кључева."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "Опција „--offset“ је подржана само за отварање обичних и упетљаних уређаја, „luksFormat“ и поновно шифровање уређаја."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Достављен је неисправан аргумент за параметар „--veracrypt-pim“."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "Опција величине сектора није подржана за ову наредбу."
+
+#~ msgid "Option --unbound may be used only with luksAddKey and luksDump actions."
+#~ msgstr "Опција „--unbound“ се може користити само са радњама „luksAddKey“ и „luksDump“."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "Опција „--refresh“ се може користити само са радњом отварања."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "Неисправна одредба величине уређаја."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Прекорачење величине смањења."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Не користи суперблок тачности"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Врста записа (1 — обично, 0 — изворни Хром ОС)"
+
+#~ msgid "number"
+#~ msgstr "број"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Величина блока на уређају података"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Величина блока на уређају хеша"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "Бајтови „FEC“ парности"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Број блокова у датотеци података"
+
+#~ msgid "blocks"
+#~ msgstr "блокови"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Путања до уређаја са подацима исправке грешке"
+
+#~ msgid "path"
+#~ msgstr "путања"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Почетни померај на уређају хеша"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Почетни померај на „FEC“ уређају"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Алгоритам хеша"
+
+#~ msgid "string"
+#~ msgstr "ниска"
+
+#~ msgid "Salt"
+#~ msgstr "Присолак"
+
+#~ msgid "hex string"
+#~ msgstr "ниска хеша"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Путања до датотеке потписа хеша корена"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Поново покреће језгро ако је откривено оштећење"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Успаничи језгро ако је откривено оштећење"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Занемарује оштећење, само га бележи у дневник"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Не проверава нулиране блокове"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Проверава блок података само приликом првог читања"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Опције „--ignore-corruption“, „--restart-on-corruption“ или „--ignore-zero-blocks“ су дозвољене само за радње отварања."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "Опција „--root-hash-signature“ се може користити само за радњу отварања."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Путања до уређаја података (ако је одвојен)"
+
+#~ msgid "Journal size"
+#~ msgstr "Величина журнала"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Подеоци преплетања"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Жиг журнала"
+
+#~ msgid "percent"
+#~ msgstr "проценат"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Време предаје журнала"
+
+#~ msgid "ms"
+#~ msgstr "ms"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Број 512-битних подеока по биту (режим битмапе)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Време испирања режима битмапе"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Величина ознаке (по подеоку)"
+
+#~ msgid "Sector size"
+#~ msgstr "Величина сектора"
+
+#~ msgid "Buffers size"
+#~ msgstr "Величина међумеморија"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Алгоритам целовитости података"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Величина кључа целовитости података"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Чита кључ целовитости из датотеке"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Алгоритам целовитости журнала"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Величина кључа целовитости журнала"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Чита кључ целовитости журнала из датотеке"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Алгоритам шифровања журнала"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Величина кључа шифровања журнала"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Чита кључ шифровања журнала из датотеке"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Режим опоравка (без журнала, без провере ознаке)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Користи битмапу да прати измене и да искључи журнал за уређај целовитости"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Аутоматски поново израчунава почетне ознаке."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Не штити суперблок са „HMAC“-ом (стари кернели)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Допушта поновно израчунавање волумена са „HMAC“ кључевима (стари кернели)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "Опција „--integrity-recalculate“ се може користити само за радњу отварања."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Опције „--journal-size“, „--interleave-sectors“, „--sector-size“, „--tag-size“ и „--no-wipe“ се могу користити само за радњу форматирања."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "Неисправна одредба величине журнала."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Величина блока поновног шифровања"
+
+#~ msgid "MiB"
+#~ msgstr "MiB"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Не мења кључ, нема поновног шифровања области података"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Чита (главни) кључ волумена из датотеке"
+
+#~ msgid "PBKDF2 iteration time for LUKS (in ms)"
+#~ msgstr "Време ПБКДФ2 понављања за ЛУКС (у милисекундама)"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Користи непосредни-уи приликом приступа уређајима"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Користи ф-усаглашавање након сваког блока"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Освежава датотеку дневника након сваког блока"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Користи само овај утор (остали ће бити искључени)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Прави ново заглавље на нешифрованом уређају"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Трајно дешифрује уређај (уклања шифровање)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "УЈИБ коришћен за настављање дешифровања"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Врста ЛУКС метаподатака: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "УПОЗОРЕЊЕ: Директоријум закључавања „%s/%s“ недостаје!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Неисправни параметри величине за уређај тачности."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "Алгоритам целовитости мора бити наведен ако се користи кључ целовитости."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Погрешна величина кључа."
+
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands."
+#~ msgstr "Параметар „--refresh“ је дозвољен само са наредбама „open“ или „refresh“."
+
+#~ msgid "Replaced with key slot %d.\n"
+#~ msgstr "Замењен је исеком кључа „%d“.\n"
+
+#~ msgid "Function not available in FIPS mode.\n"
+#~ msgstr "Функција није доступна у ФИПС режиму.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "Превише нивоа стабла за волумен тачности.\n"
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "грешка доделе меморије у „action_luksFormat“"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "Кључ „%d“ није радан. Не могу да очистим.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<назив> <уређај_података> <уређај_хеша> <хеш_корена>"
+
+#~ msgid "create active device"
+#~ msgstr "прави радни уређај"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "уклања (искључује) уређај"
+
+#~ msgid "Activated keyslot %i.\n"
+#~ msgstr "Покренути исек кључа %i.\n"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Напредовање: %5.1f%%, ЕТА %02llu:%02llu, %4llu MiB је записано, брзина %5.1f MiB/s%s"
+
+#~ msgid "Interrupted by a signal.\n"
+#~ msgstr "Прекинуто сигналом.\n"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Не могу да пронађем слободан уређај повратне петље.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Не могу да отворим уређај „%s“\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Не могу да користим прослеђени УУИД док је дешифровање у току.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "Означавам ЛУКС уређај „%s“ употребљивим.\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "УПОЗОРЕЊЕ: ово је пробни код, може потпуно да оштети ваше податке.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "Није успела провера ФИПС провере суме.\n"
diff --git a/po/sv.po b/po/sv.po
new file mode 100644
index 0000000..69eb18e
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,4527 @@
+# Swedish translation for cryptsetup.
+# Copyright © 2022 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+#
+# Daniel Nylander <po@danielnylander.se>, 2009.
+# Josef Andersson <l10nl18nsweja@gmail.com>, 2016-2022.
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.5.0-rc1\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2022-07-14 14:04+0200\n"
+"PO-Revision-Date: 2022-11-11 12:23+0100\n"
+"Last-Translator: Josef Andersson <l10nl18nsweja@gmail.com>\n"
+"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Lokalize 22.08.3\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: lib/libdevmapper.c:417
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Det går inte att initiera device-mapper, kör som icke-root-användare."
+
+#: lib/libdevmapper.c:420
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Det går inte att initiera device-mapper. Är kärnmodulen dm_mod inläst?"
+
+#: lib/libdevmapper.c:1171
+msgid "Requested deferred flag is not supported."
+msgstr "Begärd flagga deferred stöds inte."
+
+#: lib/libdevmapper.c:1240
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID för enheten %s förkortades."
+
+#: lib/libdevmapper.c:1570
+msgid "Unknown dm target type."
+msgstr "Okänd måltyp dm."
+
+#: lib/libdevmapper.c:1694 lib/libdevmapper.c:1699 lib/libdevmapper.c:1763
+#: lib/libdevmapper.c:1766
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Begärd flagga för dm-crypt-prestanda stöds inte."
+
+#: lib/libdevmapper.c:1706 lib/libdevmapper.c:1710
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Begärd flagga för dm-verity-dataintegritet stöds inte."
+
+#: lib/libdevmapper.c:1714
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Begärd flagga dm-verity FEC stöds inte."
+
+#: lib/libdevmapper.c:1718
+msgid "Requested data integrity options are not supported."
+msgstr "Begärd flagga för dataintegritet stöds inte."
+
+#: lib/libdevmapper.c:1720
+msgid "Requested sector_size option is not supported."
+msgstr "Begärd flagga sector_size stöds inte."
+
+#: lib/libdevmapper.c:1725 lib/libdevmapper.c:1729
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Begärd automatisk beräkning av integritetstaggar stöds inte."
+
+#: lib/libdevmapper.c:1733 lib/libdevmapper.c:1769 lib/libdevmapper.c:1772
+#: lib/luks2/luks2_json_metadata.c:2552
+msgid "Discard/TRIM is not supported."
+msgstr "Discard/TRIM stöds inte."
+
+#: lib/libdevmapper.c:1737
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Begärt dm-integrity bitmap-läge stöds inte."
+
+#: lib/libdevmapper.c:2763
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Misslyckades med att läsa dm-%s-segment."
+
+#: lib/random.c:74
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Systemet fick slut på entropi under generering av volymnyckeln.\n"
+"Rör på musen eller skriv in text i ett annat fönster för att samla in slumpmässiga händelser.\n"
+
+#: lib/random.c:78
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Genererar nyckel (%d%% done).\n"
+
+#: lib/random.c:164
+msgid "Running in FIPS mode."
+msgstr "Kör i FIPS-läge."
+
+#: lib/random.c:170
+msgid "Fatal error during RNG initialisation."
+msgstr "Ödesdigert fel under RNG-initiering."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Okänd RNG-kvalitet begärd."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Fel vid läsning från RNG."
+
+#: lib/setup.c:226
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Det går inte att initiera RNG-krypteringsbakände."
+
+#: lib/setup.c:232
+msgid "Cannot initialize crypto backend."
+msgstr "Det går inte att initiera krypteringsbakände."
+
+#: lib/setup.c:263 lib/setup.c:2080 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Hashalgoritmen %s stöds inte."
+
+#: lib/setup.c:266 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Fel vid nyckelbearbetning (använder hash %s)."
+
+#: lib/setup.c:332 lib/setup.c:359
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Det går inte att avgöra enhetstyp. Inkompatibel aktivering av enhet?"
+
+#: lib/setup.c:338 lib/setup.c:3221
+msgid "This operation is supported only for LUKS device."
+msgstr "Denna åtgärd stöds endast av LUKS-enheter."
+
+#: lib/setup.c:365
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Denna åtgärd stöds endast av LUKS2-enheter."
+
+#: lib/setup.c:420 lib/luks2/luks2_reencrypt.c:2985
+msgid "All key slots full."
+msgstr "Alla nyckelplatser är upptagna."
+
+#: lib/setup.c:431
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Nyckelplats %d är ogiltig. Välj mellan 0 och %d."
+
+#: lib/setup.c:437
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Nyckelplats %d är full. Välj en annan."
+
+#: lib/setup.c:522 lib/setup.c:2946
+msgid "Device size is not aligned to device logical block size."
+msgstr "Storlek på enhet är inte justerad till enhetens logiska blockstorlek."
+
+#: lib/setup.c:620
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Huvud identifierat men enheten %s är för liten."
+
+#: lib/setup.c:661 lib/setup.c:2851 lib/setup.c:4335
+#: lib/luks2/luks2_reencrypt.c:3757 lib/luks2/luks2_reencrypt.c:4159
+msgid "This operation is not supported for this device type."
+msgstr "Denna åtgärd stöds inte för denna enhetstyp."
+
+#: lib/setup.c:666
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Ogiltig åtgärd under pågående omkryptering."
+
+#: lib/setup.c:833 lib/luks1/keymanage.c:248 lib/luks1/keymanage.c:524
+#: lib/luks2/luks2_json_metadata.c:1267 src/cryptsetup.c:1449
+#: src/cryptsetup.c:1581 src/cryptsetup.c:1636 src/cryptsetup.c:1756
+#: src/cryptsetup.c:1861 src/cryptsetup.c:2142 src/cryptsetup.c:2380
+#: src/cryptsetup.c:2440 src/utils_reencrypt.c:1378
+#: src/utils_reencrypt_luks1.c:1188 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Enheten %s är inte en giltig LUKS-enhet."
+
+#: lib/setup.c:836 lib/luks1/keymanage.c:527
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "LUKS-versionen %d stöds inte."
+
+#: lib/setup.c:1431 lib/setup.c:2602 lib/setup.c:2682 lib/setup.c:2694
+#: lib/setup.c:2859 lib/setup.c:4807
+#, c-format
+msgid "Device %s is not active."
+msgstr "Enheten %s är inte aktiv."
+
+#: lib/setup.c:1448
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Underliggande enhet för krypteringsenhet %s försvann."
+
+#: lib/setup.c:1528
+msgid "Invalid plain crypt parameters."
+msgstr "Ogiltiga parametrar för plain-kryptering."
+
+#: lib/setup.c:1533 lib/setup.c:1983
+msgid "Invalid key size."
+msgstr "Ogiltig nyckelstorlek."
+
+#: lib/setup.c:1538 lib/setup.c:1988 lib/setup.c:2191
+msgid "UUID is not supported for this crypt type."
+msgstr "UUID stöds inte för denna krypteringstyp."
+
+#: lib/setup.c:1543 lib/setup.c:1993
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Frånkopplad metadataenhet stöds ej av denna crypt-typ."
+
+#: lib/setup.c:1553 lib/setup.c:1765 lib/luks2/luks2_reencrypt.c:2941
+#: src/cryptsetup.c:1250 src/cryptsetup.c:3072
+msgid "Unsupported encryption sector size."
+msgstr "Stöder inte sektorstorleken för kryptering."
+
+#: lib/setup.c:1561 lib/setup.c:1896 lib/setup.c:2940
+msgid "Device size is not aligned to requested sector size."
+msgstr "Storlek på enhet är inte justerad till begärd sektorstorlek."
+
+#: lib/setup.c:1613 lib/setup.c:1733
+msgid "Can't format LUKS without device."
+msgstr "Det går inte att formatera LUKS utan enhet."
+
+#: lib/setup.c:1619 lib/setup.c:1739
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Begärd datajustering är inte kompatibel med dataoffset."
+
+#: lib/setup.c:1687 lib/setup.c:1883
+msgid "WARNING: Data offset is outside of currently available data device.\n"
+msgstr "VARNING: Dataoffset ligger utanför aktuell dataenhet.\n"
+
+#: lib/setup.c:1697 lib/setup.c:1913 lib/setup.c:1934 lib/setup.c:2203
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Det går inte att rensa huvudet på enheten %s."
+
+#: lib/setup.c:1774
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "VARNING: Enhetsaktiveringen kommer att misslyckas, dm-crypt saknar stöd för begärd krypteringsektorstorlek.\n"
+
+#: lib/setup.c:1797
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Volymnyckeln är för liten för kryptering med integritetstillägg."
+
+#: lib/setup.c:1857
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Chiffret %s-%s (nyckelstorlek %zd bitar) är inte tillgängligt."
+
+#: lib/setup.c:1886
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "VARNING: storlek på LUKS2-metadata ändrades till %<PRIu64> byte.\n"
+
+#: lib/setup.c:1890
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "VARNING: storlek på LUKS2-nyckelplatsområde ändrades till %<PRIu64> byte.\n"
+
+#: lib/setup.c:1916 lib/utils_device.c:909 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3009 lib/luks2/luks2_reencrypt.c:4254
+#, c-format
+msgid "Device %s is too small."
+msgstr "Enheten %s är för liten."
+
+#: lib/setup.c:1927 lib/setup.c:1953
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Det går inte att formatera enheten %s då den används."
+
+#: lib/setup.c:1930 lib/setup.c:1956
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Det går inte att formatera enheten %s, behörighet nekad."
+
+#: lib/setup.c:1942 lib/setup.c:2263
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Det går inte att formatera integritet för enheten %s."
+
+#: lib/setup.c:1960
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Det går inte att formatera enheten %s."
+
+#: lib/setup.c:1978
+msgid "Can't format LOOPAES without device."
+msgstr "Kan inte formatera LOOPAES utan enhet."
+
+#: lib/setup.c:2023
+msgid "Can't format VERITY without device."
+msgstr "Det går inte att formatera VERITY utan enhet."
+
+#: lib/setup.c:2034 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "VERITY-hashtyp %d stöds inte."
+
+#: lib/setup.c:2040 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "VERITY-blockstorlek som inte stöds."
+
+#: lib/setup.c:2045 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "VERITY-hashoffset som inte stöds."
+
+#: lib/setup.c:2050
+msgid "Unsupported VERITY FEC offset."
+msgstr "VERITY-FEC-offset som inte stöds."
+
+#: lib/setup.c:2074
+msgid "Data area overlaps with hash area."
+msgstr "Dataområde spiller över på hashområdet."
+
+#: lib/setup.c:2099
+msgid "Hash area overlaps with FEC area."
+msgstr "Hashområde spiller över på FEC-mrådet."
+
+#: lib/setup.c:2106
+msgid "Data area overlaps with FEC area."
+msgstr "Dataområde spiller över på FEC-mrådet."
+
+#: lib/setup.c:2242
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "VARNING: Begärd taggstorlek på %d byte skiljer sig från %s utdatastorlek (%d byte).\n"
+
+#: lib/setup.c:2321
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Okänd typ av krypteringsenhet %s begärd."
+
+#: lib/setup.c:2608 lib/setup.c:2687 lib/setup.c:2700
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Parametrar som inte stöds på enheten %s."
+
+#: lib/setup.c:2614 lib/setup.c:2707 lib/luks2/luks2_reencrypt.c:2837
+#: lib/luks2/luks2_reencrypt.c:3074 lib/luks2/luks2_reencrypt.c:3459
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Kan inte rensa huvudet på enheten %s."
+
+#: lib/setup.c:2731
+msgid "Crypt devices mismatch."
+msgstr "Krypteringsenheter har matchningsfel."
+
+#: lib/setup.c:2768 lib/setup.c:2773 lib/luks2/luks2_reencrypt.c:2315
+#: lib/luks2/luks2_reencrypt.c:2853 lib/luks2/luks2_reencrypt.c:4007
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Misslyckades med att läsa om enhet %s."
+
+#: lib/setup.c:2779 lib/setup.c:2785 lib/luks2/luks2_reencrypt.c:2286
+#: lib/luks2/luks2_reencrypt.c:2293 lib/luks2/luks2_reencrypt.c:2867
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Misslyckades med att försätta enhet %s i vänteläge."
+
+#: lib/setup.c:2791 lib/luks2/luks2_reencrypt.c:2300
+#: lib/luks2/luks2_reencrypt.c:2888 lib/luks2/luks2_reencrypt.c:3920
+#: lib/luks2/luks2_reencrypt.c:4011
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Misslyckades med att återuppta enhet %s."
+
+#: lib/setup.c:2806
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Ödesdigert fel vid omläsning av enhet %s (ovanpå enhet %s)."
+
+#: lib/setup.c:2809 lib/setup.c:2811
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Misslyckades med att växla enhet %s till dm-error."
+
+#: lib/setup.c:2891
+msgid "Cannot resize loop device."
+msgstr "Det går inte att ändra storlek på loop-enhet."
+
+#: lib/setup.c:2931
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "VARNING: Maximal storlek redan satt eller så stöder inte kärnan storleksändring.\n"
+
+#: lib/setup.c:2989
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Misslyckades med storleksändring, kärnan stöder inte detta."
+
+#: lib/setup.c:3021
+msgid "Do you really want to change UUID of device?"
+msgstr "Vill du verkligen ändra UUID för en enhet?"
+
+#: lib/setup.c:3113
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Säkerhetskopian för huvud innehåller inte något giltigt LUKS-huvud."
+
+#: lib/setup.c:3229
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Volymen %s är inte aktiv."
+
+#: lib/setup.c:3240
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Volymen %s är redan i vänteläge."
+
+#: lib/setup.c:3253
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Vänteläge stöds inte för enhet %s."
+
+#: lib/setup.c:3255
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Fel då enheten %s försattes i vänteläge."
+
+#: lib/setup.c:3290
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Att återuppta stöds inte för enhet %s."
+
+#: lib/setup.c:3292
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Fel då enheten %s återupptogs."
+
+#: lib/setup.c:3326 lib/setup.c:3374 lib/setup.c:3444 lib/setup.c:3489
+#: src/cryptsetup.c:2207
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Volymen %s är inte i vänteläge."
+
+#: lib/setup.c:3459 lib/setup.c:3862 lib/setup.c:4584 lib/setup.c:4597
+#: lib/setup.c:4605 lib/setup.c:4618 lib/setup.c:6142 src/cryptsetup.c:1790
+msgid "Volume key does not match the volume."
+msgstr "Volymnyckeln stämmer inte överens med volymen."
+
+#: lib/setup.c:3540 lib/setup.c:3745
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Det går inte att lägga till nyckelplats. Alla platser är inaktiverade och ingen volymnyckel har angivits."
+
+#: lib/setup.c:3697
+msgid "Failed to swap new key slot."
+msgstr "Misslyckades med att byta ny nyckelplats."
+
+#: lib/setup.c:3883
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Nyckelplats %d är ogiltig."
+
+#: lib/setup.c:3889 src/cryptsetup.c:1594 src/cryptsetup.c:1936
+#: src/cryptsetup.c:2540 src/cryptsetup.c:2597
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Nyckelplats %d är inte aktiv."
+
+#: lib/setup.c:3908
+msgid "Device header overlaps with data area."
+msgstr "Dataområde spiller över på hashområdet."
+
+#: lib/setup.c:4213
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Omkryptering pågår. Det går inte att aktivera enheten."
+
+#: lib/setup.c:4215 lib/luks2/luks2_json_metadata.c:2635
+#: lib/luks2/luks2_reencrypt.c:3565
+msgid "Failed to get reencryption lock."
+msgstr "Misslyckades med att erhålla omkrypteringslås."
+
+#: lib/setup.c:4228 lib/luks2/luks2_reencrypt.c:3584
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Misslyckades med återhämtning av LUKS2-omkryptering."
+
+#: lib/setup.c:4396 lib/setup.c:4661
+msgid "Device type is not properly initialized."
+msgstr "Enhetstypen är inte korrekt initierad."
+
+#: lib/setup.c:4444
+#, c-format
+msgid "Device %s already exists."
+msgstr "Enheten %s finns redan."
+
+#: lib/setup.c:4451
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Det går inte att använda enheten %s som fortfarande används eller har ett ogiltigt namn."
+
+#: lib/setup.c:4571
+msgid "Incorrect volume key specified for plain device."
+msgstr "Felaktig volymnyckel för plain-enhet."
+
+#: lib/setup.c:4687
+msgid "Incorrect root hash specified for verity device."
+msgstr "Felaktig rothash angiven för verity-enhet."
+
+#: lib/setup.c:4697
+msgid "Root hash signature required."
+msgstr "Root-hashsignatur krävs."
+
+#: lib/setup.c:4706
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Kärnans nyckelring saknas: krävs för att skicka signatur till kärnan."
+
+#: lib/setup.c:4723 lib/setup.c:6218
+msgid "Failed to load key in kernel keyring."
+msgstr "Misslyckades med att öppna nyckelringen för kärnan."
+
+#: lib/setup.c:4779
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Misslyckades med att avbryta fördröjd borttagning från enheten %s."
+
+#: lib/setup.c:4786 lib/setup.c:4802 lib/luks2/luks2_json_metadata.c:2688
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Enheten %s används fortfarande."
+
+#: lib/setup.c:4811
+#, c-format
+msgid "Invalid device %s."
+msgstr "Ogiltig enhet %s."
+
+#: lib/setup.c:4927
+msgid "Volume key buffer too small."
+msgstr "Buffert för volymnyckelen är för liten."
+
+#: lib/setup.c:4935
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Kan inte hämta volymnyckel för plain-enhet."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Det går inte att hämta root-hash för verity-enhet."
+
+#: lib/setup.c:4956
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Denna åtgärd stöds inte för krypteringsenheter av typen %s."
+
+#: lib/setup.c:5130 lib/setup.c:5141
+msgid "Dump operation is not supported for this device type."
+msgstr "Utskriftsåtgärden stöds inte för denna enhetstyp."
+
+#: lib/setup.c:5471
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Dataförskjutning är inte en multipel av %u byte."
+
+#: lib/setup.c:5756
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Det går inte konvertera enheten %s som fortfarande används."
+
+#: lib/setup.c:6075
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Misslyckades med att tilldela nyckelplats %u som ny volymnyckel."
+
+#: lib/setup.c:6148
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Misslyckades med att initiera standardnyckelplats för LUKS2-parametrar."
+
+#: lib/setup.c:6154
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Misslyckades med att tilldela nyckelplats %d till kontrollsummor."
+
+#: lib/setup.c:6285
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "Kärnans nyckelring stöds inte av kärnan."
+
+#: lib/setup.c:6295 lib/luks2/luks2_reencrypt.c:3782
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Misslyckades med att läsa lösenfras från nyckelringsnyckel (fel %d)."
+
+#: lib/setup.c:6319
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Misslyckades med att inhämta globalt minneshårt serialiseringslås."
+
+#: lib/utils.c:80
+msgid "Cannot get process priority."
+msgstr "Det går inte att få processprioritet."
+
+#: lib/utils.c:94
+msgid "Cannot unlock memory."
+msgstr "Det går inte att låsa upp minne."
+
+#: lib/utils.c:168 lib/tcrypt/tcrypt.c:502
+msgid "Failed to open key file."
+msgstr "Misslyckades med att öppna nyckelfilen."
+
+#: lib/utils.c:173
+msgid "Cannot read keyfile from a terminal."
+msgstr "Det går inte läsa nyckelfilen från en terminal."
+
+#: lib/utils.c:189
+msgid "Failed to stat key file."
+msgstr "Misslyckades med att ta stat på nyckelfilen."
+
+#: lib/utils.c:197 lib/utils.c:218
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Det går inte att söka till begärd nyckelfilsoffset."
+
+#: lib/utils.c:212 lib/utils.c:227 src/utils_password.c:226
+#: src/utils_password.c:238
+msgid "Out of memory while reading passphrase."
+msgstr "Slut på minne vid läsning av lösenfras."
+
+#: lib/utils.c:247
+msgid "Error reading passphrase."
+msgstr "Fel vid läsning av lösenfras."
+
+#: lib/utils.c:264
+msgid "Nothing to read on input."
+msgstr "Ingenting att läsa vid inmating."
+
+#: lib/utils.c:271
+msgid "Maximum keyfile size exceeded."
+msgstr "Högsta nyckelfilsstorlek överskriden."
+
+#: lib/utils.c:276
+msgid "Cannot read requested amount of data."
+msgstr "Det går inte läsa begärd mängd data."
+
+#: lib/utils_device.c:208 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1353
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Enheten %s finns inte eller åtkomst nekas."
+
+#: lib/utils_device.c:218
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Enheten %s är inte aktiv."
+
+#: lib/utils_device.c:562
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Ignorerar falsk optimal-io-storlek för dataenheten (%u byte)."
+
+#: lib/utils_device.c:720
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Enhet %s är för liten. Behöver minst %<PRIu64> byte."
+
+#: lib/utils_device.c:801
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Det går inte att använda enheten %s som redan används (redan mappad eller monterad)."
+
+#: lib/utils_device.c:805
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Det går inte att använda enhet %s, behörighet nekad."
+
+#: lib/utils_device.c:808
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Kan inte hämta information om enheten %s."
+
+#: lib/utils_device.c:831
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Kan inte använda en loopback-enhet, kör som icke-root-användare."
+
+#: lib/utils_device.c:842
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Misslyckades med att fästa loopback-enhet (kräver loop-enhet med flaggan autoclear)."
+
+#: lib/utils_device.c:890
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Begärd offset är bortom faktiska enhetsstorleken för %s."
+
+#: lib/utils_device.c:898
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Enheten %s har noll storlek."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Begärd måltid för PBKDF kan inte vara noll."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Okänd PBKDF-typ %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Begärd hash %s stöds inte."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Begärd PBKDF-typ stöds inte för LUKS1."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Högsta minne för PBKDF eller parallella trådar får inte sättas med pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Tvingad iterationsuppräkning är för liten för %s (minsta är %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Tvingad minneskostnad är för låg för %s (minimum är %u kilobyte)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Kostnaden för det begärda högsta minnet för PBKDF är för högt (maximum är %d kilobyte)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Högst begärt minne för PBKDF kan inte vara noll."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Begärda parallella trådar för PBKDF kan inte vara noll."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "Stöder endast PBKDF2 i FIPS-läge."
+
+#: lib/utils_benchmark.c:172
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Prestandamätning för PBKDF är inaktiverad men iterationer är inte satt."
+
+#: lib/utils_benchmark.c:191
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Ej kompatibla PBKDF2-flaggor (använder hash-algoritmen %s)."
+
+#: lib/utils_benchmark.c:211
+msgid "Not compatible PBKDF options."
+msgstr "Ej kompatibla PBKDF2-flaggor."
+
+#: lib/utils_device_locking.c:102
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Låsningen avbruten. Låsningsökvägen %s/%s oanvändbar (inte en katalog eller saknas)."
+
+#: lib/utils_device_locking.c:109
+#, c-format
+msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+msgstr "Rättigheterna för låskatalogen %s/%s kommer att skapas med inkompilerade standardvärden."
+
+#: lib/utils_device_locking.c:119
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Låsningen avbruten. Låsningsökvägen %s/%s oanvändbar (%s är inte en katalog)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Det går inte att söka till enhetsoffset."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Fel vid radering av enhet, förskjutning %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Misslyckades med att konfigurera nyckelmappning för dm-crypt för enheten %s. \n"
+"Kontrollera att kärnan har stöd för chiffret %s (kontrollera syslog för mer information)."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Nyckelstorlek i XTS-läge måste vara en multipel av 256 eller 512 bitar."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Chifferspecifikation ska vara i formatet [chiffer] - [läge] - [iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:364
+#: lib/luks1/keymanage.c:674 lib/luks1/keymanage.c:1125
+#: lib/luks2/luks2_json_metadata.c:1421 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Kan inte skriva till enhet %s, behörighet nekad."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Misslyckades med att öppna temporär nyckellagringsenhet."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Misslyckades med att komma åt temporär nyckellagringsenhet."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:60
+#: lib/luks2/luks2_keyslot_luks2.c:78 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "In-/utfel vid kryptering av nyckelplats."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:367
+#: lib/luks1/keymanage.c:627 lib/luks1/keymanage.c:677 lib/tcrypt/tcrypt.c:680
+#: lib/verity/verity.c:80 lib/verity/verity.c:196 lib/verity/verity_hash.c:320
+#: lib/verity/verity_hash.c:329 lib/verity/verity_hash.c:349
+#: lib/verity/verity_fec.c:260 lib/verity/verity_fec.c:272
+#: lib/verity/verity_fec.c:277 lib/luks2/luks2_json_metadata.c:1424
+#: src/utils_reencrypt_luks1.c:121 src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Det går inte att öppna enheten %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:137
+msgid "IO error while decrypting keyslot."
+msgstr "In-/utfel vid dekryptering av nyckelplats."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Enhet %s är för liten. (LUKS1 kräver minst %<PRIu64> byte.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "LUKS-nyckelplats %u är ogiltig."
+
+#: lib/luks1/keymanage.c:266 lib/luks2/luks2_json_metadata.c:1284
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Begärd säkerhetskopia %s av huvud finns redan."
+
+#: lib/luks1/keymanage.c:268 lib/luks2/luks2_json_metadata.c:1286
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Det går inte att skapa säkerhetskopia för huvud %s."
+
+#: lib/luks1/keymanage.c:275 lib/luks2/luks2_json_metadata.c:1293
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Det går inte skriva säkerhetskopia för huvud %s."
+
+#: lib/luks1/keymanage.c:306 lib/luks2/luks2_json_metadata.c:1330
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Säkerhetskopian innehåller inte något giltigt LUKS-huvud."
+
+#: lib/luks1/keymanage.c:319 lib/luks1/keymanage.c:590
+#: lib/luks2/luks2_json_metadata.c:1351
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Det går inte att öppna säkerhetskopia för huvud %s."
+
+#: lib/luks1/keymanage.c:327 lib/luks2/luks2_json_metadata.c:1359
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Det går inte att läsa säkerhetskopia för huvud %s."
+
+#: lib/luks1/keymanage.c:337
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Dataoffset eller nyckelstorlek skiljer sig åt på enhet och säkerhetskopia. Återställningen misslyckades."
+
+#: lib/luks1/keymanage.c:345
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Enhet %s %s%s"
+
+#: lib/luks1/keymanage.c:346
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "innehåller inget LUKS-huvud. Ersättning av huvud kan förstöra data på enheten."
+
+#: lib/luks1/keymanage.c:347
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "innehåller redan LUKS-huvud. Ersättningen av huvud kommer att förstöra befintliga nyckelplatser."
+
+#: lib/luks1/keymanage.c:348 lib/luks2/luks2_json_metadata.c:1393
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"VARNING: verkligt enhetshuvud har annat UUID än säkerhetskopian!"
+
+#: lib/luks1/keymanage.c:395
+msgid "Non standard key size, manual repair required."
+msgstr "Ej standardstorlek på nyckel, manuell reparation krävs."
+
+#: lib/luks1/keymanage.c:405
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Ej standardjustering på nyckelplatser, manuell reparation krävs."
+
+#: lib/luks1/keymanage.c:414
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Chifferläge reparerat (%s -> %s)."
+
+#: lib/luks1/keymanage.c:425
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Chifferhash reparerad till gemener (%s)."
+
+#: lib/luks1/keymanage.c:427 lib/luks1/keymanage.c:533
+#: lib/luks1/keymanage.c:789
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Begärd LUKS-hash %s stöds inte."
+
+#: lib/luks1/keymanage.c:441
+msgid "Repairing keyslots."
+msgstr "Reparerar nyckelplatser."
+
+#: lib/luks1/keymanage.c:460
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Nyckelplats %i: reparerad offset (%u -> %u)."
+
+#: lib/luks1/keymanage.c:468
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Nyckelplats %i: reparerade remsor (%u -> %u)."
+
+#: lib/luks1/keymanage.c:477
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Nyckelplats %i: fejkpartitionssignatur."
+
+#: lib/luks1/keymanage.c:482
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Nyckelplats %i: salt borttaget."
+
+#: lib/luks1/keymanage.c:499
+msgid "Writing LUKS header to disk."
+msgstr "Skriver LUKS-huvud till disk."
+
+#: lib/luks1/keymanage.c:504
+msgid "Repair failed."
+msgstr "Reparation misslyckades."
+
+#: lib/luks1/keymanage.c:559
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "LUKS-chifferläge %s är ogiltigt."
+
+#: lib/luks1/keymanage.c:564
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "LUKS-hash %s är ogiltig."
+
+#: lib/luks1/keymanage.c:571 src/cryptsetup.c:1144
+msgid "No known problems detected for LUKS header."
+msgstr "Inga kända problem identifierade för LUKS-huvud."
+
+#: lib/luks1/keymanage.c:699
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Fel vid uppdatering av LUKS-huvud på enheten %s."
+
+#: lib/luks1/keymanage.c:707
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Fel vid omläsning av LUKS-huvud efter uppdatering på enheten %s."
+
+#: lib/luks1/keymanage.c:783
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Data-offset för fristående LUKS-huvud måste vara antingen 0 eller större än huvudstorleken."
+
+#: lib/luks1/keymanage.c:794 lib/luks1/keymanage.c:863
+#: lib/luks2/luks2_json_format.c:287 lib/luks2/luks2_json_metadata.c:1175
+#: src/utils_reencrypt.c:475
+msgid "Wrong LUKS UUID format provided."
+msgstr "Felaktigt LUKS-UUID-format angavs."
+
+#: lib/luks1/keymanage.c:816
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Kan inte skapa LUKS-huvud: läsning av slumpmässigt salt misslyckades."
+
+#: lib/luks1/keymanage.c:842
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Kan inte skapa LUKS-huvud: kontrollsumma för huvud misslyckades (använder hashen %s)."
+
+#: lib/luks1/keymanage.c:886
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Nyckelplats %d är aktiv, rensa först."
+
+#: lib/luks1/keymanage.c:892
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Nyckelplats %d material inkluderar för få remsor. Har huvudet manipulerats?"
+
+#: lib/luks1/keymanage.c:1033
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Det går inte att öppna nyckeplats (använder hash %s)."
+
+#: lib/luks1/keymanage.c:1111
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Nyckelplats %d är ogiltig. Välj en nyckelplats mellan 0 och %d."
+
+#: lib/luks1/keymanage.c:1129 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Kan inte rensa enheten %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Identifierade en GPG-krypterad nyckelfil som ännu inte stöds."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Använd gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- …\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Identifierade inkompatibel loop-AES-nyckelfil."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "Kärnan stöder inte loop-AES-kompatibel mappning."
+
+#: lib/tcrypt/tcrypt.c:509
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Fel vid läsning av nyckelfil %s."
+
+#: lib/tcrypt/tcrypt.c:559
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Högsta TCRYPT-lösenfraslängd (%zu) överskriden."
+
+#: lib/tcrypt/tcrypt.c:601
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "PBKDF2-hashalgoritm %s ej tillgänglig, hoppar över."
+
+#: lib/tcrypt/tcrypt.c:620 src/cryptsetup.c:1019
+msgid "Required kernel crypto interface not available."
+msgstr "Begärt kryptogränssnitt för kärnan inte tillgängligt."
+
+#: lib/tcrypt/tcrypt.c:622 src/cryptsetup.c:1021
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Försäkra dig om att kärnmodulen algif_skcipher är inläst."
+
+#: lib/tcrypt/tcrypt.c:763
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Aktivering stöds inte för sektorstorlek %d."
+
+#: lib/tcrypt/tcrypt.c:769
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "Kärnan stöder inte aktivering för detta föråldrade TCRYPT-läge."
+
+#: lib/tcrypt/tcrypt.c:800
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Aktiverar TCRYPT-systemkryptering för partition %s."
+
+#: lib/tcrypt/tcrypt.c:883
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "Kärnan stöder inte TCRYPT-kompatibel mappning."
+
+#: lib/tcrypt/tcrypt.c:1096
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Denna funktion stöds inte utan inläsning av TCRYPT-huvud."
+
+#: lib/bitlk/bitlk.c:275
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Oväntad metadatapost av typ ”%u” funnen vid tolkning av volymhuvudnyckel."
+
+#: lib/bitlk/bitlk.c:328
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Ogiltig sträng funnen vid tolkning av volymhuvudnyckel."
+
+#: lib/bitlk/bitlk.c:332
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Oväntad sträng (”%s”) funnen vid tolkning av volymhuvudnycklar som stöds."
+
+#: lib/bitlk/bitlk.c:349
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Oväntad metadatapostvärde av typ ”%u” funnen vid tolkning av volymhuvudnycklar som stöds."
+
+#: lib/bitlk/bitlk.c:451
+msgid "BITLK version 1 is currently not supported."
+msgstr "BITLK version 1 stöds ej för närvarande."
+
+#: lib/bitlk/bitlk.c:457
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Ogiltig eller okänd boot-signatur för BITLK-enhet."
+
+#: lib/bitlk/bitlk.c:469
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Stöder inte sektorstorleken %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:477
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Misslyckades med att läsa BITLK-huvud från %s."
+
+#: lib/bitlk/bitlk.c:502
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Misslyckades med att läsa BITLK FVE-metadata från %s."
+
+#: lib/bitlk/bitlk.c:554
+msgid "Unknown or unsupported encryption type."
+msgstr "Krypteringstypen är okänd eller stöds ej."
+
+#: lib/bitlk/bitlk.c:587
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Misslyckades med att läsa BITLK -metadataposter från %s."
+
+#: lib/bitlk/bitlk.c:681
+msgid "Failed to convert BITLK volume description"
+msgstr "Misslyckades med att konvertera BITLK-volymbeskrivning"
+
+#: lib/bitlk/bitlk.c:841
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Oväntad metadatapost av typ ”%u” funnen vid tolkning av extern nyckel."
+
+#: lib/bitlk/bitlk.c:860
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "BEK-filens GUID '%s' stämmer inte överens med GUID för volymen."
+
+#: lib/bitlk/bitlk.c:864
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Oväntad metadatapostvärde av typ ”%u” funnen vid tolkning av extern nyckel."
+
+#: lib/bitlk/bitlk.c:903
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Inget stöd för BEK metadata-version %<PRIu32>"
+
+#: lib/bitlk/bitlk.c:908
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Oväntad BEK-metadatastorlek %<PRIu32> matchar inte BEK-fillängd"
+
+#: lib/bitlk/bitlk.c:933
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Oväntad metadatapost av typ ”%u” funnen vid tolkning av uppstartsnyckel."
+
+#: lib/bitlk/bitlk.c:1029
+msgid "This operation is not supported."
+msgstr "Denna åtgärd stöds ej."
+
+#: lib/bitlk/bitlk.c:1037
+msgid "Unexpected key data size."
+msgstr "Oväntad nyckeldatastorlek."
+
+#: lib/bitlk/bitlk.c:1163
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Denna BITLK-enhet är i tillstånd som inte stöds och kan inte aktiveras."
+
+#: lib/bitlk/bitlk.c:1168
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Det går inte att aktivera BITLK-enheter av typen ”%s”."
+
+#: lib/bitlk/bitlk.c:1175
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Aktivering av delvis avkrypterade BITLK-enheter stöds ej."
+
+#: lib/bitlk/bitlk.c:1216
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "VARNING: BitLocker-volymstorlek %<PRIu64> överensstämmer inte med underliggande enhetstorlek %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1343
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Det går inte att aktivera enheten, kärnan dm-crypt saknar stöd för BITLK IV."
+
+#: lib/bitlk/bitlk.c:1347
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Det går inte att aktivera enheten, kärnan dm-crypt saknar stöd för BITLK Elephant diffuser."
+
+#: lib/bitlk/bitlk.c:1351
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Det går inte att aktivera enheten, kärnan dm-crypt saknar stöd för stor sektorstorlek."
+
+#: lib/bitlk/bitlk.c:1355
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Det går inte att aktivera enheten, kärnmodulen dm-zero saknas."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "Verity-enheten %s använder inte huvud på disk."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "VERITY-versionen %d stöds inte."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "VERITY-huvud är skadat."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "Felaktigt VERITY-UUID-format angivet på enhet %s."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Fel vid uppdatering av verity-huvud på enheten %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Begärd hashsignaturverifiering %s stöds inte."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Det går inte reparera fel med FEC-enhet."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "Fann %u reparerbara fel med FEC-enhet."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "Kärnan stöder inte dm-verity-mappning."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "Kärnan stöder inte flaggan för dm-verity-signatur."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Verity-enhet identifierades som skadad efter aktivering."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Ledigt utrymme är inte nollställt vid position %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Enhets-offset spillde över."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Verifiering misslyckades vid %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Hash-området spillde över."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Misslyckades med verifiering av dataområde."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Misslyckades med verifiering av rot-hash."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "In-/utdatafel vid skapandet av hashområde."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Misslyckades med skapandet av hashområde."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "VARNING: Kärnan kan inte aktivera enhet om datablockstorleken överskrider sidstorlek (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Misslyckades med att öppna RS-kontext."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Misslyckades med att allokera buffert."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Misslyckades med att läsa RS block %<PRIu64> byte %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Misslyckades med att skriva paritet för RS block %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Misslyckades med att skriva paritet för RS block %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Misslyckades med att skriva paritet för RS block %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Blockstorlekar måste matcha för FEC."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Ogiltigt antal paritet-byte."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Ogiltig FEC-segmentlängd."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Misslyckades med att bestämma storlek för enhet %s."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Inkompatibel kärnmetadata dm-integrity (version %u) identifierad på %s."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "Kärnan stöder inte dm-integrity-mappning."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "Kärnan stöder inte fast metadataförskjutning för dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Kärnan tillåter inte att den osäkra flaggan recalculate aktiveras (se föråldrade aktiveringsflaggor för att åsidosätta)."
+
+#: lib/luks2/luks2_disk_metadata.c:393 lib/luks2/luks2_json_metadata.c:1133
+#: lib/luks2/luks2_json_metadata.c:1413
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Misslyckades med att få skrivlås på enheten %s."
+
+#: lib/luks2/luks2_disk_metadata.c:402
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Identifierade samtidiga försök att uppdatera LUKS2-metadata. Avbryter åtgärden."
+
+#: lib/luks2/luks2_disk_metadata.c:701 lib/luks2/luks2_disk_metadata.c:722
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Enheten innehåller tvetydiga signaturer, det går inte att automatiskt återhämta LUKS2.\n"
+"Kör ”cryptsetup repair” för återhämtning."
+
+#: lib/luks2/luks2_json_format.c:230
+msgid "Requested data offset is too small."
+msgstr "Begärd dataoff för liten."
+
+#: lib/luks2/luks2_json_format.c:275
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "VARNING: nyckelplatsområdet (%<PRIu64> byte) är väldigt liten, tillgängligt LUKS2-nyckelplatsantal är väldigt begränsat.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1120 lib/luks2/luks2_json_metadata.c:1258
+#: lib/luks2/luks2_json_metadata.c:1319 lib/luks2/luks2_keyslot_luks2.c:92
+#: lib/luks2/luks2_keyslot_luks2.c:114
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Misslyckades med att erhålla läslås på enheten %s."
+
+#: lib/luks2/luks2_json_metadata.c:1336
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "Förbjudna LUKS2-krav identifierade i säkerhetskopian %s."
+
+#: lib/luks2/luks2_json_metadata.c:1377
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Dataoffset skiljer sig på enhet och säkerhetskopia. Återställningen misslyckades."
+
+#: lib/luks2/luks2_json_metadata.c:1383
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Binärhuvud med nyckelstorlek skiljer sig på enhet och säkerhetskopia. Återställningen misslyckades."
+
+#: lib/luks2/luks2_json_metadata.c:1390
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Enhet %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1391
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "innehåller inget LUKS2-huvud. Ersättning av huvud kan förstöra data på enheten."
+
+#: lib/luks2/luks2_json_metadata.c:1392
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "innehåller redan LUKS2-huvud. Ersättningen av huvud kommer att förstöra befintliga nyckelplatser."
+
+#: lib/luks2/luks2_json_metadata.c:1394
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"VARNING:okända LUKS2-krav identifierade i huvudet för riktig enhet!\n"
+"Att ersätta huvudet med en säkerhetskopia kan göra data korrupt på enheten!"
+
+#: lib/luks2/luks2_json_metadata.c:1396
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"VARNING:Oavslutad frånkopplade kryptering identifierad på enheten!\n"
+"Att ersätta huvudet med en säkerhetskopia kan orsaka korrupt data."
+
+#: lib/luks2/luks2_json_metadata.c:1494
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Ignorerade okänd flagga %s."
+
+#: lib/luks2/luks2_json_metadata.c:2402 lib/luks2/luks2_reencrypt.c:2015
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Saknar nyckel för dm-crypt-segmentet %u"
+
+#: lib/luks2/luks2_json_metadata.c:2414 lib/luks2/luks2_reencrypt.c:2029
+msgid "Failed to set dm-crypt segment."
+msgstr "Misslyckades med att läsa dm-crypt-segment."
+
+#: lib/luks2/luks2_json_metadata.c:2420 lib/luks2/luks2_reencrypt.c:2035
+msgid "Failed to set dm-linear segment."
+msgstr "Misslyckades med att läsa dm-linear-segment."
+
+#: lib/luks2/luks2_json_metadata.c:2547
+msgid "Unsupported device integrity configuration."
+msgstr "Integritetskonfiguration som ej stöds på enheten."
+
+#: lib/luks2/luks2_json_metadata.c:2633
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Omkryptering pågår. Det går inte att inaktivera enhet."
+
+#: lib/luks2/luks2_json_metadata.c:2644 lib/luks2/luks2_reencrypt.c:4057
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Misslyckades med att ersätta inaktiverad enhet %s med målet dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2724
+msgid "Failed to read LUKS2 requirements."
+msgstr "Misslyckades med att läsa LUKS2-krav."
+
+#: lib/luks2/luks2_json_metadata.c:2731
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Ej uppfyllt LUKS2-krav identifierat."
+
+#: lib/luks2/luks2_json_metadata.c:2739
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Åtgärden inkompatibel med enhet markerad för föråldrad omkryptering. Avbryter."
+
+#: lib/luks2/luks2_json_metadata.c:2741
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Åtgärden inkompatibel med enhet markerad för LUKS2-omkryptering. Avbryter."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Inte nog med minne för att öppna en nyckelplats."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Misslyckades med att öppna nyckelplats."
+
+#: lib/luks2/luks2_keyslot_luks2.c:53 lib/luks2/luks2_keyslot_luks2.c:108
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Det går inte att använda %s-%s-chiffer för nyckelplatskryptering."
+
+#: lib/luks2/luks2_keyslot_luks2.c:496
+msgid "No space for new keyslot."
+msgstr "Inget utrymme för ny nyckelplats."
+
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2615
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Hashalgoritm %s är inte tillgänglig."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Begärde ogiltigt återhämtningsläge för omkryptering."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Det går inte att uppdatera återhämtningstup. Ny typ tillhandahåller %<PRIu64> byte, begärt utrymme är: %<PRIu64> byte."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Misslyckades med att sammandrag för omkrypteringsverifikation."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Det går inte kontrollera status för enheten med uuid: %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Det går inte att konvertera huvud med ytterligare metadata för LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3715
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Det går inte att använda chiffer-spefikationen %s-%s för LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Kunde inte flytta nyckelplatsområde. Inte nog med utrymme."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Det går inte att konvertera till LUKS2-format - ogiltig metadata."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Kunde inte flytta nyckelplatsområde. Området för LUKS2-nyckelplatser är för litet."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Kunde inte flytta nyckelplatsområde."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Det går inte att konvertera till LUKS1-format - standardkrypteringstorleken är inte 512 byte."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Det går inte att konvertera till LUKS1-format - kontrollsummor för nyckelplatser är inte LUKS1-kompatibla."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Det går inte att konvertera till LUKS1-format - enheterna använder inbäddat nyckelchiffer %s."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Det går inte att konvertera till LUKS1-format - enheten använder flera segment."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Det går inte att konvertera till LUKS1-format - LUKS2-huvud innehåller %u token."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Det går inte att konvertera till LUKS1-format - nyckelplats %u är i ogiltigt tillstånd."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Det går inte att konvertera till LUKS1-format - plats %u (av maximalt antal platser) är fortfarande aktiv."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "Det går inte att konvertera till LUKS1-format - nyckelplats %u är inte LUKS1-kompatibel."
+
+#: lib/luks2/luks2_reencrypt.c:1107
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Hotzone-storleken måste vara en multipel av beräknad zonjustering (%zu-byte)."
+
+#: lib/luks2/luks2_reencrypt.c:1112
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Enhetsstorleken måste vara en multipel av beräknad zonstorlek (%zu byte)."
+
+#: lib/luks2/luks2_reencrypt.c:1319 lib/luks2/luks2_reencrypt.c:1505
+#: lib/luks2/luks2_reencrypt.c:1588 lib/luks2/luks2_reencrypt.c:1630
+#: lib/luks2/luks2_reencrypt.c:3852
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Misslyckades med att initiera gammal segmentlagringsinbäddning."
+
+#: lib/luks2/luks2_reencrypt.c:1333 lib/luks2/luks2_reencrypt.c:1483
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Misslyckades med att initiera ny segmentlagringsinbäddning."
+
+#: lib/luks2/luks2_reencrypt.c:1460 lib/luks2/luks2_reencrypt.c:3864
+msgid "Failed to initialize hotzone protection."
+msgstr "Misslyckades med att initiera skydd av hotzone."
+
+#: lib/luks2/luks2_reencrypt.c:1532
+msgid "Failed to read checksums for current hotzone."
+msgstr "Misslyckades med att läsa kontrollsummor från aktuell varm zon."
+
+#: lib/luks2/luks2_reencrypt.c:1539 lib/luks2/luks2_reencrypt.c:3878
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Misslyckades med att läsa område för varm zon med början %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1558
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Misslyckades med att dekryptera sektor %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1564
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Misslyckades med återhämta sektor %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2128
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Käll- och målenhetstorlekar stämmer inte överens. Källa %<PRIu64>, mål: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2226
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Misslyckades med att aktivera varm zon-enhet %s."
+
+#: lib/luks2/luks2_reencrypt.c:2243
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Misslyckades med att aktivera överlagringsenheten %s med aktuell ursprungstabell."
+
+#: lib/luks2/luks2_reencrypt.c:2250
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Misslyckades med att läsa in ny mappning för enhet %s."
+
+#: lib/luks2/luks2_reencrypt.c:2321
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Misslyckades med att uppdatera listan över omkrypteringsenheter."
+
+#: lib/luks2/luks2_reencrypt.c:2497
+msgid "Failed to set new keyslots area size."
+msgstr "Misslyckades med att sätta en ny storlek på nyckelplatsområdet."
+
+#: lib/luks2/luks2_reencrypt.c:2633
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Dataskiftning är inte justerad till krypteringssektorstorlek (%<PRIu32> byte)."
+
+#: lib/luks2/luks2_reencrypt.c:2664
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Stöder inte motståndsläge %s"
+
+#: lib/luks2/luks2_reencrypt.c:2741
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Flyttat segmentstorlek kan inte vara större än dataskift-värdet."
+
+#: lib/luks2/luks2_reencrypt.c:2799
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Flyttat segment för stor. Begärd storlek %<PRIu64>, tillgänglig storlek för: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2886
+msgid "Failed to clear table."
+msgstr "Misslyckades med att rensa tabellen."
+
+#: lib/luks2/luks2_reencrypt.c:2972
+msgid "Reduced data size is larger than real device size."
+msgstr "Minskad datastorlek är större än den riktiga enhetsstorleken."
+
+#: lib/luks2/luks2_reencrypt.c:2979
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Dataenhet är inte justerad till krypteringssektorstorlek (%<PRIu32> byte)."
+
+#: lib/luks2/luks2_reencrypt.c:3013
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Dataskiftning (%<PRIu64> sektorer) är mindre än framtida dataförskjutning (%<PRIu64> sektorer)."
+
+#: lib/luks2/luks2_reencrypt.c:3020 lib/luks2/luks2_reencrypt.c:3508
+#: lib/luks2/luks2_reencrypt.c:3529
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Misslyckades med att öppna %s i exklusivt läge (redan mappad eller monterad)."
+
+#: lib/luks2/luks2_reencrypt.c:3209
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Enheten är inte markerad för LUKS2-omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3226 lib/luks2/luks2_reencrypt.c:4181
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Misslyckades med att läsa in LUKS2-omkrypteringskontext."
+
+#: lib/luks2/luks2_reencrypt.c:3306
+msgid "Failed to get reencryption state."
+msgstr "Misslyckades med att erhålla status för omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3310 lib/luks2/luks2_reencrypt.c:3624
+msgid "Device is not in reencryption."
+msgstr "Enheten är inte i omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3317 lib/luks2/luks2_reencrypt.c:3631
+msgid "Reencryption process is already running."
+msgstr "Omkrypteringsprocessen pågår redan."
+
+#: lib/luks2/luks2_reencrypt.c:3319 lib/luks2/luks2_reencrypt.c:3633
+msgid "Failed to acquire reencryption lock."
+msgstr "Misslyckades med att erhålla skrivlås för omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3337
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Det går inte att fortsätta med omkryptering. Kör återställning av omkryptering först."
+
+#: lib/luks2/luks2_reencrypt.c:3472
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Aktiv enhetsstorlek och begärd omkrypteringsstorlek skiljer sig åt."
+
+#: lib/luks2/luks2_reencrypt.c:3486
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "Ogiltig enhetsstorlek begärd i omkrypteringsparametrarna."
+
+#: lib/luks2/luks2_reencrypt.c:3563
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Omkryptering pågår redan. Det går inte att utföra återhämtning."
+
+#: lib/luks2/luks2_reencrypt.c:3732
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "LUKS2-omkryptering är redan initierad i metadata."
+
+#: lib/luks2/luks2_reencrypt.c:3739
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Misslyckades med att initiera LUKS2-omkryptering i metadata."
+
+#: lib/luks2/luks2_reencrypt.c:3834
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Misslyckades med sätta enhetssegment för nästa varm zon-omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3886
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Misslyckades med att skriva motståndsmetadata för omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:3893
+msgid "Decryption failed."
+msgstr "Avkryptering misslyckades."
+
+#: lib/luks2/luks2_reencrypt.c:3898
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Misslyckades med att skriva område för varm zon med början vid %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3903
+msgid "Failed to sync data."
+msgstr "Misslyckades med att synkronisera data."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Misslyckades med att uppdatera metadata efter aktuell varm zon för omkrypteringär färdigställd."
+
+#: lib/luks2/luks2_reencrypt.c:4000
+msgid "Failed to write LUKS2 metadata."
+msgstr "Misslyckades med att skriva LUKS2-metadata."
+
+#: lib/luks2/luks2_reencrypt.c:4023
+msgid "Failed to wipe unused data device area."
+msgstr "Misslyckades med att radera oanvänt område på dataenheten."
+
+#: lib/luks2/luks2_reencrypt.c:4029
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Misslyckades med att ta bort oanvänd (obunden) nyckelplats %d."
+
+#: lib/luks2/luks2_reencrypt.c:4039
+msgid "Failed to remove reencryption keyslot."
+msgstr "Misslyckades med att ta bort nyckelplats för omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:4049
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Ödesdigert fel vid omkrypteringschunk med start vid %<PRIu64>, %<PRIu64> sektorer lång."
+
+#: lib/luks2/luks2_reencrypt.c:4053
+msgid "Online reencryption failed."
+msgstr "Misslyckades med omkryptering."
+
+#: lib/luks2/luks2_reencrypt.c:4058
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Återuppta inte enheten om inte den ersatts med felmål manuellt."
+
+#: lib/luks2/luks2_reencrypt.c:4112
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Det går inte att fortsätta med omkryptering. Oväntat omkrypteringsläge."
+
+#: lib/luks2/luks2_reencrypt.c:4118
+msgid "Missing or invalid reencrypt context."
+msgstr "Saknat eller ogiltigt omkrypteringskontext."
+
+#: lib/luks2/luks2_reencrypt.c:4125
+msgid "Failed to initialize reencryption device stack."
+msgstr "Misslyckades med att initiera listan för omkrypteringsenheter."
+
+#: lib/luks2/luks2_reencrypt.c:4147 lib/luks2/luks2_reencrypt.c:4194
+msgid "Failed to update reencryption context."
+msgstr "Misslyckades med att uppdatera omkrypteringskontext."
+
+#: lib/luks2/luks2_reencrypt_digest.c:406
+msgid "Reencryption metadata is invalid."
+msgstr "Omkryperingsmetadata är ogiltigt."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Krypteringsparametrar för nyckelplatser stöds endast av LUKS2-enheter."
+
+#: src/cryptsetup.c:108
+#, c-format
+msgid "Enter token PIN:"
+msgstr "Ange token-PIN:"
+
+#: src/cryptsetup.c:110
+#, c-format
+msgid "Enter token %d PIN:"
+msgstr "Ange token-PIN %d :"
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:966 src/cryptsetup.c:1293
+#: src/utils_reencrypt.c:1048 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Inget känt chifferspecifikationsmönster kunde identifieras."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "VARNING: parametern --hash ignoreras i plain-läge med specificerad nyckelfil.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "VARNING: flaggan --keyfile-size ignoreras, lässtorleken är densamma som storleken för krypteringsnyckeln.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "Identfierar enhetssignatur(er) på %s. Att fortsätta kan skada befintlig data."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1040 src/cryptsetup.c:1088
+#: src/cryptsetup.c:1154 src/cryptsetup.c:1270 src/cryptsetup.c:1343
+#: src/cryptsetup.c:1994 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:275
+msgid "Operation aborted.\n"
+msgstr "Åtgärd avbruten.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Flaggan --key-file krävs."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Ange VeraCrypt PIM: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Ogiltigt PIM-värde:tolkningsfel."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Ogiltigt PIM-värde: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Ogiltigt PIM-värde:utanför intervallet."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Inget enhetshuvud finns tillgängligt med denna lösenfras."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Enheten %s är inte en giltig BITLK-enhet."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Det går inte att avgöra volymens nyckelstorlek för BTLK, använd flaggan --key-size."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Utskrift av huvudet med volymnyckel är känslig information\n"
+"som tillåter åtkomst till krypterad partition utan lösenfras.\n"
+"Denna utskrift bör alltid lagras krypterad på ett säkert ställe."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:2019
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Utskrift av huvudet med volymnyckel är känslig information\n"
+"som tillåter åtkomst till krypterad partition utan lösenfras.\n"
+"Denna utskrift bör alltid lagras krypterad på ett säkert ställe."
+
+#: src/cryptsetup.c:664 src/veritysetup.c:321 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Enheten %s är fortfarande aktiv och schemalagd för uppskjuten borttagning.\n"
+
+#: src/cryptsetup.c:698
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Att ändra storlek på aktiv enhet kräver volymnyckel i nyckelringen, men -flaggan --disable-keyring är angiven."
+
+#: src/cryptsetup.c:845
+msgid "Benchmark interrupted."
+msgstr "Prestandamätning avbruten."
+
+#: src/cryptsetup.c:866
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s N/A\n"
+
+#: src/cryptsetup.c:868
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u iterationer per sekund för %zu-bitnyckel\n"
+
+#: src/cryptsetup.c:882
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s N/A\n"
+
+#: src/cryptsetup.c:884
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u iterationer, %5u minne, %1u parallella trådar (CPU:er) för %zu-bitnyckelplats (begärde %u ms)\n"
+
+#: src/cryptsetup.c:908
+msgid "Result of benchmark is not reliable."
+msgstr "Resultat från prestandamätningen är inte pålitligt."
+
+#: src/cryptsetup.c:958
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Tester är ungefärliga och använder endast minne (ingen lagrings-IO).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:978
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "#%*s Algoritm | Nyckel | Kryptering | Avkryptering\n"
+
+#: src/cryptsetup.c:982
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Chiffret %s (med nyckel av %i bitar) är inte tillgängligt."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1001
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Algoritm | Nyckel | Kryptering | AVkryptering\n"
+
+#: src/cryptsetup.c:1012
+msgid "N/A"
+msgstr "N/A"
+
+#: src/cryptsetup.c:1037
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Oskyddad LUKS2-omkryperingsmetadata identiferad. Vänligen verifiera att omkryperingsåtgärden behövs (se luksDump-utdata)\n"
+"och fortsätt (uppgradera metadata) endast om du anser åtgärden som behövd."
+
+#: src/cryptsetup.c:1043
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Ange lösenfras för att skydda och uppgradera omkrypteringmetadata:"
+
+#: src/cryptsetup.c:1087
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Vill du verkligen fortsätta med LUKS2-omkrypteringsåterställning?"
+
+#: src/cryptsetup.c:1096
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Ange lösenfras för att verifiera sammandrag för metadata-omkryptering:"
+
+#: src/cryptsetup.c:1098
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Ange lösenfras för omkrypteringsåterhämtning: "
+
+#: src/cryptsetup.c:1153
+msgid "Really try to repair LUKS device header?"
+msgstr "Vill du verkligen försöka att reparera LUKS-enhetshuvud?"
+
+#: src/cryptsetup.c:1177 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Skrivning avbruten."
+
+#: src/cryptsetup.c:1182 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Rensar enheten för att initialisera kontrollsumma för integritet.\n"
+"Du kan avbryta detta genom att trycka ned CTRL+c (resten av den ej rensade enheten kommer att innehålla en ogiltigt kontrollsumma).\n"
+
+#: src/cryptsetup.c:1204 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Det går inte att inaktivera temporär enhet %s."
+
+#: src/cryptsetup.c:1255
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Flaggan för integritet kan endast användas för formatet LUKS2."
+
+#: src/cryptsetup.c:1260 src/cryptsetup.c:1320
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Flaggorna för storlekar på LUKS2-metadata stöds inte."
+
+#: src/cryptsetup.c:1269
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Deklarationsfilen existerar inte, vill du skapa den?"
+
+#: src/cryptsetup.c:1277
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Det går inte att skapa huvudfil %s."
+
+#: src/cryptsetup.c:1300 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Inga kända integritetspecifikationsmönster identifierat."
+
+#: src/cryptsetup.c:1313
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Det går inte att använda %s som diskhuvud."
+
+#: src/cryptsetup.c:1337 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Detta kommer att skriva över data på %s och går inte att ångra."
+
+#: src/cryptsetup.c:1370 src/cryptsetup.c:1707 src/cryptsetup.c:1772
+#: src/cryptsetup.c:1876 src/cryptsetup.c:1942 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Misslyckades med att sätta pbkdf-parametrar."
+
+#: src/cryptsetup.c:1455
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Förminskad dataoffset endast tillåtet för fristående LUKS-huvuden."
+
+#: src/cryptsetup.c:1466 src/cryptsetup.c:1778
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Det går inte att avgöra volymens nyckelstorlek för LUKS utan nyckelplatser, använd flaggen --key-size."
+
+#: src/cryptsetup.c:1512
+msgid "Device activated but cannot make flags persistent."
+msgstr "Enheten aktiverad men kan inte spara undan flaggorna."
+
+#: src/cryptsetup.c:1591 src/cryptsetup.c:1659
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Nyckelplats %d markerad för borttagning."
+
+#: src/cryptsetup.c:1603 src/cryptsetup.c:1663
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Detta är sista nyckelplatsen. Enheten kommer att bli oanvändbar efter att denna nyckel tagits bort."
+
+#: src/cryptsetup.c:1604
+msgid "Enter any remaining passphrase: "
+msgstr "Ange eventuell återstående lösenfras: "
+
+#: src/cryptsetup.c:1605 src/cryptsetup.c:1665
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Åtgärden avbröts, nyckelplatsen raderades INTE.\n"
+
+#: src/cryptsetup.c:1641
+msgid "Enter passphrase to be deleted: "
+msgstr "Ange lösenfras att ta bort: "
+
+#: src/cryptsetup.c:1691 src/cryptsetup.c:1925 src/cryptsetup.c:2505
+#: src/cryptsetup.c:2649
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Enheten %s är inte en giltig LUKS2-enhet."
+
+#: src/cryptsetup.c:1721 src/cryptsetup.c:1795 src/cryptsetup.c:1829
+msgid "Enter new passphrase for key slot: "
+msgstr "Ange ny lösenfras för nyckelplats: "
+
+#: src/cryptsetup.c:1812 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Ange valfri existerande lösenfras: "
+
+#: src/cryptsetup.c:1880
+msgid "Enter passphrase to be changed: "
+msgstr "Ange lösenfras att ändra: "
+
+#: src/cryptsetup.c:1896 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Ange ny lösenfras: "
+
+#: src/cryptsetup.c:1946
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Ange lösenfras för nyckelplats att konvertera: "
+
+#: src/cryptsetup.c:1970
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "Endast ett enhetsargument för operationen isLuks stöds."
+
+#: src/cryptsetup.c:2078
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Nyckelplats %d innehåller inte obunden nyckel."
+
+#: src/cryptsetup.c:2083
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Utskrift av huvudet med obunden nyckel är känslig information.\n"
+"Denna utskrift bör alltid lagras krypterad på ett säkert ställe."
+
+#: src/cryptsetup.c:2169 src/cryptsetup.c:2198
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s är inte ett aktivt %s-enhetsnamn."
+
+#: src/cryptsetup.c:2193
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s är inte ett aktivt LUKS-enhetsnamn eller så saknas deklaration."
+
+#: src/cryptsetup.c:2255 src/cryptsetup.c:2274
+msgid "Option --header-backup-file is required."
+msgstr "Flaggan --header-backup-file krävs."
+
+#: src/cryptsetup.c:2305
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s är inte en cryptsetup-hanterad enhet."
+
+#: src/cryptsetup.c:2316
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Att uppdatera stöds inte för enhetstypen %s"
+
+#: src/cryptsetup.c:2362
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Okänd metadata för enhetstypen %s."
+
+#: src/cryptsetup.c:2364
+msgid "Command requires device and mapped name as arguments."
+msgstr "Kommandot kräver enhet och mappat namn som argument."
+
+#: src/cryptsetup.c:2385
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Denna åtgärd kommer att ta bort alla nyckelplatser på enhet %s.\n"
+"Enheten kommer att bli oanvändbar efter denna åtgärd."
+
+#: src/cryptsetup.c:2392
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Åtgärden avbryten, nyckelplatser raderades EJ.\n"
+
+#: src/cryptsetup.c:2431
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Ogiltig LUKS-typ, endast luks1 och luks2 stöds."
+
+#: src/cryptsetup.c:2447
+#, c-format
+msgid "Device is already %s type."
+msgstr "Enheten är redan av %s-typ."
+
+#: src/cryptsetup.c:2454
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Denna åtgärd kommer att konvertera %s till %s-format.\n"
+
+#: src/cryptsetup.c:2457
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Åtgärden avbröts, enheten konverterades INTE.\n"
+
+#: src/cryptsetup.c:2497
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Saknar flaggan --priority, --label eller --subsystem."
+
+#: src/cryptsetup.c:2531 src/cryptsetup.c:2568 src/cryptsetup.c:2588
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Token %d är ogiltig."
+
+#: src/cryptsetup.c:2534 src/cryptsetup.c:2591
+#, c-format
+msgid "Token %d in use."
+msgstr "Token %d används."
+
+#: src/cryptsetup.c:2546
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Misslyckades med att lägga till luks2-nyckelringsstoken %d."
+
+#: src/cryptsetup.c:2554 src/cryptsetup.c:2617
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Misslyckades med att tilldela token %d till nyckelplats %d."
+
+#: src/cryptsetup.c:2571
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Token %d används ej."
+
+#: src/cryptsetup.c:2608
+msgid "Failed to import token from file."
+msgstr "Misslyckades med att importera token från fil."
+
+#: src/cryptsetup.c:2633
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Misslyckades med att hämta token %d för export."
+
+#: src/cryptsetup.c:2682
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Flaggorna --tcrypt-hidden, --tcrypt-system eller --tcrypt-backup stöds endast på TCRYPT-enhet."
+
+#: src/cryptsetup.c:2685
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Flaggan --veracrypt eller --disable-veracrypt stöds endast för TCRYPT-enhetstyper."
+
+#: src/cryptsetup.c:2688
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Flaggan --veracrypt-pim stöds endast för VeraCrypt-kompatibla enheter."
+
+#: src/cryptsetup.c:2692
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Flaggan --veracrypt-query-pim stöds endast för VeraCrypt-kompatibla enheter."
+
+#: src/cryptsetup.c:2694
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Flaggorna --veracrypt-pim och --veracrypt-query-pim är ömsesidigt uteslutande."
+
+#: src/cryptsetup.c:2703
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Flaggan --persistent är ej tillåtet med --test-passphrase."
+
+#: src/cryptsetup.c:2706
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Flaggorna --refresh och --test-passphrase är ömsesidigt uteslutande."
+
+#: src/cryptsetup.c:2709
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Flaggan --shared är endast tillåten för öppning av plain-enhet."
+
+#: src/cryptsetup.c:2712
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Flaggan --skip stöds endast för öppning av plain-enheter och loopaes-enheter."
+
+#: src/cryptsetup.c:2715
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Flaggan --offset med åtgärden öppna stöds endast för öppning av plain-enheter och loopaes-enheter."
+
+#: src/cryptsetup.c:2718
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Flaggan --tcrypt-hidden kan inte kombineras med --allow-discards."
+
+#: src/cryptsetup.c:2722
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Flaggan för sektorstorlek med åtgärden öppna stöds endast för plain-enheter."
+
+#: src/cryptsetup.c:2726
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Flaggan för stora IV-sektorer stöds endast för att öppna enheter av plain-typ med sektorstorlek större än 512 byte."
+
+#: src/cryptsetup.c:2730
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT and BITLK devices."
+msgstr "Flaggan --test-passphrase är endast tillåten för open för LUKS-, TCRYPT-, och BITLK-enheter."
+
+#: src/cryptsetup.c:2733 src/cryptsetup.c:2756
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Flaggan --device-size och --size kan inte kombineras."
+
+#: src/cryptsetup.c:2736
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Flaggan --unbound är endast tillåten för öppning av luks-enhet."
+
+#: src/cryptsetup.c:2739
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Flaggan --unbound kan inte användas utan --test-passphrase."
+
+#: src/cryptsetup.c:2748 src/veritysetup.c:664 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Flaggorna --cancel-deferred och --deferred går inte att använda samtidigt."
+
+#: src/cryptsetup.c:2764
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Flaggan --reduce-device-size och --data-size kan inte kombineras."
+
+#: src/cryptsetup.c:2767
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Flaggan --active-name kan endast anges för LUKS2-enheter."
+
+#: src/cryptsetup.c:2770
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Flaggan --active-name och --force-offline-reencrypt kan inte kombineras."
+
+#: src/cryptsetup.c:2778 src/cryptsetup.c:2808
+msgid "Keyslot specification is required."
+msgstr "Specifikation för nyckelplats krävs."
+
+#: src/cryptsetup.c:2786
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Flaggan --align-payload och --offset kan inte kombineras."
+
+#: src/cryptsetup.c:2789
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Flaggan --integrity-no-wipe kan endast användas för åtgärden formatera med integritetsutökningar."
+
+#: src/cryptsetup.c:2792
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Endast en av flaggorna --use-[u]random är tillåten."
+
+#: src/cryptsetup.c:2800
+msgid "Key size is required with --unbound option."
+msgstr "Nyckelstorlek krävs med flaggan --unbound."
+
+#: src/cryptsetup.c:2819
+msgid "Invalid token action."
+msgstr "Ogiltig tokenåtgärd."
+
+#: src/cryptsetup.c:2822
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "parametern --key-description krävs för åtgärden lägg till token."
+
+#: src/cryptsetup.c:2826
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Åtgärden kräver specifik token. Använd parametern --token-id."
+
+#: src/cryptsetup.c:2840
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<enhet> [--type <typ>] [<namn>]"
+
+#: src/cryptsetup.c:2840 src/veritysetup.c:487 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "öppna enhet som <namn>"
+
+#: src/cryptsetup.c:2841 src/cryptsetup.c:2842 src/cryptsetup.c:2843
+#: src/veritysetup.c:488 src/veritysetup.c:489 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<namn>"
+
+#: src/cryptsetup.c:2841 src/veritysetup.c:488 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "stäng enhet (ta bort mappning)"
+
+#: src/cryptsetup.c:2842 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "ändra storlek på aktiv enhet"
+
+#: src/cryptsetup.c:2843
+msgid "show device status"
+msgstr "visa enhetsstatus"
+
+#: src/cryptsetup.c:2844
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <chiffer>]"
+
+#: src/cryptsetup.c:2844
+msgid "benchmark cipher"
+msgstr "prestandamät chiffer"
+
+#: src/cryptsetup.c:2845 src/cryptsetup.c:2846 src/cryptsetup.c:2847
+#: src/cryptsetup.c:2848 src/cryptsetup.c:2849 src/cryptsetup.c:2856
+#: src/cryptsetup.c:2857 src/cryptsetup.c:2858 src/cryptsetup.c:2859
+#: src/cryptsetup.c:2860 src/cryptsetup.c:2861 src/cryptsetup.c:2862
+#: src/cryptsetup.c:2863 src/cryptsetup.c:2864
+msgid "<device>"
+msgstr "<enhet>"
+
+#: src/cryptsetup.c:2845
+msgid "try to repair on-disk metadata"
+msgstr "försök att reparera metadata på disken"
+
+#: src/cryptsetup.c:2846
+msgid "reencrypt LUKS2 device"
+msgstr "omkryptering av LUKS2-enhet"
+
+#: src/cryptsetup.c:2847
+msgid "erase all keyslots (remove encryption key)"
+msgstr "ta bort alla nyckelplatser (ta bort krypteringsnyckeln)"
+
+#: src/cryptsetup.c:2848
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "konvertera LUKS från/till LUKS2-format"
+
+#: src/cryptsetup.c:2849
+msgid "set permanent configuration options for LUKS2"
+msgstr "ange permanenta konfigurationsflaggor för LUKS2"
+
+#: src/cryptsetup.c:2850 src/cryptsetup.c:2851
+msgid "<device> [<new key file>]"
+msgstr "<enhet> [<ny nyckelfil>]"
+
+#: src/cryptsetup.c:2850
+msgid "formats a LUKS device"
+msgstr "formaterar en LUKS-enhet"
+
+#: src/cryptsetup.c:2851
+msgid "add key to LUKS device"
+msgstr "lägg till nyckel till LUKS-enhet"
+
+#: src/cryptsetup.c:2852 src/cryptsetup.c:2853 src/cryptsetup.c:2854
+msgid "<device> [<key file>]"
+msgstr "<enhet> [<nyckelfil>]"
+
+#: src/cryptsetup.c:2852
+msgid "removes supplied key or key file from LUKS device"
+msgstr "tar bort angiven nyckel eller nyckelfil från LUKS-enhet"
+
+#: src/cryptsetup.c:2853
+msgid "changes supplied key or key file of LUKS device"
+msgstr "ändrar angiven nyckel eller nyckelfil för LUKS-enhet"
+
+#: src/cryptsetup.c:2854
+msgid "converts a key to new pbkdf parameters"
+msgstr "konverterar en nyckel till nya pbkdf-parametrar"
+
+#: src/cryptsetup.c:2855
+msgid "<device> <key slot>"
+msgstr "<enhet> <nyckelplats>"
+
+#: src/cryptsetup.c:2855
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "rensar nyckeln med nummer <nyckelplats> från LUKS-enhet"
+
+#: src/cryptsetup.c:2856
+msgid "print UUID of LUKS device"
+msgstr "skriv ut UUID för LUKS-enhet"
+
+#: src/cryptsetup.c:2857
+msgid "tests <device> for LUKS partition header"
+msgstr "testar <enhet> för LUKS-partitionshuvud"
+
+#: src/cryptsetup.c:2858
+msgid "dump LUKS partition information"
+msgstr "skriver ut information om LUKS-partition"
+
+#: src/cryptsetup.c:2859
+msgid "dump TCRYPT device information"
+msgstr "skriver ut information om TCRYPT-partition"
+
+#: src/cryptsetup.c:2860
+msgid "dump BITLK device information"
+msgstr "skriv ut BITLK-enhetsinformation"
+
+#: src/cryptsetup.c:2861
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Försätt LUKS-enhet i vänteläge och rensa nyckel (alla in-/ut-åtgärder är frusna)"
+
+#: src/cryptsetup.c:2862
+msgid "Resume suspended LUKS device"
+msgstr "Återuppta LUKS-enhet i vänteläge"
+
+#: src/cryptsetup.c:2863
+msgid "Backup LUKS device header and keyslots"
+msgstr "Säkerhetskopiera huvud och nyckelplatser från LUKS-enhet"
+
+#: src/cryptsetup.c:2864
+msgid "Restore LUKS device header and keyslots"
+msgstr "Återställ huvud och nyckelplatser för LUKS-enhet"
+
+#: src/cryptsetup.c:2865
+msgid "<add|remove|import|export> <device>"
+msgstr "<läggtill|tabort|importera|exportera> <enhet>"
+
+#: src/cryptsetup.c:2865
+msgid "Manipulate LUKS2 tokens"
+msgstr "Manipulera LUKS2-token"
+
+#: src/cryptsetup.c:2884 src/veritysetup.c:505 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<åtgärd> är en av:\n"
+
+#: src/cryptsetup.c:2890
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose\n"
+msgstr ""
+"\n"
+"Du kan också använda gamla <åtgärd> syntaxalias:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkOpen\n"
+
+#: src/cryptsetup.c:2894
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<namn> är enheten att skapa under %s\n"
+"<enhet> är den krypterade enheten\n"
+"<nyckelplats> är numret för LUKS-nyckelplatsen att ändra\n"
+"<nyckelfil> valfri nyckelfil för den nya nyckeln för luksAddKey-åtgärden\n"
+
+#: src/cryptsetup.c:2901
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Inkompilerat standardmetadataformat är %s (för luksFormat-åtgärd).\n"
+
+#: src/cryptsetup.c:2906 src/cryptsetup.c:2909
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Stöd för externa LUKS2-insticksmoduler är %s.\n"
+
+#: src/cryptsetup.c:2906
+msgid "compiled-in"
+msgstr "inkompilerad"
+
+#: src/cryptsetup.c:2907
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Sökväg för externa LUKS2-insticksmoduler är %s.\n"
+
+#: src/cryptsetup.c:2909
+msgid "disabled"
+msgstr "inaktiverad"
+
+#: src/cryptsetup.c:2913
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Inkompilerade standardnyckel- och standardlösenfrasparametrar:\n"
+"\tStörsta nyckelfilstorlek: %dkB, Största interaktiv lösenfraslängd %d (tecken)\n"
+"Standard-PBKDF för LUKS1: %s, iterationstid: %d (ms)\n"
+"Standard-PBKDF för LUKS2: %s\n"
+"\tIterationstid: %d, Minne: %dkB, Parallella trådar: %d\n"
+
+#: src/cryptsetup.c:2924
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Inkompilerade standardchifferparametrar för enheter:\n"
+"\tloop-AES: %s, Nyckel %d bitar\n"
+"\tplain: %s, Nyckel: %d bitar, Lösenordshashning: %s\n"
+"\tLUKS1: %s, Nyckel: %d bitar, LUKS-huvudhashning %s, RNG: %s\n"
+
+#: src/cryptsetup.c:2933
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: Standardnyckelstorlek med XTS-läge (två interna nycklar) kommer att dubbleras.\n"
+
+#: src/cryptsetup.c:2951 src/veritysetup.c:644 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: kräver %s som argument"
+
+#: src/cryptsetup.c:2997 src/utils_reencrypt_luks1.c:1194
+msgid "Key slot is invalid."
+msgstr "Nyckelplatsen är ogiltig."
+
+#: src/cryptsetup.c:3024
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Enhetsstorlek måste vara en multipel av sektor på 512-byte."
+
+#: src/cryptsetup.c:3029
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Ogiltig högsta storlekspecifikation för varm zon-omkryptering."
+
+#: src/cryptsetup.c:3043 src/cryptsetup.c:3055
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Nyckelstorlek måste vara en multipel av 8 bitar"
+
+#: src/cryptsetup.c:3060
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Högsta förminskningsstorlek för enhet är 1 GiB."
+
+#: src/cryptsetup.c:3063
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Minskningsstorlek måste vara en multipel av 512-bytesektor."
+
+#: src/cryptsetup.c:3080
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Flaggan --priority kan endast vara ignore/normal/prefer."
+
+#: src/cryptsetup.c:3099 src/veritysetup.c:568 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Visa detta hjälpmeddelande"
+
+#: src/cryptsetup.c:3100 src/veritysetup.c:569 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Visa kort information om användning"
+
+#: src/cryptsetup.c:3101 src/veritysetup.c:570 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Skriv ut paketversion"
+
+#: src/cryptsetup.c:3112 src/veritysetup.c:581 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Hjälpflaggor:"
+
+#: src/cryptsetup.c:3132 src/veritysetup.c:599 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[FLAGGA…] <åtgärd> <åtgärdsspecifik>"
+
+#: src/cryptsetup.c:3141 src/veritysetup.c:608 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Argumentet <åtgärd> saknas."
+
+#: src/cryptsetup.c:3211 src/veritysetup.c:639 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Okänd åtgärd."
+
+#: src/cryptsetup.c:3229
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Flaggan --key-file åsidosätter specificerade nyckelfilsargument."
+
+#: src/cryptsetup.c:3235
+msgid "Only one --key-file argument is allowed."
+msgstr "Endast ett argument för --key-file är tillåtet."
+
+#: src/cryptsetup.c:3240
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Password-based key derivation function (PBKDF) kan endast vara pbkdf2 eller argon2i/argon2id."
+
+#: src/cryptsetup.c:3245
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Tvingade PBKDF-iterationer går inte att kombinera med flaggan iteration time."
+
+#: src/cryptsetup.c:3256
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Flaggorna --keyslot-cipher och --keyslot-key-size måste användas tillsammans."
+
+#: src/cryptsetup.c:3264
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Ingen åtgärd utfördes. Startades med flaggan --test-args\n"
+
+#: src/cryptsetup.c:3277
+msgid "Cannot disable metadata locking."
+msgstr "Det går inte att inaktivera metadatalås."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Angav ogiltig saltsträng."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Kan inte skapa hashavbild %s för skrivning."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Det går inte att skapa FEC-avbild %s för skrivning."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Kan inte skapa root-hashfil %s för skrivning."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Det går inte att skriva till root-hash-filen %s."
+
+#: src/veritysetup.c:196 src/veritysetup.c:472
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Enheten %s är inte en giltig VERITY-enhet."
+
+#: src/veritysetup.c:213 src/veritysetup.c:230
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Det går inte att läsa rot-hash-filen %s."
+
+#: src/veritysetup.c:218
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Ogiltig rothashsträng %s."
+
+#: src/veritysetup.c:239
+msgid "Invalid root hash string specified."
+msgstr "Angav ogiltig rothashsträng."
+
+#: src/veritysetup.c:247
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Ogiltig signaturfil %s."
+
+#: src/veritysetup.c:254
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Det går inte att läsa signaturfilen %s."
+
+#: src/veritysetup.c:277 src/veritysetup.c:291
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Kommandot kräver <root-hash> eller flaggan --root-hash-file som argument."
+
+#: src/veritysetup.c:485
+msgid "<data_device> <hash_device>"
+msgstr "<dataenhet> <hashenhet>"
+
+#: src/veritysetup.c:485 src/integritysetup.c:534
+msgid "format device"
+msgstr "formatera enhet"
+
+#: src/veritysetup.c:486
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<dataenhet> <hashenhet> <root_hash>"
+
+#: src/veritysetup.c:486
+msgid "verify device"
+msgstr "verifiera enhet"
+
+#: src/veritysetup.c:487
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<dataenhet> <namn> <hashenhet> [<root_hash>]"
+
+#: src/veritysetup.c:489 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "visa statistik för aktiv enhet"
+
+#: src/veritysetup.c:490
+msgid "<hash_device>"
+msgstr "<hash_enhet>"
+
+#: src/veritysetup.c:490 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "visa information från disk"
+
+#: src/veritysetup.c:509
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<namn> är enheten att skapa under %s\n"
+"<dataenhet> är dataenheten\n"
+"<hashenhet> är enheten som innehåller verifieringsdata\n"
+"<rothash> hash för rotnoden på <hashenhet>\n"
+
+#: src/veritysetup.c:516
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Inkompilerade standardparametrar för dm-verity:\n"
+"\tHash: %s, Datablock (byte): %u, Hashblock (byte): %u, Saltstorlek: %u, Hashformat: %u\n"
+
+#: src/veritysetup.c:654
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Flaggorna --ignore-corruption och --restart-on-corruption kan inte användas tillsammans."
+
+#: src/veritysetup.c:659
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Det går inte att använda flaggorna --panic-on-corruption och --restart-on-corruption tillsammans."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Det här kommer oåterkalligen tatt skriva över data på %s och %s.\n"
+"För att bevara dataenheten använd flaggan --no-wipe (och aktivera sedan med --integrity-recalculate).:w "
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Formaterad med taggstorlek %u, intern integritet %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Att sätta flaggan för att räkna om stöds ej, överväg att använda --wipe istället."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Enheten %s är inte en giltig INTEGRITY-enhet."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<integrity_enhet>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<integritet_enhet> <namn>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<namn> är enheten att skapa under %s\n"
+"<integritetsenhet> är enheten som innehåller data med integritetstaggar\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Inkompilerade standardparametrar för dm-integrity:\n"
+"\tKontrollsummealgoritm: %s\n"
+"\tMaximal nyckelfilstorlek: %dkB\n"
+"\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Ogiltig --%s-storlek. Maximal storlek är %u byte."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Både flaggor för nyckelfil och nyckelstorlek måste specifiiceras."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Både flaggor för nyckelfil för journalintegritet och nyckelstorlek måste specificeras."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Integritetsalgoritm för journal måste anges om integritetsnyckel för journal används."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Både flaggor för nyckelfil för journalkryptering och nyckelstorlek måste specificeras."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Krypteringsalgoritm för journal måste anges om integritetsnyckel för journal används."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Flaggorna för återställning- och bitmap-läge är ömsesidigt uteslutande."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Det går inte att använda journalflaggor i bitmap-läge."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Flaggan för integritet kan endast användas i bitmap-läge."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"VARNING!\n"
+"========\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Är du säker (Ange 'yes' i versaler): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Fel vid läsning av svar från terminal."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Kommandot lyckades."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "fel eller saknar parametrar"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "ingen behörighet eller dålig lösenfras"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "slut på minne"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "angav fel enhet eller fil"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "enheten existerar redan eller så är enheten upptagen"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "okänt fel"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Kommandot misslyckades med kod %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Nyckelplats %i är ändrad."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Nyckelplats %i är upplåst."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Nyckelplats %i är upplåst."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Token %i används."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Token %i används."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "Ingen token kunde låsas upp med denna PIN."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Token %i kräver PIN."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Token (type %s) kräver PIN."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token %i kan inte låsa upp tilldelade nyckelplatser (felaktigt lösenord)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Token (typ %s) kan inte låsa upp tilldelade nyckelplatser (felaktigt lösenord)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Token %i kräver en saknad resurs."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Token (typ %s) kräver en saknad resurs."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Ingen användbar token (typ %s) tillgänglig."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Ingen användbar token tillgänglig."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Det går inte att läsa nyckelfilen %s."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Det går inte att läsa %d byte från nyckelfilen %s."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Det går inte att öppna nyckelfilen %s för skrivning."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Det går inte att skriva till nyckelfilen %s."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>t%02<PRIu64>m%02<PRIu64>s"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> dagar"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "skrev %4<PRIu64> %s"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "hastighet %5.1f %s/s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Förlopp: %5.1f%%, ETA %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Avslutad, tid %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Det går inte att kontrollera lösenordskvalitet: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Misslyckades med kvalitetskontroll av lösenord:\n"
+"%s"
+
+#: src/utils_password.c:81
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Misslyckades med kvalitetskontroll av lösenord: Dålig lösenfras (%s)"
+
+#: src/utils_password.c:231 src/utils_password.c:245
+msgid "Error reading passphrase from terminal."
+msgstr "Fel vid läsning av lösenfras från terminal."
+
+#: src/utils_password.c:243
+msgid "Verify passphrase: "
+msgstr "Verifiera lösenfras: "
+
+#: src/utils_password.c:250
+msgid "Passphrases do not match."
+msgstr "Lösenfraserna stämmer inte överens."
+
+#: src/utils_password.c:288
+msgid "Cannot use offset with terminal input."
+msgstr "Det går inte att använda offset med terminalinmatning."
+
+#: src/utils_password.c:292
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Ange lösenfras: "
+
+#: src/utils_password.c:295
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Ange lösenfras för %s: "
+
+#: src/utils_password.c:329
+msgid "No key available with this passphrase."
+msgstr "Ingen nyckel finns tillgänglig med denna lösenfras."
+
+#: src/utils_password.c:331
+msgid "No usable keyslot is available."
+msgstr "Ingen tillgänglig användbar nyckelplats."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Kan inte verifiera lösenfras på icke-tty-ingångar."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Misslyckades med att öppna filen %s i skrivskyddat läge."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Tillhandahåll giltig JSON för LUKS2-token:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Misslyckades med att läsa in JSON-filen."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Läsning avbryten."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Misslyckades med att öppna filen %s in skrivläge."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Skrivning avbruten."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Misslyckades med att skriva JSON-fil."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Auto-identifierade aktiv dm-enhet ”%s” för dataenheten %s.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Misslyckades med att identifiera kopplingarna till enhet %s."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Enheten %s är inte en giltig blockenhet.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Det går inte att avgöra om enheten %s är aktiverade eller ej.\n"
+"Är du säker på att du vill fortsätta kryptera om i frånkopplat läge?\n"
+"Det kan leda till datakorruption om enheten är aktiverad.\n"
+"För att kryptera om i uppkopplat läge, använd istället flaggan --active-name.\n"
+
+#: src/utils_reencrypt.c:175
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Enheten är inte under LUKS2-omkryptering. Motsägelsefull flagga --encrypt."
+
+#: src/utils_reencrypt.c:180
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Enheten är inte i LUKS2-dekryptering. Motsägelsefull flagga --decrypt."
+
+#: src/utils_reencrypt.c:187
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Enheten är under omkryptering med dataskiftåterhämtning. Begärd flagga --resillence kan inte tillämpas."
+
+#: src/utils_reencrypt.c:193 src/utils_reencrypt.c:199
+#: src/utils_reencrypt.c:205 src/utils_reencrypt.c:681
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Begärd flagga --resilience kan inte tillämpas på aktuell omkrypteringsåtgärd."
+
+#: src/utils_reencrypt.c:258
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Enheten kräver omkrypteringsåterställning. Starta repair först."
+
+#: src/utils_reencrypt.c:268
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Enheten %s är redan under LUKS2-omkryptering. Vill du återuppta tidigare intierad åtgärd?"
+
+#: src/utils_reencrypt.c:314
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Stöder inte längre föråldrad LUKS2-omkryptering."
+
+#: src/utils_reencrypt.c:379
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Kryptering för enhet med integritetsprofil stöds ej."
+
+#: src/utils_reencrypt.c:410
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Begärde --sector-size %<PRIu32> är inkompatibel med superblock %s\n"
+"(blockstorlek: %<PRIu32> byte) identifierad på enheten %s."
+
+#: src/utils_reencrypt.c:455
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Kryptering utan frånkopplat huvud (--header) är inte möjligt utan att minska datastorleken på enheten (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:461
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Begärd dataförskjutning måste vara mindre än, eller lika med halva av parametern --reduce-device-size."
+
+#: src/utils_reencrypt.c:471
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Justera värdet av --reduce-device-size-värdet till dubbla --offset %<PRIu64> (sektorer).\n"
+
+#: src/utils_reencrypt.c:501
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Tillfällig huvudfil %s finns redan. Avbryter."
+
+#: src/utils_reencrypt.c:503 src/utils_reencrypt.c:510
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Det går inte att skapa tillfällig huvudfil %s."
+
+#: src/utils_reencrypt.c:535
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "LUKS2-metadatastorleken är större än dataskift-värdet."
+
+#: src/utils_reencrypt.c:572
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Misslyckades med att placera ny header i början på enheten %s."
+
+#: src/utils_reencrypt.c:582
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s är nu aktiv och redo för uppkopplad kryptering.\n"
+
+#: src/utils_reencrypt.c:618
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Aktiva enheten: %s är inte LUKS2."
+
+#: src/utils_reencrypt.c:646
+msgid "Restoring original LUKS2 header."
+msgstr "Återställer ursprungligt LUKS2-huvud."
+
+#: src/utils_reencrypt.c:654
+msgid "Original LUKS2 header restore failed."
+msgstr "Misslyckades med återställning av ursprungligt LUKS2-huvud."
+
+#: src/utils_reencrypt.c:722
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Misslyckades med att läsa/skriva behörighetsflaggor till exporterad huvudfil."
+
+#: src/utils_reencrypt.c:775
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Misslyckades med initiering av omkryptering. Säkerhetskopian av huvudet är tillgänglig i %s."
+
+#: src/utils_reencrypt.c:803
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "LUKS2-dekryptering stöds endast för enheter med fristående header (med data-offset satt till 0)."
+
+#: src/utils_reencrypt.c:934 src/utils_reencrypt.c:943
+msgid "Not enough free keyslots for reencryption."
+msgstr "Inte nog med fria nyckelplatser för omkryptering."
+
+#: src/utils_reencrypt.c:964 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Nyckelfil kan endast användas med --key-slot eller precis en aktiv nyckelplats."
+
+#: src/utils_reencrypt.c:973 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Ange lösenfras för nyckelplats %d: "
+
+#: src/utils_reencrypt.c:985
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Ange lösenfras för nyckelplats %u: "
+
+#: src/utils_reencrypt.c:1037
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Byter krypteringschiffer till %s.\n"
+
+#: src/utils_reencrypt.c:1091
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Inga parametrar för datasegment ändrades. Omkryptering avbruten."
+
+#: src/utils_reencrypt.c:1187
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Ökning av sektorstorlek för kryptering på en frånkopplad enhet stöds ej.\n"
+"Aktivera enheten för eller använd flaggan --force-offline-reencrypt (farligt!)."
+
+#: src/utils_reencrypt.c:1227 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Omkryptering avbryten."
+
+#: src/utils_reencrypt.c:1232
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Återupptar LUKS-omkryptering i tvingat frånkopplat läge.\n"
+
+#: src/utils_reencrypt.c:1249
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "Enheten %s innehåller felaktig LUKS-metadata. Avbryter åtgärden."
+
+#: src/utils_reencrypt.c:1265 src/utils_reencrypt.c:1287
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Enheten %s är redan en LUKS-enhet. Avbryter åtgärd."
+
+#: src/utils_reencrypt.c:1293
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Enheten %s är redan i LUKS-omkryptering. Avbryter åtgärd."
+
+#: src/utils_reencrypt.c:1366
+msgid "LUKS2 decryption requires --header option."
+msgstr "LUKS2-dekryptering kräver flaggan --header."
+
+#: src/utils_reencrypt.c:1414
+msgid "Command requires device as argument."
+msgstr "Kommandot kräver en enhet som argument."
+
+#: src/utils_reencrypt.c:1427
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Versionskonflikt. Enheten %s är LUKS1."
+
+#: src/utils_reencrypt.c:1433
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Versionskonflikt. Enheten %s är under LUKS2-omkryptering."
+
+#: src/utils_reencrypt.c:1439
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Versionskonflikt. Enheten %s är LUKS2."
+
+#: src/utils_reencrypt.c:1445
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Versionskonflikt: Enheten %s är under LUKS2-omkryptering."
+
+#: src/utils_reencrypt.c:1451
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "LUKS2-omkryptering är redan initierad. Avbryter åtgärd."
+
+#: src/utils_reencrypt.c:1458
+msgid "Device reencryption not in progress."
+msgstr "Enhetsomkryptering pågår ej"
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Kan inte öppna %s exklusivt, enheten används."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Misslyckades med allokering av justerat minne."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Det går inte att läsa enheten %s."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Markerar LUKS1-enhet %s som oanvändbar."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Det går inte att skriva till enheten %s."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Det går inte att skriva loggfil för omkryptering."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Det går inte att läsa loggfil för omkryptering."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Fel loggformat."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Loggfilen %s existerar, återupptar kryptering.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Aktiverar temporär enhet användandes gammalt LUKS-huvud."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Aktiverar temporär enhet användandes nytt LUKS-huvud."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Aktivering av temporära enheter misslyckades."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Misslyckades med att sätta dataoffset."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Misslyckades med att sätta metadatastorlek."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Skapade nytt LUKS-huvud för enhet %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Skapade säkerhetskopia av %s-huvud på enhet %s."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Misslyckades med att skapa en säkerhetskopia av LUKS-huvuden."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Det går inte återställa %s-huvudet på enheten %s."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Återställde %s-huvudet på enheten %s."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Misslyckades med att öppna temporär LUKS-enhet."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Det går inte att hämta enhetsstorlek."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "In-/utfel under återkryptering."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Angivet UUID är ogiltigt."
+
+#: src/utils_reencrypt_luks1.c:1220
+msgid "Cannot open reencryption log file."
+msgstr "Det går inte att öppna loggfilen för omkryptering."
+
+#: src/utils_reencrypt_luks1.c:1226
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Ingen dekryptering pågår, givet UUID kan endast användas för att återuppta vilande dekrypteringsprocess."
+
+#: src/utils_reencrypt_luks1.c:1280
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Omkryptering kommer att ändra: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1281
+msgid "volume key"
+msgstr "volymnyckeln"
+
+#: src/utils_reencrypt_luks1.c:1283
+msgid "set hash to "
+msgstr "sätt hash till "
+
+#: src/utils_reencrypt_luks1.c:1284
+msgid ", set cipher to "
+msgstr ", sätt chiffer till "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "VARNING: Enheten %s innehåller redan en ”%s”-partitionssignatur.\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "VARNING: Enheten %s innehåller redan en ”%s”-superblocksignatur.\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Misslyckades med att initiera identifiering av enhetssignatur."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Misslyckades med att ta status på enhet %s."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Misslyckades med att öppna filen %s i läs-/skrivläge."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Kommer att rensa befintlig ”%s” på enheten %s."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Kommer att rensa befintlig ”%s” på enheten %s."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Misslyckades med att radera enhetssignatur."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Misslyckades med söka av enheten %s efter en signatur."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Ogiltig datastorlekspecifikation i flaggan --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Flaggan --%s tillåts inte med åtgärden --%s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Misslyckades med att skriva ssh-token i json."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Experimentell cryptsetup-insticksmodul för att låsa upp LUKS2-enheter med token ansluten via SSH-server. Den tillåter för närvarande endast att lägga till en token till en existerande nyckelplats.\n"
+"\n"
+"Angiven SSH-server måste innehålla en nyckelfil på den angivna sökvägen med ett lösenord för en befintlig nyckelplats på enheten.\n"
+"Inloggningsuppgifter kommer att användas av cryptsetup för att att hämta lösenordet genom att använda token när enheten öppnas.\n"
+"\n"
+"Observera: Information som anges när token läggs till (SSH-serverns, adress, användare och sökvägar) kommer att lagras i LUKS2-headern i klartext."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<åtgärd> <enhet>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Flaggor för åtgärden ”add”:"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "Fjärrserverns IP-adress/URL för denna token"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Användarnamn för fjärrservern"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Sökvägen till nyckelfilen på fjärrservern"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Sökväg till SSH-nyckeln för anslutning till fjärrservern"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Nyckelplats att ange token till. Om ej angiven så kommer token att tilldelas till den första nyckelplats som matchar angivet lösenfras."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Allmänna flaggor:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Visar mer detaljerade felmeddelanden"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Visa felsökningsmeddelanden"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Visa felsökningsmeddelanden inklusive JSON-metadata"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Misslyckades med att öppna och importera privat nyckel:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Misslyckades med att importera privat nyckel (lösenordskyddad?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "%s@%s's lösenord: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Misslyckades med att tolka argument.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "En åtgärd måste anges\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "En enhet måste anges för åtgärden ”%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "SSH-servern måste anges för åtgärden ”%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "SSH-användare måste anges för åtgärden ”%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "SSH-sökväg måste anges för åtgärden ”%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "SSH-nyckelplats måste anges för åtgärden ”%s”.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Misslyckades med att öppna %s med tillhandahållna autentiseringsuppgifter.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "Endast åtgärden ”add” stöds för närvarande av denna insticksmodul.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Det går inte att skapa sftp-sessionen: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Det går inte att initiera sftp-sessionen: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Det går inte att öppna sftp-sessionen:"
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Det går inte att stat sftp-filen: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Inte tillräckligt med minne.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Det går inte att läsa fjärrnyckeln: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Anslutning misslyckades: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Okänd server: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "Den öppna nyckelns auth-metod tills inte på värddatorn.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Autentiseringsfel för öppen nyckel: "
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Misslyckades med att läsa BITLK-signatur från %s."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Ogiltig eller okänd signatur för BITLK-enhet."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Misslyckades med att radera säkerhetskopia av segmentdata."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Misslyckades med att inaktivera flaggan för omkrypteringskrav."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Kryptering stöds endast för formatet LUKS2."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "Identifierade LUKS-enhet på %s. Vill du kryptera LUKS-enheten igen?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "Stödjer endast LUKS2-formatet. Använd verktyget cryptsetup-reencrypt för LUKS1."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Föråldrad frånkopplad omkryptering pågår redan. Använd verktyget cryptsetup-reencrypt."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "LUKS2-enheten är inte i omkryptering."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "Sätter LUKS2-flaggan för att kryptera om på enheten %s."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Denna version av cryptsetup-reencrypt kan inte hantera ny interna tokentypen %s."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Misslyckades med att läsa aktiveringsflaggor från säkerhetskopia av huvud."
+
+#~ msgid "Failed to read requirements from backup header."
+#~ msgstr "Misslyckades med att läsa krav från säkerhetskopiehuvud."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "Ändrade pbkdf-parametrarna i nyckelplatsen %i."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Endast värden mellan 1 MiB och 64 MiB är tillåtna som blockstorlek för omkryptering."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "Högsta förminskningsstorlek för enhet är 64 MiB."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[FLAGGA…] <enhet>"
+
+#~ msgid "Argument required."
+#~ msgstr "Kräver argument."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "Flaggan --new måste användas tillsammans med --reduce-device-size eller --header."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "Flaggan --keep-key kan endast användas med --hash, --iter-time eller --pbkdf-force-iterations."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "Flaggan --new kan inte användas tillsammans med --decrypt."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "Flaggan --decrypt är inkompatibel med specificerade parametrar."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "Flaggan --uuid är endast tillåten tillsammans med --decrypt."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Ogiltig luks-typ. Använd en av dessa: 'luks', 'luks1' or 'luks2'."
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Enheten %s används. Det går inte att fortsätta med formateringsåtgärden."
+
+#~ msgid "No free token slot."
+#~ msgstr "Ingen fri plats för token."
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Ogiltig LUKS-enhetstyp."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Chiffret som används för att kryptera disken (se /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Hashen som används för att skapa krypteringsnyckel från lösenfras"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Verifierar lösenfrasen genom att fråga efter den två gånger"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Läs nyckeln från en fil"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Läs volymnyckeln (master) från fil."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Skriv ut volymnyckel (master) istället för nyckelplatsinfo"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Storleken för krypteringsnyckeln"
+
+#~ msgid "BITS"
+#~ msgstr "BITAR"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Begränsa läsningen från nyckelfil"
+
+#~ msgid "bytes"
+#~ msgstr "byte"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Antal byte att hoppa över i nyckelfil"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Begränsa läsningen från nyligen tillagd nyckelfil"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Antal byte att hoppa över i nyligen tillagd nyckelfil"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Platsnummer för ny nyckel (standard är första lediga)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Storleken för enheten"
+
+#~ msgid "SECTORS"
+#~ msgstr "SEKTORER"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Använd endast specificerad enhetsstorlek (ignorera resten av enheten). FARLIGT!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Startoffset i bakändesenheten"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Hur många sektorer av krypterat data som ska hoppas över i början"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Skapa en skrivskyddad mappning"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Fråga inte efter bekräftelse"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Tidsgräns för interaktiv lösenfrasprompt (i sekunder)"
+
+#~ msgid "secs"
+#~ msgstr "sek"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Uppdatering av förloppslinje (i sekunder)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Hur många inmatningsförsök av lösenfrasen som kan göras"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Justera nyttolast i <n> sektorgränser - för luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Fil med säkerhetskopior av LUKS-huvud och nyckelplatser"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Använd /dev/random för att generera volymnyckel"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Använd /dev/urandom för att generera volymnyckel"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Dela enhet med ett annat ej överlappande krypteringssegment"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "UUID för enheten att använda"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Tillåt avvisningsbegäran (TRIM) för enhet"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Enhet eller fil med separerat LUKS-huvud"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Aktivera inte enhet, kontrollera endast lösenfrasen"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Använd dolt huvud (gömd TCRYPT-enhet)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Enheten är system-TCRYPT-disk (med starthanterare)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Använd säkerhetskopia (sekundär) för TCRYPT-huvud"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Sök också efter VeraCrypt-kompatibel enhet"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Personlig iteration för VeraCrypt-kompatibel enhet"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Query Personal Iteration Multiplier för VeraCrypt-kompatibel enhet"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Typer av enhetsmetadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Inaktivera kvalitetskontroll av lösenord (om aktiverat)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Använd flaggan dm-crypt same_cpu_crypt för prestandakompatibilitet"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Använd flaggan dm-crypt submit_from_crypt_cpus för prestandakompatibilitet"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Förbigå dm-crypt's arbetskö och bearbeta läsbegäran synkront"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Förbigå dm-crypt's arbetskö och bearbeta skrivbegäran synkront"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "Enhetsborttagning är förskjuten tills den sista användaren stänger den"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Använder globalt lås för att serialisera minneshård PBKDF (OOM-lösning)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "PBKDF-iterationstid för LUKS (i ms)"
+
+#~ msgid "msecs"
+#~ msgstr "ms"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "PBKDF-algoritm (för LUKS2) (argon2i/argon2id/pbkdf2)"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "Minneskostnadsgräns för PBKDF"
+
+#~ msgid "kilobytes"
+#~ msgstr "kilobyte"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "Parallellkostnad för PBKDF"
+
+#~ msgid "threads"
+#~ msgstr "trådar"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "Iterationskostnad för PBKDF (tvingad, inaktiverar prestandamätning)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Nyckelplats-prioritet: ignore,normal,prefer"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Inaktivera låsning av metadata på disk"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Inaktivera att läsa in volymnycklar via kärnans nyckelring"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Algoritm för dataintegritet (endast LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Inaktivera journal för integritetsenhet"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Rensa inte enhet efter formatering"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Använd ineffektiv föråldrad padding (gamla kärnor)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Fråga inte efter lösenfras om aktivering med token misslyckas"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Tokenantal (standardvärde: any)"
+
+#~ msgid "Key description"
+#~ msgstr "Nyckelbeskrivning"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Sektorstorlek för kryptering (standardvärde 512 byte)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Använd IV-räkning i sektorstorlek (ej i 512 byte)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Sätt och spara undan aktiveringsflaggorna för enheten"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Ange etikett för LUKS2-enhet"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Ange undersystemsetikett för LUKS2-enheten"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Skapa eller skriv ut obunden (inget tilldelat datasegment) LUKS2-nyckelplats"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Läs eller skriv json från eller till en fil"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Områdesstorlek för metadata på LUKS2-huvudet"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Storlek på nyckelplatsområdet för LUKS2-huvud"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Uppdatera (återaktivera) enhet med nya parametrar"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "LUKS2-nyckelplats: Storleken för krypteringsnyckeln"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "LUKS2-nyckelplats: Chiffret används krypering av nyckelplats"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Kryptera LUKS2-enheten permanent (direktkryptering)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Dekryptera LUKS2-enheten (ta bort kryptering)"
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Initiera LUKS2-omkryptering endast i metadata."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Återupptog endast initierad LUKS2-omkryptering."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Förminska dataenhetsstorleken (flytta dataoffset). FARLIGT!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Maximal storlek på omkryptering av varm zon."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Återhämtningstyp för omkrypteringszon (checksumma,journal,ingen)"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Hashkontrollsumma för omkryptering av varm zon"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Överlagra automatisk identifiering av dm-enhet för omkryptering"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "Flaggan --deferred är endast tillåten för kommandot close."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "Flaggan --allow-discards är endast tillåten för åtgärden open."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "Flaggan --persistent är endast tillåten för åtgärden open."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "Flaggan --allow-discards är endast tillåten för åtgärden open."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Flaggan --key-size är endast tillåten för åtgärderna luksFormat, luksAddKey,\n"
+#~ "open och benchmark. För att begränsa läsning från nyckelfil, använd --keyfile-size=(byte)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "Flaggan --integrity är endast tillåten för luksFormat (LUKS2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Flaggorna --label och --subsystem är endast tillåtna för luksFormat och konfiguration av LUKS2-åtgärder."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "Negativt tal för flagga ej tillåtet."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "Flaggan --use-[u]random är endast tillåten för luksFormat."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "Flaggan --uuid är endast tillåten för luksFormat och luksUUID."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "Flaggan --align-payload är endast tillåten för luksFormat."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Flaggorna --luks2-metadata-size och --opt-luks2-keyslots-size tillåts endast för luksFormat med LUKS2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Ogiltig storlekspecifikation för LUKS2-metadata på enhet."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Ogiltig storlekspecifikation för LUKS2-nyckelplats på enhet."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "Flaggan --offset stöds endast för öppning av vanliga och loopaes-enheter, luksFormat och omkrypteringsenheter."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Angav ett ogiltigt argument för parametern --veracrypt-pim."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "Flaggan för sektorstorlek stöds inte för detta kommando."
+
+#~ msgid "Option --unbound may be used only with luksAddKey and luksDump actions."
+#~ msgstr "Flaggan --unbound kan endast användas tillsammans med ätgärderna luksAddKey och luksDump."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "Flaggan --refresh är endast tillåten för åtgärden open."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "Ogiltig storlekspecifikation på enhet."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Minska storleksöverspill."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Använd inte verity superblock"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Formattyp (1 - normal, 0 - ursprungliga Chrome OS)"
+
+#~ msgid "number"
+#~ msgstr "antal"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Blockstorlek på dataenheten"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Blockstorlek på hashenheten"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "FEC paritetsbyte"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Antalet block i datafilen"
+
+#~ msgid "blocks"
+#~ msgstr "block"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Sökväg till enhet med felkorrigeringsdata"
+
+#~ msgid "path"
+#~ msgstr "sökväg"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Startoffset på hashenheten"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Startoffset på FEC-enheten"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Hashalgoritm"
+
+#~ msgid "string"
+#~ msgstr "sträng"
+
+#~ msgid "Salt"
+#~ msgstr "Salt"
+
+#~ msgid "hex string"
+#~ msgstr "hexsträng"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Sökväg till root-hashsignaturfilen"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Starta om kärna om något skadat identifieras"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Sätt kärnan i Panic-läge om korruption identifieras"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Ignorera om något är skadat, logga endast"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Verifiera inte nollställda block"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Verifiera datablock endast första gången det läses in"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Flaggorna --ignore-corruption, --restart-on-corruption eller --ignore-zero-blocks är endast tillåtna för åtgärden open."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "Flaggan --root-hash-signature kan användas endast för åtgärden open."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Sökvägen till dataenhet (om separat)"
+
+#~ msgid "Journal size"
+#~ msgstr "Journalstorlek"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Infoga sektorer"
+
+#~ msgid "Journal watermark"
+#~ msgstr "Journalvattenmärke"
+
+#~ msgid "percent"
+#~ msgstr "procent"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Journalincheckningstid"
+
+#~ msgid "ms"
+#~ msgstr "ms"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Antal 512-byte sektorer per bit (bitmap-läge)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Renstid för bitmap-läge"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Taggstorlek (per sektor)"
+
+#~ msgid "Sector size"
+#~ msgstr "Sektorstorlek"
+
+#~ msgid "Buffers size"
+#~ msgstr "Bufferstorlek"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Dataintegritetsalgoritm"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Storleken för dataintegritetsnyckeln"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Läs integritetsnyckeln från en fil"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Integritetsalgoritm för journal"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Storleken för journalens integritetssnyckel"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Läs journalens integritetsnyckel från en fil"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Krypteringsalgoritm för journal"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Storleken för journalens krypteringsnyckel"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Läs journalens krypteringsnyckel från en fil"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Återhämtningsläge (ingen journal, ingen taggkontroll)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Använd bitmap för att spåra ändringar och inaktivera journal för integritetsenhet"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Räkna automatiskt initiala taggar."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Skydda inte superblock md HMAC (gamla kärnor)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Tillåt recalculating (omräkning) av volymer med HMAC-nycklar (äldre kärnor)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "Flaggan --integrity-recalculate kan användas endast för öppen åtgärd."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Flaggorna --journal-size, --interleave-sectors, --sector-size, --tag-size och --no-wipe kan endast användas för åtgärden formatera."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "Ogiltig storlekspecifikation på journal."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Blockstorlek för omkryptering"
+
+#~ msgid "MiB"
+#~ msgstr "MiB"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Ändra inte nyckel, ingen omkryptering av dataområde"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Läs volymnyckeln (master) från fil"
+
+#~ msgid "PBKDF2 iteration time for LUKS (in ms)"
+#~ msgstr "PBKDF2-iterationstid för LUKS (i ms)"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Använd direct-io vid enhetsåtkomst"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Använd fsync efter varje block"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Uppdatera loggfilen efter varje block"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Använd endast denna plats (andra kommer att inaktiveras)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Skapa nytt huvud på icke-krypterad enhet"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Avkoda enheten permanent (ta bort kryptering)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "Det UUID som används för att återuppta kryptering"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Typ av LUKS-metadata: luks1, luks2"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "VARNING:Låskatalog %s/%s saknas!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Ogiltig storlek på parametrar för verity-enhet."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "Integritetsalgoritm måste specificieras om integritetsnyckel används."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Fel nyckelstorlek."
+
+#~ msgid "Requested dmcrypt performance options are not supported."
+#~ msgstr "Begärda flaggor för dmcrypt-prestanda stöds inte."
+
+#~ msgid "Cannot format device %s which is still in use."
+#~ msgstr "Det går inte att formatera enheten %s då den används."
+
+#~ msgid "Key slot %d is not used."
+#~ msgstr "Nyckelplats %d används inte."
+
+#~ msgid "Function not available in FIPS mode."
+#~ msgstr "Funktionen är inte tillgänglig i FIPS-läge."
+
+#~ msgid "Key slot %d selected for deletion."
+#~ msgstr "Nyckelplats %d markerad för borttagning."
+
+#~ msgid "open device as mapping <name>"
+#~ msgstr "öppna enhet som mappning <namn>"
+
+#, fuzzy
+#~ msgid "Parameter --refresh is only allowed with open or refresh commands.\n"
+#~ msgstr "Flaggan --refresh är endast tillåten för kommandona open eller refresh."
+
+#~ msgid "Unsupported encryption sector size.\n"
+#~ msgstr "Stöder inte sektorstorlek för kryptering.\n"
+
+#~ msgid "close device (deactivate and remove mapping)"
+#~ msgstr "stäng enhet (inaktivera och ta bort mappning)"
+
+#~ msgid "Failed to set PBKDF parameters."
+#~ msgstr "Misslyckades med att sätta PBKDF-parametrar."
+
+#~ msgid "Cannot seek to device offset.\n"
+#~ msgstr "Kan inte söka till enhetsoffset.\n"
+
+#~ msgid "Interrupted by a signal."
+#~ msgstr "Avbruten av en signal."
+
+#~ msgid "Replaced with key slot %d.\n"
+#~ msgstr "Ersätt med nyckelplats %d.\n"
+
+#~ msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)\n"
+#~ msgstr "Enhet %s är för liten. (LUKS2 kräver minst %<PRIu64> bytes.)\n"
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "minnesallokeringsfel i action_luksFormat"
+
+#~ msgid "Missing LUKS target type, option --type is required.\n"
+#~ msgstr "Saknar måltyp för LUKS, flaggan -type krävs.\n"
+
+#~ msgid "Missing --token option specifying token for removal.\n"
+#~ msgstr ""
+#~ "Saknad flagga --token för att ange token att ta bort.\n"
+#~ " \n"
+
+#~ msgid "Add or remove keyring token"
+#~ msgstr "Lägg till eller ta bort token för nyckelring"
+
+#~ msgid "Activated keyslot %i.\n"
+#~ msgstr "Aktiverade nyckelplats %i.\n"
+
+#~ msgid "Using default pbkdf parameters for new LUKS2 header.\n"
+#~ msgstr "Använder pbkdf-standardparametrar för nya LUKS2-huvuden.\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "För många trädnivåer för verity-volym.\n"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "Nyckel %d är inte aktiv. Kan inte rensa.\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<namn> <dataenhet> <hashenhet> <rothash>"
+
+#~ msgid "create active device"
+#~ msgstr "skapa aktiv enhet"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "ta bort (inaktivera) enhet"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "Förlopp: %5.1f%%, ETA %02llu:%02llu, %4llu MiB skrivna, hastighet %5.1f MiB/s%s"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Kan inte hitta en ledig loopback-enhet.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Kan inte öppna enheten %s\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Kan inte använda insänt UUID om inte dekryptering pågår.\n"
+
+#~ msgid "Enter LUKS passphrase: "
+#~ msgstr "Ange LUKS-lösenfras: "
+
+#~ msgid "Warning: exhausting read requested, but key file %s is not a regular file, function might never return.\n"
+#~ msgstr "Varning: utförlig läsning begärd men nyckelfilen %s är inte en vanlig fil, funktionen kanske aldrig avslutas.\n"
+
+#~ msgid "exclusive "
+#~ msgstr "exklusiv"
+
+#~ msgid "read-only"
+#~ msgstr "skrivskyddad"
+
+#~ msgid "Cannot open device: %s\n"
+#~ msgstr "Kan inte öppna enheten: %s\n"
+
+#~ msgid "BLKROGET failed on device %s.\n"
+#~ msgstr "BLKROGET misslyckades på enheten %s.\n"
+
+#~ msgid "BLKGETSIZE failed on device %s.\n"
+#~ msgstr "BLKGETSIZE misslyckades på enheten %s.\n"
+
+#~ msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+#~ msgstr "VARNING!!! Potentiellt osäkert minne. Är du root?\n"
+
+#~ msgid "Unable to obtain sector size for %s"
+#~ msgstr "Kunde inte läsa av sektorstorlek för %s"
+
+#~ msgid "Backup file %s doesn't exist.\n"
+#~ msgstr "Säkerhetskopian %s finns inte.\n"
+
+#~ msgid "remove LUKS mapping"
+#~ msgstr "ta bort LUKS-mappning"
+
+#~ msgid "identical to luksKillSlot - DEPRECATED - see man page"
+#~ msgstr "identisk med luksKillSlot - FÖRÅLDRAD - se manualsida"
+
+#~ msgid "modify active device - DEPRECATED - see man page"
+#~ msgstr "ändra aktiv enhet - FÖRÅLDRAD - se manualsida"
+
+#~ msgid ""
+#~ "The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\n"
+#~ "WARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"
+#~ msgstr ""
+#~ "Omläsningsåtgärden är föråldrad. Använd ”dmsetup reload” om du verkligen behöver denna funktion.\n"
+#~ "VARNING: använd inte omläsning för ”touch” på LUKS-enheter. Om så är fallet, tryck Ctrl-C nu.\n"
+
+#~ msgid "Obsolete option --non-exclusive is ignored.\n"
+#~ msgstr "Föråldrad flagga --non-exclusive ignoreras.\n"
+
+#~ msgid "Read the key from a file (can be /dev/random)"
+#~ msgstr "Läs nyckeln från en fil (kan vara /dev/random)"
+
+#~ msgid "(Obsoleted, see man page.)"
+#~ msgstr "(Föråldrad, se manualsida)"
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 0000000..6b0218f
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,4480 @@
+# Ukrainian translation for cryptsetup.
+# Copyright (C) 2012 Free Software Foundation, Inc.
+# This file is put in the public domain.
+#
+# Yuri Chornoivan <yurchor@ukr.net>, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023.
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.6.1-rc0\n"
+"Report-Msgid-Bugs-To: cryptsetup@lists.linux.dev\n"
+"POT-Creation-Date: 2023-02-01 15:58+0100\n"
+"PO-Revision-Date: 2023-02-02 10:48+0200\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Lokalize 20.12.0\n"
+
+#: lib/libdevmapper.c:419
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "Не можна ініціалізувати device-mapper, якщо програму запущено не від імені адміністратора (root)."
+
+#: lib/libdevmapper.c:422
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "Не вдалося ініціалізувати device-mapper. Чи завантажено модуль ядра dm_mod?"
+
+#: lib/libdevmapper.c:1102
+msgid "Requested deferred flag is not supported."
+msgstr "Підтримки бажаного прапорця відкладення, %s, не передбачено."
+
+#: lib/libdevmapper.c:1171
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "DM-UUID для пристрою %s було обрізано."
+
+#: lib/libdevmapper.c:1501
+msgid "Unknown dm target type."
+msgstr "Невідомий тип призначення dm."
+
+#: lib/libdevmapper.c:1620 lib/libdevmapper.c:1626 lib/libdevmapper.c:1724
+#: lib/libdevmapper.c:1727
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "Підтримки вказаних параметрів швидкодії dm-crypt не передбачено."
+
+#: lib/libdevmapper.c:1635 lib/libdevmapper.c:1647
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "Підтримки вказаних параметрів обробки пошкоджених даних за допомогою dm-verity не передбачено."
+
+#: lib/libdevmapper.c:1641
+msgid "Requested dm-verity tasklets option is not supported."
+msgstr "Підтримки вказаного параметра завдань dm-verity не передбачено."
+
+#: lib/libdevmapper.c:1653
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "Підтримки вказаних параметрів FEC за допомогою dm-verity не передбачено."
+
+#: lib/libdevmapper.c:1659
+msgid "Requested data integrity options are not supported."
+msgstr "Підтримки вказаних параметрів цілісності даних не передбачено."
+
+#: lib/libdevmapper.c:1663
+msgid "Requested sector_size option is not supported."
+msgstr "Підтримки вказаного параметра sector_size не передбачено."
+
+#: lib/libdevmapper.c:1670 lib/libdevmapper.c:1676
+msgid "Requested automatic recalculation of integrity tags is not supported."
+msgstr "Підтримки потрібного вам автоматичного повторного обчислення міток цілісності не передбачено."
+
+#: lib/libdevmapper.c:1682 lib/libdevmapper.c:1730 lib/libdevmapper.c:1733
+#: lib/luks2/luks2_json_metadata.c:2620
+msgid "Discard/TRIM is not supported."
+msgstr "Підтримки відкидання або обрізання не передбачено."
+
+#: lib/libdevmapper.c:1688
+msgid "Requested dm-integrity bitmap mode is not supported."
+msgstr "Підтримки вказаного режиму бітової карти цілісності dm не передбачено."
+
+#: lib/libdevmapper.c:2724
+#, c-format
+msgid "Failed to query dm-%s segment."
+msgstr "Не вдалося опитати сегмент dm-%s."
+
+#: lib/random.c:73
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Під час створення ключа тому було вичерпано буфер ентропії системи.\n"
+"Будь ласка, пересуньте вказівник миші або наберіть якийсь текст у іншому вікні, щоб зібрати додаткові дані на основі випадкових подій.\n"
+
+#: lib/random.c:77
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Створення ключа (виконано %d%%).\n"
+
+#: lib/random.c:163
+msgid "Running in FIPS mode."
+msgstr "Працюємо у режимі FIPS."
+
+#: lib/random.c:169
+msgid "Fatal error during RNG initialisation."
+msgstr "Критична помилка під час ініціалізації генератора псевдовипадкових чисел."
+
+#: lib/random.c:207
+msgid "Unknown RNG quality requested."
+msgstr "Надійшов запит щодо невідомої якості псевдовипадкових чисел."
+
+#: lib/random.c:212
+msgid "Error reading from RNG."
+msgstr "Помилка читання з генератора псевдовипадкових чисел."
+
+#: lib/setup.c:231
+msgid "Cannot initialize crypto RNG backend."
+msgstr "Не вдалося ініціалізувати допоміжну програму шифрування генератора псевдовипадкових чисел."
+
+#: lib/setup.c:237
+msgid "Cannot initialize crypto backend."
+msgstr "Не вдалося ініціалізувати допоміжну програму шифрування."
+
+#: lib/setup.c:268 lib/setup.c:2151 lib/verity/verity.c:122
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "Підтримки алгоритму хешування %s не передбачено."
+
+#: lib/setup.c:271 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "Помилка під час обробки ключа (на основі хешу %s)."
+
+#: lib/setup.c:342 lib/setup.c:369
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "Не вдалося визначити тип пристрою. Несумісна дія з активації пристрою?"
+
+#: lib/setup.c:348 lib/setup.c:3320
+msgid "This operation is supported only for LUKS device."
+msgstr "Підтримку цієї дії передбачено лише для пристроїв LUKS."
+
+#: lib/setup.c:375
+msgid "This operation is supported only for LUKS2 device."
+msgstr "Підтримку цієї дії передбачено лише для пристроїв LUKS2."
+
+#: lib/setup.c:427 lib/luks2/luks2_reencrypt.c:3010
+msgid "All key slots full."
+msgstr "Заповнено всі слоти ключів."
+
+#: lib/setup.c:438
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "Слот ключа %d є некоректним, будь ласка, виберіть число від 0 до %d."
+
+#: lib/setup.c:444
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "Слот ключа %d заповнено, будь ласка, виберіть інший."
+
+#: lib/setup.c:529 lib/setup.c:3042
+msgid "Device size is not aligned to device logical block size."
+msgstr "Розмір пристрою не вирівняно за розміром логічного блоку пристрою."
+
+#: lib/setup.c:627
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "Виявлено заголовок, але об’єм пристрою %s є надто малим."
+
+#: lib/setup.c:668 lib/setup.c:2942 lib/setup.c:4287
+#: lib/luks2/luks2_reencrypt.c:3782 lib/luks2/luks2_reencrypt.c:4184
+msgid "This operation is not supported for this device type."
+msgstr "Підтримки цієї дії для цього типу пристроїв не передбачено."
+
+#: lib/setup.c:673
+msgid "Illegal operation with reencryption in-progress."
+msgstr "Виконуємо заборонену дію із повторного шифрування."
+
+#: lib/setup.c:802
+msgid "Failed to rollback LUKS2 metadata in memory."
+msgstr "Не вдалося відкотити метадані LUKS2 у пам'яті."
+
+#: lib/setup.c:889 lib/luks1/keymanage.c:249 lib/luks1/keymanage.c:527
+#: lib/luks2/luks2_json_metadata.c:1336 src/cryptsetup.c:1587
+#: src/cryptsetup.c:1727 src/cryptsetup.c:1782 src/cryptsetup.c:1977
+#: src/cryptsetup.c:2133 src/cryptsetup.c:2414 src/cryptsetup.c:2656
+#: src/cryptsetup.c:2716 src/utils_reencrypt.c:1465
+#: src/utils_reencrypt_luks1.c:1192 tokens/ssh/cryptsetup-ssh.c:77
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "Пристрій %s не є коректним пристроєм LUKS."
+
+#: lib/setup.c:892 lib/luks1/keymanage.c:530
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "Непідтримувана версія LUKS, %d."
+
+#: lib/setup.c:1491 lib/setup.c:2691 lib/setup.c:2773 lib/setup.c:2785
+#: lib/setup.c:2952 lib/setup.c:4764
+#, c-format
+msgid "Device %s is not active."
+msgstr "Пристрій %s є неактивним."
+
+#: lib/setup.c:1508
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "Зник основний пристрій для пристрою для шифрування %s."
+
+#: lib/setup.c:1590
+msgid "Invalid plain crypt parameters."
+msgstr "Некоректні параметри звичайного шифрування."
+
+#: lib/setup.c:1595 lib/setup.c:2054
+msgid "Invalid key size."
+msgstr "Некоректний розмір ключа."
+
+#: lib/setup.c:1600 lib/setup.c:2059 lib/setup.c:2262
+msgid "UUID is not supported for this crypt type."
+msgstr "Підтримки UUID для цього типу шифрування не передбачено."
+
+#: lib/setup.c:1605 lib/setup.c:2064
+msgid "Detached metadata device is not supported for this crypt type."
+msgstr "Підтримки пристрою від'єднаних метаданих для цього типу шифрування не передбачено."
+
+#: lib/setup.c:1615 lib/setup.c:1831 lib/luks2/luks2_reencrypt.c:2966
+#: src/cryptsetup.c:1387 src/cryptsetup.c:3383
+msgid "Unsupported encryption sector size."
+msgstr "Непідтримуваний розмір сектора шифрування."
+
+#: lib/setup.c:1623 lib/setup.c:1959 lib/setup.c:3036
+msgid "Device size is not aligned to requested sector size."
+msgstr "Розмір пристрою не вирівняно за вказаним розміром сектора."
+
+#: lib/setup.c:1675 lib/setup.c:1799
+msgid "Can't format LUKS without device."
+msgstr "Форматування LUKS без пристрою неможливе."
+
+#: lib/setup.c:1681 lib/setup.c:1805
+msgid "Requested data alignment is not compatible with data offset."
+msgstr "Потрібне вам вирівнювання даних є несумісним із відступом у даних."
+
+#: lib/setup.c:1756 lib/setup.c:1976 lib/setup.c:1997 lib/setup.c:2274
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "Не можна витирати заголовок на пристрої %s."
+
+#: lib/setup.c:1769 lib/setup.c:2036
+#, c-format
+msgid "Device %s is too small for activation, there is no remaining space for data.\n"
+msgstr "Пристрій %s є надто малим для активації, на ньому не лишиться місця для даних.\n"
+
+#: lib/setup.c:1840
+msgid "WARNING: The device activation will fail, dm-crypt is missing support for requested encryption sector size.\n"
+msgstr "Увага: спроба активувати пристрій завершиться невдало, у dm-crypt не передбачено підтримки для вказаного розміру сектора шифрування.\n"
+
+#: lib/setup.c:1863
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "Ключ тому є надто малим для шифрування із розширеннями цілісності."
+
+#: lib/setup.c:1923
+#, c-format
+msgid "Cipher %s-%s (key size %zd bits) is not available."
+msgstr "Шифрування %s-%s (розмір ключа — %zd бітів) є недоступним."
+
+#: lib/setup.c:1949
+#, c-format
+msgid "WARNING: LUKS2 metadata size changed to %<PRIu64> bytes.\n"
+msgstr "Увага: розмір метаданих LUKS2 змінено до %<PRIu64> байтів.\n"
+
+#: lib/setup.c:1953
+#, c-format
+msgid "WARNING: LUKS2 keyslots area size changed to %<PRIu64> bytes.\n"
+msgstr "Увага: розмір області слотів ключів LUKS2 змінено до %<PRIu64> байтів.\n"
+
+#: lib/setup.c:1979 lib/utils_device.c:911 lib/luks1/keyencryption.c:255
+#: lib/luks2/luks2_reencrypt.c:3034 lib/luks2/luks2_reencrypt.c:4279
+#, c-format
+msgid "Device %s is too small."
+msgstr "Об’єм пристрою %s є надто малим."
+
+#: lib/setup.c:1990 lib/setup.c:2016
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "Не можна форматувати пристрій %s, який перебуває у користуванні."
+
+#: lib/setup.c:1993 lib/setup.c:2019
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "Не можна форматувати пристрій %s, недостатні права доступу."
+
+#: lib/setup.c:2005 lib/setup.c:2334
+#, c-format
+msgid "Cannot format integrity for device %s."
+msgstr "Не вдалося форматувати цілісність для пристрою %s."
+
+#: lib/setup.c:2023
+#, c-format
+msgid "Cannot format device %s."
+msgstr "Не вдалося форматувати пристрій %s."
+
+#: lib/setup.c:2049
+msgid "Can't format LOOPAES without device."
+msgstr "Не можна форматувати LOOPAES без пристрою."
+
+#: lib/setup.c:2094
+msgid "Can't format VERITY without device."
+msgstr "Форматування VERITY без пристрою неможливе."
+
+#: lib/setup.c:2105 lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "Непідтримуваний тип хешування VERITY, %d."
+
+#: lib/setup.c:2111 lib/verity/verity.c:109
+msgid "Unsupported VERITY block size."
+msgstr "Непідтримуваний розмір блоку VERITY."
+
+#: lib/setup.c:2116 lib/verity/verity.c:74
+msgid "Unsupported VERITY hash offset."
+msgstr "Непідтримуваний відступ хешу VERITY."
+
+#: lib/setup.c:2121
+msgid "Unsupported VERITY FEC offset."
+msgstr "Непідтримуваний зсув FEC VERITY."
+
+#: lib/setup.c:2145
+msgid "Data area overlaps with hash area."
+msgstr "Область даних перекривається із областю хешу."
+
+#: lib/setup.c:2170
+msgid "Hash area overlaps with FEC area."
+msgstr "Область хешування перекриваються з областю FEC."
+
+#: lib/setup.c:2177
+msgid "Data area overlaps with FEC area."
+msgstr "Область даних перекривається із областю FEC."
+
+#: lib/setup.c:2313
+#, c-format
+msgid "WARNING: Requested tag size %d bytes differs from %s size output (%d bytes).\n"
+msgstr "Увага: бажаний розмір мітки у %d байтів відрізняється від розміру у результаті %s (%d байтів).\n"
+
+#: lib/setup.c:2392
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "Надіслано запит щодо невідомого типу пристрою шифрування, %s."
+
+#: lib/setup.c:2699 lib/setup.c:2778 lib/setup.c:2791
+#, c-format
+msgid "Unsupported parameters on device %s."
+msgstr "Непідтримувані параметри на пристрої %s."
+
+#: lib/setup.c:2705 lib/setup.c:2798 lib/luks2/luks2_reencrypt.c:2862
+#: lib/luks2/luks2_reencrypt.c:3099 lib/luks2/luks2_reencrypt.c:3484
+#, c-format
+msgid "Mismatching parameters on device %s."
+msgstr "Невідповідність параметрів на пристрої %s."
+
+#: lib/setup.c:2822
+msgid "Crypt devices mismatch."
+msgstr "Невідповідність пристроїв шифрування."
+
+#: lib/setup.c:2859 lib/setup.c:2864 lib/luks2/luks2_reencrypt.c:2361
+#: lib/luks2/luks2_reencrypt.c:2878 lib/luks2/luks2_reencrypt.c:4032
+#, c-format
+msgid "Failed to reload device %s."
+msgstr "Не вдалося перезавантажити пристрій %s."
+
+#: lib/setup.c:2870 lib/setup.c:2876 lib/luks2/luks2_reencrypt.c:2332
+#: lib/luks2/luks2_reencrypt.c:2339 lib/luks2/luks2_reencrypt.c:2892
+#, c-format
+msgid "Failed to suspend device %s."
+msgstr "Не вдалося приспати пристрій %s."
+
+#: lib/setup.c:2882 lib/luks2/luks2_reencrypt.c:2346
+#: lib/luks2/luks2_reencrypt.c:2913 lib/luks2/luks2_reencrypt.c:3945
+#: lib/luks2/luks2_reencrypt.c:4036
+#, c-format
+msgid "Failed to resume device %s."
+msgstr "Не вдалося відновити роботу пристрою %s."
+
+#: lib/setup.c:2897
+#, c-format
+msgid "Fatal error while reloading device %s (on top of device %s)."
+msgstr "Критична помилка під час перезавантаження пристрої %s (над пристроєм %s)."
+
+#: lib/setup.c:2900 lib/setup.c:2902
+#, c-format
+msgid "Failed to switch device %s to dm-error."
+msgstr "Не вдалося перемкнути пристрій %s у режим dm-error."
+
+#: lib/setup.c:2984
+msgid "Cannot resize loop device."
+msgstr "Неможливо змінити розмір петльового пристрою."
+
+#: lib/setup.c:3027
+msgid "WARNING: Maximum size already set or kernel doesn't support resize.\n"
+msgstr "УВАГА: уже вказано максимальний розмір або у ядрі не передбачено можливості зміни розміру.\n"
+
+#: lib/setup.c:3088
+msgid "Resize failed, the kernel doesn't support it."
+msgstr "Не вдалося змінити розмір, у ядрі не передбачено підтримки такої дії."
+
+#: lib/setup.c:3120
+msgid "Do you really want to change UUID of device?"
+msgstr "Ви справді хочете змінити UUID пристрою?"
+
+#: lib/setup.c:3212
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "Файл резервної копії заголовка не містить сумісного із LUKS заголовка."
+
+#: lib/setup.c:3328
+#, c-format
+msgid "Volume %s is not active."
+msgstr "Том %s не є активним."
+
+#: lib/setup.c:3339
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "Том %s вже приспано."
+
+#: lib/setup.c:3352
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "Підтримки присипляння для пристрою %s не передбачено."
+
+#: lib/setup.c:3354
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "Помилка під час спроби приспати пристрій %s."
+
+#: lib/setup.c:3389
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "Підтримки дії з пробудження для пристрою %s не передбачено."
+
+#: lib/setup.c:3391
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "Помилка під час спроби пробудити пристрій %s."
+
+#: lib/setup.c:3425 lib/setup.c:3473 lib/setup.c:3544 lib/setup.c:3589
+#: src/cryptsetup.c:2479
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "Том %s не приспано."
+
+#: lib/setup.c:3559 lib/setup.c:4540 lib/setup.c:4553 lib/setup.c:4561
+#: lib/setup.c:4574 lib/setup.c:6157 lib/setup.c:6179 lib/setup.c:6228
+#: src/cryptsetup.c:2011
+msgid "Volume key does not match the volume."
+msgstr "Ключ тому не відповідає тому."
+
+#: lib/setup.c:3737
+msgid "Failed to swap new key slot."
+msgstr "Не вдалося зарезервувати новий слот ключа."
+
+#: lib/setup.c:3835
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "Слот ключа %d є некоректним."
+
+#: lib/setup.c:3841 src/cryptsetup.c:1740 src/cryptsetup.c:2208
+#: src/cryptsetup.c:2816 src/cryptsetup.c:2876
+#, c-format
+msgid "Keyslot %d is not active."
+msgstr "Слот ключа %d не є активним."
+
+#: lib/setup.c:3860
+msgid "Device header overlaps with data area."
+msgstr "Заголовок пристрою перекривається із областю даних."
+
+#: lib/setup.c:4165
+msgid "Reencryption in-progress. Cannot activate device."
+msgstr "Виконуємо повторне шифрування. Не можна активувати пристрій."
+
+#: lib/setup.c:4167 lib/luks2/luks2_json_metadata.c:2703
+#: lib/luks2/luks2_reencrypt.c:3590
+msgid "Failed to get reencryption lock."
+msgstr "Не вдалося отримати стан блокування для повторного шифрування."
+
+#: lib/setup.c:4180 lib/luks2/luks2_reencrypt.c:3609
+msgid "LUKS2 reencryption recovery failed."
+msgstr "Не вдалося виконати відновлення даних повторного шифрування LUKS2."
+
+#: lib/setup.c:4352 lib/setup.c:4618
+msgid "Device type is not properly initialized."
+msgstr "Тип пристрою не ініціалізовано належним чином."
+
+#: lib/setup.c:4400
+#, c-format
+msgid "Device %s already exists."
+msgstr "Пристрій %s вже існує."
+
+#: lib/setup.c:4407
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "Неможливо скористатися пристроєм %s, некоректна назва або пристрій усе ще використовується."
+
+#: lib/setup.c:4527
+msgid "Incorrect volume key specified for plain device."
+msgstr "Для пристрою зі звичайним шифруванням вказано помилковий ключ тому."
+
+#: lib/setup.c:4644
+msgid "Incorrect root hash specified for verity device."
+msgstr "Для пристрою перевірки вказано помилковий кореневий хеш."
+
+#: lib/setup.c:4654
+msgid "Root hash signature required."
+msgstr "Потрібен хеш-підпис кореневої теки."
+
+#: lib/setup.c:4663
+msgid "Kernel keyring missing: required for passing signature to kernel."
+msgstr "Немає сховища ключів ядра: це сховище потрібне для передавання підпису ядру."
+
+#: lib/setup.c:4680 lib/setup.c:6423
+msgid "Failed to load key in kernel keyring."
+msgstr "Не вдалося завантажити ключ до сховища ключів ядра."
+
+#: lib/setup.c:4736
+#, c-format
+msgid "Could not cancel deferred remove from device %s."
+msgstr "Не вдалося скасувати відкладене вилучення з пристрою %s."
+
+#: lib/setup.c:4743 lib/setup.c:4759 lib/luks2/luks2_json_metadata.c:2756
+#: src/utils_reencrypt.c:116
+#, c-format
+msgid "Device %s is still in use."
+msgstr "Пристрій %s все ще використовується."
+
+#: lib/setup.c:4768
+#, c-format
+msgid "Invalid device %s."
+msgstr "Некоректний пристрій %s."
+
+#: lib/setup.c:4908
+msgid "Volume key buffer too small."
+msgstr "Буфер ключів тому є занадто малим."
+
+#: lib/setup.c:4925
+msgid "Cannot retrieve volume key for LUKS2 device."
+msgstr "Неможливо отримати ключ тому для пристрою із шифруванням LUKS2."
+
+#: lib/setup.c:4934
+msgid "Cannot retrieve volume key for LUKS1 device."
+msgstr "Неможливо отримати ключ тому для пристрою із шифруванням LUKS1."
+
+#: lib/setup.c:4944
+msgid "Cannot retrieve volume key for plain device."
+msgstr "Неможливо отримати ключ тому для пристрою зі звичайним шифруванням."
+
+#: lib/setup.c:4952
+msgid "Cannot retrieve root hash for verity device."
+msgstr "Не вдалося отримати кореневий хеш для пристрою VERITY."
+
+#: lib/setup.c:4959
+msgid "Cannot retrieve volume key for BITLK device."
+msgstr "Неможливо отримати ключ тому для пристрою BITLK."
+
+#: lib/setup.c:4964
+msgid "Cannot retrieve volume key for FVAULT2 device."
+msgstr "Неможливо отримати ключ тому для пристрою FVAULT2."
+
+#: lib/setup.c:4966
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "Підтримки цієї дії для шифрованого пристрою %s не передбачено."
+
+#: lib/setup.c:5147 lib/setup.c:5158
+msgid "Dump operation is not supported for this device type."
+msgstr "Підтримки дії зі створення дампу для цього типу пристроїв не передбачено."
+
+#: lib/setup.c:5500
+#, c-format
+msgid "Data offset is not multiple of %u bytes."
+msgstr "Зсув у даних не є кратним до %u байтів."
+
+#: lib/setup.c:5788
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "Не можна перетворити пристрій %s, який перебуває у користуванні."
+
+#: lib/setup.c:6098 lib/setup.c:6237
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "Не вдалося прив'язати слот ключа %u як новий ключ тому."
+
+#: lib/setup.c:6122
+msgid "Failed to initialize default LUKS2 keyslot parameters."
+msgstr "Не вдалося ініціалізувати типові параметри слоту ключів LUKS2."
+
+#: lib/setup.c:6128
+#, c-format
+msgid "Failed to assign keyslot %d to digest."
+msgstr "Не вдалося прив'язати слот ключа %d до контрольної суми."
+
+#: lib/setup.c:6353
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "Не вдалося додати слот ключа, всі слоти вимкнено і не вказано ключа тому."
+
+#: lib/setup.c:6490
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "У ядрі не передбачено підтримки сховища ключів ядра."
+
+#: lib/setup.c:6500 lib/luks2/luks2_reencrypt.c:3807
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "Не вдалося прочитати пароль із ключа зі сховища ключів (помилка %d)."
+
+#: lib/setup.c:6523
+msgid "Failed to acquire global memory-hard access serialization lock."
+msgstr "Не вдалося створити загальне блокування серіалізації доступу до пам'яті."
+
+#: lib/utils.c:158 lib/tcrypt/tcrypt.c:501
+msgid "Failed to open key file."
+msgstr "Не вдалося відкрити файл ключа."
+
+#: lib/utils.c:163
+msgid "Cannot read keyfile from a terminal."
+msgstr "Не вдалося прочитати файл ключа з термінала."
+
+#: lib/utils.c:179
+msgid "Failed to stat key file."
+msgstr "Не вдалося отримати статистичні дані щодо файла ключа."
+
+#: lib/utils.c:187 lib/utils.c:208
+msgid "Cannot seek to requested keyfile offset."
+msgstr "Не вдалося встановити потрібну позицію у файлі ключа."
+
+#: lib/utils.c:202 lib/utils.c:217 src/utils_password.c:225
+#: src/utils_password.c:237
+msgid "Out of memory while reading passphrase."
+msgstr "Під час читання пароля вичерпано пам’ять."
+
+#: lib/utils.c:237
+msgid "Error reading passphrase."
+msgstr "Помилка під час читання пароля."
+
+#: lib/utils.c:254
+msgid "Nothing to read on input."
+msgstr "Нічого читати з вхідних даних."
+
+#: lib/utils.c:261
+msgid "Maximum keyfile size exceeded."
+msgstr "Перевищено максимальний розмір файла ключа."
+
+#: lib/utils.c:266
+msgid "Cannot read requested amount of data."
+msgstr "Не вдалося прочитати бажаний об’єм даних."
+
+#: lib/utils_device.c:207 lib/utils_storage_wrappers.c:110
+#: lib/luks1/keyencryption.c:91 src/utils_reencrypt.c:1440
+#, c-format
+msgid "Device %s does not exist or access denied."
+msgstr "Пристрою %s не існує або доступ до цього пристрою заборонено."
+
+#: lib/utils_device.c:217
+#, c-format
+msgid "Device %s is not compatible."
+msgstr "Пристрій %s є сумісним."
+
+#: lib/utils_device.c:561
+#, c-format
+msgid "Ignoring bogus optimal-io size for data device (%u bytes)."
+msgstr "Ігноруємо фіктивний розмір optimal-io для пристрою даних (%u байтів)."
+
+#: lib/utils_device.c:722
+#, c-format
+msgid "Device %s is too small. Need at least %<PRIu64> bytes."
+msgstr "Обсяг пристрою %s є надто малим. Потрібно принаймні %<PRIu64> байтів."
+
+#: lib/utils_device.c:803
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "Не можна використовувати пристрій %s, оскільки його вже використано (призначено або змонтовано)."
+
+#: lib/utils_device.c:807
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "Не можна скористатися пристроєм %s, недостатні права доступу."
+
+#: lib/utils_device.c:810
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "Не вдалося отримати дані щодо пристрою %s."
+
+#: lib/utils_device.c:833
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "Не можна використовувати петльовий пристрій, програму запущено не від імені адміністративного користувача (root)."
+
+#: lib/utils_device.c:844
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "Спроба долучення петльового пристрою зазнала невдачі (потрібен петльовий пристрій з встановленим прапорцем автоматичного спорожнення)."
+
+#: lib/utils_device.c:892
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "Бажана точка відступу перебуває за межами об’єму пристрою %s."
+
+#: lib/utils_device.c:900
+#, c-format
+msgid "Device %s has zero size."
+msgstr "Об’єм пристрою %s є нульовим."
+
+#: lib/utils_pbkdf.c:100
+msgid "Requested PBKDF target time cannot be zero."
+msgstr "Вказаний час PBKDF не може бути нульовим."
+
+#: lib/utils_pbkdf.c:106
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "Невідомий тип PBKDF, %s."
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Requested hash %s is not supported."
+msgstr "Підтримки бажаного хешування, %s, не передбачено."
+
+#: lib/utils_pbkdf.c:122
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "Підтримки бажаного типу PBKDF для LUKS1 не передбачено."
+
+#: lib/utils_pbkdf.c:128
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr "Максимальний об'єм пам'яті PBKDF або кількість паралельних потоків обробки не можна встановлювати разом із pbkdf2."
+
+#: lib/utils_pbkdf.c:133 lib/utils_pbkdf.c:143
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr "Задане значення кількості ітерацій для %s є надто низьким (мінімальним є %u)."
+
+#: lib/utils_pbkdf.c:148
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr "Задане значення об'єму пам'яті для %s є надто низьким (мінімальним є %u кілобайтів)."
+
+#: lib/utils_pbkdf.c:155
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "Бажана максимальна вартість пам'яті PBKDF є надто високою (максимальною є %d кілобайтів)."
+
+#: lib/utils_pbkdf.c:160
+msgid "Requested maximum PBKDF memory cannot be zero."
+msgstr "Бажаний максимальний обсяг пам'яті PBKDF не може бути нульовим."
+
+#: lib/utils_pbkdf.c:164
+msgid "Requested PBKDF parallel threads cannot be zero."
+msgstr "Вказана кількість паралельних потоків обробки PBKDF не може бути нульовою."
+
+#: lib/utils_pbkdf.c:184
+msgid "Only PBKDF2 is supported in FIPS mode."
+msgstr "У режимі FIPS передбачено підтримку лише PBKDF2."
+
+#: lib/utils_benchmark.c:175
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr "Тестування PBKDF вимкнено, але кількість ітерацій не встановлено."
+
+#: lib/utils_benchmark.c:194
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "Несумісні параметри PBKDF2 (з використанням алгоритму хешування %s)."
+
+#: lib/utils_benchmark.c:214
+msgid "Not compatible PBKDF options."
+msgstr "Несумісні параметри PBKDF."
+
+#: lib/utils_device_locking.c:101
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "Блокування перервано. Шлях блокування %s/%s є непридатним для користування (не є каталогом або його не вказано)."
+
+#: lib/utils_device_locking.c:118
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "Блокування перервано Шлях блокування %s/%s є непридатним для користування (%s не є каталогом)."
+
+#: lib/utils_wipe.c:154 lib/utils_wipe.c:225 src/utils_reencrypt_luks1.c:734
+#: src/utils_reencrypt_luks1.c:832
+msgid "Cannot seek to device offset."
+msgstr "Не вдалося встановити вказану позицію на пристрої."
+
+#: lib/utils_wipe.c:247
+#, c-format
+msgid "Device wipe error, offset %<PRIu64>."
+msgstr "Помилка витирання пристрою, зсув %<PRIu64>."
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"Не вдалося визначити призначення ключа dm-crypt для пристрою %s.\n"
+"Перевірте, чи передбачено у ядрі підтримку шифрування %s (докладніші дані можна знайти у журналі системи (syslog))."
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "Розмір ключа у режимі XTS має бути рівним 256 або 512 бітів."
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr "Специфікацію шифрування слід вказувати так: [алгоритм]-[режим]-[iv]."
+
+#: lib/luks1/keyencryption.c:97 lib/luks1/keymanage.c:366
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:1132
+#: lib/luks2/luks2_json_metadata.c:1490 lib/luks2/luks2_keyslot.c:714
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "Не вдалося виконати запис на пристрій %s, недостатні права доступу."
+
+#: lib/luks1/keyencryption.c:120
+msgid "Failed to open temporary keystore device."
+msgstr "Не вдалося відкрити пристрій тимчасового сховища ключів."
+
+#: lib/luks1/keyencryption.c:127
+msgid "Failed to access temporary keystore device."
+msgstr "Не вдалося отримати доступ до пристрою тимчасового сховища ключів."
+
+#: lib/luks1/keyencryption.c:200 lib/luks2/luks2_keyslot_luks2.c:62
+#: lib/luks2/luks2_keyslot_luks2.c:80 lib/luks2/luks2_keyslot_reenc.c:192
+msgid "IO error while encrypting keyslot."
+msgstr "Помилка введення-виведення під час шифрування слоту ключів."
+
+#: lib/luks1/keyencryption.c:246 lib/luks1/keymanage.c:369
+#: lib/luks1/keymanage.c:630 lib/luks1/keymanage.c:680 lib/tcrypt/tcrypt.c:679
+#: lib/fvault2/fvault2.c:877 lib/verity/verity.c:80 lib/verity/verity.c:196
+#: lib/verity/verity_hash.c:320 lib/verity/verity_hash.c:329
+#: lib/verity/verity_hash.c:349 lib/verity/verity_fec.c:260
+#: lib/verity/verity_fec.c:272 lib/verity/verity_fec.c:277
+#: lib/luks2/luks2_json_metadata.c:1493 src/utils_reencrypt_luks1.c:121
+#: src/utils_reencrypt_luks1.c:133
+#, c-format
+msgid "Cannot open device %s."
+msgstr "Не вдалося відкрити пристрій %s."
+
+#: lib/luks1/keyencryption.c:257 lib/luks2/luks2_keyslot_luks2.c:139
+msgid "IO error while decrypting keyslot."
+msgstr "Помилка введення-виведення під час розшифрування слоту ключів."
+
+#: lib/luks1/keymanage.c:130
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "Обсяг пристрою %s є надто малим. (LUKS1 потрібно принаймні %<PRIu64> байтів.)"
+
+#: lib/luks1/keymanage.c:151 lib/luks1/keymanage.c:159
+#: lib/luks1/keymanage.c:171 lib/luks1/keymanage.c:182
+#: lib/luks1/keymanage.c:194
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "Слот ключа LUKS %u є некоректним."
+
+#: lib/luks1/keymanage.c:267 lib/luks2/luks2_json_metadata.c:1353
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "Потрібний вам файл резервної копії заголовка, %s, вже існує."
+
+#: lib/luks1/keymanage.c:269 lib/luks2/luks2_json_metadata.c:1355
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "Не вдалося створити файл резервної копії заголовка, %s."
+
+#: lib/luks1/keymanage.c:276 lib/luks2/luks2_json_metadata.c:1362
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "Не вдалося записати файл резервної копії заголовка, %s."
+
+#: lib/luks1/keymanage.c:308 lib/luks2/luks2_json_metadata.c:1399
+msgid "Backup file does not contain valid LUKS header."
+msgstr "Файл резервної копії не містить коректного заголовка LUKS."
+
+#: lib/luks1/keymanage.c:321 lib/luks1/keymanage.c:593
+#: lib/luks2/luks2_json_metadata.c:1420
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "Не вдалося відкрити файл резервної копії заголовка, %s."
+
+#: lib/luks1/keymanage.c:329 lib/luks2/luks2_json_metadata.c:1428
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "Не вдалося прочитати дані з файла резервної копії заголовка, %s."
+
+#: lib/luks1/keymanage.c:339
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "Відступ у даних або розмір ключа на пристрої і у резервній копії є різними. Відновлення неможливе."
+
+#: lib/luks1/keymanage.c:347
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Пристрій %s %s%s"
+
+#: lib/luks1/keymanage.c:348
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "не містить заголовка LUKS. Заміна заголовка може зруйнувати дані, що зберігаються на пристрої."
+
+#: lib/luks1/keymanage.c:349
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "вже містить заголовок LUKS. Заміна заголовка призведе до руйнування вже створених слотів ключів."
+
+#: lib/luks1/keymanage.c:350 lib/luks2/luks2_json_metadata.c:1462
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"ПОПЕРЕДЖЕННЯ: заголовок, що зберігається на пристрої, має інший UUID, ніж заголовок у резервній копії!"
+
+#: lib/luks1/keymanage.c:398
+msgid "Non standard key size, manual repair required."
+msgstr "Нестандартний розмір ключа, слід виправити дані вручну."
+
+#: lib/luks1/keymanage.c:408
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "Нестандартне вирівнювання слотів ключів, слід виправити дані вручну."
+
+#: lib/luks1/keymanage.c:417
+#, c-format
+msgid "Cipher mode repaired (%s -> %s)."
+msgstr "Виправлений режим шифрування (%s -> %s)."
+
+#: lib/luks1/keymanage.c:428
+#, c-format
+msgid "Cipher hash repaired to lowercase (%s)."
+msgstr "Виправлений хеш шифрування малими літерами (%s)."
+
+#: lib/luks1/keymanage.c:430 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:792
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "Підтримки бажаного хешування LUKS, %s, не передбачено."
+
+#: lib/luks1/keymanage.c:444
+msgid "Repairing keyslots."
+msgstr "Виправлення слотів ключів."
+
+#: lib/luks1/keymanage.c:463
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "Слот ключа %i: виправлено відступ (%u -> %u)."
+
+#: lib/luks1/keymanage.c:471
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "Слот ключа %i: виправлено смужки (%u -> %u)."
+
+#: lib/luks1/keymanage.c:480
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "Слот ключа %i: зайвий підпис розділу."
+
+#: lib/luks1/keymanage.c:485
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "Слот ключа %i: дані ініціалізації (сіль) витерто."
+
+#: lib/luks1/keymanage.c:502
+msgid "Writing LUKS header to disk."
+msgstr "Запис заголовка LUKS на диск."
+
+#: lib/luks1/keymanage.c:507
+msgid "Repair failed."
+msgstr "Спроба виправлення зазнала невдачі."
+
+#: lib/luks1/keymanage.c:562
+#, c-format
+msgid "LUKS cipher mode %s is invalid."
+msgstr "Режим шифрування LUKS %s є некоректним."
+
+#: lib/luks1/keymanage.c:567
+#, c-format
+msgid "LUKS hash %s is invalid."
+msgstr "Хеш-сума LUKS %s є некоректною."
+
+#: lib/luks1/keymanage.c:574 src/cryptsetup.c:1281
+msgid "No known problems detected for LUKS header."
+msgstr "У заголовку LUKS не виявлено жодних проблем."
+
+#: lib/luks1/keymanage.c:702
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "Помилка під час оновлення заголовка LUKS на пристрої %s."
+
+#: lib/luks1/keymanage.c:710
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "Помилка під час спроби повторного читання заголовка LUKS після оновлення на пристрої %s."
+
+#: lib/luks1/keymanage.c:786
+msgid "Data offset for LUKS header must be either 0 or higher than header size."
+msgstr "Відступ даних для заголовка LUKS має бути або рівним нулеві, або перевищувати розмір заголовка."
+
+#: lib/luks1/keymanage.c:797 lib/luks1/keymanage.c:866
+#: lib/luks2/luks2_json_format.c:286 lib/luks2/luks2_json_metadata.c:1236
+#: src/utils_reencrypt.c:539
+msgid "Wrong LUKS UUID format provided."
+msgstr "Вказано UUID LUKS у помилковому форматі."
+
+#: lib/luks1/keymanage.c:819
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "Не вдалося створити заголовок LUKS: помилка читання випадкових даних для ініціалізації."
+
+#: lib/luks1/keymanage.c:845
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "Не вдалося створити заголовок LUKS: помилка під час обчислення контрольної суми заголовка (з використанням хешу %s)."
+
+#: lib/luks1/keymanage.c:889
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "Слот ключа %d є активним. Його слід спочатку спорожнити."
+
+#: lib/luks1/keymanage.c:895
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "Ентропія даних слота ключа %d є надто низькою. Маніпуляції з заголовком?"
+
+#: lib/luks1/keymanage.c:931 lib/luks2/luks2_keyslot_luks2.c:270
+msgid "PBKDF2 iteration value overflow."
+msgstr "Переповнення значення ітерації PBKDF2."
+
+#: lib/luks1/keymanage.c:1040
+#, c-format
+msgid "Cannot open keyslot (using hash %s)."
+msgstr "Не вдалося відкрити слот ключа (за допомогою хешу %s)."
+
+#: lib/luks1/keymanage.c:1118
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "Слот ключа %d є некоректним, будь ласка, виберіть слот ключа з номером від 0 до %d."
+
+#: lib/luks1/keymanage.c:1136 lib/luks2/luks2_keyslot.c:718
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "Не вдалося витерти пристрій %s."
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile."
+msgstr "Виявлено файл ключа, підтримки шифрування GPG у якому ще не передбачено."
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Будь ласка, скористайтеся командою gpg --decrypt <ФАЙЛ_КЛЮЧА> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "Виявлено несумісний з loop-AES файл ключа."
+
+#: lib/loopaes/loopaes.c:245
+msgid "Kernel does not support loop-AES compatible mapping."
+msgstr "У ядрі не передбачено підтримки призначення, сумісного з loop-AES."
+
+#: lib/tcrypt/tcrypt.c:508
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "Помилка під час спроби читання файла ключа %s."
+
+#: lib/tcrypt/tcrypt.c:558
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%zu) exceeded."
+msgstr "Перевищено максимальну можливу довжину пароля TCRYPT (%zu)."
+
+#: lib/tcrypt/tcrypt.c:600
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "Засіб створення хешів PBKDF2 за алгоритмом %s недоступний, пропускаємо."
+
+#: lib/tcrypt/tcrypt.c:619 src/cryptsetup.c:1156
+msgid "Required kernel crypto interface not available."
+msgstr "Потрібний для роботи інтерфейс ядра для шифрування недоступний."
+
+#: lib/tcrypt/tcrypt.c:621 src/cryptsetup.c:1158
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "Переконайтеся, що завантажено модуль ядра algif_skcipher."
+
+#: lib/tcrypt/tcrypt.c:762
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "Підтримки активації для розміру сектора %d не передбачено."
+
+#: lib/tcrypt/tcrypt.c:768
+msgid "Kernel does not support activation for this TCRYPT legacy mode."
+msgstr "У ядрі не передбачено підтримки вмикання цього застарілого режиму TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:799
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "Активуємо шифрування системи за допомогою TCRYPT для розділу %s."
+
+#: lib/tcrypt/tcrypt.c:882
+msgid "Kernel does not support TCRYPT compatible mapping."
+msgstr "У ядрі не передбачено підтримки призначення, сумісного з TCRYPT."
+
+#: lib/tcrypt/tcrypt.c:1095
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Підтримки цієї дії без завантаження заголовка TCRYPT."
+
+#: lib/bitlk/bitlk.c:278
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing supported Volume Master Key."
+msgstr "Під час обробки підтримуваного основного ключа тому виявлено неочікуваний тип запису метаданих «%u»."
+
+#: lib/bitlk/bitlk.c:337
+msgid "Invalid string found when parsing Volume Master Key."
+msgstr "Під час обробки основного ключа тому виявлено некоректний рядок."
+
+#: lib/bitlk/bitlk.c:341
+#, c-format
+msgid "Unexpected string ('%s') found when parsing supported Volume Master Key."
+msgstr "Під час обробки підтримуваного основного ключа тому виявлено неочікуваний рядок («%s»)."
+
+#: lib/bitlk/bitlk.c:358
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing supported Volume Master Key."
+msgstr "Під час обробки підтримуваного основного ключа тому виявлено неочікуване значення запису метаданих «%u»."
+
+#: lib/bitlk/bitlk.c:460
+msgid "BITLK version 1 is currently not supported."
+msgstr "Підтримки BITLK версії 1 у поточній версії не передбачено."
+
+#: lib/bitlk/bitlk.c:466
+msgid "Invalid or unknown boot signature for BITLK device."
+msgstr "Некоректний або невідомий підпис завантаження для пристрою BITLK."
+
+#: lib/bitlk/bitlk.c:478
+#, c-format
+msgid "Unsupported sector size %<PRIu16>."
+msgstr "Непідтримуваний розмір сектора %<PRIu16>."
+
+#: lib/bitlk/bitlk.c:486
+#, c-format
+msgid "Failed to read BITLK header from %s."
+msgstr "Не вдалося прочитати заголовок BITLK з %s."
+
+#: lib/bitlk/bitlk.c:511
+#, c-format
+msgid "Failed to read BITLK FVE metadata from %s."
+msgstr "Не вдалося прочитати метадані FVE BITLK з %s."
+
+#: lib/bitlk/bitlk.c:562
+msgid "Unknown or unsupported encryption type."
+msgstr "Невідомий або непідтримуваний тип шифрування."
+
+#: lib/bitlk/bitlk.c:602
+#, c-format
+msgid "Failed to read BITLK metadata entries from %s."
+msgstr "Не вдалося прочитати записи метаданих BITLK з %s."
+
+#: lib/bitlk/bitlk.c:719
+msgid "Failed to convert BITLK volume description"
+msgstr "Не вдалося перетворити опис тому BITLK"
+
+#: lib/bitlk/bitlk.c:882
+#, c-format
+msgid "Unexpected metadata entry type '%u' found when parsing external key."
+msgstr "Під час обробки зовнішнього ключа виявлено неочікуваний тип запису метаданих «%u»."
+
+#: lib/bitlk/bitlk.c:905
+#, c-format
+msgid "BEK file GUID '%s' does not match GUID of the volume."
+msgstr "Файл GUID BEK «%s» не відповідає GUID тому."
+
+#: lib/bitlk/bitlk.c:909
+#, c-format
+msgid "Unexpected metadata entry value '%u' found when parsing external key."
+msgstr "Під час обробки зовнішнього ключа виявлено неочікуване значення запису метаданих «%u»."
+
+#: lib/bitlk/bitlk.c:948
+#, c-format
+msgid "Unsupported BEK metadata version %<PRIu32>"
+msgstr "Непідтримувана версія метаданих BEK, %<PRIu32>"
+
+#: lib/bitlk/bitlk.c:953
+#, c-format
+msgid "Unexpected BEK metadata size %<PRIu32> does not match BEK file length"
+msgstr "Неочікуваний розмір метаданих BEK, %<PRIu32>, не відповідає довжині файла BEK"
+
+#: lib/bitlk/bitlk.c:979
+msgid "Unexpected metadata entry found when parsing startup key."
+msgstr "Під час обробки ключа запуску виявлено неочікуваний запис метаданих."
+
+#: lib/bitlk/bitlk.c:1075
+msgid "This operation is not supported."
+msgstr "Підтримки цієї дії не передбачено."
+
+#: lib/bitlk/bitlk.c:1083
+msgid "Unexpected key data size."
+msgstr "Неочікуваний розмір даних ключа."
+
+#: lib/bitlk/bitlk.c:1209
+msgid "This BITLK device is in an unsupported state and cannot be activated."
+msgstr "Цей пристрій BITLK перебуває у непідтримуваному стані — його неможливо активувати."
+
+#: lib/bitlk/bitlk.c:1214
+#, c-format
+msgid "BITLK devices with type '%s' cannot be activated."
+msgstr "Пристрої BITLK типу «%s» неможливо активувати."
+
+#: lib/bitlk/bitlk.c:1221
+msgid "Activation of partially decrypted BITLK device is not supported."
+msgstr "Активації частково розшифрованого пристрою BITLK не передбачено."
+
+#: lib/bitlk/bitlk.c:1262
+#, c-format
+msgid "WARNING: BitLocker volume size %<PRIu64> does not match the underlying device size %<PRIu64>"
+msgstr "УВАГА: розмір тому BitLocker %<PRIu64> не відповідає розміру базового пристрою %<PRIu64>"
+
+#: lib/bitlk/bitlk.c:1389
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK IV."
+msgstr "Не вдалося активувати пристрій — у dm-crypt ядра немає підтримки BITLK IV."
+
+#: lib/bitlk/bitlk.c:1393
+msgid "Cannot activate device, kernel dm-crypt is missing support for BITLK Elephant diffuser."
+msgstr "Не вдалося активувати пристрій — у dm-crypt ядра немає підтримки дифузера Elephant BITLK."
+
+#: lib/bitlk/bitlk.c:1397
+msgid "Cannot activate device, kernel dm-crypt is missing support for large sector size."
+msgstr "Не вдалося активувати пристрій — у dm-crypt ядра немає підтримки великого розміру секторів."
+
+#: lib/bitlk/bitlk.c:1401
+msgid "Cannot activate device, kernel dm-zero module is missing."
+msgstr "Не вдалося активувати пристрій — немає модуля ядра dm-zero."
+
+#: lib/fvault2/fvault2.c:542
+#, c-format
+msgid "Could not read %u bytes of volume header."
+msgstr "Не вдалося прочитати %u байтів заголовка тому."
+
+#: lib/fvault2/fvault2.c:554
+#, c-format
+msgid "Unsupported FVAULT2 version %<PRIu16>."
+msgstr "Непідтримувана версія FVAULT2 %<PRIu16>."
+
+#: lib/verity/verity.c:68 lib/verity/verity.c:182
+#, c-format
+msgid "Verity device %s does not use on-disk header."
+msgstr "На пристрої VERITY %s не використовується вбудований заголовок."
+
+#: lib/verity/verity.c:96
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "Непідтримувана версія VERITY, %d."
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted."
+msgstr "Пошкоджено заголовок VERITY."
+
+#: lib/verity/verity.c:176
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "На пристрої %s вказано UUID VERITY у помилковому форматі."
+
+#: lib/verity/verity.c:220
+#, c-format
+msgid "Error during update of verity header on device %s."
+msgstr "Помилка під час оновлення заголовка verity на пристрої %s."
+
+#: lib/verity/verity.c:278
+msgid "Root hash signature verification is not supported."
+msgstr "Підтримки перевірки підпису кореневого хешу не передбачено."
+
+#: lib/verity/verity.c:290
+msgid "Errors cannot be repaired with FEC device."
+msgstr "Помилки не може бути виправлено за допомогою пристрою FEC."
+
+#: lib/verity/verity.c:292
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr "За допомогою пристрою FEC виявлено %u придатних до виправлення помилок."
+
+#: lib/verity/verity.c:335
+msgid "Kernel does not support dm-verity mapping."
+msgstr "У ядрі не передбачено підтримки прив'язки dm-verity."
+
+#: lib/verity/verity.c:339
+msgid "Kernel does not support dm-verity signature option."
+msgstr "У ядрі не передбачено підтримки параметра підпису dm-verity."
+
+#: lib/verity/verity.c:350
+msgid "Verity device detected corruption after activation."
+msgstr "Виявлено пошкодження даних на пристрої перевірки після активації."
+
+#: lib/verity/verity_hash.c:66
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "Резервну область не занулено у позиції %<PRIu64>."
+
+#: lib/verity/verity_hash.c:167 lib/verity/verity_hash.c:300
+#: lib/verity/verity_hash.c:311
+msgid "Device offset overflow."
+msgstr "Переповнення відступу на пристрої."
+
+#: lib/verity/verity_hash.c:218
+#, c-format
+msgid "Verification failed at position %<PRIu64>."
+msgstr "Помилка під час перевірки за позицією %<PRIu64>."
+
+#: lib/verity/verity_hash.c:307
+msgid "Hash area overflow."
+msgstr "Переповнення області хешу."
+
+#: lib/verity/verity_hash.c:380
+msgid "Verification of data area failed."
+msgstr "Не вдалося перевірити область даних."
+
+#: lib/verity/verity_hash.c:385
+msgid "Verification of root hash failed."
+msgstr "Не вдалося перевірити кореневий хеш."
+
+#: lib/verity/verity_hash.c:391
+msgid "Input/output error while creating hash area."
+msgstr "Під час створення області хешу сталася помилка введення або виведення даних."
+
+#: lib/verity/verity_hash.c:393
+msgid "Creation of hash area failed."
+msgstr "Не вдалося створити область хешу."
+
+#: lib/verity/verity_hash.c:428
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "Попередження: ядро не зможе задіяти пристрій, якщо розмір блоку перевищуватиме розмір сторінки (%u)."
+
+#: lib/verity/verity_fec.c:131
+msgid "Failed to allocate RS context."
+msgstr "Не вдалося розмістити контекст RS."
+
+#: lib/verity/verity_fec.c:149
+msgid "Failed to allocate buffer."
+msgstr "Не вдалося розмістити у пам'яті буфер."
+
+#: lib/verity/verity_fec.c:159
+#, c-format
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "Не вдалося прочитати блок RS %<PRIu64>, байт %d."
+
+#: lib/verity/verity_fec.c:172
+#, c-format
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "Не вдалося прочитати парність для блоку RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:180
+#, c-format
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "Не вдалося відновити парність для блоку %<PRIu64>."
+
+#: lib/verity/verity_fec.c:192
+#, c-format
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "Не вдалося прочитати парність для блоку RS %<PRIu64>."
+
+#: lib/verity/verity_fec.c:208
+msgid "Block sizes must match for FEC."
+msgstr "Розміри блоків для FEC мають бути однаковими."
+
+#: lib/verity/verity_fec.c:214
+msgid "Invalid number of parity bytes."
+msgstr "Некоректна кількість байтів парності."
+
+#: lib/verity/verity_fec.c:248
+msgid "Invalid FEC segment length."
+msgstr "Некоректна довжина сегмента FEC."
+
+#: lib/verity/verity_fec.c:316
+#, c-format
+msgid "Failed to determine size for device %s."
+msgstr "Не вдалося визначити розмір для пристрою %s."
+
+#: lib/integrity/integrity.c:57
+#, c-format
+msgid "Incompatible kernel dm-integrity metadata (version %u) detected on %s."
+msgstr "Виявлено несумісні метадані dm-integrity ядра (версія %u) у %s."
+
+#: lib/integrity/integrity.c:277 lib/integrity/integrity.c:379
+msgid "Kernel does not support dm-integrity mapping."
+msgstr "У ядрі не передбачено підтримки прив'язки dm-integrity."
+
+#: lib/integrity/integrity.c:283
+msgid "Kernel does not support dm-integrity fixed metadata alignment."
+msgstr "У ядрі не передбачено підтримки вирівнювання фіксованих метаданих dm-integrity."
+
+#: lib/integrity/integrity.c:292
+msgid "Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."
+msgstr "Ядром відмовлено у активації небезпечного параметра повторного обчислення (див. застарілі параметри активації, щоб скористатися обчисленням попри це)."
+
+#: lib/luks2/luks2_disk_metadata.c:391 lib/luks2/luks2_json_metadata.c:1159
+#: lib/luks2/luks2_json_metadata.c:1482
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "Не вдалося отримати блокування запису на пристрої %s."
+
+#: lib/luks2/luks2_disk_metadata.c:400
+msgid "Detected attempt for concurrent LUKS2 metadata update. Aborting operation."
+msgstr "Виявлено спробу конкурентного оновлення метаданих LUKS2. Перериваємо виконання дії."
+
+#: lib/luks2/luks2_disk_metadata.c:699 lib/luks2/luks2_disk_metadata.c:720
+msgid ""
+"Device contains ambiguous signatures, cannot auto-recover LUKS2.\n"
+"Please run \"cryptsetup repair\" for recovery."
+msgstr ""
+"Пристрій містить неоднозначні підписи. Автоматичне відновлення LUKS2 неможливе.\n"
+"Будь ласка, запустіть «cryptsetup repair» для відновлення."
+
+#: lib/luks2/luks2_json_format.c:229
+msgid "Requested data offset is too small."
+msgstr "Вказаний відступ у даних є надто малим."
+
+#: lib/luks2/luks2_json_format.c:274
+#, c-format
+msgid "WARNING: keyslots area (%<PRIu64> bytes) is very small, available LUKS2 keyslot count is very limited.\n"
+msgstr "Увага: область слоту ключів є надто малою (%<PRIu64> байтів), доступна кількість слотів ключів LUKS2 буде дуже обмеженою.\n"
+
+#: lib/luks2/luks2_json_metadata.c:1146 lib/luks2/luks2_json_metadata.c:1328
+#: lib/luks2/luks2_json_metadata.c:1388 lib/luks2/luks2_keyslot_luks2.c:94
+#: lib/luks2/luks2_keyslot_luks2.c:116
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "Не вдалося отримати блокування читання на пристрої %s."
+
+#: lib/luks2/luks2_json_metadata.c:1405
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr "У резервній копії %s виявлено заборонені вимоги щодо LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:1446
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "Зсуви даних на пристрої і на резервній копії різняться, не вдалося відновити."
+
+#: lib/luks2/luks2_json_metadata.c:1452
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "Двійкові заголовки із розмірами областей слотів ключів на пристрої і у резервній копії різняться, не вдалося відновити копію."
+
+#: lib/luks2/luks2_json_metadata.c:1459
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "Пристрій %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1460
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "не містить заголовка LUKS2. Заміна заголовка може зруйнувати дані, що зберігаються на пристрої."
+
+#: lib/luks2/luks2_json_metadata.c:1461
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "вже містить заголовок LUKS2. Заміна заголовка призведе до руйнування вже створених слотів ключів."
+
+#: lib/luks2/luks2_json_metadata.c:1463
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+"\n"
+"ПОПЕРЕДЖЕННЯ: виявлено невідомі вимоги LUKS2 у справжньому заголовку пристрою!\n"
+"Заміна заголовка резервною копією може пошкодити дані на пристрої!"
+
+#: lib/luks2/luks2_json_metadata.c:1465
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+"\n"
+"ПОПЕРЕДЖЕННЯ: на пристрої виявлено дані незавершеного повторного шифрування!\n"
+"Заміна заголовка заголовком із резервної копії може пошкодити дані."
+
+#: lib/luks2/luks2_json_metadata.c:1562
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "Проігноровано невідомий прапорець %s."
+
+#: lib/luks2/luks2_json_metadata.c:2470 lib/luks2/luks2_reencrypt.c:2061
+#, c-format
+msgid "Missing key for dm-crypt segment %u"
+msgstr "Не вистачає ключа для сегмента dm-crypt %u"
+
+#: lib/luks2/luks2_json_metadata.c:2482 lib/luks2/luks2_reencrypt.c:2075
+msgid "Failed to set dm-crypt segment."
+msgstr "Не вдалося встановити сегмент dm-crypt."
+
+#: lib/luks2/luks2_json_metadata.c:2488 lib/luks2/luks2_reencrypt.c:2081
+msgid "Failed to set dm-linear segment."
+msgstr "Не вдалося встановити сегмент dm-linear."
+
+#: lib/luks2/luks2_json_metadata.c:2615
+msgid "Unsupported device integrity configuration."
+msgstr "Непідтримувані налаштування цілісності даних на пристрої."
+
+#: lib/luks2/luks2_json_metadata.c:2701
+msgid "Reencryption in-progress. Cannot deactivate device."
+msgstr "Виконуємо повторне шифрування. Не можна деактивувати пристрій."
+
+#: lib/luks2/luks2_json_metadata.c:2712 lib/luks2/luks2_reencrypt.c:4082
+#, c-format
+msgid "Failed to replace suspended device %s with dm-error target."
+msgstr "Не вдалося замінити пристрій %s, роботу якого призупинено, ціллю dm-error."
+
+#: lib/luks2/luks2_json_metadata.c:2792
+msgid "Failed to read LUKS2 requirements."
+msgstr "Не вдалося прочитати вимоги LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2799
+msgid "Unmet LUKS2 requirements detected."
+msgstr "Виявлено невідповідність вимог LUKS2."
+
+#: lib/luks2/luks2_json_metadata.c:2807
+msgid "Operation incompatible with device marked for legacy reencryption. Aborting."
+msgstr "Дія є несумісною із пристроєм, який позначено для перешифрування застарілого варіанта. Перериваємо дію."
+
+#: lib/luks2/luks2_json_metadata.c:2809
+msgid "Operation incompatible with device marked for LUKS2 reencryption. Aborting."
+msgstr "Дія є несумісною із пристроєм, який позначено для перешифрування LUKS2. Перериваємо дію."
+
+#: lib/luks2/luks2_keyslot.c:563 lib/luks2/luks2_keyslot.c:600
+msgid "Not enough available memory to open a keyslot."
+msgstr "Недостатньо пам'яті для відкриття слоту ключів."
+
+#: lib/luks2/luks2_keyslot.c:565 lib/luks2/luks2_keyslot.c:602
+msgid "Keyslot open failed."
+msgstr "Не вдалося відкрити слот ключів."
+
+#: lib/luks2/luks2_keyslot_luks2.c:55 lib/luks2/luks2_keyslot_luks2.c:110
+#, c-format
+msgid "Cannot use %s-%s cipher for keyslot encryption."
+msgstr "Не можна використовувати шифрування %s-%s для слотів ключів."
+
+#: lib/luks2/luks2_keyslot_luks2.c:285 lib/luks2/luks2_keyslot_luks2.c:394
+#: lib/luks2/luks2_keyslot_reenc.c:443 lib/luks2/luks2_reencrypt.c:2668
+#, c-format
+msgid "Hash algorithm %s is not available."
+msgstr "Алгоритм хешування %s є недоступним."
+
+#: lib/luks2/luks2_keyslot_luks2.c:510
+msgid "No space for new keyslot."
+msgstr "Немає простору для нового слоту ключа."
+
+#: lib/luks2/luks2_keyslot_reenc.c:593
+msgid "Invalid reencryption resilience mode change requested."
+msgstr "Отримано запит щодо некоректної зміни режиму стійкості для повторного шифрування."
+
+#: lib/luks2/luks2_keyslot_reenc.c:714
+#, c-format
+msgid "Can not update resilience type. New type only provides %<PRIu64> bytes, required space is: %<PRIu64> bytes."
+msgstr "Не вдалося оновити тип стійкості. Новим типом передбачено %<PRIu64> байтів, потрібне місце: %<PRIu64> байтів."
+
+#: lib/luks2/luks2_keyslot_reenc.c:724
+msgid "Failed to refresh reencryption verification digest."
+msgstr "Не вдалося освіжити контрольні суми для перевірки для повторного шифрування."
+
+#: lib/luks2/luks2_luks1_convert.c:512
+#, c-format
+msgid "Cannot check status of device with uuid: %s."
+msgstr "Не вдалося перевірити стан пристрою з uuid %s."
+
+#: lib/luks2/luks2_luks1_convert.c:538
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr "Не вдалося перетворити заголовок з додатковими метаданими LUKSMETA."
+
+#: lib/luks2/luks2_luks1_convert.c:569 lib/luks2/luks2_reencrypt.c:3740
+#, c-format
+msgid "Unable to use cipher specification %s-%s for LUKS2."
+msgstr "Не вдалося використати специфікацію шифрування %s-%s для LUKS2."
+
+#: lib/luks2/luks2_luks1_convert.c:584
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "Не вдалося пересунути область слотів ключів. Недостатньо місця."
+
+#: lib/luks2/luks2_luks1_convert.c:619
+msgid "Cannot convert to LUKS2 format - invalid metadata."
+msgstr "Не вдалося перетворити до формату LUKS2 - некоректні метадані."
+
+#: lib/luks2/luks2_luks1_convert.c:636
+msgid "Unable to move keyslot area. LUKS2 keyslots area too small."
+msgstr "Не вдалося пересунути область слотів ключів. Область слотів ключів LUKS2 є надто малою."
+
+#: lib/luks2/luks2_luks1_convert.c:642 lib/luks2/luks2_luks1_convert.c:936
+msgid "Unable to move keyslot area."
+msgstr "Не вдалося пересунути область слотів ключів."
+
+#: lib/luks2/luks2_luks1_convert.c:732
+msgid "Cannot convert to LUKS1 format - default segment encryption sector size is not 512 bytes."
+msgstr "Не вдалося перетворити на формат LUKS1 — типовий розмір сектору шифрування сегмента не дорівнює 512 байтам."
+
+#: lib/luks2/luks2_luks1_convert.c:740
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "Не вдалося перетворити до формату LUKS1 — контрольні суми слотів ключів не сумісні з LUKS1."
+
+#: lib/luks2/luks2_luks1_convert.c:752
+#, c-format
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "Не вдалося перетворити до формату LUKS1 — на пристрої використовується загорнуте шифрування ключів %s."
+
+#: lib/luks2/luks2_luks1_convert.c:757
+msgid "Cannot convert to LUKS1 format - device uses more segments."
+msgstr "Не вдалося перетворити до формату LUKS1 — на пристрої використовується більше сегментів."
+
+#: lib/luks2/luks2_luks1_convert.c:765
+#, c-format
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "Не вдалося перетворити до формату LUKS1 - заголовок LUKS2 містить %u жетонів."
+
+#: lib/luks2/luks2_luks1_convert.c:779
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "Не вдалося перетворити до формату LUKS1 - слот ключа %u перебуває у некоректному стані."
+
+#: lib/luks2/luks2_luks1_convert.c:784
+#, c-format
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "Не вдалося перетворити до формату LUKS1 — слот %u (перевищує максимальну кількість слотів) усе ще є активним."
+
+#: lib/luks2/luks2_luks1_convert.c:789
+#, c-format
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "не вдалося перетворити до формату LUKS1 — слот ключів %u є несумісним з LUKS1."
+
+#: lib/luks2/luks2_reencrypt.c:1152
+#, c-format
+msgid "Hotzone size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Розмір «гарячої» ділянки має бути кратним до обчисленого вирівнювання ділянки (%zu байтів)."
+
+#: lib/luks2/luks2_reencrypt.c:1157
+#, c-format
+msgid "Device size must be multiple of calculated zone alignment (%zu bytes)."
+msgstr "Розмір пристрою має бути кратним до обчисленого вирівнювання ділянки (%zu байтів)."
+
+#: lib/luks2/luks2_reencrypt.c:1364 lib/luks2/luks2_reencrypt.c:1551
+#: lib/luks2/luks2_reencrypt.c:1634 lib/luks2/luks2_reencrypt.c:1676
+#: lib/luks2/luks2_reencrypt.c:3877
+msgid "Failed to initialize old segment storage wrapper."
+msgstr "Не вдалося ініціалізувати обгортку старого сховища сегментів."
+
+#: lib/luks2/luks2_reencrypt.c:1378 lib/luks2/luks2_reencrypt.c:1529
+msgid "Failed to initialize new segment storage wrapper."
+msgstr "Не вдалося ініціалізувати обгортку нового сховища сегментів."
+
+#: lib/luks2/luks2_reencrypt.c:1505 lib/luks2/luks2_reencrypt.c:3889
+msgid "Failed to initialize hotzone protection."
+msgstr "Не вдалося ініціалізувати захист «гарячої» зони"
+
+#: lib/luks2/luks2_reencrypt.c:1578
+msgid "Failed to read checksums for current hotzone."
+msgstr "Не вдалося прочитати контрольні суми для поточної «гарячої» ділянки."
+
+#: lib/luks2/luks2_reencrypt.c:1585 lib/luks2/luks2_reencrypt.c:3903
+#, c-format
+msgid "Failed to read hotzone area starting at %<PRIu64>."
+msgstr "Не вдалося прочитати «гарячу» ділянку, починаючи з %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:1604
+#, c-format
+msgid "Failed to decrypt sector %zu."
+msgstr "Не вдалося розшифрувати сектор %zu."
+
+#: lib/luks2/luks2_reencrypt.c:1610
+#, c-format
+msgid "Failed to recover sector %zu."
+msgstr "Не вдалося відновити сектор %zu."
+
+#: lib/luks2/luks2_reencrypt.c:2174
+#, c-format
+msgid "Source and target device sizes don't match. Source %<PRIu64>, target: %<PRIu64>."
+msgstr "Розміри пристроїв джерела та призначення не збігаються. Розмір джерела — %<PRIu64>, розмір призначення — %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2272
+#, c-format
+msgid "Failed to activate hotzone device %s."
+msgstr "Не вдалося задіяти пристрій «гарячої» ділянки %s."
+
+#: lib/luks2/luks2_reencrypt.c:2289
+#, c-format
+msgid "Failed to activate overlay device %s with actual origin table."
+msgstr "Не вдалося задіяти пристрій-накладку %s зі справжньою таблицею походження."
+
+#: lib/luks2/luks2_reencrypt.c:2296
+#, c-format
+msgid "Failed to load new mapping for device %s."
+msgstr "Не вдалося завантажити нову прив'язку для пристрою %s."
+
+#: lib/luks2/luks2_reencrypt.c:2367
+msgid "Failed to refresh reencryption devices stack."
+msgstr "Не вдалося освіжити тек пристрої для повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:2550
+msgid "Failed to set new keyslots area size."
+msgstr "Не вдалося встановити розмір області нових слотів ключів."
+
+#: lib/luks2/luks2_reencrypt.c:2686
+#, c-format
+msgid "Data shift value is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Значення зміщення даних не вирівняно до розміру сектора для шифрування (%<PRIu32> байтів)."
+
+#: lib/luks2/luks2_reencrypt.c:2723 src/utils_reencrypt.c:189
+#, c-format
+msgid "Unsupported resilience mode %s"
+msgstr "Непідтримуваний режим стійкості %s"
+
+#: lib/luks2/luks2_reencrypt.c:2760
+msgid "Moved segment size can not be greater than data shift value."
+msgstr "Розмір пересунутого сегмента не може перевищувати значення зсуву даних."
+
+#: lib/luks2/luks2_reencrypt.c:2802
+msgid "Invalid reencryption resilience parameters."
+msgstr "Некоректні параметри стійкості для повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:2824
+#, c-format
+msgid "Moved segment too large. Requested size %<PRIu64>, available space for: %<PRIu64>."
+msgstr "Пересунутий сегмент є надто великим. Потрібний розмір %<PRIu64>, доступне місце: %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:2911
+msgid "Failed to clear table."
+msgstr "Не вдалося очистити таблицю."
+
+#: lib/luks2/luks2_reencrypt.c:2997
+msgid "Reduced data size is larger than real device size."
+msgstr "Зменшений розмір даних перевищує справжній розмір пристрою."
+
+#: lib/luks2/luks2_reencrypt.c:3004
+#, c-format
+msgid "Data device is not aligned to encryption sector size (%<PRIu32> bytes)."
+msgstr "Пристрій зберігання даних не вирівняно до розміру сектора для шифрування (%<PRIu32> байтів)."
+
+#: lib/luks2/luks2_reencrypt.c:3038
+#, c-format
+msgid "Data shift (%<PRIu64> sectors) is less than future data offset (%<PRIu64> sectors)."
+msgstr "Зміщення даних (%<PRIu64> секторів) є меншим за майбутній зсув даних (%<PRIu64> секторів)."
+
+#: lib/luks2/luks2_reencrypt.c:3045 lib/luks2/luks2_reencrypt.c:3533
+#: lib/luks2/luks2_reencrypt.c:3554
+#, c-format
+msgid "Failed to open %s in exclusive mode (already mapped or mounted)."
+msgstr "Не вдалося відкрити %s в ексклюзивному режимі (вже пов'язано або змонтовано)."
+
+#: lib/luks2/luks2_reencrypt.c:3234
+msgid "Device not marked for LUKS2 reencryption."
+msgstr "Пристрій не позначено для повторного шифрування LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3251 lib/luks2/luks2_reencrypt.c:4206
+msgid "Failed to load LUKS2 reencryption context."
+msgstr "Не вдалося завантажити контекст повторного шифрування LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:3331
+msgid "Failed to get reencryption state."
+msgstr "Не вдалося отримати стан повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3335 lib/luks2/luks2_reencrypt.c:3649
+msgid "Device is not in reencryption."
+msgstr "Пристрій не перебуває у повторному шифруванні."
+
+#: lib/luks2/luks2_reencrypt.c:3342 lib/luks2/luks2_reencrypt.c:3656
+msgid "Reencryption process is already running."
+msgstr "Процес повторного шифрування вже виконується."
+
+#: lib/luks2/luks2_reencrypt.c:3344 lib/luks2/luks2_reencrypt.c:3658
+msgid "Failed to acquire reencryption lock."
+msgstr "Не вдалося створити блокування для повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3362
+msgid "Cannot proceed with reencryption. Run reencryption recovery first."
+msgstr "Продовження повторного шифрування неможливе. Спочатку слід виконати відновлення повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3497
+msgid "Active device size and requested reencryption size don't match."
+msgstr "Не збігаються розмір активного пристрою і запитаний розмір повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3511
+msgid "Illegal device size requested in reencryption parameters."
+msgstr "У параметрах повторного шифрування вказано некоректний розмір пристрою."
+
+#: lib/luks2/luks2_reencrypt.c:3588
+msgid "Reencryption in-progress. Cannot perform recovery."
+msgstr "Виконується повторне шифрування. Неможливо виконати відновлення."
+
+#: lib/luks2/luks2_reencrypt.c:3757
+msgid "LUKS2 reencryption already initialized in metadata."
+msgstr "Повторне шифрування LUKS2 вже ініційовано у метаданих."
+
+#: lib/luks2/luks2_reencrypt.c:3764
+msgid "Failed to initialize LUKS2 reencryption in metadata."
+msgstr "Не вдалося ініціалізувати повторне шифрування LUKS2 лише у метаданих."
+
+#: lib/luks2/luks2_reencrypt.c:3859
+msgid "Failed to set device segments for next reencryption hotzone."
+msgstr "Не вдалося встановити сегменти пристрою для наступної «гарячої» ділянки повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3911
+msgid "Failed to write reencryption resilience metadata."
+msgstr "Не вдалося записати метадані стійкості для повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3918
+msgid "Decryption failed."
+msgstr "Помилка розшифрування."
+
+#: lib/luks2/luks2_reencrypt.c:3923
+#, c-format
+msgid "Failed to write hotzone area starting at %<PRIu64>."
+msgstr "Не вдалося записати «гарячу» ділянку, починаючи з %<PRIu64>."
+
+#: lib/luks2/luks2_reencrypt.c:3928
+msgid "Failed to sync data."
+msgstr "Не вдалося синхронізувати дані."
+
+#: lib/luks2/luks2_reencrypt.c:3936
+msgid "Failed to update metadata after current reencryption hotzone completed."
+msgstr "Не вдалося оновити метадані після завершення обробки поточної «гарячої» зони повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:4025
+msgid "Failed to write LUKS2 metadata."
+msgstr "Не вдалося записати метадані LUKS2."
+
+#: lib/luks2/luks2_reencrypt.c:4048
+msgid "Failed to wipe unused data device area."
+msgstr "Не вдалося витерти область невикористаних даних пристрою."
+
+#: lib/luks2/luks2_reencrypt.c:4054
+#, c-format
+msgid "Failed to remove unused (unbound) keyslot %d."
+msgstr "Не вдалося вилучити невикористаний (непов'язаний) слот ключа %d."
+
+#: lib/luks2/luks2_reencrypt.c:4064
+msgid "Failed to remove reencryption keyslot."
+msgstr "Не вдалося вилучити слот ключа для повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:4074
+#, c-format
+msgid "Fatal error while reencrypting chunk starting at %<PRIu64>, %<PRIu64> sectors long."
+msgstr "Критична помилка під час повторного шифрування фрагмента, починаючи з %<PRIu64>, довжиною у %<PRIu64> секторів."
+
+#: lib/luks2/luks2_reencrypt.c:4078
+msgid "Online reencryption failed."
+msgstr "Не вдалося виконати інтерактивне повторне шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:4083
+msgid "Do not resume the device unless replaced with error target manually."
+msgstr "Не відновлюйте пристрій, якщо не заміните вручну пристрій призначення для помилок."
+
+#: lib/luks2/luks2_reencrypt.c:4137
+msgid "Cannot proceed with reencryption. Unexpected reencryption status."
+msgstr "Не вдалося виконати повторне шифрування. Неочікуваний стан засобу повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:4143
+msgid "Missing or invalid reencrypt context."
+msgstr "Не вказано контекст повторного шифрування або вказано некоректний контекст."
+
+#: lib/luks2/luks2_reencrypt.c:4150
+msgid "Failed to initialize reencryption device stack."
+msgstr "Не вдалося ініціалізувати стос пристроїв повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt.c:4172 lib/luks2/luks2_reencrypt.c:4219
+msgid "Failed to update reencryption context."
+msgstr "Не вдалося оновити контекст повторного шифрування."
+
+#: lib/luks2/luks2_reencrypt_digest.c:405
+msgid "Reencryption metadata is invalid."
+msgstr "Метадані повторного шифрування є некоректними."
+
+#: src/cryptsetup.c:85
+msgid "Keyslot encryption parameters can be set only for LUKS2 device."
+msgstr "Параметри шифрування слоту ключів можна встановлювати лише для пристроїв LUKS2."
+
+#: src/cryptsetup.c:108 src/cryptsetup.c:1901
+#, c-format
+msgid "Enter token PIN: "
+msgstr "Введіть пінкод жетона: "
+
+#: src/cryptsetup.c:110 src/cryptsetup.c:1903
+#, c-format
+msgid "Enter token %d PIN: "
+msgstr "Введіть пінкод жетона %d: "
+
+#: src/cryptsetup.c:159 src/cryptsetup.c:1103 src/cryptsetup.c:1430
+#: src/utils_reencrypt.c:1122 src/utils_reencrypt_luks1.c:517
+#: src/utils_reencrypt_luks1.c:580
+msgid "No known cipher specification pattern detected."
+msgstr "Не виявлено жодного відомого зразка специфікації шифрування."
+
+#: src/cryptsetup.c:167
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "Попередження: параметр --hash у простому режимі із вказаним файлом ключа ігнорується.\n"
+
+#: src/cryptsetup.c:175
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "Попередження: параметр --keyfile-size проігноровано, розмір прочитаних даних збігається із розміром ключа шифрування.\n"
+
+#: src/cryptsetup.c:215
+#, c-format
+msgid "Detected device signature(s) on %s. Proceeding further may damage existing data."
+msgstr "На %s виявлено підписи пристроїв. Подальша обробка може пошкодити наявні дані."
+
+#: src/cryptsetup.c:221 src/cryptsetup.c:1177 src/cryptsetup.c:1225
+#: src/cryptsetup.c:1291 src/cryptsetup.c:1407 src/cryptsetup.c:1480
+#: src/cryptsetup.c:2266 src/integritysetup.c:187 src/utils_reencrypt.c:138
+#: src/utils_reencrypt.c:314 src/utils_reencrypt.c:749
+msgid "Operation aborted.\n"
+msgstr "Дію перервано.\n"
+
+#: src/cryptsetup.c:294
+msgid "Option --key-file is required."
+msgstr "Слід вказати параметр --key-file."
+
+#: src/cryptsetup.c:345
+msgid "Enter VeraCrypt PIM: "
+msgstr "Введіть PIM VeraCrypt: "
+
+#: src/cryptsetup.c:354
+msgid "Invalid PIM value: parse error."
+msgstr "Некоректне значення PIM: помилка обробки."
+
+#: src/cryptsetup.c:357
+msgid "Invalid PIM value: 0."
+msgstr "Некоректне значення PIM: 0."
+
+#: src/cryptsetup.c:360
+msgid "Invalid PIM value: outside of range."
+msgstr "Некоректне значення PIM: поза межами діапазону."
+
+#: src/cryptsetup.c:383
+msgid "No device header detected with this passphrase."
+msgstr "Для цього пароля не виявлено заголовка пристрою."
+
+#: src/cryptsetup.c:456 src/cryptsetup.c:632
+#, c-format
+msgid "Device %s is not a valid BITLK device."
+msgstr "Пристрій %s не є коректним пристроєм BITLK."
+
+#: src/cryptsetup.c:464
+msgid "Cannot determine volume key size for BITLK, please use --key-size option."
+msgstr "Неможливо визначити розмір ключа тому для BITLK. Будь ласка, скористайтеся параметром --key-size."
+
+#: src/cryptsetup.c:506
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Дамп заголовка з ключем тому є конфіденційними даними,\n"
+"за допомогою яких можна отримати доступ до шифрованого розділу\n"
+"без пароля. Цей дамп слід зберігати у зашифрованому форматі\n"
+"у безпечному місці."
+
+#: src/cryptsetup.c:573 src/cryptsetup.c:654 src/cryptsetup.c:2291
+msgid ""
+"The header dump with volume key is sensitive information\n"
+"that allows access to encrypted partition without a passphrase.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Дамп заголовка з ключем тому є конфіденційними даними,\n"
+"за допомогою яких можна отримати доступ до шифрованого розділу\n"
+"без пароля. Цей дамп слід зберігати у зашифрованому форматі\n"
+"у безпечному місці."
+
+#: src/cryptsetup.c:709 src/cryptsetup.c:739
+#, c-format
+msgid "Device %s is not a valid FVAULT2 device."
+msgstr "Пристрій %s не є коректним пристроєм FVAULT2."
+
+#: src/cryptsetup.c:747
+msgid "Cannot determine volume key size for FVAULT2, please use --key-size option."
+msgstr "Неможливо визначити розмір ключа тому для FVAULT2. Будь ласка, скористайтеся параметром --key-size."
+
+#: src/cryptsetup.c:801 src/veritysetup.c:323 src/integritysetup.c:400
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr "Пристрій %s усе ще є активним, його заплановано для відкладеного вилучення.\n"
+
+#: src/cryptsetup.c:835
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr "Зміна розмірів активного пристрою потребує наявності ключа тому у сховищі ключів, але вказано параметр --disable-keyring."
+
+#: src/cryptsetup.c:982
+msgid "Benchmark interrupted."
+msgstr "Тестування перервано."
+
+#: src/cryptsetup.c:1003
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr "PBKDF2-%-9s н/д\n"
+
+#: src/cryptsetup.c:1005
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr "PBKDF2-%-9s %7u ітерацій за секунду для %zu-бітового ключа\n"
+
+#: src/cryptsetup.c:1019
+#, c-format
+msgid "%-10s N/A\n"
+msgstr "%-10s н/д\n"
+
+#: src/cryptsetup.c:1021
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr "%-10s %4u ітерацій, пам'ять: %5u, %1u паралельних потоків (процесорів) для %zu-бітового ключа (запит на %u мс часу)\n"
+
+#: src/cryptsetup.c:1045
+msgid "Result of benchmark is not reliable."
+msgstr "Результат тестування є ненадійним."
+
+#: src/cryptsetup.c:1095
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Наближені значення під час перевірки визначаються лише за допомогою оперативної пам’яті (без запису на диск).\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1115
+#, c-format
+msgid "#%*s Algorithm | Key | Encryption | Decryption\n"
+msgstr "№%*s Алгоритм | Ключ | Шифрування | Розшифрування\n"
+
+#: src/cryptsetup.c:1119
+#, c-format
+msgid "Cipher %s (with %i bits key) is not available."
+msgstr "Шифрування %s (розмір ключа — %i бітів) є недоступним."
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:1138
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "№ Алгоритм | Ключ | Шифрування | Розшифрування\n"
+
+#: src/cryptsetup.c:1149
+msgid "N/A"
+msgstr "н/д"
+
+#: src/cryptsetup.c:1174
+msgid ""
+"Unprotected LUKS2 reencryption metadata detected. Please verify the reencryption operation is desirable (see luksDump output)\n"
+"and continue (upgrade metadata) only if you acknowledge the operation as genuine."
+msgstr ""
+"Виявлено незахищені метадані повторного шифрування LUKS2. Будь ласка, перевірте, чи бажаною є дія з повторного шифрування\n"
+"(див. виведення luksDump), і продовжуйте (оновлення метаданих), лише якщо впевнені, що дія є бажаною."
+
+#: src/cryptsetup.c:1180
+msgid "Enter passphrase to protect and upgrade reencryption metadata: "
+msgstr "Вкажіть пароль для захисту і оновлення метаданих повторного шифрування: "
+
+#: src/cryptsetup.c:1224
+msgid "Really proceed with LUKS2 reencryption recovery?"
+msgstr "Ви справді хочете продовжити процедуру відновлення повторного шифрування LUKS2?"
+
+#: src/cryptsetup.c:1233
+msgid "Enter passphrase to verify reencryption metadata digest: "
+msgstr "Вкажіть пароль для перевірки контрольної суми метаданих повторного шифрування: "
+
+#: src/cryptsetup.c:1235
+msgid "Enter passphrase for reencryption recovery: "
+msgstr "Вкажіть пароль для відновлення повторного шифрування: "
+
+#: src/cryptsetup.c:1290
+msgid "Really try to repair LUKS device header?"
+msgstr "Спробувати відновити заголовок пристрою LUKS?"
+
+#: src/cryptsetup.c:1314 src/integritysetup.c:89 src/integritysetup.c:238
+msgid ""
+"\n"
+"Wipe interrupted."
+msgstr ""
+"\n"
+"Витирання перервано."
+
+#: src/cryptsetup.c:1319 src/integritysetup.c:94 src/integritysetup.c:275
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+"Витираємо пристрій для ініціалізації контрольних сум для цілісності.\n"
+"Ви можете перервати цей процес натисканням комбінації клавіш CTRL+C (решта невитертого пристрою міститиме некоректну контрольну суму).\n"
+
+#: src/cryptsetup.c:1341 src/integritysetup.c:116
+#, c-format
+msgid "Cannot deactivate temporary device %s."
+msgstr "Не можна скасувати активацію тимчасового пристрою %s."
+
+#: src/cryptsetup.c:1392
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr "Параметр цілісності може бути використано лише для формату LUKS2."
+
+#: src/cryptsetup.c:1397 src/cryptsetup.c:1457
+msgid "Unsupported LUKS2 metadata size options."
+msgstr "Непідтримувані параметри розміру метаданих LUKS2."
+
+#: src/cryptsetup.c:1406
+msgid "Header file does not exist, do you want to create it?"
+msgstr "Файла заголовка не існує. Хочете його створити?"
+
+#: src/cryptsetup.c:1414
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "Не вдалося створити файл заголовка %s."
+
+#: src/cryptsetup.c:1437 src/integritysetup.c:144 src/integritysetup.c:152
+#: src/integritysetup.c:161 src/integritysetup.c:315 src/integritysetup.c:323
+#: src/integritysetup.c:333
+msgid "No known integrity specification pattern detected."
+msgstr "Не виявлено жодного відомого зразка специфікації цілісності."
+
+#: src/cryptsetup.c:1450
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "Не можна використовувати %s як заголовок на диску."
+
+#: src/cryptsetup.c:1474 src/integritysetup.c:181
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Дані на %s буде перезаписано без можливості відновлення."
+
+#: src/cryptsetup.c:1507 src/cryptsetup.c:1853 src/cryptsetup.c:1993
+#: src/cryptsetup.c:2148 src/cryptsetup.c:2214 src/utils_reencrypt_luks1.c:443
+msgid "Failed to set pbkdf parameters."
+msgstr "Не вдалося встановити параметри pbkdf."
+
+#: src/cryptsetup.c:1593
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "Зменшений відступ даних можна використовувати лише для від’єднаних заголовків LUKS."
+
+#: src/cryptsetup.c:1600
+#, c-format
+msgid "LUKS file container %s is too small for activation, there is no remaining space for data."
+msgstr "Контейнер файлів LUKS %s є надто малим для активації, на ньому не лишиться місця для даних."
+
+#: src/cryptsetup.c:1612 src/cryptsetup.c:1999
+msgid "Cannot determine volume key size for LUKS without keyslots, please use --key-size option."
+msgstr "Неможливо визначити розмір ключа тому для LUKS без слотів ключів. Будь ласка, скористайтеся параметром --key-size."
+
+#: src/cryptsetup.c:1658
+msgid "Device activated but cannot make flags persistent."
+msgstr "Пристрій задіяно, але не вдалося зробити прапорці сталими."
+
+#: src/cryptsetup.c:1737 src/cryptsetup.c:1805
+#, c-format
+msgid "Keyslot %d is selected for deletion."
+msgstr "Слот ключа %d позначено для вилучення."
+
+#: src/cryptsetup.c:1749 src/cryptsetup.c:1809
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Це останній слот ключа. Пристрій стане непридатним для використання після спорожнення цього ключа."
+
+#: src/cryptsetup.c:1750
+msgid "Enter any remaining passphrase: "
+msgstr "Введіть будь-який інший пароль: "
+
+#: src/cryptsetup.c:1751 src/cryptsetup.c:1811
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr "Дію перервано, слот ключів НЕ витерто.\n"
+
+#: src/cryptsetup.c:1787
+msgid "Enter passphrase to be deleted: "
+msgstr "Введіть пароль, який слід вилучити: "
+
+#: src/cryptsetup.c:1837 src/cryptsetup.c:2197 src/cryptsetup.c:2781
+#: src/cryptsetup.c:2948
+#, c-format
+msgid "Device %s is not a valid LUKS2 device."
+msgstr "Пристрій %s не є коректним пристроєм LUKS2."
+
+#: src/cryptsetup.c:1867 src/cryptsetup.c:2072
+msgid "Enter new passphrase for key slot: "
+msgstr "Введіть новий пароль для слота ключа: "
+
+#: src/cryptsetup.c:1968
+msgid "WARNING: The --key-slot parameter is used for new keyslot number.\n"
+msgstr "Попередження: параметр --key-slot використано для нового числа слоту ключа.\n"
+
+#: src/cryptsetup.c:2028 src/utils_reencrypt_luks1.c:1149
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Введіть будь-який пароль: "
+
+#: src/cryptsetup.c:2152
+msgid "Enter passphrase to be changed: "
+msgstr "Введіть пароль, який слід змінити: "
+
+#: src/cryptsetup.c:2168 src/utils_reencrypt_luks1.c:1135
+msgid "Enter new passphrase: "
+msgstr "Введіть новий пароль: "
+
+#: src/cryptsetup.c:2218
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "Вкажіть пароль для слоту ключа, який буде перетворено: "
+
+#: src/cryptsetup.c:2242
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "У команді isLuks можна використовувати лише один аргумент назви пристрою."
+
+#: src/cryptsetup.c:2350
+#, c-format
+msgid "Keyslot %d does not contain unbound key."
+msgstr "Слот ключа %d не містить непов'язаного ключа."
+
+#: src/cryptsetup.c:2355
+msgid ""
+"The header dump with unbound key is sensitive information.\n"
+"This dump should be stored encrypted in a safe place."
+msgstr ""
+"Дамп заголовка з непов'язаним ключем є конфіденційними даними.\n"
+"Цей дамп слід зберігати у зашифрованому форматі у безпечному місці."
+
+#: src/cryptsetup.c:2441 src/cryptsetup.c:2470
+#, c-format
+msgid "%s is not active %s device name."
+msgstr "%s не є назвою активного пристрою %s."
+
+#: src/cryptsetup.c:2465
+#, c-format
+msgid "%s is not active LUKS device name or header is missing."
+msgstr "%s не є назвою активного пристрою LUKS або пропущено заголовок."
+
+#: src/cryptsetup.c:2527 src/cryptsetup.c:2546
+msgid "Option --header-backup-file is required."
+msgstr "Слід вказати параметр --header-backup-file."
+
+#: src/cryptsetup.c:2577
+#, c-format
+msgid "%s is not cryptsetup managed device."
+msgstr "%s не є керованим cryptsetup пристроєм."
+
+#: src/cryptsetup.c:2588
+#, c-format
+msgid "Refresh is not supported for device type %s"
+msgstr "Підтримки дії з оновлення для пристрою типу %s не передбачено."
+
+#: src/cryptsetup.c:2638
+#, c-format
+msgid "Unrecognized metadata device type %s."
+msgstr "Нерозпізнаний тип пристрою метаданих, %s."
+
+#: src/cryptsetup.c:2640
+msgid "Command requires device and mapped name as arguments."
+msgstr "Аргументами команди мають бути назва пристрою та призначена до нього назва."
+
+#: src/cryptsetup.c:2661
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"У результаті виконання цієї операції буде витерто усі слоти ключів на пристрої %s.\n"
+"Після виконання цієї дії пристроєм не можна буде скористатися."
+
+#: src/cryptsetup.c:2668
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "Дію перервано, слоти ключів НЕ витерто.\n"
+
+#: src/cryptsetup.c:2707
+msgid "Invalid LUKS type, only luks1 and luks2 are supported."
+msgstr "Некоректний тип LUKS. Передбачено підтримку лише luks1 і luks2."
+
+#: src/cryptsetup.c:2723
+#, c-format
+msgid "Device is already %s type."
+msgstr "Пристрій вже належить до типу %s."
+
+#: src/cryptsetup.c:2730
+#, c-format
+msgid "This operation will convert %s to %s format.\n"
+msgstr "Ця дія перетворить %s до формату %s.\n"
+
+#: src/cryptsetup.c:2733
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr "Дію перервано, дані пристрою НЕ перетворено.\n"
+
+#: src/cryptsetup.c:2773
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "Пропущено параметр --priority, --label або --subsystem."
+
+#: src/cryptsetup.c:2807 src/cryptsetup.c:2847 src/cryptsetup.c:2867
+#, c-format
+msgid "Token %d is invalid."
+msgstr "Жетон %d є некоректним."
+
+#: src/cryptsetup.c:2810 src/cryptsetup.c:2870
+#, c-format
+msgid "Token %d in use."
+msgstr "Жетон %d використовується."
+
+#: src/cryptsetup.c:2822
+#, c-format
+msgid "Failed to add luks2-keyring token %d."
+msgstr "Не вдалося додати жетон %d зі сховища ключів luks2."
+
+#: src/cryptsetup.c:2833 src/cryptsetup.c:2896
+#, c-format
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "Не вдалося прив'язати жетон %d до слоту ключа %d."
+
+#: src/cryptsetup.c:2850
+#, c-format
+msgid "Token %d is not in use."
+msgstr "Жетон %d не використовується."
+
+#: src/cryptsetup.c:2887
+msgid "Failed to import token from file."
+msgstr "Не вдалося імпортувати жетон з файла."
+
+#: src/cryptsetup.c:2912
+#, c-format
+msgid "Failed to get token %d for export."
+msgstr "Не вдалося отримати жетон %d для експортування."
+
+#: src/cryptsetup.c:2925
+#, c-format
+msgid "Token %d is not assigned to keyslot %d."
+msgstr "Жетон %d не пов'язано зі слотом ключа %d."
+
+#: src/cryptsetup.c:2927 src/cryptsetup.c:2934
+#, c-format
+msgid "Failed to unassign token %d from keyslot %d."
+msgstr "Не вдалося відв'язати жетон %d від слоту ключа %d."
+
+#: src/cryptsetup.c:2983
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device."
+msgstr "Підтримку параметрів --tcrypt-hidden, --tcrypt-system і --tcrypt-backup передбачено лише для пристроїв TCRYPT."
+
+#: src/cryptsetup.c:2986
+msgid "Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type."
+msgstr "Підтримку параметра --veracrypt або --disable-veracrypt передбачено лише для пристроїв TCRYPT."
+
+#: src/cryptsetup.c:2989
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices."
+msgstr "Параметр --veracrypt-pim можна використовувати лише для сумісних із VeraCrypt пристроїв."
+
+#: src/cryptsetup.c:2993
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices."
+msgstr "Параметр --veracrypt-query-pim можна використовувати лише для сумісних із VeraCrypt пристроїв."
+
+#: src/cryptsetup.c:2995
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive."
+msgstr "Не можна поєднувати параметри --veracrypt-pim і --veracrypt-query-pim."
+
+#: src/cryptsetup.c:3004
+msgid "Option --persistent is not allowed with --test-passphrase."
+msgstr "Параметр --persistent не можна використовувати разом із --test-passphrase."
+
+#: src/cryptsetup.c:3007
+msgid "Options --refresh and --test-passphrase are mutually exclusive."
+msgstr "Не можна поєднувати параметри --refresh і --test-passphrase."
+
+#: src/cryptsetup.c:3010
+msgid "Option --shared is allowed only for open of plain device."
+msgstr "Параметр --shared можна використовувати лише для відкриття незашифрованого пристрою."
+
+#: src/cryptsetup.c:3013
+msgid "Option --skip is supported only for open of plain and loopaes devices."
+msgstr "Підтримку параметра --skip передбачено лише для відкриття незашифрованих пристроїв та пристроїв loopaes."
+
+#: src/cryptsetup.c:3016
+msgid "Option --offset with open action is only supported for plain and loopaes devices."
+msgstr "Підтримку параметра --offset разом із дією з відкриття передбачено лише для незашифрованих пристроїв та пристроїв loopaes."
+
+#: src/cryptsetup.c:3019
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards."
+msgstr "Параметр --tcrypt-hidden не можна поєднувати з --allow-discards."
+
+#: src/cryptsetup.c:3023
+msgid "Sector size option with open action is supported only for plain devices."
+msgstr "Підтримку параметра розміру сектора разом із дією з відкриття передбачено лише для незашифрованих пристроїв."
+
+#: src/cryptsetup.c:3027
+msgid "Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes."
+msgstr "Підтримку можливості використання великих секторів IV передбачено лише для відкриття пристроїв простого типу з розміром сектора, який перевищує 512 байтів."
+
+#: src/cryptsetup.c:3032
+msgid "Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices."
+msgstr "Параметр --test-passphrase можна використовувати лише для відкриття пристроїв LUKS, TCRYPT, BITLK та FVAULT2."
+
+#: src/cryptsetup.c:3035 src/cryptsetup.c:3058
+msgid "Options --device-size and --size cannot be combined."
+msgstr "Не можна одночасно використовувати параметри --device-size і --size."
+
+#: src/cryptsetup.c:3038
+msgid "Option --unbound is allowed only for open of luks device."
+msgstr "Параметр --sunbound можна використовувати лише для відкриття пристрою LUKS."
+
+#: src/cryptsetup.c:3041
+msgid "Option --unbound cannot be used without --test-passphrase."
+msgstr "Параметр --unbound не можна використовувати без --test-passphrase."
+
+#: src/cryptsetup.c:3050 src/veritysetup.c:668 src/integritysetup.c:755
+msgid "Options --cancel-deferred and --deferred cannot be used at the same time."
+msgstr "Не можна одночасно використовувати параметр --cancel-deferred і --deferred."
+
+#: src/cryptsetup.c:3066
+msgid "Options --reduce-device-size and --data-size cannot be combined."
+msgstr "Не можна одночасно використовувати параметри --reduce-device-size і --data-size."
+
+#: src/cryptsetup.c:3069
+msgid "Option --active-name can be set only for LUKS2 device."
+msgstr "Параметр --active-name можна встановлювати лише для пристроїв LUKS2."
+
+#: src/cryptsetup.c:3072
+msgid "Options --active-name and --force-offline-reencrypt cannot be combined."
+msgstr "Не можна одночасно використовувати параметри ---active-name і --force-offline-reencrypt."
+
+#: src/cryptsetup.c:3080 src/cryptsetup.c:3110
+msgid "Keyslot specification is required."
+msgstr "Слід вказати специфікація слотів ключів."
+
+#: src/cryptsetup.c:3088
+msgid "Options --align-payload and --offset cannot be combined."
+msgstr "Не можна одночасно використовувати параметри --align-payload і --offset."
+
+#: src/cryptsetup.c:3091
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension."
+msgstr "Параметром --integrity-no-wipe можна користуватися лише для дії з форматування із розширенням забезпечення цілісності."
+
+#: src/cryptsetup.c:3094
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Можна використовувати лише один з параметрів --use-[u]random."
+
+#: src/cryptsetup.c:3102
+msgid "Key size is required with --unbound option."
+msgstr "Разом із параметром --unbound слід вказувати розмір ключа."
+
+#: src/cryptsetup.c:3122
+msgid "Invalid token action."
+msgstr "Некоректна дія з жетоном."
+
+#: src/cryptsetup.c:3125
+msgid "--key-description parameter is mandatory for token add action."
+msgstr "Параметр --key-description є обов'язковим для дій із додавання жетонів."
+
+#: src/cryptsetup.c:3129 src/cryptsetup.c:3142
+msgid "Action requires specific token. Use --token-id parameter."
+msgstr "Для виконання дії потрібен специфічний жетон. Скористайтеся параметром --token-id."
+
+#: src/cryptsetup.c:3133
+msgid "Option --unbound is valid only with token add action."
+msgstr "Параметр --unbound можна використовувати лише разом із дією з додавання жетона."
+
+#: src/cryptsetup.c:3135
+msgid "Options --key-slot and --unbound cannot be combined."
+msgstr "Не можна поєднувати параметри --key-slot і --unbound."
+
+#: src/cryptsetup.c:3140
+msgid "Action requires specific keyslot. Use --key-slot parameter."
+msgstr "Дія потребує зазначення слоту ключа. Скористайтеся параметром --key-slot."
+
+#: src/cryptsetup.c:3156
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<пристрій> [--type <тип>] [<назва>]"
+
+#: src/cryptsetup.c:3156 src/veritysetup.c:491 src/integritysetup.c:535
+msgid "open device as <name>"
+msgstr "відкрити пристрій як <назва>"
+
+#: src/cryptsetup.c:3157 src/cryptsetup.c:3158 src/cryptsetup.c:3159
+#: src/veritysetup.c:492 src/veritysetup.c:493 src/integritysetup.c:536
+#: src/integritysetup.c:537 src/integritysetup.c:539
+msgid "<name>"
+msgstr "<назва>"
+
+#: src/cryptsetup.c:3157 src/veritysetup.c:492 src/integritysetup.c:536
+msgid "close device (remove mapping)"
+msgstr "закрити пристрій (вилучити призначення)"
+
+#: src/cryptsetup.c:3158 src/integritysetup.c:539
+msgid "resize active device"
+msgstr "змінити розмір активного пристрою"
+
+#: src/cryptsetup.c:3159
+msgid "show device status"
+msgstr "показати стан пристрою"
+
+#: src/cryptsetup.c:3160
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <шифр>]"
+
+#: src/cryptsetup.c:3160
+msgid "benchmark cipher"
+msgstr "перевірити швидкодію шифрування"
+
+#: src/cryptsetup.c:3161 src/cryptsetup.c:3162 src/cryptsetup.c:3163
+#: src/cryptsetup.c:3164 src/cryptsetup.c:3165 src/cryptsetup.c:3172
+#: src/cryptsetup.c:3173 src/cryptsetup.c:3174 src/cryptsetup.c:3175
+#: src/cryptsetup.c:3176 src/cryptsetup.c:3177 src/cryptsetup.c:3178
+#: src/cryptsetup.c:3179 src/cryptsetup.c:3180 src/cryptsetup.c:3181
+msgid "<device>"
+msgstr "<пристрій>"
+
+#: src/cryptsetup.c:3161
+msgid "try to repair on-disk metadata"
+msgstr "спробувати виправити метадані на диску"
+
+#: src/cryptsetup.c:3162
+msgid "reencrypt LUKS2 device"
+msgstr "повторно зашифрувати пристрій LUKS2"
+
+#: src/cryptsetup.c:3163
+msgid "erase all keyslots (remove encryption key)"
+msgstr "витерти усі слоти ключів (вилучити ключ шифрування)"
+
+#: src/cryptsetup.c:3164
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "перетворити LUKS із формату LUKS2 або навпаки"
+
+#: src/cryptsetup.c:3165
+msgid "set permanent configuration options for LUKS2"
+msgstr "встановити сталі параметри налаштування для LUKS2"
+
+#: src/cryptsetup.c:3166 src/cryptsetup.c:3167
+msgid "<device> [<new key file>]"
+msgstr "<пристрій> [<новий файл ключа>]"
+
+#: src/cryptsetup.c:3166
+msgid "formats a LUKS device"
+msgstr "форматує пристрій LUKS"
+
+#: src/cryptsetup.c:3167
+msgid "add key to LUKS device"
+msgstr "додати ключ до пристрою LUKS"
+
+#: src/cryptsetup.c:3168 src/cryptsetup.c:3169 src/cryptsetup.c:3170
+msgid "<device> [<key file>]"
+msgstr "<пристрій> [<файл ключа>]"
+
+#: src/cryptsetup.c:3168
+msgid "removes supplied key or key file from LUKS device"
+msgstr "вилучає наданий ключ або файл ключа з пристрою LUKS"
+
+#: src/cryptsetup.c:3169
+msgid "changes supplied key or key file of LUKS device"
+msgstr "змінює наданий ключ або файл ключа пристрою LUKS"
+
+#: src/cryptsetup.c:3170
+msgid "converts a key to new pbkdf parameters"
+msgstr "перетворює ключ до нових параметрів pbkdf"
+
+#: src/cryptsetup.c:3171
+msgid "<device> <key slot>"
+msgstr "<пристрій> <слот ключа>"
+
+#: src/cryptsetup.c:3171
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "вилучає ключ з номером <слот ключа> з пристрою LUKS"
+
+#: src/cryptsetup.c:3172
+msgid "print UUID of LUKS device"
+msgstr "вивести UUID пристрою LUKS"
+
+#: src/cryptsetup.c:3173
+msgid "tests <device> for LUKS partition header"
+msgstr "виконати спробу виявлення заголовка розділу LUKS на пристрої <пристрій>"
+
+#: src/cryptsetup.c:3174
+msgid "dump LUKS partition information"
+msgstr "створити дамп даних щодо розділу LUKS"
+
+#: src/cryptsetup.c:3175
+msgid "dump TCRYPT device information"
+msgstr "створити дамп даних пристрою TCRYPT"
+
+#: src/cryptsetup.c:3176
+msgid "dump BITLK device information"
+msgstr "створити дамп даних пристрою BITLK"
+
+#: src/cryptsetup.c:3177
+msgid "dump FVAULT2 device information"
+msgstr "створити дамп даних пристрою FVAULT2"
+
+#: src/cryptsetup.c:3178
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "Приспати пристрій LUKS і витерти ключ (роботу всіх каналів введення-виведення буде заморожено)"
+
+#: src/cryptsetup.c:3179
+msgid "Resume suspended LUKS device"
+msgstr "Відновити роботу приспаного пристрою LUKS"
+
+#: src/cryptsetup.c:3180
+msgid "Backup LUKS device header and keyslots"
+msgstr "Створити резервну копію заголовка пристрою LUKS і слотів ключів"
+
+#: src/cryptsetup.c:3181
+msgid "Restore LUKS device header and keyslots"
+msgstr "Відновити заголовок пристрою LUKS і слоти ключів"
+
+#: src/cryptsetup.c:3182
+msgid "<add|remove|import|export> <device>"
+msgstr "<add|remove|import|export> <пристрій>"
+
+#: src/cryptsetup.c:3182
+msgid "Manipulate LUKS2 tokens"
+msgstr "Керування жетонами LUKS2"
+
+#: src/cryptsetup.c:3201 src/veritysetup.c:509 src/integritysetup.c:554
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<дія> є однією з таких:\n"
+
+#: src/cryptsetup.c:3207
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+msgstr ""
+"\n"
+"Ви також можете скористатися застарілими альтернативними\n"
+"синтаксичними конструкціями для запису <дія>:\n"
+"\tвідкрити: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+"\tзакрити: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"
+
+#: src/cryptsetup.c:3211
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<назва> — пристрій для створення у %s\n"
+"<пристрій> — зашифрований пристрій\n"
+"<слот ключа> — номер слота ключа LUKS, який слід змінити\n"
+"<файл ключа> — необов’язковий файл ключа для нового ключа для дії luksAddKey\n"
+
+#: src/cryptsetup.c:3218
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+"\n"
+"Типовий укомпільований формат метаданих — %s (для дії luksFormat).\n"
+
+#: src/cryptsetup.c:3223 src/cryptsetup.c:3226
+#, c-format
+msgid ""
+"\n"
+"LUKS2 external token plugin support is %s.\n"
+msgstr ""
+"\n"
+"Підтримка додатків зовнішніх жетонів LUKS2 — %s.\n"
+
+#: src/cryptsetup.c:3223
+msgid "compiled-in"
+msgstr "вбудована"
+
+#: src/cryptsetup.c:3224
+#, c-format
+msgid "LUKS2 external token plugin path: %s.\n"
+msgstr "Шлях до теки додатків зовнішніх жетонів LUKS2: %s.\n"
+
+#: src/cryptsetup.c:3226
+msgid "disabled"
+msgstr "вимкнено"
+
+#: src/cryptsetup.c:3230
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"Типові вбудовані параметри ключа і пароля:\n"
+"\tМаксимальний розмір файла ключа: %d кБ, максимальна довжина інтерактивного пароля: %d (символів)\n"
+"Типовий час ітерації PBKDF для LUKS1: %s, час ітерації: %d мс\n"
+"Типовий PBKDF для LUKS2: %s\n"
+"\tЧас ітерації: %d, потрібний обсяг пам'яті: %d кБ, паралельних потоків: %d\n"
+
+#: src/cryptsetup.c:3241
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Типові вбудовані параметри шифрування на пристрої:\n"
+"\tloop-AES: %s, %d-бітовий ключ\n"
+"\tзвичайне: %s, ключ: %d-бітовий, хешування пароля: %s\n"
+"\tLUKS: %s, ключ: %d-бітовий, хешування заголовка LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:3250
+msgid "\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"
+msgstr "\tLUKS: типовий розмір ключа у режимі XTS (два вбудованих ключа) буде подвоєно.\n"
+
+#: src/cryptsetup.c:3268 src/veritysetup.c:648 src/integritysetup.c:711
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: слід вказати у параметрах %s"
+
+#: src/cryptsetup.c:3308 src/utils_reencrypt_luks1.c:1198
+msgid "Key slot is invalid."
+msgstr "Некоректний слот ключа."
+
+#: src/cryptsetup.c:3335
+msgid "Device size must be multiple of 512 bytes sector."
+msgstr "Розмір пристрою має бути кратним до 512-байтового сектора."
+
+#: src/cryptsetup.c:3340
+msgid "Invalid max reencryption hotzone size specification."
+msgstr "Некоректна специфікація розміру «гарячої» ділянки повторного шифрування."
+
+#: src/cryptsetup.c:3354 src/cryptsetup.c:3366
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Розмір ключа має бути кратним 8 бітам"
+
+#: src/cryptsetup.c:3371
+msgid "Maximum device reduce size is 1 GiB."
+msgstr "Максимальний розмір зменшення розміру пристрою дорівнює 1 ГіБ."
+
+#: src/cryptsetup.c:3374
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Розмір зменшення має бути кратним до 512-байтового сектора."
+
+#: src/cryptsetup.c:3391
+msgid "Option --priority can be only ignore/normal/prefer."
+msgstr "Значенням для параметра --priority може бути лише один з таких рядків: ignore, normal або prefer."
+
+#: src/cryptsetup.c:3410 src/veritysetup.c:572 src/integritysetup.c:634
+msgid "Show this help message"
+msgstr "Показати цю довідку"
+
+#: src/cryptsetup.c:3411 src/veritysetup.c:573 src/integritysetup.c:635
+msgid "Display brief usage"
+msgstr "Показати короткі настанови щодо користування"
+
+#: src/cryptsetup.c:3412 src/veritysetup.c:574 src/integritysetup.c:636
+msgid "Print package version"
+msgstr "Вивести дані щодо версії пакунка"
+
+#: src/cryptsetup.c:3423 src/veritysetup.c:585 src/integritysetup.c:647
+msgid "Help options:"
+msgstr "Пункти довідки:"
+
+#: src/cryptsetup.c:3443 src/veritysetup.c:603 src/integritysetup.c:664
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[ПАРАМЕТР...] <дія> <параметри_дії>"
+
+#: src/cryptsetup.c:3452 src/veritysetup.c:612 src/integritysetup.c:675
+msgid "Argument <action> missing."
+msgstr "Не вказано аргумент <дія>."
+
+#: src/cryptsetup.c:3528 src/veritysetup.c:643 src/integritysetup.c:706
+msgid "Unknown action."
+msgstr "Невідома дія."
+
+#: src/cryptsetup.c:3546
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "Параметр --key-file має пріоритет над вказаним параметром файла ключа."
+
+#: src/cryptsetup.c:3552
+msgid "Only one --key-file argument is allowed."
+msgstr "Можна використовувати лише один аргумент --key-file."
+
+#: src/cryptsetup.c:3557
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."
+msgstr "Функцією отримання ключа на основі пароля (PBKDF) може бути лише pbkdf2 або argon2i/argon2id."
+
+#: src/cryptsetup.c:3562
+msgid "PBKDF forced iterations cannot be combined with iteration time option."
+msgstr "Примусові ітерації PBKDF не можна поєднувати із параметром тривалості ітерацій."
+
+#: src/cryptsetup.c:3573
+msgid "Options --keyslot-cipher and --keyslot-key-size must be used together."
+msgstr "Параметри --keyslot-cipher і --keyslot-key-size має бути використано разом."
+
+#: src/cryptsetup.c:3581
+msgid "No action taken. Invoked with --test-args option.\n"
+msgstr "Дій не виконано. Викликано із параметром --test-args.\n"
+
+#: src/cryptsetup.c:3594
+msgid "Cannot disable metadata locking."
+msgstr "Не вдалося вимкнути блокування метаданих."
+
+#: src/veritysetup.c:54
+msgid "Invalid salt string specified."
+msgstr "Вказано некоректний рядок солі."
+
+#: src/veritysetup.c:87
+#, c-format
+msgid "Cannot create hash image %s for writing."
+msgstr "Не вдалося створити образ хешу %s для запису."
+
+#: src/veritysetup.c:97
+#, c-format
+msgid "Cannot create FEC image %s for writing."
+msgstr "Не вдалося створити образ FEC %s для запису."
+
+#: src/veritysetup.c:136
+#, c-format
+msgid "Cannot create root hash file %s for writing."
+msgstr "Не вдалося створити файл кореневого хешу %s для запису."
+
+#: src/veritysetup.c:143
+#, c-format
+msgid "Cannot write to root hash file %s."
+msgstr "Не вдалося записати файл кореневого хешу %s."
+
+#: src/veritysetup.c:198 src/veritysetup.c:476
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "Пристрій %s не є коректним пристроєм VERITY."
+
+#: src/veritysetup.c:215 src/veritysetup.c:232
+#, c-format
+msgid "Cannot read root hash file %s."
+msgstr "Не вдалося прочитати файл кореневого хешу %s."
+
+#: src/veritysetup.c:220
+#, c-format
+msgid "Invalid root hash file %s."
+msgstr "Некоректний файл кореневого хешу %s."
+
+#: src/veritysetup.c:241
+msgid "Invalid root hash string specified."
+msgstr "Вказано некоректний рядок кореневого хешу."
+
+#: src/veritysetup.c:249
+#, c-format
+msgid "Invalid signature file %s."
+msgstr "Некоректний файл підпису %s."
+
+#: src/veritysetup.c:256
+#, c-format
+msgid "Cannot read signature file %s."
+msgstr "Не вдалося прочитати файл підпису %s."
+
+#: src/veritysetup.c:279 src/veritysetup.c:293
+msgid "Command requires <root_hash> or --root-hash-file option as argument."
+msgstr "Для виконання команди потрібен <кореневий_хеш> або параметр --root-hash-file як аргумент."
+
+#: src/veritysetup.c:489
+msgid "<data_device> <hash_device>"
+msgstr "<пристрій_даних> <пристрій_хешу>"
+
+#: src/veritysetup.c:489 src/integritysetup.c:534
+msgid "format device"
+msgstr "форматувати пристрій"
+
+#: src/veritysetup.c:490
+msgid "<data_device> <hash_device> [<root_hash>]"
+msgstr "<пристрій_даних> <пристрій_хешу> [<кореневий_хеш>]"
+
+#: src/veritysetup.c:490
+msgid "verify device"
+msgstr "перевірити пристрій"
+
+#: src/veritysetup.c:491
+msgid "<data_device> <name> <hash_device> [<root_hash>]"
+msgstr "<пристрій_даних> <назва> <пристрій_хешу> [<кореневий_хеш>]"
+
+#: src/veritysetup.c:493 src/integritysetup.c:537
+msgid "show active device status"
+msgstr "показати стан активного пристрою"
+
+#: src/veritysetup.c:494
+msgid "<hash_device>"
+msgstr "<пристрій_хешу>"
+
+#: src/veritysetup.c:494 src/integritysetup.c:538
+msgid "show on-disk information"
+msgstr "показати вбудовані дані"
+
+#: src/veritysetup.c:513
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<назва> — назва пристрою, який слід створити у %s\n"
+"<пристрій_даних> — пристрій даних\n"
+"<пристрій_хешу> — пристрій, на якому зберігаються дані для перевірки\n"
+"<кореневий_хеш> — хеш кореневого вузла на пристрої <пристрій_хешу>\n"
+
+#: src/veritysetup.c:520
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Типові вбудовані параметри dm-verity:\n"
+"\tхеш: %s, блок даних (у байтах): %u, блок хешу (у байтах): %u, розмір солі: %u, формат хешування: %u\n"
+
+#: src/veritysetup.c:658
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together."
+msgstr "Параметри --ignore-corruption і --restart-on-corruption не можна використовувати одночасно."
+
+#: src/veritysetup.c:663
+msgid "Option --panic-on-corruption and --restart-on-corruption cannot be used together."
+msgstr "Параметри --panic-on-corruption і --restart-on-corruption не можна використовувати одночасно."
+
+#: src/integritysetup.c:177
+#, c-format
+msgid ""
+"This will overwrite data on %s and %s irrevocably.\n"
+"To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."
+msgstr ""
+"Дані на %s і %s буде перезаписано без можливості відновлення.\n"
+"Щоб зберегти пристрій даних, скористайтеся параметром --no-wipe (а потім активуйте за допомогою --integrity-recalculate)."
+
+#: src/integritysetup.c:212
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr "Форматовано із розміром мітки %u, внутрішня цілісність %s.\n"
+
+#: src/integritysetup.c:289
+msgid "Setting recalculate flag is not supported, you may consider using --wipe instead."
+msgstr "Підтримки встановлення прапорця повторного обчислення не передбачено. Вам варто розглянути можливість використання --wipe."
+
+#: src/integritysetup.c:364 src/integritysetup.c:521
+#, c-format
+msgid "Device %s is not a valid INTEGRITY device."
+msgstr "Пристрій %s не є коректним пристроєм INTEGRITY."
+
+#: src/integritysetup.c:534 src/integritysetup.c:538
+msgid "<integrity_device>"
+msgstr "<пристрій_цілісності>"
+
+#: src/integritysetup.c:535
+msgid "<integrity_device> <name>"
+msgstr "<пристрій_цілісності> <назва>"
+
+#: src/integritysetup.c:558
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<назва> є пристроєм, який слід створити у %s\n"
+"<пристрій_цілісності> є пристроєм, на якому зберігаються дані із мітками цілісності\n"
+
+#: src/integritysetup.c:563
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tChecksum algorithm: %s\n"
+"\tMaximum keyfile size: %dkB\n"
+msgstr ""
+"\n"
+"Типові компільовані параметри dm-integrity:\n"
+"\tАлгоритм обчислення контрольної суми: %s\n"
+"\tМаксимальний розмір файла ключа: %d кБ\n"
+
+#: src/integritysetup.c:620
+#, c-format
+msgid "Invalid --%s size. Maximum is %u bytes."
+msgstr "Некоректний розмір --%s. Максимальний розмір дорівнює %u байтів."
+
+#: src/integritysetup.c:720
+msgid "Both key file and key size options must be specified."
+msgstr "Не можна одночасно вказувати параметри файла ключа і розміру ключа."
+
+#: src/integritysetup.c:724
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr "Не можна одночасно вказувати параметри файла ключа цілісності журналу і розміру ключа."
+
+#: src/integritysetup.c:727
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "Якщо використано ключ цілісності журналу, має бути вказано алгоритм забезпечення цілісності журналу."
+
+#: src/integritysetup.c:731
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "Не можна одночасно вказувати параметри файла ключа шифрування журналу і розміру ключа."
+
+#: src/integritysetup.c:734
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "Якщо використано ключ шифрування журналу, має бути вказано алгоритм забезпечення шифрування журналу."
+
+#: src/integritysetup.c:738
+msgid "Recovery and bitmap mode options are mutually exclusive."
+msgstr "Не можна поєднувати параметри відновлення і бітової карти."
+
+#: src/integritysetup.c:745
+msgid "Journal options cannot be used in bitmap mode."
+msgstr "Параметри журналу у режимі бітової карти використовувати не можна."
+
+#: src/integritysetup.c:750
+msgid "Bitmap options can be used only in bitmap mode."
+msgstr "Параметри бітової карти можна використовувати лише у режимі бітового карти."
+
+#: src/utils_tools.c:118
+msgid ""
+"\n"
+"WARNING!\n"
+"========\n"
+msgstr ""
+"\n"
+"УВАГА!\n"
+"======\n"
+
+#. TRANSLATORS: User must type "YES" (in capital letters), do not translate this word.
+#: src/utils_tools.c:120
+#, c-format
+msgid ""
+"%s\n"
+"\n"
+"Are you sure? (Type 'yes' in capital letters): "
+msgstr ""
+"%s\n"
+"\n"
+"Ви впевнені? (Введіть «yes» великими літерами): "
+
+#: src/utils_tools.c:126
+msgid "Error reading response from terminal."
+msgstr "Помилка під час спроби читання відповіді з термінала."
+
+#: src/utils_tools.c:158
+msgid "Command successful."
+msgstr "Команду виконано успішно."
+
+#: src/utils_tools.c:166
+msgid "wrong or missing parameters"
+msgstr "помилкові параметри або параметри не вказано"
+
+#: src/utils_tools.c:168
+msgid "no permission or bad passphrase"
+msgstr "немає права доступу або помилковий пароль"
+
+#: src/utils_tools.c:170
+msgid "out of memory"
+msgstr "недостатньо пам'яті"
+
+#: src/utils_tools.c:172
+msgid "wrong device or file specified"
+msgstr "вказано помилковий пристрій або файл"
+
+#: src/utils_tools.c:174
+msgid "device already exists or device is busy"
+msgstr "пристрій вже існує або пристрій зайнято"
+
+#: src/utils_tools.c:176
+msgid "unknown error"
+msgstr "невідома помилка"
+
+#: src/utils_tools.c:178
+#, c-format
+msgid "Command failed with code %i (%s)."
+msgstr "Спроба виконання команди завершилася повідомленням про помилку з кодом %i (%s)."
+
+#: src/utils_tools.c:256
+#, c-format
+msgid "Key slot %i created."
+msgstr "Створено слот ключа %i."
+
+#: src/utils_tools.c:258
+#, c-format
+msgid "Key slot %i unlocked."
+msgstr "Слот ключа %i розблоковано."
+
+#: src/utils_tools.c:260
+#, c-format
+msgid "Key slot %i removed."
+msgstr "Слот ключа %i вилучено."
+
+#: src/utils_tools.c:269
+#, c-format
+msgid "Token %i created."
+msgstr "Створено жетон %i."
+
+#: src/utils_tools.c:271
+#, c-format
+msgid "Token %i removed."
+msgstr "Жетон %i вилучено."
+
+#: src/utils_tools.c:281
+msgid "No token could be unlocked with this PIN."
+msgstr "За допомогою цього коду не можна розблокувати жоден жетон."
+
+#: src/utils_tools.c:283
+#, c-format
+msgid "Token %i requires PIN."
+msgstr "Для доступу до жетона %i потрібен пінкод."
+
+#: src/utils_tools.c:285
+#, c-format
+msgid "Token (type %s) requires PIN."
+msgstr "Для доступу до жетона (тип %s) потрібен пінкод."
+
+#: src/utils_tools.c:288
+#, c-format
+msgid "Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Жетон %i не може розблокувати пов'язані слоти ключів (помилковий пароль до слота ключів)."
+
+#: src/utils_tools.c:290
+#, c-format
+msgid "Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."
+msgstr "Жетон (типу %s) не може розблокувати пов'язані слоти ключів (помилковий пароль до слота ключів)."
+
+#: src/utils_tools.c:293
+#, c-format
+msgid "Token %i requires additional missing resource."
+msgstr "Жетону %i потрібен додатковий ресурс, якого не вистачає."
+
+#: src/utils_tools.c:295
+#, c-format
+msgid "Token (type %s) requires additional missing resource."
+msgstr "Жетону (типу %s) потрібен додатковий ресурс, якого не вистачає."
+
+#: src/utils_tools.c:298
+#, c-format
+msgid "No usable token (type %s) is available."
+msgstr "Немає придатного до використання жетона (типу %s)."
+
+#: src/utils_tools.c:300
+msgid "No usable token is available."
+msgstr "Немає придатного до використання жетона."
+
+#: src/utils_tools.c:393
+#, c-format
+msgid "Cannot read keyfile %s."
+msgstr "Не вдалося прочитати файл ключа %s."
+
+#: src/utils_tools.c:398
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "Не вдалося прочитати %d байтів з файла ключа %s."
+
+#: src/utils_tools.c:423
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "Не вдалося відкрити файл ключа %s для запису."
+
+#: src/utils_tools.c:430
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "Не вдалося виконати запису до файла ключа %s."
+
+#: src/utils_progress.c:74
+#, c-format
+msgid "%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>х%02<PRIu64>с"
+
+#: src/utils_progress.c:76
+#, c-format
+msgid "%02<PRIu64>h%02<PRIu64>m%02<PRIu64>s"
+msgstr "%02<PRIu64>г%02<PRIu64>х%02<PRIu64>с"
+
+#: src/utils_progress.c:78
+#, c-format
+msgid "%02<PRIu64> days"
+msgstr "%02<PRIu64> днів"
+
+#: src/utils_progress.c:105 src/utils_progress.c:138
+#, c-format
+msgid "%4<PRIu64> %s written"
+msgstr "Записано %4<PRIu64> %s"
+
+#: src/utils_progress.c:109 src/utils_progress.c:142
+#, c-format
+msgid "speed %5.1f %s/s"
+msgstr "швидкість %5.1f %s/с"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. 'eol' is always new-line or empty.
+#. See above.
+#.
+#: src/utils_progress.c:118
+#, c-format
+msgid "Progress: %5.1f%%, ETA %s, %s, %s%s"
+msgstr "Поступ: %5.1f%%, приблизний час %s, %s, %s%s"
+
+#. TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+#. to get translated as well. See above
+#.
+#: src/utils_progress.c:150
+#, c-format
+msgid "Finished, time %s, %s, %s\n"
+msgstr "Завершено, час %s, %s, %s\n"
+
+#: src/utils_password.c:41 src/utils_password.c:72
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "Не вдалося перевірити якість пароля: %s"
+
+#: src/utils_password.c:49
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"Помилка під час спроби оцінити якість пароля:\n"
+" %s"
+
+#: src/utils_password.c:79
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "Помилка під час спроби оцінити якість пароля: некоректний пароль (%s)"
+
+#: src/utils_password.c:230 src/utils_password.c:244
+msgid "Error reading passphrase from terminal."
+msgstr "Помилка під час читання пароля з термінала."
+
+#: src/utils_password.c:242
+msgid "Verify passphrase: "
+msgstr "Перевірка пароля: "
+
+#: src/utils_password.c:249
+msgid "Passphrases do not match."
+msgstr "Паролі не збігаються."
+
+#: src/utils_password.c:287
+msgid "Cannot use offset with terminal input."
+msgstr "Не можна використовувати відступ у даних, що надходять з термінала."
+
+#: src/utils_password.c:291
+#, c-format
+msgid "Enter passphrase: "
+msgstr "Введіть пароль: "
+
+#: src/utils_password.c:294
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Введіть пароль до %s: "
+
+#: src/utils_password.c:328
+msgid "No key available with this passphrase."
+msgstr "Для цього пароля немає відповідного ключа."
+
+#: src/utils_password.c:330
+msgid "No usable keyslot is available."
+msgstr "Немає доступних придатних до користування слотів ключів."
+
+#: src/utils_luks.c:67
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "Перевірку паролів не можна виконувати на основі вхідних даних, які надходять не з tty."
+
+#: src/utils_luks.c:182
+#, c-format
+msgid "Failed to open file %s in read-only mode."
+msgstr "Не вдалося відкрити файл %s у режимі лише читання."
+
+#: src/utils_luks.c:195
+msgid "Provide valid LUKS2 token JSON:\n"
+msgstr "Надайте коректний жетон JSON LUKS2:\n"
+
+#: src/utils_luks.c:202
+msgid "Failed to read JSON file."
+msgstr "Не вдалося прочитати файл JSON."
+
+#: src/utils_luks.c:207
+msgid ""
+"\n"
+"Read interrupted."
+msgstr ""
+"\n"
+"Читання перервано."
+
+#: src/utils_luks.c:248
+#, c-format
+msgid "Failed to open file %s in write mode."
+msgstr "Не вдалося відкрити файл %s у режимі запису."
+
+#: src/utils_luks.c:257
+msgid ""
+"\n"
+"Write interrupted."
+msgstr ""
+"\n"
+"Запис перервано."
+
+#: src/utils_luks.c:261
+msgid "Failed to write JSON file."
+msgstr "Не вдалося записати файл JSON."
+
+#: src/utils_reencrypt.c:120
+#, c-format
+msgid "Auto-detected active dm device '%s' for data device %s.\n"
+msgstr "Автоматично виявлено активний пристрій dm «%s» для пристрою даних %s.\n"
+
+#: src/utils_reencrypt.c:124
+#, c-format
+msgid "Failed to auto-detect device %s holders."
+msgstr "Не вдалося автоматично визначити утримувачів пристрою %s."
+
+#: src/utils_reencrypt.c:130
+#, c-format
+msgid "Device %s is not a block device.\n"
+msgstr "Пристрій %s не є блоковим пристроєм.\n"
+
+#: src/utils_reencrypt.c:132
+#, c-format
+msgid ""
+"Unable to decide if device %s is activated or not.\n"
+"Are you sure you want to proceed with reencryption in offline mode?\n"
+"It may lead to data corruption if the device is actually activated.\n"
+"To run reencryption in online mode, use --active-name parameter instead.\n"
+msgstr ""
+"Не вдалося визначити, чи задіяно пристрій %s.\n"
+"Ви справді хочете продовжити повторне шифрування у режимі з від'єднанням?\n"
+"Таке шифрування може призвести до пошкодження даних, якщо пристрій задіяно.\n"
+"Щоб запустити повторне шифрування у режимі без від'єднання, скористайтеся параметром --active-name.\n"
+
+#: src/utils_reencrypt.c:141 src/utils_reencrypt.c:274
+#, c-format
+msgid ""
+"Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+"Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."
+msgstr ""
+"Пристрій %s не є блоковим пристроєм. Не можна визначити, чи є він активним.\n"
+"Скористайтеся --force-offline-reencrypt для обходу перевірки та запуску в автономному режимі (небезпечно!)."
+
+#: src/utils_reencrypt.c:178 src/utils_reencrypt.c:221
+#: src/utils_reencrypt.c:231
+msgid "Requested --resilience option cannot be applied to current reencryption operation."
+msgstr "Вказаний параметр --resilience не може бути застосовано до поточної дії з повторного шифрування."
+
+#: src/utils_reencrypt.c:203
+msgid "Device is not in LUKS2 encryption. Conflicting option --encrypt."
+msgstr "Пристрій не у шифруванні LUKS2. Конфліктний параметр --encrypt."
+
+#: src/utils_reencrypt.c:208
+msgid "Device is not in LUKS2 decryption. Conflicting option --decrypt."
+msgstr "Пристрій не у розшифруванні LUKS2. Конфліктний параметр --decrypt."
+
+#: src/utils_reencrypt.c:215
+msgid "Device is in reencryption using datashift resilience. Requested --resilience option cannot be applied."
+msgstr "Пристрій перебуває у повторному шифруванні з використанням стійкості зсуву даних. Вказаний параметр --resilience не може бути застосовано."
+
+#: src/utils_reencrypt.c:293
+msgid "Device requires reencryption recovery. Run repair first."
+msgstr "Пристрій потребує відновлення повторного шифрування. Спочатку виконайте відновлення."
+
+#: src/utils_reencrypt.c:307
+#, c-format
+msgid "Device %s is already in LUKS2 reencryption. Do you wish to resume previously initialised operation?"
+msgstr "Пристрій %s вже перебуває у стані повторного шифрування LUKS2. Хочете відновити раніше ініціалізовану дію?"
+
+#: src/utils_reencrypt.c:353
+msgid "Legacy LUKS2 reencryption is no longer supported."
+msgstr "Підтримки застарілого повторного шифрування LUKS2 більше не передбачено."
+
+#: src/utils_reencrypt.c:418
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "Підтримки повторного шифрування пристрою із профілем цілісності не передбачено."
+
+#: src/utils_reencrypt.c:449
+#, c-format
+msgid ""
+"Requested --sector-size %<PRIu32> is incompatible with %s superblock\n"
+"(block size: %<PRIu32> bytes) detected on device %s."
+msgstr ""
+"Вказаний --sector-size %<PRIu32> є несумісним із суперблоком %s\n"
+"(розмір блоку: %<PRIu32> байтів), який виявлено на пристрої %s."
+
+#: src/utils_reencrypt.c:518 src/utils_reencrypt.c:1391
+msgid "Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."
+msgstr "Шифрування без від'єднаного заголовка (--header) є неможливим без зменшення розміру пристрою зберігання даних (--reduce-device-size)."
+
+#: src/utils_reencrypt.c:525
+msgid "Requested data offset must be less than or equal to half of --reduce-device-size parameter."
+msgstr "Вказаний зсув даних має бути меншим або рівним половині значення параметра --reduce-device-size."
+
+#: src/utils_reencrypt.c:535
+#, c-format
+msgid "Adjusting --reduce-device-size value to twice the --offset %<PRIu64> (sectors).\n"
+msgstr "Коригуємо значення --reduce-device-size до подвійного значення --offset %<PRIu64> (у секторах).\n"
+
+#: src/utils_reencrypt.c:565
+#, c-format
+msgid "Temporary header file %s already exists. Aborting."
+msgstr "Файл тимчасового заголовка %s вже існує. Перериваємо обробку."
+
+#: src/utils_reencrypt.c:567 src/utils_reencrypt.c:574
+#, c-format
+msgid "Cannot create temporary header file %s."
+msgstr "Не вдалося створити файл тимчасового заголовка %s."
+
+#: src/utils_reencrypt.c:599
+msgid "LUKS2 metadata size is larger than data shift value."
+msgstr "Розмір метаданих LUKS2 перевищує значення зсуву даних."
+
+#: src/utils_reencrypt.c:636
+#, c-format
+msgid "Failed to place new header at head of device %s."
+msgstr "Не вдалося розмістити новий заголовок на початку пристрою %s."
+
+#: src/utils_reencrypt.c:646
+#, c-format
+msgid "%s/%s is now active and ready for online encryption.\n"
+msgstr "%s/%s задіяно, система готова до інтерактивного шифрування.\n"
+
+#: src/utils_reencrypt.c:682
+#, c-format
+msgid "Active device %s is not LUKS2."
+msgstr "Активний пристрій %s не є пристроєм LUKS2."
+
+#: src/utils_reencrypt.c:710
+msgid "Restoring original LUKS2 header."
+msgstr "Відновлюємо початковий заголовок LUKS2."
+
+#: src/utils_reencrypt.c:718
+msgid "Original LUKS2 header restore failed."
+msgstr "Спроба відновлення початкового заголовка LUKS2 зазнала невдачі."
+
+#: src/utils_reencrypt.c:744
+#, c-format
+msgid "Header file %s does not exist. Do you want to initialize LUKS2 decryption of device %s and export LUKS2 header to file %s?"
+msgstr "Файла заголовка %s не існує. Хочете ініціалізувати розшифрування LUKS2 пристрою %s і експортувати заголовок LUKS2 до файла %s?"
+
+#: src/utils_reencrypt.c:792
+msgid "Failed to add read/write permissions to exported header file."
+msgstr "Не вдалося додати права доступу для читання-запису до експортованого файла заголовка."
+
+#: src/utils_reencrypt.c:845
+#, c-format
+msgid "Reencryption initialization failed. Header backup is available in %s."
+msgstr "Не вдалося ініціалізувати повторне шифрування. Резервна копія заголовка перебуває у %s."
+
+#: src/utils_reencrypt.c:873
+msgid "LUKS2 decryption is supported with detached header device only (with data offset set to 0)."
+msgstr "Підтримку розшифровування LUKS2 передбачено лише для пристроїв із від'єднаним заголовком (із встановленим нульовим відступом даних)."
+
+#: src/utils_reencrypt.c:1008 src/utils_reencrypt.c:1017
+msgid "Not enough free keyslots for reencryption."
+msgstr "Недостатньо вільних слотів ключів для повторного шифрування."
+
+#: src/utils_reencrypt.c:1038 src/utils_reencrypt_luks1.c:1100
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "Файлом ключа можна користуватися лише з --key-slot, або якщо активним є лише один слот ключа."
+
+#: src/utils_reencrypt.c:1047 src/utils_reencrypt_luks1.c:1147
+#: src/utils_reencrypt_luks1.c:1158
+#, c-format
+msgid "Enter passphrase for key slot %d: "
+msgstr "Вкажіть пароль для слоту ключа %d: "
+
+#: src/utils_reencrypt.c:1059
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Вкажіть пароль для слоту ключа %u: "
+
+#: src/utils_reencrypt.c:1111
+#, c-format
+msgid "Switching data encryption cipher to %s.\n"
+msgstr "Перемикаємося на шифрування даних %s.\n"
+
+#: src/utils_reencrypt.c:1165
+msgid "No data segment parameters changed. Reencryption aborted."
+msgstr "Не змінено параметри сегмента даних. Повторне шифрування перервано."
+
+#: src/utils_reencrypt.c:1267
+msgid ""
+"Encryption sector size increase on offline device is not supported.\n"
+"Activate the device first or use --force-offline-reencrypt option (dangerous!)."
+msgstr ""
+"Підтримки збільшення розміру сектора шифрування на вимкненому пристрої не передбачено.\n"
+"Спочатку активуйте пристрій або скористайтеся параметром --force-offline-reencrypt (небезпечно!)."
+
+#: src/utils_reencrypt.c:1307 src/utils_reencrypt_luks1.c:726
+#: src/utils_reencrypt_luks1.c:798
+msgid ""
+"\n"
+"Reencryption interrupted."
+msgstr ""
+"\n"
+"Повторне шифрування перервано."
+
+#: src/utils_reencrypt.c:1312
+msgid "Resuming LUKS reencryption in forced offline mode.\n"
+msgstr "Відновлюємо повторне шифрування LUKS у примусовому вимкненому режимі.\n"
+
+#: src/utils_reencrypt.c:1329
+#, c-format
+msgid "Device %s contains broken LUKS metadata. Aborting operation."
+msgstr "На пристрої %s містяться пошкоджені метадані LUKS. Перериваємо дію."
+
+#: src/utils_reencrypt.c:1345 src/utils_reencrypt.c:1367
+#, c-format
+msgid "Device %s is already LUKS device. Aborting operation."
+msgstr "Пристрій %s вже є пристроєм LUKS. Перериваємо дію."
+
+#: src/utils_reencrypt.c:1373
+#, c-format
+msgid "Device %s is already in LUKS reencryption. Aborting operation."
+msgstr "Пристрій %s вже перебуває у стані повторного шифрування LUKS. Перериваємо дію."
+
+#: src/utils_reencrypt.c:1453
+msgid "LUKS2 decryption requires --header option."
+msgstr "Для розшифровування LUKS2 потрібен параметр --header."
+
+#: src/utils_reencrypt.c:1501
+msgid "Command requires device as argument."
+msgstr "Комарні слід передати аргумент пристрою."
+
+#: src/utils_reencrypt.c:1514
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS1."
+msgstr "Конфлікт версій. Пристрій %s є пристроєм LUKS1."
+
+#: src/utils_reencrypt.c:1520
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS1 reencryption."
+msgstr "Конфлікт версій. Пристрій %s перебуває у стані повторного шифрування LUKS1."
+
+#: src/utils_reencrypt.c:1526
+#, c-format
+msgid "Conflicting versions. Device %s is LUKS2."
+msgstr "Конфлікт версій. Пристрій %s є пристроєм LUKS2."
+
+#: src/utils_reencrypt.c:1532
+#, c-format
+msgid "Conflicting versions. Device %s is in LUKS2 reencryption."
+msgstr "Конфлікт версій. Пристрій %s перебуває у стані повторного шифрування LUKS2."
+
+#: src/utils_reencrypt.c:1538
+msgid "LUKS2 reencryption already initialized. Aborting operation."
+msgstr "Вже ініційовано повторне шифрування LUKS2. Перериваємо виконання дії."
+
+#: src/utils_reencrypt.c:1545
+msgid "Device reencryption not in progress."
+msgstr "Повторне шифрування пристрою не виконується."
+
+#: src/utils_reencrypt_luks1.c:129 src/utils_blockdev.c:287
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "Не можна відкрити %s у виключному режимі, пристрій вже використовується."
+
+#: src/utils_reencrypt_luks1.c:143 src/utils_reencrypt_luks1.c:945
+msgid "Allocation of aligned memory failed."
+msgstr "Спроба розподілу вирівняних ділянок пам’яті зазнала невдачі."
+
+#: src/utils_reencrypt_luks1.c:150
+#, c-format
+msgid "Cannot read device %s."
+msgstr "Не вдалося виконати читання з пристрою %s."
+
+#: src/utils_reencrypt_luks1.c:161
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "Позначаємо пристрій LUKS1 %s як непридатний."
+
+#: src/utils_reencrypt_luks1.c:177
+#, c-format
+msgid "Cannot write device %s."
+msgstr "Не вдалося виконати запис на пристрій %s."
+
+#: src/utils_reencrypt_luks1.c:226
+msgid "Cannot write reencryption log file."
+msgstr "Не вдалося записати файл журналу повторного шифрування."
+
+#: src/utils_reencrypt_luks1.c:282
+msgid "Cannot read reencryption log file."
+msgstr "Не вдалося прочитати файл журналу повторного шифрування."
+
+#: src/utils_reencrypt_luks1.c:293
+msgid "Wrong log format."
+msgstr "Помилкове форматування журналу."
+
+#: src/utils_reencrypt_luks1.c:320
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Файл журналу %s вже існує, поновлюємо повторне шифрування.\n"
+
+#: src/utils_reencrypt_luks1.c:369
+msgid "Activating temporary device using old LUKS header."
+msgstr "Спроба задіяти тимчасовий пристрій за допомогою старого заголовка LUKS."
+
+#: src/utils_reencrypt_luks1.c:379
+msgid "Activating temporary device using new LUKS header."
+msgstr "Спроба задіяти тимчасовий пристрій за допомогою нового заголовка LUKS."
+
+#: src/utils_reencrypt_luks1.c:389
+msgid "Activation of temporary devices failed."
+msgstr "Спроба задіяти тимчасові пристрої зазнала невдачі."
+
+#: src/utils_reencrypt_luks1.c:449
+msgid "Failed to set data offset."
+msgstr "Не вдалося встановити відступ у даних."
+
+#: src/utils_reencrypt_luks1.c:455
+msgid "Failed to set metadata size."
+msgstr "Не вдалося встановити розмір метаданих."
+
+#: src/utils_reencrypt_luks1.c:463
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "Створено новий заголовок LUKS для пристрою %s."
+
+#: src/utils_reencrypt_luks1.c:500
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "Створено резервну копію заголовка %s пристрою %s."
+
+#: src/utils_reencrypt_luks1.c:556
+msgid "Creation of LUKS backup headers failed."
+msgstr "Спроба створення заголовків резервних копій LUKS зазнала невдачі."
+
+#: src/utils_reencrypt_luks1.c:685
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "Не вдалося відновити заголовок %s на пристрої %s."
+
+#: src/utils_reencrypt_luks1.c:687
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "Відновлено заголовок %s на пристрої %s."
+
+#: src/utils_reencrypt_luks1.c:917 src/utils_reencrypt_luks1.c:923
+msgid "Cannot open temporary LUKS device."
+msgstr "Неможливо відкрити тимчасовий пристрій LUKS."
+
+#: src/utils_reencrypt_luks1.c:928 src/utils_reencrypt_luks1.c:933
+msgid "Cannot get device size."
+msgstr "Не вдалося отримати дані щодо розміру пристрою."
+
+#: src/utils_reencrypt_luks1.c:968
+msgid "IO error during reencryption."
+msgstr "Помилка введення-виведення під час повторного шифрування."
+
+#: src/utils_reencrypt_luks1.c:998
+msgid "Provided UUID is invalid."
+msgstr "Наданий UUID є некоректним."
+
+#: src/utils_reencrypt_luks1.c:1224
+msgid "Cannot open reencryption log file."
+msgstr "Не вдалося відкрити файл журналу повторного шифрування."
+
+#: src/utils_reencrypt_luks1.c:1230
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "Розшифровування не виконується. Наданий UUID можна використовувати лише для відновлення призупиненого процесу розшифровування."
+
+#: src/utils_reencrypt_luks1.c:1286
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "Повторне шифрування призведе до зміни: %s%s%s%s%s%s."
+
+#: src/utils_reencrypt_luks1.c:1287
+msgid "volume key"
+msgstr "ключ тому"
+
+#: src/utils_reencrypt_luks1.c:1289
+msgid "set hash to "
+msgstr "встановити хеш у значення "
+
+#: src/utils_reencrypt_luks1.c:1290
+msgid ", set cipher to "
+msgstr ", встановити шифрування "
+
+#: src/utils_blockdev.c:189
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' partition signature.\n"
+msgstr "Попередження: пристрій %s вже містить підпис розділу «%s».\n"
+
+#: src/utils_blockdev.c:197
+#, c-format
+msgid "WARNING: Device %s already contains a '%s' superblock signature.\n"
+msgstr "Попередження: пристрій %s вже містить підпис суперблоку «%s».\n"
+
+#: src/utils_blockdev.c:219 src/utils_blockdev.c:294 src/utils_blockdev.c:344
+msgid "Failed to initialize device signature probes."
+msgstr "Не вдалося ініціалізувати зондування підписів пристроїв."
+
+#: src/utils_blockdev.c:274
+#, c-format
+msgid "Failed to stat device %s."
+msgstr "Не вдалося зібрати статистичні дані щодо пристрою %s."
+
+#: src/utils_blockdev.c:289
+#, c-format
+msgid "Failed to open file %s in read/write mode."
+msgstr "Не вдалося відкрити файл %s у режимі читання-запису."
+
+#: src/utils_blockdev.c:307
+#, c-format
+msgid "Existing '%s' partition signature on device %s will be wiped."
+msgstr "Наявний підпис розділу «%s» на пристрої %s буде витерто."
+
+#: src/utils_blockdev.c:310
+#, c-format
+msgid "Existing '%s' superblock signature on device %s will be wiped."
+msgstr "Наявний підпис суперблоку «%s» на пристрої %s буде витерто."
+
+#: src/utils_blockdev.c:313
+msgid "Failed to wipe device signature."
+msgstr "Не вдалося витерти підпис пристрою."
+
+#: src/utils_blockdev.c:320
+#, c-format
+msgid "Failed to probe device %s for a signature."
+msgstr "Не вдалося виконати зондування пристрою %s з метою виявлення підпису."
+
+#: src/utils_args.c:65
+#, c-format
+msgid "Invalid size specification in parameter --%s."
+msgstr "Некоректна специфікація розміру у параметрі --%s."
+
+#: src/utils_args.c:125
+#, c-format
+msgid "Option --%s is not allowed with %s action."
+msgstr "Параметр --%s не можна використовувати разом із дією %s."
+
+#: tokens/ssh/cryptsetup-ssh.c:110
+msgid "Failed to write ssh token json."
+msgstr "Не вдалося записати JSON жетона ssh."
+
+#: tokens/ssh/cryptsetup-ssh.c:128
+msgid ""
+"Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected to an SSH server\vThis plugin currently allows only adding a token to an existing key slot.\n"
+"\n"
+"Specified SSH server must contain a key file on the specified path with a passphrase for an existing key slot on the device.\n"
+"Provided credentials will be used by cryptsetup to get the password when opening the device using the token.\n"
+"\n"
+"Note: The information provided when adding the token (SSH server address, user and paths) will be stored in the LUKS2 header in plaintext."
+msgstr ""
+"Експериментальний додаток cryptsetup для розблоковування пристроїв LUKS2 за допомогою жетона, який з'єднано із сервером SSH.\vУ поточній версії цей додаток уможливлює лише додавання жетона до наявного слоту ключа.\n"
+"\n"
+"Вказаний сервер SSH має містити файл ключа за вказаним шляхом із паролем для наявного слоту ключа на пристрою.\n"
+"Надані реєстраційні дані буде використано cryptsetup для отримання пароля для відкриття пристрою за допомогою жетона.\n"
+"\n"
+"Зауваження: дані, які надано при додаванні жетона (адреса сервера SSH, користувач та шляхи) буде збережено у заголовку LUKS2 у форматі звичайного тексту."
+
+#: tokens/ssh/cryptsetup-ssh.c:138
+msgid "<action> <device>"
+msgstr "<дія> <пристрій>"
+
+#: tokens/ssh/cryptsetup-ssh.c:141
+msgid "Options for the 'add' action:"
+msgstr "Параметри дії «add» (додати):"
+
+#: tokens/ssh/cryptsetup-ssh.c:142
+msgid "IP address/URL of the remote server for this token"
+msgstr "IP-адреса/Назва віддаленого сервера для цього жетона"
+
+#: tokens/ssh/cryptsetup-ssh.c:143
+msgid "Username used for the remote server"
+msgstr "Ім'я користувача для доступу до віддаленого сервера"
+
+#: tokens/ssh/cryptsetup-ssh.c:144
+msgid "Path to the key file on the remote server"
+msgstr "Шлях до файла ключа на віддаленому сервері"
+
+#: tokens/ssh/cryptsetup-ssh.c:145
+msgid "Path to the SSH key for connecting to the remote server"
+msgstr "Шлях до ключа SSH для з'єднання із віддаленим сервером"
+
+#: tokens/ssh/cryptsetup-ssh.c:146
+msgid "Keyslot to assign the token to. If not specified, token will be assigned to the first keyslot matching provided passphrase."
+msgstr "Слот ключа для прив'язування жетона. Якщо не вказано, жетон буде пов'язано із першим слотом ключа, який відповідає наданому паролю."
+
+#: tokens/ssh/cryptsetup-ssh.c:148
+msgid "Generic options:"
+msgstr "Загальні параметри:"
+
+#: tokens/ssh/cryptsetup-ssh.c:149
+msgid "Shows more detailed error messages"
+msgstr "Показувати докладні повідомлення про помилки"
+
+#: tokens/ssh/cryptsetup-ssh.c:150
+msgid "Show debug messages"
+msgstr "Показувати діагностичні повідомлення"
+
+#: tokens/ssh/cryptsetup-ssh.c:151
+msgid "Show debug messages including JSON metadata"
+msgstr "Показувати діагностичні повідомлення, зокрема метадані JSON"
+
+#: tokens/ssh/cryptsetup-ssh.c:262
+msgid "Failed to open and import private key:\n"
+msgstr "Не вдалося відкрити і імпортувати закритий ключ:\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:266
+msgid "Failed to import private key (password protected?).\n"
+msgstr "Не вдалося імпортувати закритий ключ (захищено паролем?).\n"
+
+#. TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: "
+#: tokens/ssh/cryptsetup-ssh.c:268
+#, c-format
+msgid "%s@%s's password: "
+msgstr "Пароль до %s@%s: "
+
+#: tokens/ssh/cryptsetup-ssh.c:357
+#, c-format
+msgid "Failed to parse arguments.\n"
+msgstr "Не вдалося обробити аргументи.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:368
+#, c-format
+msgid "An action must be specified\n"
+msgstr "Має бути вказано дію\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:374
+#, c-format
+msgid "Device must be specified for '%s' action.\n"
+msgstr "Для виконання дії «%s» має бути вказано пристрій.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:379
+#, c-format
+msgid "SSH server must be specified for '%s' action.\n"
+msgstr "Для виконання дії «%s» має бути вказано сервер SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:384
+#, c-format
+msgid "SSH user must be specified for '%s' action.\n"
+msgstr "Для виконання дії «%s» має бути вказано користувача SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:389
+#, c-format
+msgid "SSH path must be specified for '%s' action.\n"
+msgstr "Для виконання дії «%s» має бути вказано шлях до SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:394
+#, c-format
+msgid "SSH key path must be specified for '%s' action.\n"
+msgstr "Для виконання дії «%s» має бути вказано шлях до ключа SSH.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:401
+#, c-format
+msgid "Failed open %s using provided credentials.\n"
+msgstr "Не вдалося відкрити %s за допомогою наданих реєстраційних даних.\n"
+
+#: tokens/ssh/cryptsetup-ssh.c:417
+#, c-format
+msgid "Only 'add' action is currently supported by this plugin.\n"
+msgstr "У поточній версії цього додатка передбачено підтримку лише дії «add» (додати0.\n"
+
+#: tokens/ssh/ssh-utils.c:46
+msgid "Cannot create sftp session: "
+msgstr "Не вдалося створити сеанс sftp: "
+
+#: tokens/ssh/ssh-utils.c:53
+msgid "Cannot init sftp session: "
+msgstr "Не вдалося ініціалізувати сеанс sftp: "
+
+#: tokens/ssh/ssh-utils.c:59
+msgid "Cannot open sftp session: "
+msgstr "Не вдалося відкрити сеанс sftp: "
+
+#: tokens/ssh/ssh-utils.c:66
+msgid "Cannot stat sftp file: "
+msgstr "Не вдалося статистично обробити файл sftp: "
+
+#: tokens/ssh/ssh-utils.c:74
+msgid "Not enough memory.\n"
+msgstr "Недостатньо пам'яті.\n"
+
+#: tokens/ssh/ssh-utils.c:81
+msgid "Cannot read remote key: "
+msgstr "Не вдалося прочитати віддалений ключ: "
+
+#: tokens/ssh/ssh-utils.c:122
+msgid "Connection failed: "
+msgstr "Не вдалось з'єднатись: "
+
+#: tokens/ssh/ssh-utils.c:132
+msgid "Server not known: "
+msgstr "Невідомий сервер: "
+
+#: tokens/ssh/ssh-utils.c:160
+msgid "Public key auth method not allowed on host.\n"
+msgstr "На вузлі заборонено спосіб розпізнавання за відкритим ключем.\n"
+
+#: tokens/ssh/ssh-utils.c:171
+msgid "Public key authentication error: "
+msgstr "Помилка розпізнавання за відкритим ключем: "
+
+#~ msgid "WARNING: Data offset is outside of currently available data device.\n"
+#~ msgstr "Увага: відступ у даних виходить за межі поточного доступного пристрою для зберігання даних.\n"
+
+#~ msgid "Cannot get process priority."
+#~ msgstr "Не вдалося отримати значення пріоритетності процесу."
+
+#~ msgid "Cannot unlock memory."
+#~ msgstr "Не вдалося розблокувати пам’ять."
+
+#~ msgid "Locking directory %s/%s will be created with default compiled-in permissions."
+#~ msgstr "Буде створено каталог блокування %s/%s із типовими вбудованими правами доступу."
+
+#~ msgid "Failed to read BITLK signature from %s."
+#~ msgstr "Не вдалося прочитати підпис BITLK з %s."
+
+#~ msgid "Invalid or unknown signature for BITLK device."
+#~ msgstr "Некоректний або невідомий підпис для пристрою BITLK."
+
+#~ msgid "Failed to wipe backup segment data."
+#~ msgstr "Не вдалося витерти дані резервного сегмента."
+
+#~ msgid "Failed to disable reencryption requirement flag."
+#~ msgstr "Не вдалося вимкнути прапорець вимоги повторного шифрування."
+
+#~ msgid "Encryption is supported only for LUKS2 format."
+#~ msgstr "Підтримку шифрування передбачено лише для формату LUKS2."
+
+#~ msgid "Detected LUKS device on %s. Do you want to encrypt that LUKS device again?"
+#~ msgstr "Виявлено пристрій LUKS на %s. Хочете зашифрувати цей пристрій LUKS знову?"
+
+#~ msgid "Only LUKS2 format is currently supported. Please use cryptsetup-reencrypt tool for LUKS1."
+#~ msgstr "У поточній версії передбачено підтримку лише формату LUKS2. Для роботи з LUKS1, будь ласка, скористайтеся програмою cryptsetup-reencrypt."
+
+#~ msgid "Legacy offline reencryption already in-progress. Use cryptsetup-reencrypt utility."
+#~ msgstr "Вже виконується повторне шифрування з від'єднанням у застарілому режимі. Скористайтеся програмою cryptsetup-reencrypt."
+
+#~ msgid "LUKS2 device is not in reencryption."
+#~ msgstr "Пристрій LUKS2 не перебуває у стані повторного шифрування."
+
+#~ msgid "Setting LUKS2 offline reencrypt flag on device %s."
+#~ msgstr "Встановлюємо прапорець повторного шифрування LUKS2 з від'єднанням на пристрій %s."
+
+#~ msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+#~ msgstr "Ця версія cryptsetup-reencrypt не може обробляти новий тип вбудованих жетонів %s."
+
+#~ msgid "Failed to read activation flags from backup header."
+#~ msgstr "Не вдалося прочитати прапорці активації з резервного заголовка."
+
+#~ msgid "Failed to write activation flags to new header."
+#~ msgstr "Не вдалося записати прапорці активації до нового заголовка."
+
+#~ msgid "Changed pbkdf parameters in keyslot %i."
+#~ msgstr "Змінено параметри pbkdf у слоті ключа %i."
+
+#~ msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+#~ msgstr "Розмір блоку повторного шифрування повинен належати діапазону від 1 МіБ до 64 МІБ."
+
+#~ msgid "Maximum device reduce size is 64 MiB."
+#~ msgstr "Максимальний розмір зменшення розміру пристрою дорівнює 64 МіБ."
+
+#~ msgid "[OPTION...] <device>"
+#~ msgstr "[ПАРАМЕТР...] <пристрій>"
+
+#~ msgid "Argument required."
+#~ msgstr "Слід вказати аргумент."
+
+#~ msgid "Option --new must be used together with --reduce-device-size or --header."
+#~ msgstr "Параметр --new слід використовувати разом з --reduce-device-size або --header."
+
+#~ msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+#~ msgstr "Параметр --keep-key можна використовувати лише разом з параметром --hash --iter-time або --pbkdf-force-iterations."
+
+#~ msgid "Option --new cannot be used together with --decrypt."
+#~ msgstr "Параметр --new не можна використовувати разом з --decrypt."
+
+#~ msgid "Option --decrypt is incompatible with specified parameters."
+#~ msgstr "Параметр --decrypt є несумісним із вказаними параметрами."
+
+#~ msgid "Option --uuid is allowed only together with --decrypt."
+#~ msgstr "Параметр --uuid можна використовувати лише разом із --decrypt."
+
+#~ msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+#~ msgstr "Некоректний тип luks. Скористайтеся одним з таких типів: luks, luks1 або luks2."
+
+#~ msgid "Device %s is in use. Cannot proceed with format operation."
+#~ msgstr "Пристрій %s використовується сторонньою програмою. Продовження дій з форматування неможливе."
+
+#~ msgid "No free token slot."
+#~ msgstr "Немає вільного слоту ключів."
+
+#~ msgid "Invalid LUKS device type."
+#~ msgstr "Некоректний тип пристрою LUKS."
+
+#~ msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+#~ msgstr "Шифр, який використано для шифрування даних диска (див. /proc/crypto)"
+
+#~ msgid "The hash used to create the encryption key from the passphrase"
+#~ msgstr "Хеш, використаний для створення ключа шифрування на основі пароля"
+
+#~ msgid "Verifies the passphrase by asking for it twice"
+#~ msgstr "Перевіряє пароль повторним запитом щодо нього"
+
+#~ msgid "Read the key from a file"
+#~ msgstr "Прочитати ключ з файла"
+
+#~ msgid "Read the volume (master) key from file."
+#~ msgstr "Прочитати ключ тому (основний ключ) з файла."
+
+#~ msgid "Dump volume (master) key instead of keyslots info"
+#~ msgstr "Створити дамп ключа тому (основного ключа) замість показу даних щодо слотів ключів"
+
+#~ msgid "The size of the encryption key"
+#~ msgstr "Розмір ключа шифрування"
+
+#~ msgid "BITS"
+#~ msgstr "БІТИ"
+
+#~ msgid "Limits the read from keyfile"
+#~ msgstr "Обмежує читання з файла ключа"
+
+#~ msgid "bytes"
+#~ msgstr "байти"
+
+#~ msgid "Number of bytes to skip in keyfile"
+#~ msgstr "Кількість байтів, які слід пропустити у файлі ключа"
+
+#~ msgid "Limits the read from newly added keyfile"
+#~ msgstr "Обмежує читання з щойно доданого файла ключа"
+
+#~ msgid "Number of bytes to skip in newly added keyfile"
+#~ msgstr "Кількість байтів, які слід пропустити у щойно доданому файлі ключа"
+
+#~ msgid "Slot number for new key (default is first free)"
+#~ msgstr "Номер слоту для нового ключа (типовим слотом є перший вільний слот)"
+
+#~ msgid "The size of the device"
+#~ msgstr "Розмір пристрою"
+
+#~ msgid "SECTORS"
+#~ msgstr "СЕКТОРИ"
+
+#~ msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+#~ msgstr "Використовувати лише вказаний розмір пристрою (ігнорувати решту об’єму). НЕБЕЗПЕЧНО!"
+
+#~ msgid "The start offset in the backend device"
+#~ msgstr "Початковий відступ на допоміжному пристрої"
+
+#~ msgid "How many sectors of the encrypted data to skip at the beginning"
+#~ msgstr "Кількість секторів зашифрованих даних, які слід пропустити на початку"
+
+#~ msgid "Create a readonly mapping"
+#~ msgstr "Створити призначення у режимі лише читання"
+
+#~ msgid "Do not ask for confirmation"
+#~ msgstr "Не питати про підтвердження"
+
+#~ msgid "Timeout for interactive passphrase prompt (in seconds)"
+#~ msgstr "Час очікування у інтерактивному запиті щодо пароля (у секундах)"
+
+#~ msgid "secs"
+#~ msgstr "секунди"
+
+#~ msgid "Progress line update (in seconds)"
+#~ msgstr "Оновлення лінії поступу (у секундах)"
+
+#~ msgid "How often the input of the passphrase can be retried"
+#~ msgstr "Частота повторень спроб отримання вхідних даних пароля"
+
+#~ msgid "Align payload at <n> sector boundaries - for luksFormat"
+#~ msgstr "Вирівняти дані за областями у <n> секторів, для luksFormat"
+
+#~ msgid "File with LUKS header and keyslots backup"
+#~ msgstr "Файл з заголовком LUKS та резервною копію слотів ключів"
+
+#~ msgid "Use /dev/random for generating volume key"
+#~ msgstr "Використовувати для створення ключа тому /dev/random"
+
+#~ msgid "Use /dev/urandom for generating volume key"
+#~ msgstr "Використовувати для створення ключа тому /dev/urandom"
+
+#~ msgid "Share device with another non-overlapping crypt segment"
+#~ msgstr "Використовувати пристрій спільно з іншим сегментом шифрування, без перекриття"
+
+#~ msgid "UUID for device to use"
+#~ msgstr "UUID пристрою, який слід використати"
+
+#~ msgid "Allow discards (aka TRIM) requests for device"
+#~ msgstr "Дозволити запити відкидання (або TRIM) до пристрою"
+
+#~ msgid "Device or file with separated LUKS header"
+#~ msgstr "Пристрій або файл з окремим заголовком LUKS"
+
+#~ msgid "Do not activate device, just check passphrase"
+#~ msgstr "Не задіювати пристрій, просто перевірити пароль"
+
+#~ msgid "Use hidden header (hidden TCRYPT device)"
+#~ msgstr "Використовувати прихований заголовок (прихований пристрій TCRYPT)"
+
+#~ msgid "Device is system TCRYPT drive (with bootloader)"
+#~ msgstr "Пристрій є системним диском TCRYPT (диском з завантажувачем)"
+
+#~ msgid "Use backup (secondary) TCRYPT header"
+#~ msgstr "Використовувати резервний (вторинний) заголовок TCRYPT"
+
+#~ msgid "Scan also for VeraCrypt compatible device"
+#~ msgstr "Виконати також пошук сумісних із VeraCrypt пристроїв"
+
+#~ msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Особистий множник ітерації (Personal Iteration Multiplier або PIM) для сумісного з VeraCrypt пристрою"
+
+#~ msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+#~ msgstr "Особистий множник ітерації (Personal Iteration Multiplier або PIM) запису для сумісного з VeraCrypt пристрою"
+
+#~ msgid "Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+#~ msgstr "Типи метаданих пристрою: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"
+
+#~ msgid "Disable password quality check (if enabled)"
+#~ msgstr "Вимкнути перевірку якості пароля (якщо її увімкнено)"
+
+#~ msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+#~ msgstr "Скористатися параметром сумісності швидкодії dm-crypt same_cpu_crypt"
+
+#~ msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+#~ msgstr "Скористатися параметром сумісності швидкодії dm-crypt submit_from_crypt_cpus"
+
+#~ msgid "Bypass dm-crypt workqueue and process read requests synchronously"
+#~ msgstr "Обійти чергу обробки dm-crypt і обробляти запити щодо читання синхронно"
+
+#~ msgid "Bypass dm-crypt workqueue and process write requests synchronously"
+#~ msgstr "Обійти чергу обробки dm-crypt і обробляти запити щодо запису синхронно"
+
+#~ msgid "Device removal is deferred until the last user closes it"
+#~ msgstr "Вилучення пристрою відкладено до часу, коли останній користувач закриє його"
+
+#~ msgid "Use global lock to serialize memory hard PBKDF (OOM workaround)"
+#~ msgstr "Скористатися загальним блокуванням для перетворення у послідовну форму «жорсткого» PBKDF у пам'яті (обхід OOM)"
+
+#~ msgid "PBKDF iteration time for LUKS (in ms)"
+#~ msgstr "Тривалість ітерації PBKDF для LUKS (у мс)"
+
+#~ msgid "msecs"
+#~ msgstr "мс"
+
+#~ msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+#~ msgstr "Алгоритм PBKDF (для LUKS2) (argon2i/argon2id/pbkdf2)"
+
+#~ msgid "PBKDF memory cost limit"
+#~ msgstr "Обмеження вартості пам'яті PBKDF"
+
+#~ msgid "kilobytes"
+#~ msgstr "кілобайти"
+
+#~ msgid "PBKDF parallel cost"
+#~ msgstr "Вартість розпаралелювання PBKDF"
+
+#~ msgid "threads"
+#~ msgstr "threads"
+
+#~ msgid "PBKDF iterations cost (forced, disables benchmark)"
+#~ msgstr "Вартість ітерацій PBKDF (примусово, вимикає тестування)"
+
+#~ msgid "Keyslot priority: ignore, normal, prefer"
+#~ msgstr "Пріоритетність слотів ключів: ignore, normal, prefer"
+
+#~ msgid "Disable locking of on-disk metadata"
+#~ msgstr "Вимкнути блокування метаданих на диску"
+
+#~ msgid "Disable loading volume keys via kernel keyring"
+#~ msgstr "Вимкнути завантаження ключів тому за допомогою сховища ключів ядра"
+
+#~ msgid "Data integrity algorithm (LUKS2 only)"
+#~ msgstr "Алгоритм перевірки цілісності даних (лише LUKS2)"
+
+#~ msgid "Disable journal for integrity device"
+#~ msgstr "Вимкнути журнал для пристрою забезпечення цілісності"
+
+#~ msgid "Do not wipe device after format"
+#~ msgstr "Не витирати пристрій після форматування"
+
+#~ msgid "Use inefficient legacy padding (old kernels)"
+#~ msgstr "Скористатися неефективним застарілим відступом (застарілі ядра)"
+
+#~ msgid "Do not ask for passphrase if activation by token fails"
+#~ msgstr "Не просити ввести пароль, якщо не вдасться скористатися активацією за ключем"
+
+#~ msgid "Token number (default: any)"
+#~ msgstr "Номер ключа (типове значення: будь-який)"
+
+#~ msgid "Key description"
+#~ msgstr "Опис ключа"
+
+#~ msgid "Encryption sector size (default: 512 bytes)"
+#~ msgstr "Розмір сектора шифрування (типове значення: 512 байтів)"
+
+#~ msgid "Use IV counted in sector size (not in 512 bytes)"
+#~ msgstr "Використовувати обчислення за IV у розмірі сектора (не за блоками у 512 байтів)"
+
+#~ msgid "Set activation flags persistent for device"
+#~ msgstr "Встановити сталі прапорці активації для пристрою"
+
+#~ msgid "Set label for the LUKS2 device"
+#~ msgstr "Встановити мітку для пристрою LUKS2"
+
+#~ msgid "Set subsystem label for the LUKS2 device"
+#~ msgstr "Встановити мітку підтому для пристрою LUKS2"
+
+#~ msgid "Create or dump unbound (no assigned data segment) LUKS2 keyslot"
+#~ msgstr "Створити непов'язаний (без пов'язаного сегмента даних) слот ключів LUKS2 або його дамп"
+
+#~ msgid "Read or write the json from or to a file"
+#~ msgstr "Прочитати json з файла або записати json до файла"
+
+#~ msgid "LUKS2 header metadata area size"
+#~ msgstr "Розмір області метаданих у заголовку LUKS2"
+
+#~ msgid "LUKS2 header keyslots area size"
+#~ msgstr "Розмір області слотів ключів у заголовку LUKS2"
+
+#~ msgid "Refresh (reactivate) device with new parameters"
+#~ msgstr "Оновити (повторно активувати) пристрій згідно з новими параметрами"
+
+#~ msgid "LUKS2 keyslot: The size of the encryption key"
+#~ msgstr "Слот ключів LUKS2: розмір ключа шифрування"
+
+#~ msgid "LUKS2 keyslot: The cipher used for keyslot encryption"
+#~ msgstr "Слот ключа LUKS2: шифрування, яке використано для слоту ключів"
+
+#~ msgid "Encrypt LUKS2 device (in-place encryption)."
+#~ msgstr "Зашифрувати пристрій LUKS2 (шифрування на місці)."
+
+#~ msgid "Decrypt LUKS2 device (remove encryption)."
+#~ msgstr "Розшифрувати пристрій LUKS2 (усунути шифрування)."
+
+#~ msgid "Initialize LUKS2 reencryption in metadata only."
+#~ msgstr "Ініціалізувати повторне шифрування LUKS2 лише у метаданих."
+
+#~ msgid "Resume initialized LUKS2 reencryption only."
+#~ msgstr "Відновлювати лише ініціалізоване повторне шифрування LUKS2."
+
+#~ msgid "Reduce data device size (move data offset). DANGEROUS!"
+#~ msgstr "Зменшити розмір пристрою зберігання даних (змістити відступ даних). НЕБЕЗПЕЧНО!"
+
+#~ msgid "Maximal reencryption hotzone size."
+#~ msgstr "Максимальний розмір «гарячої» ділянки повторного шифрування."
+
+#~ msgid "Reencryption hotzone resilience type (checksum,journal,none)"
+#~ msgstr "Тип стійкості «гарячої» ділянки повторного шифрування (checksum (контрольна сума), journal (журнал), none (немає))"
+
+#~ msgid "Reencryption hotzone checksums hash"
+#~ msgstr "Хеш контрольних сум «гарячої» ділянки повторного шифрування"
+
+#~ msgid "Override device autodetection of dm device to be reencrypted"
+#~ msgstr "Перевизначити автоматично визначені параметри пристрою dm, який буде повторно зашифровано"
+
+#~ msgid "Option --deferred is allowed only for close command."
+#~ msgstr "Параметр --deferred можна використовувати лише для команди закриття (close)."
+
+#~ msgid "Option --allow-discards is allowed only for open operation."
+#~ msgstr "Параметр --shared можна використовувати лише для дії з відкриття."
+
+#~ msgid "Option --persistent is allowed only for open operation."
+#~ msgstr "Параметр --persistent можна використовувати лише для дії з відкриття."
+
+#~ msgid "Option --serialize-memory-hard-pbkdf is allowed only for open operation."
+#~ msgstr "Параметр --serialize-memory-hard-pbkdf можна використовувати лише для дії з відкриття."
+
+#~ msgid ""
+#~ "Option --key-size is allowed only for luksFormat, luksAddKey,\n"
+#~ "open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+#~ msgstr ""
+#~ "Параметр --key-size можна використовувати лише для luksFormat, luksAddKey,\n"
+#~ "дій open і benchmark. Щоб обмежити читання з файла ключа, скористайтеся параметром --keyfile-size=(об’єм у байтах)."
+
+#~ msgid "Option --integrity is allowed only for luksFormat (LUKS2)."
+#~ msgstr "Параметр --integrity можна використовувати лише для luksFormat (LUKS2)."
+
+#~ msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations."
+#~ msgstr "Параметри --label і --subsystem можна використовувати лише для дій luksFormat та config для LUKS2."
+
+#~ msgid "Negative number for option not permitted."
+#~ msgstr "Не можна використовувати від’ємні значення для параметра."
+
+#~ msgid "Option --use-[u]random is allowed only for luksFormat."
+#~ msgstr "Параметр --use-[u]random можна використовувати лише для дії luksFormat."
+
+#~ msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+#~ msgstr "Параметр --uuid можна використовувати лише для дій luksFormat і luksUUID."
+
+#~ msgid "Option --align-payload is allowed only for luksFormat."
+#~ msgstr "Параметр --align-payload можна використовувати лише для дії luksFormat."
+
+#~ msgid "Options --luks2-metadata-size and --opt-luks2-keyslots-size are allowed only for luksFormat with LUKS2."
+#~ msgstr "Параметрами --luks2-metadata-size і --opt-luks2-keyslots-size можна користуватися лише для luksFormat з LUKS2."
+
+#~ msgid "Invalid LUKS2 metadata size specification."
+#~ msgstr "Некоректна специфікація розміру метаданих LUKS2."
+
+#~ msgid "Invalid LUKS2 keyslots size specification."
+#~ msgstr "Некоректна специфікація розміру слоту ключів LUKS2."
+
+#~ msgid "Option --offset is supported only for open of plain and loopaes devices, luksFormat and device reencryption."
+#~ msgstr "Підтримку параметра --offset передбачено лише для відкриття незашифрованих пристроїв та пристроїв loopaes, luksFormat та повторного шифрування."
+
+#~ msgid "Invalid argument for parameter --veracrypt-pim supplied."
+#~ msgstr "Надано некоректний аргумент для параметра --veracrypt-pim."
+
+#~ msgid "Sector size option is not supported for this command."
+#~ msgstr "У цій команді не передбачено підтримки параметра розміру сектора."
+
+#~ msgid "Option --refresh may be used only with open action."
+#~ msgstr "Параметр --refresh можна використовувати лише під час дії з відкриття (open)."
+
+#~ msgid "Invalid device size specification."
+#~ msgstr "Некоректна специфікація розміру пристрою."
+
+#~ msgid "Reduce size overflow."
+#~ msgstr "Переповнення розміру зменшення."
+
+#~ msgid "Do not use verity superblock"
+#~ msgstr "Не використовувати суперблок verity"
+
+#~ msgid "Format type (1 - normal, 0 - original Chrome OS)"
+#~ msgstr "Тип форматування (1 — звичайне, 0 — початкове Chrome OS)"
+
+#~ msgid "number"
+#~ msgstr "номер"
+
+#~ msgid "Block size on the data device"
+#~ msgstr "Розмір блоку на пристрої даних"
+
+#~ msgid "Block size on the hash device"
+#~ msgstr "Розмір блоку на пристрої хешу"
+
+#~ msgid "FEC parity bytes"
+#~ msgstr "Байти парності FEC"
+
+#~ msgid "The number of blocks in the data file"
+#~ msgstr "Кількість блоків у файлі даних"
+
+#~ msgid "blocks"
+#~ msgstr "блоки"
+
+#~ msgid "Path to device with error correction data"
+#~ msgstr "Шлях до пристрою із даними для виправлення помилок"
+
+#~ msgid "path"
+#~ msgstr "шлях"
+
+#~ msgid "Starting offset on the hash device"
+#~ msgstr "Початковий відступ на пристрої хешу"
+
+#~ msgid "Starting offset on the FEC device"
+#~ msgstr "Початковий відступ на пристрої FEC"
+
+#~ msgid "Hash algorithm"
+#~ msgstr "Алгоритм хешування"
+
+#~ msgid "string"
+#~ msgstr "рядок"
+
+#~ msgid "Salt"
+#~ msgstr "Сіль"
+
+#~ msgid "hex string"
+#~ msgstr "шістнадцятковий рядок"
+
+#~ msgid "Path to root hash signature file"
+#~ msgstr "Шлях до файла підпису кореневого хешу"
+
+#~ msgid "Restart kernel if corruption is detected"
+#~ msgstr "Перезапустити ядро, якщо виявлено пошкодження"
+
+#~ msgid "Panic kernel if corruption is detected"
+#~ msgstr "Запустити паніку ядра, якщо виявлено пошкодження"
+
+#~ msgid "Ignore corruption, log it only"
+#~ msgstr "Ігнорувати пошкодження, лише записати повідомлення до журналу"
+
+#~ msgid "Do not verify zeroed blocks"
+#~ msgstr "Не перевіряти занулені блоки"
+
+#~ msgid "Verify data block only the first time it is read"
+#~ msgstr "Перевіряти блок даних лише під час його першого читання"
+
+#~ msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation."
+#~ msgstr "Параметри --ignore-corruption, --restart-on-corruption та --ignore-zero-blocks можна використовувати лише для дії з відкриття (open)."
+
+#~ msgid "Option --root-hash-signature can be used only for open operation."
+#~ msgstr "Параметром --root-hash-signature можна користуватися лише для дії з відкриття."
+
+#~ msgid "Path to data device (if separated)"
+#~ msgstr "Шлях до пристрою даних (якщо відокремлено)"
+
+#~ msgid "Journal size"
+#~ msgstr "Розмір журналу"
+
+#~ msgid "Interleave sectors"
+#~ msgstr "Перемежовування секторів"
+
+#~ msgid "Journal watermark"
+#~ msgstr "«Водяний знак» журналу"
+
+#~ msgid "percent"
+#~ msgstr "відсоток"
+
+#~ msgid "Journal commit time"
+#~ msgstr "Час внесення до журналу"
+
+#~ msgid "ms"
+#~ msgstr "мс"
+
+#~ msgid "Number of 512-byte sectors per bit (bitmap mode)."
+#~ msgstr "Кількість 512-байтових секторів на біт (режим бітової карти)."
+
+#~ msgid "Bitmap mode flush time"
+#~ msgstr "Час спорожнення режиму бітової карти"
+
+#~ msgid "Tag size (per-sector)"
+#~ msgstr "Розмір мітки на сектор"
+
+#~ msgid "Sector size"
+#~ msgstr "Розмір сектора"
+
+#~ msgid "Buffers size"
+#~ msgstr "Розмір буферів"
+
+#~ msgid "Data integrity algorithm"
+#~ msgstr "Алгоритм забезпечення цілісності даних"
+
+#~ msgid "The size of the data integrity key"
+#~ msgstr "Розмір ключа цілісності даних"
+
+#~ msgid "Read the integrity key from a file"
+#~ msgstr "Прочитати ключ цілісності з файла"
+
+#~ msgid "Journal integrity algorithm"
+#~ msgstr "Алгоритм забезпечення цілісності журналу"
+
+#~ msgid "The size of the journal integrity key"
+#~ msgstr "Розмір ключа цілісності журналу"
+
+#~ msgid "Read the journal integrity key from a file"
+#~ msgstr "Прочитати ключ цілісності журналу з файла"
+
+#~ msgid "Journal encryption algorithm"
+#~ msgstr "Алгоритм шифрування журналу"
+
+#~ msgid "The size of the journal encryption key"
+#~ msgstr "Розмір ключа шифрування журналу"
+
+#~ msgid "Read the journal encryption key from a file"
+#~ msgstr "Читати ключ шифрування журналу з файла"
+
+#~ msgid "Recovery mode (no journal, no tag checking)"
+#~ msgstr "Режим відновлення (без журналу, без перевірки міток)"
+
+#~ msgid "Use bitmap to track changes and disable journal for integrity device"
+#~ msgstr "Використовувати для стеження за змінами бітову карту і вимкнути журнал для пристрою забезпечення цілісності"
+
+#~ msgid "Recalculate initial tags automatically."
+#~ msgstr "Обчислювати початкові мітки автоматично."
+
+#~ msgid "Do not protect superblock with HMAC (old kernels)"
+#~ msgstr "Не захищати суперблок HMAC (застарілі ядра)"
+
+#~ msgid "Allow recalculating of volumes with HMAC keys (old kernels)"
+#~ msgstr "Дозволити повторне обчислення томів за допомогою ключів HMAC (застарілі ядра)"
+
+#~ msgid "Option --integrity-recalculate can be used only for open action."
+#~ msgstr "Параметр --integrity-recalculate можна використовувати лише під час дії з відкриття (open)."
+
+#~ msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action."
+#~ msgstr "Параметри --journal-size, --interleave-sectors, --sector-size, --tag-size та --no-wipe можна використовувати лише для дії з форматування."
+
+#~ msgid "Invalid journal size specification."
+#~ msgstr "Некоректна специфікація розміру журналу."
+
+#~ msgid "Reencryption block size"
+#~ msgstr "Розмір блоку повторного шифрування"
+
+#~ msgid "MiB"
+#~ msgstr "МіБ"
+
+#~ msgid "Do not change key, no data area reencryption"
+#~ msgstr "Не змінювати ключ, не виконувати повторного шифрування області даних"
+
+#~ msgid "Read new volume (master) key from file"
+#~ msgstr "Прочитати новий ключ тому (основний ключ) з файла"
+
+#~ msgid "Use direct-io when accessing devices"
+#~ msgstr "Використовувати безпосереднє введення-виведення під час доступу до пристроїв"
+
+#~ msgid "Use fsync after each block"
+#~ msgstr "Використовувати fsync після кожного блоку"
+
+#~ msgid "Update log file after every block"
+#~ msgstr "Оновлювати файл журналу після кожного блоку"
+
+#~ msgid "Use only this slot (others will be disabled)"
+#~ msgstr "Використовувати лише цей слот (інші буде вимкнено)"
+
+#~ msgid "Create new header on not encrypted device"
+#~ msgstr "Створити новий заголовок на незашифрованому пристрої"
+
+#~ msgid "Permanently decrypt device (remove encryption)"
+#~ msgstr "Остаточно розшифрувати пристрій (скасувати шифрування)"
+
+#~ msgid "The UUID used to resume decryption"
+#~ msgstr "UUID, що використовується для відновлення розшифровування"
+
+#~ msgid "Type of LUKS metadata: luks1, luks2"
+#~ msgstr "Тип метаданих LUKS (luks1 або luks2)"
+
+#~ msgid "WARNING: Locking directory %s/%s is missing!\n"
+#~ msgstr "ПОПЕРЕДЖЕННЯ: не вистачає блокування каталогу %s/%s!\n"
+
+#~ msgid "Invalid size parameters for verity device."
+#~ msgstr "Некоректні параметри розміру для пристрою перевірки."
+
+#~ msgid "Integrity algorithm must be specified if integrity key is used."
+#~ msgstr "Якщо використано ключ цілісності, має бути вказано алгоритм забезпечення цілісності."
+
+#~ msgid "Wrong key size."
+#~ msgstr "Помилковий розмір ключа."
diff --git a/po/vi.po b/po/vi.po
new file mode 100644
index 0000000..5656302
--- /dev/null
+++ b/po/vi.po
@@ -0,0 +1,1958 @@
+# Vietnamese translation for CryptSetup.
+# Bản dịch tiếng Việt dành cho cryptsetup.
+# Copyright © 2016 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Clytie Siddall <clytie@riverland.net.au>, 2010.
+# Trần Ngọc Quân <vnwildman@gmail.com>, 2012-2014, 2015, 2016, 2017.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 1.7.4\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2017-03-02 09:40+0100\n"
+"PO-Revision-Date: 2017-03-05 15:08+0700\n"
+"Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n"
+"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n"
+"Language: vi\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Gtranslator 2.91.7\n"
+
+#: lib/libdevmapper.c:262
+msgid "Cannot initialize device-mapper, running as non-root user.\n"
+msgstr "Không thể khởi tạo ánh-xạ-thiết-bị (device-mapper), do không chạy dưới quyền siêu người dùng.\n"
+
+#: lib/libdevmapper.c:265
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"
+msgstr ""
+"Không thể khởi tạo tiến trình ánh xạ thiết bị.\n"
+"Mô-đun hạt nhân “dm_mod” được nạp chưa?\n"
+
+#: lib/libdevmapper.c:581
+#, c-format
+msgid "DM-UUID for device %s was truncated.\n"
+msgstr "Mã số DM-UUID cho thiết bị %s bị cắt ngắn.\n"
+
+#: lib/libdevmapper.c:729
+msgid "Requested dm-crypt performance options are not supported.\n"
+msgstr "Không hỗ trợ tùy chọn hiệu năng dm-crypt đã yêu cầu.\n"
+
+#: lib/libdevmapper.c:735
+msgid "Requested dm-verity data corruption handling options are not supported.\n"
+msgstr "Không hỗ trợ tùy chọn xử lý dữ liệu sai hỏng dm-verity đã yêu cầu.\n"
+
+#: lib/random.c:80
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"Hệ thống bị nằm ngoài en-trô-pi trong khi tạo khóa vùng chứa.\n"
+"Xin hãy di chuyển con chuột hay gõ vài chữ trong cửa sổ khác để thu thập sự kiện ngẫu nhiên.\n"
+
+#: lib/random.c:84
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "Đang tạo khóa (xong %d%%).\n"
+
+#: lib/random.c:170
+msgid "Running in FIPS mode.\n"
+msgstr "Đang chạy trong chế độ FIPS.\n"
+
+#: lib/random.c:176
+msgid "Fatal error during RNG initialisation.\n"
+msgstr "Gặp lỗi nghiêm trọng trong quá trình khởi tạo RNG.\n"
+
+#: lib/random.c:213
+msgid "Unknown RNG quality requested.\n"
+msgstr "Không hiểu chất lượng RNG đã yêu cầu.\n"
+
+#: lib/random.c:218
+#, c-format
+msgid "Error %d reading from RNG: %s\n"
+msgstr "Lỗi %d khi đọc từ RNG: %s\n"
+
+#: lib/setup.c:200
+msgid "Cannot initialize crypto RNG backend.\n"
+msgstr "Không thể khởi tạo ứng dụng chạy ở phía sau (backend) mã hóa RNG.\n"
+
+#: lib/setup.c:206
+msgid "Cannot initialize crypto backend.\n"
+msgstr "Không thể khởi ứng dụng mã hóa chạy ở phía sau (backend).\n"
+
+#: lib/setup.c:237 lib/setup.c:1199 lib/verity/verity.c:123
+#, c-format
+msgid "Hash algorithm %s not supported.\n"
+msgstr "Thuật toán băm %s không được hỗ trợ.\n"
+
+#: lib/setup.c:240 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s).\n"
+msgstr "Lỗi xử lý khóa (dùng mã băm %s).\n"
+
+#: lib/setup.c:285
+msgid "Cannot determine device type. Incompatible activation of device?\n"
+msgstr "Không thể dò tìm kiểu thiết bị. Phần hoạt hóa của thiết bị không tương thích à?\n"
+
+#: lib/setup.c:289 lib/setup.c:1552
+msgid "This operation is supported only for LUKS device.\n"
+msgstr "Thao tác này được hỗ trợ chỉ cho thiết bị LUKS.\n"
+
+#: lib/setup.c:321
+msgid "All key slots full.\n"
+msgstr "Mọi khe khóa đều đã đầy.\n"
+
+#: lib/setup.c:328
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d.\n"
+msgstr "Khe khóa %d không đúng, hãy chọn một giá trị trong phạm vi từ 0 đến %d.\n"
+
+#: lib/setup.c:334
+#, c-format
+msgid "Key slot %d is full, please select another one.\n"
+msgstr "Khe khóa %d bị đầy, hãy chọn một khe khác.\n"
+
+#: lib/setup.c:473
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "Nhập cụm từ mật khẩu cho %s: "
+
+#: lib/setup.c:654
+#, c-format
+msgid "Header detected but device %s is too small.\n"
+msgstr "Phát hiện được phần đầu nhưng mà thiết bị %s quá nhỏ.\n"
+
+#: lib/setup.c:670 lib/setup.c:1435
+msgid "This operation is not supported for this device type.\n"
+msgstr "Thao tác này không được hỗ trợ cho kiểu thiết bị này.\n"
+
+#: lib/setup.c:909 lib/setup.c:1388 lib/setup.c:2279
+#, c-format
+msgid "Device %s is not active.\n"
+msgstr "Thiết bị %s không hoạt động.\n"
+
+#: lib/setup.c:926
+#, c-format
+msgid "Underlying device for crypt device %s disappeared.\n"
+msgstr "Thiết bị nằm dưới cho thiết bị crypt %s đã bị biến mất.\n"
+
+#: lib/setup.c:995
+msgid "Invalid plain crypt parameters.\n"
+msgstr "Đặt sai tham số mã hóa bình thường.\n"
+
+#: lib/setup.c:1000 lib/setup.c:1120
+msgid "Invalid key size.\n"
+msgstr "Kích cỡ khóa không đúng.\n"
+
+#: lib/setup.c:1005 lib/setup.c:1125
+msgid "UUID is not supported for this crypt type.\n"
+msgstr "UUID không hỗ trợ kiểu mã hóa này.\n"
+
+#: lib/setup.c:1047
+msgid "Can't format LUKS without device.\n"
+msgstr "Không thể định dạng “LUKS” mà không có thiết bị.\n"
+
+#: lib/setup.c:1090
+#, c-format
+msgid "Cannot format device %s which is still in use.\n"
+msgstr "Không thể định dạng thiết bị %s mà nó lại vẫn đang được sử dụng.\n"
+
+#: lib/setup.c:1093
+#, c-format
+msgid "Cannot format device %s, permission denied.\n"
+msgstr "Không thể định dạng thiết bị %s, không đủ thẩm quyền.\n"
+
+#: lib/setup.c:1097
+#, c-format
+msgid "Cannot wipe header on device %s.\n"
+msgstr "Không thể tẩy xóa phần đầu trên thiết bị %s.\n"
+
+#: lib/setup.c:1115
+msgid "Can't format LOOPAES without device.\n"
+msgstr "Không thể định dạng “LOOPAES” bên ngoài thiết bị.\n"
+
+#: lib/setup.c:1153
+msgid "Can't format VERITY without device.\n"
+msgstr "Không thể định dạng “VERITY” mà không có thiết bị.\n"
+
+#: lib/setup.c:1161 lib/verity/verity.c:106
+#, c-format
+msgid "Unsupported VERITY hash type %d.\n"
+msgstr "Kiểu băm “VERITY” %d không được hỗ trợ.\n"
+
+#: lib/setup.c:1167 lib/verity/verity.c:114
+msgid "Unsupported VERITY block size.\n"
+msgstr "Kích thước khối “VERITY” không được hỗ trợ.\n"
+
+#: lib/setup.c:1172 lib/verity/verity.c:76
+msgid "Unsupported VERITY hash offset.\n"
+msgstr "Khoảng bù (offset) mã băm “VERITY” không được hỗ trợ.\n"
+
+#: lib/setup.c:1193
+msgid "Data area overlaps with hash area.\n"
+msgstr "Vùng dữ liệu chồng lấn với vùng mã băm.\n"
+
+#: lib/setup.c:1292
+#, c-format
+msgid "Unknown crypt device type %s requested.\n"
+msgstr "Không rõ kiểu thiết bị mã hóa %s được yêu cầu.\n"
+
+#: lib/setup.c:1402
+msgid "Cannot resize loop device.\n"
+msgstr "Không thể đổi cỡ thiết bị vòng ngược (loopback).\n"
+
+#: lib/setup.c:1450
+msgid "Do you really want to change UUID of device?"
+msgstr "Bạn có thực sự muốn thay đổi UUID cho thiết bị?"
+
+#: lib/setup.c:1560
+#, c-format
+msgid "Volume %s is not active.\n"
+msgstr "Khối tin %s không hoạt động.\n"
+
+#: lib/setup.c:1571
+#, c-format
+msgid "Volume %s is already suspended.\n"
+msgstr "Khối %s đã bị ngưng.\n"
+
+#: lib/setup.c:1578
+#, c-format
+msgid "Suspend is not supported for device %s.\n"
+msgstr "Tạm dừng không được hỗ trợ cho kiểu thiết bị %s.\n"
+
+#: lib/setup.c:1580
+#, c-format
+msgid "Error during suspending device %s.\n"
+msgstr "Gặp lỗi khi tạm dừng thiết bị %s.\n"
+
+#: lib/setup.c:1606 lib/setup.c:1653
+#, c-format
+msgid "Volume %s is not suspended.\n"
+msgstr "Vùng %s không bị treo.\n"
+
+#: lib/setup.c:1620
+#, c-format
+msgid "Resume is not supported for device %s.\n"
+msgstr "Thao tác phục hồi không được hỗ trợ cho kiểu thiết bị %s.\n"
+
+#: lib/setup.c:1622 lib/setup.c:1674
+#, c-format
+msgid "Error during resuming device %s.\n"
+msgstr "Gặp lỗi khi cho hoạt động trở lại thiết bị %s.\n"
+
+#: lib/setup.c:1660 lib/setup.c:2095 lib/setup.c:2109 src/cryptsetup.c:184
+#: src/cryptsetup.c:248 src/cryptsetup.c:736 src/cryptsetup.c:1171
+msgid "Enter passphrase: "
+msgstr "Gõ cụm từ mật khẩu: "
+
+#: lib/setup.c:1722 lib/setup.c:1858
+msgid "Cannot add key slot, all slots disabled and no volume key provided.\n"
+msgstr "Không thể thêm khe khóa vì mọi khe đều bị tắt và không cung cấp khóa khối tin.\n"
+
+#: lib/setup.c:1731 lib/setup.c:1864 lib/setup.c:1868
+msgid "Enter any passphrase: "
+msgstr "Nhập bất cứ cụm từ mật khẩu nào: "
+
+#: lib/setup.c:1748 lib/setup.c:1881 lib/setup.c:1885 lib/setup.c:1947
+#: src/cryptsetup.c:1001 src/cryptsetup.c:1032
+msgid "Enter new passphrase for key slot: "
+msgstr "Gõ cụm từ mật khẩu mới cho khe khóa: "
+
+#: lib/setup.c:1813
+#, c-format
+msgid "Key slot %d changed.\n"
+msgstr "Khe khóa %d đã thay đổi.\n"
+
+#: lib/setup.c:1816
+#, c-format
+msgid "Replaced with key slot %d.\n"
+msgstr "Đã thay thế với khe khóa %d.\n"
+
+#: lib/setup.c:1821
+msgid "Failed to swap new key slot.\n"
+msgstr "Gặp lỗi khi hoán đổi khe khóa mới.\n"
+
+#: lib/setup.c:1938 lib/setup.c:2199 lib/setup.c:2212 lib/setup.c:2354
+msgid "Volume key does not match the volume.\n"
+msgstr "Khóa khối tin không tương ứng với khối tin đó.\n"
+
+#: lib/setup.c:1976
+#, c-format
+msgid "Key slot %d is invalid.\n"
+msgstr "Khe khóa %d không đúng.\n"
+
+#: lib/setup.c:1981
+#, c-format
+msgid "Key slot %d is not used.\n"
+msgstr "Khe khóa %d không được dùng.\n"
+
+#: lib/setup.c:2011 lib/setup.c:2083 lib/setup.c:2175
+#, c-format
+msgid "Device %s already exists.\n"
+msgstr "Thiết bị %s đã sẵn có.\n"
+
+#: lib/setup.c:2186
+msgid "Incorrect volume key specified for plain device.\n"
+msgstr "Khóa vùng chứa đã chỉ định không đúng cho thiết bị thường.\n"
+
+#: lib/setup.c:2219
+msgid "Incorrect root hash specified for verity device.\n"
+msgstr "Mã băm gốc đã chỉ định không đúng cho thiết bị chứng thực (verity).\n"
+
+#: lib/setup.c:2242
+msgid "Device type is not properly initialised.\n"
+msgstr "Kiểu thiết bị gần như chắc chắn là chưa được thiết lập.\n"
+
+#: lib/setup.c:2274
+#, c-format
+msgid "Device %s is still in use.\n"
+msgstr "Thiết bị %s vẫn đang được sử dụng.\n"
+
+#: lib/setup.c:2283
+#, c-format
+msgid "Invalid device %s.\n"
+msgstr "Thiết bị không đúng %s.\n"
+
+#: lib/setup.c:2304
+msgid "Function not available in FIPS mode.\n"
+msgstr "Chức năng không khả dụng trong chế độ “FIPS”.\n"
+
+#: lib/setup.c:2310
+msgid "Volume key buffer too small.\n"
+msgstr "Vùng đệm khóa khối tin quá nhỏ.\n"
+
+#: lib/setup.c:2318
+msgid "Cannot retrieve volume key for plain device.\n"
+msgstr "Không thể lấy khóa khối tin cho thiết bị bình thường.\n"
+
+#: lib/setup.c:2325
+#, c-format
+msgid "This operation is not supported for %s crypt device.\n"
+msgstr "Thao tác này không được hỗ trợ cho thiết bị mã hóa %s.\n"
+
+#: lib/setup.c:2521
+msgid "Dump operation is not supported for this device type.\n"
+msgstr "Thao tác đổ đống (dump) không được hỗ trợ cho kiểu thiết bị này.\n"
+
+#: lib/utils.c:244
+msgid "Cannot get process priority.\n"
+msgstr "Không thể lấy mức ưu tiên của tiến trình.\n"
+
+#: lib/utils.c:258
+msgid "Cannot unlock memory.\n"
+msgstr "Không thể mở khóa bộ nhớ.\n"
+
+#: lib/utils_crypt.c:242 lib/utils_crypt.c:255 lib/utils_crypt.c:402
+#: lib/utils_crypt.c:417
+msgid "Out of memory while reading passphrase.\n"
+msgstr "Tràn bộ nhớ trong khi đọc cụm từ mật khẩu.\n"
+
+#: lib/utils_crypt.c:247 lib/utils_crypt.c:262
+msgid "Error reading passphrase from terminal.\n"
+msgstr "Gặp lỗi khi đọc cụm từ mật khẩu từ thiết bị cuối.\n"
+
+#: lib/utils_crypt.c:260
+msgid "Verify passphrase: "
+msgstr "Nhập lại mật khẩu: "
+
+#: lib/utils_crypt.c:267
+msgid "Passphrases do not match.\n"
+msgstr "Hai cụm từ mật khẩu không trùng nhau.\n"
+
+#: lib/utils_crypt.c:351
+msgid "Cannot use offset with terminal input.\n"
+msgstr "Không thể sử dụng khoảng bù (offset) với đầu vào là thiết bị cuối.\n"
+
+#: lib/utils_crypt.c:370 lib/tcrypt/tcrypt.c:468
+msgid "Failed to open key file.\n"
+msgstr "Gặp lỗi khi mở tập tin khóa.\n"
+
+#: lib/utils_crypt.c:379
+msgid "Failed to stat key file.\n"
+msgstr "Gặp lỗi khi lấy thông tin tập tin khóa.\n"
+
+#: lib/utils_crypt.c:387 lib/utils_crypt.c:408
+msgid "Cannot seek to requested keyfile offset.\n"
+msgstr "Không thể di chuyển vị trí đầu đọc tới vị trí tương đối (offset) tập tin khóa đã yêu cầu.\n"
+
+#: lib/utils_crypt.c:425
+msgid "Error reading passphrase.\n"
+msgstr "Lỗi đọc cụm từ mật khẩu.\n"
+
+#: lib/utils_crypt.c:448
+msgid "Maximum keyfile size exceeded.\n"
+msgstr "Đã vượt quá kích thước tập tin khóa tối đa.\n"
+
+#: lib/utils_crypt.c:453
+msgid "Cannot read requested amount of data.\n"
+msgstr "Không thể đọc đống dữ liệu đã yêu cầu.\n"
+
+#: lib/utils_device.c:138 lib/luks1/keyencryption.c:90
+#, c-format
+msgid "Device %s doesn't exist or access denied.\n"
+msgstr "Thiết bị %s không tồn tại hoặc không đủ quyền truy cập.\n"
+
+#: lib/utils_device.c:429
+msgid "Cannot use a loopback device, running as non-root user.\n"
+msgstr "Không thể sử dụng thiết-bị vòng ngược (loopback), do không chạy dưới quyền siêu người dùng.\n"
+
+#: lib/utils_device.c:439
+msgid "Attaching loopback device failed (loop device with autoclear flag is required).\n"
+msgstr "Gặp lỗi khi gắn thiết bị vòng ngược (loopback) (thiết bị lặp với cờ autoclear là bắt buộc).\n"
+
+#: lib/utils_device.c:483
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted).\n"
+msgstr "Không thể sử dụng thiết bị %s mà nó lại đang được sử dụng (đang được ánh xạ hoặc gắn).\n"
+
+#: lib/utils_device.c:487
+#, c-format
+msgid "Cannot get info about device %s.\n"
+msgstr "Không thể lấy thông tin về thiết bị %s.\n"
+
+#: lib/utils_device.c:493
+#, c-format
+msgid "Requested offset is beyond real size of device %s.\n"
+msgstr "Khoảng bù (offset) đã yêu cầu nằm ngoài kích thước thật của thiết bị %s.\n"
+
+#: lib/utils_device.c:501
+#, c-format
+msgid "Device %s has zero size.\n"
+msgstr "Thiết bị %s có kích cỡ là không.\n"
+
+#: lib/utils_device.c:512
+#, c-format
+msgid "Device %s is too small.\n"
+msgstr "Thiết bị %s có kích cỡ quá nhỏ.\n"
+
+#: lib/luks1/keyencryption.c:37
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info).\n"
+msgstr ""
+"Gặp lỗi khi cài đặt ánh xạ khóa dm-crypt cho thiết bị %s.\n"
+"Kiểm tra lại hạt nhân hỗ trợ mật mã %s (kiểu tra sổ theo dõi hệ thống để tìm thêm thông tin.)\n"
+
+#: lib/luks1/keyencryption.c:42
+msgid "Key size in XTS mode must be 256 or 512 bits.\n"
+msgstr "Kích thước khóa trong chế độ “XTS” phải là 256 hay 512 bit.\n"
+
+#: lib/luks1/keyencryption.c:96 lib/luks1/keymanage.c:296
+#: lib/luks1/keymanage.c:583 lib/luks1/keymanage.c:1033
+#, c-format
+msgid "Cannot write to device %s, permission denied.\n"
+msgstr "Không thể ghi thiết bị %s, không đủ thẩm quyền.\n"
+
+#: lib/luks1/keyencryption.c:111
+msgid "Failed to open temporary keystore device.\n"
+msgstr "Gặp lỗi khi mở thiết bị lưu trữ khóa tạm thời.\n"
+
+#: lib/luks1/keyencryption.c:118
+msgid "Failed to access temporary keystore device.\n"
+msgstr "Gl khi truy cập đến thiết bị lưu trữ khóa tạm thời.\n"
+
+#: lib/luks1/keyencryption.c:191
+msgid "IO error while encrypting keyslot.\n"
+msgstr "Lỗi IO (vào/ra) trong quá trình mã hóa khe khóa.\n"
+
+#: lib/luks1/keyencryption.c:256
+msgid "IO error while decrypting keyslot.\n"
+msgstr "Lỗi IO (vào/ra) trong quá trình giải mã khe khóa.\n"
+
+#: lib/luks1/keymanage.c:90
+#, c-format
+msgid "Device %s is too small. (LUKS requires at least %<PRIu64> bytes.)\n"
+msgstr "Thiết bị %s quá nhỏ. (LUKS cần ít nhất %<PRIu64> byte.)\n"
+
+#: lib/luks1/keymanage.c:180 lib/luks1/keymanage.c:419
+#: src/cryptsetup_reencrypt.c:1152
+#, c-format
+msgid "Device %s is not a valid LUKS device.\n"
+msgstr "Thiết bị %s không phải là một thiết bị kiểu LUKS đúng.\n"
+
+#: lib/luks1/keymanage.c:198
+#, c-format
+msgid "Requested header backup file %s already exists.\n"
+msgstr "Phần đầu tập tin sao lưu dự phòng đã yêu cầu %s đã sẵn có.\n"
+
+#: lib/luks1/keymanage.c:200
+#, c-format
+msgid "Cannot create header backup file %s.\n"
+msgstr "Không thể tạo phần đầu của tập tin sao lưu dự phòng %s.\n"
+
+#: lib/luks1/keymanage.c:205
+#, c-format
+msgid "Cannot write header backup file %s.\n"
+msgstr "Không thể ghi tập tin sao lưu phần đầu %s.\n"
+
+#: lib/luks1/keymanage.c:238
+msgid "Backup file doesn't contain valid LUKS header.\n"
+msgstr "Tập tin sao lưu không chứa phần đầu LUKS hợp lệ.\n"
+
+#: lib/luks1/keymanage.c:251 lib/luks1/keymanage.c:497
+#, c-format
+msgid "Cannot open header backup file %s.\n"
+msgstr "Không mở được tập tin sao lưu phần đầu %s.\n"
+
+#: lib/luks1/keymanage.c:257
+#, c-format
+msgid "Cannot read header backup file %s.\n"
+msgstr "Không đọc được tập tin sao lưu phần đầu %s.\n"
+
+#: lib/luks1/keymanage.c:269
+msgid "Data offset or key size differs on device and backup, restore failed.\n"
+msgstr "Khoảng bù dữ liệu hoặc kích cỡ khóa vẫn khác nhau trên thiết bị và bản sao lưu thì chức năng phục hồi bị lỗi.\n"
+
+#: lib/luks1/keymanage.c:277
+#, c-format
+msgid "Device %s %s%s"
+msgstr "Thiết bị %s %s%s"
+
+#: lib/luks1/keymanage.c:278
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "không chứa phần đầu LUKS. Thay thế phần đầu thì cũng có thể hủy dữ liệu trên thiết bị đó."
+
+#: lib/luks1/keymanage.c:279
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "đã chứa phần đầu LUKS. Thay thế phần đầu thì cũng hủy các khe khóa đã có."
+
+#: lib/luks1/keymanage.c:280
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"CẢNH BÁO: phần đầu thiết bị thật có mã số “UUID” khác với bản sao lưu!"
+
+#: lib/luks1/keymanage.c:299 lib/luks1/keymanage.c:536
+#: lib/luks1/keymanage.c:586 lib/tcrypt/tcrypt.c:625 lib/verity/verity.c:82
+#: lib/verity/verity.c:180 lib/verity/verity_hash.c:292
+#: lib/verity/verity_hash.c:303 lib/verity/verity_hash.c:323
+#: src/cryptsetup_reencrypt.c:154
+#, c-format
+msgid "Cannot open device %s.\n"
+msgstr "Không thể mở thiết bị %s.\n"
+
+#: lib/luks1/keymanage.c:330
+msgid "Non standard key size, manual repair required.\n"
+msgstr "Kích thước khóa không tiêu chuẩn, yêu cầu sửa chữa bằng tay.\n"
+
+#: lib/luks1/keymanage.c:335
+msgid "Non standard keyslots alignment, manual repair required.\n"
+msgstr "Không thể đồng chỉnh các khe khóa (keyslot) tiêu chuẩn, yêu cầu sửa chữa bằng tay.\n"
+
+#: lib/luks1/keymanage.c:341
+msgid "Repairing keyslots.\n"
+msgstr "Đang chuẩn bị các khe khóa (keyslots).\n"
+
+#: lib/luks1/keymanage.c:352
+msgid "Repair failed."
+msgstr "Gặp lỗi khi sửa chữa."
+
+#: lib/luks1/keymanage.c:364
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u).\n"
+msgstr "Khe-khóa (keyslot) %i: khoảng bù (offset) được sửa chữa (%u -> %u).\n"
+
+#: lib/luks1/keymanage.c:372
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u).\n"
+msgstr "Khe-khóa (keyslot) %i: stripes được sửa chữa (%u -> %u).\n"
+
+#: lib/luks1/keymanage.c:381
+#, c-format
+msgid "Keyslot %i: bogus partition signature.\n"
+msgstr "Khe-khóa (keyslot) %i: chữ ký phân vùng không có thật.\n"
+
+#: lib/luks1/keymanage.c:386
+#, c-format
+msgid "Keyslot %i: salt wiped.\n"
+msgstr "Khe-khóa (keyslot) %i: muối bị tẩy xóa.\n"
+
+#: lib/luks1/keymanage.c:397
+msgid "Writing LUKS header to disk.\n"
+msgstr "Đang ghi phần đầu của LUKS lên đĩa.\n"
+
+#: lib/luks1/keymanage.c:422
+#, c-format
+msgid "Unsupported LUKS version %d.\n"
+msgstr "Phiên bản LUKS không được hỗ trợ %d.\n"
+
+#: lib/luks1/keymanage.c:428 lib/luks1/keymanage.c:672
+#, c-format
+msgid "Requested LUKS hash %s is not supported.\n"
+msgstr "Không hỗ trợ chuỗi duy nhất LUKS %s được yêu cầu.\n"
+
+#: lib/luks1/keymanage.c:443
+#, c-format
+msgid "LUKS keyslot %u is invalid.\n"
+msgstr "khe-khóa LUKS %u là không hợp lệ.\n"
+
+#: lib/luks1/keymanage.c:457 src/cryptsetup.c:668
+msgid "No known problems detected for LUKS header.\n"
+msgstr "Không phát hiện thấy vấn đề với phần đầu LUKS.\n"
+
+#: lib/luks1/keymanage.c:607
+#, c-format
+msgid "Error during update of LUKS header on device %s.\n"
+msgstr "Gặp lỗi trong khi cập nhật phần đầu LUKS trên thiết bị %s.\n"
+
+#: lib/luks1/keymanage.c:614
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s.\n"
+msgstr "Gặp lỗi trong khi đọc lại phần đầu LUKS sau khi cập nhật trên thiết bị %s.\n"
+
+#: lib/luks1/keymanage.c:665
+#, c-format
+msgid "Data offset for detached LUKS header must be either 0 or higher than header size (%d sectors).\n"
+msgstr "Khoảng bù dữ liệu cho phần đầu LUKS tách rời phải hoặc là 0 hoặc là lớn hơn kích thước phần đầu (%d cung từ).\n"
+
+#: lib/luks1/keymanage.c:677 lib/luks1/keymanage.c:768
+msgid "Wrong LUKS UUID format provided.\n"
+msgstr "Đưa ra định dạng mã số UUID LUKS không đúng.\n"
+
+#: lib/luks1/keymanage.c:706
+msgid "Cannot create LUKS header: reading random salt failed.\n"
+msgstr "Không thể tạo phần đầu LUKS: lỗi đọc salt ngẫu nhiên.\n"
+
+#: lib/luks1/keymanage.c:713 lib/luks1/keymanage.c:809
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s).\n"
+msgstr "Gặp các tùy chọn PBKDF2 không tương thích (dùng thuật toán chuỗi duy nhất %s).\n"
+
+#: lib/luks1/keymanage.c:728
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s).\n"
+msgstr "Không thể tạo phần đầu LUKS: lỗi tạo bản tóm tắt (dùng chuỗi duy nhất %s).\n"
+
+#: lib/luks1/keymanage.c:793
+#, c-format
+msgid "Key slot %d active, purge first.\n"
+msgstr "Khe khóa %d vẫn hoạt động: cần tẩy trước.\n"
+
+#: lib/luks1/keymanage.c:799
+#, c-format
+msgid "Key slot %d material includes too few stripes. Header manipulation?\n"
+msgstr "Nguyên liệu khe khóa %d gồm có quá ít sọc. Có nên thao tác phần đầu không?\n"
+
+#: lib/luks1/keymanage.c:966
+#, c-format
+msgid "Key slot %d unlocked.\n"
+msgstr "Khe khóa %d được mở khóa.\n"
+
+#: lib/luks1/keymanage.c:1001 src/cryptsetup.c:867
+#: src/cryptsetup_reencrypt.c:1041 src/cryptsetup_reencrypt.c:1078
+msgid "No key available with this passphrase.\n"
+msgstr "Không có khóa sẵn sàng dùng với cụm từ mật khẩu này.\n"
+
+#: lib/luks1/keymanage.c:1019
+#, c-format
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d.\n"
+msgstr "Khe khóa %d không đúng: hãy chọn khe khóa trong phạm vi 0 đến %d.\n"
+
+#: lib/luks1/keymanage.c:1037
+#, c-format
+msgid "Cannot wipe device %s.\n"
+msgstr "Không thể tẩy thiết bị %s.\n"
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile.\n"
+msgstr "Tìm thấy tập tin khóa mã hóa GPG vẫn chưa được hỗ trợ.\n"
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "Hãy dùng gpg --decrypt <TẬP-TIN-KHÓA> | cryptsetup --keyfile=- …\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected.\n"
+msgstr "Tập tin khóa (keyfile) loop-AES không tương thích được tìm thấy.\n"
+
+#: lib/loopaes/loopaes.c:244
+msgid "Kernel doesn't support loop-AES compatible mapping.\n"
+msgstr "Nhân không hỗ trợ ánh xạ tương thích loop-AES.\n"
+
+#: lib/tcrypt/tcrypt.c:476
+#, c-format
+msgid "Error reading keyfile %s.\n"
+msgstr "Gặp lỗi khi đọc tập-tin khóa %s.\n"
+
+#: lib/tcrypt/tcrypt.c:514
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%d) exceeded.\n"
+msgstr "Độ dài cụm từ mật khẩu TCRYPT tối đa (%d) đã bị vượt quá.\n"
+
+#: lib/tcrypt/tcrypt.c:544
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping.\n"
+msgstr "Thuật toán băm PBKDF2 không khả dụng %s, bỏ qua.\n"
+
+#: lib/tcrypt/tcrypt.c:562 src/cryptsetup.c:621
+msgid "Required kernel crypto interface not available.\n"
+msgstr "Giao diện mã hóa từ nhân đã yêu cầu không khả dụng.\n"
+
+#: lib/tcrypt/tcrypt.c:564 src/cryptsetup.c:623
+msgid "Ensure you have algif_skcipher kernel module loaded.\n"
+msgstr "Bạn cần chắc chắn là mô-đun nhân algif_skcipher đã được tải.\n"
+
+#: lib/tcrypt/tcrypt.c:708
+#, c-format
+msgid "Activation is not supported for %d sector size.\n"
+msgstr "Hoạt hóa không được hỗ trợ cho kích thước cung %d.\n"
+
+#: lib/tcrypt/tcrypt.c:714
+msgid "Kernel doesn't support activation for this TCRYPT legacy mode.\n"
+msgstr "Nhân không hỗ trợ hoạt hóa cho chế độ cũ của TCRYPT.\n"
+
+#: lib/tcrypt/tcrypt.c:748
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s.\n"
+msgstr "Đang kích hoạt mã hóa hệ thống TCRYPT cho phân vùng %s.\n"
+
+#: lib/tcrypt/tcrypt.c:815
+msgid "Kernel doesn't support TCRYPT compatible mapping.\n"
+msgstr "Nhân không hỗ trợ ánh xạ tương thích TCRYPT.\n"
+
+#: lib/tcrypt/tcrypt.c:1030
+msgid "This function is not supported without TCRYPT header load."
+msgstr "Chức năng này không được hỗ trợ mà không có phần tải đầu TCRYPT."
+
+#: lib/verity/verity.c:70 lib/verity/verity.c:173
+#, c-format
+msgid "Verity device %s doesn't use on-disk header.\n"
+msgstr "Thiết bị xác thực %s không sử dụng phần đầu on-disk.\n"
+
+#: lib/verity/verity.c:94
+#, c-format
+msgid "Device %s is not a valid VERITY device.\n"
+msgstr "Thiết bị %s không phải là thiết bị VERITY thích hợp.\n"
+
+#: lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY version %d.\n"
+msgstr "Không hỗ trợ phiên bản VERITY %d.\n"
+
+#: lib/verity/verity.c:131
+msgid "VERITY header corrupted.\n"
+msgstr "phần đầu VERITY sai hỏng.\n"
+
+#: lib/verity/verity.c:167
+#, c-format
+msgid "Wrong VERITY UUID format provided on device %s.\n"
+msgstr "Đưa ra định dạng mã số VERITY không đúng trên thiết bị %s.\n"
+
+#: lib/verity/verity.c:199
+#, c-format
+msgid "Error during update of verity header on device %s.\n"
+msgstr "Gặp lỗi trong khi cập nhật phần đầu xác thực trên thiết bị %s.\n"
+
+#: lib/verity/verity.c:279
+msgid "Kernel doesn't support dm-verity mapping.\n"
+msgstr "Nhân không hỗ trợ ánh xạ dm-verity.\n"
+
+#: lib/verity/verity.c:290
+msgid "Verity device detected corruption after activation.\n"
+msgstr "Thiết bị xác thực đã được phát hiện sai hỏng sau khi hoạt hóa.\n"
+
+#: lib/verity/verity_hash.c:59
+#, c-format
+msgid "Spare area is not zeroed at position %<PRIu64>.\n"
+msgstr "Vùng để dành không được điền đầy bằng số không tại vị trí %<PRIu64>.\n"
+
+#: lib/verity/verity_hash.c:121 lib/verity/verity_hash.c:249
+#: lib/verity/verity_hash.c:277 lib/verity/verity_hash.c:284
+msgid "Device offset overflow.\n"
+msgstr "Khoảng bù (offset) thiết bị bị tràn.\n"
+
+#: lib/verity/verity_hash.c:161
+#, c-format
+msgid "Verification failed at position %<PRIu64>.\n"
+msgstr "Thẩm tra gặp lỗi tại vị trí %<PRIu64>.\n"
+
+#: lib/verity/verity_hash.c:235
+msgid "Invalid size parameters for verity device.\n"
+msgstr "Các tham số kích thước cho thiết bị xác thực không hợp lệ.\n"
+
+#: lib/verity/verity_hash.c:266
+msgid "Too many tree levels for verity volume.\n"
+msgstr "Có quá nhiều mức cây cho mỗi vùng xác thực.\n"
+
+#: lib/verity/verity_hash.c:354
+msgid "Verification of data area failed.\n"
+msgstr "Việc thẩm tra vùng dữ liệu gặp lỗi.\n"
+
+#: lib/verity/verity_hash.c:359
+msgid "Verification of root hash failed.\n"
+msgstr "Việc thẩm tra mã băm gốc gặp lỗi.\n"
+
+#: lib/verity/verity_hash.c:365
+msgid "Input/output error while creating hash area.\n"
+msgstr "Lỗi Vào/Ra trong khi đang tạo vùng băm.\n"
+
+#: lib/verity/verity_hash.c:367
+msgid "Creation of hash area failed.\n"
+msgstr "Việc tạo vùng dữ liệu băm gặp lỗi.\n"
+
+#: lib/verity/verity_hash.c:414
+#, c-format
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u).\n"
+msgstr "CẢNH BÁO: Nhân (kernel) không thể kích hoạt thiết bị nếu kích thước khối dữ liệu vượt quá kích cỡ trang (%u).\n"
+
+#: src/cryptsetup.c:92
+msgid "Can't do passphrase verification on non-tty inputs.\n"
+msgstr "Không thể thẩm tra cụm từ mật khẩu trên đầu vào khác TTY.\n"
+
+#: src/cryptsetup.c:133 src/cryptsetup.c:564 src/cryptsetup.c:711
+#: src/cryptsetup_reencrypt.c:524 src/cryptsetup_reencrypt.c:578
+msgid "No known cipher specification pattern detected.\n"
+msgstr "Không phát hiện mẫu đặc tả mã hóa đã biết.\n"
+
+#: src/cryptsetup.c:141
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "CẢNH BÁO: Tham số --hash bị bỏ qua trong chế độ thường với tập tin khóa đã cho.\n"
+
+#: src/cryptsetup.c:149
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "CẢNH BÁO: Đang bỏ qua các tùy chọn kích thước tập-tin-khóa --keyfile-size --, kích thước đọc giống với kích thước khóa mã hóa.\n"
+
+#: src/cryptsetup.c:215
+msgid "Option --key-file is required.\n"
+msgstr "Cần tùy chọn “--key-file”.\n"
+
+#: src/cryptsetup.c:267
+msgid "No device header detected with this passphrase.\n"
+msgstr "Không có phần đầu thiết bị cho cụm từ mật khẩu này.\n"
+
+#: src/cryptsetup.c:327 src/cryptsetup.c:1160
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+"Đổ đống phần đầu với khóa vùng chứa là thông tin phân biệt hoa thường\n"
+"cái mà cho phép truy cập phân vùng được mã hóa mà không cần mật khẩu.\n"
+"Việc đổ đống này nên luôn được lưu trữ mã hóa tại một nơi an toàn."
+
+#: src/cryptsetup.c:517
+msgid "Result of benchmark is not reliable.\n"
+msgstr "Kết quả đo kiểm không đáng tin cậy.\n"
+
+#: src/cryptsetup.c:558
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# Các kiểm tra là chỉ ước lượng việc sử dụng bộ nhớ (không tính IO ổ đĩa).\n"
+
+#: src/cryptsetup.c:583 src/cryptsetup.c:605
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# Thuật toán| Khóa| Mã hóa | Giải mã\n"
+
+#: src/cryptsetup.c:587
+#, c-format
+msgid "Cipher %s is not available.\n"
+msgstr "Mã hóa kiểu %s không sẵn có.\n"
+
+#: src/cryptsetup.c:614
+msgid "N/A"
+msgstr "N/A"
+
+#: src/cryptsetup.c:639
+#, c-format
+msgid "Cannot read keyfile %s.\n"
+msgstr "Không thể đọc tập-tin khóa %s.\n"
+
+#: src/cryptsetup.c:643
+#, c-format
+msgid "Cannot read %d bytes from keyfile %s.\n"
+msgstr "Không thể đọc %d byte từ tập tin khóa %s.\n"
+
+#: src/cryptsetup.c:672
+msgid "Really try to repair LUKS device header?"
+msgstr "Bạn có thực sự muốn thử sửa chữa phần đầu thiết bị LUKS không?"
+
+#: src/cryptsetup.c:697
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "Thao tác này sẽ ghi đè lên dữ liệu trên thiết bị %s một cách không phục hồi được."
+
+#: src/cryptsetup.c:699
+msgid "memory allocation error in action_luksFormat"
+msgstr "gặp lỗi phân cấp vùng nhớ trong“action_luksFormat”"
+
+#: src/cryptsetup.c:721
+#, c-format
+msgid "Cannot use %s as on-disk header.\n"
+msgstr "Không thể sử dụng %s như là phần đầu on-disk.\n"
+
+#: src/cryptsetup.c:788
+msgid "Reduced data offset is allowed only for detached LUKS header.\n"
+msgstr "Giảm khoảng bù (offset) dữ liệu chỉ cho phép khi phần đầu LUKS được tách rời.\n"
+
+#: src/cryptsetup.c:890 src/cryptsetup.c:946
+#, c-format
+msgid "Key slot %d selected for deletion.\n"
+msgstr "Khe khóa %d đã được chọn để xóa.\n"
+
+#: src/cryptsetup.c:893
+#, c-format
+msgid "Key %d not active. Can't wipe.\n"
+msgstr "Khóa %d không hoạt động thì không xóa được.\n"
+
+#: src/cryptsetup.c:901 src/cryptsetup.c:949
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "Đây là khe khóa cuối cùng. Sau khi tẩy khóa này thì thiết bị không dùng được."
+
+#: src/cryptsetup.c:902
+msgid "Enter any remaining passphrase: "
+msgstr "Gõ cụm từ mật khẩu bất kỳ còn lại: "
+
+#: src/cryptsetup.c:930
+msgid "Enter passphrase to be deleted: "
+msgstr "Gõ cụm từ mật khẩu cần xóa: "
+
+#: src/cryptsetup.c:1017 src/cryptsetup_reencrypt.c:1116
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "Hãy nhập mật khẩu bất kỳ sẵn có: "
+
+#: src/cryptsetup.c:1072
+msgid "Enter passphrase to be changed: "
+msgstr "Gõ cụm từ mật khẩu cần được thay đổi: "
+
+#: src/cryptsetup.c:1086 src/cryptsetup_reencrypt.c:1101
+msgid "Enter new passphrase: "
+msgstr "Gõ cụm từ mật khẩu mới: "
+
+#: src/cryptsetup.c:1110
+msgid "Only one device argument for isLuks operation is supported.\n"
+msgstr "Chỉ hỗ trợ một đối số thiết-bị dành cho thao tác isLuks.\n"
+
+#: src/cryptsetup.c:1266 src/cryptsetup.c:1287
+msgid "Option --header-backup-file is required.\n"
+msgstr "Cần tùy chọn“--header-backup-file”.\n"
+
+#: src/cryptsetup.c:1324
+#, c-format
+msgid "Unrecognized metadata device type %s.\n"
+msgstr "Không nhận ra siêu dữ liệu của kiểu thiết bị %s.\n"
+
+#: src/cryptsetup.c:1327
+msgid "Command requires device and mapped name as arguments.\n"
+msgstr "Lệnh cần thiết bị và tên ánh xạ như là các tham số.\n"
+
+#: src/cryptsetup.c:1346
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"Thao tác này sẽ tẩy mọi khe khóa trên thiết bị %s.\n"
+"Thiết bị sẽ không dùng được sau thao tác này."
+
+#: src/cryptsetup.c:1380
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<thiết-bị> [--type <kiểu>] [<tên>]"
+
+#: src/cryptsetup.c:1380
+msgid "open device as mapping <name>"
+msgstr "mở thiết bị như là ánh xạ <tên>"
+
+#: src/cryptsetup.c:1381 src/cryptsetup.c:1382 src/cryptsetup.c:1383
+#: src/veritysetup.c:329 src/veritysetup.c:330
+msgid "<name>"
+msgstr "<tên>"
+
+#: src/cryptsetup.c:1381
+msgid "close device (remove mapping)"
+msgstr "đóng thiết bị (gỡ bỏ ánh xạ)"
+
+#: src/cryptsetup.c:1382
+msgid "resize active device"
+msgstr "thay đổi kích cỡ của thiết bị hoạt động"
+
+#: src/cryptsetup.c:1383
+msgid "show device status"
+msgstr "hiển thị trạng thái về thiết bị"
+
+#: src/cryptsetup.c:1384
+msgid "[--cipher <cipher>]"
+msgstr "[--cipher <bộ mã hóa>]"
+
+#: src/cryptsetup.c:1384
+msgid "benchmark cipher"
+msgstr "đo kiểm tốc độ mã hóa"
+
+#: src/cryptsetup.c:1385 src/cryptsetup.c:1386 src/cryptsetup.c:1392
+#: src/cryptsetup.c:1393 src/cryptsetup.c:1394 src/cryptsetup.c:1395
+#: src/cryptsetup.c:1396 src/cryptsetup.c:1397 src/cryptsetup.c:1398
+#: src/cryptsetup.c:1399
+msgid "<device>"
+msgstr "<thiết_bị>"
+
+#: src/cryptsetup.c:1385
+msgid "try to repair on-disk metadata"
+msgstr "thử sửa chữa siêu dữ liệu (metadata) on-disk"
+
+#: src/cryptsetup.c:1386
+msgid "erase all keyslots (remove encryption key)"
+msgstr "tẩy mọi khe khóa (gỡ bỏ khóa mã hóa)"
+
+#: src/cryptsetup.c:1387 src/cryptsetup.c:1388
+msgid "<device> [<new key file>]"
+msgstr "<thiết_bị> [<tập_tin_khóa_mới>]"
+
+#: src/cryptsetup.c:1387
+msgid "formats a LUKS device"
+msgstr "định dạng một thiết bị kiểu LUKS"
+
+#: src/cryptsetup.c:1388
+msgid "add key to LUKS device"
+msgstr "thêm khóa vào thiết bị LUKS"
+
+#: src/cryptsetup.c:1389 src/cryptsetup.c:1390
+msgid "<device> [<key file>]"
+msgstr "<thiết_bị> [<tập_tin_khóa>]"
+
+#: src/cryptsetup.c:1389
+msgid "removes supplied key or key file from LUKS device"
+msgstr "gỡ bỏ khỏi thiết bị LUKS khóa hoặc tập tin khóa đưa ra"
+
+#: src/cryptsetup.c:1390
+msgid "changes supplied key or key file of LUKS device"
+msgstr "thay đổi khóa hay tập tin khóa đã áp dụng của thiết bị LUKS"
+
+#: src/cryptsetup.c:1391
+msgid "<device> <key slot>"
+msgstr "<thiết_bị> <khe_khóa>"
+
+#: src/cryptsetup.c:1391
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "xóa khỏi thiết bị LUKS khóa có số <khe_khóa>"
+
+#: src/cryptsetup.c:1392
+msgid "print UUID of LUKS device"
+msgstr "in ra mã số UUID của thiết bị LUKS"
+
+#: src/cryptsetup.c:1393
+msgid "tests <device> for LUKS partition header"
+msgstr "thử <thiết_bị> có phần đầu phân vùng LUKS không"
+
+#: src/cryptsetup.c:1394
+msgid "dump LUKS partition information"
+msgstr "đổ thông tin về phân vùng LUKS"
+
+#: src/cryptsetup.c:1395
+msgid "dump TCRYPT device information"
+msgstr "dump thông tin thiết bị TCRYPT"
+
+#: src/cryptsetup.c:1396
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)."
+msgstr "Ngưng thiết bị LUKS và tẩy khóa (thì mọi việc V/R đều đông cứng)."
+
+#: src/cryptsetup.c:1397
+msgid "Resume suspended LUKS device."
+msgstr "Tiếp tục lại sử dụng thiết bị LUKS bị ngưng."
+
+#: src/cryptsetup.c:1398
+msgid "Backup LUKS device header and keyslots"
+msgstr "Sao lưu phần đầu và các khe khóa của thiết bị LUKS"
+
+#: src/cryptsetup.c:1399
+msgid "Restore LUKS device header and keyslots"
+msgstr "Phục hồi phần đầu và các khe khóa của thiết bị LUKS"
+
+#: src/cryptsetup.c:1416 src/veritysetup.c:346
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<thao-tác> là một trong:\n"
+
+#: src/cryptsetup.c:1422
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+msgstr ""
+"\n"
+"Bạn còn có thể sử dụng cú pháp bí danh <thao-tác> kiểu cũ:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+
+#: src/cryptsetup.c:1426
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<tên> là thiết bị cần tạo dưới %s\n"
+"<thiết_bị> là thiết bị đã mã hóa\n"
+"<khe_khóa> là số thứ tự khe khóa LUKS cần sửa đổi\n"
+"<tập_tin_khóa> là tập tin khóa tùy chọn cho khóa mới trong thao tác luksAddKey\n"
+
+#: src/cryptsetup.c:1433
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF2 iteration time for LUKS: %d (ms)\n"
+msgstr ""
+"\n"
+"Các tham số mặc định liên quan đến khóa và mật khẩu được biên dịch sẵn:\n"
+"\tĐộ dài tập tin khóa tối đa: %dkB, Độ dài mật khẩu tương tác tối đa %d (ký tự)\n"
+"Thời gian tương tác PBKDF2 mặc định cho LUKS: %d (ms)\n"
+
+#: src/cryptsetup.c:1440
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS1: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"Các tham số mặc định liên quan đến việc mã hóa được đặt sẵn:\n"
+"\tloop-AES: %s, Khóa %d bit\n"
+"\tdữ liệu thô: %s, Khóa: %d bit, Kiểu băm mật khẩu: %s\n"
+"\tLUKS1: %s, Khóa: %d bit, Kiểu băm cho phần đầu LUKS: %s, RNG: %s\n"
+
+#: src/cryptsetup.c:1457 src/veritysetup.c:481
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: cần thiết %s làm đối số"
+
+#: src/cryptsetup.c:1490 src/veritysetup.c:386 src/cryptsetup_reencrypt.c:1302
+msgid "Show this help message"
+msgstr "Hiển thị trợ giúp này"
+
+#: src/cryptsetup.c:1491 src/veritysetup.c:387 src/cryptsetup_reencrypt.c:1303
+msgid "Display brief usage"
+msgstr "Hiển thị thông tin ngắn về cách sử dụng"
+
+#: src/cryptsetup.c:1495 src/veritysetup.c:391 src/cryptsetup_reencrypt.c:1307
+msgid "Help options:"
+msgstr "Tùy chọn trợ giúp:"
+
+#: src/cryptsetup.c:1496 src/veritysetup.c:392 src/cryptsetup_reencrypt.c:1308
+msgid "Print package version"
+msgstr "Hiển thị phiên bản của gói"
+
+#: src/cryptsetup.c:1497 src/veritysetup.c:393 src/cryptsetup_reencrypt.c:1309
+msgid "Shows more detailed error messages"
+msgstr "Hiển thị các thông điệp lỗi chi tiết hơn"
+
+#: src/cryptsetup.c:1498 src/veritysetup.c:394 src/cryptsetup_reencrypt.c:1310
+msgid "Show debug messages"
+msgstr "Hiển thị thông điệp gỡ lỗi"
+
+#: src/cryptsetup.c:1499 src/cryptsetup_reencrypt.c:1312
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "Mật mã dùng để bảo vệ đĩa (xem “/proc/crypto”)"
+
+#: src/cryptsetup.c:1500 src/cryptsetup_reencrypt.c:1314
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "Chuỗi duy nhất dùng để tạo khóa mã hóa từ cụm từ mật khẩu"
+
+#: src/cryptsetup.c:1501
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "Thẩm tra cụm từ mật khẩu bằng cách yêu cầu nó hai lần"
+
+#: src/cryptsetup.c:1502 src/cryptsetup_reencrypt.c:1316
+msgid "Read the key from a file."
+msgstr "Đọc khóa từ một tập tin."
+
+#: src/cryptsetup.c:1503
+msgid "Read the volume (master) key from file."
+msgstr "Đọc khóa khối tin (chủ) từ tập tin."
+
+#: src/cryptsetup.c:1504
+msgid "Dump volume (master) key instead of keyslots info."
+msgstr "Dump (đổ thành đống) khóa vùng chứa (master) thay vì thông tin khe-khóa."
+
+#: src/cryptsetup.c:1505 src/cryptsetup_reencrypt.c:1313
+msgid "The size of the encryption key"
+msgstr "Kích cỡ của khóa mã hóa"
+
+#: src/cryptsetup.c:1505 src/cryptsetup_reencrypt.c:1313
+msgid "BITS"
+msgstr "BIT"
+
+#: src/cryptsetup.c:1506 src/cryptsetup_reencrypt.c:1327
+msgid "Limits the read from keyfile"
+msgstr "Giới hạn việc đọc từ tập-tin-khóa"
+
+#: src/cryptsetup.c:1506 src/cryptsetup.c:1507 src/cryptsetup.c:1508
+#: src/cryptsetup.c:1509 src/veritysetup.c:397 src/veritysetup.c:398
+#: src/veritysetup.c:400 src/cryptsetup_reencrypt.c:1326
+#: src/cryptsetup_reencrypt.c:1327 src/cryptsetup_reencrypt.c:1328
+#: src/cryptsetup_reencrypt.c:1329
+msgid "bytes"
+msgstr "byte"
+
+#: src/cryptsetup.c:1507 src/cryptsetup_reencrypt.c:1326
+msgid "Number of bytes to skip in keyfile"
+msgstr "Số lượng byte nhảy qua trong tập tin khóa"
+
+#: src/cryptsetup.c:1508
+msgid "Limits the read from newly added keyfile"
+msgstr "Giới hạn đọc từ tập tin khóa mới thêm vào"
+
+#: src/cryptsetup.c:1509
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "Số lượng byte để nhảy qua trong tập tin khóa mới thêm"
+
+#: src/cryptsetup.c:1510
+msgid "Slot number for new key (default is first free)"
+msgstr "Số thứ tự khe cho khóa mới (mặc định là khe trống thứ nhất)"
+
+#: src/cryptsetup.c:1511
+msgid "The size of the device"
+msgstr "Kích cỡ của thiết bị"
+
+#: src/cryptsetup.c:1511 src/cryptsetup.c:1512 src/cryptsetup.c:1513
+#: src/cryptsetup.c:1519
+msgid "SECTORS"
+msgstr "CUNG-TỪ"
+
+#: src/cryptsetup.c:1512
+msgid "The start offset in the backend device"
+msgstr "Khoảng bù đầu tiên trong thiết bị thật chạy ở phía sau"
+
+#: src/cryptsetup.c:1513
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "Bao nhiêu cung từ dữ liệu mã hóa cần bỏ qua ở đầu"
+
+#: src/cryptsetup.c:1514
+msgid "Create a readonly mapping"
+msgstr "Tạo một sự ánh xạ chỉ cho đọc"
+
+#: src/cryptsetup.c:1515 src/cryptsetup_reencrypt.c:1317
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "Thời gian lặp lại PBKDF2 cho LUKS (theo mili-giây)"
+
+#: src/cryptsetup.c:1515 src/cryptsetup_reencrypt.c:1317
+msgid "msecs"
+msgstr "mili-giây"
+
+#: src/cryptsetup.c:1516 src/cryptsetup_reencrypt.c:1318
+msgid "Do not ask for confirmation"
+msgstr "Không cần xác nhận"
+
+#: src/cryptsetup.c:1517
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "Thời gian chờ gõ cụm từ mật khẩu tối đa (theo giây)"
+
+#: src/cryptsetup.c:1517
+msgid "secs"
+msgstr "giây"
+
+#: src/cryptsetup.c:1518 src/cryptsetup_reencrypt.c:1319
+msgid "How often the input of the passphrase can be retried"
+msgstr "Số các lần có cho phép thử gõ lại cụm từ mật khẩu"
+
+#: src/cryptsetup.c:1519
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "Căn chỉnh trọng tải ở <n> biên giới cung từ — cho định dạng “luksFormat”"
+
+#: src/cryptsetup.c:1520
+msgid "File with LUKS header and keyslots backup."
+msgstr "Tập tin chứa bản sao lưu phần đầu và các khe khóa của thiết bị LUKS."
+
+#: src/cryptsetup.c:1521 src/cryptsetup_reencrypt.c:1320
+msgid "Use /dev/random for generating volume key."
+msgstr "Dùng /dev/random để tạo khóa volume."
+
+#: src/cryptsetup.c:1522 src/cryptsetup_reencrypt.c:1321
+msgid "Use /dev/urandom for generating volume key."
+msgstr "Dùng /dev/urandom để tạo khóa vùng."
+
+#: src/cryptsetup.c:1523
+msgid "Share device with another non-overlapping crypt segment."
+msgstr "Thiết bị chia sẻ với đoạn crypt không-chồng-lên-nhau khác."
+
+#: src/cryptsetup.c:1524 src/veritysetup.c:403
+msgid "UUID for device to use."
+msgstr "UUID dành cho tập tin sử dụng."
+
+#: src/cryptsetup.c:1525
+msgid "Allow discards (aka TRIM) requests for device."
+msgstr "Cho phép hủy bỏ (được biết đến như là TRIM) các yêu cầu cho thiết bị."
+
+#: src/cryptsetup.c:1526
+msgid "Device or file with separated LUKS header."
+msgstr "Thiết bị hay tập tin với phần đầu LUKS tách nhau."
+
+#: src/cryptsetup.c:1527
+msgid "Do not activate device, just check passphrase."
+msgstr "Không kích hoạt thiết bị, chỉ cần kiểm tra mật khẩu."
+
+#: src/cryptsetup.c:1528
+msgid "Use hidden header (hidden TCRYPT device)."
+msgstr "Dùng phần đầu ẩn (thiết bị TCRYPT ẩn)."
+
+#: src/cryptsetup.c:1529
+msgid "Device is system TCRYPT drive (with bootloader)."
+msgstr "Thiết bị là ổ đĩa TCRYPT hệ thống (có bootloader)."
+
+#: src/cryptsetup.c:1530
+msgid "Use backup (secondary) TCRYPT header."
+msgstr "Dùng phần đầu (thứ cấp) TCRYPT."
+
+#: src/cryptsetup.c:1531
+msgid "Scan also for VeraCrypt compatible device."
+msgstr "Cũng quét cho thiết bị tương thích VeraCrypt."
+
+#: src/cryptsetup.c:1532
+msgid "Type of device metadata: luks, plain, loopaes, tcrypt."
+msgstr "Kiểu của siêu dữ liệu thiết bị: luks, plain, loopaes, tcrypt."
+
+#: src/cryptsetup.c:1533
+msgid "Disable password quality check (if enabled)."
+msgstr "Tắt chức năng kiểm tra chất lượng mật khẩu (nếu nó đang bật)."
+
+#: src/cryptsetup.c:1534
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option."
+msgstr "Dùng tùy chọn tương thích hiệu năng same_cpu_crypt dm-crypt."
+
+#: src/cryptsetup.c:1535
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option."
+msgstr "Dùng tùy chọn tương thích hiệu năng submit_from_crypt_cpus dm-crypt."
+
+#: src/cryptsetup.c:1551 src/veritysetup.c:423
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[TÙY CHỌN…] <thao-tác> <đặc-tả-thao-tác>"
+
+#: src/cryptsetup.c:1602 src/veritysetup.c:460
+msgid "Argument <action> missing."
+msgstr "Còn thiếu đối số <thao-tác>."
+
+#: src/cryptsetup.c:1655 src/veritysetup.c:466
+msgid "Unknown action."
+msgstr "Không hiểu thao-tác."
+
+#: src/cryptsetup.c:1665
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "Tùy chọn “--shared” chỉ cho phép với thao tác tạo mở của thiết bị thường.\n"
+
+#: src/cryptsetup.c:1670
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "Tùy chọn “--allow-discards” chỉ cho phép với thao tác mở.\n"
+
+#: src/cryptsetup.c:1678
+msgid ""
+"Option --key-size is allowed only for luksFormat, open and benchmark.\n"
+"To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"Tùy chọn --key-size thì chỉ cho phép với các thao tác luksFormat, mở và đo kiểm.\n"
+"Để giới hạn đọc từ tập-tin-khóa, hãy sử dụng tùy chọn --keyfile-size=(bytes)."
+
+#: src/cryptsetup.c:1685
+msgid "Option --test-passphrase is allowed only for open of LUKS and TCRYPT devices.\n"
+msgstr "Tùy chọn “--test-passphrase” chỉ được phép cho lệnh mở thiết bị LUKS và TCRYPT.\n"
+
+#: src/cryptsetup.c:1690 src/cryptsetup_reencrypt.c:1389
+msgid "Key size must be a multiple of 8 bits"
+msgstr "Kích cỡ khóa phải là bội số của 8 bít"
+
+#: src/cryptsetup.c:1697 src/cryptsetup_reencrypt.c:1394
+msgid "Key slot is invalid."
+msgstr "Khe khóa không đúng."
+
+#: src/cryptsetup.c:1704
+msgid "Option --key-file takes precedence over specified key file argument.\n"
+msgstr "Tùy chọn --key-file giữ quyền ưu tiên cao hơn tham số tập tin khóa đã chỉ định.\n"
+
+#: src/cryptsetup.c:1712 src/veritysetup.c:488 src/cryptsetup_reencrypt.c:1378
+msgid "Negative number for option not permitted."
+msgstr "Tùy chọn không chấp nhận giá trị là số âm."
+
+#: src/cryptsetup.c:1716
+msgid "Only one --key-file argument is allowed."
+msgstr "Chỉ cho phép một tùy chọn --key-file."
+
+#: src/cryptsetup.c:1720 src/cryptsetup_reencrypt.c:1372
+#: src/cryptsetup_reencrypt.c:1398
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "Chỉ cho phép một tùy chọn “--use-[u]random”."
+
+#: src/cryptsetup.c:1724
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "Tùy chọn “--use-[u]random” chỉ được phép cho “luksFormat”."
+
+#: src/cryptsetup.c:1728
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "Tùy chọn “--uuid” thì chỉ cho phép với “luksFormat” và “luksUUID”."
+
+#: src/cryptsetup.c:1732
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "Tùy chọn “--align-payload” chỉ được phép cho “luksFormat”."
+
+#: src/cryptsetup.c:1738
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "Tùy chọn “--skip” chỉ hỗ trợ cho lệnh mở (open) của thiết bị thường và “loopaes”.\n"
+
+#: src/cryptsetup.c:1744
+msgid "Option --offset is supported only for open of plain and loopaes devices.\n"
+msgstr "Tùy chọn “--offset” chỉ hỗ trợ cho lệnh mở (open) của thiết bị thường và “loopaes”.\n"
+
+#: src/cryptsetup.c:1750
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "Tùy chọn --tcrypt-hidden, --tcrypt-system hay --tcrypt-backup chỉ được hỗ trợ trên thiết bị TCRYPT.\n"
+
+#: src/cryptsetup.c:1755
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "Tùy chọn --tcrypt-hidden không thể được tổ hợp cùng với --allow-discards.\n"
+
+#: src/cryptsetup.c:1760
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "Tùy chọn --veracrypt chỉ được hỗ trợ trên thiết bị TCRYPT.\n"
+
+#: src/veritysetup.c:61
+msgid "Invalid salt string specified.\n"
+msgstr "Chuỗi salt (muối) đã cho không hợp lệ.\n"
+
+#: src/veritysetup.c:91
+#, c-format
+msgid "Cannot create hash image %s for writing.\n"
+msgstr "Không thể tạo ảnh băm %s để ghi.\n"
+
+#: src/veritysetup.c:158
+msgid "Invalid root hash string specified.\n"
+msgstr "Chuỗi mã băm gốc (thư mục root) đã chỉ ra không hợp lệ.\n"
+
+#: src/veritysetup.c:326
+msgid "<data_device> <hash_device>"
+msgstr "<thiết-bị-dữ-liệu> <thiết-bị-băm>"
+
+#: src/veritysetup.c:326
+msgid "format device"
+msgstr "định dạng thiết bị"
+
+#: src/veritysetup.c:327
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<thiết-bị-dữ-liệu> <thiết-bị-băm> <mã-băm-gốc>"
+
+#: src/veritysetup.c:327
+msgid "verify device"
+msgstr "thẩm tra thiết bị"
+
+#: src/veritysetup.c:328
+msgid "<name> <data_device> <hash_device> <root_hash>"
+msgstr "<tên> <thiết-bị-dữ-liệu> <thiết-bị-băm> <mã-băm-gốc>"
+
+#: src/veritysetup.c:328
+msgid "create active device"
+msgstr "tạo thiết bị hoạt động"
+
+#: src/veritysetup.c:329
+msgid "remove (deactivate) device"
+msgstr "gỡ bỏ (dừng hoạt động) thiết bị"
+
+#: src/veritysetup.c:330
+msgid "show active device status"
+msgstr "hiển thị trạng thái các thiết bị đang hoạt động"
+
+#: src/veritysetup.c:331
+msgid "<hash_device>"
+msgstr "<thiết_bị_băm>"
+
+#: src/veritysetup.c:331
+msgid "show on-disk information"
+msgstr "hiển thị thông tin trên-đĩa"
+
+#: src/veritysetup.c:350
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<tên> là thiết bị để tạo dưới %s\n"
+"<thiết-bị-dữ-liệu> là thiết bị dữ liệu\n"
+"<thiết-bị-băm> là thiết bị chứa dữ liệu xác thực\n"
+"<mã-băm-gốc> mã băm của nút root (gốc) trên <thiết-bị-băm>\n"
+
+#: src/veritysetup.c:357
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"Các tham số dm-verity dựng sẵn mặc định:\n"
+"\tBăm: %s, Khối dữ liệu (bytes): %u, Khối băm (bytes): %u, Kích thước muối: %u, Định dạng băm: %u\n"
+
+#: src/veritysetup.c:395
+msgid "Do not use verity superblock"
+msgstr "Không sử dụng siêu khối thẩm định"
+
+#: src/veritysetup.c:396
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "Kiểu định dạng (1 - thông thường, 0 - Chrome OS)"
+
+#: src/veritysetup.c:396
+msgid "number"
+msgstr "số"
+
+#: src/veritysetup.c:397
+msgid "Block size on the data device"
+msgstr "Kích cỡ khối trên thiết bị dữ liệu"
+
+#: src/veritysetup.c:398
+msgid "Block size on the hash device"
+msgstr "Kích cỡ của khối trên thiết bị băm"
+
+#: src/veritysetup.c:399
+msgid "The number of blocks in the data file"
+msgstr "Số lượng khối trong tập tin dữ liệu"
+
+#: src/veritysetup.c:399
+msgid "blocks"
+msgstr "khối"
+
+#: src/veritysetup.c:400
+msgid "Starting offset on the hash device"
+msgstr "Khoảng bù (offset) khởi đầu của thiết bị băm"
+
+#: src/veritysetup.c:401
+msgid "Hash algorithm"
+msgstr "Thuật toán băm"
+
+#: src/veritysetup.c:401
+msgid "string"
+msgstr "chuỗi"
+
+#: src/veritysetup.c:402
+msgid "Salt"
+msgstr "Muối"
+
+#: src/veritysetup.c:402
+msgid "hex string"
+msgstr "chuỗi hex (thập lục phân)"
+
+#: src/veritysetup.c:404
+msgid "Restart kernel if corruption is detected"
+msgstr "Khởi động lại nhân nếu thấy có sai hỏng"
+
+#: src/veritysetup.c:405
+msgid "Ignore corruption, log it only"
+msgstr "Bỏ qua sai hỏng, chỉ ghi nhật ký lại"
+
+#: src/veritysetup.c:406
+msgid "Do not verify zeroed blocks"
+msgstr "Không thẩm tra các khối không"
+
+#: src/veritysetup.c:494
+msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for create operation.\n"
+msgstr "Tùy chọn --ignore-corruption, --restart-on-corruption hay --ignore-zero-blocks chỉ được phép dùng cho thao tác tạo.\n"
+
+#: src/veritysetup.c:499
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together.\n"
+msgstr "Không được dùng các tùy chọn --ignore-corruption và --restart-on-corruption cùng một lúc.\n"
+
+#: src/cryptsetup_reencrypt.c:150
+#, c-format
+msgid "Cannot exclusively open %s, device in use.\n"
+msgstr "Không thể mở %s một cách đệ qui, thiết bị vẫn đang được sử dụng.\n"
+
+#: src/cryptsetup_reencrypt.c:164 src/cryptsetup_reencrypt.c:920
+msgid "Allocation of aligned memory failed.\n"
+msgstr "Phân bổ bộ nhớ điều chỉnh gặp lỗi.\n"
+
+#: src/cryptsetup_reencrypt.c:171
+#, c-format
+msgid "Cannot read device %s.\n"
+msgstr "Không thể đọc thiết bị %s.\n"
+
+#: src/cryptsetup_reencrypt.c:182
+#, c-format
+msgid "Marking LUKS device %s unusable.\n"
+msgstr "Đánh dấu thiết bị LUKS %s là không thể dùng.\n"
+
+#: src/cryptsetup_reencrypt.c:198
+#, c-format
+msgid "Cannot write device %s.\n"
+msgstr "Không thể ghi thiết bị %s.\n"
+
+#: src/cryptsetup_reencrypt.c:281
+msgid "Cannot write reencryption log file.\n"
+msgstr "Không thể ghi tập tin nhật ký reencryption (mã hóa lại).\n"
+
+#: src/cryptsetup_reencrypt.c:337
+msgid "Cannot read reencryption log file.\n"
+msgstr "Không đọc được tập tin nhật ký reencryption.\n"
+
+#: src/cryptsetup_reencrypt.c:375
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "Tập tin nhật ký %s đã có sẵn rồi, giả định là reencryption (mã hóa lại).\n"
+
+#: src/cryptsetup_reencrypt.c:425
+msgid "Activating temporary device using old LUKS header.\n"
+msgstr "Hoạt hóa thiết bị tạm thời sử dụng phần đầu LUKS kiểu cũ.\n"
+
+#: src/cryptsetup_reencrypt.c:436
+msgid "Activating temporary device using new LUKS header.\n"
+msgstr "Hoạt hóa thiết bị tạm thời sử dụng phần đầu LUKS kiểu mới.\n"
+
+#: src/cryptsetup_reencrypt.c:446
+msgid "Activation of temporary devices failed.\n"
+msgstr "Việc hoạt hóa các thiết bị tạm thời gặp lỗi.\n"
+
+#: src/cryptsetup_reencrypt.c:472
+#, c-format
+msgid "New LUKS header for device %s created.\n"
+msgstr "Phần đầu LUKS mới cho thiết bị %s được tạo.\n"
+
+#: src/cryptsetup_reencrypt.c:480
+#, c-format
+msgid "Activated keyslot %i.\n"
+msgstr "Khe-khóa (keyslot) đã được kích hoạt %i.\n"
+
+#: src/cryptsetup_reencrypt.c:506
+#, c-format
+msgid "LUKS header backup of device %s created.\n"
+msgstr "Phần đầu sao lưu LUKS của thiết bị %s được tạo.\n"
+
+#: src/cryptsetup_reencrypt.c:554
+msgid "Creation of LUKS backup headers failed.\n"
+msgstr "Việc tạo phần đầu LUKS sao lưu dự phòng gặp lỗi.\n"
+
+#: src/cryptsetup_reencrypt.c:656
+#, c-format
+msgid "Cannot restore LUKS header on device %s.\n"
+msgstr "Không thể phục hồi phần đầu LUKS trên thiết bị %s.\n"
+
+#: src/cryptsetup_reencrypt.c:658
+#, c-format
+msgid "LUKS header on device %s restored.\n"
+msgstr "Phần đầu LUKS trên thiết bị %s đã được phục hồi.\n"
+
+#: src/cryptsetup_reencrypt.c:693
+#, c-format
+msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+msgstr "Diễn biến: %5.1f%%, ETA %02llu:%02llu, đã ghi %4llu MiB, tốc độ %5.1f MiB/s%s"
+
+#: src/cryptsetup_reencrypt.c:732 src/cryptsetup_reencrypt.c:811
+#: src/cryptsetup_reencrypt.c:853
+msgid "Cannot seek to device offset.\n"
+msgstr "Không thể di chuyển vị trí tới vị trí tương đối thiết bị.\n"
+
+#: src/cryptsetup_reencrypt.c:892 src/cryptsetup_reencrypt.c:898
+msgid "Cannot open temporary LUKS device.\n"
+msgstr "Không thể r thiết bị LUKS tạm thời.\n"
+
+#: src/cryptsetup_reencrypt.c:903 src/cryptsetup_reencrypt.c:908
+msgid "Cannot get device size.\n"
+msgstr "Không thể lấy kích cỡ thiết bị.\n"
+
+#: src/cryptsetup_reencrypt.c:946
+msgid "Interrupted by a signal.\n"
+msgstr "Bị ngắt bởi tín hiệu signal.\n"
+
+#: src/cryptsetup_reencrypt.c:948
+msgid "IO error during reencryption.\n"
+msgstr "Lỗi IO (vào/ra) trong quá trình mã hóa lại.\n"
+
+#: src/cryptsetup_reencrypt.c:978
+msgid "Provided UUID is invalid.\n"
+msgstr "UUID đã cung cấp không hợp lệ.\n"
+
+#: src/cryptsetup_reencrypt.c:1070
+msgid "Key file can be used only with --key-slot or with exactly one key slot active.\n"
+msgstr "Tập tin khóa có thể sử dụng với tùy chọn --key-slot hoặc với chính xác một khe khóa hoạt động.\n"
+
+#: src/cryptsetup_reencrypt.c:1114 src/cryptsetup_reencrypt.c:1129
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "Gõ cụm từ mật khẩu cho khe khóa %u: "
+
+#: src/cryptsetup_reencrypt.c:1178
+msgid "Cannot open reencryption log file.\n"
+msgstr "Không mở được tập tin nhật ký reencryption.\n"
+
+#: src/cryptsetup_reencrypt.c:1184
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process.\n"
+msgstr "Không có quá trình giải mã nào đang xử lý, UUID đã cung cấp có thể chỉ được dùng để phục hồi lại tiến trình giải mã đã tạm dừng.\n"
+
+#: src/cryptsetup_reencrypt.c:1311
+msgid "Reencryption block size"
+msgstr "Kích thước khối mã hóa lại"
+
+#: src/cryptsetup_reencrypt.c:1311
+msgid "MiB"
+msgstr "MiB"
+
+#: src/cryptsetup_reencrypt.c:1315
+msgid "Do not change key, no data area reencryption."
+msgstr "Khôngười thay đổi khóa, không có mã hóa lại vùng dữ liệu."
+
+#: src/cryptsetup_reencrypt.c:1322
+msgid "Use direct-io when accessing devices."
+msgstr "Sử dụng vào ra trực tiếp khi truy cập các thiết bị."
+
+#: src/cryptsetup_reencrypt.c:1323
+msgid "Use fsync after each block."
+msgstr "Sử dụng fsync sau mỗi khối."
+
+#: src/cryptsetup_reencrypt.c:1324
+msgid "Update log file after every block."
+msgstr "Cập nhật tập tin nhật ký sau mỗi khối."
+
+#: src/cryptsetup_reencrypt.c:1325
+msgid "Use only this slot (others will be disabled)."
+msgstr "Chỉ sử dụng khe này (những cái khác sẽ bị tắt đi)."
+
+#: src/cryptsetup_reencrypt.c:1328
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "Giảm kích thước dữ liệu thiết bị (di chuyển offset dữ liệu). NGUY HIỂM!"
+
+#: src/cryptsetup_reencrypt.c:1329
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "Chỉ sử dụng kích thước dữ liệu thiết bị (bỏ qua phần còn lại của thiết bị). NGUY HIỂM!"
+
+#: src/cryptsetup_reencrypt.c:1330
+msgid "Create new header on not encrypted device."
+msgstr "Tạo phần đầu mới không trên thiết bị được mã hóa."
+
+#: src/cryptsetup_reencrypt.c:1331
+msgid "Permanently decrypt device (remove encryption)."
+msgstr "Thiết bị mã hóa cố định (gỡ bỏ mã hóa)."
+
+#: src/cryptsetup_reencrypt.c:1332
+msgid "The uuid used to resume decryption."
+msgstr "uuid được dùng để khôi phục việc giải mã."
+
+#: src/cryptsetup_reencrypt.c:1348
+msgid "[OPTION...] <device>"
+msgstr "[TÙY_CHỌN…] <thiết-bị>"
+
+#: src/cryptsetup_reencrypt.c:1362
+#, c-format
+msgid "Reencryption will change: volume key%s%s%s%s.\n"
+msgstr "Reencryption sẽ thay đổi: khóa dung lượng%s%s%s%s.\n"
+
+#: src/cryptsetup_reencrypt.c:1363
+msgid ", set hash to "
+msgstr ", đặt kiểu băm thành "
+
+#: src/cryptsetup_reencrypt.c:1364
+msgid ", set cipher to "
+msgstr ", đặt kiểu mã hóa thành "
+
+#: src/cryptsetup_reencrypt.c:1368
+msgid "Argument required."
+msgstr "Cần đối số."
+
+#: src/cryptsetup_reencrypt.c:1384
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "Chỉ những giá trị nằm giữa 1MiB và 64 MiB là cho phép đối với kích thước khối reencryption (mã hóa lại)."
+
+#: src/cryptsetup_reencrypt.c:1403 src/cryptsetup_reencrypt.c:1408
+msgid "Invalid device size specification."
+msgstr "Đặc tả kích thước thiết bị không đúng."
+
+#: src/cryptsetup_reencrypt.c:1411
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "Kích thước thu nhỏ thiết bị tối đa là 64 MiB."
+
+#: src/cryptsetup_reencrypt.c:1414
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "Kích cỡ giảm phải là bội số cung từ (sector) 512 byte"
+
+#: src/cryptsetup_reencrypt.c:1418
+msgid "Option --new must be used together with --reduce-device-size."
+msgstr "Tùy chọn “--new” phải được sử dụng cùng với “--reduce-device-size”."
+
+#: src/cryptsetup_reencrypt.c:1422
+msgid "Option --keep-key can be used only with --hash or --iter-time."
+msgstr "Tùy chọn “--keep-key” có thể dùng với “--hash” hoặc “--iter-time”."
+
+#: src/cryptsetup_reencrypt.c:1426
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "Tùy chọn “--new” không được sử dụng cùng với “ --decrypt”."
+
+#: src/cryptsetup_reencrypt.c:1430
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "Tùy chọn --decrypt không tương thích với các đối số đã cho."
+
+#: src/cryptsetup_reencrypt.c:1434
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "Tùy chọn “--uuid” chỉ được sử dụng cùng với “ --decrypt”."
+
+#: src/utils_tools.c:151
+msgid "Error reading response from terminal.\n"
+msgstr "Gặp lỗi khi đọc phản hồi từ thiết bị cuối.\n"
+
+#: src/utils_tools.c:173
+msgid "Command successful.\n"
+msgstr "Câu lệnh đã chạy thành công.\n"
+
+#: src/utils_tools.c:191
+#, c-format
+msgid "Command failed with code %i"
+msgstr "Câu lệnh đã thất bại với mã %i"
+
+#: src/utils_password.c:42 src/utils_password.c:74
+#, c-format
+msgid "Cannot check password quality: %s\n"
+msgstr "Không thể kiểm tra chất lượng mật khẩu: %s\n"
+
+#: src/utils_password.c:50
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s\n"
+msgstr ""
+"Chất lượng mật khẩu không đạt:\n"
+" %s\n"
+
+#: src/utils_password.c:82
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)\n"
+msgstr "Gặp lỗi khi kiểm tra chất lượng mật khẩu: mật khẩu sai (%s)\n"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "Không tìm thấy thiết bị vòng ngược (loopback) nào còn rảnh.\n"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "Không thể mở thiết bị %s\n"
+
+#~ msgid "Cannot use passed UUID unless decryption in progress.\n"
+#~ msgstr "Không thể dùng UUID chuyển qua trừ khi việc giải mã đang được thực hiện.\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "Đánh dấu thiết bị LUKS %s là có thể dùng.\n"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "CẢNH BÁO: đây chỉ là mã thử nghiệm, nó có thể phá hoại dữ liệu của bạn.\n"
+
+#~ msgid "FIPS checksum verification failed.\n"
+#~ msgstr "Thẩm tra mã băm FIPS không đạt.\n"
+
+#~ msgid "WARNING: device %s is a partition, for TCRYPT system encryption you usually need to use whole block device path.\n"
+#~ msgstr "CẢNH BÁO: thiết-bị %s là một phân vùng, với mã hóa hệ thống TCRYPT bạn thường cần phải sử dụng toàn bộ đường dẫn thiết-bị khối.\n"
+
+#~ msgid "Kernel doesn't support plain64 IV.\n"
+#~ msgstr "Nhân không hỗ trợ plain64 IV.\n"
+
+#~ msgid "Enter LUKS passphrase: "
+#~ msgstr "Gõ cụm từ mật khẩu LUKS: "
+
+#~ msgid "Enter new LUKS passphrase: "
+#~ msgstr "Gõ cụm từ mật khẩu LUKS: "
+
+#~ msgid "Enter any LUKS passphrase: "
+#~ msgstr "Nhập mật khẩu LUKS vào: "
+
+#~ msgid "Failed to obtain device mapper directory."
+#~ msgstr "Lỗi lấy thư mục trình ánh xạ thiết bị."
+
+#~ msgid "Backup file %s doesn't exist.\n"
+#~ msgstr "Tập tin sao lưu %s không tồn tại.\n"
+
+#~ msgid "Cannot open file %s.\n"
+#~ msgstr "Không thể mở tập tin %s.\n"
+
+#~ msgid "<name> <device>"
+#~ msgstr "<tên> <thiết_bị>"
+
+#~ msgid "create device"
+#~ msgstr "tạo thiết bị"
+
+#~ msgid "remove device"
+#~ msgstr "gỡ bỏ thiết bị"
+
+#~ msgid "remove LUKS mapping"
+#~ msgstr "gỡ bỏ sự ánh xạ LUKS"
+
+#~ msgid "open loop-AES device as mapping <name>"
+#~ msgstr "mở thiết bị loop-AES như là ánh xạ <tên>"
+
+#~ msgid "remove loop-AES mapping"
+#~ msgstr "gỡ bỏ ánh xạ loop-AES"
+
+#~ msgid "Option --allow-discards is allowed only for luksOpen, loopaesOpen and create operation.\n"
+#~ msgstr "Tùy chọn “--allow-discards” thì chỉ cho phép với thao tác “luksOpen”, “loopaesOpen” và tạo (create).\n"
+
+#~ msgid "Cannot open device %s for %s%s access.\n"
+#~ msgstr "Không thể mở thiết bị %s cho truy cập %s%s.\n"
+
+#~ msgid "exclusive "
+#~ msgstr "dành riêng "
+
+#~ msgid "writable"
+#~ msgstr "ghi được"
+
+#~ msgid "read-only"
+#~ msgstr "chỉ đọc"
+
+#~ msgid "WARNING!!! Possibly insecure memory. Are you root?\n"
+#~ msgstr "CẢNH BÁO!!! Có thể là vùng nhớ không an toàn. Bạn có đang chạy dưới quyền siêu người dùng (root) không?\n"
+
+#~ msgid "Unable to obtain sector size for %s"
+#~ msgstr "Không thể lấy kích cỡ cung từ cho %s"
+
+#~ msgid "Failed to write to key storage.\n"
+#~ msgstr "Lỗi ghi khóa vào kho lưu khóa.\n"
+
+#~ msgid "Failed to read from key storage.\n"
+#~ msgstr "Lỗi đọc từ kho lưu khóa.\n"
+
+#~ msgid "Cannot use device %s (crypt segments overlaps or in use by another device).\n"
+#~ msgstr "Không thể sử dụng thiết bị %s (các đoạn crypt chồng lên nhau hay đang sử dụng bởi thiết bị khác).\n"
+
+#~ msgid "Cannot find compatible device-mapper kernel modules.\n"
+#~ msgstr "Không tìm thấy mô-đun hạt nhân ánh xạ thiết bị tương thích.\n"
+
+#~ msgid "Key slot %d verified.\n"
+#~ msgstr "Khe khóa %d được thẩm định.\n"
+
+#~ msgid "Invalid key size %d.\n"
+#~ msgstr "Kích cỡ khóa không đúng %d.\n"
+
+#~ msgid "Warning: exhausting read requested, but key file %s is not a regular file, function might never return.\n"
+#~ msgstr "Cảnh báo: yêu cầu một hàm đọc vét kiệt mà tập tin khóa %s không phải là một tập tin thông thường thì có thể là hàm chưa bao giờ trả lại.\n"
+
+#~ msgid "Cannot open device: %s\n"
+#~ msgstr "Không thể mở thiết bị: %s\n"
+
+#~ msgid "BLKROGET failed on device %s.\n"
+#~ msgstr "BLKROGET bị lỗi trên thiết bị %s.\n"
+
+#~ msgid "BLKGETSIZE failed on device %s.\n"
+#~ msgstr "BLKGETSIZE bị lỗi trên thiết bị %s.\n"
+
+#~ msgid "identical to luksKillSlot - DEPRECATED - see man page"
+#~ msgstr "trùng với luksKillSlot - BỊ PHẢN ĐỐI - xem trang hướng dẫn"
+
+#~ msgid "modify active device - DEPRECATED - see man page"
+#~ msgstr "sửa đổi thiết bị hoạt động - BỊ PHẢN ĐỐI - xem trang hướng dẫn"
+
+#~ msgid ""
+#~ "The reload action is deprecated. Please use`dmsetup reload' in case you really need this functionality.\n"
+#~ "WARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"
+#~ msgstr ""
+#~ "Thao tác nạp lại bị phản đối. Hãy sử dụng“dmsetup reload” trong trường hợp bạn thực sự yêu cầu chức năng này.\n"
+#~ "CẢNH BÁO: đừng sử dụng chức năng nạp lại để thao tác thiết bị kiểu LUKS. Trong trường hợp đó, bấm tổ hợp phím Ctrl-C ngay bây giờ.\n"
+
+#~ msgid "Obsolete option --non-exclusive is ignored.\n"
+#~ msgstr "Tùy chọn cũ“--non-exclusive” bị bỏ qua.\n"
+
+#~ msgid "Read the key from a file (can be /dev/random)"
+#~ msgstr "Đọc khóa từ một tập tin nào đó (có thể là“/dev/random”)"
+
+#~ msgid "(Obsoleted, see man page.)"
+#~ msgstr "(Bị phản đối, xem trang hướng dẫn.)"
diff --git a/po/zh_CN.po b/po/zh_CN.po
new file mode 100644
index 0000000..5ab96fb
--- /dev/null
+++ b/po/zh_CN.po
@@ -0,0 +1,3075 @@
+# Chinese simplified translation for cryptsetup.
+# Copyright (C) 2015 Free Software Foundation, Inc.
+# This file is distributed under the same license as the cryptsetup package.
+# Mingcong Bai <jeffbai@aosc.xyz>, 2015.
+# Mingye Wang <arthur200126@gmail.com>, 2015.
+# Boyuan Yang <073plan@gmail.com>, 2018.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: cryptsetup 2.0.3.1\n"
+"Report-Msgid-Bugs-To: dm-crypt@saout.de\n"
+"POT-Creation-Date: 2018-04-26 22:11+0200\n"
+"PO-Revision-Date: 2018-04-27 22:41+0800\n"
+"Last-Translator: Boyuan Yang <073plan@gmail.com>\n"
+"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
+"X-Generator: Poedit 2.0.6\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: lib/libdevmapper.c:331
+msgid "Cannot initialize device-mapper, running as non-root user."
+msgstr "无法初始化设备映射器,正作为非 root 用户运行。"
+
+#: lib/libdevmapper.c:334
+msgid "Cannot initialize device-mapper. Is dm_mod kernel module loaded?"
+msgstr "无法初始化设备映射器。dm_mod 内核模块装载了吗?"
+
+#: lib/libdevmapper.c:938
+msgid "Requested deferred flag is not supported."
+msgstr "不支持请求的推迟(deferred)标记。"
+
+#: lib/libdevmapper.c:1003
+#, c-format
+msgid "DM-UUID for device %s was truncated."
+msgstr "设备 %s 的 DM-UUID 被截断。"
+
+#: lib/libdevmapper.c:1223
+msgid "Requested dm-crypt performance options are not supported."
+msgstr "不支持请求的 dm-crypt 性能选项。"
+
+#: lib/libdevmapper.c:1230
+msgid "Requested dm-verity data corruption handling options are not supported."
+msgstr "不支持请求的 dm-verity 数据损坏处理选项。"
+
+#: lib/libdevmapper.c:1234
+msgid "Requested dm-verity FEC options are not supported."
+msgstr "不支持请求的 dm-verity FEC 选项。"
+
+#: lib/libdevmapper.c:1238
+msgid "Requested data integrity options are not supported."
+msgstr "不支持请求的数据完整性选项。"
+
+#: lib/libdevmapper.c:1240
+msgid "Requested sector_size option is not supported."
+msgstr "不支持请求的 sector_size 选项。"
+
+#: lib/random.c:80
+msgid ""
+"System is out of entropy while generating volume key.\n"
+"Please move mouse or type some text in another window to gather some random events.\n"
+msgstr ""
+"系统在生成卷密钥时熵不足。\n"
+"请随意移动鼠标或是在别的窗口打字,以便生成随机事件让系统使用。\n"
+
+#: lib/random.c:84
+#, c-format
+msgid "Generating key (%d%% done).\n"
+msgstr "正生成密钥(%d%% 已完成)\n"
+
+#: lib/random.c:170
+msgid "Running in FIPS mode."
+msgstr "在 FIPS 模式下运行。"
+
+#: lib/random.c:176
+msgid "Fatal error during RNG initialisation."
+msgstr "随机数生成器初始化时发生致命错误。"
+
+#: lib/random.c:213
+msgid "Unknown RNG quality requested."
+msgstr "未知的随机数生成器质量请求。"
+
+#: lib/random.c:218
+msgid "Error reading from RNG."
+msgstr "从随机数生成器(RNG)读取时出错。"
+
+#: lib/setup.c:203
+msgid "Cannot initialize crypto RNG backend."
+msgstr "无法初始化加密随机数生成器后端。"
+
+#: lib/setup.c:209
+msgid "Cannot initialize crypto backend."
+msgstr "无法初始化加密后端。"
+
+#: lib/setup.c:240 lib/setup.c:1766 lib/verity/verity.c:123
+#, c-format
+msgid "Hash algorithm %s not supported."
+msgstr "不支持哈希算法 %s。"
+
+#: lib/setup.c:243 lib/loopaes/loopaes.c:90
+#, c-format
+msgid "Key processing error (using hash %s)."
+msgstr "密钥处理错误(使用散列 %s)。"
+
+#: lib/setup.c:304 lib/setup.c:331
+msgid "Cannot determine device type. Incompatible activation of device?"
+msgstr "无法确定设备类型。不兼容的设备激活?"
+
+#: lib/setup.c:310 lib/setup.c:2326
+msgid "This operation is supported only for LUKS device."
+msgstr "此操作只适用 LUKS 设备。"
+
+#: lib/setup.c:337
+msgid "This operation is supported only for LUKS2 device."
+msgstr "此操作只适用 LUKS2 设备。"
+
+#: lib/setup.c:382
+msgid "All key slots full."
+msgstr "密钥槽全都满了。"
+
+#: lib/setup.c:393
+#, c-format
+msgid "Key slot %d is invalid, please select between 0 and %d."
+msgstr "密钥槽 %d 无效,请选择 0 到 %d 间的数字。"
+
+#: lib/setup.c:399
+#, c-format
+msgid "Key slot %d is full, please select another one."
+msgstr "密钥槽 %d 满了,请选择另一个。"
+
+#: lib/setup.c:597
+#, c-format
+msgid "Header detected but device %s is too small."
+msgstr "检测到标头但设备 %s 太小。"
+
+#: lib/setup.c:616
+msgid "This operation is not supported for this device type."
+msgstr "不支持在这类设备上执行此操作。"
+
+#: lib/setup.c:1239 lib/setup.c:2066 lib/setup.c:3300
+#, c-format
+msgid "Device %s is not active."
+msgstr "设备 %s 未激活。"
+
+#: lib/setup.c:1256
+#, c-format
+msgid "Underlying device for crypt device %s disappeared."
+msgstr "加密设备 %s 下层的设备消失了。"
+
+#: lib/setup.c:1336
+msgid "Invalid plain crypt parameters."
+msgstr "无效的纯加密选项。"
+
+#: lib/setup.c:1341 lib/setup.c:1680 src/integritysetup.c:68
+msgid "Invalid key size."
+msgstr "无效的密钥大小。"
+
+#: lib/setup.c:1346 lib/setup.c:1685 lib/setup.c:1876
+msgid "UUID is not supported for this crypt type."
+msgstr "此加密类型不支持 UUID。"
+
+#: lib/setup.c:1356 lib/setup.c:1500 src/cryptsetup.c:950
+msgid "Unsupported encryption sector size."
+msgstr "不支持的加密扇区大小。"
+
+#: lib/setup.c:1402 lib/setup.c:1494
+msgid "Can't format LUKS without device."
+msgstr "无法在没有设备的情况下格式化 LUKS。"
+
+#: lib/setup.c:1464 lib/setup.c:1617 lib/setup.c:1888
+#, c-format
+msgid "Cannot wipe header on device %s."
+msgstr "无法将设备 %s 上的标头擦除。"
+
+#: lib/setup.c:1523
+msgid "Volume key is too small for encryption with integrity extensions."
+msgstr "卷密钥对于带完整性校验扩展的加密而言过小。"
+
+#: lib/setup.c:1530 lib/utils_device.c:599
+#, c-format
+msgid "Cannot use device %s which is in use (already mapped or mounted)."
+msgstr "无法使用正被使用的设备 %s(已被映射或挂载)。"
+
+#: lib/setup.c:1610
+#, c-format
+msgid "Cannot format device %s which is still in use."
+msgstr "无法格式化正在使用的设备 %s。"
+
+#: lib/setup.c:1613 lib/setup.c:1648
+#, c-format
+msgid "Cannot format device %s, permission denied."
+msgstr "无法格式化设备 %s,权限被拒绝。"
+
+#: lib/setup.c:1625 lib/luks2/luks2_json_metadata.c:863
+#: lib/luks2/luks2_json_metadata.c:1141 lib/luks2/luks2_keyslot.c:429
+#: lib/luks2/luks2_keyslot_luks2.c:40 lib/luks2/luks2_keyslot_luks2.c:69
+#, c-format
+msgid "Failed to acquire write lock on device %s."
+msgstr "无法获取设备 %s 上的写入锁。"
+
+#: lib/setup.c:1633 lib/setup.c:1940
+#, fuzzy, c-format
+#| msgid "Cannot write device %s.\n"
+msgid "Cannot format integrity for device %s."
+msgstr "无法写入设备 %s。\n"
+
+#: lib/setup.c:1645
+#, c-format
+msgid "Cannot format device %s in use."
+msgstr "无法格式化正在使用的设备 %s。"
+
+#: lib/setup.c:1652
+#, c-format
+msgid "Cannot format device %s."
+msgstr "无法格式化设备 %s。"
+
+#: lib/setup.c:1675
+msgid "Can't format LOOPAES without device."
+msgstr "无法在没有设备的情况下格式化 LOOPAES。"
+
+#: lib/setup.c:1715
+msgid "Can't format VERITY without device."
+msgstr "无法在没有设备的情况下格式化 VERIFY。"
+
+#: lib/setup.c:1723 lib/verity/verity.c:106
+#, c-format
+msgid "Unsupported VERITY hash type %d."
+msgstr "不支持的 VERITY 哈希类型 %d。"
+
+#: lib/setup.c:1729 lib/verity/verity.c:114
+msgid "Unsupported VERITY block size."
+msgstr "不支持的 VERITY 块大小。"
+
+#: lib/setup.c:1734 lib/verity/verity.c:75
+msgid "Unsupported VERITY hash offset."
+msgstr "不支持的 VERITY 哈希偏移量。"
+
+#: lib/setup.c:1739
+msgid "Unsupported VERITY FEC offset."
+msgstr "不支持的 VERITY 哈希偏移量。"
+
+#: lib/setup.c:1760
+msgid "Data area overlaps with hash area."
+msgstr "数据区域重叠覆盖了哈希区域。"
+
+#: lib/setup.c:1785
+msgid "Hash area overlaps with FEC area."
+msgstr "哈希区域重叠覆盖了 FEC 区域。"
+
+#: lib/setup.c:1792
+msgid "Data area overlaps with FEC area."
+msgstr "数据区域重叠覆盖了 FEC 区域。"
+
+#: lib/setup.c:1997
+#, c-format
+msgid "Unknown crypt device type %s requested."
+msgstr "请求了未知的加密设备类型 %s。"
+
+#: lib/setup.c:2098
+msgid "Cannot resize loop device."
+msgstr "无法改变回环设备大小。"
+
+#: lib/setup.c:2107
+#, c-format
+msgid "Device %s size is not aligned to requested sector size (%u bytes)."
+msgstr "设备 %s 的大小没有和请求的扇区大小对齐(%u 字节)。"
+
+#: lib/setup.c:2161
+msgid "Do you really want to change UUID of device?"
+msgstr "你真的想改变设备的 UUID 吗?"
+
+#: lib/setup.c:2237
+msgid "Header backup file does not contain compatible LUKS header."
+msgstr "标头备份文件不包含兼容的 LUKS 标头。"
+
+#: lib/setup.c:2334
+#, c-format
+msgid "Volume %s is not active."
+msgstr "卷 %s 未激活。"
+
+#: lib/setup.c:2345
+#, c-format
+msgid "Volume %s is already suspended."
+msgstr "卷 %s 已挂起。"
+
+#: lib/setup.c:2359
+#, c-format
+msgid "Suspend is not supported for device %s."
+msgstr "设备 %s 不支持挂起。"
+
+#: lib/setup.c:2361
+#, c-format
+msgid "Error during suspending device %s."
+msgstr "挂起设备 %s 时出错。"
+
+#: lib/setup.c:2394 lib/setup.c:2461
+#, c-format
+msgid "Volume %s is not suspended."
+msgstr "卷 %s 未挂起。"
+
+#: lib/setup.c:2423
+#, c-format
+msgid "Resume is not supported for device %s."
+msgstr "设备 %s 不支持恢复。"
+
+#: lib/setup.c:2425 lib/setup.c:2493
+#, c-format
+msgid "Error during resuming device %s."
+msgstr "恢复设备 %s 时出错。"
+
+#: lib/setup.c:2561 lib/setup.c:2754
+msgid "Cannot add key slot, all slots disabled and no volume key provided."
+msgstr "无法添加密钥槽,所有密钥槽已禁用且未提供卷密钥。"
+
+#: lib/setup.c:2698
+#, c-format
+msgid "Key slot %d changed."
+msgstr "密钥槽 %d 已改变。"
+
+#: lib/setup.c:2701
+#, c-format
+msgid "Replaced with key slot %d."
+msgstr "替换为密钥槽 %d。"
+
+#: lib/setup.c:2706
+msgid "Failed to swap new key slot."
+msgstr "交换新密钥槽失败。"
+
+#: lib/setup.c:2871 lib/setup.c:3145 lib/setup.c:3158 lib/setup.c:3166
+#: lib/setup.c:3179 lib/setup.c:3453 lib/setup.c:4370
+msgid "Volume key does not match the volume."
+msgstr "卷密钥与卷不匹配。"
+
+#: lib/setup.c:2892
+#, c-format
+msgid "Key slot %d is invalid."
+msgstr "密钥槽 %d 无效。"
+
+#: lib/setup.c:2898
+#, c-format
+msgid "Key slot %d is not used."
+msgstr "密钥槽 %d 未使用。"
+
+#: lib/setup.c:2968 lib/setup.c:3232
+msgid "Device type is not properly initialised."
+msgstr "设备类型未正确初始化。"
+
+#: lib/setup.c:3010
+#, c-format
+msgid "Cannot use device %s, name is invalid or still in use."
+msgstr "无法使用设备 %s,名称无效或它正被使用。"
+
+#: lib/setup.c:3013
+#, c-format
+msgid "Device %s already exists."
+msgstr "设备 %s 已存在。"
+
+#: lib/setup.c:3132
+msgid "Incorrect volume key specified for plain device."
+msgstr "为普通设备指定的卷密钥有误。"
+
+#: lib/setup.c:3198
+msgid "Incorrect root hash specified for verity device."
+msgstr "为 verity 设备指定的根 hash 不正确。"
+
+#: lib/setup.c:3274 lib/setup.c:3289
+#, c-format
+msgid "Device %s is still in use."
+msgstr "设备 %s 仍在使用。"
+
+#: lib/setup.c:3304
+#, c-format
+msgid "Invalid device %s."
+msgstr "设备 %s 无效。"
+
+#: lib/setup.c:3389
+msgid "Function not available in FIPS mode."
+msgstr "功能在 FIPS 模式无效。"
+
+#: lib/setup.c:3403
+msgid "Volume key buffer too small."
+msgstr "卷密钥缓冲区太小。"
+
+#: lib/setup.c:3411
+msgid "Cannot retrieve volume key for plain device."
+msgstr "无法获取普通设备的卷密钥。"
+
+#: lib/setup.c:3422
+#, c-format
+msgid "This operation is not supported for %s crypt device."
+msgstr "不支持在 %s 加密设备上执行此操作。"
+
+#: lib/setup.c:3609
+msgid "Dump operation is not supported for this device type."
+msgstr "不支持在此类设备上执行导出操作。"
+
+#: lib/setup.c:4018
+#, c-format
+msgid "Cannot convert device %s which is still in use."
+msgstr "无法转换正在使用的设备 %s。"
+
+#: lib/setup.c:4301
+#, c-format
+msgid "Failed to assign keyslot %u as the new volume key."
+msgstr "将密钥槽 %u 指定为新卷密钥的操作失败。"
+
+#: lib/setup.c:4364
+msgid "Failed to initialise default LUKS2 keyslot parameters."
+msgstr "初始化默认 LUKS2 密钥槽参数失败。"
+
+#: lib/setup.c:4376
+#, fuzzy, c-format
+#| msgid "Failed to swap new key slot.\n"
+msgid "Failed to assign keyslot %d to digest."
+msgstr "交换新密钥槽失败。\n"
+
+#: lib/setup.c:4460
+msgid "Failed to load key in kernel keyring."
+msgstr "在内核密钥环中加载密钥失败。"
+
+#: lib/setup.c:4515
+msgid "Kernel keyring is not supported by the kernel."
+msgstr "该内核不支持内核密钥环。"
+
+#: lib/setup.c:4525
+#, c-format
+msgid "Failed to read passphrase from keyring (error %d)."
+msgstr "从密钥环读取口令失败(错误 %d)。"
+
+#: lib/utils.c:81
+msgid "Cannot get process priority."
+msgstr "无法获取进程优先级。"
+
+#: lib/utils.c:95
+msgid "Cannot unlock memory."
+msgstr "无法解锁内存。"
+
+#: lib/utils.c:169 lib/tcrypt/tcrypt.c:475
+msgid "Failed to open key file."
+msgstr "打开 (open) 密钥文件失败。"
+
+#: lib/utils.c:174
+msgid "Cannot read keyfile from a terminal."
+msgstr "无法从终端读取密钥文件。"
+
+# stat() 主要就是出来一个各种文件信息……
+#: lib/utils.c:191
+msgid "Failed to stat key file."
+msgstr "获取 (stat) 密钥文件信息失败。"
+
+#: lib/utils.c:199 lib/utils.c:220
+msgid "Cannot seek to requested keyfile offset."
+msgstr "无法寻找 (seek) 到请求的密钥文件偏移量。"
+
+#: lib/utils.c:214 lib/utils.c:229 src/utils_password.c:207
+#: src/utils_password.c:220
+msgid "Out of memory while reading passphrase."
+msgstr "读取密码时内存耗尽。"
+
+#: lib/utils.c:249
+msgid "Error reading passphrase."
+msgstr "读取口令出错。"
+
+#: lib/utils.c:273
+msgid "Maximum keyfile size exceeded."
+msgstr "超出最大密钥文件大小。"
+
+#: lib/utils.c:278
+msgid "Cannot read requested amount of data."
+msgstr "无法读取请求量的数据。"
+
+#: lib/utils_device.c:184 lib/luks1/keyencryption.c:101
+#, c-format
+msgid "Device %s doesn't exist or access denied."
+msgstr "设备 %s 不存在或访问被拒绝。"
+
+#: lib/utils_device.c:603
+#, c-format
+msgid "Cannot use device %s, permission denied."
+msgstr "无法使用设备 %s,权限被拒绝。"
+
+#: lib/utils_device.c:606
+#, c-format
+msgid "Cannot get info about device %s."
+msgstr "无法获取有关设备 %s 的信息。"
+
+#: lib/utils_device.c:628
+msgid "Cannot use a loopback device, running as non-root user."
+msgstr "无法使用回环设备,正作为非 root 用户运行。"
+
+#: lib/utils_device.c:638
+msgid "Attaching loopback device failed (loop device with autoclear flag is required)."
+msgstr "连接回环设备失败(需要有 autoclear 旗标的回环设备)。"
+
+#: lib/utils_device.c:684
+#, c-format
+msgid "Requested offset is beyond real size of device %s."
+msgstr "请求的偏移量超出设备 %s 的真实大小。"
+
+#: lib/utils_device.c:692
+#, c-format
+msgid "Device %s has zero size."
+msgstr "设备 %s 大小为零。"
+
+#: lib/utils_device.c:703
+#, c-format
+msgid "Device %s is too small."
+msgstr "设备 %s 太小。"
+
+#: lib/utils_pbkdf.c:74
+#, c-format
+msgid "Unknown PBKDF type %s."
+msgstr "未知的 PBKDF 类型 %s。"
+
+#: lib/utils_pbkdf.c:85
+msgid "Requested PBKDF type is not supported for LUKS1."
+msgstr "请求的 PBKDF 类型不被 LUKS1 支持。"
+
+#: lib/utils_pbkdf.c:91
+msgid "PBKDF max memory or parallel threads must not be set with pbkdf2."
+msgstr ""
+
+#: lib/utils_pbkdf.c:96 lib/utils_pbkdf.c:106
+#, c-format
+msgid "Forced iteration count is too low for %s (minimum is %u)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:111
+#, c-format
+msgid "Forced memory cost is too low for %s (minimum is %u kilobytes)."
+msgstr ""
+
+#: lib/utils_pbkdf.c:118
+#, c-format
+msgid "Requested maximum PBKDF memory cost is too high (maximum is %d kilobytes)."
+msgstr "请求的最大 PBKDF 内存开销过大(最大为 %d 千字节)。"
+
+#: lib/utils_pbkdf.c:123
+msgid "Requested maximum PBKDF memory can not be zero."
+msgstr "请求的最大 PBKDF 内存使用量不能为零。"
+
+#: lib/utils_pbkdf.c:127
+msgid "Requested PBKDF parallel threads can not be zero."
+msgstr "请求的 PBKDF 并行线程数不能为零。"
+
+#: lib/utils_pbkdf.c:131
+msgid "Requested PBKDF target time can not be zero."
+msgstr "请求的 PBKDF 目标时间不能为零。"
+
+#: lib/utils_benchmark.c:304
+msgid "PBKDF benchmark disabled but iterations not set."
+msgstr ""
+
+#: lib/utils_benchmark.c:326
+#, c-format
+msgid "Not compatible PBKDF2 options (using hash algorithm %s)."
+msgstr "PBKDF2 选项不兼容(正在使用哈希算法 %s)。"
+
+#: lib/utils_benchmark.c:340
+msgid "Not compatible PBKDF options."
+msgstr "PBKDF2 选项不兼容。"
+
+#: lib/utils_device_locking.c:80
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."
+msgstr "锁定中止。锁定路径 %s/%s 不可用(不是一个目录或缺失)。"
+
+#: lib/utils_device_locking.c:87
+#, c-format
+msgid "WARNING: Locking directory %s/%s is missing!\n"
+msgstr "警告:锁定目录 %s/%s 缺失!\n"
+
+#: lib/utils_device_locking.c:97
+#, c-format
+msgid "Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."
+msgstr "锁定中止。锁定路径 %s/%s 不可用(%s 不是目录)。"
+
+#: lib/luks1/keyencryption.c:39
+#, c-format
+msgid ""
+"Failed to setup dm-crypt key mapping for device %s.\n"
+"Check that kernel supports %s cipher (check syslog for more info)."
+msgstr ""
+"为设备 %s 配置 dm-crypt 键映射失败。\n"
+"请确认内核支持 %s 加密(查看系统日志 (syslog) 以获取更多信息)。"
+
+#: lib/luks1/keyencryption.c:44
+msgid "Key size in XTS mode must be 256 or 512 bits."
+msgstr "XTS 模式的密钥大小必须是 256 或 512 位。"
+
+#: lib/luks1/keyencryption.c:46
+msgid "Cipher specification should be in [cipher]-[mode]-[iv] format."
+msgstr ""
+
+#: lib/luks1/keyencryption.c:107 lib/luks1/keymanage.c:362
+#: lib/luks1/keymanage.c:658 lib/luks1/keymanage.c:1094
+#: lib/luks2/luks2_json_metadata.c:1149 lib/luks2/luks2_keyslot.c:446
+#, c-format
+msgid "Cannot write to device %s, permission denied."
+msgstr "无法写入到设备 %s,访问被拒绝。"
+
+#: lib/luks1/keyencryption.c:122
+msgid "Failed to open temporary keystore device."
+msgstr "打开临时密钥存储设备失败。"
+
+#: lib/luks1/keyencryption.c:129
+msgid "Failed to access temporary keystore device."
+msgstr "访问临时密钥存储设备失败。"
+
+#: lib/luks1/keyencryption.c:199 lib/luks2/luks2_keyslot_luks2.c:89
+msgid "IO error while encrypting keyslot."
+msgstr "加密密钥槽时发生输入输出错误。"
+
+#: lib/luks1/keyencryption.c:261 lib/luks2/luks2_keyslot_luks2.c:150
+msgid "IO error while decrypting keyslot."
+msgstr "解密密钥槽时发生输入输出错误。"
+
+#: lib/luks1/keymanage.c:128
+#, c-format
+msgid "Device %s is too small. (LUKS1 requires at least %<PRIu64> bytes.)"
+msgstr "设备 %s 过小。(LUKS1 需要至少 %<PRIu64> 字节。)"
+
+#: lib/luks1/keymanage.c:149 lib/luks1/keymanage.c:157
+#: lib/luks1/keymanage.c:169 lib/luks1/keymanage.c:180
+#: lib/luks1/keymanage.c:192
+#, c-format
+msgid "LUKS keyslot %u is invalid."
+msgstr "LUKS 密钥槽 %u 无效。"
+
+#: lib/luks1/keymanage.c:245 lib/luks1/keymanage.c:494
+#: lib/luks2/luks2_json_metadata.c:983 src/cryptsetup_reencrypt.c:1396
+#, c-format
+msgid "Device %s is not a valid LUKS device."
+msgstr "%s 不是有效的 LUKS 设备。"
+
+#: lib/luks1/keymanage.c:264 lib/luks2/luks2_json_metadata.c:1002
+#, c-format
+msgid "Requested header backup file %s already exists."
+msgstr "请求的标头备份文件 %s 已存在。"
+
+#: lib/luks1/keymanage.c:266 lib/luks2/luks2_json_metadata.c:1004
+#, c-format
+msgid "Cannot create header backup file %s."
+msgstr "无法创建标头备份文件 %s。"
+
+#: lib/luks1/keymanage.c:271 lib/luks2/luks2_json_metadata.c:1009
+#, c-format
+msgid "Cannot write header backup file %s."
+msgstr "无法写入标头备份文件 %s。"
+
+#: lib/luks1/keymanage.c:304 lib/luks2/luks2_json_metadata.c:1058
+msgid "Backup file doesn't contain valid LUKS header."
+msgstr "备份文件不包含有效 LUKS 标头。"
+
+#: lib/luks1/keymanage.c:317 lib/luks1/keymanage.c:571
+#: lib/luks2/luks2_json_metadata.c:1079
+#, c-format
+msgid "Cannot open header backup file %s."
+msgstr "无法打开备份标头文件 %s。"
+
+#: lib/luks1/keymanage.c:323 lib/luks2/luks2_json_metadata.c:1085
+#, c-format
+msgid "Cannot read header backup file %s."
+msgstr "无法读取标头备份文件 %s。"
+
+#: lib/luks1/keymanage.c:335
+#, fuzzy
+#| msgid "Data offset or key size differs on device and backup, restore failed.\n"
+msgid "Data offset or key size differs on device and backup, restore failed."
+msgstr "源设备和备份上的数据偏移或密钥大小不符,恢复失败。\n"
+
+#: lib/luks1/keymanage.c:343
+#, c-format
+msgid "Device %s %s%s"
+msgstr "设备 %s %s%s"
+
+#: lib/luks1/keymanage.c:344
+msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgstr "不包含 LUKS 标头。替换标头可能损毁设备上的数据。"
+
+#: lib/luks1/keymanage.c:345
+msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgstr "已包含 LUKS 标头。替换标头将损毁已存在的密钥槽。"
+
+#: lib/luks1/keymanage.c:346 lib/luks2/luks2_json_metadata.c:1121
+msgid ""
+"\n"
+"WARNING: real device header has different UUID than backup!"
+msgstr ""
+"\n"
+"警告: 真实设备标头 UUID 和备份不符!"
+
+#: lib/luks1/keymanage.c:365 lib/luks1/keymanage.c:610
+#: lib/luks1/keymanage.c:661 lib/tcrypt/tcrypt.c:640 lib/verity/verity.c:81
+#: lib/verity/verity.c:182 lib/verity/verity_hash.c:308
+#: lib/verity/verity_hash.c:319 lib/verity/verity_hash.c:339
+#: lib/verity/verity_fec.c:241 lib/verity/verity_fec.c:253
+#: lib/verity/verity_fec.c:258 lib/luks2/luks2_json_metadata.c:1152
+#: src/cryptsetup_reencrypt.c:207
+#, c-format
+msgid "Cannot open device %s."
+msgstr "无法打开设备 %s。"
+
+#: lib/luks1/keymanage.c:396
+msgid "Non standard key size, manual repair required."
+msgstr "不标准的密钥大小,需要手动修复。"
+
+#: lib/luks1/keymanage.c:401
+msgid "Non standard keyslots alignment, manual repair required."
+msgstr "不标准的密钥槽对齐,需要手动修复。"
+
+#: lib/luks1/keymanage.c:411
+msgid "Repairing keyslots."
+msgstr "正在修复密钥槽。"
+
+#: lib/luks1/keymanage.c:431
+#, c-format
+msgid "Keyslot %i: offset repaired (%u -> %u)."
+msgstr "密钥槽 %i: 偏移已修复 (%u -> %u)。"
+
+#: lib/luks1/keymanage.c:439
+#, c-format
+msgid "Keyslot %i: stripes repaired (%u -> %u)."
+msgstr "密钥槽 %i:已修复条带(%u -> %u)。"
+
+#: lib/luks1/keymanage.c:448
+#, c-format
+msgid "Keyslot %i: bogus partition signature."
+msgstr "密钥槽 %i:虚假的分区签名。"
+
+#: lib/luks1/keymanage.c:453
+#, c-format
+msgid "Keyslot %i: salt wiped."
+msgstr "密钥槽 %i: 已清除盐。"
+
+#: lib/luks1/keymanage.c:470
+msgid "Writing LUKS header to disk."
+msgstr "正在将 LUKS 标头写入磁盘。"
+
+#: lib/luks1/keymanage.c:475
+msgid "Repair failed."
+msgstr "修复失败。"
+
+#: lib/luks1/keymanage.c:497
+#, c-format
+msgid "Unsupported LUKS version %d."
+msgstr "不支持的 LUKS 版本 %d。"
+
+#: lib/luks1/keymanage.c:503 lib/luks1/keymanage.c:749
+#, c-format
+msgid "Requested LUKS hash %s is not supported."
+msgstr "不支持请求的 LUKS 哈希 %s。"
+
+#: lib/luks1/keymanage.c:531 src/cryptsetup.c:869
+msgid "No known problems detected for LUKS header."
+msgstr "未在 LUKS 标头发现已知问题。"
+
+#: lib/luks1/keymanage.c:683
+#, c-format
+msgid "Error during update of LUKS header on device %s."
+msgstr "更新设备 %s 上的 LUKS 标头时出错。"
+
+#: lib/luks1/keymanage.c:690
+#, c-format
+msgid "Error re-reading LUKS header after update on device %s."
+msgstr "在更新设备 %s 后重新读取 LUKS 标头失败。"
+
+#: lib/luks1/keymanage.c:742
+#, c-format
+msgid "Data offset for detached LUKS header must be either 0 or higher than header size (%d sectors)."
+msgstr "分离的 LUKS 标头的数据偏移量必须为零或高于标头大小(%d 扇区)。"
+
+#: lib/luks1/keymanage.c:754 lib/luks1/keymanage.c:840
+#: lib/luks2/luks2_json_format.c:145 lib/luks2/luks2_json_metadata.c:894
+msgid "Wrong LUKS UUID format provided."
+msgstr "提供了错误的 LUKS UUID 格式。"
+
+#: lib/luks1/keymanage.c:779
+msgid "Cannot create LUKS header: reading random salt failed."
+msgstr "无法创建 LUKS 标头:读取随机盐失败。"
+
+#: lib/luks1/keymanage.c:800
+#, c-format
+msgid "Cannot create LUKS header: header digest failed (using hash %s)."
+msgstr "无法创建 LUKS 标头:标头摘要失败(正在使用哈希 %s)。"
+
+#: lib/luks1/keymanage.c:863
+#, c-format
+msgid "Key slot %d active, purge first."
+msgstr "密钥槽 %d 已激活,请先清除。"
+
+#: lib/luks1/keymanage.c:869
+#, fuzzy, c-format
+#| msgid "Key slot %d material includes too few stripes. Header manipulation?\n"
+msgid "Key slot %d material includes too few stripes. Header manipulation?"
+msgstr "密钥槽 %d 条带数过少。标头修改?\n"
+
+#: lib/luks1/keymanage.c:1028
+#, c-format
+msgid "Key slot %d unlocked."
+msgstr "密钥槽 %d 已解锁。"
+
+#: lib/luks1/keymanage.c:1080
+#, fuzzy, c-format
+#| msgid "Key slot %d is invalid, please select keyslot between 0 and %d.\n"
+msgid "Key slot %d is invalid, please select keyslot between 0 and %d."
+msgstr "密钥槽 %d 无效,请选择标号 0 到 %d 间的密钥槽。\n"
+
+#: lib/luks1/keymanage.c:1098 lib/luks2/luks2_keyslot.c:450
+#, c-format
+msgid "Cannot wipe device %s."
+msgstr "无法擦除设备 %s。"
+
+#: lib/loopaes/loopaes.c:146
+msgid "Detected not yet supported GPG encrypted keyfile.\n"
+msgstr "探测到未支持的 GPG 加密密钥文件。\n"
+
+#: lib/loopaes/loopaes.c:147
+msgid "Please use gpg --decrypt <KEYFILE> | cryptsetup --keyfile=- ...\n"
+msgstr "请使用 gpg --decrypt <密钥文件> | cryptsetup --keyfile=- ...\n"
+
+#: lib/loopaes/loopaes.c:168 lib/loopaes/loopaes.c:188
+msgid "Incompatible loop-AES keyfile detected."
+msgstr "探测到不兼容的 loop-AES 密钥文件。"
+
+#: lib/loopaes/loopaes.c:246
+#, fuzzy
+#| msgid "Kernel doesn't support loop-AES compatible mapping.\n"
+msgid "Kernel doesn't support loop-AES compatible mapping."
+msgstr "内核不支持 loop-AES 兼容映射。\n"
+
+#: lib/tcrypt/tcrypt.c:482
+#, c-format
+msgid "Error reading keyfile %s."
+msgstr "读取密钥文件 %s 出错。"
+
+#: lib/tcrypt/tcrypt.c:522
+#, c-format
+msgid "Maximum TCRYPT passphrase length (%d) exceeded."
+msgstr "超出 TCRYPT 口令最大长度限制 (%d)。"
+
+#: lib/tcrypt/tcrypt.c:563
+#, c-format
+msgid "PBKDF2 hash algorithm %s not available, skipping."
+msgstr "PBKDF2 哈希算法 %s 不可用,将跳过。"
+
+#: lib/tcrypt/tcrypt.c:581 src/cryptsetup.c:820
+msgid "Required kernel crypto interface not available."
+msgstr "无法找到所需的内核加密接口。"
+
+#: lib/tcrypt/tcrypt.c:583 src/cryptsetup.c:822
+msgid "Ensure you have algif_skcipher kernel module loaded."
+msgstr "请确定您已载入内核模块 algif_skcipher。"
+
+#: lib/tcrypt/tcrypt.c:729
+#, c-format
+msgid "Activation is not supported for %d sector size."
+msgstr "扇区大小为 %d 时不支持激活。"
+
+#: lib/tcrypt/tcrypt.c:735
+msgid "Kernel doesn't support activation for this TCRYPT legacy mode."
+msgstr "内核不支持激活此处的旧 TCRYPT 模式。"
+
+#: lib/tcrypt/tcrypt.c:769
+#, c-format
+msgid "Activating TCRYPT system encryption for partition %s."
+msgstr "正在为分区 %s 激活 TCRYPT 系统加密。"
+
+#: lib/tcrypt/tcrypt.c:837
+msgid "Kernel doesn't support TCRYPT compatible mapping."
+msgstr "内核不支持 TCRYPT 兼容映射。"
+
+#: lib/tcrypt/tcrypt.c:1052
+msgid "This function is not supported without TCRYPT header load."
+msgstr "未载入 TCRYPT 标头时不支持此功能。"
+
+#: lib/verity/verity.c:69 lib/verity/verity.c:175
+#, c-format
+msgid "Verity device %s doesn't use on-disk header."
+msgstr "Verity 设备 %s 未使用磁盘上的标头。"
+
+#: lib/verity/verity.c:94
+#, c-format
+msgid "Device %s is not a valid VERITY device."
+msgstr "%s 不是有效的 VERITY 设备。"
+
+#: lib/verity/verity.c:101
+#, c-format
+msgid "Unsupported VERITY version %d."
+msgstr "不支持的 VERITY 版本 %d。"
+
+#: lib/verity/verity.c:132
+msgid "VERITY header corrupted."
+msgstr "VERITY 标头损坏。"
+
+#: lib/verity/verity.c:169
+#, fuzzy, c-format
+#| msgid "Wrong VERITY UUID format provided on device %s.\n"
+msgid "Wrong VERITY UUID format provided on device %s."
+msgstr "为设备 %s 提供的 VERITY UUID 错误。\n"
+
+#: lib/verity/verity.c:202
+#, fuzzy, c-format
+#| msgid "Error during update of verity header on device %s.\n"
+msgid "Error during update of verity header on device %s."
+msgstr "更新设备 %s 上的 VERITY 标头时出错。\n"
+
+#: lib/verity/verity.c:259
+msgid "Errors cannot be repaired with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:261
+#, c-format
+msgid "Found %u repairable errors with FEC device."
+msgstr ""
+
+#: lib/verity/verity.c:305
+msgid "Kernel doesn't support dm-verity mapping."
+msgstr "内核不支持 dm-verity 映射。"
+
+#: lib/verity/verity.c:316
+#, fuzzy
+#| msgid "Verity device detected corruption after activation.\n"
+msgid "Verity device detected corruption after activation."
+msgstr "在 VERITY 设备激活后探测到损坏。\n"
+
+#: lib/verity/verity_hash.c:59
+#, fuzzy, c-format
+#| msgid "Spare area is not zeroed at position %<PRIu64>.\n"
+msgid "Spare area is not zeroed at position %<PRIu64>."
+msgstr "备用区位置 %<PRIu64> 未清零。\n"
+
+#: lib/verity/verity_hash.c:160 lib/verity/verity_hash.c:287
+#: lib/verity/verity_hash.c:300
+msgid "Device offset overflow."
+msgstr "设备偏移量溢出。"
+
+#: lib/verity/verity_hash.c:200
+#, fuzzy, c-format
+#| msgid "Verification failed at position %<PRIu64>.\n"
+msgid "Verification failed at position %<PRIu64>."
+msgstr "在 %<PRIu64> 上发生检验错误。\n"
+
+#: lib/verity/verity_hash.c:273
+#, fuzzy
+#| msgid "Invalid size parameters for verity device.\n"
+msgid "Invalid size parameters for verity device."
+msgstr "为 VERITY 设备提供的大小指标无效。\n"
+
+#: lib/verity/verity_hash.c:293
+msgid "Hash area overflow."
+msgstr "哈希区域溢出。"
+
+#: lib/verity/verity_hash.c:370
+msgid "Verification of data area failed."
+msgstr "数据区检验失败。"
+
+#: lib/verity/verity_hash.c:375
+msgid "Verification of root hash failed."
+msgstr "根哈希值检验失败。"
+
+#: lib/verity/verity_hash.c:381
+#, fuzzy
+#| msgid "Input/output error while creating hash area.\n"
+msgid "Input/output error while creating hash area."
+msgstr "创建哈希数据区时发生输入/输出错误。\n"
+
+#: lib/verity/verity_hash.c:383
+msgid "Creation of hash area failed."
+msgstr "创建哈希区失败。"
+
+#: lib/verity/verity_hash.c:430
+#, fuzzy, c-format
+#| msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u).\n"
+msgid "WARNING: Kernel cannot activate device if data block size exceeds page size (%u)."
+msgstr "警告:如数据块大小超过内存分页大小,内核将无法激活设备 (%u)。\n"
+
+#: lib/verity/verity_fec.c:132
+#, fuzzy
+#| msgid "Failed to open key file.\n"
+msgid "Failed to allocate RS context."
+msgstr "打开 (open) 密钥文件失败。\n"
+
+# stat() 主要就是出来一个各种文件信息……
+#: lib/verity/verity_fec.c:147
+#, fuzzy
+#| msgid "Failed to stat key file.\n"
+msgid "Failed to allocate buffer."
+msgstr "获取 (stat) 密钥文件统计数据失败。\n"
+
+#: lib/verity/verity_fec.c:157
+#, fuzzy, c-format
+#| msgid "Failed to access temporary keystore device.\n"
+msgid "Failed to read RS block %<PRIu64> byte %d."
+msgstr "无法访问临时密钥存储设备。\n"
+
+#: lib/verity/verity_fec.c:170
+#, fuzzy, c-format
+#| msgid "Failed to access temporary keystore device.\n"
+msgid "Failed to read parity for RS block %<PRIu64>."
+msgstr "无法访问临时密钥存储设备。\n"
+
+#: lib/verity/verity_fec.c:177
+#, fuzzy, c-format
+#| msgid "Failed to access temporary keystore device.\n"
+msgid "Failed to repair parity for block %<PRIu64>."
+msgstr "无法访问临时密钥存储设备。\n"
+
+#: lib/verity/verity_fec.c:188
+#, fuzzy, c-format
+#| msgid "Failed to access temporary keystore device.\n"
+msgid "Failed to write parity for RS block %<PRIu64>."
+msgstr "无法访问临时密钥存储设备。\n"
+
+#: lib/verity/verity_fec.c:223
+msgid "Block sizes must match for FEC."
+msgstr ""
+
+#: lib/verity/verity_fec.c:229
+msgid "Invalid number of parity bytes."
+msgstr ""
+
+#: lib/verity/verity_fec.c:265
+#, fuzzy, c-format
+#| msgid "Failed to open temporary keystore device.\n"
+msgid "Failed to determine size for device %s."
+msgstr "打开临时密钥存储设备失败。\n"
+
+#: lib/integrity/integrity.c:219 lib/integrity/integrity.c:270
+#, fuzzy
+#| msgid "Kernel doesn't support dm-verity mapping.\n"
+msgid "Kernel doesn't support dm-integrity mapping."
+msgstr "内核不支持 dm-verity 映射。\n"
+
+#: lib/luks2/luks2_disk_metadata.c:364
+#, c-format
+msgid "Device %s is too small. (LUKS2 requires at least %<PRIu64> bytes.)"
+msgstr "设备 %s 过小。(LUKS2 需要至少 %<PRIu64> 字节。)"
+
+#: lib/luks2/luks2_disk_metadata.c:428
+msgid "Failed to acquire write device lock."
+msgstr "无法获取写入设备锁。"
+
+#: lib/luks2/luks2_json_format.c:99
+#, fuzzy
+#| msgid "Failed to swap new key slot.\n"
+msgid "No space for new keyslot."
+msgstr "交换新密钥槽失败。\n"
+
+#: lib/luks2/luks2_json_metadata.c:851 lib/luks2/luks2_json_metadata.c:974
+#: lib/luks2/luks2_json_metadata.c:1047 lib/luks2/luks2_keyslot_luks2.c:103
+#: lib/luks2/luks2_keyslot_luks2.c:126
+#, c-format
+msgid "Failed to acquire read lock on device %s."
+msgstr "无法获取设备 %s 的读取锁。"
+
+#: lib/luks2/luks2_json_metadata.c:1064
+#, c-format
+msgid "Forbidden LUKS2 requirements detected in backup %s."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1105
+#, fuzzy
+#| msgid "Data offset or key size differs on device and backup, restore failed.\n"
+msgid "Data offset differ on device and backup, restore failed."
+msgstr "源设备和备份上的数据偏移或密钥大小不符,恢复失败。\n"
+
+#: lib/luks2/luks2_json_metadata.c:1111
+#, fuzzy
+#| msgid "Data offset or key size differs on device and backup, restore failed.\n"
+msgid "Binary header with keyslot areas size differ on device and backup, restore failed."
+msgstr "源设备和备份上的数据偏移或密钥大小不符,恢复失败。\n"
+
+#: lib/luks2/luks2_json_metadata.c:1118
+#, c-format
+msgid "Device %s %s%s%s%s"
+msgstr "设备 %s %s%s%s%s"
+
+#: lib/luks2/luks2_json_metadata.c:1119
+#, fuzzy
+#| msgid "does not contain LUKS header. Replacing header can destroy data on that device."
+msgid "does not contain LUKS2 header. Replacing header can destroy data on that device."
+msgstr "不包含 LUKS 标头。替换标头可能损毁设备上的数据。"
+
+#: lib/luks2/luks2_json_metadata.c:1120
+#, fuzzy
+#| msgid "already contains LUKS header. Replacing header will destroy existing keyslots."
+msgid "already contains LUKS2 header. Replacing header will destroy existing keyslots."
+msgstr "已包含 LUKS 标头。替换标头将损毁已存在的密钥槽。"
+
+#: lib/luks2/luks2_json_metadata.c:1122
+msgid ""
+"\n"
+"WARNING: unknown LUKS2 requirements detected in real device header!\n"
+"Replacing header with backup may corrupt the data on that device!"
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1124
+msgid ""
+"\n"
+"WARNING: Unfinished offline reencryption detected on the device!\n"
+"Replacing header with backup may corrupt data."
+msgstr ""
+
+#: lib/luks2/luks2_json_metadata.c:1226
+#, c-format
+msgid "Ignored unknown flag %s."
+msgstr "已忽略未知旗标 %s。"
+
+#: lib/luks2/luks2_json_metadata.c:1923
+msgid "Failed to read LUKS2 requirements."
+msgstr "读取 LUKS2 需求时失败。"
+
+#: lib/luks2/luks2_json_metadata.c:1930
+msgid "Unmet LUKS2 requirements detected."
+msgstr "探测到未满足的 LUKS2 需求。"
+
+#: lib/luks2/luks2_json_metadata.c:1938
+msgid "Offline reencryption in progress. Aborting."
+msgstr "正在进行离线重加密。中止。"
+
+#: lib/luks2/luks2_luks1_convert.c:477
+#, fuzzy, c-format
+#| msgid "Cannot check password quality: %s\n"
+msgid "Can not check status of device with uuid: %s."
+msgstr "无法检查密码质量:%s\n"
+
+#: lib/luks2/luks2_luks1_convert.c:503
+msgid "Unable to convert header with LUKSMETA additional metadata."
+msgstr ""
+
+#: lib/luks2/luks2_luks1_convert.c:540
+msgid "Unable to move keyslot area. Not enough space."
+msgstr "无法移动密钥槽区域。空间不足。"
+
+#: lib/luks2/luks2_luks1_convert.c:580 lib/luks2/luks2_luks1_convert.c:846
+msgid "Unable to move keyslot area."
+msgstr "无法移动密钥槽区域。"
+
+#: lib/luks2/luks2_luks1_convert.c:668
+#, fuzzy
+#| msgid "LUKS keyslot %u is invalid.\n"
+msgid "Cannot convert to LUKS1 format - key slot digests are not LUKS1 compatible."
+msgstr "LUKS 密钥槽 %u 无效。\n"
+
+#: lib/luks2/luks2_luks1_convert.c:677
+#, fuzzy, c-format
+#| msgid "LUKS keyslot %u is invalid.\n"
+msgid "Cannot convert to LUKS1 format - device uses wrapped key cipher %s."
+msgstr "LUKS 密钥槽 %u 无效。\n"
+
+#: lib/luks2/luks2_luks1_convert.c:685
+#, fuzzy, c-format
+#| msgid "LUKS keyslot %u is invalid.\n"
+msgid "Cannot convert to LUKS1 format - LUKS2 header contains %u token(s)."
+msgstr "LUKS 密钥槽 %u 无效。\n"
+
+#: lib/luks2/luks2_luks1_convert.c:699
+#, fuzzy, c-format
+#| msgid "LUKS keyslot %u is invalid.\n"
+msgid "Cannot convert to LUKS1 format - keyslot %u is in invalid state."
+msgstr "LUKS 密钥槽 %u 无效。\n"
+
+#: lib/luks2/luks2_luks1_convert.c:704
+#, fuzzy, c-format
+#| msgid "LUKS keyslot %u is invalid.\n"
+msgid "Cannot convert to LUKS1 format - slot %u (over maximum slots) is still active."
+msgstr "LUKS 密钥槽 %u 无效。\n"
+
+#: lib/luks2/luks2_luks1_convert.c:709
+#, fuzzy, c-format
+#| msgid "LUKS keyslot %u is invalid.\n"
+msgid "Cannot convert to LUKS1 format - keyslot %u is not LUKS1 compatible."
+msgstr "LUKS 密钥槽 %u 无效。\n"
+
+#: lib/luks2/luks2_token.c:266
+#, fuzzy
+#| msgid "Failed to swap new key slot.\n"
+msgid "No free token slot."
+msgstr "交换新密钥槽失败。\n"
+
+# stat() 主要就是出来一个各种文件信息……
+#: lib/luks2/luks2_token.c:274
+#, fuzzy, c-format
+#| msgid "Failed to stat key file.\n"
+msgid "Failed to create builtin token %s."
+msgstr "获取 (stat) 密钥文件统计数据失败。\n"
+
+#: src/cryptsetup.c:132
+#, fuzzy
+#| msgid "Can't do passphrase verification on non-tty inputs.\n"
+msgid "Can't do passphrase verification on non-tty inputs."
+msgstr "无法从非 TTY 输入验证密码。\n"
+
+#: src/cryptsetup.c:185 src/cryptsetup.c:760 src/cryptsetup.c:995
+#: src/cryptsetup_reencrypt.c:743 src/cryptsetup_reencrypt.c:817
+#, fuzzy
+#| msgid "No known cipher specification pattern detected.\n"
+msgid "No known cipher specification pattern detected."
+msgstr "未探测到已知的密文特征。\n"
+
+#: src/cryptsetup.c:193
+msgid "WARNING: The --hash parameter is being ignored in plain mode with keyfile specified.\n"
+msgstr "警告:在纯文本模式下指定密钥文件时将忽略参数 --hash。\n"
+
+#: src/cryptsetup.c:201
+msgid "WARNING: The --keyfile-size option is being ignored, the read size is the same as the encryption key size.\n"
+msgstr "警告:将忽略参数 --keyfile-size,读取大小应与加密密钥大小一致。\n"
+
+#: src/cryptsetup.c:263
+msgid "Option --key-file is required."
+msgstr "需要选项 --key-file。"
+
+#: src/cryptsetup.c:308
+msgid "Enter VeraCrypt PIM: "
+msgstr "输入 VeraCrypt PIM: "
+
+#: src/cryptsetup.c:317
+msgid "Invalid PIM value: parse error."
+msgstr "无效的 PIM 值:解析错误。"
+
+#: src/cryptsetup.c:320
+msgid "Invalid PIM value: 0."
+msgstr "无效的 PIM 值:0。"
+
+#: src/cryptsetup.c:323
+msgid "Invalid PIM value: outside of range."
+msgstr "无效的 PIM 值:超出范围。"
+
+#: src/cryptsetup.c:346
+#, fuzzy
+#| msgid "No device header detected with this passphrase.\n"
+msgid "No device header detected with this passphrase."
+msgstr "未从此密码中探测到设备标头。\n"
+
+#: src/cryptsetup.c:408 src/cryptsetup.c:1587
+msgid ""
+"Header dump with volume key is sensitive information\n"
+"which allows access to encrypted partition without passphrase.\n"
+"This dump should be always stored encrypted on safe place."
+msgstr ""
+
+#: src/cryptsetup.c:487
+#, c-format
+msgid "Device %s is still active and scheduled for deferred removal.\n"
+msgstr ""
+
+#: src/cryptsetup.c:515
+msgid "Resize of active device requires volume key in keyring but --disable-keyring option is set."
+msgstr ""
+
+#: src/cryptsetup.c:638
+#, fuzzy
+#| msgid "benchmark cipher"
+msgid "Benchmark interrupted."
+msgstr "测试密文"
+
+#: src/cryptsetup.c:659
+#, c-format
+msgid "PBKDF2-%-9s N/A\n"
+msgstr ""
+
+#: src/cryptsetup.c:661
+#, c-format
+msgid "PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"
+msgstr ""
+
+#: src/cryptsetup.c:675
+#, c-format
+msgid "%-10s N/A\n"
+msgstr ""
+
+#: src/cryptsetup.c:677
+#, c-format
+msgid "%-10s %4u iterations, %5u memory, %1u parallel threads (CPUs) for %zu-bit key (requested %u ms time)\n"
+msgstr ""
+
+#: src/cryptsetup.c:701
+#, fuzzy
+#| msgid "Result of benchmark is not reliable.\n"
+msgid "Result of benchmark is not reliable."
+msgstr "测试结果不可靠。\n"
+
+#: src/cryptsetup.c:752
+msgid "# Tests are approximate using memory only (no storage IO).\n"
+msgstr "# 测试仅使用内存(无存储 IO)。\n"
+
+#. TRANSLATORS: The string is header of a table and must be exactly (right side) aligned.
+#: src/cryptsetup.c:780 src/cryptsetup.c:804
+#, fuzzy
+#| msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgid "# Algorithm | Key | Encryption | Decryption\n"
+msgstr "# 算法 | 密钥 | 加密 | 解密\n"
+
+#: src/cryptsetup.c:784
+#, fuzzy, c-format
+#| msgid "Cipher %s is not available.\n"
+msgid "Cipher %s is not available."
+msgstr "密文 %s 不可用。\n"
+
+#: src/cryptsetup.c:813
+msgid "N/A"
+msgstr "不可用"
+
+#: src/cryptsetup.c:873
+msgid "Really try to repair LUKS device header?"
+msgstr "确定要尝试修复 LUKS 设备标头吗?"
+
+#: src/cryptsetup.c:874 src/cryptsetup.c:965 src/cryptsetup.c:987
+#: src/cryptsetup.c:1560
+msgid "Operation aborted.\n"
+msgstr "操作中止。\n"
+
+#: src/cryptsetup.c:889 src/integritysetup.c:140
+msgid ""
+"Wiping device to initialize integrity checksum.\n"
+"You can interrupt this by pressing CTRL+c (rest of not wiped device will contain invalid checksum).\n"
+msgstr ""
+
+#: src/cryptsetup.c:911 src/integritysetup.c:162
+#, fuzzy, c-format
+#| msgid "Cannot open temporary LUKS device.\n"
+msgid "Cannot deactivate temporary device %s."
+msgstr "无法打开临时 LUKS 设备。\n"
+
+#: src/cryptsetup.c:955
+msgid "Integrity option can be used only for LUKS2 format."
+msgstr ""
+
+#: src/cryptsetup.c:971
+#, c-format
+msgid "Cannot create header file %s."
+msgstr "无法创建标头文件 %s。"
+
+#: src/cryptsetup.c:982
+#, c-format
+msgid "This will overwrite data on %s irrevocably."
+msgstr "这将覆盖 %s 上的数据,该动作不可取消。"
+
+#: src/cryptsetup.c:1002 src/integritysetup.c:187 src/integritysetup.c:196
+#: src/integritysetup.c:205 src/integritysetup.c:252 src/integritysetup.c:261
+#: src/integritysetup.c:271
+#, fuzzy
+#| msgid "No known cipher specification pattern detected.\n"
+msgid "No known integrity specification pattern detected."
+msgstr "未探测到已知的密文特征。\n"
+
+#: src/cryptsetup.c:1015
+#, c-format
+msgid "Cannot use %s as on-disk header."
+msgstr "无法将 %s 作为磁盘上的标头使用。"
+
+# stat() 主要就是出来一个各种文件信息……
+#: src/cryptsetup.c:1040 src/cryptsetup.c:1314 src/cryptsetup.c:1373
+#: src/cryptsetup.c:1459 src/cryptsetup.c:1510
+msgid "Failed to set pbkdf parameters."
+msgstr "设置 pbkdf 参数失败。"
+
+#: src/cryptsetup.c:1092
+#, fuzzy
+#| msgid "Reduced data offset is allowed only for detached LUKS header.\n"
+msgid "Reduced data offset is allowed only for detached LUKS header."
+msgstr "仅已脱离的 LUKS 数据头可以使用缩减的数据偏移。\n"
+
+#: src/cryptsetup.c:1131
+msgid "Device activated but cannot make flags persistent."
+msgstr ""
+
+#: src/cryptsetup.c:1209
+#, fuzzy, c-format
+#| msgid "Key slot %d selected for deletion.\n"
+msgid "Keyslot %d is selected for deletion."
+msgstr "已选中密钥槽 %d 以删除。\n"
+
+#: src/cryptsetup.c:1212
+#, fuzzy, c-format
+#| msgid "Key slot %d is not used.\n"
+msgid "Keyslot %d is not active."
+msgstr "密钥槽 %d 未使用。\n"
+
+#: src/cryptsetup.c:1221 src/cryptsetup.c:1276
+msgid "This is the last keyslot. Device will become unusable after purging this key."
+msgstr "这是最后一个密钥槽。设备在清空此密钥后将不可用。"
+
+#: src/cryptsetup.c:1222
+msgid "Enter any remaining passphrase: "
+msgstr "输入任意剩余的口令: "
+
+#: src/cryptsetup.c:1223 src/cryptsetup.c:1278
+msgid "Operation aborted, the keyslot was NOT wiped.\n"
+msgstr ""
+
+#: src/cryptsetup.c:1256
+msgid "Enter passphrase to be deleted: "
+msgstr "输入要移除的口令: "
+
+#: src/cryptsetup.c:1273
+#, c-format
+msgid "Key slot %d selected for deletion."
+msgstr "已选中密钥槽 %d 以供删除。"
+
+#: src/cryptsetup.c:1328 src/cryptsetup.c:1387 src/cryptsetup.c:1420
+msgid "Enter new passphrase for key slot: "
+msgstr "输入密钥槽的新口令: "
+
+#: src/cryptsetup.c:1404 src/cryptsetup_reencrypt.c:1351
+#, c-format
+msgid "Enter any existing passphrase: "
+msgstr "输入任意已存在的口令: "
+
+#: src/cryptsetup.c:1463
+msgid "Enter passphrase to be changed: "
+msgstr "输入要更改的口令: "
+
+#: src/cryptsetup.c:1478 src/cryptsetup_reencrypt.c:1336
+msgid "Enter new passphrase: "
+msgstr "输入新口令: "
+
+#: src/cryptsetup.c:1514
+#, fuzzy
+#| msgid "Enter passphrase for key slot %u: "
+msgid "Enter passphrase for keyslot to be converted: "
+msgstr "输入密钥槽 %u 的密码:"
+
+#: src/cryptsetup.c:1537
+#, fuzzy
+#| msgid "Only one device argument for isLuks operation is supported.\n"
+msgid "Only one device argument for isLuks operation is supported."
+msgstr "isLuks 操作仅支持一个设备参数。\n"
+
+#: src/cryptsetup.c:1716 src/cryptsetup.c:1737
+#, fuzzy
+#| msgid "Option --header-backup-file is required.\n"
+msgid "Option --header-backup-file is required."
+msgstr "必须指定 --header-backup-file 选项。\n"
+
+#: src/cryptsetup.c:1776
+#, fuzzy, c-format
+#| msgid "Unrecognized metadata device type %s.\n"
+msgid "Unrecognized metadata device type %s."
+msgstr "无法识别的元数据设备类型 %s。\n"
+
+#: src/cryptsetup.c:1779
+#, fuzzy
+#| msgid "Command requires device and mapped name as arguments.\n"
+msgid "Command requires device and mapped name as arguments."
+msgstr "命令需要设备及映射名作为参数。\n"
+
+#: src/cryptsetup.c:1798
+#, c-format
+msgid ""
+"This operation will erase all keyslots on device %s.\n"
+"Device will become unusable after this operation."
+msgstr ""
+"该操作将清空设备 %s 上所有的密钥槽。\n"
+"设备在此操作后将不可用。"
+
+#: src/cryptsetup.c:1805
+msgid "Operation aborted, keyslots were NOT wiped.\n"
+msgstr "操作已中止,密钥槽没有被擦除。\n"
+
+#: src/cryptsetup.c:1841
+msgid "Missing LUKS target type, option --type is required."
+msgstr ""
+
+#: src/cryptsetup.c:1857
+#, c-format
+msgid "Device is already %s type."
+msgstr "设备已为 %s 类型。"
+
+#: src/cryptsetup.c:1862
+#, fuzzy, c-format
+#| msgid "This operation is not supported for %s crypt device.\n"
+msgid "This operation will convert %s to %s format.\n"
+msgstr "不支持在 %s 加密设备上执行此操作。\n"
+
+#: src/cryptsetup.c:1868
+msgid "Operation aborted, device was NOT converted.\n"
+msgstr ""
+
+#: src/cryptsetup.c:1908
+msgid "Option --priority, --label or --subsystem is missing."
+msgstr "选项 --priority、--label 或 --subsystem 缺失。"
+
+#: src/cryptsetup.c:1939
+#, fuzzy, c-format
+#| msgid "Key slot %d is invalid.\n"
+msgid "Token %d is invalid."
+msgstr "密钥槽 %d 无效。\n"
+
+#: src/cryptsetup.c:1942
+#, fuzzy, c-format
+#| msgid "Key slot %d is not used.\n"
+msgid "Token %d in use."
+msgstr "密钥槽 %d 未使用。\n"
+
+#: src/cryptsetup.c:1955
+#, fuzzy, c-format
+#| msgid "Failed to swap new key slot.\n"
+msgid "Failed to assign token %d to keyslot %d."
+msgstr "交换新密钥槽失败。\n"
+
+#: src/cryptsetup.c:1969
+msgid "--key-description parameter is mandatory for token add action."
+msgstr ""
+
+#: src/cryptsetup.c:1975
+msgid "Missing --token option specifying token for removal."
+msgstr ""
+
+#: src/cryptsetup.c:1980
+#, fuzzy, c-format
+#| msgid "Invalid device %s.\n"
+msgid "Invalid token operation %s."
+msgstr "设备 %s 无效。\n"
+
+# stat() 主要就是出来一个各种文件信息……
+#: src/cryptsetup.c:1995
+#, fuzzy, c-format
+#| msgid "Failed to stat key file.\n"
+msgid "Failed to add keyring token %d."
+msgstr "获取 (stat) 密钥文件统计数据失败。\n"
+
+#: src/cryptsetup.c:1997
+#, fuzzy, c-format
+#| msgid "Failed to open key file.\n"
+msgid "Failed to remove token %d."
+msgstr "打开 (open) 密钥文件失败。\n"
+
+#: src/cryptsetup.c:2013
+msgid "<device> [--type <type>] [<name>]"
+msgstr "<设备> [--type <类型>] [<名称>]"
+
+#: src/cryptsetup.c:2013
+msgid "open device as mapping <name>"
+msgstr "以映射 <名称> 打开设备"
+
+#: src/cryptsetup.c:2014 src/cryptsetup.c:2015 src/cryptsetup.c:2016
+#: src/veritysetup.c:366 src/veritysetup.c:367 src/integritysetup.c:427
+#: src/integritysetup.c:428
+msgid "<name>"
+msgstr "<名称>"
+
+#: src/cryptsetup.c:2014
+msgid "close device (remove mapping)"
+msgstr "关闭设备(移除映射)"
+
+#: src/cryptsetup.c:2015
+msgid "resize active device"
+msgstr "改变活动设备大小。"
+
+#: src/cryptsetup.c:2016
+msgid "show device status"
+msgstr "显示设备状态"
+
+#: src/cryptsetup.c:2017
+msgid "[--cipher <cipher>]"
+msgstr ""
+
+#: src/cryptsetup.c:2017
+msgid "benchmark cipher"
+msgstr "测试密文"
+
+#: src/cryptsetup.c:2018 src/cryptsetup.c:2019 src/cryptsetup.c:2020
+#: src/cryptsetup.c:2021 src/cryptsetup.c:2028 src/cryptsetup.c:2029
+#: src/cryptsetup.c:2030 src/cryptsetup.c:2031 src/cryptsetup.c:2032
+#: src/cryptsetup.c:2033 src/cryptsetup.c:2034 src/cryptsetup.c:2035
+msgid "<device>"
+msgstr "<设备>"
+
+#: src/cryptsetup.c:2018
+msgid "try to repair on-disk metadata"
+msgstr "尝试修复磁盘上的元数据"
+
+#: src/cryptsetup.c:2019
+msgid "erase all keyslots (remove encryption key)"
+msgstr "清空所有密钥槽(移除加密密钥)"
+
+#: src/cryptsetup.c:2020
+msgid "convert LUKS from/to LUKS2 format"
+msgstr "在 LUKS 和 LUKS2 格式之间转换"
+
+#: src/cryptsetup.c:2021
+msgid "set permanent configuration options for LUKS2"
+msgstr ""
+
+#: src/cryptsetup.c:2022 src/cryptsetup.c:2023
+msgid "<device> [<new key file>]"
+msgstr "<设备> [<新密钥文件>]"
+
+#: src/cryptsetup.c:2022
+msgid "formats a LUKS device"
+msgstr "格式化一个 LUKS 设备"
+
+#: src/cryptsetup.c:2023
+msgid "add key to LUKS device"
+msgstr "向 LUKS 设备添加密钥"
+
+#: src/cryptsetup.c:2024 src/cryptsetup.c:2025 src/cryptsetup.c:2026
+msgid "<device> [<key file>]"
+msgstr "<设备> [<密钥文件>]"
+
+#: src/cryptsetup.c:2024
+msgid "removes supplied key or key file from LUKS device"
+msgstr "移除 LUKS 设备中指定的密钥或密钥文件"
+
+#: src/cryptsetup.c:2025
+msgid "changes supplied key or key file of LUKS device"
+msgstr "更改 LUKS 设备中指定的密钥或密钥文件"
+
+# stat() 主要就是出来一个各种文件信息……
+#: src/cryptsetup.c:2026
+#, fuzzy
+#| msgid "Failed to stat key file.\n"
+msgid "converts a key to new pbkdf parameters"
+msgstr "获取 (stat) 密钥文件统计数据失败。\n"
+
+#: src/cryptsetup.c:2027
+msgid "<device> <key slot>"
+msgstr "<设备> <密钥槽>"
+
+#: src/cryptsetup.c:2027
+msgid "wipes key with number <key slot> from LUKS device"
+msgstr "从 LUKS 设备清理标号为 <key slot> 的密钥"
+
+#: src/cryptsetup.c:2028
+msgid "print UUID of LUKS device"
+msgstr "输出 LUKS 设备的 UUID(唯一标识符)"
+
+#: src/cryptsetup.c:2029
+msgid "tests <device> for LUKS partition header"
+msgstr "从 <device> 探测 LUKS 分区标头"
+
+#: src/cryptsetup.c:2030
+msgid "dump LUKS partition information"
+msgstr "调出 LUKS 分区信息"
+
+#: src/cryptsetup.c:2031
+msgid "dump TCRYPT device information"
+msgstr "调出 TCRYPT 设备信息"
+
+#: src/cryptsetup.c:2032
+#, fuzzy
+#| msgid "Suspend LUKS device and wipe key (all IOs are frozen)."
+msgid "Suspend LUKS device and wipe key (all IOs are frozen)"
+msgstr "挂起 LUKS 设备并清除密钥(冻结所有 IO 操作)。"
+
+#: src/cryptsetup.c:2033
+msgid "Resume suspended LUKS device"
+msgstr "恢复已挂起的 LUKS 设备"
+
+#: src/cryptsetup.c:2034
+msgid "Backup LUKS device header and keyslots"
+msgstr "备份 LUKS 设备标头和密钥槽"
+
+#: src/cryptsetup.c:2035
+msgid "Restore LUKS device header and keyslots"
+msgstr "恢复 LUKS 设备标头和密钥槽"
+
+#: src/cryptsetup.c:2036
+msgid "<add|remove> <device>"
+msgstr ""
+
+#: src/cryptsetup.c:2036
+msgid "Add or remove keyring token"
+msgstr ""
+
+#: src/cryptsetup.c:2054 src/veritysetup.c:383 src/integritysetup.c:444
+msgid ""
+"\n"
+"<action> is one of:\n"
+msgstr ""
+"\n"
+"<动作> 为其中之一:\n"
+
+#: src/cryptsetup.c:2060
+msgid ""
+"\n"
+"You can also use old <action> syntax aliases:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+msgstr ""
+"\n"
+"你亦可使用老的 <动作> 语法别名:\n"
+"\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen\n"
+"\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose\n"
+
+#: src/cryptsetup.c:2064
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<device> is the encrypted device\n"
+"<key slot> is the LUKS key slot number to modify\n"
+"<key file> optional key file for the new key for luksAddKey action\n"
+msgstr ""
+"\n"
+"<name> 为要在 %s 创建的设备\n"
+"<device> 为加密设备\n"
+"<key slot> 为需要更改的 LUKS 密钥槽\n"
+"<key file> 提供给 luksAddKey 动作的密钥文件\n"
+
+#: src/cryptsetup.c:2071
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in metadata format is %s (for luksFormat action).\n"
+msgstr ""
+
+#: src/cryptsetup.c:2076
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "Default compiled-in key and passphrase parameters:\n"
+#| "\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+#| "Default PBKDF2 iteration time for LUKS: %d (ms)\n"
+msgid ""
+"\n"
+"Default compiled-in key and passphrase parameters:\n"
+"\tMaximum keyfile size: %dkB, Maximum interactive passphrase length %d (characters)\n"
+"Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+"Default PBKDF for LUKS2: %s\n"
+"\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"
+msgstr ""
+"\n"
+"默认集成的密钥和密码参数:\n"
+"\t密钥文件的最大大小:%dkB, 交互式密码的最大长度:%d (字符)\n"
+"LUKS 的默认 PBKDF2 迭代时间:%d (毫秒)\n"
+
+#: src/cryptsetup.c:2087
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in device cipher parameters:\n"
+"\tloop-AES: %s, Key %d bits\n"
+"\tplain: %s, Key: %d bits, Password hashing: %s\n"
+"\tLUKS1: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"
+msgstr ""
+"\n"
+"默认集成的设备密文参数:\n"
+"\tloop-AES:%s, %d 位密钥\n"
+"\tplain:%s, 密钥:%d 位, 密码哈希:%s\n"
+"\tLUKS1:%s, 密钥:%d bits, LUKS 数据头哈希:%s, RNG:%s\n"
+
+#: src/cryptsetup.c:2104 src/veritysetup.c:540 src/integritysetup.c:581
+#, c-format
+msgid "%s: requires %s as arguments"
+msgstr "%s: 需要 %s 作为参数"
+
+#: src/cryptsetup.c:2137 src/veritysetup.c:423 src/integritysetup.c:478
+#: src/cryptsetup_reencrypt.c:1608
+msgid "Show this help message"
+msgstr "显示此帮助"
+
+#: src/cryptsetup.c:2138 src/veritysetup.c:424 src/integritysetup.c:479
+#: src/cryptsetup_reencrypt.c:1609
+msgid "Display brief usage"
+msgstr "显示简短用法"
+
+#: src/cryptsetup.c:2142 src/veritysetup.c:428 src/integritysetup.c:483
+#: src/cryptsetup_reencrypt.c:1613
+msgid "Help options:"
+msgstr "帮助选项:"
+
+#: src/cryptsetup.c:2143 src/veritysetup.c:429 src/integritysetup.c:484
+#: src/cryptsetup_reencrypt.c:1614
+msgid "Print package version"
+msgstr "打印软件包版本"
+
+#: src/cryptsetup.c:2144 src/veritysetup.c:430 src/integritysetup.c:485
+#: src/cryptsetup_reencrypt.c:1615
+msgid "Shows more detailed error messages"
+msgstr "显示更详细的错误信息"
+
+#: src/cryptsetup.c:2145 src/veritysetup.c:431 src/integritysetup.c:486
+#: src/cryptsetup_reencrypt.c:1616
+msgid "Show debug messages"
+msgstr "显示调试信息"
+
+#: src/cryptsetup.c:2146 src/cryptsetup_reencrypt.c:1618
+msgid "The cipher used to encrypt the disk (see /proc/crypto)"
+msgstr "用于加密磁盘的密文(参见 /proc/crypto)"
+
+#: src/cryptsetup.c:2147 src/cryptsetup_reencrypt.c:1620
+msgid "The hash used to create the encryption key from the passphrase"
+msgstr "用于从密码创建加密密钥的哈希值"
+
+#: src/cryptsetup.c:2148
+msgid "Verifies the passphrase by asking for it twice"
+msgstr "两次询问密码以进行验证"
+
+#: src/cryptsetup.c:2149 src/cryptsetup_reencrypt.c:1622
+msgid "Read the key from a file"
+msgstr "从文件读取密钥"
+
+#: src/cryptsetup.c:2150
+msgid "Read the volume (master) key from file."
+msgstr "从文件读取卷(主)密钥。"
+
+#: src/cryptsetup.c:2151
+#, fuzzy
+#| msgid "Dump volume (master) key instead of keyslots info."
+msgid "Dump volume (master) key instead of keyslots info"
+msgstr "转储卷(主)密钥而不是键槽信息。"
+
+#: src/cryptsetup.c:2152 src/cryptsetup_reencrypt.c:1619
+msgid "The size of the encryption key"
+msgstr "加密密钥大小"
+
+#: src/cryptsetup.c:2152 src/integritysetup.c:500 src/integritysetup.c:504
+#: src/integritysetup.c:508 src/cryptsetup_reencrypt.c:1619
+msgid "BITS"
+msgstr "位"
+
+#: src/cryptsetup.c:2153 src/cryptsetup_reencrypt.c:1635
+msgid "Limits the read from keyfile"
+msgstr "限制从密钥文件读取"
+
+#: src/cryptsetup.c:2153 src/cryptsetup.c:2154 src/cryptsetup.c:2155
+#: src/cryptsetup.c:2156 src/veritysetup.c:434 src/veritysetup.c:435
+#: src/veritysetup.c:436 src/veritysetup.c:439 src/veritysetup.c:440
+#: src/integritysetup.c:491 src/integritysetup.c:495 src/integritysetup.c:496
+#: src/cryptsetup_reencrypt.c:1634 src/cryptsetup_reencrypt.c:1635
+#: src/cryptsetup_reencrypt.c:1636 src/cryptsetup_reencrypt.c:1637
+msgid "bytes"
+msgstr "字节"
+
+#: src/cryptsetup.c:2154 src/cryptsetup_reencrypt.c:1634
+msgid "Number of bytes to skip in keyfile"
+msgstr "要从密钥文件跳过的字节数"
+
+#: src/cryptsetup.c:2155
+msgid "Limits the read from newly added keyfile"
+msgstr "限制从新增密钥文件的读取"
+
+#: src/cryptsetup.c:2156
+msgid "Number of bytes to skip in newly added keyfile"
+msgstr "要从新增密钥文件跳过的字节数"
+
+#: src/cryptsetup.c:2157
+msgid "Slot number for new key (default is first free)"
+msgstr "新密钥的槽号(默认为第一个可用的)"
+
+#: src/cryptsetup.c:2158
+msgid "The size of the device"
+msgstr "设备大小"
+
+#: src/cryptsetup.c:2158 src/cryptsetup.c:2159 src/cryptsetup.c:2160
+#: src/cryptsetup.c:2166 src/integritysetup.c:492 src/integritysetup.c:497
+msgid "SECTORS"
+msgstr "扇区"
+
+#: src/cryptsetup.c:2159
+msgid "The start offset in the backend device"
+msgstr "后端设备的起始偏移量"
+
+#: src/cryptsetup.c:2160
+msgid "How many sectors of the encrypted data to skip at the beginning"
+msgstr "从开头要跳过的加密数据扇区数量"
+
+#: src/cryptsetup.c:2161
+msgid "Create a readonly mapping"
+msgstr "创建只读映射"
+
+#: src/cryptsetup.c:2162 src/integritysetup.c:487
+#: src/cryptsetup_reencrypt.c:1625
+msgid "Do not ask for confirmation"
+msgstr "不要请求确认"
+
+#: src/cryptsetup.c:2163
+msgid "Timeout for interactive passphrase prompt (in seconds)"
+msgstr "交互式密码提示符超时长度(秒)"
+
+#: src/cryptsetup.c:2163 src/cryptsetup.c:2164 src/integritysetup.c:488
+#: src/cryptsetup_reencrypt.c:1626
+msgid "secs"
+msgstr "秒"
+
+#: src/cryptsetup.c:2164 src/integritysetup.c:488
+#: src/cryptsetup_reencrypt.c:1626
+msgid "Progress line update (in seconds)"
+msgstr ""
+
+#: src/cryptsetup.c:2165 src/cryptsetup_reencrypt.c:1627
+msgid "How often the input of the passphrase can be retried"
+msgstr "输入密码的最大重试频率"
+
+#: src/cryptsetup.c:2166
+msgid "Align payload at <n> sector boundaries - for luksFormat"
+msgstr "于 <n> 个扇区边界处对其载荷数据 - 供 luks 格式用"
+
+#: src/cryptsetup.c:2167
+#, fuzzy
+#| msgid "File with LUKS header and keyslots backup."
+msgid "File with LUKS header and keyslots backup"
+msgstr "带有 LUKS 数据头和密钥槽备份的文件。"
+
+#: src/cryptsetup.c:2168 src/cryptsetup_reencrypt.c:1628
+msgid "Use /dev/random for generating volume key"
+msgstr "使用 /dev/random 生成卷密钥"
+
+#: src/cryptsetup.c:2169 src/cryptsetup_reencrypt.c:1629
+msgid "Use /dev/urandom for generating volume key"
+msgstr "使用 /dev/urandom 生成卷密钥"
+
+#: src/cryptsetup.c:2170
+#, fuzzy
+#| msgid "Share device with another non-overlapping crypt segment."
+msgid "Share device with another non-overlapping crypt segment"
+msgstr "与另一个不重合的加密段共享设备。"
+
+#: src/cryptsetup.c:2171 src/veritysetup.c:443
+#, fuzzy
+#| msgid "UUID for device to use."
+msgid "UUID for device to use"
+msgstr "设备使用的 UUID 已占用。"
+
+#: src/cryptsetup.c:2172
+#, fuzzy
+#| msgid "Allow discards (aka TRIM) requests for device."
+msgid "Allow discards (aka TRIM) requests for device"
+msgstr "允许设备的 discard(或称 TRIM)请求。"
+
+#: src/cryptsetup.c:2173 src/cryptsetup_reencrypt.c:1646
+#, fuzzy
+#| msgid "Device or file with separated LUKS header."
+msgid "Device or file with separated LUKS header"
+msgstr "带有分离 LUKS 数据头的设备或文件。"
+
+#: src/cryptsetup.c:2174
+#, fuzzy
+#| msgid "Do not activate device, just check passphrase."
+msgid "Do not activate device, just check passphrase"
+msgstr "不要激活设备,仅检查密码。"
+
+#: src/cryptsetup.c:2175
+#, fuzzy
+#| msgid "Use hidden header (hidden TCRYPT device)."
+msgid "Use hidden header (hidden TCRYPT device)"
+msgstr "使用隐藏数据头(隐藏 TCRYPT 设备)"
+
+#: src/cryptsetup.c:2176
+#, fuzzy
+#| msgid "Device is system TCRYPT drive (with bootloader)."
+msgid "Device is system TCRYPT drive (with bootloader)"
+msgstr "设备为系统 TCRYPT 驱动器(带有引导器)。"
+
+#: src/cryptsetup.c:2177
+msgid "Use backup (secondary) TCRYPT header"
+msgstr "使用备份(次级)TCRYPT 标头"
+
+#: src/cryptsetup.c:2178
+#, fuzzy
+#| msgid "Scan also for VeraCrypt compatible device."
+msgid "Scan also for VeraCrypt compatible device"
+msgstr "同时扫描 VeraCrypt 兼容的设备。"
+
+#: src/cryptsetup.c:2179
+#, fuzzy
+#| msgid "Scan also for VeraCrypt compatible device."
+msgid "Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "同时扫描 VeraCrypt 兼容的设备。"
+
+#: src/cryptsetup.c:2180
+#, fuzzy
+#| msgid "Scan also for VeraCrypt compatible device."
+msgid "Query Personal Iteration Multiplier for VeraCrypt compatible device"
+msgstr "同时扫描 VeraCrypt 兼容的设备。"
+
+#: src/cryptsetup.c:2181
+#, fuzzy
+#| msgid "Type of device metadata: luks, plain, loopaes, tcrypt."
+msgid "Type of device metadata: luks, plain, loopaes, tcrypt"
+msgstr "设备元数据类型:luks, 纯粹 (plain), loopaes, tcrypt."
+
+#: src/cryptsetup.c:2182
+#, fuzzy
+#| msgid "Disable password quality check (if enabled)."
+msgid "Disable password quality check (if enabled)"
+msgstr "禁用密码质量检查 (如果已启用)。"
+
+#: src/cryptsetup.c:2183
+#, fuzzy
+#| msgid "Use dm-crypt same_cpu_crypt performance compatibility option."
+msgid "Use dm-crypt same_cpu_crypt performance compatibility option"
+msgstr "使用 dm-crypt same_cpu_crypt 性能兼容性选项。"
+
+#: src/cryptsetup.c:2184
+#, fuzzy
+#| msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option."
+msgid "Use dm-crypt submit_from_crypt_cpus performance compatibility option"
+msgstr "使用 dm-crypt submit_from_crypt_cpus 性能兼容性选项。"
+
+#: src/cryptsetup.c:2185
+msgid "Device removal is deferred until the last user closes it"
+msgstr ""
+
+#: src/cryptsetup.c:2186
+msgid "PBKDF iteration time for LUKS (in ms)"
+msgstr "LUKS 默认 PBKDF 迭代时间(毫秒)"
+
+#: src/cryptsetup.c:2186 src/cryptsetup_reencrypt.c:1624
+msgid "msecs"
+msgstr "毫秒"
+
+#: src/cryptsetup.c:2187 src/cryptsetup_reencrypt.c:1642
+msgid "PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"
+msgstr ""
+
+#: src/cryptsetup.c:2188 src/cryptsetup_reencrypt.c:1643
+msgid "PBKDF memory cost limit"
+msgstr "PBKDF 内存开销限制"
+
+#: src/cryptsetup.c:2188 src/cryptsetup_reencrypt.c:1643
+msgid "kilobytes"
+msgstr "千字节"
+
+#: src/cryptsetup.c:2189 src/cryptsetup_reencrypt.c:1644
+msgid "PBKDF parallel cost"
+msgstr "PBKDF 并行开销"
+
+#: src/cryptsetup.c:2189 src/cryptsetup_reencrypt.c:1644
+msgid "threads"
+msgstr "线程"
+
+#: src/cryptsetup.c:2190 src/cryptsetup_reencrypt.c:1645
+msgid "PBKDF iterations cost (forced, disables benchmark)"
+msgstr ""
+
+#: src/cryptsetup.c:2191
+msgid "Keyslot priority: ignore, normal, prefer)"
+msgstr ""
+
+#: src/cryptsetup.c:2192
+#, fuzzy
+#| msgid "try to repair on-disk metadata"
+msgid "Disable locking of on-disk metadata"
+msgstr "尝试修复磁盘上的元数据"
+
+#: src/cryptsetup.c:2193
+msgid "Disable loading volume keys via kernel keyring"
+msgstr ""
+
+#: src/cryptsetup.c:2194
+msgid "Data integrity algorithm (LUKS2 only)"
+msgstr ""
+
+#: src/cryptsetup.c:2195 src/integritysetup.c:511
+#, fuzzy
+#| msgid "Invalid size parameters for verity device.\n"
+msgid "Disable journal for integrity device"
+msgstr "为 VERITY 设备提供的大小指标无效。\n"
+
+#: src/cryptsetup.c:2196 src/integritysetup.c:489
+msgid "Do not wipe device after format"
+msgstr ""
+
+#: src/cryptsetup.c:2197
+msgid "Do not ask for passphrase if activation by token fails"
+msgstr ""
+
+#: src/cryptsetup.c:2198
+msgid "Token number (default: any)"
+msgstr ""
+
+#: src/cryptsetup.c:2199
+msgid "Key description"
+msgstr ""
+
+#: src/cryptsetup.c:2200
+msgid "Encryption sector size (default: 512 bytes)"
+msgstr ""
+
+#: src/cryptsetup.c:2201
+msgid "Set activation flags persistent for device"
+msgstr ""
+
+#: src/cryptsetup.c:2202
+#, fuzzy
+#| msgid "formats a LUKS device"
+msgid "Set label for the LUKS2 device"
+msgstr "格式化一个 LUKS 设备"
+
+#: src/cryptsetup.c:2203
+#, fuzzy
+#| msgid "formats a LUKS device"
+msgid "Set subsystem label for the LUKS2 device"
+msgstr "格式化一个 LUKS 设备"
+
+#: src/cryptsetup.c:2204
+msgid "Create unbound (no assigned data segment) LUKS2 keyslot"
+msgstr ""
+
+#: src/cryptsetup.c:2220 src/veritysetup.c:464 src/integritysetup.c:528
+msgid "[OPTION...] <action> <action-specific>"
+msgstr "[选项…] <动作> <动作特定参数>"
+
+#: src/cryptsetup.c:2277 src/veritysetup.c:504 src/integritysetup.c:545
+msgid "Argument <action> missing."
+msgstr "缺失参数 <动作>。"
+
+#: src/cryptsetup.c:2333 src/veritysetup.c:535 src/integritysetup.c:576
+msgid "Unknown action."
+msgstr "未知动作。"
+
+#: src/cryptsetup.c:2343
+#, fuzzy
+#| msgid "Option --shared is allowed only for open of plain device.\n"
+msgid "Option --deferred is allowed only for close command.\n"
+msgstr "选项 --shared 只适用于打开纯设备。\n"
+
+#: src/cryptsetup.c:2348
+msgid "Option --shared is allowed only for open of plain device.\n"
+msgstr "选项 --shared 只适用于打开纯设备。\n"
+
+#: src/cryptsetup.c:2353
+msgid "Option --allow-discards is allowed only for open operation.\n"
+msgstr "选项 --allow-discards 只适用于打开操作。\n"
+
+#: src/cryptsetup.c:2358
+#, fuzzy
+#| msgid "Option --allow-discards is allowed only for open operation.\n"
+msgid "Option --persistent is allowed only for open operation.\n"
+msgstr "选项 --allow-discards 只适用于打开操作。\n"
+
+#: src/cryptsetup.c:2363
+msgid "Option --persistent is not allowed with --test-passphrase.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2372
+#, fuzzy
+#| msgid ""
+#| "Option --key-size is allowed only for luksFormat, open and benchmark.\n"
+#| "To limit read from keyfile use --keyfile-size=(bytes)."
+msgid ""
+"Option --key-size is allowed only for luksFormat, luksAddKey (with --unbound),\n"
+"open and benchmark actions. To limit read from keyfile use --keyfile-size=(bytes)."
+msgstr ""
+"选项 --key-size 只能用于 luksFormat, 打开和性能测试。\n"
+"要限制密钥文件读取请使用 --keyfile-size=(字节数)。"
+
+#: src/cryptsetup.c:2378
+#, fuzzy
+#| msgid "Option --align-payload is allowed only for luksFormat."
+msgid "Option --integrity is allowed only for luksFormat (LUKS2).\n"
+msgstr "选项 --align-payload 只允许用于 luksFormat。"
+
+#: src/cryptsetup.c:2383
+msgid "Option --integrity-no-wipe can be used only for format action with integrity extension.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2389
+#, fuzzy
+#| msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgid "Options --label and --subsystem are allowed only for luksFormat and config LUKS2 operations.\n"
+msgstr "选项 --uuid 只允许用于 luksFormat 和 luksUUID。"
+
+#: src/cryptsetup.c:2395
+msgid "Option --test-passphrase is allowed only for open of LUKS and TCRYPT devices.\n"
+msgstr "选项 --test-passphrase 只能用于打开 LUKS 和 TCRYPT 设备。\n"
+
+#: src/cryptsetup.c:2400 src/cryptsetup_reencrypt.c:1717
+msgid "Key size must be a multiple of 8 bits"
+msgstr "密钥尺寸必须是 8 的倍数"
+
+#: src/cryptsetup.c:2406 src/cryptsetup_reencrypt.c:1402
+#: src/cryptsetup_reencrypt.c:1722
+msgid "Key slot is invalid."
+msgstr "密钥槽无效。"
+
+#: src/cryptsetup.c:2413
+#, fuzzy
+#| msgid "Option --key-file takes precedence over specified key file argument.\n"
+msgid "Option --key-file takes precedence over specified key file argument."
+msgstr "选项 --key-file 优先使用指定的密钥文件参数。\n"
+
+#: src/cryptsetup.c:2420 src/veritysetup.c:547 src/integritysetup.c:595
+#: src/cryptsetup_reencrypt.c:1696
+msgid "Negative number for option not permitted."
+msgstr "不允许在选项中填入负数。"
+
+#: src/cryptsetup.c:2424
+msgid "Only one --key-file argument is allowed."
+msgstr "只允许存在一个 --key-file 选项。"
+
+#: src/cryptsetup.c:2428 src/cryptsetup_reencrypt.c:1688
+#: src/cryptsetup_reencrypt.c:1726
+msgid "Only one of --use-[u]random options is allowed."
+msgstr "--use-[u]random 选项只能用一处。"
+
+#: src/cryptsetup.c:2432
+msgid "Option --use-[u]random is allowed only for luksFormat."
+msgstr "选项 --use-[u]random 只适用于 luksFormat。"
+
+#: src/cryptsetup.c:2436
+msgid "Option --uuid is allowed only for luksFormat and luksUUID."
+msgstr "选项 --uuid 只允许用于 luksFormat 和 luksUUID。"
+
+#: src/cryptsetup.c:2440
+msgid "Option --align-payload is allowed only for luksFormat."
+msgstr "选项 --align-payload 只允许用于 luksFormat。"
+
+#: src/cryptsetup.c:2446
+msgid "Option --skip is supported only for open of plain and loopaes devices.\n"
+msgstr "选项 --skip 只适用于打开纯设备和 loopaes 设备。\n"
+
+#: src/cryptsetup.c:2452
+msgid "Option --offset is supported only for open of plain and loopaes devices.\n"
+msgstr "选项 --offset 只适用于打开纯设备和 loopaes 设备。\n"
+
+#: src/cryptsetup.c:2458
+msgid "Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.\n"
+msgstr "选项 --tcrypt-hidden, --tcrypt-system 或 --tcrypt-backup 只支持 TCRYPT 设备。\n"
+
+#: src/cryptsetup.c:2463
+msgid "Option --tcrypt-hidden cannot be combined with --allow-discards.\n"
+msgstr "选项 --tcrypt-hidden 不能与 --allow-discards 共用。\n"
+
+#: src/cryptsetup.c:2468
+msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgstr "选项 --veracrypt 只支持 TCRYPT 设备类型。\n"
+
+#: src/cryptsetup.c:2474
+msgid "Invalid argument for parameter --veracrypt-pim supplied.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2478
+#, fuzzy
+#| msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgid "Option --veracrypt-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "选项 --veracrypt 只支持 TCRYPT 设备类型。\n"
+
+#: src/cryptsetup.c:2486
+#, fuzzy
+#| msgid "Option --veracrypt is supported only for TCRYPT device type.\n"
+msgid "Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices.\n"
+msgstr "选项 --veracrypt 只支持 TCRYPT 设备类型。\n"
+
+#: src/cryptsetup.c:2490
+msgid "The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2497
+msgid "Option --priority can be only ignore/normal/prefer.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2502
+msgid "Keyslot specification is required.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2507 src/cryptsetup_reencrypt.c:1702
+msgid "Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2512 src/cryptsetup_reencrypt.c:1707
+msgid "PBKDF forced iterations cannot be combined with iteration time option.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2518
+#, fuzzy
+#| msgid "This operation is not supported for this device type.\n"
+msgid "Sector size option is not supported for this command.\n"
+msgstr "不支持在这类设备上执行此操作。\n"
+
+#: src/cryptsetup.c:2524
+msgid "Unsupported encryption sector size.\n"
+msgstr "不支持的加密扇区大小。\n"
+
+#: src/cryptsetup.c:2529
+msgid "Key size is required with --unbound option.\n"
+msgstr ""
+
+#: src/cryptsetup.c:2534
+#, fuzzy
+#| msgid "Option --new cannot be used together with --decrypt."
+msgid "Option --unbound may be used only with luksAddKey action.\n"
+msgstr "选项 --new 不可与 --decrypt 共用。"
+
+#: src/cryptsetup.c:2544
+msgid "Cannot disable metadata locking.\n"
+msgstr "无法禁用元数据锁定。\n"
+
+#: src/veritysetup.c:67
+msgid "Invalid salt string specified."
+msgstr "指定了无效的盐字串。"
+
+#: src/veritysetup.c:98
+#, fuzzy, c-format
+#| msgid "Cannot create hash image %s for writing.\n"
+msgid "Cannot create hash image %s for writing."
+msgstr "无法为创建哈希映像 %s 以供写入。\n"
+
+#: src/veritysetup.c:108
+#, fuzzy, c-format
+#| msgid "Cannot create hash image %s for writing.\n"
+msgid "Cannot create FEC image %s for writing."
+msgstr "无法为创建哈希映像 %s 以供写入。\n"
+
+#: src/veritysetup.c:181
+#, fuzzy
+#| msgid "Invalid root hash string specified.\n"
+msgid "Invalid root hash string specified."
+msgstr "指定了无效的根哈希值字串。\n"
+
+#: src/veritysetup.c:363
+msgid "<data_device> <hash_device>"
+msgstr "<数据设备> <哈希设备>"
+
+#: src/veritysetup.c:363 src/integritysetup.c:425
+msgid "format device"
+msgstr "格式化设备"
+
+#: src/veritysetup.c:364
+msgid "<data_device> <hash_device> <root_hash>"
+msgstr "<数据设备> <哈希设备> <根哈希值>"
+
+#: src/veritysetup.c:364
+msgid "verify device"
+msgstr "验证设备"
+
+#: src/veritysetup.c:365
+#, fuzzy
+#| msgid "<data_device> <hash_device> <root_hash>"
+msgid "<data_device> <name> <hash_device> <root_hash>"
+msgstr "<数据设备> <哈希设备> <根哈希值>"
+
+#: src/veritysetup.c:365 src/integritysetup.c:426
+msgid "open device as <name>"
+msgstr "以 <名称> 打开设备"
+
+#: src/veritysetup.c:366 src/integritysetup.c:427
+#, fuzzy
+#| msgid "close device (remove mapping)"
+msgid "close device (deactivate and remove mapping)"
+msgstr "关闭设备(移除映射)"
+
+#: src/veritysetup.c:367 src/integritysetup.c:428
+msgid "show active device status"
+msgstr "显示已激活的设备信息"
+
+#: src/veritysetup.c:368
+msgid "<hash_device>"
+msgstr "<哈希设备>"
+
+#: src/veritysetup.c:368 src/integritysetup.c:429
+msgid "show on-disk information"
+msgstr "显示磁盘上的信息"
+
+#: src/veritysetup.c:387
+#, c-format
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<data_device> is the data device\n"
+"<hash_device> is the device containing verification data\n"
+"<root_hash> hash of the root node on <hash_device>\n"
+msgstr ""
+"\n"
+"<名称> 是在 %s 下要创建的设备\n"
+"<数据设备> 就是数据设备\n"
+"<哈希设备> 是含有验证信息的设备\n"
+"<根哈希值> 是 <哈希设备> 根节点的哈希值\n"
+
+#: src/veritysetup.c:394
+#, c-format
+msgid ""
+"\n"
+"Default compiled-in dm-verity parameters:\n"
+"\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgstr ""
+"\n"
+"编译时决定的默认 dm-verify 参数:\n"
+"\t哈希: %s, 数据块 (字节): %u, 哈希块 (字节): %u, 盐大小: %u, 哈希格式: %u\n"
+
+#: src/veritysetup.c:432
+msgid "Do not use verity superblock"
+msgstr "不使用真理超级块"
+
+#: src/veritysetup.c:433
+msgid "Format type (1 - normal, 0 - original Chrome OS)"
+msgstr "格式类型 (1 - 正常, 0 - 原版 Chrome OS)"
+
+#: src/veritysetup.c:433
+msgid "number"
+msgstr "数字"
+
+#: src/veritysetup.c:434
+msgid "Block size on the data device"
+msgstr "数据设备的块大小"
+
+#: src/veritysetup.c:435
+msgid "Block size on the hash device"
+msgstr "哈希设备的块大小"
+
+#: src/veritysetup.c:436
+msgid "FEC parity bytes"
+msgstr "FEC 校验字节"
+
+#: src/veritysetup.c:437
+msgid "The number of blocks in the data file"
+msgstr "数据文件的块数量"
+
+#: src/veritysetup.c:437
+msgid "blocks"
+msgstr "块"
+
+#: src/veritysetup.c:438
+msgid "Path to device with error correction data"
+msgstr ""
+
+#: src/veritysetup.c:438
+msgid "path"
+msgstr ""
+
+#: src/veritysetup.c:439
+msgid "Starting offset on the hash device"
+msgstr "哈希设备开始位置偏移量"
+
+#: src/veritysetup.c:440
+#, fuzzy
+#| msgid "Starting offset on the hash device"
+msgid "Starting offset on the FEC device"
+msgstr "哈希设备开始位置偏移量"
+
+#: src/veritysetup.c:441
+msgid "Hash algorithm"
+msgstr "哈希算法"
+
+#: src/veritysetup.c:441
+msgid "string"
+msgstr "字符串"
+
+#: src/veritysetup.c:442
+msgid "Salt"
+msgstr "盐"
+
+#: src/veritysetup.c:442
+msgid "hex string"
+msgstr "十六进制字符串"
+
+#: src/veritysetup.c:444
+msgid "Restart kernel if corruption is detected"
+msgstr ""
+
+#: src/veritysetup.c:445
+msgid "Ignore corruption, log it only"
+msgstr "忽略数据损坏,仅对其进行日志记录"
+
+#: src/veritysetup.c:446
+#, fuzzy
+#| msgid "Do not use verity superblock"
+msgid "Do not verify zeroed blocks"
+msgstr "不使用真理超级块"
+
+#: src/veritysetup.c:447
+msgid "Verify data block only the first time it is read"
+msgstr ""
+
+#: src/veritysetup.c:553
+#, fuzzy
+#| msgid "Option --allow-discards is allowed only for open operation.\n"
+msgid "Option --ignore-corruption, --restart-on-corruption or --ignore-zero-blocks is allowed only for open operation.\n"
+msgstr "选项 --allow-discards 只适用于打开操作。\n"
+
+#: src/veritysetup.c:558
+msgid "Option --ignore-corruption and --restart-on-corruption cannot be used together.\n"
+msgstr ""
+
+#: src/integritysetup.c:78 src/utils_password.c:317
+#, fuzzy, c-format
+#| msgid "Cannot read keyfile %s.\n"
+msgid "Cannot read keyfile %s."
+msgstr ""
+"无法读取密钥文件 %s。\n"
+"\n"
+
+#: src/integritysetup.c:82 src/utils_password.c:321
+#, fuzzy, c-format
+#| msgid "Cannot read %d bytes from keyfile %s.\n"
+msgid "Cannot read %d bytes from keyfile %s."
+msgstr "无法从密钥文件 %2$s 读取 %1$d 字节。\n"
+
+#: src/integritysetup.c:224
+#, c-format
+msgid "Formatted with tag size %u, internal integrity %s.\n"
+msgstr ""
+
+#: src/integritysetup.c:425 src/integritysetup.c:429
+#, fuzzy
+#| msgid "verify device"
+msgid "<integrity_device>"
+msgstr "验证设备"
+
+#: src/integritysetup.c:426
+msgid "<integrity_device> <name>"
+msgstr ""
+
+#: src/integritysetup.c:448
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "<name> is the device to create under %s\n"
+#| "<data_device> is the data device\n"
+#| "<hash_device> is the device containing verification data\n"
+#| "<root_hash> hash of the root node on <hash_device>\n"
+msgid ""
+"\n"
+"<name> is the device to create under %s\n"
+"<integrity_device> is the device containing data with integrity tags\n"
+msgstr ""
+"\n"
+"<名称> 是在 %s 下要创建的设备\n"
+"<数据设备> 就是数据设备\n"
+"<哈希设备> 是含有验证信息的设备\n"
+"<根哈希值> 是 <哈希设备> 根节点的哈希值\n"
+
+#: src/integritysetup.c:453
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "Default compiled-in dm-verity parameters:\n"
+#| "\tHash: %s, Data block (bytes): %u, Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"
+msgid ""
+"\n"
+"Default compiled-in dm-integrity parameters:\n"
+"\tTag size: %u bytes, Checksum algorithm: %s\n"
+msgstr ""
+"\n"
+"编译时决定的默认 dm-verify 参数:\n"
+"\t哈希: %s, 数据块 (字节): %u, 哈希块 (字节): %u, 盐大小: %u, 哈希格式: %u\n"
+
+#: src/integritysetup.c:491
+msgid "Journal size"
+msgstr "日志大小"
+
+#: src/integritysetup.c:492
+msgid "Interleave sectors"
+msgstr ""
+
+#: src/integritysetup.c:493
+msgid "Journal watermark"
+msgstr ""
+
+#: src/integritysetup.c:493
+msgid "percent"
+msgstr ""
+
+#: src/integritysetup.c:494
+msgid "Journal commit time"
+msgstr "日志提交时间"
+
+#: src/integritysetup.c:494
+msgid "ms"
+msgstr ""
+
+#: src/integritysetup.c:495
+msgid "Tag size (per-sector)"
+msgstr ""
+
+#: src/integritysetup.c:496
+msgid "Sector size"
+msgstr "扇区大小"
+
+#: src/integritysetup.c:497
+msgid "Buffers size"
+msgstr "缓冲大小"
+
+#: src/integritysetup.c:499
+msgid "Data integrity algorithm"
+msgstr "数据完整性校验算法"
+
+#: src/integritysetup.c:500
+#, fuzzy
+#| msgid "The size of the encryption key"
+msgid "The size of the data integrity key"
+msgstr "加密密钥大小"
+
+#: src/integritysetup.c:501
+#, fuzzy
+#| msgid "Read the key from a file."
+msgid "Read the integrity key from a file"
+msgstr "从文件读取密钥。"
+
+#: src/integritysetup.c:503
+msgid "Journal integrity algorithm"
+msgstr ""
+
+#: src/integritysetup.c:504
+#, fuzzy
+#| msgid "The size of the encryption key"
+msgid "The size of the journal integrity key"
+msgstr "加密密钥大小"
+
+#: src/integritysetup.c:505
+#, fuzzy
+#| msgid "Read the key from a file."
+msgid "Read the journal integrity key from a file"
+msgstr "从文件读取密钥。"
+
+#: src/integritysetup.c:507
+msgid "Journal encryption algorithm"
+msgstr "日志加密算法"
+
+#: src/integritysetup.c:508
+#, fuzzy
+#| msgid "The size of the encryption key"
+msgid "The size of the journal encryption key"
+msgstr "加密密钥大小"
+
+#: src/integritysetup.c:509
+#, fuzzy
+#| msgid "Read the key from a file."
+msgid "Read the journal encryption key from a file"
+msgstr "从文件读取密钥。"
+
+#: src/integritysetup.c:512
+msgid "Recovery mode (no journal, no tag checking)"
+msgstr ""
+
+#: src/integritysetup.c:601
+msgid "Options --journal-size, --interleave-sectors, --sector-size, --tag-size and --no-wipe can be used only for format action.\n"
+msgstr ""
+
+#: src/integritysetup.c:607
+msgid "Invalid journal size specification."
+msgstr "无效的日志大小指标。"
+
+#: src/integritysetup.c:612
+msgid "Both key file and key size options must be specified."
+msgstr "密钥文件和密钥大小选项均必须指定。"
+
+#: src/integritysetup.c:615
+msgid "Integrity algorithm must be specified if integrity key is used."
+msgstr ""
+
+#: src/integritysetup.c:620
+msgid "Both journal integrity key file and key size options must be specified."
+msgstr ""
+
+#: src/integritysetup.c:623
+msgid "Journal integrity algorithm must be specified if journal integrity key is used."
+msgstr "如果使用了日志加密密钥,则必须指定日志完整性校验算法。"
+
+#: src/integritysetup.c:628
+msgid "Both journal encryption key file and key size options must be specified."
+msgstr "日志加密密钥文件和密钥大小选项均必须指定。"
+
+#: src/integritysetup.c:631
+msgid "Journal encryption algorithm must be specified if journal encryption key is used."
+msgstr "如果使用了日志加密密钥,则必须指定日志加密算法。"
+
+#: src/cryptsetup_reencrypt.c:174
+msgid "Reencryption already in-progress."
+msgstr "重加密已在进行中。"
+
+#: src/cryptsetup_reencrypt.c:180
+msgid "Reencryption of device with integrity profile is not supported."
+msgstr "不支持带有完整性 profile 信息的设备的重加密。"
+
+#: src/cryptsetup_reencrypt.c:203
+#, c-format
+msgid "Cannot exclusively open %s, device in use."
+msgstr "无法独占打开 %s,设备正在使用中。"
+
+#: src/cryptsetup_reencrypt.c:217 src/cryptsetup_reencrypt.c:1147
+msgid "Allocation of aligned memory failed."
+msgstr "分配对齐内存失败。"
+
+#: src/cryptsetup_reencrypt.c:224
+#, c-format
+msgid "Cannot read device %s."
+msgstr "无法读取设备 %s。"
+
+#: src/cryptsetup_reencrypt.c:235
+#, c-format
+msgid "Marking LUKS1 device %s unusable."
+msgstr "正在标记 LUKS1 设备 %s 为不可用状态。"
+
+#: src/cryptsetup_reencrypt.c:239
+#, c-format
+msgid "Setting LUKS2 offline reencrypt flag on device %s."
+msgstr "正在设备 %s 上设定 LUKS2 离线重加密旗标。"
+
+#: src/cryptsetup_reencrypt.c:256
+#, c-format
+msgid "Cannot write device %s."
+msgstr "无法写入设备 %s。"
+
+#: src/cryptsetup_reencrypt.c:340
+msgid "Cannot write reencryption log file."
+msgstr "无法写入重加密日志文件。"
+
+#: src/cryptsetup_reencrypt.c:396
+msgid "Cannot read reencryption log file."
+msgstr "无法读取重加密日志文件。"
+
+#: src/cryptsetup_reencrypt.c:434
+#, c-format
+msgid "Log file %s exists, resuming reencryption.\n"
+msgstr "日志文件 %s 存在,继续重加密。\n"
+
+#: src/cryptsetup_reencrypt.c:484
+msgid "Activating temporary device using old LUKS header."
+msgstr "正使用旧 LUKS 标头激活临时设备。"
+
+#: src/cryptsetup_reencrypt.c:495
+msgid "Activating temporary device using new LUKS header."
+msgstr "正使用新 LUKS 标头激活临时设备。"
+
+#: src/cryptsetup_reencrypt.c:505
+msgid "Activation of temporary devices failed."
+msgstr "激活临时设备失败。"
+
+# stat() 主要就是出来一个各种文件信息……
+#: src/cryptsetup_reencrypt.c:587
+msgid "Failed to set PBKDF parameters."
+msgstr "设置 pbkdf 参数失败。"
+
+#: src/cryptsetup_reencrypt.c:594
+#, c-format
+msgid "New LUKS header for device %s created."
+msgstr "已创建设备 %s 的新 LUKS 标头。"
+
+#: src/cryptsetup_reencrypt.c:603
+#, c-format
+msgid "Activated keyslot %i."
+msgstr "已激活密钥槽 %i。"
+
+#: src/cryptsetup_reencrypt.c:653
+#, c-format
+msgid "This version of cryptsetup-reencrypt can't handle new internal token type %s."
+msgstr "该版本的 cryptsetup-reencrypt 无法处理新的内部 token 类型 %s。"
+
+#: src/cryptsetup_reencrypt.c:675
+msgid "Failed to read activation flags from backup header."
+msgstr "从备份标头读取活动旗标失败。"
+
+#: src/cryptsetup_reencrypt.c:679
+msgid "Failed to write activation flags to new header."
+msgstr "向新表头写入活动旗标失败。"
+
+#: src/cryptsetup_reencrypt.c:683 src/cryptsetup_reencrypt.c:687
+msgid "Failed to read requirements from backup header."
+msgstr "从备份标头读取需求失败。"
+
+#: src/cryptsetup_reencrypt.c:723
+#, c-format
+msgid "%s header backup of device %s created."
+msgstr "已创建 %s 标头备份(对应设备 %s)。"
+
+#: src/cryptsetup_reencrypt.c:783
+msgid "Creation of LUKS backup headers failed."
+msgstr "LUKS 备份标头创建失败。"
+
+#: src/cryptsetup_reencrypt.c:917
+#, c-format
+msgid "Cannot restore %s header on device %s."
+msgstr "无法恢复 %s 标头(在设备 %s 上)。"
+
+#: src/cryptsetup_reencrypt.c:919
+#, c-format
+msgid "%s header on device %s restored."
+msgstr "已恢复 %s 标头(在设备 %s 上)。"
+
+#: src/cryptsetup_reencrypt.c:957 src/cryptsetup_reencrypt.c:1037
+msgid "Cannot seek to device offset."
+msgstr "无法寻找到设备偏移位置。"
+
+#: src/cryptsetup_reencrypt.c:1080
+msgid "Cannot seek to device offset.\n"
+msgstr "无法寻找到设备偏移位置。\n"
+
+#: src/cryptsetup_reencrypt.c:1119 src/cryptsetup_reencrypt.c:1125
+msgid "Cannot open temporary LUKS device."
+msgstr "无法打开临时 LUKS 设备。"
+
+#: src/cryptsetup_reencrypt.c:1130 src/cryptsetup_reencrypt.c:1135
+msgid "Cannot get device size."
+msgstr "无法获取设备大小。"
+
+#: src/cryptsetup_reencrypt.c:1172
+msgid "Interrupted by a signal."
+msgstr "被信号中断。"
+
+#: src/cryptsetup_reencrypt.c:1174
+msgid "IO error during reencryption."
+msgstr "重加密时发生 IO 错误。"
+
+#: src/cryptsetup_reencrypt.c:1205
+msgid "Provided UUID is invalid."
+msgstr "提供的 UUID 无效。"
+
+#: src/cryptsetup_reencrypt.c:1307
+msgid "Key file can be used only with --key-slot or with exactly one key slot active."
+msgstr "密钥文件只能在指定 --key-slot 时或有且只有一个槽启用时使用。"
+
+#: src/cryptsetup_reencrypt.c:1349 src/cryptsetup_reencrypt.c:1360
+#, c-format
+msgid "Enter passphrase for key slot %u: "
+msgstr "输入密钥槽 %u 的口令: "
+
+#: src/cryptsetup_reencrypt.c:1431
+msgid "Cannot open reencryption log file."
+msgstr "无法打开重加密日志文件。"
+
+#: src/cryptsetup_reencrypt.c:1437
+msgid "No decryption in progress, provided UUID can be used only to resume suspended decryption process."
+msgstr "没有正在进行中的解密操作,提供的 UUID 仅能用于继续已挂起的解密操作。"
+
+#: src/cryptsetup_reencrypt.c:1512
+#, c-format
+msgid "Changed pbkdf parameters in keyslot %i."
+msgstr "已在密钥槽 %i 更改 pbkdf 参数。"
+
+#: src/cryptsetup_reencrypt.c:1617
+msgid "Reencryption block size"
+msgstr "重加密块大小"
+
+#: src/cryptsetup_reencrypt.c:1617
+msgid "MiB"
+msgstr "MiB"
+
+#: src/cryptsetup_reencrypt.c:1621
+msgid "Do not change key, no data area reencryption"
+msgstr "不要更改密钥,无数据区重加密"
+
+#: src/cryptsetup_reencrypt.c:1623
+msgid "Read new volume (master) key from file"
+msgstr "从文件读取卷(主)密钥"
+
+#: src/cryptsetup_reencrypt.c:1624
+msgid "PBKDF2 iteration time for LUKS (in ms)"
+msgstr "LUKS 默认 PBKDF2 迭代时间(毫秒)"
+
+#: src/cryptsetup_reencrypt.c:1630
+msgid "Use direct-io when accessing devices"
+msgstr "在访问设备时使用 direct-io"
+
+#: src/cryptsetup_reencrypt.c:1631
+msgid "Use fsync after each block"
+msgstr "在每个数据块后使用 fsync"
+
+#: src/cryptsetup_reencrypt.c:1632
+msgid "Update log file after every block"
+msgstr "在每个数据块后更新日志文件"
+
+#: src/cryptsetup_reencrypt.c:1633
+msgid "Use only this slot (others will be disabled)"
+msgstr "仅使用这个密钥槽(其他的密钥槽将被禁用)"
+
+#: src/cryptsetup_reencrypt.c:1636
+msgid "Reduce data device size (move data offset). DANGEROUS!"
+msgstr "减少数据设备大小(移动数据偏移量)。危险!"
+
+#: src/cryptsetup_reencrypt.c:1637
+msgid "Use only specified device size (ignore rest of device). DANGEROUS!"
+msgstr "只使用指定的设备大小(忽略设备其余部分)。危险!"
+
+#: src/cryptsetup_reencrypt.c:1638
+msgid "Create new header on not encrypted device"
+msgstr "在未加密的设备上创建新的标头"
+
+#: src/cryptsetup_reencrypt.c:1639
+msgid "Permanently decrypt device (remove encryption)"
+msgstr "永久解密设备(移除加密)"
+
+#: src/cryptsetup_reencrypt.c:1640
+msgid "The UUID used to resume decryption"
+msgstr "用于继续解密的 UUID"
+
+#: src/cryptsetup_reencrypt.c:1641
+msgid "Type of LUKS metadata: luks1, luks2"
+msgstr "LUKS 元数据类型:luks1、luks2"
+
+#: src/cryptsetup_reencrypt.c:1662
+msgid "[OPTION...] <device>"
+msgstr "[选项...] <设备>"
+
+#: src/cryptsetup_reencrypt.c:1676
+#, c-format
+msgid "Reencryption will change: %s%s%s%s%s%s."
+msgstr "重加密会改变:%s%s%s%s%s%s。"
+
+#: src/cryptsetup_reencrypt.c:1677
+msgid "volume key"
+msgstr "卷密钥"
+
+#: src/cryptsetup_reencrypt.c:1679
+msgid "set hash to "
+msgstr "设置哈希值为 "
+
+#: src/cryptsetup_reencrypt.c:1680
+msgid ", set cipher to "
+msgstr ",设定密文为 "
+
+#: src/cryptsetup_reencrypt.c:1684
+msgid "Argument required."
+msgstr "需要参数。"
+
+#: src/cryptsetup_reencrypt.c:1712
+msgid "Only values between 1 MiB and 64 MiB allowed for reencryption block size."
+msgstr "重加密块大小只能是 1 MiB 到 64 MiB 之间的值。"
+
+#: src/cryptsetup_reencrypt.c:1731 src/cryptsetup_reencrypt.c:1736
+msgid "Invalid device size specification."
+msgstr "无效的设备大小指标。"
+
+#: src/cryptsetup_reencrypt.c:1739
+msgid "Maximum device reduce size is 64 MiB."
+msgstr "最大设备缩减大小为 64 MiB。"
+
+#: src/cryptsetup_reencrypt.c:1742
+msgid "Reduce size must be multiple of 512 bytes sector."
+msgstr "缩减大小必须为 512 字节扇区的倍数。"
+
+#: src/cryptsetup_reencrypt.c:1746
+msgid "Option --new must be used together with --reduce-device-size or --header."
+msgstr "选项 --new 必须与 --reduce-device-size 或 --header 共用。"
+
+#: src/cryptsetup_reencrypt.c:1750
+msgid "Option --keep-key can be used only with --hash, --iter-time or --pbkdf-force-iterations."
+msgstr "选项 --keep-key 只能与 --hash、--iter-time 或 --pbkdf-force-iterations 共用。"
+
+#: src/cryptsetup_reencrypt.c:1754
+msgid "Option --new cannot be used together with --decrypt."
+msgstr "选项 --new 不可与 --decrypt 共用。"
+
+#: src/cryptsetup_reencrypt.c:1758
+msgid "Option --decrypt is incompatible with specified parameters."
+msgstr "选项 --decrypt 与选定参数不兼容。"
+
+#: src/cryptsetup_reencrypt.c:1762
+msgid "Option --uuid is allowed only together with --decrypt."
+msgstr "选项 --uuid 不可与 --decrypt 共用。"
+
+#: src/cryptsetup_reencrypt.c:1766
+msgid "Invalid luks type. Use one of these: 'luks', 'luks1' or 'luks2'."
+msgstr "无效的 luks 类型。请使用下列选项之一:'luks'、'luks1' 或 'luks2'。"
+
+#: src/utils_tools.c:159
+msgid "Error reading response from terminal."
+msgstr "从终端读取响应时失败。"
+
+#: src/utils_tools.c:184
+msgid "Command successful.\n"
+msgstr "命令成功。\n"
+
+#: src/utils_tools.c:192
+msgid "wrong or missing parameters"
+msgstr "错误或缺失的参数"
+
+#: src/utils_tools.c:194
+msgid "no permission or bad passphrase"
+msgstr "无权限或口令错误"
+
+#: src/utils_tools.c:196
+msgid "out of memory"
+msgstr "内存耗尽"
+
+#: src/utils_tools.c:198
+msgid "wrong device or file specified"
+msgstr "指定了错误的设备或文件"
+
+#: src/utils_tools.c:200
+msgid "device already exists or device is busy"
+msgstr "设备已存在或设备正忙"
+
+#: src/utils_tools.c:202
+msgid "unknown error"
+msgstr "未知错误"
+
+#: src/utils_tools.c:204
+#, c-format
+msgid "Command failed with code %i (%s).\n"
+msgstr "命令失败,代码 %i(%s)。\n"
+
+#: src/utils_password.c:43 src/utils_password.c:75
+#, c-format
+msgid "Cannot check password quality: %s"
+msgstr "无法检查密码质量:%s"
+
+#: src/utils_password.c:51
+#, c-format
+msgid ""
+"Password quality check failed:\n"
+" %s"
+msgstr ""
+"密码质量检查失败:\n"
+" %s"
+
+#: src/utils_password.c:83
+#, c-format
+msgid "Password quality check failed: Bad passphrase (%s)"
+msgstr "密码质量检查失败:无效密码 (%s)"
+
+#: src/utils_password.c:212 src/utils_password.c:227
+msgid "Error reading passphrase from terminal."
+msgstr "从终端读取口令时出错。"
+
+#: src/utils_password.c:225
+msgid "Verify passphrase: "
+msgstr "确认密码:"
+
+#: src/utils_password.c:232
+msgid "Passphrases do not match."
+msgstr "口令不匹配。"
+
+#: src/utils_password.c:269
+msgid "Cannot use offset with terminal input."
+msgstr "不能将偏移量用于终端输入。"
+
+#: src/utils_password.c:272
+#, c-format
+msgid "Enter passphrase: "
+msgstr "输入口令:"
+
+#: src/utils_password.c:274
+#, c-format
+msgid "Enter passphrase for %s: "
+msgstr "输入 %s 的口令:"
+
+#: src/utils_password.c:304
+msgid "No key available with this passphrase."
+msgstr "此口令无可用的密钥。"
+
+#: src/utils_password.c:339
+#, c-format
+msgid "Cannot open keyfile %s for write."
+msgstr "无法打开密钥文件 %s 以供写入。"
+
+#: src/utils_password.c:346
+#, c-format
+msgid "Cannot write to keyfile %s."
+msgstr "无法写入密钥文件 %s。"
+
+#~ msgid "memory allocation error in action_luksFormat"
+#~ msgstr "在 action_luksFormat 中发生内存分配错误"
+
+#, fuzzy
+#~| msgid "Key slot is invalid."
+#~ msgid "Key slot is invalid.\n"
+#~ msgstr "密钥槽无效。"
+
+#~ msgid "Cannot find a free loopback device.\n"
+#~ msgstr "找不到空闲的回环设备。\n"
+
+#~ msgid "Too many tree levels for verity volume.\n"
+#~ msgstr "VERITY 卷上的目录树层级过多。\n"
+
+#~ msgid "Key %d not active. Can't wipe.\n"
+#~ msgstr "无法清除未激活的密钥 %d。\n"
+
+#~ msgid "<name> <data_device> <hash_device> <root_hash>"
+#~ msgstr "<名称> <数据设备> <哈希设备> <根哈希值>"
+
+#~ msgid "create active device"
+#~ msgstr "创建已激活的设备"
+
+#~ msgid "remove (deactivate) device"
+#~ msgstr "移除(禁用)设备"
+
+#~ msgid "Cannot open device %s\n"
+#~ msgstr "无法打开设备 %s。\n"
+
+#~ msgid "Marking LUKS device %s usable.\n"
+#~ msgstr "正将 LUKS 设备 %s 标为可用。\n"
+
+#~ msgid "Progress: %5.1f%%, ETA %02llu:%02llu, %4llu MiB written, speed %5.1f MiB/s%s"
+#~ msgstr "进度:%5.1f%%, 生育 %02llu:%02llu, %4llu MiB 已写入, 速度 %5.1f MiB/s%s"
+
+#~ msgid "WARNING: this is experimental code, it can completely break your data.\n"
+#~ msgstr "警告:此为实验性代码,实验性代码可能完全损毁你的数据。\n"
diff --git a/scripts/Makemodule.am b/scripts/Makemodule.am
new file mode 100644
index 0000000..5bf6ddf
--- /dev/null
+++ b/scripts/Makemodule.am
@@ -0,0 +1,5 @@
+DISTCLEAN_TARGETS += scripts/cryptsetup.conf
+
+if CRYPTSETUP_TMPFILE
+tmpfilesd_DATA += scripts/cryptsetup.conf
+endif
diff --git a/scripts/cryptsetup.conf.in b/scripts/cryptsetup.conf.in
new file mode 100644
index 0000000..8bbc5af
--- /dev/null
+++ b/scripts/cryptsetup.conf.in
@@ -0,0 +1 @@
+d @DEFAULT_LUKS2_LOCK_PATH@ @DEFAULT_LUKS2_LOCK_DIR_PERMS@ root root -
diff --git a/src/Makemodule.am b/src/Makemodule.am
new file mode 100644
index 0000000..57fff40
--- /dev/null
+++ b/src/Makemodule.am
@@ -0,0 +1,118 @@
+# cryptsetup
+if CRYPTSETUP
+
+cryptsetup_SOURCES = \
+ lib/utils_crypt.c \
+ lib/utils_loop.c \
+ lib/utils_io.c \
+ lib/utils_blkid.c \
+ src/utils_args.c \
+ src/utils_tools.c \
+ src/utils_password.c \
+ src/utils_luks.c \
+ src/utils_luks.h \
+ src/utils_blockdev.c \
+ src/utils_arg_names.h \
+ src/utils_arg_macros.h \
+ src/utils_reencrypt.c \
+ src/utils_reencrypt_luks1.c \
+ src/utils_progress.c \
+ src/cryptsetup.c \
+ src/cryptsetup.h \
+ src/cryptsetup_args.h \
+ src/cryptsetup_arg_list.h
+
+cryptsetup_LDADD = $(LDADD) \
+ libcryptsetup.la \
+ @POPT_LIBS@ \
+ @PWQUALITY_LIBS@ \
+ @PASSWDQC_LIBS@ \
+ @UUID_LIBS@ \
+ @BLKID_LIBS@
+
+sbin_PROGRAMS += cryptsetup
+
+if STATIC_TOOLS
+sbin_PROGRAMS += cryptsetup.static
+cryptsetup_static_SOURCES = $(cryptsetup_SOURCES)
+cryptsetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static
+cryptsetup_static_LDADD = \
+ $(cryptsetup_LDADD) \
+ @CRYPTO_STATIC_LIBS@ \
+ @PWQUALITY_STATIC_LIBS@ \
+ @DEVMAPPER_STATIC_LIBS@
+endif
+endif
+
+# veritysetup
+if VERITYSETUP
+
+veritysetup_SOURCES = \
+ lib/utils_crypt.c \
+ lib/utils_loop.c \
+ lib/utils_io.c \
+ lib/utils_blkid.c \
+ src/utils_args.c \
+ src/utils_arg_names.h \
+ src/utils_arg_macros.h \
+ src/utils_tools.c \
+ src/veritysetup.c \
+ src/veritysetup_args.h \
+ src/veritysetup_arg_list.h \
+ src/cryptsetup.h
+
+veritysetup_LDADD = $(LDADD) \
+ libcryptsetup.la \
+ @POPT_LIBS@ \
+ @BLKID_LIBS@
+
+sbin_PROGRAMS += veritysetup
+
+if STATIC_TOOLS
+sbin_PROGRAMS += veritysetup.static
+veritysetup_static_SOURCES = $(veritysetup_SOURCES)
+veritysetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static
+veritysetup_static_LDADD = \
+ $(veritysetup_LDADD) \
+ @CRYPTO_STATIC_LIBS@ \
+ @DEVMAPPER_STATIC_LIBS@
+endif
+endif
+
+# integritysetup
+if INTEGRITYSETUP
+
+integritysetup_SOURCES = \
+ lib/utils_crypt.c \
+ lib/utils_loop.c \
+ lib/utils_io.c \
+ lib/utils_blkid.c \
+ src/utils_args.c \
+ src/utils_arg_names.h \
+ src/utils_arg_macros.h \
+ src/utils_tools.c \
+ src/utils_blockdev.c \
+ src/utils_progress.c \
+ src/integritysetup.c \
+ src/integritysetup_args.h \
+ src/integritysetup_arg_list.h \
+ src/cryptsetup.h
+
+integritysetup_LDADD = $(LDADD) \
+ libcryptsetup.la \
+ @POPT_LIBS@ \
+ @UUID_LIBS@ \
+ @BLKID_LIBS@
+
+sbin_PROGRAMS += integritysetup
+
+if STATIC_TOOLS
+sbin_PROGRAMS += integritysetup.static
+integritysetup_static_SOURCES = $(integritysetup_SOURCES)
+integritysetup_static_LDFLAGS = $(AM_LDFLAGS) -all-static
+integritysetup_static_LDADD = \
+ $(integritysetup_LDADD) \
+ @CRYPTO_STATIC_LIBS@ \
+ @DEVMAPPER_STATIC_LIBS@
+endif
+endif
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
new file mode 100644
index 0000000..e387c1c
--- /dev/null
+++ b/src/cryptsetup.c
@@ -0,0 +1,3603 @@
+/*
+ * cryptsetup - setup cryptographic volumes for dm-crypt
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <uuid/uuid.h>
+
+#include "cryptsetup.h"
+#include "cryptsetup_args.h"
+#include "utils_luks.h"
+
+static char *keyfiles[MAX_KEYFILES];
+static char *keyfile_stdin = NULL;
+
+static int keyfiles_count = 0;
+int64_t data_shift = 0;
+
+const char *device_type = "luks";
+const char *set_pbkdf = NULL;
+
+static const char **action_argv;
+static int action_argc;
+static const char *null_action_argv[] = {NULL, NULL};
+static int total_keyfiles = 0;
+
+static struct tools_log_params log_parms;
+
+struct tools_arg tool_core_args[] = { { NULL, false, CRYPT_ARG_BOOL }, /* leave unused due to popt library */
+#define ARG(A, B, C, D, E, F, G, H) { A, false, F, G, H },
+#include "cryptsetup_arg_list.h"
+#undef ARG
+};
+
+void tools_cleanup(void)
+{
+ tools_args_free(tool_core_args, ARRAY_SIZE(tool_core_args));
+
+ FREE_AND_NULL(keyfile_stdin);
+
+ while (keyfiles_count)
+ free(keyfiles[--keyfiles_count]);
+
+ total_keyfiles = 0;
+}
+
+static const char *uuid_or_device_header(const char **data_device)
+{
+ if (data_device)
+ *data_device = ARG_SET(OPT_HEADER_ID) ? action_argv[0] : NULL;
+
+ return uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]);
+}
+
+static bool isLUKS(const char *type)
+{
+ return isLUKS2(type) || isLUKS1(type);
+}
+
+static int _set_keyslot_encryption_params(struct crypt_device *cd)
+{
+ const char *type = crypt_get_type(cd);
+
+ if (!ARG_SET(OPT_KEYSLOT_KEY_SIZE_ID) && !ARG_SET(OPT_KEYSLOT_CIPHER_ID))
+ return 0;
+
+ if (!isLUKS2(type)) {
+ log_err(_("Keyslot encryption parameters can be set only for LUKS2 device."));
+ return -EINVAL;
+ }
+
+ return crypt_keyslot_set_encryption(cd, ARG_STR(OPT_KEYSLOT_CIPHER_ID), ARG_UINT32(OPT_KEYSLOT_KEY_SIZE_ID) / 8);
+}
+
+static int _try_token_pin_unlock(struct crypt_device *cd,
+ int token_id,
+ const char *activated_name,
+ const char *token_type,
+ uint32_t activate_flags,
+ int tries,
+ bool activation)
+{
+ size_t pin_len;
+ char msg[64], *pin = NULL;
+ int r;
+
+ assert(tries >= 1);
+ assert(token_id >= 0 || token_id == CRYPT_ANY_TOKEN);
+
+ if (token_id == CRYPT_ANY_TOKEN)
+ r = snprintf(msg, sizeof(msg), _("Enter token PIN: "));
+ else
+ r = snprintf(msg, sizeof(msg), _("Enter token %d PIN: "), token_id);
+ if (r < 0 || (size_t)r >= sizeof(msg))
+ return -EINVAL;
+
+ do {
+ r = tools_get_key(msg, &pin, &pin_len, 0, 0, NULL,
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ break;
+
+ if (activation)
+ r = crypt_activate_by_token_pin(cd, activated_name, token_type,
+ token_id, pin, pin_len, NULL,
+ activate_flags);
+ else
+ r = crypt_resume_by_token_pin(cd, activated_name, token_type,
+ token_id, pin, pin_len, NULL);
+ crypt_safe_free(pin);
+ pin = NULL;
+ tools_keyslot_msg(r, UNLOCKED);
+ tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), token_id, true);
+ check_signal(&r);
+ } while (r == -ENOANO && (--tries > 0));
+
+ return r;
+}
+
+static int action_open_plain(void)
+{
+ struct crypt_device *cd = NULL, *cd1 = NULL;
+ const char *pcipher, *pmode;
+ char *msg, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ struct crypt_active_device cad;
+ struct crypt_params_plain params = {
+ .hash = ARG_SET(OPT_HASH_ID) ? ARG_STR(OPT_HASH_ID) : DEFAULT_PLAIN_HASH,
+ .skip = ARG_UINT64(OPT_SKIP_ID),
+ .offset = ARG_UINT64(OPT_OFFSET_ID),
+ .sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID) ?: SECTOR_SIZE
+ };
+ char *password = NULL;
+ const char *activated_name = NULL;
+ size_t passwordLen, key_size_max, signatures = 0,
+ key_size = (ARG_UINT32(OPT_KEY_SIZE_ID) ?: DEFAULT_PLAIN_KEYBITS) / 8;
+ uint32_t activate_flags = 0;
+ int r;
+
+ r = crypt_parse_name_and_mode(ARG_STR(OPT_CIPHER_ID) ?: DEFAULT_CIPHER(PLAIN),
+ cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected."));
+ goto out;
+ }
+
+ /* FIXME: temporary hack, no hashing for keyfiles in plain mode */
+ if (ARG_SET(OPT_KEY_FILE_ID) && !tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) {
+ params.hash = NULL;
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && ARG_SET(OPT_HASH_ID))
+ log_std(_("WARNING: The --hash parameter is being ignored "
+ "in plain mode with keyfile specified.\n"));
+ }
+
+ if (params.hash && !strcmp(params.hash, "plain"))
+ params.hash = NULL;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !params.hash && ARG_SET(OPT_KEY_FILE_ID) && !tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID)) && ARG_SET(OPT_KEYFILE_SIZE_ID))
+ log_std(_("WARNING: The --keyfile-size option is being ignored, "
+ "the read size is the same as the encryption key size.\n"));
+
+ if (ARG_SET(OPT_REFRESH_ID)) {
+ activated_name = action_argc > 1 ? action_argv[1] : action_argv[0];
+ r = crypt_init_by_name_and_header(&cd1, activated_name, NULL);
+ if (r)
+ goto out;
+ r = crypt_get_active_device(cd1, activated_name, &cad);
+ if (r)
+ goto out;
+
+ /* copy known parameters from existing device */
+ params.skip = crypt_get_iv_offset(cd1);
+ params.offset = crypt_get_data_offset(cd1);
+ params.size = cad.size;
+ params.sector_size = crypt_get_sector_size(cd1);
+ key_size = crypt_get_volume_key_size(cd1);
+
+ if ((r = crypt_init(&cd, crypt_get_device_name(cd1))))
+ goto out;
+
+ activate_flags |= CRYPT_ACTIVATE_REFRESH;
+
+ pcipher = crypt_get_cipher(cd1);
+ pmode = crypt_get_cipher_mode(cd1);
+ } else {
+ activated_name = action_argv[1];
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ /* Skip blkid scan when activating plain device with offset */
+ if (!ARG_UINT64(OPT_OFFSET_ID)) {
+ /* Print all present signatures in read-only mode */
+ r = tools_detect_signatures(action_argv[0], PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID));
+ if (r < 0)
+ goto out;
+ }
+
+ if (signatures && !ARG_SET(OPT_BATCH_MODE_ID)) {
+ r = asprintf(&msg, _("Detected device signature(s) on %s. Proceeding further may damage existing data."), action_argv[0]);
+ if (r == -1) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
+ free(msg);
+ if (r < 0)
+ goto out;
+ }
+
+ pcipher = cipher;
+ pmode = cipher_mode;
+ }
+
+ if (ARG_SET(OPT_DEVICE_SIZE_ID))
+ params.size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE;
+ else if (ARG_SET(OPT_SIZE_ID))
+ params.size = ARG_UINT64(OPT_SIZE_ID);
+
+ r = crypt_format(cd, CRYPT_PLAIN,
+ pcipher, pmode,
+ NULL, NULL,
+ key_size,
+ &params);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+
+ if (ARG_SET(OPT_SHARED_ID))
+ activate_flags |= CRYPT_ACTIVATE_SHARED;
+
+ set_activation_flags(&activate_flags);
+
+ if (!tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) {
+ /* If no hash, key is read directly, read size is always key_size
+ * (possible --keyfile_size is ignored.
+ * If hash is specified, --keyfile_size is applied.
+ * The --keyfile_offset is applied always.
+ */
+ key_size_max = params.hash ? ARG_UINT32(OPT_KEYFILE_SIZE_ID) : key_size;
+ r = crypt_activate_by_keyfile_device_offset(cd, action_argv[1],
+ CRYPT_ANY_SLOT, ARG_STR(OPT_KEY_FILE_ID), key_size_max,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), activate_flags);
+ } else {
+ key_size_max = (ARG_SET(OPT_KEY_FILE_ID) && !params.hash) ? key_size : ARG_UINT32(OPT_KEYFILE_SIZE_ID);
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), key_size_max,
+ ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, activated_name,
+ CRYPT_ANY_SLOT, password, passwordLen, activate_flags);
+ }
+out:
+ crypt_free(cd);
+ crypt_free(cd1);
+ crypt_safe_free(password);
+
+ return r;
+}
+
+static int action_open_loopaes(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_loopaes params = {
+ .hash = ARG_STR(OPT_HASH_ID),
+ .offset = ARG_UINT64(OPT_OFFSET_ID),
+ .skip = ARG_SET(OPT_SKIP_ID) ? ARG_UINT64(OPT_SKIP_ID) : ARG_UINT64(OPT_OFFSET_ID)
+ };
+ unsigned int key_size = (ARG_UINT32(OPT_KEY_SIZE_ID) ?: DEFAULT_LOOPAES_KEYBITS) / 8;
+ uint32_t activate_flags = 0;
+ const char *activated_name = NULL;
+ int r;
+
+ if (!ARG_SET(OPT_KEY_FILE_ID)) {
+ log_err(_("Option --key-file is required."));
+ return -EINVAL;
+ }
+
+ if (ARG_SET(OPT_REFRESH_ID)) {
+ activated_name = action_argc > 1 ? action_argv[1] : action_argv[0];
+ if ((r = crypt_init_by_name(&cd, activated_name)))
+ goto out;
+ activate_flags |= CRYPT_ACTIVATE_REFRESH;
+ } else {
+ activated_name = action_argv[1];
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ r = crypt_format(cd, CRYPT_LOOPAES, ARG_STR(OPT_CIPHER_ID) ?: DEFAULT_LOOPAES_CIPHER,
+ NULL, NULL, NULL, key_size, &params);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ }
+
+ set_activation_flags(&activate_flags);
+
+ r = crypt_activate_by_keyfile_device_offset(cd, activated_name, CRYPT_ANY_SLOT,
+ tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID)) ? "/dev/stdin" : ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID),
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), activate_flags);
+out:
+ crypt_free(cd);
+
+ return r;
+}
+
+static int tcrypt_load(struct crypt_device *cd, struct crypt_params_tcrypt *params)
+{
+ int r, tries, eperm = 0;
+
+ tries = set_tries_tty();
+ do {
+ /* TCRYPT header is encrypted, get passphrase now */
+ r = tools_get_key(NULL, CONST_CAST(char**)&params->passphrase,
+ &params->passphrase_size, 0, 0, keyfile_stdin, ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ continue;
+
+ if (ARG_SET(OPT_VERACRYPT_QUERY_PIM_ID)) {
+ char *tmp_pim_nptr = NULL;
+ char *tmp_pim_end = NULL;
+ size_t tmp_pim_size = 0;
+ unsigned long long tmp_pim_ull = 0;
+
+ r = tools_get_key(_("Enter VeraCrypt PIM: "),
+ &tmp_pim_nptr,
+ &tmp_pim_size, 0, 0, keyfile_stdin, ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ continue;
+
+ tmp_pim_ull = strtoull(tmp_pim_nptr, &tmp_pim_end, 10);
+ if (*tmp_pim_nptr == '\0' || !tmp_pim_end || *tmp_pim_end != '\0') {
+ log_err(_("Invalid PIM value: parse error."));
+ r = -EINVAL;
+ } else if (tmp_pim_ull == 0) {
+ log_err(_("Invalid PIM value: 0."));
+ r = -EINVAL;
+ } else if (tmp_pim_ull > UINT32_MAX) {
+ log_err(_("Invalid PIM value: outside of range."));
+ r = -ERANGE;
+ }
+ crypt_safe_free(tmp_pim_nptr);
+ if (r < 0)
+ continue;
+
+ params->veracrypt_pim = (uint32_t)tmp_pim_ull;
+ crypt_safe_memzero(&tmp_pim_ull, sizeof(tmp_pim_ull));
+ }
+
+ if (ARG_SET(OPT_TCRYPT_HIDDEN_ID))
+ params->flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
+
+ if (ARG_SET(OPT_TCRYPT_SYSTEM_ID))
+ params->flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
+
+ if (ARG_SET(OPT_TCRYPT_BACKUP_ID))
+ params->flags |= CRYPT_TCRYPT_BACKUP_HEADER;
+
+ r = crypt_load(cd, CRYPT_TCRYPT, params);
+
+ if (r == -EPERM) {
+ log_err(_("No device header detected with this passphrase."));
+ eperm = 1;
+ }
+
+ if (r < 0) {
+ crypt_safe_free(CONST_CAST(char*)params->passphrase);
+ params->passphrase = NULL;
+ params->passphrase_size = 0;
+ }
+ check_signal(&r);
+ } while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
+
+ /* Report wrong passphrase if at least one try failed */
+ if (eperm && r == -EPIPE)
+ r = -EPERM;
+
+ return r;
+}
+
+static int action_open_tcrypt(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_tcrypt params = {
+ .keyfiles = CONST_CAST(const char **)keyfiles,
+ .keyfiles_count = keyfiles_count,
+ .flags = CRYPT_TCRYPT_LEGACY_MODES |
+ (ARG_SET(OPT_DISABLE_VERACRYPT_ID) ? 0 : CRYPT_TCRYPT_VERA_MODES),
+ .veracrypt_pim = ARG_UINT32(OPT_VERACRYPT_PIM_ID),
+ .hash_name = ARG_STR(OPT_HASH_ID),
+ .cipher = ARG_STR(OPT_CIPHER_ID),
+ };
+ const char *activated_name;
+ uint32_t activate_flags = 0;
+ int r;
+
+ activated_name = ARG_SET(OPT_TEST_PASSPHRASE_ID) ? NULL : action_argv[1];
+
+ r = crypt_init_data_device(&cd, ARG_STR(OPT_HEADER_ID) ?: action_argv[0], action_argv[0]);
+ if (r < 0)
+ goto out;
+
+ r = tcrypt_load(cd, &params);
+ if (r < 0)
+ goto out;
+
+ set_activation_flags(&activate_flags);
+
+ if (activated_name)
+ r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, activate_flags);
+out:
+ crypt_free(cd);
+ crypt_safe_free(CONST_CAST(char*)params.passphrase);
+ crypt_safe_memzero(&params.veracrypt_pim, sizeof(params.veracrypt_pim));
+ return r;
+}
+
+static int action_open_bitlk(void)
+{
+ struct crypt_device *cd = NULL;
+ const char *activated_name;
+ uint32_t activate_flags = 0;
+ int r, tries, keysize;
+ char *password = NULL;
+ char *key = NULL;
+ size_t passwordLen;
+
+ activated_name = ARG_SET(OPT_TEST_PASSPHRASE_ID) ? NULL : action_argv[1];
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ r = crypt_load(cd, CRYPT_BITLK, NULL);
+ if (r < 0) {
+ log_err(_("Device %s is not a valid BITLK device."), action_argv[0]);
+ goto out;
+ }
+ set_activation_flags(&activate_flags);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ keysize = crypt_get_volume_key_size(cd);
+ if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) {
+ log_err(_("Cannot determine volume key size for BITLK, please use --key-size option."));
+ r = -EINVAL;
+ goto out;
+ } else if (!keysize)
+ keysize = ARG_UINT32(OPT_KEY_SIZE_ID) / 8;
+
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize);
+ if (r < 0)
+ goto out;
+ r = crypt_activate_by_volume_key(cd, activated_name,
+ key, keysize, activate_flags);
+ } else {
+ tries = set_tries_tty();
+ do {
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, activated_name, CRYPT_ANY_SLOT,
+ password, passwordLen, activate_flags);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ crypt_safe_free(password);
+ password = NULL;
+ } while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
+ }
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(key);
+ crypt_free(cd);
+ return r;
+}
+
+static int tcryptDump_with_volume_key(struct crypt_device *cd)
+{
+ char *vk = NULL;
+ size_t vk_size;
+ int r;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(
+ _("Header dump with volume key is sensitive information\n"
+ "which allows access to encrypted partition without passphrase.\n"
+ "This dump should be always stored encrypted on safe place."),
+ NULL))
+ return -EPERM;
+
+ vk_size = crypt_get_volume_key_size(cd);
+ vk = crypt_safe_alloc(vk_size);
+ if (!vk)
+ return -ENOMEM;
+
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size, NULL, 0);
+ if (r < 0)
+ goto out;
+
+ log_std("TCRYPT header information for %s\n", crypt_get_device_name(cd));
+ log_std("Cipher chain: \t%s\n", crypt_get_cipher(cd));
+ log_std("Cipher mode: \t%s\n", crypt_get_cipher_mode(cd));
+ log_std("Payload offset:\t%d\n", (int)crypt_get_data_offset(cd));
+ log_std("MK bits: \t%d\n", (int)vk_size * 8);
+ log_std("MK dump:\t");
+ crypt_log_hex(NULL, vk, vk_size, " ", 16, "\n\t\t");
+ log_std("\n");
+out:
+ crypt_safe_free(vk);
+ return r;
+}
+
+static int action_tcryptDump(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_tcrypt params = {
+ .keyfiles = CONST_CAST(const char **)keyfiles,
+ .keyfiles_count = keyfiles_count,
+ .flags = CRYPT_TCRYPT_LEGACY_MODES |
+ (ARG_SET(OPT_DISABLE_VERACRYPT_ID) ? 0: CRYPT_TCRYPT_VERA_MODES),
+ .veracrypt_pim = ARG_UINT32(OPT_VERACRYPT_PIM_ID),
+ .hash_name = ARG_STR(OPT_HASH_ID),
+ .cipher = ARG_STR(OPT_CIPHER_ID),
+ };
+ int r;
+ r = crypt_init_data_device(&cd, ARG_STR(OPT_HEADER_ID) ?: action_argv[0], action_argv[0]);
+ if (r < 0)
+ goto out;
+
+ r = tcrypt_load(cd, &params);
+ if (r < 0)
+ goto out;
+
+ if (ARG_SET(OPT_DUMP_VOLUME_KEY_ID))
+ r = tcryptDump_with_volume_key(cd);
+ else
+ r = crypt_dump(cd);
+out:
+ crypt_free(cd);
+ crypt_safe_free(CONST_CAST(char*)params.passphrase);
+ return r;
+}
+
+static int bitlkDump_with_volume_key(struct crypt_device *cd)
+{
+ char *vk = NULL, *password = NULL;
+ size_t passwordLen = 0;
+ size_t vk_size;
+ int r;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(
+ _("The header dump with volume key is sensitive information\n"
+ "that allows access to encrypted partition without a passphrase.\n"
+ "This dump should be stored encrypted in a safe place."),
+ NULL))
+ return -EPERM;
+
+ vk_size = crypt_get_volume_key_size(cd);
+ vk = crypt_safe_alloc(vk_size);
+ if (!vk)
+ return -ENOMEM;
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), 0, 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size,
+ password, passwordLen);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, UNLOCKED);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_write_mk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), vk, vk_size);
+ if (r < 0)
+ goto out;
+ }
+
+ log_std("BITLK header information for %s\n", crypt_get_device_name(cd));
+ log_std("Cipher name: \t%s\n", crypt_get_cipher(cd));
+ log_std("Cipher mode: \t%s\n", crypt_get_cipher_mode(cd));
+ log_std("UUID: \t%s\n", crypt_get_uuid(cd));
+ log_std("MK bits: \t%d\n", (int)vk_size * 8);
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ log_std("Key stored to file %s.\n", ARG_STR(OPT_VOLUME_KEY_FILE_ID));
+ goto out;
+ }
+ log_std("MK dump:\t");
+ crypt_log_hex(NULL, vk, vk_size, " ", 16, "\n\t\t");
+ log_std("\n");
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(vk);
+ return r;
+}
+
+static int action_bitlkDump(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ r = crypt_load(cd, CRYPT_BITLK, NULL);
+ if (r < 0) {
+ log_err(_("Device %s is not a valid BITLK device."), action_argv[0]);
+ goto out;
+ }
+
+ if (ARG_SET(OPT_DUMP_VOLUME_KEY_ID))
+ r = bitlkDump_with_volume_key(cd);
+ else
+ r = crypt_dump(cd);
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int fvault2Dump_with_volume_key(struct crypt_device *cd)
+{
+ char *vk = NULL;
+ char *password = NULL;
+ size_t vk_size = 0;
+ size_t pass_len = 0;
+ int r = 0;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(
+ _("The header dump with volume key is sensitive information\n"
+ "that allows access to encrypted partition without a passphrase.\n"
+ "This dump should be stored encrypted in a safe place."),
+ NULL))
+ return -EPERM;
+
+ vk_size = crypt_get_volume_key_size(cd);
+ vk = crypt_safe_alloc(vk_size);
+ if (vk == NULL)
+ return -ENOMEM;
+
+ r = tools_get_key(NULL, &password, &pass_len,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID),
+ ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID), 0, 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size, password, pass_len);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+
+ tools_keyslot_msg(r, UNLOCKED);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_write_mk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), vk, vk_size);
+ if (r < 0)
+ goto out;
+ }
+
+ r = crypt_dump(cd);
+ if (r < 0)
+ goto out;
+
+ log_std("Volume key: \t");
+ crypt_log_hex(cd, vk, vk_size, " ", 0, NULL);
+ log_std("\n");
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(vk);
+ return r;
+}
+
+static int action_fvault2Dump(void)
+{
+ struct crypt_device *cd = NULL;
+ int r = 0;
+
+ r = crypt_init(&cd, action_argv[0]);
+ if (r < 0)
+ goto out;
+
+ r = crypt_load(cd, CRYPT_FVAULT2, NULL);
+ if (r < 0) {
+ log_err(_("Device %s is not a valid FVAULT2 device."), action_argv[0]);
+ goto out;
+ }
+
+ if (ARG_SET(OPT_DUMP_VOLUME_KEY_ID))
+ r = fvault2Dump_with_volume_key(cd);
+ else
+ r = crypt_dump(cd);
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int action_open_fvault2(void)
+{
+ struct crypt_device *cd = NULL;
+ const char *activated_name;
+ uint32_t activate_flags = 0;
+ int r, tries, keysize;
+ char *password = NULL;
+ char *key = NULL;
+ size_t passwordLen;
+
+ activated_name = ARG_SET(OPT_TEST_PASSPHRASE_ID) ? NULL : action_argv[1];
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ r = crypt_load(cd, CRYPT_FVAULT2, NULL);
+ if (r < 0) {
+ log_err(_("Device %s is not a valid FVAULT2 device."), action_argv[0]);
+ goto out;
+ }
+ set_activation_flags(&activate_flags);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ keysize = crypt_get_volume_key_size(cd);
+ if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) {
+ log_err(_("Cannot determine volume key size for FVAULT2, please use --key-size option."));
+ r = -EINVAL;
+ goto out;
+ } else if (!keysize)
+ keysize = ARG_UINT32(OPT_KEY_SIZE_ID) / 8;
+
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize);
+ if (r < 0)
+ goto out;
+ r = crypt_activate_by_volume_key(cd, activated_name, key, keysize, activate_flags);
+ } else {
+ tries = set_tries_tty();
+ do {
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID),
+ ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, activated_name, CRYPT_ANY_SLOT,
+ password, passwordLen, activate_flags);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ crypt_safe_free(password);
+ password = NULL;
+ } while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
+ }
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(key);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_close(void)
+{
+ struct crypt_device *cd = NULL;
+ crypt_status_info ci;
+ uint32_t flags = 0;
+ int r;
+
+ if (ARG_SET(OPT_DEFERRED_ID))
+ flags |= CRYPT_DEACTIVATE_DEFERRED;
+ if (ARG_SET(OPT_CANCEL_DEFERRED_ID))
+ flags |= CRYPT_DEACTIVATE_DEFERRED_CANCEL;
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], ARG_STR(OPT_HEADER_ID));
+ if (r == 0)
+ r = crypt_deactivate_by_name(cd, action_argv[0], flags);
+
+ if (!r && ARG_SET(OPT_DEFERRED_ID)) {
+ ci = crypt_status(cd, action_argv[0]);
+ if (ci == CRYPT_ACTIVE || ci == CRYPT_BUSY)
+ log_std(_("Device %s is still active and scheduled for deferred removal.\n"),
+ action_argv[0]);
+ }
+
+ crypt_free(cd);
+ return r;
+}
+
+static int action_resize(void)
+{
+ int r;
+ size_t passwordLen;
+ struct crypt_active_device cad;
+ uint64_t dev_size = 0;
+ char *password = NULL;
+ struct crypt_device *cd = NULL;
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], ARG_STR(OPT_HEADER_ID));
+ if (r)
+ goto out;
+
+ /* FIXME: LUKS2 may enforce fixed size and it must not be changed */
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r)
+ goto out;
+
+ if (ARG_SET(OPT_DEVICE_SIZE_ID))
+ dev_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE;
+ else if (ARG_SET(OPT_SIZE_ID))
+ dev_size = ARG_UINT64(OPT_SIZE_ID);
+
+ if (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) {
+ if (ARG_SET(OPT_DISABLE_KEYRING_ID)) {
+ r = -EINVAL;
+ log_err(_("Resize of active device requires volume key "
+ "in keyring but --disable-keyring option is set."));
+ goto out;
+ }
+
+ /* try load VK in kernel keyring using token */
+ r = crypt_activate_by_token_pin(cd, NULL, ARG_STR(OPT_TOKEN_TYPE_ID),
+ ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL,
+ CRYPT_ACTIVATE_KEYRING_KEY);
+ tools_keyslot_msg(r, UNLOCKED);
+ tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false);
+
+ /* Token requires PIN. Ask if there is evident preference for tokens */
+ if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) ||
+ ARG_SET(OPT_TOKEN_ID_ID)))
+ r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL, ARG_STR(OPT_TOKEN_TYPE_ID), CRYPT_ACTIVATE_KEYRING_KEY, 1, true);
+
+ if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
+ goto out;
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, NULL, ARG_INT32(OPT_KEY_SLOT_ID),
+ password, passwordLen,
+ CRYPT_ACTIVATE_KEYRING_KEY);
+ tools_passphrase_msg(r);
+ tools_keyslot_msg(r, UNLOCKED);
+ }
+
+out:
+ if (r >= 0)
+ r = crypt_resize(cd, action_argv[0], dev_size);
+
+ crypt_safe_free(password);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_status(void)
+{
+ crypt_status_info ci;
+ crypt_reencrypt_info ri;
+ struct crypt_active_device cad;
+ struct crypt_params_integrity ip = {};
+ struct crypt_device *cd = NULL;
+ char *backing_file;
+ const char *device;
+ int path = 0, r = 0;
+
+ /* perhaps a path, not a dm device name */
+ if (strchr(action_argv[0], '/'))
+ path = 1;
+
+ ci = crypt_status(NULL, action_argv[0]);
+ switch (ci) {
+ case CRYPT_INVALID:
+ r = -EINVAL;
+ break;
+ case CRYPT_INACTIVE:
+ if (path)
+ log_std("%s is inactive.\n", action_argv[0]);
+ else
+ log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
+ r = -ENODEV;
+ break;
+ case CRYPT_ACTIVE:
+ case CRYPT_BUSY:
+ if (path)
+ log_std("%s is active%s.\n", action_argv[0],
+ ci == CRYPT_BUSY ? " and is in use" : "");
+ else
+ log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
+ ci == CRYPT_BUSY ? " and is in use" : "");
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], ARG_STR(OPT_HEADER_ID));
+ if (r < 0)
+ goto out;
+
+ log_std(" type: %s\n", crypt_get_type(cd) ?: "n/a");
+
+ /* Print only CRYPT type devices */
+ if (!crypt_get_cipher(cd))
+ goto out;
+
+ ri = crypt_reencrypt_status(cd, NULL);
+ if (ri > CRYPT_REENCRYPT_NONE && ri < CRYPT_REENCRYPT_INVALID)
+ log_std(" reencryption: in-progress\n");
+
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r < 0)
+ goto out;
+
+ r = crypt_get_integrity_info(cd, &ip);
+ if (r < 0 && r != -ENOTSUP)
+ goto out;
+
+ log_std(" cipher: %s-%s\n", crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
+ log_std(" keysize: %d bits\n", crypt_get_volume_key_size(cd) * 8);
+ log_std(" key location: %s\n", (cad.flags & CRYPT_ACTIVATE_KEYRING_KEY) ? "keyring" : "dm-crypt");
+ if (ip.integrity)
+ log_std(" integrity: %s\n", ip.integrity);
+ if (ip.integrity_key_size)
+ log_std(" integrity keysize: %d bits\n", ip.integrity_key_size * 8);
+ device = crypt_get_device_name(cd);
+ log_std(" device: %s\n", device);
+ if ((backing_file = crypt_loop_backing_file(device))) {
+ log_std(" loop: %s\n", backing_file);
+ free(backing_file);
+ }
+ log_std(" sector size: %d\n", crypt_get_sector_size(cd));
+ log_std(" offset: %" PRIu64 " sectors\n", cad.offset);
+ log_std(" size: %" PRIu64 " sectors\n", cad.size);
+ if (cad.iv_offset)
+ log_std(" skipped: %" PRIu64 " sectors\n", cad.iv_offset);
+ log_std(" mode: %s%s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
+ "readonly" : "read/write",
+ (cad.flags & CRYPT_ACTIVATE_SUSPENDED) ? " (suspended)" : "");
+ if (cad.flags & (CRYPT_ACTIVATE_ALLOW_DISCARDS|
+ CRYPT_ACTIVATE_SAME_CPU_CRYPT|
+ CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS|
+ CRYPT_ACTIVATE_NO_READ_WORKQUEUE|
+ CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE))
+ log_std(" flags: %s%s%s%s%s\n",
+ (cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? "discards " : "",
+ (cad.flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? "same_cpu_crypt " : "",
+ (cad.flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? "submit_from_crypt_cpus " : "",
+ (cad.flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE) ? "no_read_workqueue " : "",
+ (cad.flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) ? "no_write_workqueue" : "");
+ }
+out:
+ crypt_free(cd);
+ if (r == -ENOTSUP)
+ r = 0;
+ return r;
+}
+
+static int benchmark_callback(uint32_t time_ms, void *usrptr)
+{
+ struct crypt_pbkdf_type *pbkdf = usrptr;
+ int r = 0;
+
+ check_signal(&r);
+ if (r)
+ log_err(_("Benchmark interrupted."));
+ else
+ log_dbg("PBKDF benchmark: memory cost = %u, iterations = %u, "
+ "threads = %u (took %u ms)", pbkdf->max_memory_kb,
+ pbkdf->iterations, pbkdf->parallel_threads, time_ms);
+ return r;
+}
+
+static int action_benchmark_kdf(const char *kdf, const char *hash, size_t key_size)
+{
+ int r;
+ if (!strcmp(kdf, CRYPT_KDF_PBKDF2)) {
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_PBKDF2,
+ .hash = hash,
+ .time_ms = 1000,
+ };
+
+ r = crypt_benchmark_pbkdf(NULL, &pbkdf, "foobarfo", 8, "0123456789abcdef", 16, key_size,
+ &benchmark_callback, &pbkdf);
+ if (r < 0)
+ log_std(_("PBKDF2-%-9s N/A\n"), hash);
+ else
+ log_std(_("PBKDF2-%-9s %7u iterations per second for %zu-bit key\n"),
+ hash, pbkdf.iterations, key_size * 8);
+ } else {
+ struct crypt_pbkdf_type pbkdf = {
+ .type = kdf,
+ .time_ms = ARG_UINT32(OPT_ITER_TIME_ID) ?: DEFAULT_LUKS2_ITER_TIME,
+ .max_memory_kb = ARG_UINT32(OPT_PBKDF_MEMORY_ID),
+ .parallel_threads = ARG_UINT32(OPT_PBKDF_PARALLEL_ID)
+ };
+
+ r = crypt_benchmark_pbkdf(NULL, &pbkdf, "foobarfo", 8,
+ "0123456789abcdef0123456789abcdef", 32,
+ key_size, &benchmark_callback, &pbkdf);
+ if (r < 0)
+ log_std(_("%-10s N/A\n"), kdf);
+ else
+ log_std(_("%-10s %4u iterations, %5u memory, "
+ "%1u parallel threads (CPUs) for "
+ "%zu-bit key (requested %u ms time)\n"), kdf,
+ pbkdf.iterations, pbkdf.max_memory_kb, pbkdf.parallel_threads,
+ key_size * 8, pbkdf.time_ms);
+ }
+
+ return r;
+}
+
+static int benchmark_cipher_loop(const char *cipher, const char *cipher_mode,
+ size_t volume_key_size,
+ double *encryption_mbs, double *decryption_mbs)
+{
+ int r, buffer_size = 1024 * 1024;
+
+ do {
+ r = crypt_benchmark(NULL, cipher, cipher_mode,
+ volume_key_size, 0, buffer_size,
+ encryption_mbs, decryption_mbs);
+ if (r == -ERANGE) {
+ if (buffer_size < 1024 * 1024 * 65)
+ buffer_size *= 2;
+ else {
+ log_err(_("Result of benchmark is not reliable."));
+ r = -ENOENT;
+ }
+ }
+ } while (r == -ERANGE);
+
+ return r;
+}
+
+static int action_benchmark(void)
+{
+ static struct {
+ const char *cipher;
+ const char *mode;
+ size_t key_size;
+ } bciphers[] = {
+ { "aes", "cbc", 16 },
+ { "serpent", "cbc", 16 },
+ { "twofish", "cbc", 16 },
+ { "aes", "cbc", 32 },
+ { "serpent", "cbc", 32 },
+ { "twofish", "cbc", 32 },
+ { "aes", "xts", 32 },
+ { "serpent", "xts", 32 },
+ { "twofish", "xts", 32 },
+ { "aes", "xts", 64 },
+ { "serpent", "xts", 64 },
+ { "twofish", "xts", 64 },
+ { NULL, NULL, 0 }
+ };
+ static struct {
+ const char *type;
+ const char *hash;
+ } bkdfs[] = {
+ { CRYPT_KDF_PBKDF2, "sha1" },
+ { CRYPT_KDF_PBKDF2, "sha256" },
+ { CRYPT_KDF_PBKDF2, "sha512" },
+ { CRYPT_KDF_PBKDF2, "ripemd160" },
+ { CRYPT_KDF_PBKDF2, "whirlpool" },
+ { CRYPT_KDF_ARGON2I, NULL },
+ { CRYPT_KDF_ARGON2ID, NULL },
+ { NULL, NULL }
+ };
+ char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ double enc_mbr = 0, dec_mbr = 0;
+ int key_size = (ARG_UINT32(OPT_KEY_SIZE_ID) ?: DEFAULT_PLAIN_KEYBITS) / 8;
+ int skipped = 0, width;
+ char *c;
+ int i, r;
+
+ log_std(_("# Tests are approximate using memory only (no storage IO).\n"));
+ if (set_pbkdf || ARG_SET(OPT_HASH_ID)) {
+ if (!set_pbkdf && ARG_SET(OPT_HASH_ID))
+ set_pbkdf = CRYPT_KDF_PBKDF2;
+ r = action_benchmark_kdf(set_pbkdf, ARG_STR(OPT_HASH_ID), key_size);
+ } else if (ARG_SET(OPT_CIPHER_ID)) {
+ r = crypt_parse_name_and_mode(ARG_STR(OPT_CIPHER_ID), cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected."));
+ return r;
+ }
+ if ((c = strchr(cipher_mode, '-')))
+ *c = '\0';
+
+ r = benchmark_cipher_loop(cipher, cipher_mode, key_size, &enc_mbr, &dec_mbr);
+ if (!r) {
+ width = strlen(cipher) + strlen(cipher_mode) + 1;
+ if (width < 11)
+ width = 11;
+ /* TRANSLATORS: The string is header of a table and must be exactly (right side) aligned. */
+ log_std(_("#%*s Algorithm | Key | Encryption | Decryption\n"), width - 11, "");
+ log_std("%*s-%s %9db %10.1f MiB/s %10.1f MiB/s\n", width - (int)strlen(cipher_mode) - 1,
+ cipher, cipher_mode, key_size*8, enc_mbr, dec_mbr);
+ } else if (r < 0)
+ log_err(_("Cipher %s (with %i bits key) is not available."), ARG_STR(OPT_CIPHER_ID), key_size * 8);
+ } else {
+ for (i = 0; bkdfs[i].type; i++) {
+ r = action_benchmark_kdf(bkdfs[i].type, bkdfs[i].hash, key_size);
+ check_signal(&r);
+ if (r == -EINTR)
+ break;
+ }
+
+ for (i = 0; bciphers[i].cipher; i++) {
+ r = benchmark_cipher_loop(bciphers[i].cipher, bciphers[i].mode,
+ bciphers[i].key_size, &enc_mbr, &dec_mbr);
+ check_signal(&r);
+ if (r == -ENOTSUP || r == -EINTR)
+ break;
+ if (r == -ENOENT)
+ skipped++;
+ if (i == 0)
+ /* TRANSLATORS: The string is header of a table and must be exactly (right side) aligned. */
+ log_std(_("# Algorithm | Key | Encryption | Decryption\n"));
+
+ if (snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
+ bciphers[i].cipher, bciphers[i].mode) < 0)
+ r = -EINVAL;
+
+ if (!r)
+ log_std("%15s %9zub %10.1f MiB/s %10.1f MiB/s\n",
+ cipher, bciphers[i].key_size*8, enc_mbr, dec_mbr);
+ else
+ log_std("%15s %9zub %17s %17s\n", cipher,
+ bciphers[i].key_size*8, _("N/A"), _("N/A"));
+ }
+ if (skipped && skipped == i)
+ r = -ENOTSUP;
+ }
+
+ if (r == -ENOTSUP) {
+ log_err(_("Required kernel crypto interface not available."));
+#ifdef ENABLE_AF_ALG
+ log_err( _("Ensure you have algif_skcipher kernel module loaded."));
+#endif
+ }
+ return r;
+}
+
+static int reencrypt_metadata_repair(struct crypt_device *cd)
+{
+ char *password;
+ size_t passwordLen;
+ int r;
+ struct crypt_params_reencrypt params = {
+ .flags = CRYPT_REENCRYPT_REPAIR_NEEDED
+ };
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) &&
+ !yesDialog(_("Unprotected LUKS2 reencryption metadata detected. "
+ "Please verify the reencryption operation is desirable (see luksDump output)\n"
+ "and continue (upgrade metadata) only if you acknowledge the operation as genuine."),
+ _("Operation aborted.\n")))
+ return -EINVAL;
+
+ r = tools_get_key(_("Enter passphrase to protect and upgrade reencryption metadata: "),
+ &password, &passwordLen, ARG_UINT64(OPT_KEYFILE_OFFSET_ID),
+ ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ return r;
+
+ r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
+ ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_KEY_SLOT_ID), NULL, NULL, &params);
+ tools_passphrase_msg(r);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, NULL, ARG_INT32(OPT_KEY_SLOT_ID),
+ password, passwordLen, 0);
+ tools_passphrase_msg(r);
+ if (r >= 0)
+ r = 0;
+
+out:
+ crypt_safe_free(password);
+ return r;
+}
+
+static int luks2_reencrypt_repair(struct crypt_device *cd)
+{
+ int r;
+ size_t passwordLen;
+ const char *msg;
+ char *password = NULL;
+ struct crypt_params_reencrypt params = {};
+
+ crypt_reencrypt_info ri = crypt_reencrypt_status(cd, &params);
+
+ if (params.flags & CRYPT_REENCRYPT_REPAIR_NEEDED)
+ return reencrypt_metadata_repair(cd);
+
+ switch (ri) {
+ case CRYPT_REENCRYPT_NONE:
+ return 0;
+ case CRYPT_REENCRYPT_CLEAN:
+ break;
+ case CRYPT_REENCRYPT_CRASH:
+ if (!ARG_SET(OPT_BATCH_MODE_ID) &&
+ !yesDialog(_("Really proceed with LUKS2 reencryption recovery?"),
+ _("Operation aborted.\n")))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ri == CRYPT_REENCRYPT_CLEAN)
+ msg = _("Enter passphrase to verify reencryption metadata digest: ");
+ else
+ msg = _("Enter passphrase for reencryption recovery: ");
+
+ r = tools_get_key(msg, &password, &passwordLen, ARG_UINT64(OPT_KEYFILE_OFFSET_ID),
+ ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ return r;
+
+ r = crypt_activate_by_passphrase(cd, NULL, ARG_INT32(OPT_KEY_SLOT_ID),
+ password, passwordLen, 0);
+ if (r < 0)
+ goto out;
+
+ if (ri == CRYPT_REENCRYPT_CLEAN) {
+ r = 0;
+ goto out;
+ }
+
+ r = crypt_reencrypt_init_by_passphrase(cd, NULL, password, passwordLen,
+ ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_KEY_SLOT_ID), NULL, NULL,
+ &(struct crypt_params_reencrypt){ .flags = CRYPT_REENCRYPT_RECOVERY });
+ if (r > 0)
+ r = 0;
+out:
+ crypt_safe_free(password);
+
+ return r;
+}
+
+static int action_luksRepair(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ if ((r = crypt_init_data_device(&cd, ARG_STR(OPT_HEADER_ID) ?: action_argv[0],
+ action_argv[0])))
+ goto out;
+
+ crypt_set_log_callback(cd, quiet_log, &log_parms);
+ r = crypt_load(cd, luksType(device_type), NULL);
+ crypt_set_log_callback(cd, tool_log, &log_parms);
+ if (r == 0 && isLUKS2(crypt_get_type(cd))) {
+ /*
+ * LUKS2 triggers autorepair in crypt_load() above
+ * LUKS1 need to call crypt_repair() even if crypt_load() is ok
+ */
+ log_verbose(_("No known problems detected for LUKS header."));
+ goto out;
+ }
+
+ r = tools_detect_signatures(action_argv[0], PRB_FILTER_LUKS, NULL, ARG_SET(OPT_BATCH_MODE_ID));
+ if (r < 0)
+ goto out;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) &&
+ !yesDialog(_("Really try to repair LUKS device header?"),
+ _("Operation aborted.\n")))
+ r = -EINVAL;
+ else
+ r = crypt_repair(cd, luksType(device_type), NULL);
+out:
+ /* Header is ok, check if reencryption metadata needs repair/recovery. */
+ if (!r && isLUKS2(crypt_get_type(cd)))
+ r = luks2_reencrypt_repair(cd);
+
+ crypt_free(cd);
+ return r;
+}
+
+static int _wipe_data_device(struct crypt_device *cd)
+{
+ char tmp_name[64], tmp_path[128], tmp_uuid[40];
+ uuid_t tmp_uuid_bin;
+ int r = -EINVAL;
+ char *backing_file = NULL;
+ struct tools_progress_params prog_parms = {
+ .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID),
+ .batch_mode = ARG_SET(OPT_BATCH_MODE_ID),
+ .json_output = ARG_SET(OPT_PROGRESS_JSON_ID),
+ .interrupt_message = _("\nWipe interrupted."),
+ .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file)
+ };
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ log_std(_("Wiping device to initialize integrity checksum.\n"
+ "You can interrupt this by pressing CTRL+c "
+ "(rest of not wiped device will contain invalid checksum).\n"));
+
+ /* Activate the device a temporary one */
+ uuid_generate(tmp_uuid_bin);
+ uuid_unparse(tmp_uuid_bin, tmp_uuid);
+ if (snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid) < 0)
+ goto out;
+ if (snprintf(tmp_path, sizeof(tmp_path), "%s/%s", crypt_get_dir(), tmp_name) < 0)
+ goto out;
+
+ r = crypt_activate_by_volume_key(cd, tmp_name, NULL, 0,
+ CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL);
+ if (r < 0)
+ goto out;
+
+ /* Wipe the device */
+ set_int_handler(0);
+ r = crypt_wipe(cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, DEFAULT_WIPE_BLOCK,
+ 0, &tools_progress, &prog_parms);
+ if (crypt_deactivate(cd, tmp_name))
+ log_err(_("Cannot deactivate temporary device %s."), tmp_path);
+ set_int_block(0);
+
+out:
+ free(backing_file);
+ return r;
+}
+
+static int strcmp_or_null(const char *str, const char *expected)
+{
+ return !str ? 0 : strcmp(str, expected);
+}
+
+int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_passwordLen)
+{
+ int r = -EINVAL, keysize, integrity_keysize = 0, fd, created = 0;
+ struct stat st;
+ const char *header_device, *type;
+ char *msg = NULL, *key = NULL, *password = NULL;
+ char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN], integrity[MAX_CIPHER_LEN];
+ size_t passwordLen, signatures;
+ struct crypt_device *cd = NULL;
+ struct crypt_params_luks1 params1 = {
+ .hash = ARG_STR(OPT_HASH_ID) ?: DEFAULT_LUKS1_HASH,
+ .data_alignment = ARG_UINT32(OPT_ALIGN_PAYLOAD_ID),
+ .data_device = ARG_SET(OPT_HEADER_ID) ? action_argv[0] : NULL,
+ };
+ struct crypt_params_luks2 params2 = {
+ .data_alignment = params1.data_alignment,
+ .data_device = params1.data_device,
+ .sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID),
+ .label = ARG_STR(OPT_LABEL_ID),
+ .subsystem = ARG_STR(OPT_SUBSYSTEM_ID)
+ };
+ void *params;
+
+ type = luksType(device_type);
+ if (!type)
+ type = crypt_get_default_type();
+
+ if (isLUKS2(type)) {
+ params = &params2;
+ } else if (isLUKS1(type)) {
+ params = &params1;
+
+ if (ARG_UINT32(OPT_SECTOR_SIZE_ID) > SECTOR_SIZE) {
+ log_err(_("Unsupported encryption sector size."));
+ return -EINVAL;
+ }
+
+ if (ARG_SET(OPT_INTEGRITY_ID)) {
+ log_err(_("Integrity option can be used only for LUKS2 format."));
+ return -EINVAL;
+ }
+
+ if (ARG_SET(OPT_LUKS2_KEYSLOTS_SIZE_ID) || ARG_SET(OPT_LUKS2_METADATA_SIZE_ID)) {
+ log_err(_("Unsupported LUKS2 metadata size options."));
+ return -EINVAL;
+ }
+ } else
+ return -EINVAL;
+
+ /* Create header file (must contain at least one sector)? */
+ if (ARG_SET(OPT_HEADER_ID) && stat(ARG_STR(OPT_HEADER_ID), &st) < 0 && errno == ENOENT) {
+ if (!ARG_SET(OPT_BATCH_MODE_ID) &&
+ !yesDialog(_("Header file does not exist, do you want to create it?"),
+ _("Operation aborted.\n")))
+ return -EPERM;
+
+ log_dbg("Creating header file.");
+ /* coverity[toctou] */
+ fd = open(ARG_STR(OPT_HEADER_ID), O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
+ if (fd == -1 || posix_fallocate(fd, 0, 4096))
+ log_err(_("Cannot create header file %s."), ARG_STR(OPT_HEADER_ID));
+ else {
+ r = 0;
+ created = 1;
+ }
+ if (fd != -1)
+ close(fd);
+ if (r < 0)
+ return r;
+ }
+
+ header_device = ARG_STR(OPT_HEADER_ID) ?: action_argv[0];
+
+ r = crypt_parse_name_and_mode(ARG_STR(OPT_CIPHER_ID) ?: DEFAULT_CIPHER(LUKS1),
+ cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected."));
+ goto out;
+ }
+
+ if (ARG_SET(OPT_INTEGRITY_ID)) {
+ r = crypt_parse_integrity_mode(ARG_STR(OPT_INTEGRITY_ID), integrity, &integrity_keysize);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ goto out;
+ }
+ params2.integrity = integrity;
+ /* FIXME: we use default integrity_params (set to NULL) */
+ }
+
+ /* Never call pwquality if using null cipher */
+ if (crypt_is_cipher_null(cipher))
+ ARG_SET_TRUE(OPT_FORCE_PASSWORD_ID);
+
+ if ((r = crypt_init(&cd, header_device))) {
+ if (ARG_SET(OPT_HEADER_ID))
+ log_err(_("Cannot use %s as on-disk header."), header_device);
+ return r;
+ }
+
+ if (ARG_SET(OPT_LUKS2_KEYSLOTS_SIZE_ID) || ARG_SET(OPT_LUKS2_METADATA_SIZE_ID)) {
+ r = crypt_set_metadata_size(cd, ARG_UINT64(OPT_LUKS2_METADATA_SIZE_ID), ARG_UINT64(OPT_LUKS2_KEYSLOTS_SIZE_ID));
+ if (r < 0) {
+ log_err(_("Unsupported LUKS2 metadata size options."));
+ goto out;
+ }
+ }
+
+ if (ARG_SET(OPT_OFFSET_ID)) {
+ r = crypt_set_data_offset(cd, ARG_UINT64(OPT_OFFSET_ID));
+ if (r < 0)
+ goto out;
+ }
+
+ /* Print all present signatures in read-only mode */
+ r = tools_detect_signatures(header_device, PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID));
+ if (r < 0)
+ goto out;
+
+ if (!created && !ARG_SET(OPT_BATCH_MODE_ID)) {
+ r = asprintf(&msg, _("This will overwrite data on %s irrevocably."), header_device);
+ if (r == -1) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
+ free(msg);
+ if (r < 0)
+ goto out;
+ }
+
+ keysize = get_adjusted_key_size(cipher_mode, DEFAULT_LUKS1_KEYBITS, integrity_keysize);
+
+ if (ARG_SET(OPT_USE_RANDOM_ID))
+ crypt_set_rng_type(cd, CRYPT_RNG_RANDOM);
+ else if (ARG_SET(OPT_USE_URANDOM_ID))
+ crypt_set_rng_type(cd, CRYPT_RNG_URANDOM);
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(1), !ARG_SET(OPT_FORCE_PASSWORD_ID), cd);
+ if (r < 0)
+ goto out;
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize);
+ if (r < 0)
+ goto out;
+ }
+
+ r = set_pbkdf_params(cd, type);
+ if (r) {
+ log_err(_("Failed to set pbkdf parameters."));
+ goto out;
+ }
+
+ /* Signature candidates found */
+ if (signatures && ((r = tools_wipe_all_signatures(header_device, true, false)) < 0))
+ goto out;
+
+ if (ARG_SET(OPT_INTEGRITY_LEGACY_PADDING_ID))
+ crypt_set_compatibility(cd, CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING);
+
+ r = crypt_format(cd, type, cipher, cipher_mode,
+ ARG_STR(OPT_UUID_ID), key, keysize, params);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+
+ r = _set_keyslot_encryption_params(cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_keyslot_add_by_volume_key(cd, ARG_INT32(OPT_KEY_SLOT_ID),
+ key, keysize,
+ password, passwordLen);
+ if (r < 0) {
+ (void) tools_wipe_all_signatures(header_device, true, false);
+ goto out;
+ }
+ tools_keyslot_msg(r, CREATED);
+
+ if (ARG_SET(OPT_INTEGRITY_ID) && !ARG_SET(OPT_INTEGRITY_NO_WIPE_ID) &&
+ strcmp_or_null(params2.integrity, "none"))
+ r = _wipe_data_device(cd);
+out:
+ if (r >= 0 && r_cd && r_password && r_passwordLen) {
+ *r_cd = cd;
+ *r_password = password;
+ *r_passwordLen = passwordLen;
+ } else {
+ crypt_free(cd);
+ crypt_safe_free(password);
+ }
+
+ crypt_safe_free(key);
+
+ return r;
+}
+
+static int action_luksFormat(void)
+{
+ return luksFormat(NULL, NULL, NULL);
+}
+
+static int action_open_luks(void)
+{
+ struct crypt_active_device cad;
+ struct crypt_device *cd = NULL;
+ const char *data_device, *header_device, *activated_name;
+ char *key = NULL;
+ uint32_t activate_flags = 0;
+ int r, keysize, tries;
+ char *password = NULL;
+ size_t passwordLen;
+ struct stat st;
+
+ if (ARG_SET(OPT_REFRESH_ID)) {
+ activated_name = action_argc > 1 ? action_argv[1] : action_argv[0];
+ r = crypt_init_by_name_and_header(&cd, activated_name, ARG_STR(OPT_HEADER_ID));
+ if (r)
+ goto out;
+ activate_flags |= CRYPT_ACTIVATE_REFRESH;
+ } else {
+ header_device = uuid_or_device_header(&data_device);
+
+ activated_name = ARG_SET(OPT_TEST_PASSPHRASE_ID) ? NULL : action_argv[1];
+
+ if ((r = crypt_init_data_device(&cd, header_device, data_device)))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ header_device);
+ goto out;
+ }
+
+ if (!data_device && (crypt_get_data_offset(cd) < 8) && !ARG_SET(OPT_TEST_PASSPHRASE_ID)) {
+ log_err(_("Reduced data offset is allowed only for detached LUKS header."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (activated_name && !stat(crypt_get_device_name(cd), &st) && S_ISREG(st.st_mode) &&
+ crypt_get_data_offset(cd) >= ((uint64_t)st.st_size / SECTOR_SIZE)) {
+ log_err(_("LUKS file container %s is too small for activation, there is no remaining space for data."),
+ crypt_get_device_name(cd));
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ set_activation_flags(&activate_flags);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ keysize = crypt_get_volume_key_size(cd);
+ if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) {
+ log_err(_("Cannot determine volume key size for LUKS without keyslots, please use --key-size option."));
+ r = -EINVAL;
+ goto out;
+ } else if (!keysize)
+ keysize = ARG_UINT32(OPT_KEY_SIZE_ID) / 8;
+
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize);
+ if (r < 0)
+ goto out;
+ r = crypt_activate_by_volume_key(cd, activated_name,
+ key, keysize, activate_flags);
+ } else {
+ r = crypt_activate_by_token_pin(cd, activated_name, ARG_STR(OPT_TOKEN_TYPE_ID),
+ ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, activate_flags);
+ tools_keyslot_msg(r, UNLOCKED);
+ tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false);
+
+ /* Token requires PIN. Ask if there is evident preference for tokens */
+ if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) ||
+ ARG_SET(OPT_TOKEN_ID_ID)))
+ r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), activated_name, ARG_STR(OPT_TOKEN_TYPE_ID), activate_flags, set_tries_tty(), true);
+
+ if (r >= 0 || r == -EEXIST || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
+ goto out;
+
+ tries = set_tries_tty();
+ do {
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, activated_name,
+ ARG_INT32(OPT_KEY_SLOT_ID), password, passwordLen, activate_flags);
+ tools_keyslot_msg(r, UNLOCKED);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ crypt_safe_free(password);
+ password = NULL;
+ } while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
+ }
+out:
+ if (r >= 0 && ARG_SET(OPT_PERSISTENT_ID) &&
+ (crypt_get_active_device(cd, activated_name, &cad) ||
+ crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, cad.flags & activate_flags)))
+ log_err(_("Device activated but cannot make flags persistent."));
+
+ crypt_safe_free(key);
+ crypt_safe_free(password);
+ crypt_free(cd);
+ return r;
+}
+
+static int verify_keyslot(struct crypt_device *cd, int key_slot, crypt_keyslot_info ki,
+ char *msg_last, char *msg_pass, char *msg_fail,
+ const char *key_file, uint64_t keyfile_offset,
+ int keyfile_size)
+{
+ char *password = NULL;
+ size_t passwordLen;
+ int i, max, r;
+
+ if (ki == CRYPT_SLOT_ACTIVE_LAST && !ARG_SET(OPT_BATCH_MODE_ID) && !key_file &&
+ msg_last && !ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(msg_last, msg_fail))
+ return -EPERM;
+
+ r = tools_get_key(msg_pass, &password, &passwordLen,
+ keyfile_offset, keyfile_size, key_file, ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ if (ki == CRYPT_SLOT_ACTIVE_LAST) {
+ /* check the last keyslot */
+ r = crypt_activate_by_passphrase(cd, NULL, key_slot,
+ password, passwordLen, 0);
+ } else {
+ /* try all other keyslots */
+ r = crypt_keyslot_max(crypt_get_type(cd));
+ if (r < 0)
+ goto out;
+ max = r;
+
+ for (i = 0; i < max ; i++) {
+ if (i == key_slot)
+ continue;
+ ki = crypt_keyslot_status(cd, i);
+ if (ki == CRYPT_SLOT_ACTIVE || ki == CRYPT_SLOT_ACTIVE_LAST)
+ r = crypt_activate_by_passphrase(cd, NULL, i,
+ password, passwordLen, 0);
+ if (r == i)
+ break;
+ }
+ }
+
+ /* Handle inactive keyslots the same as bad password here */
+ if (r == -ENOENT)
+ r = -EPERM;
+ tools_passphrase_msg(r);
+out:
+ crypt_safe_free(password);
+ return r;
+}
+
+static int action_luksKillSlot(void)
+{
+ struct crypt_device *cd = NULL;
+ crypt_keyslot_info ki;
+ int r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ ki = crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ switch (ki) {
+ case CRYPT_SLOT_ACTIVE_LAST:
+ case CRYPT_SLOT_ACTIVE:
+ case CRYPT_SLOT_UNBOUND:
+ log_verbose(_("Keyslot %d is selected for deletion."), ARG_INT32(OPT_KEY_SLOT_ID));
+ break;
+ case CRYPT_SLOT_INACTIVE:
+ log_err(_("Keyslot %d is not active."), ARG_INT32(OPT_KEY_SLOT_ID));
+ /* fall through */
+ case CRYPT_SLOT_INVALID:
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) || ARG_SET(OPT_KEY_FILE_ID) || !isatty(STDIN_FILENO)) {
+ r = verify_keyslot(cd, ARG_INT32(OPT_KEY_SLOT_ID), ki,
+ _("This is the last keyslot. Device will become unusable after purging this key."),
+ _("Enter any remaining passphrase: "),
+ _("Operation aborted, the keyslot was NOT wiped.\n"),
+ ARG_STR(OPT_KEY_FILE_ID), ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID));
+ tools_keyslot_msg(r, UNLOCKED);
+
+ if (r == -EPIPE && (!ARG_SET(OPT_KEY_FILE_ID) || tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID)))) {
+ log_dbg("Failed read from input, ignoring passphrase.");
+ r = 0;
+ }
+
+ if (r < 0)
+ goto out;
+ }
+
+ r = crypt_keyslot_destroy(cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ tools_keyslot_msg(ARG_INT32(OPT_KEY_SLOT_ID), REMOVED);
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksRemoveKey(void)
+{
+ struct crypt_device *cd = NULL;
+ char *password = NULL;
+ size_t passwordLen;
+ int r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ r = tools_get_key(_("Enter passphrase to be deleted: "),
+ &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0,
+ cd);
+ if(r < 0)
+ goto out;
+
+ r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT,
+ password, passwordLen, 0);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, UNLOCKED);
+
+ ARG_SET_INT32(OPT_KEY_SLOT_ID, r);
+ log_verbose(_("Keyslot %d is selected for deletion."), ARG_INT32(OPT_KEY_SLOT_ID));
+
+ if (crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID)) == CRYPT_SLOT_ACTIVE_LAST &&
+ !ARG_SET(OPT_BATCH_MODE_ID) &&
+ !yesDialog(_("This is the last keyslot. "
+ "Device will become unusable after purging this key."),
+ _("Operation aborted, the keyslot was NOT wiped.\n"))) {
+ r = -EPERM;
+ goto out;
+ }
+
+ r = crypt_keyslot_destroy(cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ tools_keyslot_msg(ARG_INT32(OPT_KEY_SLOT_ID), REMOVED);
+out:
+ crypt_safe_free(password);
+ crypt_free(cd);
+ return r;
+}
+
+static int luksAddUnboundKey(void)
+{
+ int r = -EINVAL, keysize = 0;
+ char *key = NULL;
+ const char *new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
+ char *password_new = NULL;
+ size_t password_new_size = 0;
+ struct crypt_device *cd = NULL;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) {
+ log_err(_("Device %s is not a valid LUKS2 device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ r = _set_keyslot_encryption_params(cd);
+ if (r < 0)
+ goto out;
+
+ /* Never call pwquality if using null cipher */
+ if (crypt_is_cipher_null(crypt_get_cipher(cd)))
+ ARG_SET_TRUE(OPT_FORCE_PASSWORD_ID);
+
+ keysize = ARG_UINT32(OPT_KEY_SIZE_ID) / 8;
+ r = set_pbkdf_params(cd, crypt_get_type(cd));
+ if (r) {
+ log_err(_("Failed to set pbkdf parameters."));
+ goto out;
+ }
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize);
+ if (r < 0)
+ goto out;
+
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ }
+
+ r = tools_get_key(_("Enter new passphrase for key slot: "),
+ &password_new, &password_new_size,
+ ARG_UINT64(OPT_NEW_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_NEW_KEYFILE_SIZE_ID),
+ new_key_file, ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(1), !ARG_SET(OPT_FORCE_PASSWORD_ID), cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_keyslot_add_by_key(cd, ARG_INT32(OPT_KEY_SLOT_ID), key, keysize,
+ password_new, password_new_size, CRYPT_VOLUME_KEY_NO_SEGMENT);
+ tools_keyslot_msg(r, CREATED);
+out:
+ crypt_safe_free(password_new);
+ crypt_safe_free(key);
+ crypt_free(cd);
+ return r;
+}
+
+static int _ask_for_pin(struct crypt_device *cd,
+ int token_id, char **r_pin, size_t *r_pin_size,
+ struct crypt_keyslot_context *kc)
+{
+ int r;
+ char msg[64];
+
+ assert(r_pin);
+ assert(r_pin_size);
+ assert(kc);
+ assert(token_id >= 0 || token_id == CRYPT_ANY_TOKEN);
+
+ if (crypt_keyslot_context_get_type(kc) != CRYPT_KC_TYPE_TOKEN)
+ return -EINVAL;
+
+ if (token_id == CRYPT_ANY_TOKEN)
+ r = snprintf(msg, sizeof(msg), _("Enter token PIN: "));
+ else
+ r = snprintf(msg, sizeof(msg), _("Enter token %d PIN: "), token_id);
+ if (r < 0 || (size_t)r >= sizeof(msg))
+ return -EINVAL;
+
+ r = tools_get_key(msg, r_pin, r_pin_size, 0, 0, NULL,
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ return r;
+
+ r = crypt_keyslot_context_set_pin(cd, *r_pin, *r_pin_size, kc);
+ if (r < 0) {
+ crypt_safe_free(*r_pin);
+ *r_pin = NULL;
+ *r_pin_size = 0;
+ }
+
+ return r;
+}
+
+static int try_keyslot_add(struct crypt_device *cd,
+ int keyslot_existing,
+ int keyslot_new,
+ struct crypt_keyslot_context *kc,
+ struct crypt_keyslot_context *kc_new,
+ bool pin_provided,
+ bool new_pin_provided)
+{
+ int r;
+
+ r = crypt_keyslot_add_by_keyslot_context(cd, keyslot_existing, kc, keyslot_new, kc_new, 0);
+ if (crypt_keyslot_context_get_type(kc) == CRYPT_KC_TYPE_TOKEN)
+ tools_token_error_msg(crypt_keyslot_context_get_error(kc), ARG_STR(OPT_TOKEN_TYPE_ID),
+ ARG_INT32(OPT_TOKEN_ID_ID), pin_provided);
+ if (crypt_keyslot_context_get_type(kc_new) == CRYPT_KC_TYPE_TOKEN)
+ tools_token_error_msg(crypt_keyslot_context_get_error(kc_new), NULL,
+ ARG_INT32(OPT_NEW_TOKEN_ID_ID), new_pin_provided);
+ return r;
+}
+
+static int action_luksAddKey(void)
+{
+ int keyslot_old, keyslot_new, keysize = 0, r = -EINVAL;
+ const char *new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
+ char *key = NULL, *password = NULL, *password_new = NULL, *pin = NULL, *pin_new = NULL;
+ size_t pin_size, pin_size_new, password_size = 0, password_new_size = 0;
+ struct crypt_device *cd = NULL;
+ struct crypt_keyslot_context *p_kc_new = NULL, *kc = NULL, *kc_new = NULL;
+
+ /* Unbound keyslot (no assigned data segment) is special case */
+ if (ARG_SET(OPT_UNBOUND_ID))
+ return luksAddUnboundKey();
+
+ /* maintain backward compatibility of luksAddKey action positional parameter */
+ if (!new_key_file)
+ new_key_file = ARG_STR(OPT_NEW_KEYFILE_ID);
+
+ keyslot_old = ARG_INT32(OPT_KEY_SLOT_ID);
+ keyslot_new = ARG_INT32(OPT_NEW_KEY_SLOT_ID);
+
+ /*
+ * maintain backward compatibility of --key-slot/-S as 'new keyslot number'
+ * unless --new-key-slot is used.
+ */
+ if (!ARG_SET(OPT_NEW_KEY_SLOT_ID) && ARG_SET(OPT_KEY_SLOT_ID)) {
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ log_std(_("WARNING: The --key-slot parameter is used for new keyslot number.\n"));
+ keyslot_old = CRYPT_ANY_SLOT;
+ keyslot_new = ARG_INT32(OPT_KEY_SLOT_ID);
+ }
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ r = _set_keyslot_encryption_params(cd);
+ if (r < 0)
+ goto out;
+
+ /* Never call pwquality if using null cipher */
+ if (crypt_is_cipher_null(crypt_get_cipher(cd)))
+ ARG_SET_TRUE(OPT_FORCE_PASSWORD_ID);
+
+ keysize = crypt_get_volume_key_size(cd);
+ r = set_pbkdf_params(cd, crypt_get_type(cd));
+ if (r) {
+ log_err(_("Failed to set pbkdf parameters."));
+ goto out;
+ }
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) {
+ log_err(_("Cannot determine volume key size for LUKS without keyslots, please use --key-size option."));
+ r = -EINVAL;
+ goto out;
+ } else if (!keysize)
+ keysize = ARG_UINT32(OPT_KEY_SIZE_ID) / 8;
+
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, keysize);
+ if (r < 0)
+ goto out;
+
+ r = crypt_volume_key_verify(cd, key, keysize);
+ if (r == -EPERM)
+ log_err(_("Volume key does not match the volume."));
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ r = crypt_keyslot_context_init_by_volume_key(cd, key, keysize, &kc);
+ } else if (ARG_SET(OPT_KEY_FILE_ID) && !tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID)))
+ r = crypt_keyslot_context_init_by_keyfile(cd,
+ ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_KEYFILE_SIZE_ID),
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID),
+ &kc);
+ else if (ARG_SET(OPT_TOKEN_ID_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || ARG_SET(OPT_TOKEN_ONLY_ID)) {
+ r = crypt_keyslot_context_init_by_token(cd,
+ ARG_INT32(OPT_TOKEN_ID_ID),
+ ARG_STR(OPT_TOKEN_TYPE_ID),
+ NULL, 0, NULL, &kc);
+ } else {
+ r = tools_get_key(_("Enter any existing passphrase: "),
+ &password, &password_size,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+
+ if (r < 0)
+ goto out;
+
+ /* Check password before asking for new one */
+ r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT,
+ password, password_size, 0);
+ check_signal(&r);
+ tools_passphrase_msg(r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, UNLOCKED);
+
+ r = crypt_keyslot_context_init_by_passphrase(cd, password, password_size, &kc);
+ }
+
+ if (r < 0)
+ goto out;
+
+ if (new_key_file && !tools_is_stdin(new_key_file)) {
+ if (ARG_SET(OPT_KEY_FILE_ID) && !strcmp(ARG_STR(OPT_KEY_FILE_ID), new_key_file))
+ p_kc_new = kc;
+ else {
+ r = crypt_keyslot_context_init_by_keyfile(cd,
+ new_key_file,
+ ARG_UINT32(OPT_NEW_KEYFILE_SIZE_ID),
+ ARG_UINT64(OPT_NEW_KEYFILE_OFFSET_ID),
+ &kc_new);
+ p_kc_new = kc_new;
+ }
+ } else if (ARG_SET(OPT_NEW_TOKEN_ID_ID)) {
+ if (ARG_INT32(OPT_NEW_TOKEN_ID_ID) == ARG_INT32(OPT_TOKEN_ID_ID))
+ p_kc_new = kc;
+ else {
+ r = crypt_keyslot_context_init_by_token(cd,
+ ARG_INT32(OPT_NEW_TOKEN_ID_ID),
+ NULL, NULL, 0, NULL, &kc_new);
+ p_kc_new = kc_new;
+ }
+ } else {
+ r = tools_get_key(_("Enter new passphrase for key slot: "),
+ &password_new, &password_new_size,
+ ARG_UINT64(OPT_NEW_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_NEW_KEYFILE_SIZE_ID), new_key_file,
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(1), !ARG_SET(OPT_FORCE_PASSWORD_ID), cd);
+
+ if (r < 0)
+ goto out;
+ r = crypt_keyslot_context_init_by_passphrase(cd, password_new, password_new_size, &kc_new);
+ }
+
+ if (r < 0)
+ goto out;
+
+ if (!p_kc_new)
+ p_kc_new = kc_new;
+
+ r = try_keyslot_add(cd, keyslot_old, keyslot_new, kc, p_kc_new, pin, pin_new);
+ if (r >= 0 || r != -ENOANO)
+ goto out;
+
+ if (crypt_keyslot_context_get_error(kc) == -ENOANO) {
+ r = _ask_for_pin(cd, ARG_INT32(OPT_TOKEN_ID_ID), &pin, &pin_size, kc);
+ if (r < 0)
+ goto out;
+
+ r = try_keyslot_add(cd, keyslot_old, keyslot_new, kc, p_kc_new, pin, pin_new);
+ if (r >= 0 || r != -ENOANO)
+ goto out;
+ }
+
+ if (crypt_keyslot_context_get_error(p_kc_new) == -ENOANO) {
+ r = _ask_for_pin(cd, ARG_INT32(OPT_NEW_TOKEN_ID_ID), &pin_new, &pin_size_new, p_kc_new);
+ if (r < 0)
+ goto out;
+ r = try_keyslot_add(cd, keyslot_old, keyslot_new, kc, p_kc_new, pin, pin_new);
+ }
+out:
+ tools_keyslot_msg(r, CREATED);
+ crypt_keyslot_context_free(kc);
+ crypt_keyslot_context_free(kc_new);
+ crypt_safe_free(password);
+ crypt_safe_free(password_new);
+ crypt_safe_free(pin);
+ crypt_safe_free(pin_new);
+ crypt_safe_free(key);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksChangeKey(void)
+{
+ const char *new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
+ struct crypt_device *cd = NULL;
+ char *password = NULL, *password_new = NULL;
+ size_t password_size = 0, password_new_size = 0;
+ int r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ r = _set_keyslot_encryption_params(cd);
+ if (r < 0)
+ goto out;
+
+ /* Never call pwquality if using null cipher */
+ if (crypt_is_cipher_null(crypt_get_cipher(cd)))
+ ARG_SET_TRUE(OPT_FORCE_PASSWORD_ID);
+
+ r = set_pbkdf_params(cd, crypt_get_type(cd));
+ if (r) {
+ log_err(_("Failed to set pbkdf parameters."));
+ goto out;
+ }
+
+ r = tools_get_key(_("Enter passphrase to be changed: "),
+ &password, &password_size,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ /* Check password before asking for new one */
+ r = crypt_activate_by_passphrase(cd, NULL, ARG_INT32(OPT_KEY_SLOT_ID),
+ password, password_size, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, UNLOCKED);
+
+ r = tools_get_key(_("Enter new passphrase: "),
+ &password_new, &password_new_size,
+ ARG_UINT64(OPT_NEW_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_NEW_KEYFILE_SIZE_ID),
+ new_key_file,
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(1), !ARG_SET(OPT_FORCE_PASSWORD_ID), cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_keyslot_change_by_passphrase(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_KEY_SLOT_ID),
+ password, password_size, password_new, password_new_size);
+ tools_keyslot_msg(r, CREATED);
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(password_new);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksConvertKey(void)
+{
+ struct crypt_device *cd = NULL;
+ char *password = NULL;
+ size_t password_size = 0;
+ int r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) {
+ log_err(_("Device %s is not a valid LUKS2 device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ r = _set_keyslot_encryption_params(cd);
+ if (r < 0)
+ goto out;
+
+ if (crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID)) == CRYPT_SLOT_INACTIVE) {
+ r = -EINVAL;
+ log_err(_("Keyslot %d is not active."), ARG_INT32(OPT_KEY_SLOT_ID));
+ goto out;
+ }
+
+ r = set_pbkdf_params(cd, crypt_get_type(cd));
+ if (r) {
+ log_err(_("Failed to set pbkdf parameters."));
+ goto out;
+ }
+
+ r = tools_get_key(_("Enter passphrase for keyslot to be converted: "),
+ &password, &password_size,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_keyslot_change_by_passphrase(cd, ARG_INT32(OPT_KEY_SLOT_ID), ARG_INT32(OPT_KEY_SLOT_ID),
+ password, password_size, password, password_size);
+ tools_passphrase_msg(r);
+ tools_keyslot_msg(r, CREATED);
+out:
+ crypt_safe_free(password);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_isLuks(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ /* FIXME: argc > max should be checked for other operations as well */
+ if (action_argc > 1) {
+ log_err(_("Only one device argument for isLuks operation is supported."));
+ return -ENODEV;
+ }
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ crypt_set_log_callback(cd, quiet_log, &log_parms);
+ r = crypt_load(cd, luksType(device_type), NULL);
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksUUID(void)
+{
+ struct crypt_device *cd = NULL;
+ const char *existing_uuid = NULL;
+ int r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ crypt_set_confirm_callback(cd, yesDialog, _("Operation aborted.\n"));
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL)))
+ goto out;
+
+ if (ARG_SET(OPT_UUID_ID))
+ r = crypt_set_uuid(cd, ARG_STR(OPT_UUID_ID));
+ else {
+ existing_uuid = crypt_get_uuid(cd);
+ log_std("%s\n", existing_uuid ?: "");
+ r = existing_uuid ? 0 : 1;
+ }
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int luksDump_with_volume_key(struct crypt_device *cd)
+{
+ char *vk = NULL, *password = NULL;
+ size_t passwordLen = 0;
+ size_t vk_size;
+ int r;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(
+ _("The header dump with volume key is sensitive information\n"
+ "that allows access to encrypted partition without a passphrase.\n"
+ "This dump should be stored encrypted in a safe place."),
+ NULL))
+ return -EPERM;
+
+ vk_size = crypt_get_volume_key_size(cd);
+ vk = crypt_safe_alloc(vk_size);
+ if (!vk)
+ return -ENOMEM;
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), 0, 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size,
+ password, passwordLen);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, UNLOCKED);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_write_mk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), vk, vk_size);
+ if (r < 0)
+ goto out;
+ }
+
+ log_std("LUKS header information for %s\n", crypt_get_device_name(cd));
+ log_std("Cipher name: \t%s\n", crypt_get_cipher(cd));
+ log_std("Cipher mode: \t%s\n", crypt_get_cipher_mode(cd));
+ log_std("Payload offset:\t%d\n", (int)crypt_get_data_offset(cd));
+ log_std("UUID: \t%s\n", crypt_get_uuid(cd));
+ log_std("MK bits: \t%d\n", (int)vk_size * 8);
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ log_std("Key stored to file %s.\n", ARG_STR(OPT_VOLUME_KEY_FILE_ID));
+ goto out;
+ }
+ log_std("MK dump:\t");
+ crypt_log_hex(NULL, vk, vk_size, " ", 16, "\n\t\t");
+ log_std("\n");
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(vk);
+ return r;
+}
+
+static int luksDump_with_unbound_key(struct crypt_device *cd)
+{
+ crypt_keyslot_info ki;
+ char *uk = NULL, *password = NULL;
+ size_t uk_size, passwordLen = 0;
+ int r;
+
+ ki = crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ if (ki != CRYPT_SLOT_UNBOUND) {
+ log_err(_("Keyslot %d does not contain unbound key."), ARG_INT32(OPT_KEY_SLOT_ID));
+ return -EINVAL;
+ }
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(
+ _("The header dump with unbound key is sensitive information.\n"
+ "This dump should be stored encrypted in a safe place."),
+ NULL))
+ return -EPERM;
+
+ r = crypt_keyslot_get_key_size(cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ if (r < 0)
+ return -EINVAL;
+ uk_size = r;
+ uk = crypt_safe_alloc(uk_size);
+ if (!uk)
+ return -ENOMEM;
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), 0, 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_volume_key_get(cd, ARG_INT32(OPT_KEY_SLOT_ID), uk, &uk_size,
+ password, passwordLen);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, UNLOCKED);
+
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_write_mk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), uk, uk_size);
+ if (r < 0)
+ goto out;
+ }
+
+ log_std("LUKS header information for %s\n", crypt_get_device_name(cd));
+ log_std("UUID: \t%s\n", crypt_get_uuid(cd));
+ log_std("Keyslot: \t%d\n", ARG_INT32(OPT_KEY_SLOT_ID));
+ log_std("Key bits:\t%d\n", (int)uk_size * 8);
+ if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ log_std("Key stored to file %s.\n", ARG_STR(OPT_VOLUME_KEY_FILE_ID));
+ goto out;
+ }
+ log_std("Unbound Key:\t");
+ crypt_log_hex(NULL, uk, uk_size, " ", 16, "\n\t\t");
+ log_std("\n");
+out:
+ crypt_safe_free(password);
+ crypt_safe_free(uk);
+ return r;
+}
+
+static int action_luksDump(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ if (ARG_SET(OPT_DUMP_VOLUME_KEY_ID))
+ r = luksDump_with_volume_key(cd);
+ else if (ARG_SET(OPT_UNBOUND_ID))
+ r = luksDump_with_unbound_key(cd);
+ else if (ARG_SET(OPT_DUMP_JSON_ID))
+ r = crypt_dump_json(cd, NULL, 0);
+ else
+ r = crypt_dump(cd);
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksSuspend(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(ARG_STR(OPT_HEADER_ID)));
+ if (!r) {
+ r = crypt_suspend(cd, action_argv[0]);
+ if (r == -ENODEV)
+ log_err(_("%s is not active %s device name."), action_argv[0], "LUKS");
+ }
+
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksResume(void)
+{
+ struct crypt_device *cd = NULL;
+ char *password = NULL;
+ size_t passwordLen;
+ int r, tries;
+ struct crypt_active_device cad;
+ const char *req_type = luksType(device_type);
+
+ if (req_type && !isLUKS(req_type))
+ return -EINVAL;
+
+ if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], uuid_or_device(ARG_STR(OPT_HEADER_ID)))))
+ return r;
+
+ r = -EINVAL;
+ if (!isLUKS(crypt_get_type(cd))) {
+ log_err(_("%s is not active LUKS device name or header is missing."), action_argv[0]);
+ goto out;
+ }
+
+ if (req_type && strcmp(req_type, crypt_get_type(cd))) {
+ log_err(_("%s is not active %s device name."), action_argv[0], req_type);
+ goto out;
+ }
+
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r < 0)
+ goto out;
+
+ if (!(cad.flags & CRYPT_ACTIVATE_SUSPENDED)) {
+ log_err(_("Volume %s is not suspended."), action_argv[0]);
+ r = -EINVAL;
+ goto out;
+ }
+
+ /* try to resume LUKS2 device by token first */
+ r = crypt_resume_by_token_pin(cd, action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID),
+ ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL);
+ tools_keyslot_msg(r, UNLOCKED);
+ tools_token_error_msg(r, ARG_STR(OPT_TOKEN_TYPE_ID), ARG_INT32(OPT_TOKEN_ID_ID), false);
+
+ /* Token requires PIN. Ask if there is evident preference for tokens */
+ if (r == -ENOANO && (ARG_SET(OPT_TOKEN_ONLY_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) ||
+ ARG_SET(OPT_TOKEN_ID_ID)))
+ r = _try_token_pin_unlock(cd, ARG_INT32(OPT_TOKEN_ID_ID), action_argv[0], ARG_STR(OPT_TOKEN_TYPE_ID), 0, set_tries_tty(), false);
+
+ if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
+ goto out;
+
+ tries = set_tries_tty();
+ do {
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ r = crypt_resume_by_passphrase(cd, action_argv[0], ARG_INT32(OPT_KEY_SLOT_ID),
+ password, passwordLen);
+ tools_passphrase_msg(r);
+ check_signal(&r);
+ tools_keyslot_msg(r, UNLOCKED);
+
+ crypt_safe_free(password);
+ password = NULL;
+ } while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
+out:
+ crypt_safe_free(password);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksBackup(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ if (!ARG_SET(OPT_HEADER_BACKUP_FILE_ID)) {
+ log_err(_("Option --header-backup-file is required."));
+ return -EINVAL;
+ }
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ r = crypt_header_backup(cd, NULL, ARG_STR(OPT_HEADER_BACKUP_FILE_ID));
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksRestore(void)
+{
+ struct crypt_device *cd = NULL;
+ int r = 0;
+
+ if (!ARG_SET(OPT_HEADER_BACKUP_FILE_ID)) {
+ log_err(_("Option --header-backup-file is required."));
+ return -EINVAL;
+ }
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ crypt_set_confirm_callback(cd, yesDialog, NULL);
+ r = crypt_header_restore(cd, NULL, ARG_STR(OPT_HEADER_BACKUP_FILE_ID));
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static const char *_get_device_type(void)
+{
+ const char *type, *name = NULL;
+ struct crypt_device *cd = NULL;
+
+ if (action_argc > 1)
+ name = action_argv[1];
+ else if (action_argc == 1)
+ name = action_argv[0];
+
+ if (crypt_init_by_name_and_header(&cd, name, ARG_STR(OPT_HEADER_ID)))
+ return NULL;
+
+ type = crypt_get_type(cd);
+ if (!type) {
+ crypt_free(cd);
+ log_err(_("%s is not cryptsetup managed device."), name);
+ return NULL;
+ }
+
+ if (!strncmp(type, "LUKS", 4))
+ type = "luks";
+ else if (!strcmp(type, CRYPT_PLAIN))
+ type = "plain";
+ else if (!strcmp(type, CRYPT_LOOPAES))
+ type = "loopaes";
+ else {
+ log_err(_("Refresh is not supported for device type %s"), type);
+ type = NULL;
+ }
+
+ crypt_free(cd);
+
+ return type;
+}
+
+static int action_open(void)
+{
+ int r = -EINVAL;
+
+ if (ARG_SET(OPT_REFRESH_ID) && !device_type)
+ /* read device type from active mapping */
+ device_type = _get_device_type();
+
+ if (!device_type)
+ return -EINVAL;
+
+ if (!strcmp(device_type, "luks") ||
+ !strcmp(device_type, "luks1") ||
+ !strcmp(device_type, "luks2")) {
+ if (action_argc < 2 && (!ARG_SET(OPT_TEST_PASSPHRASE_ID) && !ARG_SET(OPT_REFRESH_ID)))
+ goto out;
+ return action_open_luks();
+ } else if (!strcmp(device_type, "plain")) {
+ if (action_argc < 2 && !ARG_SET(OPT_REFRESH_ID))
+ goto out;
+ return action_open_plain();
+ } else if (!strcmp(device_type, "loopaes")) {
+ if (action_argc < 2 && !ARG_SET(OPT_REFRESH_ID))
+ goto out;
+ return action_open_loopaes();
+ } else if (!strcmp(device_type, "tcrypt")) {
+ if (action_argc < 2 && !ARG_SET(OPT_TEST_PASSPHRASE_ID))
+ goto out;
+ return action_open_tcrypt();
+ } else if (!strcmp(device_type, "bitlk")) {
+ if (action_argc < 2 && !ARG_SET(OPT_TEST_PASSPHRASE_ID))
+ goto out;
+ return action_open_bitlk();
+ } else if (!strcmp(device_type, "fvault2")) {
+ if (action_argc < 2 && !ARG_SET(OPT_TEST_PASSPHRASE_ID))
+ goto out;
+ return action_open_fvault2();
+ } else
+ r = -ENOENT;
+out:
+ if (r == -ENOENT)
+ log_err(_("Unrecognized metadata device type %s."), device_type);
+ else
+ log_err(_("Command requires device and mapped name as arguments."));
+
+ return r;
+}
+
+static int action_luksErase(void)
+{
+ struct crypt_device *cd = NULL;
+ crypt_keyslot_info ki;
+ char *msg = NULL;
+ int i, max, r;
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ goto out;
+
+ if ((r = crypt_load(cd, luksType(device_type), NULL))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ if(asprintf(&msg, _("This operation will erase all keyslots on device %s.\n"
+ "Device will become unusable after this operation."),
+ uuid_or_device_header(NULL)) == -1) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !yesDialog(msg, _("Operation aborted, keyslots were NOT wiped.\n"))) {
+ r = -EPERM;
+ goto out;
+ }
+
+ /* Safety check */
+ max = crypt_keyslot_max(crypt_get_type(cd));
+ if (max <= 0) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < max; i++) {
+ ki = crypt_keyslot_status(cd, i);
+ if (ki == CRYPT_SLOT_ACTIVE || ki == CRYPT_SLOT_ACTIVE_LAST) {
+ r = crypt_keyslot_destroy(cd, i);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(i, REMOVED);
+ }
+ }
+out:
+ free(msg);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_luksConvert(void)
+{
+ struct crypt_device *cd = NULL;
+ char *msg = NULL;
+ const char *to_type, *from_type;
+ int r;
+
+ if (!strcmp(device_type, "luks2")) {
+ to_type = CRYPT_LUKS2;
+ } else if (!strcmp(device_type, "luks1")) {
+ to_type = CRYPT_LUKS1;
+ } else {
+ log_err(_("Invalid LUKS type, only luks1 and luks2 are supported."));
+ return -EINVAL;
+ }
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ return r;
+
+ if ((r = crypt_load(cd, CRYPT_LUKS, NULL)) ||
+ !(from_type = crypt_get_type(cd))) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ uuid_or_device_header(NULL));
+ crypt_free(cd);
+ return r;
+ }
+
+ if (!strcmp(from_type, to_type)) {
+ log_err(_("Device is already %s type."), to_type);
+ crypt_free(cd);
+ return -EINVAL;
+ }
+
+ r = 0;
+ if (!ARG_SET(OPT_BATCH_MODE_ID)) {
+ if (asprintf(&msg, _("This operation will convert %s to %s format.\n"),
+ uuid_or_device_header(NULL), to_type) == -1)
+ r = -ENOMEM;
+ else if (!yesDialog(msg, _("Operation aborted, device was NOT converted.\n")))
+ r = -EPERM;
+ }
+
+ r = r ?: crypt_convert(cd, to_type, NULL);
+
+ free(msg);
+ crypt_free(cd);
+ return r;
+}
+
+static int _config_priority(struct crypt_device *cd)
+{
+ crypt_keyslot_info cs;
+ crypt_keyslot_priority priority = CRYPT_SLOT_PRIORITY_INVALID;
+
+ if (!strcmp("normal", ARG_STR(OPT_PRIORITY_ID)))
+ priority = CRYPT_SLOT_PRIORITY_NORMAL;
+ else if (!strcmp("prefer", ARG_STR(OPT_PRIORITY_ID)))
+ priority = CRYPT_SLOT_PRIORITY_PREFER;
+ else if (!strcmp("ignore", ARG_STR(OPT_PRIORITY_ID)))
+ priority = CRYPT_SLOT_PRIORITY_IGNORE;
+
+ cs = crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ if (cs != CRYPT_SLOT_INVALID)
+ return crypt_keyslot_set_priority(cd, ARG_INT32(OPT_KEY_SLOT_ID), priority);
+ return -EINVAL;
+}
+
+static int _config_labels(struct crypt_device *cd)
+{
+ return crypt_set_label(cd, ARG_STR(OPT_LABEL_ID), ARG_STR(OPT_SUBSYSTEM_ID));
+}
+
+static int action_luksConfig(void)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+
+ if (!ARG_SET(OPT_PRIORITY_ID) && !ARG_SET(OPT_LABEL_ID) && !ARG_SET(OPT_SUBSYSTEM_ID)) {
+ log_err(_("Option --priority, --label or --subsystem is missing."));
+ return -EINVAL;
+ }
+
+ if ((r = crypt_init(&cd, uuid_or_device_header(NULL))))
+ return r;
+
+ if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) {
+ log_err(_("Device %s is not a valid LUKS2 device."),
+ uuid_or_device_header(NULL));
+ goto out;
+ }
+
+ if (ARG_SET(OPT_PRIORITY_ID) && (r = _config_priority(cd)))
+ goto out;
+
+ if ((ARG_SET(OPT_LABEL_ID) || ARG_SET(OPT_SUBSYSTEM_ID)) && (r = _config_labels(cd)))
+ goto out;
+out:
+ crypt_free(cd);
+ return r;
+}
+
+static int _token_add(struct crypt_device *cd)
+{
+ int r, token;
+ crypt_token_info token_info;
+ const struct crypt_token_params_luks2_keyring params = {
+ .key_description = ARG_STR(OPT_KEY_DESCRIPTION_ID)
+ };
+
+ if (ARG_INT32(OPT_TOKEN_ID_ID) != CRYPT_ANY_TOKEN) {
+ token_info = crypt_token_status(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL);
+ if (token_info < CRYPT_TOKEN_INACTIVE) {
+ log_err(_("Token %d is invalid."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return -EINVAL;
+ } else if (token_info > CRYPT_TOKEN_INACTIVE && !ARG_SET(OPT_TOKEN_REPLACE_ID)) {
+ log_err(_("Token %d in use."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return -EINVAL;
+ }
+ }
+
+ if (crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID)) == CRYPT_SLOT_INACTIVE) {
+ log_err(_("Keyslot %d is not active."), ARG_INT32(OPT_KEY_SLOT_ID));
+ return -EINVAL;
+ }
+
+ r = crypt_token_luks2_keyring_set(cd, ARG_INT32(OPT_TOKEN_ID_ID), &params);
+ if (r < 0) {
+ log_err(_("Failed to add luks2-keyring token %d."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return r;
+ }
+
+ token = r;
+
+ if (ARG_SET(OPT_UNBOUND_ID))
+ return token;
+
+ r = crypt_token_assign_keyslot(cd, token, ARG_INT32(OPT_KEY_SLOT_ID));
+ if (r < 0) {
+ log_err(_("Failed to assign token %d to keyslot %d."), token, ARG_INT32(OPT_KEY_SLOT_ID));
+ (void) crypt_token_json_set(cd, token, NULL);
+ return r;
+ }
+
+ return token;
+}
+
+static int _token_remove(struct crypt_device *cd)
+{
+ crypt_token_info token_info;
+
+ token_info = crypt_token_status(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL);
+ if (token_info < CRYPT_TOKEN_INACTIVE) {
+ log_err(_("Token %d is invalid."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return -EINVAL;
+ } else if (token_info == CRYPT_TOKEN_INACTIVE) {
+ log_err(_("Token %d is not in use."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return -EINVAL;
+ }
+
+ return crypt_token_json_set(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL);
+}
+
+static int _token_import(struct crypt_device *cd)
+{
+ char *json;
+ size_t json_length;
+ crypt_token_info token_info;
+ int r, token;
+
+ if (ARG_INT32(OPT_TOKEN_ID_ID) != CRYPT_ANY_TOKEN) {
+ token_info = crypt_token_status(cd, ARG_INT32(OPT_TOKEN_ID_ID), NULL);
+ if (token_info < CRYPT_TOKEN_INACTIVE) {
+ log_err(_("Token %d is invalid."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return -EINVAL;
+ } else if (token_info > CRYPT_TOKEN_INACTIVE && !ARG_SET(OPT_TOKEN_REPLACE_ID)) {
+ log_err(_("Token %d in use."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return -EINVAL;
+ }
+ }
+
+ if (crypt_keyslot_status(cd, ARG_INT32(OPT_KEY_SLOT_ID)) == CRYPT_SLOT_INACTIVE) {
+ log_err(_("Keyslot %d is not active."), ARG_INT32(OPT_KEY_SLOT_ID));
+ return -EINVAL;
+ }
+
+ r = tools_read_json_file(ARG_STR(OPT_JSON_FILE_ID), &json, &json_length, ARG_SET(OPT_BATCH_MODE_ID));
+ if (r)
+ return r;
+
+ r = crypt_token_json_set(cd, ARG_INT32(OPT_TOKEN_ID_ID), json);
+ free(json);
+ if (r < 0) {
+ log_err(_("Failed to import token from file."));
+ return r;
+ }
+
+ token = r;
+
+ if (ARG_INT32(OPT_KEY_SLOT_ID) != CRYPT_ANY_SLOT) {
+ r = crypt_token_assign_keyslot(cd, token, ARG_INT32(OPT_KEY_SLOT_ID));
+ if (r < 0) {
+ log_err(_("Failed to assign token %d to keyslot %d."), token, ARG_INT32(OPT_KEY_SLOT_ID));
+ (void) crypt_token_json_set(cd, token, NULL);
+ return r;
+ }
+ }
+
+ return token;
+}
+
+static int _token_export(struct crypt_device *cd)
+{
+ const char *json;
+ int r;
+
+ r = crypt_token_json_get(cd, ARG_INT32(OPT_TOKEN_ID_ID), &json);
+ if (r < 0) {
+ log_err(_("Failed to get token %d for export."), ARG_INT32(OPT_TOKEN_ID_ID));
+ return r;
+ }
+
+ return tools_write_json_file(ARG_STR(OPT_JSON_FILE_ID), json);
+}
+
+static int _token_unassign(struct crypt_device *cd)
+{
+ int r = crypt_token_is_assigned(cd, ARG_INT32(OPT_TOKEN_ID_ID), ARG_INT32(OPT_KEY_SLOT_ID));
+
+ if (r < 0) {
+ if (r == -ENOENT)
+ log_err(_("Token %d is not assigned to keyslot %d."), ARG_INT32(OPT_TOKEN_ID_ID), ARG_INT32(OPT_KEY_SLOT_ID));
+ else
+ log_err(_("Failed to unassign token %d from keyslot %d."), ARG_INT32(OPT_TOKEN_ID_ID), ARG_INT32(OPT_KEY_SLOT_ID));
+
+ return r;
+ }
+
+ r = crypt_token_unassign_keyslot(cd, ARG_INT32(OPT_TOKEN_ID_ID), ARG_INT32(OPT_KEY_SLOT_ID));
+ if (r < 0)
+ log_err(_("Failed to unassign token %d from keyslot %d."), ARG_INT32(OPT_TOKEN_ID_ID), ARG_INT32(OPT_KEY_SLOT_ID));
+
+ return r;
+}
+
+static int action_token(void)
+{
+ int r;
+ struct crypt_device *cd = NULL;
+
+ if ((r = crypt_init(&cd, uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[1]))))
+ return r;
+
+ if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) {
+ log_err(_("Device %s is not a valid LUKS2 device."),
+ uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[1]));
+ crypt_free(cd);
+ return r;
+ }
+
+ r = -EINVAL;
+
+ if (!strcmp(action_argv[0], "add")) {
+ r = _token_add(cd); /* adds only luks2-keyring type */
+ tools_token_msg(r, CREATED);
+ } else if (!strcmp(action_argv[0], "remove")) {
+ r = _token_remove(cd);
+ tools_token_msg(r, REMOVED);
+ } else if (!strcmp(action_argv[0], "import")) {
+ r = _token_import(cd);
+ tools_token_msg(r, CREATED);
+ } else if (!strcmp(action_argv[0], "export"))
+ r = _token_export(cd);
+ else if (!strcmp(action_argv[0], "unassign"))
+ r = _token_unassign(cd);
+
+ crypt_free(cd);
+
+ return r;
+}
+
+static int action_reencrypt(void)
+{
+ return reencrypt(action_argc, action_argv);
+}
+
+static const char *verify_tcryptdump(void)
+{
+ if ((ARG_SET(OPT_TCRYPT_HIDDEN_ID) || ARG_SET(OPT_TCRYPT_SYSTEM_ID) || ARG_SET(OPT_TCRYPT_BACKUP_ID)) && (!device_type || strcmp(device_type, "tcrypt")))
+ return _("Option --tcrypt-hidden, --tcrypt-system or --tcrypt-backup is supported only for TCRYPT device.");
+
+ if ((ARG_SET(OPT_VERACRYPT_ID) || ARG_SET(OPT_DISABLE_VERACRYPT_ID)) && (!device_type || strcmp(device_type, "tcrypt")))
+ return _("Option --veracrypt or --disable-veracrypt is supported only for TCRYPT device type.");
+
+ if (ARG_SET(OPT_VERACRYPT_PIM_ID) && ARG_SET(OPT_DISABLE_VERACRYPT_ID))
+ return _("Option --veracrypt-pim is supported only for VeraCrypt compatible devices.");
+
+ if (ARG_SET(OPT_VERACRYPT_QUERY_PIM_ID)) {
+ if (ARG_SET(OPT_DISABLE_VERACRYPT_ID))
+ return _("Option --veracrypt-query-pim is supported only for VeraCrypt compatible devices.");
+ else if (ARG_SET(OPT_VERACRYPT_PIM_ID))
+ return _("The options --veracrypt-pim and --veracrypt-query-pim are mutually exclusive.");
+ }
+
+ return NULL;
+}
+
+static const char * verify_open(void)
+{
+ if (ARG_SET(OPT_PERSISTENT_ID) && ARG_SET(OPT_TEST_PASSPHRASE_ID))
+ return _("Option --persistent is not allowed with --test-passphrase.");
+
+ if (ARG_SET(OPT_REFRESH_ID) && ARG_SET(OPT_TEST_PASSPHRASE_ID))
+ return _("Options --refresh and --test-passphrase are mutually exclusive.");
+
+ if (ARG_SET(OPT_SHARED_ID) && strcmp_or_null(device_type, "plain"))
+ return _("Option --shared is allowed only for open of plain device.");
+
+ if (ARG_SET(OPT_SKIP_ID) && strcmp_or_null(device_type, "plain") && strcmp(device_type, "loopaes"))
+ return _("Option --skip is supported only for open of plain and loopaes devices.");
+
+ if (ARG_SET(OPT_OFFSET_ID) && strcmp_or_null(device_type, "plain") && strcmp(device_type, "loopaes"))
+ return _("Option --offset with open action is only supported for plain and loopaes devices.");
+
+ if (ARG_SET(OPT_TCRYPT_HIDDEN_ID) && ARG_SET(OPT_ALLOW_DISCARDS_ID))
+ return _("Option --tcrypt-hidden cannot be combined with --allow-discards.");
+
+ if (ARG_SET(OPT_SECTOR_SIZE_ID) &&
+ (!device_type || strcmp(device_type, "plain")))
+ return _("Sector size option with open action is supported only for plain devices.");
+
+ if (ARG_SET(OPT_IV_LARGE_SECTORS_ID) && (!device_type || strcmp(device_type, "plain") ||
+ ARG_UINT32(OPT_SECTOR_SIZE_ID) <= SECTOR_SIZE))
+ return _("Large IV sectors option is supported only for opening plain type device with sector size larger than 512 bytes.");
+
+ if (ARG_SET(OPT_TEST_PASSPHRASE_ID) && (!device_type ||
+ (strncmp(device_type, "luks", 4) && strcmp(device_type, "tcrypt") &&
+ strcmp(device_type, "bitlk") && strcmp(device_type, "fvault2"))))
+ return _("Option --test-passphrase is allowed only for open of LUKS, TCRYPT, BITLK and FVAULT2 devices.");
+
+ if (ARG_SET(OPT_DEVICE_SIZE_ID) && ARG_SET(OPT_SIZE_ID))
+ return _("Options --device-size and --size cannot be combined.");
+
+ if (ARG_SET(OPT_UNBOUND_ID) && device_type && strncmp(device_type, "luks", 4))
+ return _("Option --unbound is allowed only for open of luks device.");
+
+ if (ARG_SET(OPT_UNBOUND_ID) && !ARG_SET(OPT_TEST_PASSPHRASE_ID))
+ return _("Option --unbound cannot be used without --test-passphrase.");
+
+ /* "open --type tcrypt" and "tcryptDump" checks are identical */
+ return verify_tcryptdump();
+}
+
+static const char *verify_close(void)
+{
+ if (ARG_SET(OPT_CANCEL_DEFERRED_ID) && ARG_SET(OPT_DEFERRED_ID))
+ return _("Options --cancel-deferred and --deferred cannot be used at the same time.");
+
+ return NULL;
+}
+
+static const char *verify_resize(void)
+{
+ if (ARG_SET(OPT_DEVICE_SIZE_ID) && ARG_SET(OPT_SIZE_ID))
+ return _("Options --device-size and --size cannot be combined.");
+
+ return NULL;
+}
+
+static const char *verify_reencrypt(void)
+{
+ if (ARG_SET(OPT_REDUCE_DEVICE_SIZE_ID) && ARG_SET(OPT_DEVICE_SIZE_ID))
+ return _("Options --reduce-device-size and --data-size cannot be combined.");
+
+ if (isLUKS1(luksType(device_type)) && ARG_SET(OPT_ACTIVE_NAME_ID))
+ return _("Option --active-name can be set only for LUKS2 device.");
+
+ if (ARG_SET(OPT_ACTIVE_NAME_ID) && ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID))
+ return _("Options --active-name and --force-offline-reencrypt cannot be combined.");
+
+ return NULL;
+}
+
+static const char *verify_config(void)
+{
+ if (ARG_SET(OPT_PRIORITY_ID) && ARG_INT32(OPT_KEY_SLOT_ID) == CRYPT_ANY_SLOT)
+ return _("Keyslot specification is required.");
+
+ return NULL;
+}
+
+static const char *verify_format(void)
+{
+ if (ARG_SET(OPT_ALIGN_PAYLOAD_ID) && ARG_SET(OPT_OFFSET_ID))
+ return _("Options --align-payload and --offset cannot be combined.");
+
+ if (ARG_SET(OPT_INTEGRITY_NO_WIPE_ID) && !ARG_SET(OPT_INTEGRITY_ID))
+ return _("Option --integrity-no-wipe can be used only for format action with integrity extension.");
+
+ if (ARG_SET(OPT_USE_RANDOM_ID) && ARG_SET(OPT_USE_URANDOM_ID))
+ return _("Only one of --use-[u]random options is allowed.");
+
+ return NULL;
+}
+
+static const char *verify_addkey(void)
+{
+ if (ARG_SET(OPT_UNBOUND_ID) && !ARG_UINT32(OPT_KEY_SIZE_ID))
+ return _("Key size is required with --unbound option.");
+
+ return NULL;
+}
+
+static const char *verify_luksDump(void)
+{
+ if (ARG_SET(OPT_UNBOUND_ID) && ARG_INT32(OPT_KEY_SLOT_ID) == CRYPT_ANY_SLOT)
+ return _("Keyslot specification is required.");
+
+ return NULL;
+}
+
+static const char *verify_token(void)
+{
+ if (strcmp(action_argv[0], "add") &&
+ strcmp(action_argv[0], "remove") &&
+ strcmp(action_argv[0], "import") &&
+ strcmp(action_argv[0], "export") &&
+ strcmp(action_argv[0], "unassign"))
+ return _("Invalid token action.");
+
+ if (!ARG_SET(OPT_KEY_DESCRIPTION_ID) && !strcmp(action_argv[0], "add"))
+ return _("--key-description parameter is mandatory for token add action.");
+
+ if (ARG_INT32(OPT_TOKEN_ID_ID) == CRYPT_ANY_TOKEN &&
+ (!strcmp(action_argv[0], "remove") || !strcmp(action_argv[0], "export")))
+ return _("Action requires specific token. Use --token-id parameter.");
+
+ if (ARG_SET(OPT_UNBOUND_ID)) {
+ if (strcmp(action_argv[0], "add"))
+ return _("Option --unbound is valid only with token add action.");
+ if (ARG_SET(OPT_KEY_SLOT_ID))
+ return _("Options --key-slot and --unbound cannot be combined.");
+ }
+
+ if (!strcmp(action_argv[0], "unassign")) {
+ if (!ARG_SET(OPT_KEY_SLOT_ID))
+ return _("Action requires specific keyslot. Use --key-slot parameter.");
+ if (!ARG_SET(OPT_TOKEN_ID_ID))
+ return _("Action requires specific token. Use --token-id parameter.");
+ }
+
+ return NULL;
+}
+
+static struct action_type {
+ const char *type;
+ int (*handler)(void);
+ const char *(*verify)(void);
+ int required_action_argc;
+ const char *arg_desc;
+ const char *desc;
+} action_types[] = {
+ { OPEN_ACTION, action_open, verify_open, 1, N_("<device> [--type <type>] [<name>]"),N_("open device as <name>") },
+ { CLOSE_ACTION, action_close, verify_close, 1, N_("<name>"), N_("close device (remove mapping)") },
+ { RESIZE_ACTION, action_resize, verify_resize, 1, N_("<name>"), N_("resize active device") },
+ { STATUS_ACTION, action_status, NULL, 1, N_("<name>"), N_("show device status") },
+ { BENCHMARK_ACTION, action_benchmark, NULL, 0, N_("[--cipher <cipher>]"), N_("benchmark cipher") },
+ { REPAIR_ACTION, action_luksRepair, NULL, 1, N_("<device>"), N_("try to repair on-disk metadata") },
+ { REENCRYPT_ACTION, action_reencrypt, verify_reencrypt, 0, N_("<device>"), N_("reencrypt LUKS2 device") },
+ { ERASE_ACTION, action_luksErase, NULL, 1, N_("<device>"), N_("erase all keyslots (remove encryption key)") },
+ { CONVERT_ACTION, action_luksConvert, NULL, 1, N_("<device>"), N_("convert LUKS from/to LUKS2 format") },
+ { CONFIG_ACTION, action_luksConfig, verify_config, 1, N_("<device>"), N_("set permanent configuration options for LUKS2") },
+ { FORMAT_ACTION, action_luksFormat, verify_format, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
+ { ADDKEY_ACTION, action_luksAddKey, verify_addkey, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
+ { REMOVEKEY_ACTION, action_luksRemoveKey, NULL, 1, N_("<device> [<key file>]"), N_("removes supplied key or key file from LUKS device") },
+ { CHANGEKEY_ACTION, action_luksChangeKey, NULL, 1, N_("<device> [<key file>]"), N_("changes supplied key or key file of LUKS device") },
+ { CONVERTKEY_ACTION, action_luksConvertKey, NULL, 1, N_("<device> [<key file>]"), N_("converts a key to new pbkdf parameters") },
+ { KILLKEY_ACTION, action_luksKillSlot, NULL, 2, N_("<device> <key slot>"), N_("wipes key with number <key slot> from LUKS device") },
+ { UUID_ACTION, action_luksUUID, NULL, 1, N_("<device>"), N_("print UUID of LUKS device") },
+ { ISLUKS_ACTION, action_isLuks, NULL, 1, N_("<device>"), N_("tests <device> for LUKS partition header") },
+ { LUKSDUMP_ACTION, action_luksDump, verify_luksDump, 1, N_("<device>"), N_("dump LUKS partition information") },
+ { TCRYPTDUMP_ACTION, action_tcryptDump, verify_tcryptdump, 1, N_("<device>"), N_("dump TCRYPT device information") },
+ { BITLKDUMP_ACTION, action_bitlkDump, NULL, 1, N_("<device>"), N_("dump BITLK device information") },
+ { FVAULT2DUMP_ACTION, action_fvault2Dump, NULL, 1, N_("<device>"), N_("dump FVAULT2 device information") },
+ { SUSPEND_ACTION, action_luksSuspend, NULL, 1, N_("<device>"), N_("Suspend LUKS device and wipe key (all IOs are frozen)") },
+ { RESUME_ACTION, action_luksResume, NULL, 1, N_("<device>"), N_("Resume suspended LUKS device") },
+ { HEADERBACKUP_ACTION, action_luksBackup, NULL, 1, N_("<device>"), N_("Backup LUKS device header and keyslots") },
+ { HEADERRESTORE_ACTION, action_luksRestore, NULL, 1, N_("<device>"), N_("Restore LUKS device header and keyslots") },
+ { TOKEN_ACTION, action_token, verify_token, 2, N_("<add|remove|import|export> <device>"), N_("Manipulate LUKS2 tokens") },
+ {}
+};
+
+static void help(poptContext popt_context,
+ enum poptCallbackReason reason __attribute__((unused)),
+ struct poptOption *key,
+ const char *arg __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ const char *path;
+
+ if (key->shortName == '?') {
+ struct action_type *action;
+ const struct crypt_pbkdf_type *pbkdf_luks1, *pbkdf_luks2;
+
+ tools_package_version(PACKAGE_NAME, true);
+ poptPrintHelp(popt_context, stdout, 0);
+
+ log_std(_("\n"
+ "<action> is one of:\n"));
+
+ for(action = action_types; action->type; action++)
+ log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
+
+ log_std(_("\n"
+ "You can also use old <action> syntax aliases:\n"
+ "\topen: create (plainOpen), luksOpen, loopaesOpen, tcryptOpen, bitlkOpen, fvault2Open\n"
+ "\tclose: remove (plainClose), luksClose, loopaesClose, tcryptClose, bitlkClose, fvault2Close\n"));
+ log_std(_("\n"
+ "<name> is the device to create under %s\n"
+ "<device> is the encrypted device\n"
+ "<key slot> is the LUKS key slot number to modify\n"
+ "<key file> optional key file for the new key for luksAddKey action\n"),
+ crypt_get_dir());
+
+ log_std(_("\nDefault compiled-in metadata format is %s (for luksFormat action).\n"),
+ crypt_get_default_type());
+
+ path = crypt_token_external_path();
+ if (path) {
+ log_std(_("\nLUKS2 external token plugin support is %s.\n"), _("compiled-in"));
+ log_std(_("LUKS2 external token plugin path: %s.\n"), path);
+ } else
+ log_std(_("\nLUKS2 external token plugin support is %s.\n"), _("disabled"));
+
+ pbkdf_luks1 = crypt_get_pbkdf_default(CRYPT_LUKS1);
+ pbkdf_luks2 = crypt_get_pbkdf_default(CRYPT_LUKS2);
+ log_std(_("\nDefault compiled-in key and passphrase parameters:\n"
+ "\tMaximum keyfile size: %dkB, "
+ "Maximum interactive passphrase length %d (characters)\n"
+ "Default PBKDF for LUKS1: %s, iteration time: %d (ms)\n"
+ "Default PBKDF for LUKS2: %s\n"
+ "\tIteration time: %d, Memory required: %dkB, Parallel threads: %d\n"),
+ DEFAULT_KEYFILE_SIZE_MAXKB, DEFAULT_PASSPHRASE_SIZE_MAX,
+ pbkdf_luks1->type, pbkdf_luks1->time_ms,
+ pbkdf_luks2->type, pbkdf_luks2->time_ms, pbkdf_luks2->max_memory_kb,
+ pbkdf_luks2->parallel_threads);
+
+ log_std(_("\nDefault compiled-in device cipher parameters:\n"
+ "\tloop-AES: %s, Key %d bits\n"
+ "\tplain: %s, Key: %d bits, Password hashing: %s\n"
+ "\tLUKS: %s, Key: %d bits, LUKS header hashing: %s, RNG: %s\n"),
+ DEFAULT_LOOPAES_CIPHER, DEFAULT_LOOPAES_KEYBITS,
+ DEFAULT_CIPHER(PLAIN), DEFAULT_PLAIN_KEYBITS, DEFAULT_PLAIN_HASH,
+ DEFAULT_CIPHER(LUKS1), DEFAULT_LUKS1_KEYBITS, DEFAULT_LUKS1_HASH,
+ DEFAULT_RNG);
+#if defined(ENABLE_LUKS_ADJUST_XTS_KEYSIZE) && DEFAULT_LUKS1_KEYBITS != 512
+ log_std(_("\tLUKS: Default keysize with XTS mode (two internal keys) will be doubled.\n"));
+#endif
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(EXIT_SUCCESS);
+ } else if (key->shortName == 'V') {
+ tools_package_version(PACKAGE_NAME, true);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(EXIT_SUCCESS);
+ } else
+ usage(popt_context, EXIT_SUCCESS, NULL, NULL);
+}
+
+static void help_args(struct action_type *action, poptContext popt_context)
+{
+ char buf[128];
+
+ if (snprintf(buf, sizeof(buf), _("%s: requires %s as arguments"), action->type, action->arg_desc) < 0)
+ buf[0] = '\0';
+ usage(popt_context, EXIT_FAILURE, buf, poptGetInvocationName(popt_context));
+}
+
+static int run_action(struct action_type *action)
+{
+ int r;
+
+ log_dbg("Running command %s.", action->type);
+
+ set_int_handler(0);
+ r = action->handler();
+
+ /* Some functions returns keyslot # */
+ if (r > 0)
+ r = 0;
+ check_signal(&r);
+
+ show_status(r);
+ return translate_errno(r);
+}
+
+static const char *verify_action(struct action_type *action)
+{
+ log_dbg("Verifying parameters for command %s.", action->type);
+
+ return action->verify ? action->verify() : NULL;
+}
+
+static bool needs_size_conversion(unsigned arg_id)
+{
+ return (arg_id == OPT_DEVICE_SIZE_ID || arg_id == OPT_HOTZONE_SIZE_ID ||
+ arg_id == OPT_LUKS2_KEYSLOTS_SIZE_ID || arg_id == OPT_LUKS2_METADATA_SIZE_ID ||
+ arg_id == OPT_REDUCE_DEVICE_SIZE_ID);
+}
+
+static void check_key_slot_value(poptContext popt_context)
+{
+ if (ARG_INT32(OPT_KEY_SLOT_ID) < 0)
+ usage(popt_context, EXIT_FAILURE, _("Key slot is invalid."),
+ poptGetInvocationName(popt_context));
+}
+
+static void basic_options_cb(poptContext popt_context,
+ enum poptCallbackReason reason __attribute__((unused)),
+ struct poptOption *key,
+ const char *arg,
+ void *data __attribute__((unused)))
+{
+ tools_parse_arg_value(popt_context, tool_core_args[key->val].type, tool_core_args + key->val, arg, key->val, needs_size_conversion);
+
+ /* special cases additional handling */
+ switch (key->val) {
+ case OPT_DEBUG_JSON_ID:
+ /* fall through */
+ case OPT_DEBUG_ID:
+ log_parms.debug = true;
+ /* fall through */
+ case OPT_VERBOSE_ID:
+ log_parms.verbose = true;
+ break;
+ case OPT_DEVICE_SIZE_ID:
+ if (ARG_UINT64(OPT_DEVICE_SIZE_ID) == 0)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
+ poptGetInvocationName(popt_context));
+ if (ARG_UINT64(OPT_DEVICE_SIZE_ID) % SECTOR_SIZE)
+ usage(popt_context, EXIT_FAILURE, _("Device size must be multiple of 512 bytes sector."),
+ poptGetInvocationName(popt_context));
+ break;
+ case OPT_HOTZONE_SIZE_ID:
+ if (ARG_UINT64(OPT_HOTZONE_SIZE_ID) == 0)
+ usage(popt_context, EXIT_FAILURE, _("Invalid max reencryption hotzone size specification."),
+ poptGetInvocationName(popt_context));
+ break;
+ case OPT_KEY_FILE_ID:
+ if (tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) {
+ free(keyfile_stdin);
+ keyfile_stdin = strdup(ARG_STR(OPT_KEY_FILE_ID));
+ } else if (keyfiles_count < MAX_KEYFILES)
+ keyfiles[keyfiles_count++] = strdup(ARG_STR(OPT_KEY_FILE_ID));
+ total_keyfiles++;
+ break;
+ case OPT_KEY_SIZE_ID:
+ if (ARG_UINT32(OPT_KEY_SIZE_ID) % 8)
+ usage(popt_context, EXIT_FAILURE,
+ _("Key size must be a multiple of 8 bits"),
+ poptGetInvocationName(popt_context));
+ break;
+ case OPT_KEY_SLOT_ID:
+ check_key_slot_value(popt_context);
+ break;
+ case OPT_KEYSLOT_KEY_SIZE_ID:
+ if (ARG_UINT32(OPT_KEYSLOT_KEY_SIZE_ID) == 0)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
+ poptGetInvocationName(popt_context));
+ if (ARG_UINT32(OPT_KEYSLOT_KEY_SIZE_ID) % 8)
+ usage(popt_context, EXIT_FAILURE,
+ _("Key size must be a multiple of 8 bits"),
+ poptGetInvocationName(popt_context));
+ break;
+ case OPT_REDUCE_DEVICE_SIZE_ID:
+ if (ARG_UINT64(OPT_REDUCE_DEVICE_SIZE_ID) > 1024 * 1024 * 1024)
+ usage(popt_context, EXIT_FAILURE, _("Maximum device reduce size is 1 GiB."),
+ poptGetInvocationName(popt_context));
+ if (ARG_UINT64(OPT_REDUCE_DEVICE_SIZE_ID) % SECTOR_SIZE)
+ usage(popt_context, EXIT_FAILURE, _("Reduce size must be multiple of 512 bytes sector."),
+ poptGetInvocationName(popt_context));
+ data_shift = -(int64_t)ARG_UINT64(OPT_REDUCE_DEVICE_SIZE_ID);
+ break;
+ case OPT_SECTOR_SIZE_ID:
+ if (ARG_UINT32(OPT_SECTOR_SIZE_ID) < SECTOR_SIZE ||
+ ARG_UINT32(OPT_SECTOR_SIZE_ID) > MAX_SECTOR_SIZE ||
+ (ARG_UINT32(OPT_SECTOR_SIZE_ID) & (ARG_UINT32(OPT_SECTOR_SIZE_ID) - 1)))
+ usage(popt_context, EXIT_FAILURE,
+ _("Unsupported encryption sector size."),
+ poptGetInvocationName(popt_context));
+ break;
+ case OPT_PRIORITY_ID:
+ if (strcmp(ARG_STR(OPT_PRIORITY_ID), "normal") &&
+ strcmp(ARG_STR(OPT_PRIORITY_ID), "prefer") &&
+ strcmp(ARG_STR(OPT_PRIORITY_ID), "ignore"))
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --priority can be only ignore/normal/prefer."),
+ poptGetInvocationName(popt_context));
+ break;
+ }
+}
+
+static void cryptsetup_init_arg_aliases(void)
+{
+ unsigned i;
+
+ for (i = 1; i < ARRAY_SIZE(tool_core_args); i++)
+ if (tool_core_args[i].type == CRYPT_ARG_ALIAS)
+ ARG_INIT_ALIAS(i);
+}
+
+int main(int argc, const char **argv)
+{
+ static struct poptOption popt_help_options[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, help, 0, NULL, NULL },
+ { "help", '?', POPT_ARG_NONE, NULL, 0, N_("Show this help message"), NULL },
+ { "usage", '\0', POPT_ARG_NONE, NULL, 0, N_("Display brief usage"), NULL },
+ { "version",'V', POPT_ARG_NONE, NULL, 0, N_("Print package version"), NULL },
+ POPT_TABLEEND
+ };
+ static struct poptOption popt_basic_options[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, basic_options_cb, 0, NULL, NULL },
+#define ARG(A, B, C, D, E, F, G, H) { A, B, C, NULL, A ## _ID, D, E },
+#include "cryptsetup_arg_list.h"
+#undef ARG
+ POPT_TABLEEND
+ };
+ static struct poptOption popt_options[] = {
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_basic_options, 0, NULL, NULL },
+ POPT_TABLEEND
+ };
+ poptContext popt_context;
+ struct action_type *action;
+ const char *aname, *error_message;
+ int r;
+
+ /* initialize aliases */
+ cryptsetup_init_arg_aliases();
+
+ crypt_set_log_callback(NULL, tool_log, &log_parms);
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
+ poptSetOtherOptionHelp(popt_context,
+ _("[OPTION...] <action> <action-specific>"));
+
+ while ((r = poptGetNextOpt(popt_context)) > 0) {}
+
+ if (r < -1)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(r),
+ poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
+
+ if (!(aname = poptGetArg(popt_context)))
+ usage(popt_context, EXIT_FAILURE, _("Argument <action> missing."),
+ poptGetInvocationName(popt_context));
+
+ action_argc = 0;
+ action_argv = poptGetArgs(popt_context);
+ /* Make return values of poptGetArgs more consistent in case of remaining argc = 0 */
+ if(!action_argv)
+ action_argv = null_action_argv;
+
+ /* Count args, somewhat unnice, change? */
+ while(action_argv[action_argc] != NULL)
+ action_argc++;
+
+ /* Handle aliases */
+ if (!strcmp(aname, "create")) {
+ /* create command had historically switched arguments */
+ if (action_argv[0] && action_argv[1]) {
+ const char *tmp = action_argv[0];
+ action_argv[0] = action_argv[1];
+ action_argv[1] = tmp;
+ }
+ aname = OPEN_ACTION;
+ device_type = "plain";
+ } else if (!strcmp(aname, "plainOpen")) {
+ aname = OPEN_ACTION;
+ device_type = "plain";
+ } else if (!strcmp(aname, "luksOpen")) {
+ aname = OPEN_ACTION;
+ device_type = "luks";
+ } else if (!strcmp(aname, "loopaesOpen")) {
+ aname = OPEN_ACTION;
+ device_type = "loopaes";
+ } else if (!strcmp(aname, "tcryptOpen")) {
+ aname = OPEN_ACTION;
+ device_type = "tcrypt";
+ } else if (!strcmp(aname, "bitlkOpen")) {
+ aname = OPEN_ACTION;
+ device_type = "bitlk";
+ } else if (!strcmp(aname, "fvault2Open")) {
+ aname = OPEN_ACTION;
+ device_type = "fvault2";
+ } else if (!strcmp(aname, "tcryptDump")) {
+ device_type = "tcrypt";
+ } else if (!strcmp(aname, "bitlkDump")) {
+ device_type = "bitlk";
+ } else if (!strcmp(aname, "fvault2Dump")) {
+ device_type = "fvault2";
+ } else if (!strcmp(aname, "remove") ||
+ !strcmp(aname, "plainClose") ||
+ !strcmp(aname, "luksClose") ||
+ !strcmp(aname, "loopaesClose") ||
+ !strcmp(aname, "tcryptClose") ||
+ !strcmp(aname, "bitlkClose") ||
+ !strcmp(aname, "fvault2Close")) {
+ aname = CLOSE_ACTION;
+ } else if (!strcmp(aname, "luksErase")) {
+ aname = ERASE_ACTION;
+ device_type = "luks";
+ } else if (!strcmp(aname, "luksConfig")) {
+ aname = CONFIG_ACTION;
+ device_type = "luks2";
+ } else if (!strcmp(aname, "refresh")) {
+ aname = OPEN_ACTION;
+ ARG_SET_TRUE(OPT_REFRESH_ID);
+ } else if (ARG_SET(OPT_TYPE_ID))
+ device_type = ARG_STR(OPT_TYPE_ID);
+
+ /* ignore user supplied type and query device type instead */
+ if (ARG_SET(OPT_REFRESH_ID))
+ device_type = NULL;
+
+ for(action = action_types; action->type; action++)
+ if (strcmp(action->type, aname) == 0)
+ break;
+
+ if (!action->type)
+ usage(popt_context, EXIT_FAILURE, _("Unknown action."),
+ poptGetInvocationName(popt_context));
+
+ if (action_argc < action->required_action_argc)
+ help_args(action, popt_context);
+
+ /* this routine short circuits to exit() on error */
+ tools_check_args(action->type, tool_core_args, ARRAY_SIZE(tool_core_args), popt_context);
+
+ if (!strcmp(aname, KILLKEY_ACTION) && action_argc > 1) {
+ ARG_SET_INT32(OPT_KEY_SLOT_ID, atoi(action_argv[1]));
+ check_key_slot_value(popt_context);
+ }
+
+ if ((!strcmp(aname, REMOVEKEY_ACTION) ||
+ !strcmp(aname, FORMAT_ACTION)) &&
+ action_argc > 1) {
+ if (ARG_SET(OPT_KEY_FILE_ID))
+ log_err(_("Option --key-file takes precedence over specified key file argument."));
+ else
+ ARG_SET_STR(OPT_KEY_FILE_ID, strdup(action_argv[1]));
+ }
+
+ if (total_keyfiles > 1 && (strcmp_or_null(device_type, "tcrypt")))
+ usage(popt_context, EXIT_FAILURE, _("Only one --key-file argument is allowed."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_PBKDF_ID) && crypt_parse_pbkdf(ARG_STR(OPT_PBKDF_ID), &set_pbkdf))
+ usage(popt_context, EXIT_FAILURE,
+ _("Password-based key derivation function (PBKDF) can be only pbkdf2 or argon2i/argon2id."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_PBKDF_FORCE_ITERATIONS_ID) && ARG_SET(OPT_ITER_TIME_ID))
+ usage(popt_context, EXIT_FAILURE,
+ _("PBKDF forced iterations cannot be combined with iteration time option."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_DEBUG_ID) || ARG_SET(OPT_DEBUG_JSON_ID)) {
+ crypt_set_debug_level(ARG_SET(OPT_DEBUG_JSON_ID)? CRYPT_DEBUG_JSON : CRYPT_DEBUG_ALL);
+ dbg_version_and_cmd(argc, argv);
+ }
+
+ /* reencrypt action specific check */
+
+ if (ARG_SET(OPT_KEYSLOT_CIPHER_ID) != ARG_SET(OPT_KEYSLOT_KEY_SIZE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Options --keyslot-cipher and --keyslot-key-size must be used together."),
+ poptGetInvocationName(popt_context));
+
+ error_message = verify_action(action);
+ if (error_message)
+ usage(popt_context, EXIT_FAILURE, error_message, poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_TEST_ARGS_ID)) {
+ log_std(_("No action taken. Invoked with --test-args option.\n"));
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ return 0;
+ }
+
+ if (ARG_SET(OPT_DISABLE_KEYRING_ID))
+ (void) crypt_volume_key_keyring(NULL, 0);
+
+ if (ARG_SET(OPT_DISABLE_EXTERNAL_TOKENS_ID))
+ (void) crypt_token_external_disable();
+
+ if (ARG_SET(OPT_DISABLE_LOCKS_ID) && crypt_metadata_locking(NULL, 0)) {
+ log_std(_("Cannot disable metadata locking."));
+ r = EXIT_FAILURE;
+ } else {
+ r = run_action(action);
+ }
+
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ return r;
+}
diff --git a/src/cryptsetup.h b/src/cryptsetup.h
new file mode 100644
index 0000000..011a669
--- /dev/null
+++ b/src/cryptsetup.h
@@ -0,0 +1,177 @@
+/*
+ * cryptsetup - setup cryptographic volumes for dm-crypt
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CRYPTSETUP_H
+#define CRYPTSETUP_H
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <popt.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include "lib/nls.h"
+#include "lib/bitops.h"
+#include "lib/utils_crypt.h"
+#include "lib/utils_loop.h"
+#include "lib/utils_io.h"
+#include "lib/utils_blkid.h"
+#include "lib/libcryptsetup_macros.h"
+
+#include "libcryptsetup.h"
+
+#define DEFAULT_CIPHER(type) (DEFAULT_##type##_CIPHER "-" DEFAULT_##type##_MODE)
+
+#define DEFAULT_WIPE_BLOCK 1048576 /* 1 MiB */
+#define MAX_ACTIONS 16
+
+/* Common tools */
+void tool_log(int level, const char *msg, void *usrptr __attribute__((unused)));
+void quiet_log(int level, const char *msg, void *usrptr);
+
+int yesDialog(const char *msg, void *usrptr);
+int noDialog(const char *msg, void *usrptr);
+void show_status(int errcode);
+const char *uuid_or_device(const char *spec);
+__attribute__ ((noreturn)) \
+void usage(poptContext popt_context, int exitcode, const char *error, const char *more);
+void dbg_version_and_cmd(int argc, const char **argv);
+int translate_errno(int r);
+
+typedef enum { CREATED, UNLOCKED, REMOVED } crypt_object_op;
+void tools_keyslot_msg(int keyslot, crypt_object_op op);
+void tools_token_msg(int token, crypt_object_op op);
+void tools_token_error_msg(int error, const char *type, int token, bool pin_provided);
+void tools_package_version(const char *name, bool use_pwlibs);
+
+extern volatile int quit;
+void set_int_block(int block);
+void set_int_handler(int block);
+void check_signal(int *r);
+int tools_signals_blocked(void);
+
+int tools_get_key(const char *prompt,
+ char **key, size_t *key_size,
+ uint64_t keyfile_offset, size_t keyfile_size_max,
+ const char *key_file,
+ int timeout, int verify, int pwquality,
+ struct crypt_device *cd);
+void tools_passphrase_msg(int r);
+int tools_is_stdin(const char *key_file);
+int tools_string_to_size(const char *s, uint64_t *size);
+
+struct tools_progress_params {
+ uint32_t frequency;
+ struct timeval start_time;
+ struct timeval end_time;
+ uint64_t start_offset;
+ bool batch_mode;
+ bool json_output;
+ const char *interrupt_message;
+ const char *device;
+};
+
+int tools_progress(uint64_t size, uint64_t offset, void *usrptr);
+const char *tools_get_device_name(const char *device, char **r_backing_file);
+
+int tools_read_vk(const char *file, char **key, int keysize);
+int tools_write_mk(const char *file, const char *key, int keysize);
+
+int tools_read_json_file(const char *file, char **json, size_t *json_size, bool batch_mode);
+int tools_write_json_file(const char *file, const char *json);
+
+typedef enum {
+ PRB_FILTER_NONE = 0,
+ PRB_FILTER_LUKS,
+ PRB_ONLY_LUKS
+} tools_probe_filter_info;
+
+int tools_detect_signatures(const char *device, tools_probe_filter_info filter, size_t *count, bool batch_mode);
+int tools_wipe_all_signatures(const char *path, bool exclusive, bool only_luks);
+int tools_superblock_block_size(const char *device, char *sb_name,
+ size_t sb_name_len, unsigned *r_block_size);
+bool tools_blkid_supported(void);
+
+int tools_lookup_crypt_device(struct crypt_device *cd, const char *type,
+ const char *data_device_path, char **r_name);
+
+
+/* each utility is required to implement it */
+void tools_cleanup(void);
+
+/* Log */
+#define log_dbg(x...) crypt_logf(NULL, CRYPT_LOG_DEBUG, x)
+#define log_std(x...) crypt_logf(NULL, CRYPT_LOG_NORMAL, x)
+#define log_verbose(x...) crypt_logf(NULL, CRYPT_LOG_VERBOSE, x)
+#define log_err(x...) crypt_logf(NULL, CRYPT_LOG_ERROR, x)
+
+typedef enum {
+ CRYPT_ARG_BOOL = 0,
+ CRYPT_ARG_STRING,
+ CRYPT_ARG_INT32,
+ CRYPT_ARG_UINT32,
+ CRYPT_ARG_INT64,
+ CRYPT_ARG_UINT64,
+ CRYPT_ARG_ALIAS
+} crypt_arg_type_info;
+
+struct tools_arg {
+ const char *name;
+ bool set;
+ crypt_arg_type_info type;
+ union {
+ char *str_value;
+ uint64_t u64_value;
+ uint32_t u32_value;
+ int32_t i32_value;
+ int64_t i64_value;
+ union {
+ unsigned id;
+ struct tools_arg *ptr;
+ } o;
+ } u;
+ const char *actions_array[MAX_ACTIONS];
+};
+
+void tools_parse_arg_value(poptContext popt_context, crypt_arg_type_info type, struct tools_arg *arg, const char *popt_arg, int popt_val, bool(*needs_size_conv_fn)(unsigned arg_id));
+
+void tools_args_free(struct tools_arg *args, size_t args_count);
+
+void tools_check_args(const char *action, const struct tools_arg *args, size_t args_size, poptContext popt_context);
+
+struct tools_log_params {
+ bool verbose;
+ bool debug;
+};
+
+#endif /* CRYPTSETUP_H */
diff --git a/src/cryptsetup_arg_list.h b/src/cryptsetup_arg_list.h
new file mode 100644
index 0000000..a7e5bb0
--- /dev/null
+++ b/src/cryptsetup_arg_list.h
@@ -0,0 +1,232 @@
+/*
+ * Cryptsetup command line arguments list
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* long name, short name, popt type, help description, units, internal argument type, default value, allowed actions (empty=global) */
+
+ARG(OPT_ACTIVE_NAME, '\0', POPT_ARG_STRING, N_("Override device autodetection of dm device to be reencrypted"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_ALIGN_PAYLOAD, '\0', POPT_ARG_STRING, N_("Align payload at <n> sector boundaries - for luksFormat"), N_("SECTORS"), CRYPT_ARG_UINT32, {}, OPT_ALIGN_PAYLOAD_ACTIONS)
+
+ARG(OPT_ALLOW_DISCARDS, '\0', POPT_ARG_NONE, N_("Allow discards (aka TRIM) requests for device"), NULL, CRYPT_ARG_BOOL, {}, OPT_ALLOW_DISCARDS_ACTIONS)
+
+ARG(OPT_BATCH_MODE, 'q', POPT_ARG_NONE, N_("Do not ask for confirmation"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_CANCEL_DEFERRED, '\0', POPT_ARG_NONE, N_("Cancel a previously set deferred device removal"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS)
+
+ARG(OPT_CIPHER, 'c', POPT_ARG_STRING, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_DEBUG, '\0', POPT_ARG_NONE, N_("Show debug messages"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DEBUG_JSON, '\0', POPT_ARG_NONE, N_("Show debug messages including JSON metadata"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DEFERRED, '\0', POPT_ARG_NONE, N_("Device removal is deferred until the last user closes it"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS)
+
+ARG(OPT_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_DEVICE_SIZE_ACTIONS)
+
+ARG(OPT_DECRYPT, '\0', POPT_ARG_NONE, N_("Decrypt LUKS2 device (remove encryption)."), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DISABLE_EXTERNAL_TOKENS, '\0', POPT_ARG_NONE, N_("Disable loading of external LUKS2 token plugins"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DISABLE_KEYRING, '\0', POPT_ARG_NONE, N_("Disable loading volume keys via kernel keyring"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DISABLE_LOCKS, '\0', POPT_ARG_NONE, N_("Disable locking of on-disk metadata"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DISABLE_VERACRYPT, '\0', POPT_ARG_NONE, N_("Do not scan for VeraCrypt compatible device"), NULL, CRYPT_ARG_BOOL, {}, OPT_DISABLE_VERACRYPT_ACTIONS)
+
+ARG(OPT_DUMP_JSON, '\0', POPT_ARG_NONE, N_("Dump info in JSON format (LUKS2 only)"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DUMP_VOLUME_KEY, '\0', POPT_ARG_NONE, N_("Dump volume key instead of keyslots info"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_ENCRYPT, '\0', POPT_ARG_NONE, N_("Encrypt LUKS2 device (in-place encryption)."), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_FORCE_PASSWORD, '\0', POPT_ARG_NONE, N_("Disable password quality check (if enabled)"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_FORCE_OFFLINE_REENCRYPT, '\0', POPT_ARG_NONE, N_("Force offline LUKS2 reencryption and bypass active device detection."), NULL, CRYPT_ARG_BOOL, {}, OPT_FORCE_OFFLINE_REENCRYPT_ACTIONS)
+
+ARG(OPT_HASH, 'h', POPT_ARG_STRING, N_("The hash used to create the encryption key from the passphrase"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_HEADER, '\0', POPT_ARG_STRING, N_("Device or file with separated LUKS header"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_HEADER_BACKUP_FILE, '\0', POPT_ARG_STRING, N_("File with LUKS header and keyslots backup"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_HOTZONE_SIZE, '\0', POPT_ARG_STRING, N_("Maximal reencryption hotzone size."), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_HOTZONE_SIZE_ACTIONS)
+
+ARG(OPT_INIT_ONLY, '\0', POPT_ARG_NONE, N_("Initialize LUKS2 reencryption in metadata only."), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTEGRITY, 'I', POPT_ARG_STRING, N_("Data integrity algorithm (LUKS2 only)"), NULL, CRYPT_ARG_STRING, {}, OPT_INTEGRITY_ACTIONS)
+
+ARG(OPT_INTEGRITY_LEGACY_PADDING,'\0', POPT_ARG_NONE, N_("Use inefficient legacy padding (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTEGRITY_NO_JOURNAL, '\0', POPT_ARG_NONE, N_("Disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTEGRITY_NO_WIPE, '\0', POPT_ARG_NONE, N_("Do not wipe device after format"), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_NO_WIPE_ACTIONS)
+
+ARG(OPT_ITER_TIME, 'i', POPT_ARG_STRING, N_("PBKDF iteration time for LUKS (in ms)"), N_("msecs"), CRYPT_ARG_UINT32, {}, OPT_ITER_TIME_ACTIONS)
+
+ARG(OPT_IV_LARGE_SECTORS, '\0', POPT_ARG_NONE, N_("Use IV counted in sector size (not in 512 bytes)"), NULL , CRYPT_ARG_BOOL, {}, OPT_IV_LARGE_SECTORS_ACTIONS)
+
+ARG(OPT_JSON_FILE, '\0', POPT_ARG_STRING, N_("Read or write the json from or to a file"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_KEEP_KEY, '\0', POPT_ARG_NONE, N_("Do not change volume key."), NULL, CRYPT_ARG_BOOL, {}, OPT_KEEP_KEY_ACTIONS)
+
+ARG(OPT_KEY_DESCRIPTION, '\0', POPT_ARG_STRING, N_("Key description"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_KEY_FILE, 'd', POPT_ARG_STRING, N_("Read the key from a file"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_KEY_SIZE, 's', POPT_ARG_STRING, N_("The size of the encryption key"), N_("BITS"), CRYPT_ARG_UINT32, {}, OPT_KEY_SIZE_ACTIONS)
+
+ARG(OPT_KEY_SLOT, 'S', POPT_ARG_STRING, N_("Slot number for new key (default is first free)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_SLOT }, OPT_KEY_SLOT_ACTIONS)
+
+ARG(OPT_KEYFILE_OFFSET, '\0', POPT_ARG_STRING, N_("Number of bytes to skip in keyfile"), N_("bytes"), CRYPT_ARG_UINT64, {}, {})
+
+ARG(OPT_KEYFILE_SIZE, 'l', POPT_ARG_STRING, N_("Limits the read from keyfile"), N_("bytes"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_KEYSLOT_CIPHER, '\0', POPT_ARG_STRING, N_("LUKS2 keyslot: The cipher used for keyslot encryption"), NULL, CRYPT_ARG_STRING, {}, OPT_KEYSLOT_CIPHER_ACTIONS)
+
+ARG(OPT_KEYSLOT_KEY_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 keyslot: The size of the encryption key"), N_("BITS"), CRYPT_ARG_UINT32, {}, OPT_KEYSLOT_KEY_SIZE_ACTIONS)
+
+ARG(OPT_LABEL, '\0', POPT_ARG_STRING, N_("Set label for the LUKS2 device"), NULL, CRYPT_ARG_STRING, {}, OPT_LABEL_ACTIONS)
+
+ARG(OPT_LUKS2_KEYSLOTS_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header keyslots area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS)
+
+ARG(OPT_LUKS2_METADATA_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header metadata area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_METADATA_SIZE_ACTIONS)
+
+ARG(OPT_VOLUME_KEY_FILE, '\0', POPT_ARG_STRING, N_("Use the volume key from file."), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_NEW_KEYFILE, '\0', POPT_ARG_STRING, N_("Read the key for a new slot from a file"), NULL, CRYPT_ARG_STRING, {}, OPT_NEW_KEYFILE_ACTIONS)
+
+ARG(OPT_NEW_KEY_SLOT, '\0', POPT_ARG_STRING, N_("Slot number for new key (default is first free)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_SLOT }, OPT_NEW_KEY_SLOT_ACTIONS)
+
+ARG(OPT_NEW_KEYFILE_OFFSET , '\0', POPT_ARG_STRING, N_("Number of bytes to skip in newly added keyfile"), N_("bytes"), CRYPT_ARG_UINT64, {}, {})
+
+ARG(OPT_NEW_KEYFILE_SIZE, '\0', POPT_ARG_STRING, N_("Limits the read from newly added keyfile"), N_("bytes"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_NEW_TOKEN_ID, '\0', POPT_ARG_STRING, N_("Token number (default: any)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_TOKEN }, OPT_NEW_TOKEN_ID_ACTIONS)
+
+ARG(OPT_OFFSET, 'o', POPT_ARG_STRING, N_("The start offset in the backend device"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_OFFSET_ACTIONS)
+
+ARG(OPT_PBKDF, '\0', POPT_ARG_STRING, N_("PBKDF algorithm (for LUKS2): argon2i, argon2id, pbkdf2"), NULL, CRYPT_ARG_STRING, {}, OPT_PBKDF_ACTIONS)
+
+ARG(OPT_PBKDF_FORCE_ITERATIONS, '\0', POPT_ARG_STRING, N_("PBKDF iterations cost (forced, disables benchmark)"), "LONG", CRYPT_ARG_UINT32, {}, OPT_PBKDF_FORCE_ITERATIONS_ACTIONS)
+
+ARG(OPT_PBKDF_MEMORY, '\0', POPT_ARG_STRING, N_("PBKDF memory cost limit"), N_("kilobytes"), CRYPT_ARG_UINT32, { .u32_value = DEFAULT_LUKS2_MEMORY_KB }, {})
+
+ARG(OPT_PBKDF_PARALLEL, '\0', POPT_ARG_STRING, N_("PBKDF parallel cost"), N_("threads"), CRYPT_ARG_UINT32, { .u32_value = DEFAULT_LUKS2_PARALLEL_THREADS }, {})
+
+ARG(OPT_PERF_NO_READ_WORKQUEUE, '\0', POPT_ARG_NONE, N_("Bypass dm-crypt workqueue and process read requests synchronously"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_PERF_NO_WRITE_WORKQUEUE, '\0', POPT_ARG_NONE, N_("Bypass dm-crypt workqueue and process write requests synchronously"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_PERF_SAME_CPU_CRYPT, '\0', POPT_ARG_NONE, N_("Use dm-crypt same_cpu_crypt performance compatibility option"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_PERF_SUBMIT_FROM_CRYPT_CPUS, '\0', POPT_ARG_NONE, N_("Use dm-crypt submit_from_crypt_cpus performance compatibility option"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_PERSISTENT, '\0', POPT_ARG_NONE, N_("Set activation flags persistent for device"), NULL, CRYPT_ARG_BOOL, {}, OPT_PERSISTENT_ACTIONS)
+
+ARG(OPT_PRIORITY, '\0', POPT_ARG_STRING, N_("Keyslot priority: ignore, normal, prefer"), NULL, CRYPT_ARG_STRING, {}, OPT_PRIORITY_ACTIONS)
+
+ARG(OPT_PROGRESS_JSON, '\0', POPT_ARG_NONE, N_("Print progress data in json format (suitable for machine processing)"), NULL, CRYPT_ARG_BOOL, {}, OPT_PROGRESS_JSON_ACTIONS)
+
+ARG(OPT_PROGRESS_FREQUENCY, '\0', POPT_ARG_STRING, N_("Progress line update (in seconds)"), N_("secs"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_READONLY, 'r', POPT_ARG_NONE, N_("Create a readonly mapping"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_REDUCE_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Reduce data device size (move data offset). DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, {})
+
+ARG(OPT_REFRESH, '\0', POPT_ARG_NONE, N_("Refresh (reactivate) device with new parameters"), NULL, CRYPT_ARG_BOOL, {}, OPT_REFRESH_ACTIONS)
+
+ARG(OPT_RESILIENCE, '\0', POPT_ARG_STRING, N_("Reencryption hotzone resilience type (checksum,journal,none)"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_RESILIENCE_HASH, '\0', POPT_ARG_STRING, N_("Reencryption hotzone checksums hash"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_RESUME_ONLY, '\0', POPT_ARG_NONE, N_("Resume initialized LUKS2 reencryption only."), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_SECTOR_SIZE, '\0', POPT_ARG_STRING, N_("Encryption sector size (default: 512 bytes)"), "INT", CRYPT_ARG_UINT32, {}, OPT_SECTOR_SIZE_ACTIONS)
+
+ARG(OPT_SERIALIZE_MEMORY_HARD_PBKDF, '\0', POPT_ARG_NONE, N_("Use global lock to serialize memory hard PBKDF (OOM workaround)"), NULL, CRYPT_ARG_BOOL, {}, OPT_SERIALIZE_MEMORY_HARD_PBKDF_ACTIONS)
+
+ARG(OPT_SHARED, '\0', POPT_ARG_NONE, N_("Share device with another non-overlapping crypt segment"), NULL, CRYPT_ARG_BOOL, {}, OPT_SHARED_ACTIONS )
+
+ARG(OPT_SIZE, 'b', POPT_ARG_STRING, N_("The size of the device"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_SIZE_ACTIONS)
+
+ARG(OPT_SKIP, 'p', POPT_ARG_STRING, N_("How many sectors of the encrypted data to skip at the beginning"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_SKIP_ACTIONS)
+
+ARG(OPT_SUBSYSTEM, '\0', POPT_ARG_STRING, N_("Set subsystem label for the LUKS2 device"), NULL, CRYPT_ARG_STRING, {}, OPT_SUBSYSTEM_ACTIONS)
+
+ARG(OPT_TCRYPT_BACKUP, '\0', POPT_ARG_NONE, N_("Use backup (secondary) TCRYPT header"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_BACKUP_ACTIONS)
+
+ARG(OPT_TCRYPT_HIDDEN, '\0', POPT_ARG_NONE, N_("Use hidden header (hidden TCRYPT device)"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_HIDDEN_ACTIONS)
+
+ARG(OPT_TCRYPT_SYSTEM, '\0', POPT_ARG_NONE, N_("Device is system TCRYPT drive (with bootloader)"), NULL, CRYPT_ARG_BOOL, {}, OPT_TCRYPT_SYSTEM_ACTIONS)
+
+ARG(OPT_TEST_ARGS, '\0', POPT_ARG_NONE, N_("Do not run action, just validate all command line parameters"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_TEST_PASSPHRASE, '\0', POPT_ARG_NONE, N_("Do not activate device, just check passphrase"), NULL, CRYPT_ARG_BOOL, {}, OPT_TEST_PASSPHRASE_ACTIONS)
+
+ARG(OPT_TIMEOUT, 't', POPT_ARG_STRING, N_("Timeout for interactive passphrase prompt (in seconds)"), N_("secs"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_TOKEN_ID, '\0', POPT_ARG_STRING, N_("Token number (default: any)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_TOKEN }, {})
+
+ARG(OPT_TOKEN_ONLY, '\0', POPT_ARG_NONE, N_("Do not ask for passphrase if activation by token fails"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_TOKEN_REPLACE, '\0', POPT_ARG_NONE, N_("Replace the current token"), NULL, CRYPT_ARG_BOOL, {}, OPT_TOKEN_REPLACE_ACTIONS)
+
+ARG(OPT_TOKEN_TYPE, '\0', POPT_ARG_STRING, N_("Restrict allowed token types used to retrieve LUKS2 key"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_TRIES, 'T', POPT_ARG_STRING, N_("How often the input of the passphrase can be retried"), "INT", CRYPT_ARG_UINT32, { .u32_value = 3 }, {})
+
+ARG(OPT_TYPE, 'M', POPT_ARG_STRING, N_("Type of device metadata: luks, luks1, luks2, plain, loopaes, tcrypt, bitlk"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_UNBOUND, '\0', POPT_ARG_NONE, N_("Create or dump unbound LUKS2 keyslot (unassigned to data segment) or LUKS2 token (unassigned to keyslot)"), NULL, CRYPT_ARG_BOOL, {}, OPT_UNBOUND_ACTIONS)
+
+ARG(OPT_USE_RANDOM, '\0', POPT_ARG_NONE, N_("Use /dev/random for generating volume key"), NULL, CRYPT_ARG_BOOL, {}, OPT_USE_RANDOM_ACTIONS)
+
+ARG(OPT_USE_URANDOM, '\0', POPT_ARG_NONE, N_("Use /dev/urandom for generating volume key"), NULL, CRYPT_ARG_BOOL, {}, OPT_USE_URANDOM_ACTIONS)
+
+ARG(OPT_UUID, '\0', POPT_ARG_STRING, N_("UUID for device to use"), NULL, CRYPT_ARG_STRING, {}, OPT_UUID_ACTIONS)
+
+ARG(OPT_VERACRYPT, '\0', POPT_ARG_NONE, N_("Scan also for VeraCrypt compatible device"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_VERACRYPT_PIM, '\0', POPT_ARG_STRING, N_("Personal Iteration Multiplier for VeraCrypt compatible device"), "INT", CRYPT_ARG_UINT32, {}, OPT_VERACRYPT_PIM_ACTIONS)
+
+ARG(OPT_VERACRYPT_QUERY_PIM, '\0', POPT_ARG_NONE, N_("Query Personal Iteration Multiplier for VeraCrypt compatible device"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_VERBOSE, 'v', POPT_ARG_NONE, N_("Shows more detailed error messages"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_VERIFY_PASSPHRASE, 'y', POPT_ARG_NONE, N_("Verifies the passphrase by asking for it twice"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+/* added for reencryption */
+
+ARG(OPT_BLOCK_SIZE, 'B', POPT_ARG_STRING, N_("Reencryption block size"), N_("MiB"), CRYPT_ARG_UINT32, { .u32_value = 4 }, {})
+
+ARG(OPT_NEW, 'N', POPT_ARG_NONE, N_("Create new header on not encrypted device"), NULL, CRYPT_ARG_ALIAS, { .o.id = OPT_ENCRYPT_ID }, {})
+
+ARG(OPT_USE_DIRECTIO, '\0', POPT_ARG_NONE, N_("Use direct-io when accessing devices"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_USE_FSYNC, '\0', POPT_ARG_NONE, N_("Use fsync after each block"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_WRITE_LOG, '\0', POPT_ARG_NONE, N_("Update log file after every block"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+/* aliases */
+
+ARG(OPT_DUMP_MASTER_KEY, '\0', POPT_ARG_NONE, N_("Alias for --dump-volume-key"), NULL, CRYPT_ARG_ALIAS, { .o.id = OPT_DUMP_VOLUME_KEY_ID}, {})
+
+ARG(OPT_MASTER_KEY_FILE, '\0', POPT_ARG_STRING, N_("Alias for --dump-volume-key-file"), NULL, CRYPT_ARG_ALIAS, { .o.id = OPT_VOLUME_KEY_FILE_ID}, {})
diff --git a/src/cryptsetup_args.h b/src/cryptsetup_args.h
new file mode 100644
index 0000000..63604a3
--- /dev/null
+++ b/src/cryptsetup_args.h
@@ -0,0 +1,113 @@
+/*
+ * Command line arguments helpers
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef CRYPTSETUP_ARGS_H
+#define CRYPTSETUP_ARGS_H
+
+#include "utils_arg_names.h"
+#include "utils_arg_macros.h"
+
+#define BITLKDUMP_ACTION "bitlkDump"
+#define BENCHMARK_ACTION "benchmark"
+#define CLOSE_ACTION "close"
+#define CONFIG_ACTION "config"
+#define CONVERT_ACTION "convert"
+#define ERASE_ACTION "erase"
+#define FVAULT2DUMP_ACTION "fvault2Dump"
+#define ISLUKS_ACTION "isLuks"
+#define ADDKEY_ACTION "luksAddKey"
+#define CHANGEKEY_ACTION "luksChangeKey"
+#define CONVERTKEY_ACTION "luksConvertKey"
+#define LUKSDUMP_ACTION "luksDump"
+#define FORMAT_ACTION "luksFormat"
+#define HEADERBACKUP_ACTION "luksHeaderBackup"
+#define HEADERRESTORE_ACTION "luksHeaderRestore"
+#define KILLKEY_ACTION "luksKillSlot"
+#define REMOVEKEY_ACTION "luksRemoveKey"
+#define RESUME_ACTION "luksResume"
+#define SUSPEND_ACTION "luksSuspend"
+#define UUID_ACTION "luksUUID"
+#define OPEN_ACTION "open"
+#define REENCRYPT_ACTION "reencrypt"
+#define REPAIR_ACTION "repair"
+#define RESIZE_ACTION "resize"
+#define STATUS_ACTION "status"
+#define TCRYPTDUMP_ACTION "tcryptDump"
+#define TOKEN_ACTION "token"
+
+/* avoid unshielded commas in ARG() macros later */
+#define OPT_ALIGN_PAYLOAD_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_ALLOW_DISCARDS_ACTIONS { OPEN_ACTION }
+#define OPT_DEFERRED_ACTIONS { CLOSE_ACTION }
+#define OPT_DEVICE_SIZE_ACTIONS { OPEN_ACTION, RESIZE_ACTION, REENCRYPT_ACTION }
+#define OPT_DISABLE_VERACRYPT_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
+#define OPT_HOTZONE_SIZE_ACTIONS { REENCRYPT_ACTION }
+#define OPT_FORCE_OFFLINE_REENCRYPT_ACTIONS { REENCRYPT_ACTION }
+#define OPT_INTEGRITY_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_INTEGRITY_NO_WIPE_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_ITER_TIME_ACTIONS { BENCHMARK_ACTION, FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION }
+#define OPT_IV_LARGE_SECTORS_ACTIONS { OPEN_ACTION }
+#define OPT_KEEP_KEY_ACTIONS { REENCRYPT_ACTION }
+#define OPT_KEY_SIZE_ACTIONS { OPEN_ACTION, BENCHMARK_ACTION, FORMAT_ACTION, REENCRYPT_ACTION, ADDKEY_ACTION }
+#define OPT_KEY_SLOT_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, CONFIG_ACTION, FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, LUKSDUMP_ACTION, TOKEN_ACTION, RESUME_ACTION }
+#define OPT_KEYSLOT_CIPHER_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION }
+#define OPT_KEYSLOT_KEY_SIZE_ACTIONS OPT_KEYSLOT_CIPHER_ACTIONS
+#define OPT_NEW_KEYFILE_ACTIONS { ADDKEY_ACTION }
+#define OPT_NEW_KEY_SLOT_ACTIONS { ADDKEY_ACTION }
+#define OPT_NEW_TOKEN_ID_ACTIONS { ADDKEY_ACTION }
+#define OPT_LABEL_ACTIONS { CONFIG_ACTION, FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION }
+#define OPT_LUKS2_METADATA_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION }
+#define OPT_OFFSET_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, FORMAT_ACTION }
+#define OPT_PBKDF_ACTIONS { BENCHMARK_ACTION, FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION }
+#define OPT_PBKDF_FORCE_ITERATIONS_ACTIONS { FORMAT_ACTION, ADDKEY_ACTION, CHANGEKEY_ACTION, CONVERTKEY_ACTION, REENCRYPT_ACTION }
+#define OPT_PERSISTENT_ACTIONS { OPEN_ACTION }
+#define OPT_PRIORITY_ACTIONS { CONFIG_ACTION }
+#define OPT_PROGRESS_JSON_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_REFRESH_ACTIONS { OPEN_ACTION }
+#define OPT_SECTOR_SIZE_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, FORMAT_ACTION }
+#define OPT_SERIALIZE_MEMORY_HARD_PBKDF_ACTIONS { OPEN_ACTION }
+#define OPT_SHARED_ACTIONS { OPEN_ACTION }
+#define OPT_SIZE_ACTIONS { OPEN_ACTION, RESIZE_ACTION }
+#define OPT_SKIP_ACTIONS { OPEN_ACTION }
+#define OPT_SUBSYSTEM_ACTIONS { CONFIG_ACTION, FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_TCRYPT_BACKUP_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
+#define OPT_TCRYPT_HIDDEN_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
+#define OPT_TCRYPT_SYSTEM_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
+#define OPT_TEST_PASSPHRASE_ACTIONS { OPEN_ACTION }
+#define OPT_TOKEN_REPLACE_ACTIONS { TOKEN_ACTION }
+#define OPT_UNBOUND_ACTIONS { ADDKEY_ACTION, LUKSDUMP_ACTION, OPEN_ACTION, TOKEN_ACTION }
+#define OPT_USE_RANDOM_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_USE_URANDOM_ACTIONS { FORMAT_ACTION, REENCRYPT_ACTION }
+#define OPT_UUID_ACTIONS { FORMAT_ACTION, UUID_ACTION, REENCRYPT_ACTION }
+#define OPT_VERACRYPT_PIM_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
+#define OPT_VERACRYPT_QUERY_PIM_ACTIONS { OPEN_ACTION, TCRYPTDUMP_ACTION }
+
+enum {
+OPT_UNUSED_ID = 0, /* leave unused due to popt library */
+#define ARG(A, B, C, D, E, F, G, H) A ## _ID,
+#include "cryptsetup_arg_list.h"
+#undef ARG
+};
+
+extern struct tools_arg tool_core_args[];
+
+#endif
diff --git a/src/integritysetup.c b/src/integritysetup.c
new file mode 100644
index 0000000..eee6171
--- /dev/null
+++ b/src/integritysetup.c
@@ -0,0 +1,767 @@
+/*
+ * integritysetup - setup integrity protected volumes for dm-integrity
+ *
+ * Copyright (C) 2017-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2017-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <uuid/uuid.h>
+
+#define DEFAULT_ALG_NAME "crc32c"
+
+#include "cryptsetup.h"
+#include "integritysetup_args.h"
+
+#define PACKAGE_INTEGRITY "integritysetup"
+
+static const char **action_argv;
+static int action_argc;
+static struct tools_log_params log_parms;
+
+void tools_cleanup(void)
+{
+ tools_args_free(tool_core_args, ARRAY_SIZE(tool_core_args));
+}
+
+static int _read_keys(char **integrity_key, struct crypt_params_integrity *params)
+{
+ char *int_key = NULL, *journal_integrity_key = NULL, *journal_crypt_key = NULL;
+ int r;
+
+ if (integrity_key && ARG_SET(OPT_INTEGRITY_KEY_FILE_ID)) {
+ r = tools_read_vk(ARG_STR(OPT_INTEGRITY_KEY_FILE_ID), &int_key, ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID));
+ if (r < 0)
+ return r;
+ params->integrity_key_size = ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID);
+ }
+
+ if (ARG_SET(OPT_JOURNAL_INTEGRITY_KEY_FILE_ID)) {
+ r = tools_read_vk(ARG_STR(OPT_JOURNAL_INTEGRITY_KEY_FILE_ID), &journal_integrity_key, ARG_UINT32(OPT_JOURNAL_INTEGRITY_KEY_SIZE_ID));
+ if (r < 0) {
+ crypt_safe_free(int_key);
+ return r;
+ }
+ params->journal_integrity_key = journal_integrity_key;
+ params->journal_integrity_key_size = ARG_UINT32(OPT_JOURNAL_INTEGRITY_KEY_SIZE_ID);
+ }
+
+ if (ARG_SET(OPT_JOURNAL_CRYPT_KEY_FILE_ID)) {
+ r = tools_read_vk(ARG_STR(OPT_JOURNAL_CRYPT_KEY_FILE_ID), &journal_crypt_key, ARG_UINT32(OPT_JOURNAL_CRYPT_KEY_SIZE_ID));
+ if (r < 0) {
+ crypt_safe_free(int_key);
+ crypt_safe_free(journal_integrity_key);
+ return r;
+ }
+ params->journal_crypt_key = journal_crypt_key;
+ params->journal_crypt_key_size = ARG_UINT32(OPT_JOURNAL_CRYPT_KEY_SIZE_ID);
+ }
+
+ if (integrity_key)
+ *integrity_key = int_key;
+
+ return 0;
+}
+
+static int _wipe_data_device(struct crypt_device *cd, const char *integrity_key)
+{
+ char tmp_name[64], tmp_path[128], tmp_uuid[40];
+ uuid_t tmp_uuid_bin;
+ int r = -EINVAL;
+ char *backing_file = NULL;
+ struct tools_progress_params prog_parms = {
+ .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID),
+ .batch_mode = ARG_SET(OPT_BATCH_MODE_ID),
+ .json_output = ARG_SET(OPT_PROGRESS_JSON_ID),
+ .interrupt_message = _("\nWipe interrupted."),
+ .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file)
+ };
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ log_std(_("Wiping device to initialize integrity checksum.\n"
+ "You can interrupt this by pressing CTRL+c "
+ "(rest of not wiped device will contain invalid checksum).\n"));
+
+ /* Activate the device a temporary one */
+ uuid_generate(tmp_uuid_bin);
+ uuid_unparse(tmp_uuid_bin, tmp_uuid);
+ if (snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid) < 0)
+ goto out;
+ if (snprintf(tmp_path, sizeof(tmp_path), "%s/%s", crypt_get_dir(), tmp_name) < 0)
+ goto out;
+
+ r = crypt_activate_by_volume_key(cd, tmp_name, integrity_key,
+ ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID), CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL);
+ if (r < 0)
+ goto out;
+
+ /* Wipe the device */
+ set_int_handler(0);
+ r = crypt_wipe(cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, DEFAULT_WIPE_BLOCK,
+ 0, &tools_progress, &prog_parms);
+ if (crypt_deactivate(cd, tmp_name))
+ log_err(_("Cannot deactivate temporary device %s."), tmp_path);
+ set_int_block(0);
+
+out:
+ free(backing_file);
+ return r;
+}
+
+static int action_format(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_integrity params = {
+ .journal_size = ARG_UINT64(OPT_JOURNAL_SIZE_ID),
+ .interleave_sectors = ARG_UINT32(OPT_INTERLEAVE_SECTORS_ID),
+ /* in bitmap mode we have to overload these values... */
+ .journal_watermark = ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID) ? ARG_UINT32(OPT_BITMAP_SECTORS_PER_BIT_ID) : ARG_UINT32(OPT_JOURNAL_WATERMARK_ID),
+ .journal_commit_time = ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID) ? ARG_UINT32(OPT_BITMAP_FLUSH_TIME_ID) : ARG_UINT32(OPT_JOURNAL_COMMIT_TIME_ID),
+ .buffer_sectors = ARG_UINT32(OPT_BUFFER_SECTORS_ID),
+ .tag_size = ARG_UINT32(OPT_TAG_SIZE_ID),
+ .sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID),
+ }, params2;
+ char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
+ char *integrity_key = NULL, *msg = NULL;
+ int r;
+ size_t signatures;
+
+ r = crypt_parse_hash_integrity_mode(ARG_STR(OPT_INTEGRITY_ID), integrity);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ return r;
+ }
+ params.integrity = integrity;
+
+ if (ARG_SET(OPT_JOURNAL_INTEGRITY_ID)) {
+ r = crypt_parse_hash_integrity_mode(ARG_STR(OPT_JOURNAL_INTEGRITY_ID), journal_integrity);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ return r;
+ }
+ params.journal_integrity = journal_integrity;
+ }
+
+ if (ARG_SET(OPT_JOURNAL_CRYPT_ID)) {
+ r = crypt_parse_hash_integrity_mode(ARG_STR(OPT_JOURNAL_CRYPT_ID), journal_crypt);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ return r;
+ }
+ params.journal_crypt = journal_crypt;
+ }
+
+ r = _read_keys(&integrity_key, &params);
+ if (r)
+ goto out;
+
+ r = crypt_init_data_device(&cd, action_argv[0], ARG_STR(OPT_DATA_DEVICE_ID));
+ if (r < 0)
+ goto out;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID)) {
+ if (ARG_SET(OPT_DATA_DEVICE_ID) && !ARG_SET(OPT_NO_WIPE_ID))
+ r = asprintf(&msg, _("This will overwrite data on %s and %s irrevocably.\n"
+ "To preserve data device use --no-wipe option (and then activate with --integrity-recalculate)."),
+ action_argv[0], ARG_STR(OPT_DATA_DEVICE_ID));
+ else
+ r = asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]);
+ if (r == -1) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
+ free(msg);
+ if (r < 0)
+ goto out;
+ }
+
+ r = tools_detect_signatures(action_argv[0], PRB_FILTER_NONE, &signatures, ARG_SET(OPT_BATCH_MODE_ID));
+ if (r < 0)
+ goto out;
+
+ /* Signature candidates found */
+ if (signatures && ((r = tools_wipe_all_signatures(action_argv[0], true, false)) < 0))
+ goto out;
+
+ if (ARG_SET(OPT_INTEGRITY_LEGACY_PADDING_ID))
+ crypt_set_compatibility(cd, CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING);
+
+ if (ARG_SET(OPT_INTEGRITY_LEGACY_HMAC_ID))
+ crypt_set_compatibility(cd, CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC);
+
+ r = crypt_format(cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, &params);
+ if (r < 0) /* FIXME: call wipe signatures again */
+ goto out;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !crypt_get_integrity_info(cd, &params2))
+ log_std(_("Formatted with tag size %u, internal integrity %s.\n"),
+ params2.tag_size, params2.integrity);
+
+ if (!ARG_SET(OPT_NO_WIPE_ID))
+ r = _wipe_data_device(cd, integrity_key);
+out:
+ crypt_safe_free(integrity_key);
+ crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key);
+ crypt_safe_free(CONST_CAST(void*)params.journal_crypt_key);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_resize(void)
+{
+ int r;
+ struct crypt_device *cd = NULL;
+ struct crypt_active_device cad;
+ uint64_t new_dev_size = 0;
+ uint64_t old_dev_size;
+ char path[PATH_MAX];
+ char *backing_file = NULL;
+ struct tools_progress_params prog_parms = {
+ .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID),
+ .batch_mode = ARG_SET(OPT_BATCH_MODE_ID),
+ .json_output = ARG_SET(OPT_PROGRESS_JSON_ID),
+ .interrupt_message = _("\nWipe interrupted."),
+ .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file)
+ };
+
+ if (ARG_SET(OPT_DEVICE_SIZE_ID))
+ new_dev_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE;
+ else if (ARG_SET(OPT_SIZE_ID))
+ new_dev_size = ARG_UINT64(OPT_SIZE_ID);
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
+ if (r)
+ goto out;
+
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r)
+ goto out;
+ old_dev_size = cad.size;
+
+ r = snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), action_argv[0]);
+ if (r < 0)
+ goto out;
+ r = crypt_resize(cd, action_argv[0], new_dev_size);
+ if (r)
+ goto out;
+
+ if (!new_dev_size) {
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r)
+ goto out;
+ new_dev_size = cad.size;
+ }
+
+ if (new_dev_size > old_dev_size) {
+ if (ARG_SET(OPT_WIPE_ID)) {
+ if (ARG_SET(OPT_BATCH_MODE_ID))
+ log_dbg("Wiping the end of the resized device");
+ else
+ log_std(_("Wiping device to initialize integrity checksum.\n"
+ "You can interrupt this by pressing CTRL+c "
+ "(rest of not wiped device will contain invalid checksum).\n"));
+
+ set_int_handler(0);
+ r = crypt_wipe(cd, path, CRYPT_WIPE_ZERO, old_dev_size * SECTOR_SIZE,
+ (new_dev_size - old_dev_size) * SECTOR_SIZE, DEFAULT_WIPE_BLOCK,
+ 0, &tools_progress, &prog_parms);
+ set_int_block(0);
+ } else {
+ log_dbg("Setting recalculate flag");
+ r = crypt_activate_by_volume_key(cd, action_argv[0], NULL, 0, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_RECALCULATE);
+
+ if (r == -ENOTSUP)
+ log_err(_("Setting recalculate flag is not supported, you may consider using --wipe instead."));
+ }
+ }
+out:
+ if (backing_file)
+ free(backing_file);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_open(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_integrity params = {
+ /* in bitmap mode we have to overload these values... */
+ .journal_watermark = ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID) ? ARG_UINT32(OPT_BITMAP_SECTORS_PER_BIT_ID) : ARG_UINT32(OPT_JOURNAL_WATERMARK_ID),
+ .journal_commit_time = ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID) ? ARG_UINT32(OPT_BITMAP_FLUSH_TIME_ID) : ARG_UINT32(OPT_JOURNAL_COMMIT_TIME_ID),
+ .buffer_sectors = ARG_UINT32(OPT_BUFFER_SECTORS_ID),
+ };
+ uint32_t activate_flags = 0;
+ char integrity[MAX_CIPHER_LEN], journal_integrity[MAX_CIPHER_LEN], journal_crypt[MAX_CIPHER_LEN];
+ char *integrity_key = NULL;
+ int r;
+
+ r = crypt_parse_hash_integrity_mode(ARG_STR(OPT_INTEGRITY_ID), integrity);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ return r;
+ }
+ params.integrity = integrity;
+
+ if (ARG_SET(OPT_JOURNAL_INTEGRITY_ID)) {
+ r = crypt_parse_hash_integrity_mode(ARG_STR(OPT_JOURNAL_INTEGRITY_ID), journal_integrity);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ return r;
+
+ }
+ params.journal_integrity = journal_integrity;
+ }
+
+ if (ARG_SET(OPT_JOURNAL_CRYPT_ID)) {
+ r = crypt_parse_hash_integrity_mode(ARG_STR(OPT_JOURNAL_CRYPT_ID), journal_crypt);
+ if (r < 0) {
+ log_err(_("No known integrity specification pattern detected."));
+ return r;
+ }
+ params.journal_crypt = journal_crypt;
+ }
+
+ if (ARG_SET(OPT_INTEGRITY_NO_JOURNAL_ID) || ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID))
+ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
+ if (ARG_SET(OPT_INTEGRITY_RECOVERY_MODE_ID))
+ activate_flags |= CRYPT_ACTIVATE_RECOVERY;
+ if (ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID))
+ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;
+
+ if (ARG_SET(OPT_INTEGRITY_RECALCULATE_ID) || ARG_SET(OPT_INTEGRITY_LEGACY_RECALC_ID))
+ activate_flags |= CRYPT_ACTIVATE_RECALCULATE;
+
+ if (ARG_SET(OPT_INTEGRITY_RECALCULATE_RESET_ID))
+ activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET;
+
+ if (ARG_SET(OPT_ALLOW_DISCARDS_ID))
+ activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
+
+ r = _read_keys(&integrity_key, &params);
+ if (r)
+ goto out;
+
+ if ((r = crypt_init_data_device(&cd, action_argv[0], ARG_STR(OPT_DATA_DEVICE_ID))))
+ goto out;
+
+ r = crypt_load(cd, CRYPT_INTEGRITY, &params);
+ if (r) {
+ log_err(_("Device %s is not a valid INTEGRITY device."), action_argv[0]);
+ goto out;
+ }
+
+ if (ARG_SET(OPT_INTEGRITY_LEGACY_RECALC_ID))
+ crypt_set_compatibility(cd, CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC);
+
+ r = crypt_activate_by_volume_key(cd, action_argv[1], integrity_key,
+ ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID), activate_flags);
+out:
+ crypt_safe_free(integrity_key);
+ crypt_safe_free(CONST_CAST(void*)params.journal_integrity_key);
+ crypt_safe_free(CONST_CAST(void*)params.journal_crypt_key);
+ crypt_free(cd);
+ return r;
+}
+
+static int action_close(void)
+{
+ struct crypt_device *cd = NULL;
+ crypt_status_info ci;
+ uint32_t flags = 0;
+ int r;
+
+ if (ARG_SET(OPT_DEFERRED_ID))
+ flags |= CRYPT_DEACTIVATE_DEFERRED;
+ if (ARG_SET(OPT_CANCEL_DEFERRED_ID))
+ flags |= CRYPT_DEACTIVATE_DEFERRED_CANCEL;
+
+ r = crypt_init_by_name(&cd, action_argv[0]);
+ if (r == 0)
+ r = crypt_deactivate_by_name(cd, action_argv[0], flags);
+
+ if (!r && ARG_SET(OPT_DEFERRED_ID)) {
+ ci = crypt_status(cd, action_argv[0]);
+ if (ci == CRYPT_ACTIVE || ci == CRYPT_BUSY)
+ log_std(_("Device %s is still active and scheduled for deferred removal.\n"),
+ action_argv[0]);
+ }
+
+ crypt_free(cd);
+ return r;
+}
+
+static int action_status(void)
+{
+ crypt_status_info ci;
+ struct crypt_active_device cad;
+ struct crypt_params_integrity ip = {};
+ struct crypt_device *cd = NULL;
+ char *backing_file;
+ const char *device, *metadata_device;
+ int path = 0, r = 0;
+
+ /* perhaps a path, not a dm device name */
+ if (strchr(action_argv[0], '/'))
+ path = 1;
+
+ ci = crypt_status(NULL, action_argv[0]);
+ switch (ci) {
+ case CRYPT_INVALID:
+ r = -EINVAL;
+ break;
+ case CRYPT_INACTIVE:
+ if (path)
+ log_std("%s is inactive.\n", action_argv[0]);
+ else
+ log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
+ r = -ENODEV;
+ break;
+ case CRYPT_ACTIVE:
+ case CRYPT_BUSY:
+ if (path)
+ log_std("%s is active%s.\n", action_argv[0],
+ ci == CRYPT_BUSY ? " and is in use" : "");
+ else
+ log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
+ ci == CRYPT_BUSY ? " and is in use" : "");
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
+ if (r < 0)
+ goto out;
+
+ log_std(" type: %s\n", crypt_get_type(cd) ?: "n/a");
+
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r < 0)
+ goto out;
+
+ /* Print only INTEGRITY (and LUKS2 with integrity) info */
+ r = crypt_get_integrity_info(cd, &ip);
+ if (r < 0)
+ goto out;
+
+ log_std(" tag size: %u\n", ip.tag_size);
+ log_std(" integrity: %s\n", ip.integrity ?: "(none)");
+ device = crypt_get_device_name(cd);
+ metadata_device = crypt_get_metadata_device_name(cd);
+ log_std(" device: %s%s\n", device, metadata_device ? " (detached)" : "");
+ if ((backing_file = crypt_loop_backing_file(device))) {
+ log_std(" loop: %s\n", backing_file);
+ free(backing_file);
+ }
+ if (metadata_device) {
+ log_std(" metadata device: %s\n", metadata_device);
+ if ((backing_file = crypt_loop_backing_file(metadata_device))) {
+ log_std(" loop: %s\n", backing_file);
+ free(backing_file);
+ }
+ }
+ log_std(" sector size: %u bytes\n", crypt_get_sector_size(cd));
+ log_std(" interleave sectors: %u\n", ip.interleave_sectors);
+ log_std(" size: %" PRIu64 " sectors\n", cad.size);
+ log_std(" mode: %s%s\n",
+ cad.flags & CRYPT_ACTIVATE_READONLY ? "readonly" : "read/write",
+ cad.flags & CRYPT_ACTIVATE_RECOVERY ? " recovery" : "");
+ log_std(" failures: %" PRIu64 "\n",
+ crypt_get_active_integrity_failures(cd, action_argv[0]));
+ if (cad.flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) {
+ log_std(" bitmap 512-byte sectors per bit: %u\n", ip.journal_watermark);
+ log_std(" bitmap flush interval: %u ms\n", ip.journal_commit_time);
+ } if (cad.flags & CRYPT_ACTIVATE_NO_JOURNAL) {
+ log_std(" journal: not active\n");
+ } else {
+ log_std(" journal size: %" PRIu64 " bytes\n", ip.journal_size);
+ log_std(" journal watermark: %u%%\n", ip.journal_watermark);
+ log_std(" journal commit time: %u ms\n", ip.journal_commit_time);
+ if (ip.journal_integrity)
+ log_std(" journal integrity MAC: %s\n", ip.journal_integrity);
+ if (ip.journal_crypt)
+ log_std(" journal encryption: %s\n", ip.journal_crypt);
+ }
+ if (cad.flags & (CRYPT_ACTIVATE_ALLOW_DISCARDS))
+ log_std(" flags: %s\n",
+ (cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? "discards " : "");
+ }
+out:
+ crypt_free(cd);
+ if (r == -ENOTSUP)
+ r = 0;
+ return r;
+ return -EINVAL;
+}
+
+static int action_dump(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_integrity params = {};
+ int r;
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ return r;
+
+ r = crypt_load(cd, CRYPT_INTEGRITY, &params);
+ if (!r)
+ crypt_dump(cd);
+ else
+ log_err(_("Device %s is not a valid INTEGRITY device."), action_argv[0]);
+
+ crypt_free(cd);
+ return r;
+}
+
+static struct action_type {
+ const char *type;
+ int (*handler)(void);
+ int required_action_argc;
+ const char *arg_desc;
+ const char *desc;
+} action_types[] = {
+ { FORMAT_ACTION,action_format, 1, N_("<integrity_device>"),N_("format device") },
+ { OPEN_ACTION, action_open, 2, N_("<integrity_device> <name>"),N_("open device as <name>") },
+ { CLOSE_ACTION, action_close, 1, N_("<name>"),N_("close device (remove mapping)") },
+ { STATUS_ACTION,action_status, 1, N_("<name>"),N_("show active device status") },
+ { DUMP_ACTION, action_dump, 1, N_("<integrity_device>"),N_("show on-disk information") },
+ { RESIZE_ACTION,action_resize, 1, N_("<name>"), N_("resize active device") },
+ {}
+};
+
+static void help(poptContext popt_context,
+ enum poptCallbackReason reason __attribute__((unused)),
+ struct poptOption *key,
+ const char *arg __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ struct action_type *action;
+
+ if (key->shortName == '?') {
+ tools_package_version(PACKAGE_INTEGRITY, false);
+ poptPrintHelp(popt_context, stdout, 0);
+ log_std(_("\n"
+ "<action> is one of:\n"));
+ for(action = action_types; action->type; action++)
+ log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
+ log_std(_("\n"
+ "<name> is the device to create under %s\n"
+ "<integrity_device> is the device containing data with integrity tags\n"),
+ crypt_get_dir());
+
+ log_std(_("\nDefault compiled-in dm-integrity parameters:\n"
+ "\tChecksum algorithm: %s\n"
+ "\tMaximum keyfile size: %dkB\n"),
+ DEFAULT_ALG_NAME, DEFAULT_INTEGRITY_KEYFILE_SIZE_MAXKB);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(EXIT_SUCCESS);
+ } else if (key->shortName == 'V') {
+ tools_package_version(PACKAGE_INTEGRITY, false);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(EXIT_SUCCESS);
+ } else
+ usage(popt_context, EXIT_SUCCESS, NULL, NULL);
+}
+
+static int run_action(struct action_type *action)
+{
+ int r;
+
+ log_dbg("Running command %s.", action->type);
+
+ r = action->handler();
+
+ show_status(r);
+ return translate_errno(r);
+}
+
+static bool needs_size_conversion(unsigned int arg_id)
+{
+ return (arg_id == OPT_JOURNAL_SIZE_ID || arg_id == OPT_DEVICE_SIZE_ID);
+}
+
+static void basic_options_cb(poptContext popt_context,
+ enum poptCallbackReason reason __attribute__((unused)),
+ struct poptOption *key,
+ const char *arg,
+ void *data __attribute__((unused)))
+{
+ char msg[256];
+
+ tools_parse_arg_value(popt_context, tool_core_args[key->val].type, tool_core_args + key->val, arg, key->val, needs_size_conversion);
+
+ /* special cases additional handling */
+ switch (key->val) {
+ case OPT_DEBUG_ID:
+ log_parms.debug = true;
+ /* fall through */
+ case OPT_VERBOSE_ID:
+ log_parms.verbose = true;
+ break;
+ case OPT_INTEGRITY_KEY_SIZE_ID:
+ /* fall through */
+ case OPT_JOURNAL_INTEGRITY_KEY_SIZE_ID:
+ /* fall through */
+ case OPT_JOURNAL_CRYPT_KEY_SIZE_ID:
+ if (ARG_UINT32(key->val) > (DEFAULT_INTEGRITY_KEYFILE_SIZE_MAXKB * 1024)) {
+ if (snprintf(msg, sizeof(msg), _("Invalid --%s size. Maximum is %u bytes."),
+ key->longName, DEFAULT_INTEGRITY_KEYFILE_SIZE_MAXKB * 1024) < 0)
+ msg[0] = '\0';
+ usage(popt_context, EXIT_FAILURE, msg,
+ poptGetInvocationName(popt_context));
+ }
+ }
+}
+
+int main(int argc, const char **argv)
+{
+ static const char *null_action_argv[] = {NULL};
+ static struct poptOption popt_help_options[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, help, 0, NULL, NULL },
+ { "help", '?', POPT_ARG_NONE, NULL, 0, N_("Show this help message"), NULL },
+ { "usage", '\0', POPT_ARG_NONE, NULL, 0, N_("Display brief usage"), NULL },
+ { "version",'V', POPT_ARG_NONE, NULL, 0, N_("Print package version"), NULL },
+ POPT_TABLEEND
+ };
+ static struct poptOption popt_basic_options[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, basic_options_cb, 0, NULL, NULL },
+#define ARG(A, B, C, D, E, F, G, H) { A, B, C, NULL, A ## _ID, D, E },
+#include "integritysetup_arg_list.h"
+#undef ARG
+ POPT_TABLEEND
+ };
+ static struct poptOption popt_options[] = {
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_basic_options, 0, NULL, NULL },
+ POPT_TABLEEND
+ };
+ poptContext popt_context;
+ struct action_type *action;
+ const char *aname;
+ int r;
+
+ crypt_set_log_callback(NULL, tool_log, &log_parms);
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ popt_context = poptGetContext("integrity", argc, argv, popt_options, 0);
+ poptSetOtherOptionHelp(popt_context,
+ _("[OPTION...] <action> <action-specific>"));
+
+
+ while ((r = poptGetNextOpt(popt_context)) >= 0) {
+ }
+
+ if (r < -1)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(r),
+ poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
+
+ if (!(aname = poptGetArg(popt_context)))
+ usage(popt_context, EXIT_FAILURE, _("Argument <action> missing."),
+ poptGetInvocationName(popt_context));
+
+ action_argc = 0;
+ action_argv = poptGetArgs(popt_context);
+ /* Make return values of poptGetArgs more consistent in case of remaining argc = 0 */
+ if (!action_argv)
+ action_argv = null_action_argv;
+
+ /* Count args, somewhat unnice, change? */
+ while (action_argv[action_argc] != NULL)
+ action_argc++;
+
+ /* Handle aliases */
+ if (!strcmp(aname, "create") && action_argc > 1) {
+ /* create command had historically switched arguments */
+ if (action_argv[0] && action_argv[1]) {
+ const char *tmp = action_argv[0];
+ action_argv[0] = action_argv[1];
+ action_argv[1] = tmp;
+ }
+ aname = "open";
+ } else if (!strcmp(aname, "remove")) {
+ aname = "close";
+ }
+
+ for (action = action_types; action->type; action++)
+ if (strcmp(action->type, aname) == 0)
+ break;
+
+ if (!action->type)
+ usage(popt_context, EXIT_FAILURE, _("Unknown action."),
+ poptGetInvocationName(popt_context));
+
+ if (action_argc < action->required_action_argc) {
+ char buf[128];
+ if (snprintf(buf, 128,_("%s: requires %s as arguments"), action->type, action->arg_desc) < 0)
+ buf[0] ='\0';
+ usage(popt_context, EXIT_FAILURE, buf,
+ poptGetInvocationName(popt_context));
+ }
+
+ tools_check_args(action->type, tool_core_args, ARRAY_SIZE(tool_core_args), popt_context);
+
+ if (ARG_SET(OPT_INTEGRITY_KEY_FILE_ID) != ARG_SET(OPT_INTEGRITY_KEY_SIZE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Both key file and key size options must be specified."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_JOURNAL_INTEGRITY_KEY_FILE_ID) != ARG_SET(OPT_JOURNAL_INTEGRITY_KEY_SIZE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Both journal integrity key file and key size options must be specified."),
+ poptGetInvocationName(popt_context));
+ if (!ARG_SET(OPT_JOURNAL_INTEGRITY_ID) && ARG_SET(OPT_JOURNAL_INTEGRITY_KEY_FILE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Journal integrity algorithm must be specified if journal integrity key is used."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_JOURNAL_CRYPT_KEY_FILE_ID) != ARG_SET(OPT_JOURNAL_CRYPT_KEY_SIZE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Both journal encryption key file and key size options must be specified."),
+ poptGetInvocationName(popt_context));
+ if (!ARG_SET(OPT_JOURNAL_CRYPT_ID) && ARG_SET(OPT_JOURNAL_CRYPT_KEY_FILE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Journal encryption algorithm must be specified if journal encryption key is used."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_INTEGRITY_RECOVERY_MODE_ID) && ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID))
+ usage(popt_context, EXIT_FAILURE, _("Recovery and bitmap mode options are mutually exclusive."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID) &&
+ (ARG_SET(OPT_JOURNAL_INTEGRITY_KEY_FILE_ID) ||
+ ARG_SET(OPT_JOURNAL_CRYPT_ID) || ARG_SET(OPT_JOURNAL_WATERMARK_ID) ||
+ ARG_SET(OPT_JOURNAL_COMMIT_TIME_ID)))
+ usage(popt_context, EXIT_FAILURE, _("Journal options cannot be used in bitmap mode."),
+ poptGetInvocationName(popt_context));
+
+ if (!ARG_SET(OPT_INTEGRITY_BITMAP_MODE_ID) &&
+ (ARG_SET(OPT_BITMAP_FLUSH_TIME_ID) || ARG_SET(OPT_BITMAP_SECTORS_PER_BIT_ID)))
+ usage(popt_context, EXIT_FAILURE, _("Bitmap options can be used only in bitmap mode."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_CANCEL_DEFERRED_ID) && ARG_SET(OPT_DEFERRED_ID))
+ usage(popt_context, EXIT_FAILURE,
+ _("Options --cancel-deferred and --deferred cannot be used at the same time."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_DEBUG_ID)) {
+ crypt_set_debug_level(CRYPT_DEBUG_ALL);
+ dbg_version_and_cmd(argc, argv);
+ }
+
+ r = run_action(action);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ return r;
+}
diff --git a/src/integritysetup_arg_list.h b/src/integritysetup_arg_list.h
new file mode 100644
index 0000000..39f2906
--- /dev/null
+++ b/src/integritysetup_arg_list.h
@@ -0,0 +1,100 @@
+/*
+ * Integritysetup command line arguments list
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* long name, short name, popt type, help description, units, internal argument type, default value */
+
+ARG(OPT_ALLOW_DISCARDS, '\0', POPT_ARG_NONE, N_("Allow discards (aka TRIM) requests for device"), NULL, CRYPT_ARG_BOOL, {}, OPT_ALLOW_DISCARDS_ACTIONS)
+
+ARG(OPT_BATCH_MODE, 'q', POPT_ARG_NONE, N_("Do not ask for confirmation"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_BUFFER_SECTORS, '\0', POPT_ARG_STRING, N_("Buffers size"), N_("SECTORS"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_BITMAP_FLUSH_TIME, '\0', POPT_ARG_STRING, N_("Bitmap mode flush time"), N_("ms"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_BITMAP_SECTORS_PER_BIT, '\0', POPT_ARG_STRING, N_("Number of 512-byte sectors per bit (bitmap mode)."), "INT", CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_CANCEL_DEFERRED, '\0', POPT_ARG_NONE, N_("Cancel a previously set deferred device removal"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS)
+
+ARG(OPT_DATA_DEVICE, '\0', POPT_ARG_STRING, N_("Path to data device (if separated)"), N_("path"), CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_DEBUG, '\0', POPT_ARG_NONE, N_("Show debug messages"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DEFERRED, '\0', POPT_ARG_NONE, N_("Device removal is deferred until the last user closes it"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS)
+
+ARG(OPT_INTEGRITY, 'I', POPT_ARG_STRING, N_("Data integrity algorithm"), NULL, CRYPT_ARG_STRING, { .str_value = CONST_CAST(void *)DEFAULT_ALG_NAME }, {})
+
+ARG(OPT_INTEGRITY_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the integrity key from a file"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the data integrity key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_INTEGRITY_LEGACY_PADDING, '\0', POPT_ARG_NONE, N_("Use inefficient legacy padding (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTEGRITY_LEGACY_HMAC, '\0', POPT_ARG_NONE, N_("Do not protect superblock with HMAC (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTEGRITY_LEGACY_RECALC, '\0', POPT_ARG_NONE, N_("Allow recalculating of volumes with HMAC keys (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS)
+
+ARG(OPT_INTEGRITY_NO_JOURNAL, 'D', POPT_ARG_NONE, N_("Disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTERLEAVE_SECTORS, '\0', POPT_ARG_STRING, N_("Interleave sectors"), N_("SECTORS"), CRYPT_ARG_UINT32, {}, OPT_INTERLEAVE_SECTORS_ACTIONS)
+
+ARG(OPT_JOURNAL_COMMIT_TIME, '\0', POPT_ARG_STRING, N_("Journal commit time"), N_("ms"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_JOURNAL_INTEGRITY, '\0', POPT_ARG_STRING, N_("Journal integrity algorithm"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_JOURNAL_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the journal integrity key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_JOURNAL_INTEGRITY_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the journal integrity key from a file"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_JOURNAL_CRYPT, '\0', POPT_ARG_STRING, N_("Journal encryption algorithm"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_JOURNAL_CRYPT_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the journal encryption key from a file"), NULL, CRYPT_ARG_STRING,{}, {})
+
+ARG(OPT_JOURNAL_CRYPT_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the journal encryption key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_JOURNAL_SIZE, 'j', POPT_ARG_STRING, N_("Journal size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_JOURNAL_SIZE_ACTIONS)
+
+ARG(OPT_JOURNAL_WATERMARK, '\0', POPT_ARG_STRING, N_("Journal watermark"), N_("percent"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_NO_WIPE, '\0', POPT_ARG_NONE, N_("Do not wipe device after format"), NULL, CRYPT_ARG_BOOL, {}, OPT_NO_WIPE_ACTIONS)
+
+ARG(OPT_WIPE, '\0', POPT_ARG_NONE, N_("Wipe the end of the device after resize"), NULL, CRYPT_ARG_BOOL, {}, OPT_WIPE_ACTIONS)
+
+ARG(OPT_PROGRESS_FREQUENCY, '\0', POPT_ARG_STRING, N_("Progress line update (in seconds)"), N_("secs"), CRYPT_ARG_UINT32, {}, {})
+
+ARG(OPT_PROGRESS_JSON, '\0', POPT_ARG_NONE, N_("Print wipe progress data in json format (suitable for machine processing)"), NULL, CRYPT_ARG_BOOL, {}, OPT_PROGRESS_JSON_ACTIONS)
+
+ARG(OPT_INTEGRITY_BITMAP_MODE, 'B', POPT_ARG_NONE, N_("Use bitmap to track changes and disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_INTEGRITY_RECALCULATE, '\0', POPT_ARG_NONE, N_("Recalculate initial tags automatically."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS)
+
+ARG(OPT_INTEGRITY_RECALCULATE_RESET, '\0', POPT_ARG_NONE, N_("Reset automatic recalculate position."), NULL, CRYPT_ARG_BOOL, {}, OPT_INTEGRITY_RECALCULATE_ACTIONS)
+
+ARG(OPT_INTEGRITY_RECOVERY_MODE, 'R', POPT_ARG_NONE, N_("Recovery mode (no journal, no tag checking)"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_SECTOR_SIZE, 's', POPT_ARG_STRING, N_("Sector size"), N_("bytes"), CRYPT_ARG_UINT32, { .u32_value = 512 }, OPT_SECTOR_SIZE_ACTIONS)
+
+ARG(OPT_TAG_SIZE, 't', POPT_ARG_STRING, N_("Tag size (per-sector)"), N_("bytes"), CRYPT_ARG_UINT32, {}, OPT_TAG_SIZE_ACTIONS)
+
+ARG(OPT_VERBOSE, 'v', POPT_ARG_NONE, N_("Shows more detailed error messages"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DEVICE_SIZE, '\0', POPT_ARG_STRING, N_("Use only specified device size (ignore rest of device). DANGEROUS!"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_DEVICE_SIZE_ACTIONS)
+
+ARG(OPT_SIZE, 'b', POPT_ARG_STRING, N_("The size of the device"), N_("SECTORS"), CRYPT_ARG_UINT64, {}, OPT_SIZE_ACTIONS)
diff --git a/src/integritysetup_args.h b/src/integritysetup_args.h
new file mode 100644
index 0000000..8241008
--- /dev/null
+++ b/src/integritysetup_args.h
@@ -0,0 +1,61 @@
+/*
+ * Command line arguments helpers
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INTEGRITYSETUP_ARGS_H
+#define INTEGRITYSETUP_ARGS_H
+
+#include "utils_arg_names.h"
+#include "utils_arg_macros.h"
+
+#define FORMAT_ACTION "format"
+#define OPEN_ACTION "open"
+#define CLOSE_ACTION "close"
+#define STATUS_ACTION "status"
+#define DUMP_ACTION "dump"
+#define RESIZE_ACTION "resize"
+
+#define OPT_ALLOW_DISCARDS_ACTIONS { OPEN_ACTION }
+#define OPT_DEFERRED_ACTIONS { CLOSE_ACTION }
+#define OPT_INTEGRITY_RECALCULATE_ACTIONS { OPEN_ACTION }
+#define OPT_JOURNAL_SIZE_ACTIONS { FORMAT_ACTION }
+#define OPT_NO_WIPE_ACTIONS { FORMAT_ACTION }
+#define OPT_INTERLEAVE_SECTORS_ACTIONS { FORMAT_ACTION }
+#define OPT_PROGRESS_JSON_ACTIONS { FORMAT_ACTION, RESIZE_ACTION }
+#define OPT_SECTOR_SIZE_ACTIONS { FORMAT_ACTION }
+#define OPT_TAG_SIZE_ACTIONS { FORMAT_ACTION }
+#define OPT_DEVICE_SIZE_ACTIONS { RESIZE_ACTION }
+#define OPT_SIZE_ACTIONS { RESIZE_ACTION }
+#define OPT_WIPE_ACTIONS { RESIZE_ACTION }
+
+enum {
+OPT_UNUSED_ID = 0,
+#define ARG(A, B, C, D, E, F, G, H) A ## _ID,
+#include "integritysetup_arg_list.h"
+#undef ARG
+};
+
+static struct tools_arg tool_core_args[] = { { NULL, false, CRYPT_ARG_BOOL }, // UNUSED
+#define ARG(A, B, C, D, E, F, G, H) { A, false, F, G, H },
+#include "integritysetup_arg_list.h"
+#undef ARG
+};
+
+#endif
diff --git a/src/utils_arg_macros.h b/src/utils_arg_macros.h
new file mode 100644
index 0000000..901b3f4
--- /dev/null
+++ b/src/utils_arg_macros.h
@@ -0,0 +1,103 @@
+/*
+ * Command line arguments parsing helpers
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef UTILS_ARG_MACROS_H
+#define UTILS_ARG_MACROS_H
+
+#include <assert.h>
+
+#define ARG_SET(X) !!tool_core_args[(X)].set
+
+#define ARG_STR(X) ({ \
+ assert(tool_core_args[(X)].type == CRYPT_ARG_STRING); \
+ tool_core_args[(X)].u.str_value; \
+})
+
+#define ARG_INT32(X) ({ \
+ assert(tool_core_args[(X)].type == CRYPT_ARG_INT32); \
+ tool_core_args[(X)].u.i32_value; \
+})
+
+#define ARG_UINT32(X) ({ \
+ assert(tool_core_args[(X)].type == CRYPT_ARG_UINT32); \
+ tool_core_args[(X)].u.u32_value; \
+})
+
+#define ARG_INT64(X) ({ \
+ assert(tool_core_args[(X)].type == CRYPT_ARG_INT64); \
+ tool_core_args[(X)].u.i64_value; \
+})
+
+#define ARG_UINT64(X) ({ \
+ assert(tool_core_args[(X)].type == CRYPT_ARG_UINT64); \
+ tool_core_args[(X)].u.u64_value; \
+})
+
+#define ARG_SET_TRUE(X) do { \
+ tool_core_args[(X)].set = true; \
+} while (0)
+
+#define ARG_SET_STR(X, Y) \
+do { \
+ char *str; \
+ assert(tool_core_args[(X)].set == false && tool_core_args[(X)].type == CRYPT_ARG_STRING); \
+ str = (Y); \
+ assert(str != NULL); \
+ tool_core_args[(X)].u.str_value = str; \
+ tool_core_args[(X)].set = true; \
+} while (0)
+
+#define ARG_SET_INT32(X, Y) \
+do { \
+ assert(tool_core_args[(X)].set == false && tool_core_args[(X)].type == CRYPT_ARG_INT32); \
+ tool_core_args[(X)].u.i32_value = (Y); \
+ tool_core_args[(X)].set = true; \
+} while (0)
+
+#define ARG_SET_UINT32(X, Y) \
+do { \
+ assert(tool_core_args[(X)].set == false && tool_core_args[(X)].type == CRYPT_ARG_UINT32); \
+ tool_core_args[(X)].u.u32_value = (Y); \
+ tool_core_args[(X)].set = true; \
+} while (0)
+
+#define ARG_SET_INT64(X, Y) \
+do { \
+ assert(tool_core_args[(X)].set == false && tool_core_args[(X)].type == CRYPT_ARG_INT64); \
+ tool_core_args[(X)].u.i64_value = (Y); \
+ tool_core_args[(X)].set = true; \
+} while (0)
+
+#define ARG_SET_UINT64(X, Y) \
+do { \
+ assert(tool_core_args[(X)].set == false && tool_core_args[(X)].type == CRYPT_ARG_UINT64); \
+ tool_core_args[(X)].u.u64_value = (Y); \
+ tool_core_args[(X)].set = true; \
+} while (0)
+
+
+#define ARG_INIT_ALIAS(X) \
+do { \
+ assert(tool_core_args[(X)].type == CRYPT_ARG_ALIAS); \
+ tool_core_args[(X)].u.o.ptr = &tool_core_args[tool_core_args[(X)].u.o.id]; \
+} while (0)
+
+#endif
diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h
new file mode 100644
index 0000000..66a59e8
--- /dev/null
+++ b/src/utils_arg_names.h
@@ -0,0 +1,173 @@
+/*
+ * Command line arguments name list
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef UTILS_ARG_NAMES_H
+#define UTILS_ARG_NAMES_H
+
+#define OPT_ACTIVE_NAME "active-name"
+#define OPT_ALIGN_PAYLOAD "align-payload"
+#define OPT_ALLOW_DISCARDS "allow-discards"
+#define OPT_BATCH_MODE "batch-mode"
+#define OPT_BITMAP_FLUSH_TIME "bitmap-flush-time"
+#define OPT_BITMAP_SECTORS_PER_BIT "bitmap-sectors-per-bit"
+#define OPT_BLOCK_SIZE "block-size"
+#define OPT_BUFFER_SECTORS "buffer-sectors"
+#define OPT_CANCEL_DEFERRED "cancel-deferred"
+#define OPT_CHECK_AT_MOST_ONCE "check-at-most-once"
+#define OPT_CIPHER "cipher"
+#define OPT_DATA_BLOCK_SIZE "data-block-size"
+#define OPT_DATA_BLOCKS "data-blocks"
+#define OPT_DATA_DEVICE "data-device"
+#define OPT_DEBUG "debug"
+#define OPT_DEBUG_JSON "debug-json"
+#define OPT_DEFERRED "deferred"
+#define OPT_DEVICE_SIZE "device-size"
+#define OPT_DECRYPT "decrypt"
+#define OPT_DISABLE_EXTERNAL_TOKENS "disable-external-tokens"
+#define OPT_DISABLE_KEYRING "disable-keyring"
+#define OPT_DISABLE_LOCKS "disable-locks"
+#define OPT_DISABLE_VERACRYPT "disable-veracrypt"
+#define OPT_DUMP_JSON "dump-json-metadata"
+#define OPT_DUMP_MASTER_KEY "dump-master-key"
+#define OPT_DUMP_VOLUME_KEY "dump-volume-key"
+#define OPT_ENCRYPT "encrypt"
+#define OPT_FEC_DEVICE "fec-device"
+#define OPT_FEC_OFFSET "fec-offset"
+#define OPT_FEC_ROOTS "fec-roots"
+#define OPT_FORCE_PASSWORD "force-password"
+#define OPT_FORCE_OFFLINE_REENCRYPT "force-offline-reencrypt"
+#define OPT_FORMAT "format"
+#define OPT_HASH "hash"
+#define OPT_HASH_BLOCK_SIZE "hash-block-size"
+#define OPT_HASH_OFFSET "hash-offset"
+#define OPT_HEADER "header"
+#define OPT_HEADER_BACKUP_FILE "header-backup-file"
+#define OPT_HOTZONE_SIZE "hotzone-size"
+#define OPT_IGNORE_CORRUPTION "ignore-corruption"
+#define OPT_IGNORE_ZERO_BLOCKS "ignore-zero-blocks"
+#define OPT_INIT_ONLY "init-only"
+#define OPT_INTEGRITY "integrity"
+#define OPT_INTEGRITY_BITMAP_MODE "integrity-bitmap-mode"
+#define OPT_INTEGRITY_KEY_FILE "integrity-key-file"
+#define OPT_INTEGRITY_KEY_SIZE "integrity-key-size"
+#define OPT_INTEGRITY_LEGACY_PADDING "integrity-legacy-padding"
+#define OPT_INTEGRITY_LEGACY_HMAC "integrity-legacy-hmac"
+#define OPT_INTEGRITY_LEGACY_RECALC "integrity-legacy-recalculate"
+#define OPT_INTEGRITY_NO_JOURNAL "integrity-no-journal"
+#define OPT_INTEGRITY_NO_WIPE "integrity-no-wipe"
+#define OPT_INTEGRITY_RECALCULATE "integrity-recalculate"
+#define OPT_INTEGRITY_RECALCULATE_RESET "integrity-recalculate-reset"
+#define OPT_INTEGRITY_RECOVERY_MODE "integrity-recovery-mode"
+#define OPT_INTERLEAVE_SECTORS "interleave-sectors"
+#define OPT_ITER_TIME "iter-time"
+#define OPT_IV_LARGE_SECTORS "iv-large-sectors"
+#define OPT_JSON_FILE "json-file"
+#define OPT_JOURNAL_COMMIT_TIME "journal-commit-time"
+#define OPT_JOURNAL_CRYPT "journal-crypt"
+#define OPT_JOURNAL_CRYPT_KEY_FILE "journal-crypt-key-file"
+#define OPT_JOURNAL_CRYPT_KEY_SIZE "journal-crypt-key-size"
+#define OPT_JOURNAL_INTEGRITY "journal-integrity"
+#define OPT_JOURNAL_INTEGRITY_KEY_FILE "journal-integrity-key-file"
+#define OPT_JOURNAL_INTEGRITY_KEY_SIZE "journal-integrity-key-size"
+#define OPT_JOURNAL_SIZE "journal-size"
+#define OPT_JOURNAL_WATERMARK "journal-watermark"
+#define OPT_KEEP_KEY "keep-key"
+#define OPT_KEY_DESCRIPTION "key-description"
+#define OPT_KEY_FILE "key-file"
+#define OPT_KEY_SIZE "key-size"
+#define OPT_KEY_SLOT "key-slot"
+#define OPT_KEYFILE_OFFSET "keyfile-offset"
+#define OPT_KEYFILE_SIZE "keyfile-size"
+#define OPT_KEYSLOT_CIPHER "keyslot-cipher"
+#define OPT_KEYSLOT_KEY_SIZE "keyslot-key-size"
+#define OPT_NO_SUPERBLOCK "no-superblock"
+#define OPT_NO_WIPE "no-wipe"
+#define OPT_WIPE "wipe"
+#define OPT_LABEL "label"
+#define OPT_LUKS2_KEYSLOTS_SIZE "luks2-keyslots-size"
+#define OPT_LUKS2_METADATA_SIZE "luks2-metadata-size"
+#define OPT_MASTER_KEY_FILE "master-key-file"
+#define OPT_VOLUME_KEY_FILE "volume-key-file"
+#define OPT_NEW "new"
+#define OPT_NEW_KEY_SLOT "new-key-slot"
+#define OPT_NEW_KEYFILE "new-keyfile"
+#define OPT_NEW_KEYFILE_OFFSET "new-keyfile-offset"
+#define OPT_NEW_KEYFILE_SIZE "new-keyfile-size"
+#define OPT_NEW_TOKEN_ID "new-token-id"
+#define OPT_OFFSET "offset"
+#define OPT_PANIC_ON_CORRUPTION "panic-on-corruption"
+#define OPT_PBKDF "pbkdf"
+#define OPT_PBKDF_FORCE_ITERATIONS "pbkdf-force-iterations"
+#define OPT_PBKDF_MEMORY "pbkdf-memory"
+#define OPT_PBKDF_PARALLEL "pbkdf-parallel"
+#define OPT_PERF_NO_READ_WORKQUEUE "perf-no_read_workqueue"
+#define OPT_PERF_NO_WRITE_WORKQUEUE "perf-no_write_workqueue"
+#define OPT_PERF_SAME_CPU_CRYPT "perf-same_cpu_crypt"
+#define OPT_PERF_SUBMIT_FROM_CRYPT_CPUS "perf-submit_from_crypt_cpus"
+#define OPT_PERSISTENT "persistent"
+#define OPT_PLUGIN "plugin"
+#define OPT_PRIORITY "priority"
+#define OPT_PROGRESS_JSON "progress-json"
+#define OPT_PROGRESS_FREQUENCY "progress-frequency"
+#define OPT_READONLY "readonly"
+#define OPT_REDUCE_DEVICE_SIZE "reduce-device-size"
+#define OPT_REFRESH "refresh"
+#define OPT_RESILIENCE "resilience"
+#define OPT_RESILIENCE_HASH "resilience-hash"
+#define OPT_RESTART_ON_CORRUPTION "restart-on-corruption"
+#define OPT_RESUME_ONLY "resume-only"
+#define OPT_ROOT_HASH_FILE "root-hash-file"
+#define OPT_ROOT_HASH_SIGNATURE "root-hash-signature"
+#define OPT_SALT "salt"
+#define OPT_SECTOR_SIZE "sector-size"
+#define OPT_SERIALIZE_MEMORY_HARD_PBKDF "serialize-memory-hard-pbkdf"
+#define OPT_SHARED "shared"
+#define OPT_SIZE "size"
+#define OPT_SKIP "skip"
+#define OPT_SUBSYSTEM "subsystem"
+#define OPT_TAG_SIZE "tag-size"
+#define OPT_TCRYPT_BACKUP "tcrypt-backup"
+#define OPT_TCRYPT_HIDDEN "tcrypt-hidden"
+#define OPT_TCRYPT_SYSTEM "tcrypt-system"
+#define OPT_TEST_ARGS "test-args"
+#define OPT_TEST_PASSPHRASE "test-passphrase"
+#define OPT_TIMEOUT "timeout"
+#define OPT_TOKEN_ID "token-id"
+#define OPT_TOKEN_ONLY "token-only"
+#define OPT_TOKEN_REPLACE "token-replace"
+#define OPT_TOKEN_TYPE "token-type"
+#define OPT_TRIES "tries"
+#define OPT_TYPE "type"
+#define OPT_UNBOUND "unbound"
+#define OPT_USE_DIRECTIO "use-directio"
+#define OPT_USE_FSYNC "use-fsync"
+#define OPT_USE_RANDOM "use-random"
+#define OPT_USE_URANDOM "use-urandom"
+#define OPT_USE_TASKLETS "use-tasklets"
+#define OPT_UUID "uuid"
+#define OPT_VERACRYPT "veracrypt"
+#define OPT_VERACRYPT_PIM "veracrypt-pim"
+#define OPT_VERACRYPT_QUERY_PIM "veracrypt-query-pim"
+#define OPT_VERBOSE "verbose"
+#define OPT_VERIFY_PASSPHRASE "verify-passphrase"
+#define OPT_WRITE_LOG "write-log"
+
+#endif
diff --git a/src/utils_args.c b/src/utils_args.c
new file mode 100644
index 0000000..fda2350
--- /dev/null
+++ b/src/utils_args.c
@@ -0,0 +1,131 @@
+/*
+ * Command line arguments parsing helpers
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "cryptsetup.h"
+
+void tools_parse_arg_value(poptContext popt_context, crypt_arg_type_info type, struct tools_arg *arg, const char *popt_arg, int popt_val, bool(*needs_size_conv_fn)(unsigned arg_id))
+{
+ char *end, msg[128];
+ long long int ll;
+ long long unsigned int ull;
+
+ errno = 0;
+
+ switch (type) {
+ case CRYPT_ARG_BOOL:
+ break;
+ case CRYPT_ARG_STRING:
+ if (arg->set)
+ free(arg->u.str_value);
+ arg->u.str_value = poptGetOptArg(popt_context);
+ break;
+ case CRYPT_ARG_INT32:
+ ll = strtoll(popt_arg, &end, 10);
+ if (*end || !*popt_arg || ll > INT32_MAX || ll < INT32_MIN || errno == ERANGE)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
+ poptGetInvocationName(popt_context));
+ arg->u.i32_value = (int32_t)ll;
+ break;
+ case CRYPT_ARG_UINT32:
+ ull = strtoull(popt_arg, &end, 10);
+ if (*end || !*popt_arg || ull > UINT32_MAX || errno == ERANGE)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
+ poptGetInvocationName(popt_context));
+ arg->u.u32_value = (uint32_t)ull;
+ break;
+ case CRYPT_ARG_INT64:
+ ll = strtoll(popt_arg, &end, 10);
+ if (*end || !*popt_arg || errno == ERANGE)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
+ poptGetInvocationName(popt_context));
+ arg->u.i64_value = ll;
+ break;
+ case CRYPT_ARG_UINT64:
+ /* special size strings with units converted to integers */
+ if (needs_size_conv_fn && needs_size_conv_fn(popt_val)) {
+ if (tools_string_to_size(popt_arg, &arg->u.u64_value)) {
+ if (snprintf(msg, sizeof(msg), _("Invalid size specification in parameter --%s."), arg->name) < 0)
+ msg[0] = '\0';
+ usage(popt_context, EXIT_FAILURE, msg,
+ poptGetInvocationName(popt_context));
+ }
+ } else {
+ ull = strtoull(popt_arg, &end, 10);
+ if (*end || !*popt_arg || errno == ERANGE)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
+ poptGetInvocationName(popt_context));
+ arg->u.u64_value = ull;
+ }
+ break;
+ case CRYPT_ARG_ALIAS:
+ tools_parse_arg_value(popt_context, arg->u.o.ptr->type, arg->u.o.ptr, popt_arg, arg->u.o.id, needs_size_conv_fn);
+ break;
+ default:
+ /* this signals internal tools coding mistake */
+ abort();
+ }
+
+ arg->set = true;
+}
+
+void tools_args_free(struct tools_arg *args, size_t args_size)
+{
+ size_t i;
+
+ for (i = 0; i < args_size; i++) {
+ if (args[i].set && args[i].type == CRYPT_ARG_STRING)
+ free(args[i].u.str_value);
+ args[i].set = false;
+ }
+}
+
+static bool action_allowed(const char *action, const char * const* list, size_t list_size)
+{
+ size_t i;
+
+ if (!list[0])
+ return true;
+
+ for (i = 0; i < list_size && list[i]; i++) {
+ if (!strcmp(action, list[i]))
+ return true;
+ }
+
+ return false;
+}
+
+void tools_check_args(const char *action, const struct tools_arg *args, size_t args_size, poptContext popt_context)
+{
+ size_t i;
+ char msg[256];
+
+ for (i = 1; i < args_size; i++) {
+ if (args[i].set) {
+ if (action_allowed(action, args[i].actions_array, MAX_ACTIONS)) {
+ continue;
+ } else {
+ if (snprintf(msg, sizeof(msg), _("Option --%s is not allowed with %s action."), args[i].name, action) < 0)
+ msg[0] = '\0';
+ usage(popt_context, EXIT_FAILURE, msg, poptGetInvocationName(popt_context));
+ }
+ }
+ }
+}
diff --git a/src/utils_blockdev.c b/src/utils_blockdev.c
new file mode 100644
index 0000000..ae6dec4
--- /dev/null
+++ b/src/utils_blockdev.c
@@ -0,0 +1,382 @@
+/*
+ * Linux block devices helpers
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "cryptsetup.h"
+#include <dirent.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+#include <uuid/uuid.h>
+
+#define UUID_LEN 37 /* 36 + \0, libuuid ... */
+
+static int dm_prepare_uuid(const char *type, const char *uuid, char *buf, size_t buflen)
+{
+ char *ptr, uuid2[UUID_LEN] = {0};
+ uuid_t uu;
+ unsigned i = 0;
+
+ /* Remove '-' chars */
+ if (uuid) {
+ if (uuid_parse(uuid, uu) < 0) {
+ log_dbg("Requested UUID %s has invalid format.", uuid);
+ return 0;
+ }
+
+ for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
+ if (uuid[i] != '-') {
+ *ptr = uuid[i];
+ ptr++;
+ }
+ }
+
+ if (snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s",
+ type ?: "", type ? "-" : "",
+ uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "") < 0)
+ return 0;
+
+ return 1;
+}
+
+/* return number of holders in general, if matched dm_uuid prefix it's returned via dm_name */
+/* negative value is error */
+static int lookup_holder_dm_name(const char *dm_uuid, dev_t devno, char **r_dm_name)
+{
+ struct dirent *entry;
+ char dm_subpath[PATH_MAX], data_dev_dir[PATH_MAX], uuid[DM_UUID_LEN], dm_name[PATH_MAX] = {};
+ ssize_t s;
+ struct stat st;
+ int dmfd, fd, len, r = 0; /* not found */
+ DIR *dir;
+
+ if (!r_dm_name)
+ return -EINVAL;
+
+ len = snprintf(data_dev_dir, PATH_MAX, "/sys/dev/block/%u:%u/holders", major(devno), minor(devno));
+ if (len < 0 || len >= PATH_MAX)
+ return -EINVAL;
+
+ if (!(dir = opendir(data_dev_dir)))
+ /* map ENOTDIR to ENOENT we'll handle both errors same */
+ return errno == ENOTDIR ? -ENOENT : -errno;
+
+ while (r != 1 && (entry = readdir(dir))) {
+ if (entry->d_name[0] == '.' ||
+ !strncmp(entry->d_name, "..", 2))
+ continue;
+
+ /* there's a holder */
+ r++;
+
+ /* we already have a dm_name, just count remaining holders */
+ if (*dm_name != '\0')
+ continue;
+
+ len = snprintf(dm_subpath, PATH_MAX, "%s/%s", entry->d_name, "dm");
+ if (len < 0 || len >= PATH_MAX) {
+ r = -EINVAL;
+ break;
+ }
+
+ /* looking for dm-X/dm directory, symlinks are fine */
+ dmfd = openat(dirfd(dir), dm_subpath, O_DIRECTORY | O_RDONLY);
+ if (dmfd < 0)
+ continue;
+
+ fd = openat(dmfd, "uuid", O_RDONLY);
+ if (fd < 0) {
+ close(dmfd);
+ continue;
+ }
+
+ if (fstat(fd, &st) || !S_ISREG(st.st_mode)) {
+ close(fd);
+ close(dmfd);
+ continue;
+ }
+
+ /* reads binary data */
+ s = read_buffer(fd, uuid, sizeof(uuid) - 1);
+ close(fd);
+ uuid[s > 0 ? s : 0] = '\0';
+ if (!strncmp(uuid, dm_uuid, strlen(dm_uuid)))
+ log_dbg("Found candidate device %s", entry->d_name);
+ else {
+ close(dmfd);
+ continue;
+ }
+
+ fd = openat(dmfd, "name", O_RDONLY);
+ if (fd < 0) {
+ close(dmfd);
+ continue;
+ }
+
+ if (fstat(fd, &st) || !S_ISREG(st.st_mode)) {
+ close(fd);
+ close(dmfd);
+ continue;
+ }
+
+ /* reads binary data */
+ s = read_buffer(fd, dm_name, sizeof(dm_name));
+ close(fd);
+ close(dmfd);
+ if (s > 1) {
+ dm_name[s-1] = '\0';
+ log_dbg("Found dm device %s", dm_name);
+ if (!(*r_dm_name = strdup(dm_name)))
+ return -ENOMEM;
+ }
+ }
+
+ closedir(dir);
+
+ return r;
+}
+
+int tools_lookup_crypt_device(struct crypt_device *cd, const char *type,
+ const char *data_device_path, char **r_name)
+{
+ char *c;
+ struct stat st;
+ char dev_uuid[DM_UUID_LEN + DM_BY_ID_PREFIX_LEN] = DM_BY_ID_PREFIX;
+
+ if (!dm_prepare_uuid(type, crypt_get_uuid(cd), dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN))
+ return -EINVAL;
+
+ c = strrchr(dev_uuid, '-');
+ if (!c)
+ return -EINVAL;
+
+ /* cut of dm name */
+ *c = '\0';
+
+ log_dbg("Looking for any dm device with prefix: %s", dev_uuid);
+
+ if (stat(data_device_path, &st) < 0)
+ return -ENODEV;
+
+ if (!S_ISBLK(st.st_mode))
+ return -ENOTBLK;
+
+ return lookup_holder_dm_name(dev_uuid + DM_BY_ID_PREFIX_LEN, st.st_rdev, r_name);
+}
+
+static void report_partition(const char *value, const char *device, bool batch_mode)
+{
+ if (batch_mode)
+ log_dbg("Device %s already contains a '%s' partition signature.", device, value);
+ else
+ log_std(_("WARNING: Device %s already contains a '%s' partition signature.\n"), device, value);
+}
+
+static void report_superblock(const char *value, const char *device, bool batch_mode)
+{
+ if (batch_mode)
+ log_dbg("Device %s already contains a '%s' superblock signature.", device, value);
+ else
+ log_std(_("WARNING: Device %s already contains a '%s' superblock signature.\n"), device, value);
+}
+
+int tools_detect_signatures(const char *device, tools_probe_filter_info filter,
+ size_t *count,bool batch_mode)
+{
+ int r;
+ size_t tmp_count;
+ struct blkid_handle *h;
+ blk_probe_status pr;
+
+ if (!count)
+ count = &tmp_count;
+
+ *count = 0;
+
+ if (!blk_supported()) {
+ log_dbg("Blkid support disabled.");
+ return 0;
+ }
+
+ if ((r = blk_init_by_path(&h, device))) {
+ log_err(_("Failed to initialize device signature probes."));
+ return -EINVAL;
+ }
+
+ switch (filter) {
+ case PRB_FILTER_LUKS:
+ if (blk_superblocks_filter_luks(h)) {
+ r = -EINVAL;
+ goto out;
+ }
+ /* fall-through */
+ case PRB_FILTER_NONE:
+ blk_set_chains_for_full_print(h);
+ break;
+ case PRB_ONLY_LUKS:
+ blk_set_chains_for_fast_detection(h);
+ if (blk_superblocks_only_luks(h)) {
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ while ((pr = blk_probe(h)) < PRB_EMPTY) {
+ if (blk_is_partition(h))
+ report_partition(blk_get_partition_type(h), device, batch_mode);
+ else if (blk_is_superblock(h))
+ report_superblock(blk_get_superblock_type(h), device, batch_mode);
+ else {
+ log_dbg("Internal tools_detect_signatures() error.");
+ r = -EINVAL;
+ goto out;
+ }
+ (*count)++;
+ }
+
+ if (pr == PRB_FAIL)
+ r = -EINVAL;
+out:
+ blk_free(h);
+ return r;
+}
+
+int tools_wipe_all_signatures(const char *path, bool exclusive, bool only_luks)
+{
+ int fd, flags, r;
+ blk_probe_status pr;
+ struct stat st;
+ struct blkid_handle *h = NULL;
+
+ if (!blk_supported()) {
+ log_dbg("Blkid support disabled.");
+ return 0;
+ }
+
+ if (stat(path, &st)) {
+ log_err(_("Failed to stat device %s."), path);
+ return -EINVAL;
+ }
+
+ flags = O_RDWR;
+ if (S_ISBLK(st.st_mode) && exclusive)
+ flags |= O_EXCL;
+
+ /* better than opening regular file with O_EXCL (undefined) */
+ /* coverity[toctou] */
+ fd = open(path, flags); /* lgtm[cpp/toctou-race-condition] */
+ if (fd < 0) {
+ if (errno == EBUSY)
+ log_err(_("Cannot exclusively open %s, device in use."), path);
+ else
+ log_err(_("Failed to open file %s in read/write mode."), path);
+ return -EINVAL;
+ }
+
+ if ((r = blk_init_by_fd(&h, fd))) {
+ log_err(_("Failed to initialize device signature probes."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ blk_set_chains_for_wipes(h);
+ if (only_luks && (r = blk_superblocks_only_luks(h))) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ while ((pr = blk_probe(h)) < PRB_EMPTY) {
+ if (blk_is_partition(h))
+ log_verbose(_("Existing '%s' partition signature on device %s will be wiped."),
+ blk_get_partition_type(h), path);
+ if (blk_is_superblock(h))
+ log_verbose(_("Existing '%s' superblock signature on device %s will be wiped."),
+ blk_get_superblock_type(h), path);
+ if (blk_do_wipe(h) || fsync(fd)) {
+ log_err(_("Failed to wipe device signature."));
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ if (pr != PRB_EMPTY) {
+ log_err(_("Failed to probe device %s for a signature."), path);
+ r = -EINVAL;
+ }
+out:
+ close(fd);
+ blk_free(h);
+ return r;
+}
+
+int tools_superblock_block_size(const char *device, char *sb_name, size_t sb_name_len, unsigned *r_block_size)
+{
+ struct blkid_handle *h;
+ const char *name;
+ int r = 0;
+
+ if (!r_block_size || !sb_name || sb_name_len < 1)
+ return -EINVAL;
+
+ if (!blk_supported()) {
+ log_dbg("Blkid support disabled.");
+ return 0;
+ }
+
+ if ((r = blk_init_by_path(&h, device))) {
+ log_err(_("Failed to initialize device signature probes."));
+ return -EINVAL;
+ }
+
+ blk_set_chains_for_superblocks(h);
+
+ switch (blk_probe(h)) {
+ case PRB_OK:
+ *r_block_size = blk_get_block_size(h);
+ if (!*r_block_size) /* same as not-found */
+ break;
+
+ if (!(name = blk_get_superblock_type(h))) {
+ r = -EINVAL;
+ break;
+ }
+
+ /* we don't mind truncating */
+ strncpy(sb_name, name, sb_name_len - 1);
+ sb_name[sb_name_len-1] = '\0';
+
+ log_dbg("Detected superblock %s on device %s (block size: %u).", sb_name, device, *r_block_size);
+ r = 1;
+ /* fall-through */
+ case PRB_EMPTY:
+ break;
+ default:
+ r = -EINVAL;
+ }
+
+ blk_free(h);
+
+ return r;
+}
+
+bool tools_blkid_supported(void)
+{
+ return blk_supported() != 0;
+}
diff --git a/src/utils_luks.c b/src/utils_luks.c
new file mode 100644
index 0000000..6a10ab6
--- /dev/null
+++ b/src/utils_luks.c
@@ -0,0 +1,274 @@
+/*
+ * Helper utilities for LUKS2 features
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2023 Milan Broz
+ * Copyright (C) 2018-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "cryptsetup.h"
+#include "cryptsetup_args.h"
+#include "utils_luks.h"
+
+extern const char *set_pbkdf;
+
+const char *luksType(const char *type)
+{
+ if (type && !strcmp(type, "luks2"))
+ return CRYPT_LUKS2;
+
+ if (type && !strcmp(type, "luks1"))
+ return CRYPT_LUKS1;
+
+ if (type && !strcmp(type, "luks"))
+ return CRYPT_LUKS; /* NULL */
+
+ if (type && *type)
+ return type;
+
+ return CRYPT_LUKS; /* NULL */
+}
+
+bool isLUKS1(const char *type)
+{
+ return type && !strcmp(type, CRYPT_LUKS1);
+}
+
+bool isLUKS2(const char *type)
+{
+ return type && !strcmp(type, CRYPT_LUKS2);
+}
+
+int verify_passphrase(int def)
+{
+ /* Batch mode switch off verify - if not overridden by -y */
+ if (ARG_SET(OPT_VERIFY_PASSPHRASE_ID))
+ def = 1;
+ else if (ARG_SET(OPT_BATCH_MODE_ID))
+ def = 0;
+
+ /* Non-tty input doesn't allow verify */
+ if (def && !isatty(STDIN_FILENO)) {
+ if (ARG_SET(OPT_VERIFY_PASSPHRASE_ID))
+ log_err(_("Can't do passphrase verification on non-tty inputs."));
+ def = 0;
+ }
+
+ return def;
+}
+
+void set_activation_flags(uint32_t *flags)
+{
+ if (ARG_SET(OPT_READONLY_ID))
+ *flags |= CRYPT_ACTIVATE_READONLY;
+
+ if (ARG_SET(OPT_ALLOW_DISCARDS_ID))
+ *flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
+
+ if (ARG_SET(OPT_PERF_SAME_CPU_CRYPT_ID))
+ *flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
+
+ if (ARG_SET(OPT_PERF_SUBMIT_FROM_CRYPT_CPUS_ID))
+ *flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
+
+ if (ARG_SET(OPT_PERF_NO_READ_WORKQUEUE_ID))
+ *flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
+
+ if (ARG_SET(OPT_PERF_NO_WRITE_WORKQUEUE_ID))
+ *flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
+
+ if (ARG_SET(OPT_INTEGRITY_NO_JOURNAL_ID))
+ *flags |= CRYPT_ACTIVATE_NO_JOURNAL;
+
+ /* In persistent mode, we use what is set on command line */
+ if (ARG_SET(OPT_PERSISTENT_ID))
+ *flags |= CRYPT_ACTIVATE_IGNORE_PERSISTENT;
+
+ /* Only for LUKS2 but ignored elsewhere */
+ if (ARG_SET(OPT_TEST_PASSPHRASE_ID) &&
+ (ARG_SET(OPT_KEY_SLOT_ID) || ARG_SET(OPT_UNBOUND_ID)))
+ *flags |= CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY;
+
+ if (ARG_SET(OPT_SERIALIZE_MEMORY_HARD_PBKDF_ID))
+ *flags |= CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF;
+
+ /* Only for plain */
+ if (ARG_SET(OPT_IV_LARGE_SECTORS_ID))
+ *flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
+}
+
+int set_pbkdf_params(struct crypt_device *cd, const char *dev_type)
+{
+ const struct crypt_pbkdf_type *pbkdf_default;
+ struct crypt_pbkdf_type pbkdf = {};
+
+ pbkdf_default = crypt_get_pbkdf_default(dev_type);
+ if (!pbkdf_default)
+ return -EINVAL;
+
+ pbkdf.type = set_pbkdf ?: pbkdf_default->type;
+ pbkdf.hash = ARG_STR(OPT_HASH_ID) ?: pbkdf_default->hash;
+ pbkdf.time_ms = ARG_UINT32(OPT_ITER_TIME_ID) ?: pbkdf_default->time_ms;
+ if (strcmp(pbkdf.type, CRYPT_KDF_PBKDF2)) {
+ pbkdf.max_memory_kb = ARG_UINT32(OPT_PBKDF_MEMORY_ID) ?: pbkdf_default->max_memory_kb;
+ pbkdf.parallel_threads = ARG_UINT32(OPT_PBKDF_PARALLEL_ID) ?: pbkdf_default->parallel_threads;
+ }
+
+ if (ARG_SET(OPT_PBKDF_FORCE_ITERATIONS_ID)) {
+ pbkdf.iterations = ARG_UINT32(OPT_PBKDF_FORCE_ITERATIONS_ID);
+ pbkdf.time_ms = 0;
+ pbkdf.flags |= CRYPT_PBKDF_NO_BENCHMARK;
+ }
+
+ return crypt_set_pbkdf_type(cd, &pbkdf);
+}
+
+int set_tries_tty(void)
+{
+ return (tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID)) && isatty(STDIN_FILENO)) ? ARG_UINT32(OPT_TRIES_ID) : 1;
+}
+
+int get_adjusted_key_size(const char *cipher_mode, uint32_t default_size_bits, int integrity_keysize)
+{
+ uint32_t keysize_bits = ARG_UINT32(OPT_KEY_SIZE_ID);
+
+#ifdef ENABLE_LUKS_ADJUST_XTS_KEYSIZE
+ if (!ARG_SET(OPT_KEY_SIZE_ID) && !strncmp(cipher_mode, "xts-", 4)) {
+ if (default_size_bits == 128)
+ keysize_bits = 256;
+ else if (default_size_bits == 256)
+ keysize_bits = 512;
+ }
+#endif
+ return (keysize_bits ?: default_size_bits) / 8 + integrity_keysize;
+}
+
+/*
+ * FIXME: 4MiBs is max LUKS2 mda length (including binary header).
+ * In future, read max allowed JSON size from config section.
+ */
+#define LUKS2_MAX_MDA_SIZE 0x400000
+int tools_read_json_file(const char *file, char **json, size_t *json_size, bool batch_mode)
+{
+ ssize_t ret;
+ int fd, block, r;
+ void *buf = NULL;
+
+ block = tools_signals_blocked();
+ if (block)
+ set_int_block(0);
+
+ if (tools_is_stdin(file)) {
+ fd = STDIN_FILENO;
+ log_dbg("STDIN descriptor JSON read requested.");
+ } else {
+ log_dbg("File descriptor JSON read requested.");
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ log_err(_("Failed to open file %s in read-only mode."), file);
+ r = -EINVAL;
+ goto out;
+ }
+ }
+
+ buf = malloc(LUKS2_MAX_MDA_SIZE);
+ if (!buf) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (isatty(fd) && !batch_mode)
+ log_std(_("Provide valid LUKS2 token JSON:\n"));
+
+ /* we expect JSON (string) */
+ r = 0;
+ ret = read_buffer_intr(fd, buf, LUKS2_MAX_MDA_SIZE - 1, &quit);
+ if (ret < 0) {
+ r = -EIO;
+ log_err(_("Failed to read JSON file."));
+ goto out;
+ }
+ check_signal(&r);
+ if (r) {
+ log_err(_("\nRead interrupted."));
+ goto out;
+ }
+
+ *json_size = (size_t)ret;
+ *json = buf;
+ *(*json + ret) = '\0';
+out:
+ if (block && !quit)
+ set_int_block(1);
+ if (fd >= 0 && fd != STDIN_FILENO)
+ close(fd);
+ if (r && buf) {
+ memset(buf, 0, LUKS2_MAX_MDA_SIZE);
+ free(buf);
+ }
+ return r;
+}
+
+int tools_write_json_file(const char *file, const char *json)
+{
+ int block, fd, r;
+ size_t json_len;
+ ssize_t ret;
+
+ if (!json || !(json_len = strlen(json)) || json_len >= LUKS2_MAX_MDA_SIZE)
+ return -EINVAL;
+
+ block = tools_signals_blocked();
+ if (block)
+ set_int_block(0);
+
+ if (tools_is_stdin(file)) {
+ fd = STDOUT_FILENO;
+ log_dbg("STDOUT descriptor JSON write requested.");
+ } else {
+ log_dbg("File descriptor JSON write requested.");
+ fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+ }
+
+ if (fd < 0) {
+ log_err(_("Failed to open file %s in write mode."), file ?: "");
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = 0;
+ ret = write_buffer_intr(fd, json, json_len, &quit);
+ check_signal(&r);
+ if (r) {
+ log_err(_("\nWrite interrupted."));
+ goto out;
+ }
+ if (ret < 0 || (size_t)ret != json_len) {
+ log_err(_("Failed to write JSON file."));
+ r = -EIO;
+ goto out;
+ }
+
+ if (isatty(fd))
+ (void) write_buffer_intr(fd, "\n", 1, &quit);
+out:
+ if (block && !quit)
+ set_int_block(1);
+ if (fd >=0 && fd != STDOUT_FILENO)
+ close(fd);
+ return r;
+}
diff --git a/src/utils_luks.h b/src/utils_luks.h
new file mode 100644
index 0000000..28220ab
--- /dev/null
+++ b/src/utils_luks.h
@@ -0,0 +1,52 @@
+/*
+ * Helper utilities for LUKS in cryptsetup
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2023 Milan Broz
+ * Copyright (C) 2018-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef UTILS_LUKS_H
+#define UTILS_LUKS_H
+
+#include <stdint.h>
+
+const char *luksType(const char *type);
+
+bool isLUKS1(const char *type);
+
+bool isLUKS2(const char *type);
+
+int verify_passphrase(int def);
+
+void set_activation_flags(uint32_t *flags);
+
+int set_pbkdf_params(struct crypt_device *cd, const char *dev_type);
+
+int set_tries_tty(void);
+
+int get_adjusted_key_size(const char *cipher_mode, uint32_t default_size_bits, int integrity_keysize);
+
+int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_passwordLen);
+
+int reencrypt(int action_argc, const char **action_argv);
+
+int reencrypt_luks1(const char *device);
+
+int reencrypt_luks1_in_progress(const char *device);
+
+#endif /* UTILS_LUKS_H */
diff --git a/src/utils_password.c b/src/utils_password.c
new file mode 100644
index 0000000..3374e18
--- /dev/null
+++ b/src/utils_password.c
@@ -0,0 +1,331 @@
+/*
+ * Password quality check wrapper
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "cryptsetup.h"
+#include <termios.h>
+
+#if defined ENABLE_PWQUALITY
+#include <pwquality.h>
+
+static int tools_check_pwquality(const char *password)
+{
+ int r;
+ void *auxerror;
+ pwquality_settings_t *pwq;
+
+ log_dbg("Checking new password using default pwquality settings.");
+ pwq = pwquality_default_settings();
+ if (!pwq)
+ return -EINVAL;
+
+ r = pwquality_read_config(pwq, NULL, &auxerror);
+ if (r) {
+ log_err(_("Cannot check password quality: %s"),
+ pwquality_strerror(NULL, 0, r, auxerror));
+ pwquality_free_settings(pwq);
+ return -EINVAL;
+ }
+
+ r = pwquality_check(pwq, password, NULL, NULL, &auxerror);
+ if (r < 0) {
+ log_err(_("Password quality check failed:\n %s"),
+ pwquality_strerror(NULL, 0, r, auxerror));
+ r = -EPERM;
+ } else
+ r = 0;
+
+ pwquality_free_settings(pwq);
+ return r;
+}
+#elif defined ENABLE_PASSWDQC
+#include <passwdqc.h>
+
+static int tools_check_passwdqc(const char *password)
+{
+ passwdqc_params_t params;
+ char *parse_reason = NULL;
+ const char *check_reason;
+ const char *config = PASSWDQC_CONFIG_FILE;
+ int r = -EINVAL;
+
+ passwdqc_params_reset(&params);
+
+ if (*config && passwdqc_params_load(&params, &parse_reason, config)) {
+ log_err(_("Cannot check password quality: %s"),
+ (parse_reason ? parse_reason : "Out of memory"));
+ goto out;
+ }
+
+ check_reason = passwdqc_check(&params.qc, password, NULL, NULL);
+ if (check_reason) {
+ log_err(_("Password quality check failed: Bad passphrase (%s)"),
+ check_reason);
+ r = -EPERM;
+ } else
+ r = 0;
+out:
+#if HAVE_PASSWDQC_PARAMS_FREE
+ passwdqc_params_free(&params);
+#endif
+ free(parse_reason);
+ return r;
+}
+#endif /* ENABLE_PWQUALITY || ENABLE_PASSWDQC */
+
+/* coverity[ +tainted_string_sanitize_content : arg-0 ] */
+static int tools_check_password(const char *password)
+{
+#if defined ENABLE_PWQUALITY
+ return tools_check_pwquality(password);
+#elif defined ENABLE_PASSWDQC
+ return tools_check_passwdqc(password);
+#else
+ return 0;
+#endif
+}
+
+/* Password reading helpers */
+
+/* coverity[ -taint_source : arg-1 ] */
+static ssize_t read_tty_eol(int fd, char *pass, size_t maxlen)
+{
+ bool eol = false;
+ size_t read_size = 0;
+ ssize_t r;
+
+ do {
+ r = read(fd, pass, maxlen - read_size);
+ if ((r == -1 && errno != EINTR) || quit)
+ return -1;
+ if (r >= 0) {
+ if (!r || pass[r-1] == '\n')
+ eol = true;
+ read_size += (size_t)r;
+ pass = pass + r;
+ }
+ } while (!eol && read_size != maxlen);
+
+ return (ssize_t)read_size;
+}
+
+/* The pass buffer is zeroed and has trailing \0 already " */
+static int untimed_read(int fd, char *pass, size_t maxlen, size_t *realsize)
+{
+ ssize_t i;
+
+ i = read_tty_eol(fd, pass, maxlen);
+ if (i > 0) {
+ if (pass[i-1] == '\n') {
+ pass[i-1] = '\0';
+ *realsize = i - 1;
+ } else
+ *realsize = i;
+ i = 0;
+ } else if (i == 0) /* empty input */
+ i = -1;
+
+ return i;
+}
+
+static int timed_read(int fd, char *pass, size_t maxlen, size_t *realsize, long timeout)
+{
+ struct timeval t;
+ fd_set fds = {}; /* Just to avoid scan-build false report for FD_SET */
+ int failed = -1;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ t.tv_sec = timeout;
+ t.tv_usec = 0;
+
+ if (select(fd+1, &fds, NULL, NULL, &t) > 0)
+ failed = untimed_read(fd, pass, maxlen, realsize);
+
+ return failed;
+}
+
+static int interactive_pass(const char *prompt, char *pass, size_t maxlen,
+ long timeout)
+{
+ struct termios orig, tmp;
+ int failed = -1;
+ int infd, outfd;
+ size_t realsize = 0;
+
+ if (maxlen < 1)
+ return failed;
+
+ /* Read and write to /dev/tty if available */
+ infd = open("/dev/tty", O_RDWR);
+ if (infd == -1) {
+ infd = STDIN_FILENO;
+ outfd = STDERR_FILENO;
+ } else
+ outfd = infd;
+
+ if (tcgetattr(infd, &orig))
+ goto out;
+
+ memcpy(&tmp, &orig, sizeof(tmp));
+ tmp.c_lflag &= ~ECHO;
+
+ if (prompt && write(outfd, prompt, strlen(prompt)) < 0)
+ goto out;
+
+ tcsetattr(infd, TCSAFLUSH, &tmp);
+ if (timeout)
+ failed = timed_read(infd, pass, maxlen, &realsize, timeout);
+ else
+ failed = untimed_read(infd, pass, maxlen, &realsize);
+ tcsetattr(infd, TCSAFLUSH, &orig);
+out:
+ if (!failed && write(outfd, "\n", 1)) {};
+
+ if (realsize == maxlen)
+ log_dbg("Read stopped at maximal interactive input length, passphrase can be trimmed.");
+
+ if (infd != STDIN_FILENO)
+ close(infd);
+ return failed;
+}
+
+static int crypt_get_key_tty(const char *prompt,
+ char **key, size_t *key_size,
+ int timeout, int verify)
+{
+ int key_size_max = DEFAULT_PASSPHRASE_SIZE_MAX;
+ int r = -EINVAL;
+ char *pass = NULL, *pass_verify = NULL;
+
+ *key = NULL;
+ *key_size = 0;
+
+ log_dbg("Interactive passphrase entry requested.");
+
+ pass = crypt_safe_alloc(key_size_max + 1);
+ if (!pass) {
+ log_err( _("Out of memory while reading passphrase."));
+ return -ENOMEM;
+ }
+
+ if (interactive_pass(prompt, pass, key_size_max, timeout)) {
+ log_err(_("Error reading passphrase from terminal."));
+ goto out;
+ }
+
+ if (verify) {
+ pass_verify = crypt_safe_alloc(key_size_max + 1);
+ if (!pass_verify) {
+ log_err(_("Out of memory while reading passphrase."));
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (interactive_pass(_("Verify passphrase: "),
+ pass_verify, key_size_max, timeout)) {
+ log_err(_("Error reading passphrase from terminal."));
+ goto out;
+ }
+
+ if (strncmp(pass, pass_verify, key_size_max)) {
+ log_err(_("Passphrases do not match."));
+ r = -EPERM;
+ goto out;
+ }
+ }
+
+ *key = pass;
+ /* coverity[string_null] (crypt_safe_alloc wipes string with additional \0) */
+ *key_size = strlen(pass);
+ r = 0;
+out:
+ crypt_safe_free(pass_verify);
+ if (r)
+ crypt_safe_free(pass);
+ return r;
+}
+
+/*
+ * Note: --key-file=- is interpreted as a read from a binary file (stdin)
+ * key_size_max == 0 means detect maximum according to input type (tty/file)
+ */
+int tools_get_key(const char *prompt,
+ char **key, size_t *key_size,
+ uint64_t keyfile_offset, size_t keyfile_size_max,
+ const char *key_file,
+ int timeout, int verify, int pwquality,
+ struct crypt_device *cd)
+{
+ char tmp[PATH_MAX], *backing_file;
+ int r = -EINVAL, block;
+
+ block = tools_signals_blocked();
+ if (block)
+ set_int_block(0);
+
+ if (tools_is_stdin(key_file)) {
+ if (isatty(STDIN_FILENO)) {
+ if (keyfile_offset) {
+ log_err(_("Cannot use offset with terminal input."));
+ } else {
+ r = 0;
+ if (!prompt && !crypt_get_device_name(cd))
+ r = snprintf(tmp, sizeof(tmp), _("Enter passphrase: "));
+ else if (!prompt) {
+ backing_file = crypt_loop_backing_file(crypt_get_device_name(cd));
+ r = snprintf(tmp, sizeof(tmp), _("Enter passphrase for %s: "), backing_file ?: crypt_get_device_name(cd));
+ free(backing_file);
+ }
+ if (r >= 0)
+ r = crypt_get_key_tty(prompt ?: tmp, key, key_size, timeout, verify);
+ else
+ r = -EINVAL;
+ }
+ } else {
+ log_dbg("STDIN descriptor passphrase entry requested.");
+ /* No keyfile means STDIN with EOL handling (\n will end input)). */
+ r = crypt_keyfile_device_read(cd, NULL, key, key_size,
+ keyfile_offset, keyfile_size_max,
+ key_file ? 0 : CRYPT_KEYFILE_STOP_EOL);
+ }
+ } else {
+ log_dbg("File descriptor passphrase entry requested.");
+ r = crypt_keyfile_device_read(cd, key_file, key, key_size,
+ keyfile_offset, keyfile_size_max, 0);
+ }
+
+ if (block && !quit)
+ set_int_block(1);
+
+ /* Check pwquality for password (not keyfile) */
+ if (pwquality && !key_file && !r)
+ r = tools_check_password(*key);
+
+ return r;
+}
+
+void tools_passphrase_msg(int r)
+{
+ if (r == -EPERM)
+ log_err(_("No key available with this passphrase."));
+ else if (r == -ENOENT)
+ log_err(_("No usable keyslot is available."));
+}
diff --git a/src/utils_progress.c b/src/utils_progress.c
new file mode 100644
index 0000000..76b1818
--- /dev/null
+++ b/src/utils_progress.c
@@ -0,0 +1,301 @@
+/*
+ * cryptsetup - progress output utilities
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <assert.h>
+#include "cryptsetup.h"
+
+#define MINUTES_90 UINT64_C(5400000000) /* 90 minutes in microseconds */
+#define HOURS_36 UINT64_C(129600000000) /* 36 hours in microseconds */
+
+#define MINUTES(A) (A) / UINT64_C(60000000) /* microseconds to minutes */
+#define SECONDS(A) (A) / UINT64_C(1000000) /* microseconds to seconds */
+#define HOURS(A) (A) / UINT64_C(3600000000) /* microseconds to hours */
+#define DAYS(A) (A) / UINT64_C(86400000000) /* microseconds to days */
+
+#define REMAIN_SECONDS(A) (SECONDS((A))) % 60
+#define REMAIN_MINUTES(A) (MINUTES((A))) % 60
+
+/* The difference in microseconds between two times in "timeval" format. */
+static uint64_t time_diff(struct timeval *start, struct timeval *end)
+{
+ return (end->tv_sec - start->tv_sec) * UINT64_C(1000000)
+ + (end->tv_usec - start->tv_usec);
+}
+
+static void tools_clear_line(void)
+{
+ /* vt100 code clear line */
+ log_std("\33[2K\r");
+}
+
+static void bytes_to_units(uint64_t *bytes, const char **units)
+{
+ if (*bytes < (UINT64_C(1) << 32)) { /* less than 4 GiBs */
+ *units = "MiB";
+ *bytes >>= 20;
+ } else if (*bytes < (UINT64_C(1) << 42)) { /* less than 4 TiBs */
+ *units = "GiB";
+ *bytes >>= 30;
+ } else if (*bytes < (UINT64_C(1) << 52)) { /* less than 4 PiBs */
+ *units = "TiB";
+ *bytes >>= 40;
+ } else if (*bytes < (UINT64_C(1) << 62)) { /* less than 4 EiBs */
+ *units = "PiB";
+ *bytes >>= 50;
+ } else {
+ *units = "EiB";
+ *bytes >>= 60;
+ }
+}
+
+static bool time_to_human_string(uint64_t usecs, char *buf, size_t buf_len)
+{
+ ssize_t r;
+
+ if (usecs < MINUTES_90)
+ r = snprintf(buf, buf_len, _("%02" PRIu64 "m%02" PRIu64 "s"), MINUTES(usecs), REMAIN_SECONDS(usecs));
+ else if (usecs < HOURS_36)
+ r = snprintf(buf, buf_len, _("%02" PRIu64 "h%02" PRIu64 "m%02" PRIu64 "s"), HOURS(usecs), REMAIN_MINUTES(usecs), REMAIN_SECONDS(usecs));
+ else
+ r = snprintf(buf, buf_len, _("%02" PRIu64 " days"), DAYS(usecs));
+
+ if (r < 0 || (size_t)r >= buf_len)
+ return false;
+
+ return true;
+}
+
+static void log_progress(uint64_t bytes, uint64_t device_size, uint64_t eta, double uib, const char *ustr, const char *eol)
+{
+ double progress;
+ int r;
+ const char *units;
+ char time[128], written[128], speed[128];
+
+ /*
+ * TRANSLATORS: 'time' string with examples:
+ * "12m44s" : meaning 12 minutes 44 seconds
+ * "26h12m44s" : meaning 26 hours 12 minutes 44 seconds
+ * "3 days"
+ */
+ if (!time_to_human_string(eta, time, sizeof(time)))
+ return;
+
+ progress = (double)bytes / device_size * 100.0;
+
+ bytes_to_units(&bytes, &units);
+ r = snprintf(written, sizeof(written), _("%4" PRIu64 " %s written"), bytes, units);
+ if (r < 0 || (size_t)r >= sizeof(written))
+ return;
+
+ r = snprintf(speed, sizeof(speed), _("speed %5.1f %s/s"), uib, ustr);
+ if (r < 0 || (size_t)r >= sizeof(speed))
+ return;
+
+ /*
+ * TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+ * to get translated as well. 'eol' is always new-line or empty.
+ * See above.
+ */
+ log_std(_("Progress: %5.1f%%, ETA %s, %s, %s%s"),
+ progress, time, written, speed, eol);
+}
+
+static void log_progress_final(uint64_t time_spent, uint64_t bytes, double uib, const char *ustr)
+{
+ int r;
+ const char *units;
+ char time[128], written[128], speed[128];
+
+ /*
+ * TRANSLATORS: 'time' string with examples:
+ * "12m44s" : meaning 12 minutes 44 seconds
+ * "26h12m44s" : meaning 26 hours 12 minutes 44 seconds
+ * "3 days"
+ */
+ if (!time_to_human_string(time_spent, time, sizeof(time)))
+ return;
+
+ bytes_to_units(&bytes, &units);
+ r = snprintf(written, sizeof(written) - 1, _("%4" PRIu64 " %s written"), bytes, units);
+ if (r < 0 || (size_t)r >= sizeof(written))
+ return;
+
+ r = snprintf(speed, sizeof(speed) - 1, _("speed %5.1f %s/s"), uib, ustr);
+ if (r < 0 || (size_t)r >= sizeof(speed))
+ return;
+
+ /*
+ * TRANSLATORS: 'time', 'written' and 'speed' string are supposed
+ * to get translated as well. See above
+ */
+ log_std(_("Finished, time %s, %s, %s\n"), time, written, speed);
+}
+
+static bool calculate_tdiff(bool final, uint64_t bytes, struct tools_progress_params *parms, double *r_tdiff)
+{
+ uint64_t frequency;
+ struct timeval now_time;
+
+ assert(r_tdiff);
+
+ gettimeofday(&now_time, NULL);
+ if (parms->start_time.tv_sec == 0 && parms->start_time.tv_usec == 0) {
+ parms->start_time = now_time;
+ parms->end_time = now_time;
+ parms->start_offset = bytes;
+ return false;
+ }
+
+ if (parms->frequency)
+ frequency = parms->frequency * UINT64_C(1000000);
+ else
+ frequency = 500000;
+
+ if (!final && time_diff(&parms->end_time, &now_time) < frequency)
+ return false;
+
+ parms->end_time = now_time;
+
+ *r_tdiff = time_diff(&parms->start_time, &parms->end_time) / 1E6;
+ if (!*r_tdiff)
+ return false;
+
+ return true;
+}
+
+static void tools_time_progress(uint64_t device_size, uint64_t bytes, struct tools_progress_params *parms)
+{
+ uint64_t eta;
+ double tdiff, uib;
+ const char *eol, *ustr;
+ bool final = (bytes == device_size);
+
+ if (!calculate_tdiff(final, bytes, parms, &tdiff))
+ return;
+
+ if (parms->frequency)
+ eol = "\n";
+ else
+ eol = "";
+
+ uib = (double)(bytes - parms->start_offset) / tdiff;
+
+ eta = (uint64_t)((device_size / uib - tdiff) * 1E6);
+
+ if (uib > 1073741824.0f) {
+ uib /= 1073741824.0f;
+ ustr = "GiB";
+ } else if (uib > 1048576.0f) {
+ uib /= 1048576.0f;
+ ustr = "MiB";
+ } else if (uib > 1024.0f) {
+ uib /= 1024.0f;
+ ustr = "KiB";
+ } else
+ ustr = "B";
+
+ if (!parms->frequency)
+ tools_clear_line();
+
+ if (final)
+ log_progress_final((uint64_t)(tdiff * 1E6), bytes, uib, ustr);
+ else
+ log_progress(bytes, device_size, eta, uib, ustr, eol);
+
+ fflush(stdout);
+}
+
+static void log_progress_json(const char *device, uint64_t bytes, uint64_t device_size, uint64_t eta, uint64_t uib, uint64_t time_spent)
+{
+ int r;
+ char json[PATH_MAX+256];
+
+ r = snprintf(json, sizeof(json) - 1,
+ "{\"device\":\"%s\","
+ "\"device_bytes\":\"%" PRIu64 "\"," /* in bytes */
+ "\"device_size\":\"%" PRIu64 "\"," /* in bytes */
+ "\"speed\":\"%" PRIu64 "\"," /* in bytes per second */
+ "\"eta_ms\":\"%" PRIu64 "\"," /* in milliseconds */
+ "\"time_ms\":\"%" PRIu64 "\"}\n", /* in milliseconds */
+ device, bytes, device_size, uib, eta, time_spent);
+
+ if (r < 0 || (size_t)r >= sizeof(json) - 1)
+ return;
+
+ log_std("%s", json);
+}
+
+static void tools_time_progress_json(uint64_t device_size, uint64_t bytes, struct tools_progress_params *parms)
+{
+ double tdiff, uib;
+ bool final = (bytes == device_size);
+
+ if (!calculate_tdiff(final, bytes, parms, &tdiff))
+ return;
+
+ uib = (double)(bytes - parms->start_offset) / tdiff;
+
+ log_progress_json(parms->device,
+ bytes,
+ device_size,
+ final ? UINT64_C(0) : (uint64_t)((device_size / uib - tdiff) * 1E3),
+ (uint64_t)uib,
+ (uint64_t)(tdiff * 1E3));
+
+ fflush(stdout);
+}
+
+int tools_progress(uint64_t size, uint64_t offset, void *usrptr)
+{
+ int r = 0;
+ struct tools_progress_params *parms = (struct tools_progress_params *)usrptr;
+
+ if (parms && parms->json_output)
+ tools_time_progress_json(size, offset, parms);
+ else if (parms && !parms->batch_mode)
+ tools_time_progress(size, offset, parms);
+
+ check_signal(&r);
+ if (r) {
+ if (!parms || (!parms->frequency && !parms->json_output))
+ tools_clear_line();
+ if (parms && parms->interrupt_message)
+ log_err("%s", parms->interrupt_message);
+ }
+
+ return r;
+}
+
+const char *tools_get_device_name(const char *device, char **r_backing_file)
+{
+ char *bfile;
+
+ assert(r_backing_file);
+
+ bfile = crypt_loop_backing_file(device);
+ if (bfile) {
+ *r_backing_file = bfile;
+ return bfile;
+ }
+
+ return device;
+}
diff --git a/src/utils_reencrypt.c b/src/utils_reencrypt.c
new file mode 100644
index 0000000..a78557c
--- /dev/null
+++ b/src/utils_reencrypt.c
@@ -0,0 +1,1560 @@
+/*
+ * cryptsetup - action re-encryption utilities
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ * Copyright (C) 2021-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <uuid/uuid.h>
+
+#include "cryptsetup.h"
+#include "cryptsetup_args.h"
+#include "utils_luks.h"
+
+extern int64_t data_shift;
+extern const char *device_type;
+extern const char *set_pbkdf;
+
+enum device_status_info {
+ DEVICE_LUKS2 = 0, /* LUKS2 device */
+ DEVICE_LUKS2_REENCRYPT, /* LUKS2 device in reencryption */
+ DEVICE_LUKS1, /* LUKS1 device */
+ DEVICE_LUKS1_UNUSABLE, /* LUKS1 device in reencryption (legacy) */
+ DEVICE_NOT_LUKS, /* device is not LUKS type */
+ DEVICE_INVALID /* device is invalid */
+};
+
+static void _set_reencryption_flags(uint32_t *flags)
+{
+ if (ARG_SET(OPT_INIT_ONLY_ID))
+ *flags |= CRYPT_REENCRYPT_INITIALIZE_ONLY;
+
+ if (ARG_SET(OPT_RESUME_ONLY_ID))
+ *flags |= CRYPT_REENCRYPT_RESUME_ONLY;
+}
+
+static int reencrypt_check_passphrase(struct crypt_device *cd,
+ int keyslot,
+ const char *passphrase,
+ size_t passphrase_len)
+{
+ int r;
+
+ assert(cd);
+
+ r = crypt_activate_by_passphrase(cd, NULL, keyslot,
+ passphrase, passphrase_len, 0);
+ check_signal(&r);
+ tools_passphrase_msg(r);
+ tools_keyslot_msg(r, UNLOCKED);
+
+ return r;
+}
+
+static int set_keyslot_params(struct crypt_device *cd, int keyslot)
+{
+ const char *cipher;
+ struct crypt_pbkdf_type pbkdf;
+ size_t key_size;
+
+ cipher = crypt_keyslot_get_encryption(cd, keyslot, &key_size);
+ if (!cipher)
+ return -EINVAL;
+
+ if (crypt_is_cipher_null(cipher)) {
+ log_dbg("Keyslot %d uses cipher_null. "
+ "Replacing with default encryption in new keyslot.", keyslot);
+ cipher = DEFAULT_LUKS2_KEYSLOT_CIPHER;
+ key_size = DEFAULT_LUKS2_KEYSLOT_KEYBITS / 8;
+ }
+
+ if (crypt_keyslot_set_encryption(cd, cipher, key_size))
+ return -EINVAL;
+
+ /* if requested any of those just reinitialize context pbkdf */
+ if (set_pbkdf || ARG_SET(OPT_HASH_ID) || ARG_SET(OPT_PBKDF_FORCE_ITERATIONS_ID) ||
+ ARG_SET(OPT_ITER_TIME_ID))
+ return set_pbkdf_params(cd, CRYPT_LUKS2);
+
+ if (crypt_keyslot_get_pbkdf(cd, keyslot, &pbkdf))
+ return -EINVAL;
+
+ pbkdf.flags |= CRYPT_PBKDF_NO_BENCHMARK;
+
+ return crypt_set_pbkdf_type(cd, &pbkdf);
+}
+
+static int get_active_device_name(struct crypt_device *cd,
+ const char *data_device,
+ char **r_active_name)
+{
+ char *msg;
+ int r;
+
+ assert(data_device);
+
+ r = tools_lookup_crypt_device(cd, crypt_get_type(cd), data_device, r_active_name);
+ if (r > 0) {
+ log_dbg("Device %s has %d active holders.", data_device, r);
+
+ if (!*r_active_name) {
+ log_err(_("Device %s is still in use."), data_device);
+ return -EINVAL;
+ }
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ log_std(_("Auto-detected active dm device '%s' for data device %s.\n"),
+ *r_active_name, data_device);
+ } else if (r < 0) {
+ if (r != -ENOTBLK) {
+ log_err(_("Failed to auto-detect device %s holders."), data_device);
+ return -EINVAL;
+ }
+
+ r = -EINVAL;
+ if (!ARG_SET(OPT_BATCH_MODE_ID)) {
+ log_std(_("Device %s is not a block device.\n"), data_device);
+
+ r = asprintf(&msg, _("Unable to decide if device %s is activated or not.\n"
+ "Are you sure you want to proceed with reencryption in offline mode?\n"
+ "It may lead to data corruption if the device is actually activated.\n"
+ "To run reencryption in online mode, use --active-name parameter instead.\n"), data_device);
+ if (r < 0)
+ return -ENOMEM;
+ r = noDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
+ free(msg);
+ } else {
+ log_err(_("Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+ "Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."), data_device);
+ }
+ } else {
+ *r_active_name = NULL;
+ log_dbg("Device %s is unused. Proceeding with offline reencryption.", data_device);
+ }
+
+ return r;
+}
+
+static int reencrypt_get_active_name(struct crypt_device *cd,
+ const char *data_device,
+ char **r_active_name)
+{
+ assert(cd);
+ assert(r_active_name);
+
+ if (ARG_SET(OPT_ACTIVE_NAME_ID))
+ return (*r_active_name = strdup(ARG_STR(OPT_ACTIVE_NAME_ID))) ? 0 : -ENOMEM;
+
+ return get_active_device_name(cd, data_device, r_active_name);
+}
+
+static int decrypt_verify_and_set_params(struct crypt_params_reencrypt *params)
+{
+ const char *resilience;
+
+ assert(params);
+
+ if (!ARG_SET(OPT_RESILIENCE_ID))
+ return 0;
+
+ resilience = ARG_STR(OPT_RESILIENCE_ID);
+
+ if (!strcmp(resilience, "datashift") ||
+ !strcmp(resilience, "none")) {
+ log_err(_("Requested --resilience option cannot be applied "
+ "to current reencryption operation."));
+ return -EINVAL;
+ } else if (!strcmp(resilience, "journal"))
+ params->resilience = "datashift-journal";
+ else if (!strcmp(resilience, "checksum"))
+ params->resilience = "datashift-checksum";
+ else if (!strcmp(resilience, "datashift-checksum") ||
+ !strcmp(resilience, "datashift-journal"))
+ params->resilience = resilience;
+ else {
+ log_err(_("Unsupported resilience mode %s"), resilience);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int reencrypt_verify_and_update_params(struct crypt_params_reencrypt *params,
+ char **r_hash)
+{
+ assert(params);
+ assert(r_hash);
+
+ if (ARG_SET(OPT_ENCRYPT_ID) && params->mode != CRYPT_REENCRYPT_ENCRYPT) {
+ log_err(_("Device is not in LUKS2 encryption. Conflicting option --encrypt."));
+ return -EINVAL;
+ }
+
+ if (ARG_SET(OPT_DECRYPT_ID) && params->mode != CRYPT_REENCRYPT_DECRYPT) {
+ log_err(_("Device is not in LUKS2 decryption. Conflicting option --decrypt."));
+ return -EINVAL;
+ }
+
+ if (ARG_SET(OPT_RESILIENCE_ID)) {
+ if (!strcmp(params->resilience, "datashift") &&
+ strcmp(ARG_STR(OPT_RESILIENCE_ID), "datashift")) {
+ log_err(_("Device is in reencryption using datashift resilience. "
+ "Requested --resilience option cannot be applied."));
+ return -EINVAL;
+ }
+ if (strcmp(params->resilience, "datashift") &&
+ !strcmp(ARG_STR(OPT_RESILIENCE_ID), "datashift")) {
+ log_err(_("Requested --resilience option cannot be applied "
+ "to current reencryption operation."));
+ return -EINVAL;
+ }
+
+ if (!strncmp(params->resilience, "datashift-", 10)) {
+ /* decryption with datashift in progress */
+ if (decrypt_verify_and_set_params(params))
+ return -EINVAL;
+ } else if (!strncmp(ARG_STR(OPT_RESILIENCE_ID), "datashift-", 10)) {
+ log_err(_("Requested --resilience option cannot be applied "
+ "to current reencryption operation."));
+ return -EINVAL;
+ } else
+ params->resilience = ARG_STR(OPT_RESILIENCE_ID);
+
+ /* we have to copy hash string returned by API */
+ if (params->hash && !ARG_SET(OPT_RESILIENCE_HASH_ID)) {
+ /* r_hash owns the memory. Freed by caller */
+ *r_hash = strdup(params->hash);
+ if (!*r_hash)
+ return -ENOMEM;
+ params->hash = *r_hash;
+ }
+
+ /* Add default hash when switching to checksum based resilience */
+ if (!params->hash && !ARG_SET(OPT_RESILIENCE_HASH_ID) &&
+ (!strcmp(params->resilience, "checksum") ||
+ !strcmp(params->resilience, "datashift-checksum")))
+ params->hash = "sha256";
+
+ if (ARG_SET(OPT_RESILIENCE_HASH_ID))
+ params->hash = ARG_STR(OPT_RESILIENCE_HASH_ID);
+ } else
+ params->resilience = NULL;
+
+ params->max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE;
+ params->device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE;
+ params->flags = CRYPT_REENCRYPT_RESUME_ONLY;
+
+ return 0;
+}
+
+static int reencrypt_hint_force_offline_reencrypt(const char *data_device)
+{
+ struct stat st;
+
+ if (ARG_SET(OPT_ACTIVE_NAME_ID) ||
+ !ARG_SET(OPT_BATCH_MODE_ID) ||
+ ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID))
+ return 0;
+
+ if (stat(data_device, &st) == 0 && S_ISREG(st.st_mode)) {
+ log_err(_("Device %s is not a block device. Can not auto-detect if it is active or not.\n"
+ "Use --force-offline-reencrypt to bypass the check and run in offline mode (dangerous!)."), data_device);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int reencrypt_luks2_load(struct crypt_device *cd, const char *data_device)
+{
+ char *msg;
+ crypt_reencrypt_info ri;
+ int r;
+ size_t passwordLen;
+ char *active_name = NULL, *hash = NULL, *password = NULL;
+ struct crypt_params_reencrypt params = {};
+
+ ri = crypt_reencrypt_status(cd, &params);
+ if (ri == CRYPT_REENCRYPT_CRASH)
+ log_err(_("Device requires reencryption recovery. Run repair first."));
+
+ if (ri != CRYPT_REENCRYPT_CLEAN)
+ return -EINVAL;
+
+ r = reencrypt_verify_and_update_params(&params, &hash);
+ if (r < 0)
+ return r;
+
+ r = reencrypt_hint_force_offline_reencrypt(data_device);
+ if (r < 0)
+ goto out;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID) && !ARG_SET(OPT_RESUME_ONLY_ID)) {
+ r = asprintf(&msg, _("Device %s is already in LUKS2 reencryption. "
+ "Do you wish to resume previously initialised operation?"),
+ crypt_get_metadata_device_name(cd) ?: data_device);
+ if (r < 0) {
+ r = -ENOMEM;
+ goto out;
+ }
+ r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
+ free(msg);
+ if (r < 0)
+ goto out;
+ }
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID),
+ ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, cd);
+ if (r < 0)
+ goto out;
+
+ if (!ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID))
+ r = reencrypt_get_active_name(cd, data_device, &active_name);
+ if (r >= 0)
+ r = crypt_reencrypt_init_by_passphrase(cd, active_name, password,
+ passwordLen, ARG_INT32(OPT_KEY_SLOT_ID),
+ ARG_INT32(OPT_KEY_SLOT_ID), NULL, NULL, &params);
+out:
+ free(hash);
+ crypt_safe_free(password);
+ free(active_name);
+ return r;
+}
+
+/*
+ * 1: in-progress
+ * 0: clean luks2 device
+ * < 0: error
+ */
+static int luks2_reencrypt_in_progress(struct crypt_device *cd)
+{
+ uint32_t flags;
+
+ if (crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags))
+ return -EINVAL;
+
+ if (flags & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT) {
+ log_err(_("Legacy LUKS2 reencryption is no longer supported."));
+ return -EINVAL;
+ }
+
+ return flags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
+}
+
+/*
+ * Returns crypt context for:
+ * DEVICE_LUKS2
+ * DEVICE_LUKS2_REENCRYPT
+ * DEVICE_LUKS1
+ */
+static enum device_status_info load_luks(struct crypt_device **r_cd,
+ const char *header_device,
+ const char *data_device)
+{
+ int r;
+ struct crypt_device *cd;
+ struct stat st;
+
+ assert(r_cd);
+ assert(data_device);
+
+ if (header_device && stat(header_device, &st) < 0 && errno == ENOENT)
+ return DEVICE_NOT_LUKS;
+
+ if (crypt_init_data_device(&cd, uuid_or_device(header_device ?: data_device), data_device))
+ return DEVICE_INVALID;
+
+ if ((r = crypt_load(cd, CRYPT_LUKS, NULL))) {
+ crypt_free(cd);
+
+ if (r == -EBUSY) /* luks2 locking error (message printed by libcryptsetup) */
+ return DEVICE_INVALID;
+
+ r = reencrypt_luks1_in_progress(uuid_or_device(header_device ?: data_device));
+ if (!r)
+ return DEVICE_LUKS1_UNUSABLE;
+
+ return DEVICE_NOT_LUKS;
+ }
+
+ if (isLUKS2(crypt_get_type(cd))) {
+ r = luks2_reencrypt_in_progress(cd);
+ if (r < 0) {
+ crypt_free(cd);
+ return DEVICE_INVALID;
+ }
+ }
+
+ *r_cd = cd;
+
+ if (r > 0)
+ return DEVICE_LUKS2_REENCRYPT;
+
+ return isLUKS2(crypt_get_type(cd)) ? DEVICE_LUKS2 : DEVICE_LUKS1;
+}
+
+static bool luks2_reencrypt_eligible(struct crypt_device *cd)
+{
+ struct crypt_params_integrity ip = { 0 };
+
+ /* raw integrity info is available since 2.0 */
+ if (crypt_get_integrity_info(cd, &ip) || ip.tag_size) {
+ log_err(_("Reencryption of device with integrity profile is not supported."));
+ return false;
+ }
+
+ return true;
+}
+
+static enum device_status_info check_luks_device(const char *device)
+{
+ enum device_status_info dev_st;
+ struct crypt_device *cd = NULL;
+
+ dev_st = load_luks(&cd, NULL, device);
+ crypt_free(cd);
+
+ return dev_st;
+}
+
+static int reencrypt_check_data_sb_block_size(const char *data_device, uint32_t new_sector_size)
+{
+ int r;
+ char sb_name[32];
+ unsigned block_size;
+
+ assert(data_device);
+
+ r = tools_superblock_block_size(data_device, sb_name, sizeof(sb_name), &block_size);
+ if (r <= 0)
+ return r;
+
+ if (new_sector_size > block_size) {
+ log_err(_("Requested --sector-size %" PRIu32 " is incompatible with %s superblock\n"
+ "(block size: %" PRIu32 " bytes) detected on device %s."),
+ new_sector_size, sb_name, block_size, data_device);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int reencrypt_check_active_device_sb_block_size(const char *active_device, uint32_t new_sector_size)
+{
+ int r;
+ char dm_device[PATH_MAX];
+
+ r = snprintf(dm_device, sizeof(dm_device), "%s/%s", crypt_get_dir(), active_device);
+ if (r < 0 || (size_t)r >= sizeof(dm_device))
+ return -EINVAL;
+
+ return reencrypt_check_data_sb_block_size(dm_device, new_sector_size);
+}
+
+static int reencrypt_is_header_detached(const char *header_device, const char *data_device)
+{
+ int r;
+ struct stat st;
+ struct crypt_device *cd;
+
+ if (!header_device)
+ return 0;
+
+ if (header_device && stat(header_device, &st) < 0 && errno == ENOENT)
+ return 1;
+
+ if ((r = crypt_init_data_device(&cd, header_device, data_device)))
+ return r;
+
+ r = crypt_header_is_detached(cd);
+ crypt_free(cd);
+ return r;
+}
+
+static int encrypt_luks2_init(struct crypt_device **cd, const char *data_device, const char *device_name)
+{
+ int keyslot, r, fd;
+ uuid_t uuid;
+ size_t passwordLen;
+ char *tmp, uuid_str[37], header_file[PATH_MAX] = { 0 }, *password = NULL;
+ uint32_t activate_flags = 0;
+ const struct crypt_params_luks2 luks2_params = {
+ .sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID) ?: SECTOR_SIZE
+ };
+ struct crypt_params_reencrypt params = {
+ .mode = CRYPT_REENCRYPT_ENCRYPT,
+ .direction = data_shift < 0 ? CRYPT_REENCRYPT_BACKWARD : CRYPT_REENCRYPT_FORWARD,
+ .resilience = ARG_STR(OPT_RESILIENCE_ID) ?: "checksum",
+ .hash = ARG_STR(OPT_RESILIENCE_HASH_ID) ?: "sha256",
+ .max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE,
+ .device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE,
+ .luks2 = &luks2_params,
+ .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY
+ };
+
+ _set_reencryption_flags(&params.flags);
+
+ if (!data_shift) {
+ r = reencrypt_is_header_detached(ARG_STR(OPT_HEADER_ID), data_device);
+ if (r < 0)
+ return r;
+ if (!r) {
+ log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
+ return -ENOTSUP;
+ }
+ }
+
+ if (!ARG_SET(OPT_HEADER_ID) && ARG_UINT64(OPT_OFFSET_ID) &&
+ data_shift && (ARG_UINT64(OPT_OFFSET_ID) > (uint64_t)(imaxabs(data_shift) / (2 * SECTOR_SIZE)))) {
+ log_err(_("Requested data offset must be less than or equal to half of --reduce-device-size parameter."));
+ return -EINVAL;
+ }
+
+ /* TODO: ask user to confirm. It's useless to do data device reduction and than use smaller value */
+ if (!ARG_SET(OPT_HEADER_ID) && ARG_UINT64(OPT_OFFSET_ID) &&
+ data_shift && (ARG_UINT64(OPT_OFFSET_ID) < (uint64_t)(imaxabs(data_shift) / (2 * SECTOR_SIZE)))) {
+ data_shift = -(ARG_UINT64(OPT_OFFSET_ID) * 2 * SECTOR_SIZE);
+ if (data_shift >= 0)
+ return -EINVAL;
+ log_std(_("Adjusting --reduce-device-size value to twice the --offset %" PRIu64 " (sectors).\n"), ARG_UINT64(OPT_OFFSET_ID) * 2);
+ }
+
+ if (ARG_SET(OPT_UUID_ID) && uuid_parse(ARG_STR(OPT_UUID_ID), uuid) == -1) {
+ log_err(_("Wrong LUKS UUID format provided."));
+ return -EINVAL;
+ }
+
+ if (ARG_SET(OPT_SECTOR_SIZE_ID)) {
+ r = reencrypt_check_data_sb_block_size(data_device, ARG_UINT32(OPT_SECTOR_SIZE_ID));
+ if (r < 0)
+ return r;
+ }
+
+ if (!ARG_SET(OPT_UUID_ID)) {
+ uuid_generate(uuid);
+ uuid_unparse(uuid, uuid_str);
+ if (!(tmp = strdup(uuid_str)))
+ return -ENOMEM;
+ ARG_SET_STR(OPT_UUID_ID, tmp);
+ }
+
+ if (!ARG_SET(OPT_HEADER_ID)) {
+ r = snprintf(header_file, sizeof(header_file), "LUKS2-temp-%s.new", ARG_STR(OPT_UUID_ID));
+ if (r < 0 || (size_t)r >= sizeof(header_file))
+ return -EINVAL;
+
+ fd = open(header_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
+ if (fd == -1) {
+ if (errno == EEXIST)
+ log_err(_("Temporary header file %s already exists. Aborting."), header_file);
+ else
+ log_err(_("Cannot create temporary header file %s."), header_file);
+ return -EINVAL;
+ }
+
+ r = posix_fallocate(fd, 0, 4096);
+ close(fd);
+ if (r) {
+ log_err(_("Cannot create temporary header file %s."), header_file);
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!(tmp = strdup(header_file))) {
+ r = -ENOMEM;
+ goto out;
+ }
+ ARG_SET_STR(OPT_HEADER_ID, tmp);
+
+ /*
+ * FIXME: just override offset here, but we should support both.
+ * offset and implicit offset via data shift (lvprepend?)
+ */
+ if (!ARG_UINT64(OPT_OFFSET_ID))
+ ARG_SET_UINT64(OPT_OFFSET_ID, imaxabs(data_shift) / (2 * SECTOR_SIZE));
+ data_shift >>= 1;
+ params.flags |= CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT;
+ } else if (data_shift < 0) {
+ if (!ARG_SET(OPT_LUKS2_METADATA_SIZE_ID))
+ ARG_SET_UINT64(OPT_LUKS2_METADATA_SIZE_ID, 0x4000); /* missing default here */
+ if (!ARG_SET(OPT_LUKS2_KEYSLOTS_SIZE_ID))
+ ARG_SET_UINT64(OPT_LUKS2_KEYSLOTS_SIZE_ID, -data_shift - 2 * ARG_UINT64(OPT_LUKS2_METADATA_SIZE_ID));
+ if (2 * ARG_UINT64(OPT_LUKS2_METADATA_SIZE_ID) + ARG_UINT64(OPT_LUKS2_KEYSLOTS_SIZE_ID) > (uint64_t)-data_shift) {
+ log_err(_("LUKS2 metadata size is larger than data shift value."));
+ return -EINVAL;
+ }
+ }
+
+ r = luksFormat(cd, &password, &passwordLen);
+ if (r < 0)
+ goto out;
+
+ if (!luks2_reencrypt_eligible(*cd)) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (data_shift) {
+ params.data_shift = imaxabs(data_shift) / SECTOR_SIZE,
+ params.resilience = "datashift";
+ }
+ keyslot = !ARG_SET(OPT_KEY_SLOT_ID) ? 0 : ARG_INT32(OPT_KEY_SLOT_ID);
+ r = crypt_reencrypt_init_by_passphrase(*cd, NULL, password, passwordLen,
+ CRYPT_ANY_SLOT, keyslot, crypt_get_cipher(*cd),
+ crypt_get_cipher_mode(*cd), &params);
+ if (r < 0) {
+ crypt_keyslot_destroy(*cd, keyslot);
+ goto out;
+ }
+
+ /* Restore temporary header in head of data device */
+ if (*header_file) {
+ crypt_free(*cd);
+ *cd = NULL;
+
+ r = crypt_init(cd, data_device);
+ if (!r)
+ r = crypt_header_restore(*cd, CRYPT_LUKS2, header_file);
+
+ if (r) {
+ log_err(_("Failed to place new header at head of device %s."), data_device);
+ goto out;
+ }
+ }
+
+ /* activate device */
+ if (device_name) {
+ set_activation_flags(&activate_flags);
+ r = crypt_activate_by_passphrase(*cd, device_name, ARG_INT32(OPT_KEY_SLOT_ID), password, passwordLen, activate_flags);
+ if (r >= 0)
+ log_std(_("%s/%s is now active and ready for online encryption.\n"), crypt_get_dir(), device_name);
+ }
+
+ if (r < 0)
+ goto out;
+
+ /* just load reencryption context to continue reencryption */
+ if (!ARG_SET(OPT_INIT_ONLY_ID)) {
+ params.flags &= ~CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ r = crypt_reencrypt_init_by_passphrase(*cd, device_name, password, passwordLen,
+ CRYPT_ANY_SLOT, keyslot, NULL, NULL, &params);
+ }
+out:
+ crypt_safe_free(password);
+ if (*header_file)
+ unlink(header_file);
+ return r;
+}
+
+static enum device_status_info load_luks2_by_name(struct crypt_device **r_cd, const char *active_name, const char *header_device)
+{
+ int r;
+ struct crypt_device *cd;
+ struct stat st;
+
+ assert(r_cd);
+ assert(active_name);
+
+ if (header_device && stat(header_device, &st) < 0 && errno == ENOENT)
+ return DEVICE_NOT_LUKS;
+
+ r = crypt_init_by_name_and_header(&cd, active_name, header_device);
+ if (r)
+ return DEVICE_INVALID;
+
+ if (!isLUKS2(crypt_get_type(cd))) {
+ log_err(_("Active device %s is not LUKS2."), active_name);
+ crypt_free(cd);
+ return DEVICE_INVALID;
+ }
+
+ r = luks2_reencrypt_in_progress(cd);
+ if (r < 0) {
+ crypt_free(cd);
+ return DEVICE_INVALID;
+ }
+
+ *r_cd = cd;
+
+ return !r ? DEVICE_LUKS2 : DEVICE_LUKS2_REENCRYPT;
+}
+
+static int reencrypt_restore_header(struct crypt_device **cd,
+ const char *data_device, const char *header)
+{
+ int r;
+
+ assert(cd);
+ assert(data_device);
+ assert(header);
+
+ crypt_free(*cd);
+ *cd = NULL;
+
+ log_verbose(_("Restoring original LUKS2 header."));
+
+ r = crypt_init(cd, data_device);
+ if (r < 0)
+ return r;
+
+ r = crypt_header_restore(*cd, CRYPT_LUKS2, header);
+ if (r < 0)
+ log_err(_("Original LUKS2 header restore failed."));
+
+ return r;
+}
+
+static int decrypt_luks2_datashift_init(struct crypt_device **cd,
+ const char *data_device,
+ const char *expheader)
+{
+ int fd, r;
+ size_t passwordLen;
+ struct stat hdr_st;
+ bool remove_header = false;
+ char *msg, *active_name = NULL, *password = NULL;
+ struct crypt_params_reencrypt params = {
+ .mode = CRYPT_REENCRYPT_DECRYPT,
+ .direction = CRYPT_REENCRYPT_FORWARD,
+ .resilience = "datashift-checksum",
+ .hash = ARG_STR(OPT_RESILIENCE_HASH_ID) ?: "sha256",
+ .data_shift = crypt_get_data_offset(*cd),
+ .device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE,
+ .max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE,
+ .flags = CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+ };
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID)) {
+ r = asprintf(&msg, _("Header file %s does not exist. Do you want to initialize LUKS2 "
+ "decryption of device %s and export LUKS2 header to file %s?"),
+ expheader, data_device, expheader);
+ if (r < 0)
+ return -ENOMEM;
+ r = yesDialog(msg, _("Operation aborted.\n")) ? 0 : -EINVAL;
+ free(msg);
+ if (r < 0)
+ return r;
+ }
+
+ if ((r = decrypt_verify_and_set_params(&params)))
+ return r;
+
+ r = reencrypt_hint_force_offline_reencrypt(data_device);
+ if (r < 0)
+ return r;
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID),
+ ARG_STR(OPT_KEY_FILE_ID), ARG_UINT32(OPT_TIMEOUT_ID),
+ verify_passphrase(0), 0, *cd);
+ if (r < 0)
+ return r;
+
+ r = reencrypt_check_passphrase(*cd, ARG_INT32(OPT_KEY_SLOT_ID), password, passwordLen);
+ if (r < 0)
+ goto out;
+
+ r = crypt_header_backup(*cd, CRYPT_LUKS2, expheader);
+ if (r < 0)
+ goto out;
+
+ remove_header = true;
+
+ fd = open(expheader, O_RDONLY);
+ if (fd < 0)
+ goto out;
+
+ if (fstat(fd, &hdr_st)) {
+ close(fd);
+ r = -EINVAL;
+ goto out;
+ }
+
+ r = fchmod(fd, hdr_st.st_mode | S_IRUSR | S_IWUSR);
+ close(fd);
+ if (r) {
+ log_err(_("Failed to add read/write permissions to exported header file."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ crypt_free(*cd);
+ *cd = NULL;
+
+ /* reload with exported header */
+ if (ARG_SET(OPT_ACTIVE_NAME_ID)) {
+ if (load_luks2_by_name(cd, ARG_STR(OPT_ACTIVE_NAME_ID), expheader) != DEVICE_LUKS2) {
+ r = -EINVAL;
+ goto out;
+ }
+ } else {
+ if ((r = crypt_init_data_device(cd, expheader, data_device)))
+ goto out;
+ if ((r = crypt_load(*cd, CRYPT_LUKS2, NULL)))
+ goto out;
+ }
+
+ _set_reencryption_flags(&params.flags);
+
+ if (!ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID))
+ r = reencrypt_get_active_name(*cd, data_device, &active_name);
+
+ if (r < 0)
+ goto out;
+
+ r = tools_wipe_all_signatures(data_device, active_name == NULL, true);
+ if (r < 0) {
+ /* if header restore fails keep original header backup */
+ if (reencrypt_restore_header(cd, data_device, expheader) < 0)
+ remove_header = false;
+ goto out;
+ }
+
+ remove_header = false;
+
+ r = crypt_reencrypt_init_by_passphrase(*cd, active_name, password,
+ passwordLen, ARG_INT32(OPT_KEY_SLOT_ID), CRYPT_ANY_SLOT,
+ NULL, NULL, &params);
+
+ if (r < 0 && crypt_reencrypt_status(*cd, NULL) == CRYPT_REENCRYPT_NONE) {
+ /* if restore is successful we can remove header backup */
+ if (!reencrypt_restore_header(cd, data_device, expheader))
+ remove_header = true;
+ }
+out:
+ free(active_name);
+ crypt_safe_free(password);
+
+ if (r < 0 && !remove_header && !stat(expheader, &hdr_st) && S_ISREG(hdr_st.st_mode))
+ log_err(_("Reencryption initialization failed. Header backup is available in %s."),
+ expheader);
+ if (remove_header)
+ unlink(expheader);
+
+ return r;
+}
+
+static int decrypt_luks2_init(struct crypt_device *cd, const char *data_device)
+{
+ int r;
+ size_t passwordLen;
+ char *active_name = NULL, *password = NULL;
+ struct crypt_params_reencrypt params = {
+ .mode = CRYPT_REENCRYPT_DECRYPT,
+ .direction = data_shift > 0 ? CRYPT_REENCRYPT_FORWARD : CRYPT_REENCRYPT_BACKWARD,
+ .resilience = data_shift ? "datashift" : (ARG_STR(OPT_RESILIENCE_ID) ?: "checksum"),
+ .hash = ARG_STR(OPT_RESILIENCE_HASH_ID) ?: "sha256",
+ .data_shift = imaxabs(data_shift) / SECTOR_SIZE,
+ .device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE,
+ .max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE,
+ };
+
+ if (!luks2_reencrypt_eligible(cd))
+ return -EINVAL;
+
+ if ((!crypt_get_metadata_device_name(cd) || crypt_header_is_detached(cd) <= 0 ||
+ crypt_get_data_offset(cd) > 0)) {
+ log_err(_("LUKS2 decryption is supported with detached header device only (with data offset set to 0)."));
+ return -ENOTSUP;
+ }
+
+ r = reencrypt_hint_force_offline_reencrypt(data_device);
+ if (r < 0)
+ return r;
+
+ _set_reencryption_flags(&params.flags);
+
+ r = tools_get_key(NULL, &password, &passwordLen,
+ ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
+ ARG_UINT32(OPT_TIMEOUT_ID), verify_passphrase(0), 0, cd);
+ if (r < 0)
+ return r;
+
+ r = reencrypt_check_passphrase(cd, ARG_INT32(OPT_KEY_SLOT_ID), password, passwordLen);
+ if (r < 0)
+ goto out;
+
+ if (!ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID))
+ r = reencrypt_get_active_name(cd, data_device, &active_name);
+ if (r >= 0)
+ r = crypt_reencrypt_init_by_passphrase(cd, active_name, password,
+ passwordLen, ARG_INT32(OPT_KEY_SLOT_ID), CRYPT_ANY_SLOT, NULL, NULL, &params);
+
+out:
+ free(active_name);
+ crypt_safe_free(password);
+ return r;
+}
+
+struct keyslot_passwords {
+ char *password;
+ size_t passwordLen;
+ int new;
+};
+
+static struct keyslot_passwords *init_keyslot_passwords(size_t count)
+{
+ size_t i;
+ struct keyslot_passwords *tmp = calloc(count, sizeof(struct keyslot_passwords));
+
+ if (!tmp)
+ return tmp;
+
+ for (i = 0; i < count; i++)
+ tmp[i].new = -1;
+
+ return tmp;
+}
+
+static int init_passphrase(struct keyslot_passwords *kp, size_t keyslot_passwords_length,
+ struct crypt_device *cd, const char *msg, int slot_to_check)
+{
+ crypt_keyslot_info ki;
+ char *password;
+ int r = -EINVAL, retry_count;
+ size_t passwordLen;
+
+ if (slot_to_check != CRYPT_ANY_SLOT) {
+ ki = crypt_keyslot_status(cd, slot_to_check);
+ if (ki < CRYPT_SLOT_ACTIVE || ki == CRYPT_SLOT_UNBOUND)
+ return -ENOENT;
+ }
+
+ retry_count = set_tries_tty();
+
+ while (retry_count--) {
+ r = tools_get_key(msg, &password, &passwordLen, 0, 0,
+ ARG_STR(OPT_KEY_FILE_ID), 0, 0, 0 /*pwquality*/, cd);
+ if (r < 0)
+ return r;
+ if (quit) {
+ crypt_safe_free(password);
+ password = NULL;
+ passwordLen = 0;
+ return -EAGAIN;
+ }
+
+ r = crypt_activate_by_passphrase(cd, NULL, slot_to_check,
+ password, passwordLen, 0);
+ if (r < 0) {
+ crypt_safe_free(password);
+ password = NULL;
+ passwordLen = 0;
+ }
+ if (r < 0 && r != -EPERM)
+ return r;
+
+ if (r >= 0) {
+ tools_keyslot_msg(r, UNLOCKED);
+ if ((size_t)r >= keyslot_passwords_length) {
+ crypt_safe_free(password);
+ return -EINVAL;
+ }
+ kp[r].password = password;
+ kp[r].passwordLen = passwordLen;
+ break;
+ }
+ tools_passphrase_msg(r);
+ }
+
+ password = NULL;
+ passwordLen = 0;
+
+ return r;
+}
+
+static int _check_luks2_keyslots(struct crypt_device *cd, bool vk_change)
+{
+ int i, new_vk_slot = (vk_change ? 1 : 0), max = crypt_keyslot_max(CRYPT_LUKS2), active = 0, unbound = 0;
+
+ if (max < 0)
+ return max;
+
+ for (i = 0; i < max; i++) {
+ switch (crypt_keyslot_status(cd, i)) {
+ case CRYPT_SLOT_INVALID:
+ return -EINVAL;
+ case CRYPT_SLOT_ACTIVE:
+ /* fall-through */
+ case CRYPT_SLOT_ACTIVE_LAST:
+ active++;
+ break;
+ case CRYPT_SLOT_UNBOUND:
+ unbound++;
+ /* fall-through */
+ default:
+ break;
+ }
+ }
+
+ /* at least one keyslot for reencryption plus new volume key (if needed) */
+ if (active + unbound + new_vk_slot + 1 > max) {
+ log_err(_("Not enough free keyslots for reencryption."));
+ return -EINVAL;
+ }
+
+ if (!vk_change)
+ return 0;
+
+ if ((ARG_INT32(OPT_KEY_SLOT_ID) == CRYPT_ANY_SLOT) &&
+ (2 * active + unbound + 1 > max)) {
+ log_err(_("Not enough free keyslots for reencryption."));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fill_keyslot_passwords(struct crypt_device *cd,
+ struct keyslot_passwords *kp, size_t kp_size,
+ bool vk_change)
+{
+ char msg[128];
+ crypt_keyslot_info ki;
+ int i, r = 0;
+
+ if (vk_change && ARG_INT32(OPT_KEY_SLOT_ID) == CRYPT_ANY_SLOT && ARG_SET(OPT_KEY_FILE_ID)) {
+ for (i = 0; (size_t)i < kp_size; i++) {
+ ki = crypt_keyslot_status(cd, i);
+ if (ki == CRYPT_SLOT_INVALID)
+ return -EINVAL;
+ if (ki == CRYPT_SLOT_ACTIVE) {
+ log_err(_("Key file can be used only with --key-slot or with "
+ "exactly one key slot active."));
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (ARG_INT32(OPT_KEY_SLOT_ID) == CRYPT_ANY_SLOT) {
+ for (i = 0; (size_t)i < kp_size; i++) {
+ if (snprintf(msg, sizeof(msg), _("Enter passphrase for key slot %d: "), i) < 0)
+ return -EINVAL;
+ r = init_passphrase(kp, kp_size, cd, msg, i);
+ /* no need to initialize all keyslots with --keep-key */
+ if (r >= 0 && !vk_change)
+ break;
+ if (r == -ENOENT)
+ r = 0;
+ if (r < 0)
+ break;
+ }
+ } else {
+ if (snprintf(msg, sizeof(msg), _("Enter passphrase for key slot %u: "), ARG_INT32(OPT_KEY_SLOT_ID)) < 0)
+ return -EINVAL;
+ r = init_passphrase(kp, kp_size, cd, msg, ARG_INT32(OPT_KEY_SLOT_ID));
+ }
+
+ return r < 0 ? r : 0;
+}
+
+static int assign_tokens(struct crypt_device *cd, int keyslot_old, int keyslot_new)
+{
+ int token = 0, r = crypt_token_is_assigned(cd, token, keyslot_old);
+
+ while (r != -EINVAL) {
+ if (!r && (token != crypt_token_assign_keyslot(cd, token, keyslot_new)))
+ return -EINVAL;
+ token++;
+ r = crypt_token_is_assigned(cd, token, keyslot_old);
+ }
+
+ /* we reached max token number, exit */
+ return 0;
+}
+
+static int reencrypt_luks2_init(struct crypt_device *cd, const char *data_device)
+{
+ bool vk_size_change, sector_size_change, sector_size_increase, vk_change;
+ size_t i, vk_size, kp_size;
+ int r, keyslot_old = CRYPT_ANY_SLOT, keyslot_new = CRYPT_ANY_SLOT, key_size;
+ char cipher[MAX_CIPHER_LEN], mode[MAX_CIPHER_LEN], *vk = NULL, *active_name = NULL;
+ const char *new_cipher = NULL;
+ struct keyslot_passwords *kp = NULL;
+ struct crypt_params_luks2 luks2_params = {};
+ struct crypt_params_reencrypt params = {
+ .mode = CRYPT_REENCRYPT_REENCRYPT,
+ .direction = data_shift < 0 ? CRYPT_REENCRYPT_BACKWARD : CRYPT_REENCRYPT_FORWARD,
+ .resilience = data_shift ? "datashift" : (ARG_STR(OPT_RESILIENCE_ID) ?: "checksum"),
+ .hash = ARG_STR(OPT_RESILIENCE_HASH_ID) ?: "sha256",
+ .data_shift = imaxabs(data_shift) / SECTOR_SIZE,
+ .max_hotzone_size = ARG_UINT64(OPT_HOTZONE_SIZE_ID) / SECTOR_SIZE,
+ .device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID) / SECTOR_SIZE,
+ .luks2 = &luks2_params,
+ };
+
+ if (!luks2_reencrypt_eligible(cd))
+ return -EINVAL;
+
+ _set_reencryption_flags(&params.flags);
+
+ /* cipher */
+ if (ARG_SET(OPT_CIPHER_ID))
+ new_cipher = ARG_STR(OPT_CIPHER_ID);
+ else if (!ARG_SET(OPT_CIPHER_ID) && crypt_is_cipher_null(crypt_get_cipher(cd))) {
+ log_std(_("Switching data encryption cipher to %s.\n"), DEFAULT_CIPHER(LUKS1));
+ new_cipher = DEFAULT_CIPHER(LUKS1);
+ }
+
+ if (!new_cipher) {
+ strncpy(cipher, crypt_get_cipher(cd), MAX_CIPHER_LEN - 1);
+ strncpy(mode, crypt_get_cipher_mode(cd), MAX_CIPHER_LEN - 1);
+ cipher[MAX_CIPHER_LEN-1] = '\0';
+ mode[MAX_CIPHER_LEN-1] = '\0';
+ } else {
+ if ((r = crypt_parse_name_and_mode(new_cipher, cipher, NULL, mode))) {
+ log_err(_("No known cipher specification pattern detected."));
+ return r;
+ }
+
+ /* the segment cipher is identical with existing one */
+ if (!strcmp(cipher, crypt_get_cipher(cd)) && !strcmp(mode, crypt_get_cipher_mode(cd)))
+ new_cipher = NULL;
+ }
+
+ /* sector size */
+ luks2_params.sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID) ?: (uint32_t)crypt_get_sector_size(cd);
+ sector_size_change = luks2_params.sector_size != (uint32_t)crypt_get_sector_size(cd);
+ sector_size_increase = luks2_params.sector_size > (uint32_t)crypt_get_sector_size(cd);
+
+ /* key size */
+ if (ARG_SET(OPT_KEY_SIZE_ID) || new_cipher)
+ key_size = get_adjusted_key_size(mode, DEFAULT_LUKS1_KEYBITS, 0);
+ else
+ key_size = crypt_get_volume_key_size(cd);
+
+ if (!key_size)
+ return -EINVAL;
+ vk_size = key_size;
+
+ vk_size_change = key_size != crypt_get_volume_key_size(cd);
+
+ /* volume key */
+ vk_change = !ARG_SET(OPT_KEEP_KEY_ID);
+
+ if (vk_change && ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &vk, key_size);
+ if (r < 0)
+ goto out;
+
+ if (!crypt_volume_key_verify(cd, vk, key_size)) {
+ /* passed key was valid volume key */
+ vk_change = false;
+ crypt_safe_free(vk);
+ vk = NULL;
+ }
+ }
+
+ if (!vk_change && !vk_size_change && !new_cipher && !sector_size_change) {
+ log_err(_("No data segment parameters changed. Reencryption aborted."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (!ARG_SET(OPT_INIT_ONLY_ID) || (tools_blkid_supported() && sector_size_increase)) {
+ r = reencrypt_hint_force_offline_reencrypt(data_device);
+ if (r < 0)
+ goto out;
+ }
+
+ r = _check_luks2_keyslots(cd, vk_change);
+ if (r)
+ goto out;
+
+ r = crypt_keyslot_max(CRYPT_LUKS2);
+ if (r < 0)
+ goto out;
+ kp_size = r;
+
+ kp = init_keyslot_passwords(kp_size);
+ if (!kp) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ /* coverity[overrun-call] */
+ r = fill_keyslot_passwords(cd, kp, kp_size, vk_change);
+ if (r)
+ goto out;
+
+ r = -ENOENT;
+
+ for (i = 0; i < kp_size; i++) {
+ if (!vk_change) {
+ if (kp[i].password) {
+ r = keyslot_old = kp[i].new = i;
+ break;
+ }
+ continue;
+ }
+
+ if (kp[i].password && keyslot_new < 0) {
+ r = set_keyslot_params(cd, i);
+ if (r < 0)
+ break;
+ r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, vk, key_size,
+ kp[i].password, kp[i].passwordLen, CRYPT_VOLUME_KEY_NO_SEGMENT);
+ tools_keyslot_msg(r, CREATED);
+ if (r < 0)
+ break;
+
+ kp[i].new = r;
+ keyslot_new = r;
+ keyslot_old = i;
+ if (!vk) {
+ /* key generated in crypt_keyslot_add_by_key() call above */
+ vk = crypt_safe_alloc(key_size);
+ if (!vk) {
+ r = -ENOMEM;
+ break;
+ }
+ r = crypt_volume_key_get(cd, keyslot_new, vk, &vk_size, kp[i].password, kp[i].passwordLen);
+ if (r < 0)
+ break;
+ }
+ r = assign_tokens(cd, i, r);
+ if (r < 0)
+ break;
+ } else if (kp[i].password) {
+ r = set_keyslot_params(cd, i);
+ if (r < 0)
+ break;
+ r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, vk, key_size,
+ kp[i].password, kp[i].passwordLen, CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_DIGEST_REUSE);
+ tools_keyslot_msg(r, CREATED);
+ if (r < 0)
+ break;
+ kp[i].new = r;
+ r = assign_tokens(cd, i, r);
+ if (r < 0)
+ break;
+ }
+ }
+
+ if (r < 0)
+ goto out;
+
+ /*
+ * with --init-only lookup active device only if
+ * blkid probes are allowed and sector size increase
+ * is requested.
+ */
+ if (!ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID) &&
+ (!ARG_SET(OPT_INIT_ONLY_ID) || (tools_blkid_supported() && sector_size_increase))) {
+ r = reencrypt_get_active_name(cd, data_device, &active_name);
+ if (r < 0)
+ goto out;
+ }
+
+ if (sector_size_increase && !active_name && tools_blkid_supported() &&
+ !ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID)) {
+ log_err(_("Encryption sector size increase on offline device is not supported.\n"
+ "Activate the device first or use --force-offline-reencrypt option (dangerous!)."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (sector_size_increase && active_name) {
+ r = reencrypt_check_active_device_sb_block_size(active_name, luks2_params.sector_size);
+ if (r < 0)
+ goto out;
+ }
+
+ r = crypt_reencrypt_init_by_passphrase(cd,
+ ARG_SET(OPT_INIT_ONLY_ID) ? NULL : active_name,
+ kp[keyslot_old].password, kp[keyslot_old].passwordLen,
+ keyslot_old, kp[keyslot_old].new, cipher, mode, &params);
+out:
+ crypt_safe_free(vk);
+ if (kp) {
+ for (i = 0; i < kp_size; i++) {
+ crypt_safe_free(kp[i].password);
+ if (r < 0 && kp[i].new >= 0 && kp[i].new != (int)i &&
+ crypt_reencrypt_status(cd, NULL) == CRYPT_REENCRYPT_NONE &&
+ crypt_keyslot_destroy(cd, kp[i].new))
+ log_dbg("Failed to remove keyslot %d with unbound key.", kp[i].new);
+ }
+ free(kp);
+ }
+ free(active_name);
+ return r;
+}
+
+static int reencrypt_luks2_resume(struct crypt_device *cd)
+{
+ int r;
+ char *backing_file = NULL;
+ struct tools_progress_params prog_parms = {
+ .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID),
+ .batch_mode = ARG_SET(OPT_BATCH_MODE_ID),
+ .json_output = ARG_SET(OPT_PROGRESS_JSON_ID),
+ .interrupt_message = _("\nReencryption interrupted."),
+ .device = tools_get_device_name(crypt_get_device_name(cd), &backing_file)
+ };
+
+ if (ARG_SET(OPT_FORCE_OFFLINE_REENCRYPT_ID) && !ARG_SET(OPT_BATCH_MODE_ID))
+ log_std(_("Resuming LUKS reencryption in forced offline mode.\n"));
+
+ set_int_handler(0);
+ r = crypt_reencrypt_run(cd, tools_progress, &prog_parms);
+ free(backing_file);
+ return r;
+}
+
+static int check_broken_luks_signature(const char *device)
+{
+ int r;
+ size_t count;
+
+ r = tools_detect_signatures(device, PRB_ONLY_LUKS, &count, ARG_SET(OPT_BATCH_MODE_ID));
+ if (r < 0)
+ return -EINVAL;
+ if (count) {
+ log_err(_("Device %s contains broken LUKS metadata. Aborting operation."), device);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _encrypt(struct crypt_device *cd, const char *type, enum device_status_info dev_st, int action_argc, const char **action_argv)
+{
+ const char *device_ptr;
+ enum device_status_info data_dev_st;
+ struct stat st;
+ struct crypt_device *encrypt_cd = NULL;
+ int r = -EINVAL;
+
+ if (dev_st == DEVICE_LUKS2 || dev_st == DEVICE_LUKS1) {
+ log_err(_("Device %s is already LUKS device. Aborting operation."),
+ uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]));
+ return -EINVAL;
+ }
+
+ if (dev_st == DEVICE_NOT_LUKS &&
+ (!ARG_SET(OPT_HEADER_ID) || !stat(ARG_STR(OPT_HEADER_ID), &st))) {
+ device_ptr = ARG_SET(OPT_HEADER_ID) ? ARG_STR(OPT_HEADER_ID) : action_argv[0];
+ r = check_broken_luks_signature(device_ptr);
+ if (r < 0)
+ return r;
+ }
+
+ /* check data device type/state */
+ if (ARG_SET(OPT_HEADER_ID)) {
+ device_ptr = cd ? crypt_get_device_name(cd) : action_argv[0];
+ data_dev_st = check_luks_device(device_ptr);
+
+ if (data_dev_st == DEVICE_INVALID)
+ return -EINVAL;
+
+ if (data_dev_st == DEVICE_LUKS2 || data_dev_st == DEVICE_LUKS1) {
+ log_err(_("Device %s is already LUKS device. Aborting operation."),
+ device_ptr);
+ return -EINVAL;
+ }
+
+ if (data_dev_st == DEVICE_LUKS2_REENCRYPT || data_dev_st == DEVICE_LUKS1_UNUSABLE) {
+ log_err(_("Device %s is already in LUKS reencryption. Aborting operation."),
+ device_ptr);
+ return -EINVAL;
+ }
+
+ r = check_broken_luks_signature(device_ptr);
+ if (r < 0)
+ return r;
+ }
+
+ if (!type)
+ type = crypt_get_default_type();
+
+ if (dev_st == DEVICE_LUKS1_UNUSABLE || isLUKS1(type)) {
+ r = reencrypt_is_header_detached(ARG_STR(OPT_HEADER_ID), action_argv[0]);
+ if (r < 0)
+ return r;
+ if (!r && !ARG_SET(OPT_REDUCE_DEVICE_SIZE_ID)) {
+ log_err(_("Encryption without detached header (--header) is not possible without data device size reduction (--reduce-device-size)."));
+ return -ENOTSUP;
+ }
+ return reencrypt_luks1(action_argv[0]);
+ } else if (dev_st == DEVICE_NOT_LUKS) {
+ r = encrypt_luks2_init(&encrypt_cd, action_argv[0], action_argc > 1 ? action_argv[1] : NULL);
+ if (r < 0 || ARG_SET(OPT_INIT_ONLY_ID)) {
+ crypt_free(encrypt_cd);
+ return r;
+ }
+ cd = encrypt_cd;
+ dev_st = DEVICE_LUKS2_REENCRYPT;
+ } else if (dev_st == DEVICE_LUKS2_REENCRYPT &&
+ (r = reencrypt_luks2_load(cd, action_argv[0])) < 0)
+ return r;
+
+ if (dev_st != DEVICE_LUKS2_REENCRYPT)
+ return -EINVAL;
+
+ r = reencrypt_luks2_resume(cd);
+
+ crypt_free(encrypt_cd);
+ return r;
+}
+
+static int _decrypt(struct crypt_device **cd, enum device_status_info dev_st, const char *data_device)
+{
+ int r;
+ struct stat st;
+ bool export_header = false;
+
+ assert(cd);
+
+ if (dev_st == DEVICE_LUKS1 || dev_st == DEVICE_LUKS1_UNUSABLE)
+ return reencrypt_luks1(data_device);
+
+ /* header file does not exist, try loading device type from data device */
+ if (dev_st == DEVICE_NOT_LUKS && ARG_SET(OPT_HEADER_ID) &&
+ (stat(ARG_STR(OPT_HEADER_ID), &st) < 0) && errno == ENOENT) {
+ if (ARG_SET(OPT_ACTIVE_NAME_ID))
+ dev_st = load_luks2_by_name(cd, ARG_STR(OPT_ACTIVE_NAME_ID), NULL);
+ else
+ dev_st = load_luks(cd, NULL, uuid_or_device(data_device));
+
+ /*
+ * If data device is not LUKS2 report 'header is missing' error
+ * message user would get originally.
+ */
+ if (dev_st != DEVICE_LUKS2) {
+ log_err(_("Device %s does not exist or access denied."),
+ ARG_STR(OPT_HEADER_ID));
+ return -EINVAL;
+ }
+
+ export_header = true;
+ }
+
+ if (dev_st == DEVICE_LUKS2_REENCRYPT) {
+ if ((r = reencrypt_luks2_load(*cd, data_device)) < 0)
+ return r;
+ } else if (dev_st == DEVICE_LUKS2) {
+ if (!ARG_SET(OPT_HEADER_ID)) {
+ log_err(_("LUKS2 decryption requires --header option."));
+ return -EINVAL;
+ }
+
+ if (export_header)
+ r = decrypt_luks2_datashift_init(cd, data_device, ARG_STR(OPT_HEADER_ID));
+ else
+ r = decrypt_luks2_init(*cd, data_device);
+
+ if (r < 0 || ARG_SET(OPT_INIT_ONLY_ID))
+ return r;
+ } else if (dev_st == DEVICE_NOT_LUKS) {
+ log_err(_("Device %s is not a valid LUKS device."),
+ ARG_STR(OPT_HEADER_ID) ?: uuid_or_device(data_device));
+ return -EINVAL;
+ }
+
+ r = reencrypt_luks2_resume(*cd);
+ return r;
+}
+
+static int _reencrypt(struct crypt_device *cd, enum device_status_info dev_st, const char *data_device)
+{
+ int r;
+
+ if (dev_st == DEVICE_LUKS1 || dev_st == DEVICE_LUKS1_UNUSABLE)
+ return reencrypt_luks1(data_device);
+ else if (dev_st == DEVICE_LUKS2_REENCRYPT) {
+ if ((r = reencrypt_luks2_load(cd, data_device)) < 0)
+ return r;
+ } else if (dev_st == DEVICE_LUKS2) {
+ r = reencrypt_luks2_init(cd, data_device);
+ if (r < 0|| ARG_SET(OPT_INIT_ONLY_ID))
+ return r;
+ } else
+ return -EINVAL;
+
+ return reencrypt_luks2_resume(cd);
+}
+
+int reencrypt(int action_argc, const char **action_argv)
+{
+ enum device_status_info dev_st;
+ int r = -EINVAL;
+ struct crypt_device *cd = NULL;
+ const char *type = luksType(device_type);
+
+ if (action_argc < 1 && (!ARG_SET(OPT_ACTIVE_NAME_ID) || ARG_SET(OPT_ENCRYPT_ID))) {
+ log_err(_("Command requires device as argument."));
+ return r;
+ }
+
+ if (ARG_SET(OPT_ACTIVE_NAME_ID))
+ dev_st = load_luks2_by_name(&cd, ARG_STR(OPT_ACTIVE_NAME_ID), ARG_STR(OPT_HEADER_ID));
+ else
+ dev_st = load_luks(&cd, ARG_STR(OPT_HEADER_ID), uuid_or_device(action_argv[0]));
+
+ if (dev_st == DEVICE_INVALID)
+ return r;
+
+ if (dev_st == DEVICE_LUKS1 && isLUKS2(type)) {
+ log_err(_("Conflicting versions. Device %s is LUKS1."),
+ uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]));
+ goto out;
+ }
+
+ if (dev_st == DEVICE_LUKS1_UNUSABLE && isLUKS2(type)) {
+ log_err(_("Conflicting versions. Device %s is in LUKS1 reencryption."),
+ uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]));
+ goto out;
+ }
+
+ if (dev_st == DEVICE_LUKS2 && isLUKS1(type)) {
+ log_err(_("Conflicting versions. Device %s is LUKS2."),
+ uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]));
+ goto out;
+ }
+
+ if (dev_st == DEVICE_LUKS2_REENCRYPT && isLUKS1(type)) {
+ log_err(_("Conflicting versions. Device %s is in LUKS2 reencryption."),
+ uuid_or_device(ARG_STR(OPT_HEADER_ID) ?: action_argv[0]));
+ goto out;
+ }
+
+ if (dev_st == DEVICE_LUKS2_REENCRYPT && ARG_SET(OPT_INIT_ONLY_ID)) {
+ log_err(_("LUKS2 reencryption already initialized. Aborting operation."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (ARG_SET(OPT_RESUME_ONLY_ID) &&
+ (dev_st == DEVICE_LUKS2 || dev_st == DEVICE_LUKS1 || dev_st == DEVICE_NOT_LUKS)) {
+ log_err(_("Device reencryption not in progress."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (ARG_SET(OPT_ENCRYPT_ID))
+ r = _encrypt(cd, type, dev_st, action_argc, action_argv);
+ else if (ARG_SET(OPT_DECRYPT_ID))
+ r = _decrypt(&cd, dev_st, action_argv[0]);
+ else
+ r = _reencrypt(cd, dev_st, action_argv[0]);
+
+out:
+ crypt_free(cd);
+ return r;
+}
diff --git a/src/utils_reencrypt_luks1.c b/src/utils_reencrypt_luks1.c
new file mode 100644
index 0000000..ae849c0
--- /dev/null
+++ b/src/utils_reencrypt_luks1.c
@@ -0,0 +1,1354 @@
+/*
+ * cryptsetup - LUKS1 utility for offline re-encryption
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <uuid/uuid.h>
+
+#include "cryptsetup.h"
+#include "cryptsetup_args.h"
+#include "utils_luks.h"
+
+#define NO_UUID "cafecafe-cafe-cafe-cafe-cafecafeeeee"
+
+extern int64_t data_shift;
+
+#define MAX_SLOT 8
+
+struct reenc_ctx {
+ char *device;
+ char *device_header;
+ char *device_uuid;
+ const char *type;
+ uint64_t device_size; /* overridden by parameter */
+ uint64_t device_size_new_real;
+ uint64_t device_size_org_real;
+ uint64_t device_offset;
+ uint64_t device_shift;
+ uint64_t data_offset;
+
+ bool stained;
+ bool in_progress;
+ enum { FORWARD = 0, BACKWARD = 1 } reencrypt_direction;
+ enum { REENCRYPT = 0, ENCRYPT = 1, DECRYPT = 2 } reencrypt_mode;
+
+ char header_file_org[PATH_MAX];
+ char header_file_new[PATH_MAX];
+ char log_file[PATH_MAX];
+
+ char crypt_path_org[PATH_MAX];
+ char crypt_path_new[PATH_MAX];
+ int log_fd;
+ char log_buf[SECTOR_SIZE];
+
+ struct {
+ char *password;
+ size_t passwordLen;
+ } p[MAX_SLOT];
+ int keyslot;
+
+ uint64_t resume_bytes;
+};
+
+char MAGIC[] = {'L','U','K','S', 0xba, 0xbe};
+char NOMAGIC[] = {'L','U','K','S', 0xde, 0xad};
+int MAGIC_L = 6;
+
+typedef enum {
+ MAKE_UNUSABLE,
+ MAKE_USABLE,
+ CHECK_UNUSABLE,
+ CHECK_OPEN,
+} header_magic;
+
+static void _quiet_log(int level, const char *msg, void *usrptr)
+{
+ if (!ARG_SET(OPT_DEBUG_ID))
+ return;
+ tool_log(level, msg, usrptr);
+}
+
+static int alignment(int fd)
+{
+ int alignment;
+
+ alignment = fpathconf(fd, _PC_REC_XFER_ALIGN);
+ if (alignment < 0)
+ alignment = 4096;
+ return alignment;
+}
+
+static size_t pagesize(void)
+{
+ long r = sysconf(_SC_PAGESIZE);
+ return r < 0 ? 4096 : (size_t)r;
+}
+
+static const char *hdr_device(const struct reenc_ctx *rc)
+{
+ return rc->device_header ?: rc->device;
+}
+
+/* Depends on the first two fields of LUKS1 header format, magic and version */
+static int device_check(struct reenc_ctx *rc, const char *device, header_magic set_magic, bool exclusive)
+{
+ char *buf = NULL;
+ int r, devfd;
+ ssize_t s;
+ uint16_t version;
+ size_t buf_size = pagesize();
+ struct stat st;
+
+ if (stat(device, &st)) {
+ log_err(_("Cannot open device %s."), device);
+ return -EINVAL;
+ }
+
+ /* coverity[toctou] */
+ devfd = open(device, O_RDWR | ((S_ISBLK(st.st_mode) && exclusive) ? O_EXCL : 0)); /* lgtm[cpp/toctou-race-condition] */
+ if (devfd == -1) {
+ if (errno == EBUSY) {
+ log_err(_("Cannot exclusively open %s, device in use."),
+ device);
+ return -EBUSY;
+ }
+ log_err(_("Cannot open device %s."), device);
+ return -EINVAL;
+ }
+
+ if (set_magic == CHECK_OPEN) {
+ r = 0;
+ goto out;
+ }
+
+ if (posix_memalign((void *)&buf, alignment(devfd), buf_size)) {
+ log_err(_("Allocation of aligned memory failed."));
+ r = -ENOMEM;
+ goto out;
+ }
+
+ s = read(devfd, buf, buf_size);
+ if (s < 0 || s != (ssize_t)buf_size) {
+ log_err(_("Cannot read device %s."), device);
+ r = -EIO;
+ goto out;
+ }
+
+ /* Be sure that we do not process new version of header */
+ memcpy((void*)&version, &buf[MAGIC_L], sizeof(uint16_t));
+ version = be16_to_cpu(version);
+
+ if (set_magic == MAKE_UNUSABLE && !memcmp(buf, MAGIC, MAGIC_L) &&
+ version == 1) {
+ log_verbose(_("Marking LUKS1 device %s unusable."), device);
+ memcpy(buf, NOMAGIC, MAGIC_L);
+ r = 0;
+ } else if (set_magic == CHECK_UNUSABLE && version == 1) {
+ r = memcmp(buf, NOMAGIC, MAGIC_L) ? -EINVAL : 0;
+ if (rc && !r)
+ rc->device_uuid = strndup(&buf[0xa8], 40);
+ goto out;
+ } else
+ r = -EINVAL;
+
+ if (!r && version == 1) {
+ if (lseek(devfd, 0, SEEK_SET) == -1)
+ goto out;
+ s = write(devfd, buf, buf_size);
+ if (s < 0 || s != (ssize_t)buf_size || fsync(devfd) < 0) {
+ log_err(_("Cannot write device %s."), device);
+ r = -EIO;
+ }
+ if (rc && s > 0 && set_magic == MAKE_UNUSABLE)
+ rc->stained = true;
+ }
+ if (r)
+ log_dbg("LUKS signature check failed for %s.", device);
+out:
+ if (buf)
+ memset(buf, 0, buf_size);
+ free(buf);
+ close(devfd);
+ return r;
+}
+
+static int create_empty_header(const char *new_file)
+{
+ int fd, r = 0;
+
+ log_dbg("Creating empty file %s of size 4096.", new_file);
+
+ /* coverity[toctou] */
+ fd = open(new_file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
+ if (fd == -1 || posix_fallocate(fd, 0, 4096))
+ r = -EINVAL;
+ if (fd >= 0)
+ close(fd);
+
+ return r;
+}
+
+static int write_log(struct reenc_ctx *rc)
+{
+ ssize_t r;
+
+ memset(rc->log_buf, 0, SECTOR_SIZE);
+ if (snprintf(rc->log_buf, SECTOR_SIZE, "# LUKS reencryption log, DO NOT EDIT OR DELETE.\n"
+ "version = %d\nUUID = %s\ndirection = %d\nmode = %d\n"
+ "offset = %" PRIu64 "\nshift = %" PRIu64 "\n# EOF\n",
+ 2, rc->device_uuid, rc->reencrypt_direction, rc->reencrypt_mode,
+ rc->device_offset, rc->device_shift) < 0)
+ return -EINVAL;
+
+ if (lseek(rc->log_fd, 0, SEEK_SET) == -1)
+ return -EIO;
+
+ r = write(rc->log_fd, rc->log_buf, SECTOR_SIZE);
+ if (r < 0 || r != SECTOR_SIZE) {
+ log_err(_("Cannot write reencryption log file."));
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int parse_line_log(struct reenc_ctx *rc, const char *line)
+{
+ uint64_t u64;
+ int i;
+ char s[64];
+
+ /* whole line is comment */
+ if (*line == '#')
+ return 0;
+
+ if (sscanf(line, "version = %d", &i) == 1) {
+ if (i < 1 || i > 2) {
+ log_dbg("Log: Unexpected version = %i", i);
+ return -EINVAL;
+ }
+ } else if (sscanf(line, "UUID = %40s", s) == 1) {
+ if (!rc->device_uuid || strcmp(rc->device_uuid, s)) {
+ log_dbg("Log: Unexpected UUID %s", s);
+ return -EINVAL;
+ }
+ } else if (sscanf(line, "direction = %d", &i) == 1) {
+ log_dbg("Log: direction = %i", i);
+ rc->reencrypt_direction = i;
+ } else if (sscanf(line, "offset = %" PRIu64, &u64) == 1) {
+ log_dbg("Log: offset = %" PRIu64, u64);
+ rc->device_offset = u64;
+ } else if (sscanf(line, "shift = %" PRIu64, &u64) == 1) {
+ log_dbg("Log: shift = %" PRIu64, u64);
+ rc->device_shift = u64;
+ } else if (sscanf(line, "mode = %d", &i) == 1) { /* added in v2 */
+ log_dbg("Log: mode = %i", i);
+ rc->reencrypt_mode = i;
+ if (rc->reencrypt_mode != REENCRYPT &&
+ rc->reencrypt_mode != ENCRYPT &&
+ rc->reencrypt_mode != DECRYPT)
+ return -EINVAL;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+static int parse_log(struct reenc_ctx *rc)
+{
+ char *start, *end;
+ ssize_t s;
+
+ s = read(rc->log_fd, rc->log_buf, SECTOR_SIZE);
+ if (s == -1) {
+ log_err(_("Cannot read reencryption log file."));
+ return -EIO;
+ }
+
+ rc->log_buf[SECTOR_SIZE - 1] = '\0';
+ start = rc->log_buf;
+ do {
+ end = strchr(start, '\n');
+ if (end) {
+ *end++ = '\0';
+ if (parse_line_log(rc, start)) {
+ log_err(_("Wrong log format."));
+ return -EINVAL;
+ }
+ }
+
+ start = end;
+ } while (start);
+
+ return 0;
+}
+
+static void close_log(struct reenc_ctx *rc)
+{
+ log_dbg("Closing LUKS reencryption log file %s.", rc->log_file);
+ if (rc->log_fd != -1)
+ close(rc->log_fd);
+}
+
+static int open_log(struct reenc_ctx *rc)
+{
+ int flags = ARG_SET(OPT_USE_FSYNC_ID) ? O_SYNC : 0;
+
+ rc->log_fd = open(rc->log_file, O_RDWR|O_EXCL|O_CREAT|flags, S_IRUSR|S_IWUSR);
+ if (rc->log_fd != -1) {
+ log_dbg("Created LUKS reencryption log file %s.", rc->log_file);
+ rc->stained = 0;
+ } else if (errno == EEXIST) {
+ log_std(_("Log file %s exists, resuming reencryption.\n"), rc->log_file);
+ rc->log_fd = open(rc->log_file, O_RDWR|flags);
+ rc->in_progress = true;
+ }
+
+ if (rc->log_fd == -1)
+ return -EINVAL;
+
+ if (!rc->in_progress && write_log(rc) < 0) {
+ close_log(rc);
+ return -EIO;
+ }
+
+ /* Be sure it is correct format */
+ return parse_log(rc);
+}
+
+static int activate_luks_headers(struct reenc_ctx *rc)
+{
+ struct crypt_device *cd = NULL, *cd_new = NULL;
+ const char *pwd_old, *pwd_new, pwd_empty[] = "";
+ size_t pwd_old_len, pwd_new_len;
+ int r;
+
+ log_dbg("Activating LUKS devices from headers.");
+
+ /* Never use real password for empty header processing */
+ if (rc->reencrypt_mode == REENCRYPT) {
+ pwd_old = rc->p[rc->keyslot].password;
+ pwd_old_len = rc->p[rc->keyslot].passwordLen;
+ pwd_new = pwd_old;
+ pwd_new_len = pwd_old_len;
+ } else if (rc->reencrypt_mode == DECRYPT) {
+ pwd_old = rc->p[rc->keyslot].password;
+ pwd_old_len = rc->p[rc->keyslot].passwordLen;
+ pwd_new = pwd_empty;
+ pwd_new_len = 0;
+ } else if (rc->reencrypt_mode == ENCRYPT) {
+ pwd_old = pwd_empty;
+ pwd_old_len = 0;
+ pwd_new = rc->p[rc->keyslot].password;
+ pwd_new_len = rc->p[rc->keyslot].passwordLen;
+ } else
+ return -EINVAL;
+
+ if ((r = crypt_init_data_device(&cd, rc->header_file_org, rc->device)) ||
+ (r = crypt_load(cd, CRYPT_LUKS1, NULL)))
+ goto out;
+
+ log_verbose(_("Activating temporary device using old LUKS header."));
+ if ((r = crypt_activate_by_passphrase(cd, rc->header_file_org,
+ ARG_INT32(OPT_KEY_SLOT_ID), pwd_old, pwd_old_len,
+ CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_PRIVATE)) < 0)
+ goto out;
+
+ if ((r = crypt_init_data_device(&cd_new, rc->header_file_new, rc->device)) ||
+ (r = crypt_load(cd_new, CRYPT_LUKS1, NULL)))
+ goto out;
+
+ log_verbose(_("Activating temporary device using new LUKS header."));
+ if ((r = crypt_activate_by_passphrase(cd_new, rc->header_file_new,
+ ARG_INT32(OPT_KEY_SLOT_ID), pwd_new, pwd_new_len,
+ CRYPT_ACTIVATE_SHARED|CRYPT_ACTIVATE_PRIVATE)) < 0)
+ goto out;
+ r = 0;
+out:
+ crypt_free(cd);
+ crypt_free(cd_new);
+ if (r < 0)
+ log_err(_("Activation of temporary devices failed."));
+ return r;
+}
+
+static int create_new_keyslot(struct reenc_ctx *rc, int keyslot,
+ struct crypt_device *cd_old,
+ struct crypt_device *cd_new)
+{
+ int r;
+ char *key = NULL;
+ size_t key_size;
+
+ if (cd_old && crypt_keyslot_status(cd_old, keyslot) == CRYPT_SLOT_UNBOUND) {
+ key_size = 4096;
+ key = crypt_safe_alloc(key_size);
+ if (!key)
+ return -ENOMEM;
+ r = crypt_volume_key_get(cd_old, keyslot, key, &key_size,
+ rc->p[keyslot].password, rc->p[keyslot].passwordLen);
+ if (r == keyslot) {
+ r = crypt_keyslot_add_by_key(cd_new, keyslot, key, key_size,
+ rc->p[keyslot].password, rc->p[keyslot].passwordLen,
+ CRYPT_VOLUME_KEY_NO_SEGMENT);
+ } else
+ r = -EINVAL;
+ crypt_safe_free(key);
+ } else
+ r = crypt_keyslot_add_by_volume_key(cd_new, keyslot, NULL, 0,
+ rc->p[keyslot].password, rc->p[keyslot].passwordLen);
+
+ return r;
+}
+
+static int create_new_header(struct reenc_ctx *rc, struct crypt_device *cd_old,
+ const char *cipher, const char *cipher_mode,
+ const char *uuid,
+ const char *key, int key_size,
+ uint64_t metadata_size,
+ uint64_t keyslots_size,
+ void *params)
+{
+ struct crypt_device *cd_new = NULL;
+ int i, r;
+
+ if ((r = crypt_init(&cd_new, rc->header_file_new)))
+ goto out;
+
+ if (ARG_SET(OPT_USE_RANDOM_ID))
+ crypt_set_rng_type(cd_new, CRYPT_RNG_RANDOM);
+ else if (ARG_SET(OPT_USE_URANDOM_ID))
+ crypt_set_rng_type(cd_new, CRYPT_RNG_URANDOM);
+
+ r = set_pbkdf_params(cd_new, CRYPT_LUKS1);
+ if (r) {
+ log_err(_("Failed to set pbkdf parameters."));
+ goto out;
+ }
+
+ r = crypt_set_data_offset(cd_new, rc->data_offset);
+ if (r) {
+ log_err(_("Failed to set data offset."));
+ goto out;
+ }
+
+ r = crypt_set_metadata_size(cd_new, metadata_size, keyslots_size);
+ if (r) {
+ log_err(_("Failed to set metadata size."));
+ goto out;
+ }
+
+ r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode, uuid, key, key_size, params);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ log_verbose(_("New LUKS header for device %s created."), rc->device);
+
+ for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1); i++) {
+ if (!rc->p[i].password)
+ continue;
+
+ r = create_new_keyslot(rc, i, cd_old, cd_new);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+ tools_keyslot_msg(r, CREATED);
+ r = 0;
+ }
+out:
+ crypt_free(cd_new);
+ return r;
+}
+
+static int backup_luks_headers(struct reenc_ctx *rc)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_luks1 params = {0};
+ char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ char *key = NULL;
+ size_t key_size;
+ uint64_t mdata_size = 0, keyslots_size = 0;
+ int r;
+
+ log_dbg("Creating LUKS header backup for device %s.", hdr_device(rc));
+
+ if ((r = crypt_init(&cd, hdr_device(rc))) ||
+ (r = crypt_load(cd, CRYPT_LUKS1, NULL)))
+ goto out;
+
+ if ((r = crypt_header_backup(cd, CRYPT_LUKS1, rc->header_file_org)))
+ goto out;
+
+ log_verbose(_("%s header backup of device %s created."), "LUKS1", rc->device);
+
+ /* For decrypt, new header will be fake one, so we are done here. */
+ if (rc->reencrypt_mode == DECRYPT)
+ goto out;
+
+ rc->data_offset = crypt_get_data_offset(cd) + ROUND_SECTOR(ARG_UINT64(OPT_REDUCE_DEVICE_SIZE_ID));
+
+ if ((r = create_empty_header(rc->header_file_new)))
+ goto out;
+
+ params.hash = ARG_STR(OPT_HASH_ID) ?: DEFAULT_LUKS1_HASH;
+ params.data_device = rc->device;
+
+ if (ARG_SET(OPT_CIPHER_ID)) {
+ r = crypt_parse_name_and_mode(ARG_STR(OPT_CIPHER_ID), cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected."));
+ goto out;
+ }
+ }
+
+ key_size = ARG_SET(OPT_KEY_SIZE_ID) ? ARG_UINT32(OPT_KEY_SIZE_ID) / 8 : (uint32_t)crypt_get_volume_key_size(cd);
+
+ if (ARG_SET(OPT_KEEP_KEY_ID)) {
+ log_dbg("Keeping key from old header.");
+ key_size = crypt_get_volume_key_size(cd);
+ key = crypt_safe_alloc(key_size);
+ if (!key) {
+ r = -ENOMEM;
+ goto out;
+ }
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size,
+ rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
+ } else if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
+ log_dbg("Loading new key from file.");
+ r = tools_read_vk(ARG_STR(OPT_VOLUME_KEY_FILE_ID), &key, key_size);
+ }
+
+ if (r < 0)
+ goto out;
+
+ r = create_new_header(rc, cd,
+ ARG_SET(OPT_CIPHER_ID) ? cipher : crypt_get_cipher(cd),
+ ARG_SET(OPT_CIPHER_ID) ? cipher_mode : crypt_get_cipher_mode(cd),
+ crypt_get_uuid(cd),
+ key,
+ key_size,
+ mdata_size,
+ keyslots_size,
+ (void*)&params);
+
+out:
+ crypt_free(cd);
+ crypt_safe_free(key);
+ if (r)
+ log_err(_("Creation of LUKS backup headers failed."));
+ return r;
+}
+
+/* Create fake header for original device */
+static int backup_fake_header(struct reenc_ctx *rc)
+{
+ struct crypt_device *cd_new = NULL;
+ struct crypt_params_luks1 params = {0};
+ char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ const char *header_file_fake;
+ int r;
+
+ log_dbg("Creating fake (cipher_null) header for %s device.",
+ (rc->reencrypt_mode == DECRYPT) ? "new" : "original");
+
+ header_file_fake = (rc->reencrypt_mode == DECRYPT) ? rc->header_file_new : rc->header_file_org;
+
+ if (!ARG_SET(OPT_KEY_SIZE_ID))
+ ARG_SET_UINT32(OPT_KEY_SIZE_ID, DEFAULT_LUKS1_KEYBITS);
+
+ if (ARG_SET(OPT_CIPHER_ID)) {
+ r = crypt_parse_name_and_mode(ARG_STR(OPT_CIPHER_ID), cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected."));
+ goto out;
+ }
+ }
+
+ r = create_empty_header(header_file_fake);
+ if (r < 0)
+ return r;
+
+ params.hash = ARG_STR(OPT_HASH_ID) ?: DEFAULT_LUKS1_HASH;
+ params.data_alignment = 0;
+ params.data_device = rc->device;
+
+ r = crypt_init(&cd_new, header_file_fake);
+ if (r < 0)
+ return r;
+
+ r = crypt_format(cd_new, CRYPT_LUKS1, "cipher_null", "ecb",
+ NO_UUID, NULL, ARG_UINT32(OPT_KEY_SIZE_ID) / 8, &params);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+
+ r = crypt_keyslot_add_by_volume_key(cd_new, rc->keyslot, NULL, 0,
+ rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
+ check_signal(&r);
+ if (r < 0)
+ goto out;
+
+ /* The real header is backup header created in backup_luks_headers() */
+ if (rc->reencrypt_mode == DECRYPT) {
+ r = 0;
+ goto out;
+ }
+
+ r = create_empty_header(rc->header_file_new);
+ if (r < 0)
+ goto out;
+
+ params.data_alignment = ROUND_SECTOR(ARG_UINT64(OPT_REDUCE_DEVICE_SIZE_ID));
+ r = create_new_header(rc, NULL,
+ ARG_SET(OPT_CIPHER_ID) ? cipher : DEFAULT_LUKS1_CIPHER,
+ ARG_SET(OPT_CIPHER_ID) ? cipher_mode : DEFAULT_LUKS1_MODE,
+ NULL, NULL,
+ ARG_UINT32(OPT_KEY_SIZE_ID) / 8,
+ 0,
+ 0,
+ (void*)&params);
+out:
+ crypt_free(cd_new);
+ return r;
+}
+
+static void remove_headers(struct reenc_ctx *rc)
+{
+ struct crypt_device *cd = NULL;
+
+ log_dbg("Removing headers.");
+
+ if (crypt_init(&cd, NULL))
+ return;
+ crypt_set_log_callback(cd, _quiet_log, NULL);
+ if (*rc->header_file_org)
+ (void)crypt_deactivate(cd, rc->header_file_org);
+ if (*rc->header_file_new)
+ (void)crypt_deactivate(cd, rc->header_file_new);
+ crypt_free(cd);
+}
+
+static int restore_luks_header(struct reenc_ctx *rc)
+{
+ struct stat st;
+ struct crypt_device *cd = NULL;
+ int fd, r;
+
+ log_dbg("Restoring header for %s from %s.", hdr_device(rc), rc->header_file_new);
+
+ /*
+ * For new encryption and new detached header in file just move it.
+ * For existing file try to ensure we have preallocated space for restore.
+ */
+ if (ARG_SET(OPT_ENCRYPT_ID) && rc->device_header) {
+ r = stat(rc->device_header, &st);
+ if (r == -1) {
+ r = rename(rc->header_file_new, rc->device_header);
+ goto out;
+ } else if ((st.st_mode & S_IFMT) == S_IFREG &&
+ stat(rc->header_file_new, &st) != -1) {
+ /* coverity[toctou] */
+ fd = open(rc->device_header, O_WRONLY);
+ if (fd != -1) {
+ if (posix_fallocate(fd, 0, st.st_size)) {};
+ close(fd);
+ }
+ }
+ }
+
+ r = crypt_init(&cd, hdr_device(rc));
+ if (r == 0) {
+ r = crypt_header_restore(cd, CRYPT_LUKS1, rc->header_file_new);
+ }
+
+ crypt_free(cd);
+out:
+ if (r)
+ log_err(_("Cannot restore %s header on device %s."), "LUKS1", hdr_device(rc));
+ else {
+ log_verbose(_("%s header on device %s restored."), "LUKS1", hdr_device(rc));
+ rc->stained = false;
+ }
+ return r;
+}
+
+static ssize_t read_buf(int fd, void *buf, size_t count)
+{
+ size_t read_size = 0;
+ ssize_t s;
+
+ do {
+ /* This expects that partial read is aligned in buffer */
+ s = read(fd, buf, count - read_size);
+ if (s == -1 && errno != EINTR)
+ return s;
+ if (s == 0)
+ return (ssize_t)read_size;
+ if (s > 0) {
+ if (s != (ssize_t)count)
+ log_dbg("Partial read %zd / %zu.", s, count);
+ read_size += (size_t)s;
+ buf = (uint8_t*)buf + s;
+ }
+ } while (read_size != count);
+
+ return (ssize_t)count;
+}
+
+static int copy_data_forward(struct reenc_ctx *rc, int fd_old, int fd_new,
+ size_t block_size, void *buf, uint64_t *bytes)
+{
+ ssize_t s1, s2;
+ int r = -EIO;
+ char *backing_file = NULL;
+ struct tools_progress_params prog_parms = {
+ .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID),
+ .batch_mode = ARG_SET(OPT_BATCH_MODE_ID),
+ .json_output = ARG_SET(OPT_PROGRESS_JSON_ID),
+ .interrupt_message = _("\nReencryption interrupted."),
+ .device = tools_get_device_name(rc->device, &backing_file)
+ };
+
+ log_dbg("Reencrypting in forward direction.");
+
+ if (lseek(fd_old, rc->device_offset, SEEK_SET) < 0 ||
+ lseek(fd_new, rc->device_offset, SEEK_SET) < 0) {
+ log_err(_("Cannot seek to device offset."));
+ goto out;
+ }
+
+ rc->resume_bytes = *bytes = rc->device_offset;
+
+ tools_progress(rc->device_size, *bytes, &prog_parms);
+
+ if (write_log(rc) < 0)
+ goto out;
+
+ while (!quit && rc->device_offset < rc->device_size) {
+ if ((rc->device_size - rc->device_offset) < (uint64_t)block_size)
+ block_size = rc->device_size - rc->device_offset;
+ s1 = read_buf(fd_old, buf, block_size);
+ if (s1 < 0 || ((size_t)s1 != block_size &&
+ (rc->device_offset + s1) != rc->device_size)) {
+ log_dbg("Read error, expecting %zu, got %zd.",
+ block_size, s1);
+ goto out;
+ }
+
+ /* If device_size is forced, never write more than limit */
+ if ((s1 + rc->device_offset) > rc->device_size)
+ s1 = rc->device_size - rc->device_offset;
+
+ s2 = write(fd_new, buf, s1);
+ if (s2 < 0) {
+ log_dbg("Write error, expecting %zu, got %zd.",
+ block_size, s2);
+ goto out;
+ }
+
+ rc->device_offset += s1;
+ if (ARG_SET(OPT_WRITE_LOG_ID) && write_log(rc) < 0)
+ goto out;
+
+ if (ARG_SET(OPT_USE_FSYNC_ID) && fsync(fd_new) < 0) {
+ log_dbg("Write error, fsync.");
+ goto out;
+ }
+
+ *bytes += (uint64_t)s2;
+
+ tools_progress(rc->device_size, *bytes, &prog_parms);
+ }
+
+ r = 0;
+out:
+ free(backing_file);
+ return quit ? -EAGAIN : r;
+}
+
+static int copy_data_backward(struct reenc_ctx *rc, int fd_old, int fd_new,
+ size_t block_size, void *buf, uint64_t *bytes)
+{
+ ssize_t s1, s2, working_block;
+ off_t working_offset;
+ int r = -EIO;
+ char *backing_file = NULL;
+ struct tools_progress_params prog_parms = {
+ .frequency = ARG_UINT32(OPT_PROGRESS_FREQUENCY_ID),
+ .batch_mode = ARG_SET(OPT_BATCH_MODE_ID),
+ .json_output = ARG_SET(OPT_PROGRESS_JSON_ID),
+ .interrupt_message = _("\nReencryption interrupted."),
+ .device = tools_get_device_name(rc->device, &backing_file)
+ };
+
+ log_dbg("Reencrypting in backward direction.");
+
+ if (!rc->in_progress) {
+ rc->device_offset = rc->device_size;
+ rc->resume_bytes = 0;
+ *bytes = 0;
+ } else {
+ rc->resume_bytes = rc->device_size - rc->device_offset;
+ *bytes = rc->resume_bytes;
+ }
+
+ tools_progress(rc->device_size, *bytes, &prog_parms);
+
+ if (write_log(rc) < 0)
+ goto out;
+
+ /* dirty the device during ENCRYPT mode */
+ rc->stained = true;
+
+ while (!quit && rc->device_offset) {
+ if (rc->device_offset < block_size) {
+ working_offset = 0;
+ working_block = rc->device_offset;
+ } else {
+ working_offset = rc->device_offset - block_size;
+ working_block = block_size;
+ }
+
+ if (lseek(fd_old, working_offset, SEEK_SET) < 0 ||
+ lseek(fd_new, working_offset, SEEK_SET) < 0) {
+ log_err(_("Cannot seek to device offset."));
+ goto out;
+ }
+
+ s1 = read_buf(fd_old, buf, working_block);
+ if (s1 < 0 || (s1 != working_block)) {
+ log_dbg("Read error, expecting %zu, got %zd.",
+ block_size, s1);
+ goto out;
+ }
+
+ s2 = write(fd_new, buf, working_block);
+ if (s2 < 0) {
+ log_dbg("Write error, expecting %zu, got %zd.",
+ block_size, s2);
+ goto out;
+ }
+
+ rc->device_offset -= s1;
+ if (ARG_SET(OPT_WRITE_LOG_ID) && write_log(rc) < 0)
+ goto out;
+
+ if (ARG_SET(OPT_USE_FSYNC_ID) && fsync(fd_new) < 0) {
+ log_dbg("Write error, fsync.");
+ goto out;
+ }
+
+ *bytes += (uint64_t)s2;
+
+ tools_progress(rc->device_size, *bytes, &prog_parms);
+ }
+
+ r = 0;
+out:
+ free(backing_file);
+ return quit ? -EAGAIN : r;
+}
+
+static void zero_rest_of_device(int fd, size_t block_size, void *buf,
+ uint64_t *bytes, uint64_t offset)
+{
+ ssize_t s1, s2;
+
+ log_dbg("Zeroing rest of device.");
+
+ if (lseek(fd, offset, SEEK_SET) < 0) {
+ log_dbg("Cannot seek to device offset.");
+ return;
+ }
+
+ memset(buf, 0, block_size);
+ s1 = block_size;
+
+ while (!quit && *bytes) {
+ if (*bytes < (uint64_t)s1)
+ s1 = *bytes;
+
+ s2 = write(fd, buf, s1);
+ if (s2 != s1) {
+ log_dbg("Write error, expecting %zd, got %zd.",
+ s1, s2);
+ return;
+ }
+
+ if (ARG_SET(OPT_USE_FSYNC_ID) && fsync(fd) < 0) {
+ log_dbg("Write error, fsync.");
+ return;
+ }
+
+ *bytes -= s2;
+ }
+}
+
+static int copy_data(struct reenc_ctx *rc)
+{
+ size_t block_size = ARG_UINT32(OPT_BLOCK_SIZE_ID) * 1024 * 1024;
+ int fd_old = -1, fd_new = -1;
+ int r = -EINVAL;
+ void *buf = NULL;
+ uint64_t bytes = 0;
+
+ log_dbg("Data copy preparation.");
+
+ fd_old = open(rc->crypt_path_org, O_RDONLY | (ARG_SET(OPT_USE_DIRECTIO_ID) ? O_DIRECT : 0));
+ if (fd_old == -1) {
+ log_err(_("Cannot open temporary LUKS device."));
+ goto out;
+ }
+
+ fd_new = open(rc->crypt_path_new, O_WRONLY | (ARG_SET(OPT_USE_DIRECTIO_ID) ? O_DIRECT : 0));
+ if (fd_new == -1) {
+ log_err(_("Cannot open temporary LUKS device."));
+ goto out;
+ }
+
+ if (ioctl(fd_old, BLKGETSIZE64, &rc->device_size_org_real) < 0) {
+ log_err(_("Cannot get device size."));
+ goto out;
+ }
+
+ if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size_new_real) < 0) {
+ log_err(_("Cannot get device size."));
+ goto out;
+ }
+
+ if (ARG_SET(OPT_DEVICE_SIZE_ID))
+ rc->device_size = ARG_UINT64(OPT_DEVICE_SIZE_ID);
+ else if (rc->reencrypt_mode == DECRYPT)
+ rc->device_size = rc->device_size_org_real;
+ else
+ rc->device_size = rc->device_size_new_real;
+
+ if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) {
+ log_err(_("Allocation of aligned memory failed."));
+ r = -ENOMEM;
+ goto out;
+ }
+
+ set_int_handler(0);
+
+ if (rc->reencrypt_direction == FORWARD)
+ r = copy_data_forward(rc, fd_old, fd_new, block_size, buf, &bytes);
+ else
+ r = copy_data_backward(rc, fd_old, fd_new, block_size, buf, &bytes);
+
+ /* Zero (wipe) rest of now plain-only device when decrypting.
+ * (To not leave any sign of encryption here.) */
+ if (!r && rc->reencrypt_mode == DECRYPT &&
+ rc->device_size_new_real > rc->device_size_org_real) {
+ bytes = rc->device_size_new_real - rc->device_size_org_real;
+ zero_rest_of_device(fd_new, block_size, buf, &bytes, rc->device_size_org_real);
+ }
+
+ set_int_block(1);
+
+ if (r < 0 && r != -EAGAIN)
+ log_err(_("IO error during reencryption."));
+
+ (void)write_log(rc);
+out:
+ if (fd_old != -1)
+ close(fd_old);
+ if (fd_new != -1)
+ close(fd_new);
+ free(buf);
+ return r;
+}
+
+static int initialize_uuid(struct reenc_ctx *rc)
+{
+ struct crypt_device *cd = NULL;
+ int r;
+ uuid_t device_uuid;
+
+ log_dbg("Initialising UUID.");
+
+ if (ARG_SET(OPT_ENCRYPT_ID)) {
+ rc->device_uuid = strdup(NO_UUID);
+ return 0;
+ }
+
+ if (ARG_SET(OPT_DECRYPT_ID) && ARG_SET(OPT_UUID_ID)) {
+ r = uuid_parse(ARG_STR(OPT_UUID_ID), device_uuid);
+ if (!r)
+ rc->device_uuid = strdup(ARG_STR(OPT_UUID_ID));
+ else
+ log_err(_("Provided UUID is invalid."));
+
+ return r;
+ }
+
+ /* Try to load LUKS from device */
+ if ((r = crypt_init(&cd, hdr_device(rc))))
+ return r;
+ crypt_set_log_callback(cd, _quiet_log, NULL);
+ r = crypt_load(cd, CRYPT_LUKS1, NULL);
+ if (!r)
+ rc->device_uuid = strdup(crypt_get_uuid(cd));
+ else
+ /* Reencryption already in progress - magic header? */
+ r = device_check(rc, hdr_device(rc), CHECK_UNUSABLE, true);
+
+ crypt_free(cd);
+ return r;
+}
+
+static int init_passphrase1(struct reenc_ctx *rc, struct crypt_device *cd,
+ const char *msg, int slot_to_check, int check, int verify)
+{
+ crypt_keyslot_info ki;
+ char *password;
+ int r = -EINVAL, retry_count;
+ size_t passwordLen;
+
+ /* mode ENCRYPT call this without header */
+ if (cd && slot_to_check != CRYPT_ANY_SLOT) {
+ ki = crypt_keyslot_status(cd, slot_to_check);
+ if (ki < CRYPT_SLOT_ACTIVE)
+ return -ENOENT;
+ } else
+ ki = CRYPT_SLOT_ACTIVE;
+
+ retry_count = ARG_UINT32(OPT_TRIES_ID) ?: 1;
+ while (retry_count--) {
+ r = tools_get_key(msg, &password, &passwordLen, 0, 0,
+ NULL /*opt_key_file*/, 0, verify, 0 /*pwquality*/, cd);
+ if (r < 0)
+ return r;
+ if (quit) {
+ crypt_safe_free(password);
+ password = NULL;
+ passwordLen = 0;
+ return -EAGAIN;
+ }
+
+ if (check)
+ r = crypt_activate_by_passphrase(cd, NULL, slot_to_check,
+ password, passwordLen, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY);
+ else
+ r = (slot_to_check == CRYPT_ANY_SLOT) ? 0 : slot_to_check;
+
+ if (r < 0) {
+ crypt_safe_free(password);
+ password = NULL;
+ passwordLen = 0;
+ }
+ if (r < 0 && r != -EPERM)
+ return r;
+
+ if (r >= 0) {
+ tools_keyslot_msg(r, UNLOCKED);
+ rc->p[r].password = password;
+ rc->p[r].passwordLen = passwordLen;
+ if (ki != CRYPT_SLOT_UNBOUND)
+ rc->keyslot = r;
+ break;
+ }
+ tools_passphrase_msg(r);
+ }
+
+ password = NULL;
+ passwordLen = 0;
+
+ return r;
+}
+
+static int init_keyfile(struct reenc_ctx *rc, struct crypt_device *cd, int slot_check)
+{
+ char *password;
+ int r;
+ size_t passwordLen;
+
+ r = tools_get_key(NULL, &password, &passwordLen, ARG_UINT64(OPT_KEYFILE_OFFSET_ID),
+ ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID), 0, 0, 0, cd);
+ if (r < 0)
+ return r;
+
+ /* mode ENCRYPT call this without header */
+ if (cd) {
+ r = crypt_activate_by_passphrase(cd, NULL, slot_check, password,
+ passwordLen, 0);
+
+ /*
+ * Allow keyslot only if it is last slot or if user explicitly
+ * specify which slot to use (IOW others will be disabled).
+ */
+ if (r >= 0 && ARG_INT32(OPT_KEY_SLOT_ID) == CRYPT_ANY_SLOT &&
+ crypt_keyslot_status(cd, r) != CRYPT_SLOT_ACTIVE_LAST) {
+ log_err(_("Key file can be used only with --key-slot or with "
+ "exactly one key slot active."));
+ r = -EINVAL;
+ }
+ } else {
+ r = slot_check == CRYPT_ANY_SLOT ? 0 : slot_check;
+ }
+
+ if (r < 0) {
+ crypt_safe_free(password);
+ tools_passphrase_msg(r);
+ } else {
+ rc->keyslot = r;
+ rc->p[r].password = password;
+ rc->p[r].passwordLen = passwordLen;
+ }
+
+ password = NULL;
+ passwordLen = 0;
+
+ return r;
+}
+
+static int initialize_passphrase(struct reenc_ctx *rc, const char *device)
+{
+ struct crypt_device *cd = NULL;
+ char msg[256];
+ int i, r;
+
+ log_dbg("Passphrases initialization.");
+
+ if (rc->reencrypt_mode == ENCRYPT && !rc->in_progress) {
+ if (ARG_SET(OPT_KEY_FILE_ID))
+ r = init_keyfile(rc, NULL, ARG_INT32(OPT_KEY_SLOT_ID));
+ else
+ r = init_passphrase1(rc, NULL, _("Enter new passphrase: "), ARG_INT32(OPT_KEY_SLOT_ID), 0, 1);
+ return r > 0 ? 0 : r;
+ }
+
+ if ((r = crypt_init_data_device(&cd, device, rc->device)) ||
+ (r = crypt_load(cd, CRYPT_LUKS1, NULL))) {
+ crypt_free(cd);
+ return r;
+ }
+
+ if (ARG_INT32(OPT_KEY_SLOT_ID) != CRYPT_ANY_SLOT)
+ snprintf(msg, sizeof(msg),
+ _("Enter passphrase for key slot %d: "), ARG_INT32(OPT_KEY_SLOT_ID));
+ else
+ snprintf(msg, sizeof(msg), _("Enter any existing passphrase: "));
+
+ if (ARG_SET(OPT_KEY_FILE_ID)) {
+ r = init_keyfile(rc, cd, ARG_INT32(OPT_KEY_SLOT_ID));
+ } else if (rc->in_progress ||
+ ARG_INT32(OPT_KEY_SLOT_ID) != CRYPT_ANY_SLOT ||
+ rc->reencrypt_mode == DECRYPT) {
+ r = init_passphrase1(rc, cd, msg, ARG_INT32(OPT_KEY_SLOT_ID), 1, 0);
+ } else for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1); i++) {
+ snprintf(msg, sizeof(msg), _("Enter passphrase for key slot %d: "), i);
+ r = init_passphrase1(rc, cd, msg, i, 1, 0);
+ if (r == -ENOENT) {
+ r = 0;
+ continue;
+ }
+ if (r < 0)
+ break;
+ }
+
+ crypt_free(cd);
+ return r > 0 ? 0 : r;
+}
+
+static int initialize_context(struct reenc_ctx *rc, const char *device)
+{
+ log_dbg("Initialising reencryption context.");
+
+ memset(rc, 0, sizeof(*rc));
+
+ rc->in_progress = false;
+ rc->stained = true;
+ rc->log_fd = -1;
+
+ if (!(rc->device = strndup(device, PATH_MAX)))
+ return -ENOMEM;
+
+ if (ARG_SET(OPT_HEADER_ID) && !(rc->device_header = strndup(ARG_STR(OPT_HEADER_ID), PATH_MAX)))
+ return -ENOMEM;
+
+ if (device_check(rc, rc->device, CHECK_OPEN, true) < 0)
+ return -EINVAL;
+
+ if (initialize_uuid(rc)) {
+ log_err(_("Device %s is not a valid LUKS device."), device);
+ return -EINVAL;
+ }
+
+ if (ARG_INT32(OPT_KEY_SLOT_ID) != CRYPT_ANY_SLOT &&
+ ARG_INT32(OPT_KEY_SLOT_ID) >= crypt_keyslot_max(CRYPT_LUKS1)) {
+ log_err(_("Key slot is invalid."));
+ return -EINVAL;
+ }
+
+ /* Prepare device names */
+ if (snprintf(rc->log_file, PATH_MAX,
+ "LUKS-%s.log", rc->device_uuid) < 0)
+ return -ENOMEM;
+ if (snprintf(rc->header_file_org, PATH_MAX,
+ "LUKS-%s.org", rc->device_uuid) < 0)
+ return -ENOMEM;
+ if (snprintf(rc->header_file_new, PATH_MAX,
+ "LUKS-%s.new", rc->device_uuid) < 0)
+ return -ENOMEM;
+
+ /* Paths to encrypted devices */
+ if (snprintf(rc->crypt_path_org, PATH_MAX,
+ "%s/%s", crypt_get_dir(), rc->header_file_org) < 0)
+ return -ENOMEM;
+ if (snprintf(rc->crypt_path_new, PATH_MAX,
+ "%s/%s", crypt_get_dir(), rc->header_file_new) < 0)
+ return -ENOMEM;
+
+ remove_headers(rc);
+
+ if (open_log(rc) < 0) {
+ log_err(_("Cannot open reencryption log file."));
+ return -EINVAL;
+ }
+
+ if (!rc->in_progress) {
+ if (ARG_SET(OPT_UUID_ID)) {
+ log_err(_("No decryption in progress, provided UUID can "
+ "be used only to resume suspended decryption process."));
+ return -EINVAL;
+ }
+
+ if (!ARG_SET(OPT_REDUCE_DEVICE_SIZE_ID))
+ rc->reencrypt_direction = FORWARD;
+ else {
+ rc->reencrypt_direction = BACKWARD;
+ rc->device_offset = (uint64_t)~0;
+ }
+
+ if (ARG_SET(OPT_ENCRYPT_ID))
+ rc->reencrypt_mode = ENCRYPT;
+ else if (ARG_SET(OPT_DECRYPT_ID))
+ rc->reencrypt_mode = DECRYPT;
+ else
+ rc->reencrypt_mode = REENCRYPT;
+ }
+
+ return 0;
+}
+
+static void destroy_context(struct reenc_ctx *rc)
+{
+ int i;
+
+ log_dbg("Destroying reencryption context.");
+
+ close_log(rc);
+ remove_headers(rc);
+
+ if (!rc->stained) {
+ unlink(rc->log_file);
+ unlink(rc->header_file_org);
+ unlink(rc->header_file_new);
+ }
+
+ for (i = 0; i < MAX_SLOT; i++)
+ crypt_safe_free(rc->p[i].password);
+
+ free(rc->device);
+ free(rc->device_header);
+ free(rc->device_uuid);
+}
+
+int reencrypt_luks1(const char *device)
+{
+ int r = -EINVAL;
+ struct reenc_ctx *rc;
+
+ rc = malloc(sizeof(*rc));
+ if (!rc)
+ return -ENOMEM;
+
+ if (!ARG_SET(OPT_BATCH_MODE_ID))
+ log_verbose(_("Reencryption will change: %s%s%s%s%s%s."),
+ ARG_SET(OPT_KEEP_KEY_ID) ? "" : _("volume key"),
+ (!ARG_SET(OPT_KEEP_KEY_ID) && ARG_SET(OPT_HASH_ID)) ? ", " : "",
+ ARG_SET(OPT_HASH_ID) ? _("set hash to ") : "", ARG_STR(OPT_HASH_ID) ?: "",
+ ARG_SET(OPT_CIPHER_ID) ? _(", set cipher to "): "", ARG_STR(OPT_CIPHER_ID) ?: "");
+ /* FIXME: block all non pbkdf2 pkdfs */
+
+ set_int_handler(0);
+
+ if (initialize_context(rc, device))
+ goto out;
+
+ log_dbg("Running reencryption.");
+
+ if (!rc->in_progress) {
+ if ((r = initialize_passphrase(rc, hdr_device(rc))))
+ goto out;
+
+ log_dbg("Storing backup of LUKS headers.");
+ if (rc->reencrypt_mode == ENCRYPT) {
+ /* Create fake header for existing device */
+ if ((r = backup_fake_header(rc)))
+ goto out;
+ } else {
+ if ((r = backup_luks_headers(rc)))
+ goto out;
+ /* Create fake header for decrypted device */
+ if (rc->reencrypt_mode == DECRYPT &&
+ (r = backup_fake_header(rc)))
+ goto out;
+ if ((r = device_check(rc, hdr_device(rc), MAKE_UNUSABLE, true)))
+ goto out;
+ }
+ } else {
+ if ((r = initialize_passphrase(rc, ARG_SET(OPT_DECRYPT_ID) ? rc->header_file_org : rc->header_file_new)))
+ goto out;
+ }
+
+ if (!ARG_SET(OPT_KEEP_KEY_ID)) {
+ log_dbg("Running data area reencryption.");
+ if ((r = activate_luks_headers(rc)))
+ goto out;
+
+ if ((r = copy_data(rc)))
+ goto out;
+ } else
+ log_dbg("Keeping existing key, skipping data area reencryption.");
+
+ // FIXME: fix error path above to not skip this
+ if (rc->reencrypt_mode != DECRYPT)
+ r = restore_luks_header(rc);
+ else
+ rc->stained = false;
+out:
+ destroy_context(rc);
+ free(rc);
+
+ return r;
+}
+
+int reencrypt_luks1_in_progress(const char *device)
+{
+ struct stat st;
+
+ if (stat(device, &st) || (size_t)st.st_size < pagesize())
+ return -EINVAL;
+
+ return device_check(NULL, device, CHECK_UNUSABLE, false);
+}
diff --git a/src/utils_tools.c b/src/utils_tools.c
new file mode 100644
index 0000000..a0e2ebc
--- /dev/null
+++ b/src/utils_tools.c
@@ -0,0 +1,468 @@
+/*
+ * cryptsetup - setup cryptographic volumes for dm-crypt
+ *
+ * Copyright (C) 2004 Jana Saout <jana@saout.de>
+ * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "cryptsetup.h"
+#include <signal.h>
+
+/* interrupt handling */
+volatile int quit = 0;
+static int signals_blocked = 0;
+
+static void int_handler(int sig __attribute__((__unused__)))
+{
+ quit++;
+}
+
+int tools_signals_blocked(void)
+{
+ return signals_blocked;
+}
+
+void set_int_block(int block)
+{
+ sigset_t signals_open;
+
+ log_dbg("%slocking interruption on signal.", block ? "B" : "Unb");
+
+ sigemptyset(&signals_open);
+ sigaddset(&signals_open, SIGINT);
+ sigaddset(&signals_open, SIGTERM);
+ sigprocmask(block ? SIG_SETMASK : SIG_UNBLOCK, &signals_open, NULL);
+ signals_blocked = block;
+ quit = 0;
+}
+
+void set_int_handler(int block)
+{
+ struct sigaction sigaction_open;
+
+ log_dbg("Installing SIGINT/SIGTERM handler.");
+ memset(&sigaction_open, 0, sizeof(struct sigaction));
+ sigaction_open.sa_handler = int_handler;
+ sigaction(SIGINT, &sigaction_open, 0);
+ sigaction(SIGTERM, &sigaction_open, 0);
+ set_int_block(block);
+}
+
+void check_signal(int *r)
+{
+ if (quit && !*r)
+ *r = -EINTR;
+}
+
+void tool_log(int level, const char *msg, void *usrptr)
+{
+ struct tools_log_params *params = (struct tools_log_params *)usrptr;
+
+ switch (level) {
+
+ case CRYPT_LOG_NORMAL:
+ fprintf(stdout, "%s", msg);
+ break;
+ case CRYPT_LOG_VERBOSE:
+ if (params && params->verbose)
+ fprintf(stdout, "%s", msg);
+ break;
+ case CRYPT_LOG_ERROR:
+ fprintf(stderr, "%s", msg);
+ break;
+ case CRYPT_LOG_DEBUG_JSON:
+ case CRYPT_LOG_DEBUG:
+ if (params && params->debug)
+ fprintf(stdout, "# %s", msg);
+ break;
+ }
+}
+
+void quiet_log(int level, const char *msg, void *usrptr)
+{
+ struct tools_log_params *params = (struct tools_log_params *)usrptr;
+
+ if ((!params || !params->verbose) && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
+ return;
+ tool_log(level, msg, usrptr);
+}
+
+static int _dialog(const char *msg, void *usrptr, int default_answer)
+{
+ const char *fail_msg = (const char *)usrptr;
+ char *answer = NULL;
+ size_t size = 0;
+ int r = default_answer, block;
+
+ block = tools_signals_blocked();
+ if (block)
+ set_int_block(0);
+
+ if (isatty(STDIN_FILENO)) {
+ log_std(_("\nWARNING!\n========\n"));
+ /* TRANSLATORS: User must type "YES" (in capital letters), do not translate this word. */
+ log_std(_("%s\n\nAre you sure? (Type 'yes' in capital letters): "), msg);
+ fflush(stdout);
+ if(getline(&answer, &size, stdin) == -1) {
+ r = 0;
+ /* Aborted by signal */
+ if (!quit)
+ log_err(_("Error reading response from terminal."));
+ else
+ log_dbg("Query interrupted on signal.");
+ } else {
+ r = !strcmp(answer, "YES\n");
+ if (!r && fail_msg)
+ log_err("%s", fail_msg);
+ }
+ }
+
+ if (block && !quit)
+ set_int_block(1);
+
+ free(answer);
+ return r;
+}
+
+int yesDialog(const char *msg, void *usrptr)
+{
+ return _dialog(msg, usrptr, 1);
+}
+
+int noDialog(const char *msg, void *usrptr)
+{
+ return _dialog(msg, usrptr, 0);
+}
+
+void show_status(int errcode)
+{
+ char *crypt_error;
+
+ if (!errcode) {
+ log_verbose(_("Command successful."));
+ return;
+ }
+
+ if (errcode < 0)
+ errcode = translate_errno(errcode);
+
+ if (errcode == 1)
+ crypt_error = _("wrong or missing parameters");
+ else if (errcode == 2)
+ crypt_error = _("no permission or bad passphrase");
+ else if (errcode == 3)
+ crypt_error = _("out of memory");
+ else if (errcode == 4)
+ crypt_error = _("wrong device or file specified");
+ else if (errcode == 5)
+ crypt_error = _("device already exists or device is busy");
+ else
+ crypt_error = _("unknown error");
+
+ log_verbose(_("Command failed with code %i (%s)."), -errcode, crypt_error);
+}
+
+const char *uuid_or_device(const char *spec)
+{
+ static char device[PATH_MAX];
+ char s, *ptr;
+ int i = 0, uuid_len = 5;
+
+ /* Check if it is correct UUID=<LUKS_UUID> format */
+ if (spec && !strncmp(spec, "UUID=", uuid_len)) {
+ strcpy(device, "/dev/disk/by-uuid/");
+ ptr = &device[strlen(device)];
+ i = uuid_len;
+ while ((s = spec[i++]) && i < (PATH_MAX - 13)) {
+ if (!isxdigit(s) && s != '-')
+ return spec; /* Bail it out */
+ if (isalpha(s))
+ s = tolower(s);
+ *ptr++ = s;
+ }
+ *ptr = '\0';
+ return device;
+ }
+
+ return spec;
+}
+
+__attribute__ ((noreturn)) void usage(poptContext popt_context,
+ int exitcode, const char *error,
+ const char *more)
+{
+ poptPrintUsage(popt_context, stderr, 0);
+ if (error)
+ log_err("%s: %s", more, error);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(exitcode);
+}
+
+void dbg_version_and_cmd(int argc, const char **argv)
+{
+ int i;
+
+ log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
+ for (i = 0; i < argc; i++) {
+ if (i)
+ log_std(" ");
+ log_std("%s", argv[i]);
+ }
+ log_std("\"\n");
+}
+
+/* Translate exit code to simple codes */
+int translate_errno(int r)
+{
+ switch (r) {
+ case 0: r = EXIT_SUCCESS; break;
+ case -EEXIST:
+ case -EBUSY: r = 5; break;
+ case -ENOTBLK:
+ case -ENODEV: r = 4; break;
+ case -ENOMEM: r = 3; break;
+ case -EPERM: r = 2; break;
+ case -EINVAL:
+ case -ENOENT:
+ case -ENOSYS:
+ default: r = EXIT_FAILURE;
+ }
+ return r;
+}
+
+void tools_keyslot_msg(int keyslot, crypt_object_op op)
+{
+ if (keyslot < 0)
+ return;
+
+ if (op == CREATED)
+ log_verbose(_("Key slot %i created."), keyslot);
+ else if (op == UNLOCKED)
+ log_verbose(_("Key slot %i unlocked."), keyslot);
+ else if (op == REMOVED)
+ log_verbose(_("Key slot %i removed."), keyslot);
+}
+
+void tools_token_msg(int token, crypt_object_op op)
+{
+ if (token < 0)
+ return;
+
+ if (op == CREATED)
+ log_verbose(_("Token %i created."), token);
+ else if (op == REMOVED)
+ log_verbose(_("Token %i removed."), token);
+}
+
+void tools_token_error_msg(int error, const char *type, int token, bool pin_provided)
+{
+ if (error >= 0)
+ return;
+
+ if (error == -ENOANO) {
+ if (pin_provided)
+ log_verbose(_("No token could be unlocked with this PIN."));
+ else if (token != CRYPT_ANY_TOKEN)
+ log_verbose(_("Token %i requires PIN."), token);
+ else if (type)
+ log_verbose(_("Token (type %s) requires PIN."), type);
+ } else if (error == -EPERM) {
+ if (token != CRYPT_ANY_TOKEN)
+ log_verbose(_("Token %i cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."), token);
+ else if (type)
+ log_verbose(_("Token (type %s) cannot unlock assigned keyslot(s) (wrong keyslot passphrase)."), type);
+ } if (error == -EAGAIN) {
+ if (token != CRYPT_ANY_TOKEN)
+ log_verbose(_("Token %i requires additional missing resource."), token);
+ else if (type)
+ log_verbose(_("Token (type %s) requires additional missing resource."), type);
+ } if (error == -ENOENT) {
+ if (type)
+ log_verbose(_("No usable token (type %s) is available."), type);
+ else
+ log_verbose(_("No usable token is available."));
+ }
+}
+
+/*
+ * Device size string parsing, suffixes:
+ * s|S - 512 bytes sectors
+ * k |K |m |M |g |G |t |T - 1024 base
+ * kiB|KiB|miB|MiB|giB|GiB|tiB|TiB - 1024 base
+ * kb |KB |mM |MB |gB |GB |tB |TB - 1000 base
+ */
+int tools_string_to_size(const char *s, uint64_t *size)
+{
+ char *endp = NULL;
+ size_t len;
+ uint64_t mult_base, mult, tmp;
+
+ *size = strtoull(s, &endp, 10);
+ if (!isdigit(s[0]) ||
+ (errno == ERANGE && *size == ULLONG_MAX) ||
+ (errno != 0 && *size == 0))
+ return -EINVAL;
+
+ if (!endp || !*endp)
+ return 0;
+
+ len = strlen(endp);
+ /* Allow "B" and "iB" suffixes */
+ if (len > 3 ||
+ (len == 3 && (endp[1] != 'i' || endp[2] != 'B')) ||
+ (len == 2 && endp[1] != 'B'))
+ return -EINVAL;
+
+ if (len == 1 || len == 3)
+ mult_base = 1024;
+ else
+ mult_base = 1000;
+
+ mult = 1;
+ switch (endp[0]) {
+ case 's':
+ case 'S': mult = 512;
+ break;
+ case 't':
+ case 'T': mult *= mult_base;
+ /* Fall through */
+ case 'g':
+ case 'G': mult *= mult_base;
+ /* Fall through */
+ case 'm':
+ case 'M': mult *= mult_base;
+ /* Fall through */
+ case 'k':
+ case 'K': mult *= mult_base;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = *size * mult;
+ if (*size && (tmp / *size) != mult) {
+ log_dbg("Device size overflow.");
+ return -EINVAL;
+ }
+
+ *size = tmp;
+ return 0;
+}
+
+/*
+ * Keyfile - is standard input treated as a binary file (no EOL handling).
+ */
+int tools_is_stdin(const char *key_file)
+{
+ if (!key_file)
+ return 1;
+
+ return strcmp(key_file, "-") ? 0 : 1;
+}
+
+int tools_read_vk(const char *file, char **key, int keysize)
+{
+ int fd = -1, r = -EINVAL;
+
+ if (keysize <= 0 || !key)
+ return -EINVAL;
+
+ *key = crypt_safe_alloc(keysize);
+ if (!*key)
+ return -ENOMEM;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1) {
+ log_err(_("Cannot read keyfile %s."), file);
+ goto out;
+ }
+
+ if (read_buffer(fd, *key, keysize) != keysize) {
+ log_err(_("Cannot read %d bytes from keyfile %s."), keysize, file);
+ goto out;
+ }
+ r = 0;
+out:
+ if (fd != -1)
+ close(fd);
+
+ if (r) {
+ crypt_safe_free(*key);
+ *key = NULL;
+ }
+
+ return r;
+}
+
+int tools_write_mk(const char *file, const char *key, int keysize)
+{
+ int fd, r = -EINVAL;
+
+ if (keysize <= 0 || !key)
+ return -EINVAL;
+
+ fd = open(file, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR);
+ if (fd < 0) {
+ log_err(_("Cannot open keyfile %s for write."), file);
+ return r;
+ }
+
+ if (write_buffer(fd, key, keysize) == keysize)
+ r = 0;
+ else
+ log_err(_("Cannot write to keyfile %s."), file);
+
+ close(fd);
+ return r;
+}
+
+void tools_package_version(const char *name, bool use_pwlibs)
+{
+ bool udev = false, blkid = false, keyring = false, fips = false;
+ bool kernel_capi = false, pwquality = false, passwdqc = false;
+#ifdef USE_UDEV
+ udev = true;
+#endif
+#ifdef HAVE_BLKID
+ blkid = true;
+#endif
+#ifdef KERNEL_KEYRING
+ keyring = true;
+#endif
+#ifdef ENABLE_FIPS
+ fips = true;
+#endif
+#ifdef ENABLE_AF_ALG
+ kernel_capi = true;
+#endif
+#if defined(ENABLE_PWQUALITY)
+ pwquality = true;
+#elif defined(ENABLE_PASSWDQC)
+ passwdqc = true;
+#endif
+ log_std("%s %s flags: %s%s%s%s%s%s%s\n", name, PACKAGE_VERSION,
+ udev ? "UDEV " : "",
+ blkid ? "BLKID " : "",
+ keyring ? "KEYRING " : "",
+ fips ? "FIPS " : "",
+ kernel_capi ? "KERNEL_CAPI " : "",
+ pwquality && use_pwlibs ? "PWQUALITY " : "",
+ passwdqc && use_pwlibs ? "PASSWDQC " : "");
+}
diff --git a/src/veritysetup.c b/src/veritysetup.c
new file mode 100644
index 0000000..8be81cc
--- /dev/null
+++ b/src/veritysetup.c
@@ -0,0 +1,680 @@
+/*
+ * veritysetup - setup cryptographic volumes for dm-verity
+ *
+ * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "cryptsetup.h"
+#include "veritysetup_args.h"
+
+#define PACKAGE_VERITY "veritysetup"
+
+static const char **action_argv;
+static int action_argc;
+static struct tools_log_params log_parms;
+
+void tools_cleanup(void)
+{
+ tools_args_free(tool_core_args, ARRAY_SIZE(tool_core_args));
+}
+
+static int _prepare_format(struct crypt_params_verity *params,
+ const char *data_device,
+ uint32_t flags)
+{
+ char *salt = NULL;
+ int len;
+
+ params->hash_name = ARG_STR(OPT_HASH_ID);
+ params->data_device = data_device;
+ params->fec_device = ARG_STR(OPT_FEC_DEVICE_ID);
+ params->fec_roots = ARG_UINT32(OPT_FEC_ROOTS_ID);
+
+ if (ARG_STR(OPT_SALT_ID) && !strcmp(ARG_STR(OPT_SALT_ID), "-")) {
+ params->salt_size = 0;
+ params->salt = NULL;
+ } else if (ARG_SET(OPT_SALT_ID)) {
+ len = crypt_hex_to_bytes(ARG_STR(OPT_SALT_ID), &salt, 0);
+ if (len < 0) {
+ log_err(_("Invalid salt string specified."));
+ return -EINVAL;
+ }
+ params->salt_size = len;
+ params->salt = salt;
+ } else {
+ params->salt_size = DEFAULT_VERITY_SALT_SIZE;
+ params->salt = NULL;
+ }
+
+ params->data_block_size = ARG_UINT32(OPT_DATA_BLOCK_SIZE_ID);
+ params->hash_block_size = ARG_UINT32(OPT_HASH_BLOCK_SIZE_ID);
+ params->data_size = ARG_UINT64(OPT_DATA_BLOCKS_ID);
+ params->hash_area_offset = ARG_UINT64(OPT_HASH_OFFSET_ID);
+ params->fec_area_offset = ARG_UINT64(OPT_FEC_OFFSET_ID);
+ params->hash_type = ARG_UINT32(OPT_FORMAT_ID);
+ params->flags = flags;
+
+ return 0;
+}
+
+static int action_format(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_verity params = {};
+ uint32_t flags = CRYPT_VERITY_CREATE_HASH;
+ char *root_hash_bytes = NULL;
+ size_t root_hash_size;
+ int root_hash_fd = -1, i, r;
+
+ /* Try to create hash image if doesn't exist */
+ r = open(action_argv[1], O_WRONLY | O_EXCL | O_CREAT, S_IRUSR | S_IWUSR);
+ if (r < 0 && errno != EEXIST) {
+ log_err(_("Cannot create hash image %s for writing."), action_argv[1]);
+ return -EINVAL;
+ } else if (r >= 0) {
+ log_dbg("Created hash image %s.", action_argv[1]);
+ close(r);
+ }
+ /* Try to create FEC image if doesn't exist */
+ if (ARG_SET(OPT_FEC_DEVICE_ID)) {
+ r = open(ARG_STR(OPT_FEC_DEVICE_ID), O_WRONLY | O_EXCL | O_CREAT, S_IRUSR | S_IWUSR);
+ if (r < 0 && errno != EEXIST) {
+ log_err(_("Cannot create FEC image %s for writing."), ARG_STR(OPT_FEC_DEVICE_ID));
+ return -EINVAL;
+ } else if (r >= 0) {
+ log_dbg("Created FEC image %s.", ARG_STR(OPT_FEC_DEVICE_ID));
+ close(r);
+ }
+ }
+
+ if ((r = crypt_init(&cd, action_argv[1])))
+ goto out;
+
+ if (ARG_SET(OPT_NO_SUPERBLOCK_ID))
+ flags |= CRYPT_VERITY_NO_HEADER;
+
+ r = _prepare_format(&params, action_argv[0], flags);
+ if (r < 0)
+ goto out;
+
+ r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, ARG_STR(OPT_UUID_ID), NULL, 0, &params);
+ if (r < 0)
+ goto out;
+
+ crypt_dump(cd);
+
+ /* Create or overwrite the root hash file */
+ if (ARG_SET(OPT_ROOT_HASH_FILE_ID)) {
+ root_hash_size = crypt_get_volume_key_size(cd);
+ root_hash_bytes = malloc(root_hash_size);
+ if (!root_hash_bytes) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_bytes, &root_hash_size, NULL, 0);
+ if (r < 0)
+ goto out;
+
+ root_hash_fd = open(ARG_STR(OPT_ROOT_HASH_FILE_ID), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+ if (root_hash_fd == -1) {
+ log_err(_("Cannot create root hash file %s for writing."), ARG_STR(OPT_ROOT_HASH_FILE_ID));
+ r = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < (int)root_hash_size; i++)
+ if (dprintf(root_hash_fd, "%02hhx", root_hash_bytes[i]) != 2) {
+ log_err(_("Cannot write to root hash file %s."), ARG_STR(OPT_ROOT_HASH_FILE_ID));
+ r = -EIO;
+ goto out;
+ }
+
+ log_dbg("Created root hash file %s.", ARG_STR(OPT_ROOT_HASH_FILE_ID));
+ }
+out:
+ crypt_free(cd);
+ free(CONST_CAST(char*)params.salt);
+ free(root_hash_bytes);
+ if (root_hash_fd != -1)
+ close(root_hash_fd);
+ return r;
+}
+
+static int _activate(const char *dm_device,
+ const char *data_device,
+ const char *hash_device,
+ const char *root_hash,
+ uint32_t flags)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_verity params = {};
+ uint32_t activate_flags = CRYPT_ACTIVATE_READONLY;
+ char *root_hash_bytes = NULL, *root_hash_from_file = NULL;
+ ssize_t hash_size, hash_size_hex;
+ struct stat st;
+ char *signature = NULL;
+ int signature_size = 0, root_hash_fd = -1, r;
+
+ if ((r = crypt_init_data_device(&cd, hash_device, data_device)))
+ goto out;
+
+ if (ARG_SET(OPT_IGNORE_CORRUPTION_ID))
+ activate_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION;
+ if (ARG_SET(OPT_RESTART_ON_CORRUPTION_ID))
+ activate_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
+ if (ARG_SET(OPT_PANIC_ON_CORRUPTION_ID))
+ activate_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
+ if (ARG_SET(OPT_IGNORE_ZERO_BLOCKS_ID))
+ activate_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
+ if (ARG_SET(OPT_CHECK_AT_MOST_ONCE_ID))
+ activate_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
+ if (ARG_SET(OPT_USE_TASKLETS_ID))
+ activate_flags |= CRYPT_ACTIVATE_TASKLETS;
+
+ if (!ARG_SET(OPT_NO_SUPERBLOCK_ID)) {
+ params.flags = flags;
+ params.hash_area_offset = ARG_UINT64(OPT_HASH_OFFSET_ID);
+ params.fec_area_offset = ARG_UINT64(OPT_FEC_OFFSET_ID);
+ params.fec_device = ARG_STR(OPT_FEC_DEVICE_ID);
+ params.fec_roots = ARG_UINT32(OPT_FEC_ROOTS_ID);
+ r = crypt_load(cd, CRYPT_VERITY, &params);
+ if (r)
+ log_err(_("Device %s is not a valid VERITY device."), hash_device);
+
+ } else {
+ r = _prepare_format(&params, data_device, flags | CRYPT_VERITY_NO_HEADER);
+ if (r < 0)
+ goto out;
+ r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params);
+ }
+ if (r < 0)
+ goto out;
+
+ hash_size = crypt_get_volume_key_size(cd);
+ hash_size_hex = 2 * hash_size;
+
+ if (!root_hash) {
+ root_hash_fd = open(ARG_STR(OPT_ROOT_HASH_FILE_ID), O_RDONLY);
+ if (root_hash_fd == -1) {
+ log_err(_("Cannot read root hash file %s."), ARG_STR(OPT_ROOT_HASH_FILE_ID));
+ goto out;
+ }
+
+ if (fstat(root_hash_fd, &st) || !S_ISREG(st.st_mode) || st.st_size < hash_size_hex) {
+ log_err(_("Invalid root hash file %s."), ARG_STR(OPT_ROOT_HASH_FILE_ID));
+ r = -EINVAL;
+ goto out;
+ }
+
+ root_hash_from_file = malloc(hash_size_hex + 1);
+ if (!root_hash_from_file) {
+ r = -ENOMEM;
+ goto out;
+ }
+
+ if (read_buffer(root_hash_fd, root_hash_from_file, hash_size_hex) != hash_size_hex) {
+ log_err(_("Cannot read root hash file %s."), root_hash_from_file);
+ goto out;
+ }
+
+ root_hash_from_file[hash_size_hex] = '\0';
+ root_hash = root_hash_from_file;
+ }
+
+ if (crypt_hex_to_bytes(root_hash, &root_hash_bytes, 0) != hash_size) {
+ log_err(_("Invalid root hash string specified."));
+ r = -EINVAL;
+ goto out;
+ }
+
+ if (ARG_SET(OPT_ROOT_HASH_SIGNATURE_ID)) {
+ // FIXME: check max file size
+ if (stat(ARG_STR(OPT_ROOT_HASH_SIGNATURE_ID), &st) || !S_ISREG(st.st_mode) || !st.st_size) {
+ log_err(_("Invalid signature file %s."), ARG_STR(OPT_ROOT_HASH_SIGNATURE_ID));
+ r = -EINVAL;
+ goto out;
+ }
+ signature_size = st.st_size;
+ r = tools_read_vk(ARG_STR(OPT_ROOT_HASH_SIGNATURE_ID), &signature, signature_size);
+ if (r < 0) {
+ log_err(_("Cannot read signature file %s."), ARG_STR(OPT_ROOT_HASH_SIGNATURE_ID));
+ goto out;
+ }
+ }
+ r = crypt_activate_by_signed_key(cd, dm_device,
+ root_hash_bytes,
+ hash_size,
+ signature, signature_size,
+ activate_flags);
+out:
+ crypt_safe_free(signature);
+ crypt_free(cd);
+ free(root_hash_from_file);
+ free(root_hash_bytes);
+ free(CONST_CAST(char*)params.salt);
+ if (root_hash_fd != -1)
+ close(root_hash_fd);
+ return r;
+}
+
+static int action_open(void)
+{
+ if (action_argc < 4 && !ARG_SET(OPT_ROOT_HASH_FILE_ID)) {
+ log_err(_("Command requires <root_hash> or --root-hash-file option as argument."));
+ return -EINVAL;
+ }
+
+ return _activate(action_argv[1],
+ action_argv[0],
+ action_argv[2],
+ ARG_SET(OPT_ROOT_HASH_FILE_ID) ? NULL : action_argv[3],
+ ARG_SET(OPT_ROOT_HASH_SIGNATURE_ID) ? CRYPT_VERITY_ROOT_HASH_SIGNATURE : 0);
+}
+
+static int action_verify(void)
+{
+ if (action_argc < 3 && !ARG_SET(OPT_ROOT_HASH_FILE_ID)) {
+ log_err(_("Command requires <root_hash> or --root-hash-file option as argument."));
+ return -EINVAL;
+ }
+
+ return _activate(NULL,
+ action_argv[0],
+ action_argv[1],
+ ARG_SET(OPT_ROOT_HASH_FILE_ID) ? NULL : action_argv[2],
+ CRYPT_VERITY_CHECK_HASH);
+}
+
+static int action_close(void)
+{
+ struct crypt_device *cd = NULL;
+ crypt_status_info ci;
+ uint32_t flags = 0;
+ int r;
+
+ if (ARG_SET(OPT_DEFERRED_ID))
+ flags |= CRYPT_DEACTIVATE_DEFERRED;
+ if (ARG_SET(OPT_CANCEL_DEFERRED_ID))
+ flags |= CRYPT_DEACTIVATE_DEFERRED_CANCEL;
+
+ r = crypt_init_by_name(&cd, action_argv[0]);
+ if (r == 0)
+ r = crypt_deactivate_by_name(cd, action_argv[0], flags);
+
+ if (!r && ARG_SET(OPT_DEFERRED_ID)) {
+ ci = crypt_status(cd, action_argv[0]);
+ if (ci == CRYPT_ACTIVE || ci == CRYPT_BUSY)
+ log_std(_("Device %s is still active and scheduled for deferred removal.\n"),
+ action_argv[0]);
+ }
+
+ crypt_free(cd);
+ return r;
+}
+
+static int action_status(void)
+{
+ crypt_status_info ci;
+ struct crypt_active_device cad;
+ struct crypt_params_verity vp = {};
+ struct crypt_device *cd = NULL;
+ struct stat st;
+ char *backing_file, *root_hash;
+ size_t root_hash_size;
+ unsigned path = 0;
+ int r = 0;
+
+ /* perhaps a path, not a dm device name */
+ if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
+ path = 1;
+
+ ci = crypt_status(NULL, action_argv[0]);
+ switch (ci) {
+ case CRYPT_INVALID:
+ r = -EINVAL;
+ break;
+ case CRYPT_INACTIVE:
+ if (path)
+ log_std("%s is inactive.\n", action_argv[0]);
+ else
+ log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
+ r = -ENODEV;
+ break;
+ case CRYPT_ACTIVE:
+ case CRYPT_BUSY:
+ if (path)
+ log_std("%s is active%s.\n", action_argv[0],
+ ci == CRYPT_BUSY ? " and is in use" : "");
+ else
+ log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
+ ci == CRYPT_BUSY ? " and is in use" : "");
+
+ r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
+ if (r < 0)
+ goto out;
+
+ log_std(" type: %s\n", crypt_get_type(cd) ?: "n/a");
+
+ r = crypt_get_active_device(cd, action_argv[0], &cad);
+ if (r < 0)
+ goto out;
+
+ /* Print only VERITY type devices */
+ r = crypt_get_verity_info(cd, &vp);
+ if (r < 0)
+ goto out;
+
+ log_std(" status: %s%s\n",
+ cad.flags & CRYPT_ACTIVATE_CORRUPTED ? "corrupted" : "verified",
+ vp.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE ? " (with signature)" : "");
+
+ log_std(" hash type: %u\n", vp.hash_type);
+ log_std(" data block: %u\n", vp.data_block_size);
+ log_std(" hash block: %u\n", vp.hash_block_size);
+ log_std(" hash name: %s\n", vp.hash_name);
+ log_std(" salt: ");
+ if (vp.salt_size)
+ crypt_log_hex(NULL, vp.salt, vp.salt_size, "", 0, NULL);
+ else
+ log_std("-");
+ log_std("\n");
+
+ log_std(" data device: %s\n", vp.data_device);
+ if ((backing_file = crypt_loop_backing_file(vp.data_device))) {
+ log_std(" data loop: %s\n", backing_file);
+ free(backing_file);
+ }
+ log_std(" size: %" PRIu64 " sectors\n", cad.size);
+ log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
+ "readonly" : "read/write");
+
+ log_std(" hash device: %s\n", vp.hash_device);
+ if ((backing_file = crypt_loop_backing_file(vp.hash_device))) {
+ log_std(" hash loop: %s\n", backing_file);
+ free(backing_file);
+ }
+ log_std(" hash offset: %" PRIu64 " sectors\n",
+ vp.hash_area_offset * vp.hash_block_size / 512);
+
+ if (vp.fec_device) {
+ log_std(" FEC device: %s\n", vp.fec_device);
+ if ((backing_file = crypt_loop_backing_file(ARG_STR(OPT_FEC_DEVICE_ID)))) {
+ log_std(" FEC loop: %s\n", backing_file);
+ free(backing_file);
+ }
+ log_std(" FEC offset: %" PRIu64 " sectors\n",
+ vp.fec_area_offset * vp.hash_block_size / 512);
+ log_std(" FEC roots: %u\n", vp.fec_roots);
+ }
+
+ root_hash_size = crypt_get_volume_key_size(cd);
+ if (root_hash_size > 0 && (root_hash = malloc(root_hash_size))) {
+ r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash, &root_hash_size, NULL, 0);
+ if (!r) {
+ log_std(" root hash: ");
+ crypt_log_hex(NULL, root_hash, root_hash_size, "", 0, NULL);
+ log_std("\n");
+ }
+ free(root_hash);
+ }
+
+ if (cad.flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
+ CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
+ CRYPT_ACTIVATE_PANIC_ON_CORRUPTION|
+ CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
+ CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE|
+ CRYPT_ACTIVATE_TASKLETS))
+ log_std(" flags: %s%s%s%s%s%s\n",
+ (cad.flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? "ignore_corruption " : "",
+ (cad.flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? "restart_on_corruption " : "",
+ (cad.flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? "panic_on_corruption " : "",
+ (cad.flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? "ignore_zero_blocks " : "",
+ (cad.flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? "check_at_most_once" : "",
+ (cad.flags & CRYPT_ACTIVATE_TASKLETS) ? "try_verify_in_tasklet" : "");
+ }
+out:
+ crypt_free(cd);
+ if (r == -ENOTSUP)
+ r = 0;
+ return r;
+}
+
+static int action_dump(void)
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_verity params = {};
+ int r;
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ return r;
+
+ params.hash_area_offset = ARG_UINT64(OPT_HASH_OFFSET_ID);
+ params.fec_area_offset = ARG_UINT64(OPT_FEC_OFFSET_ID);
+ params.fec_device = ARG_STR(OPT_FEC_DEVICE_ID);
+ params.fec_roots = ARG_UINT32(OPT_FEC_ROOTS_ID);
+
+ r = crypt_load(cd, CRYPT_VERITY, &params);
+ if (!r)
+ crypt_dump(cd);
+ else
+ log_err(_("Device %s is not a valid VERITY device."), action_argv[0]);
+
+ crypt_free(cd);
+ return r;
+}
+
+static struct action_type {
+ const char *type;
+ int (*handler)(void);
+ int required_action_argc;
+ const char *arg_desc;
+ const char *desc;
+} action_types[] = {
+ { "format", action_format, 2, N_("<data_device> <hash_device>"),N_("format device") },
+ { "verify", action_verify, 2, N_("<data_device> <hash_device> [<root_hash>]"),N_("verify device") },
+ { "open", action_open, 3, N_("<data_device> <name> <hash_device> [<root_hash>]"),N_("open device as <name>") },
+ { "close", action_close, 1, N_("<name>"),N_("close device (remove mapping)") },
+ { "status", action_status, 1, N_("<name>"),N_("show active device status") },
+ { "dump", action_dump, 1, N_("<hash_device>"),N_("show on-disk information") },
+ { NULL, NULL, 0, NULL, NULL }
+};
+
+static void help(poptContext popt_context,
+ enum poptCallbackReason reason __attribute__((unused)),
+ struct poptOption *key,
+ const char *arg __attribute__((unused)),
+ void *data __attribute__((unused)))
+{
+ struct action_type *action;
+
+ if (key->shortName == '?') {
+ tools_package_version(PACKAGE_VERITY, false);
+ poptPrintHelp(popt_context, stdout, 0);
+ log_std(_("\n"
+ "<action> is one of:\n"));
+ for(action = action_types; action->type; action++)
+ log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
+ log_std(_("\n"
+ "<name> is the device to create under %s\n"
+ "<data_device> is the data device\n"
+ "<hash_device> is the device containing verification data\n"
+ "<root_hash> hash of the root node on <hash_device>\n"),
+ crypt_get_dir());
+
+ log_std(_("\nDefault compiled-in dm-verity parameters:\n"
+ "\tHash: %s, Data block (bytes): %u, "
+ "Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"),
+ DEFAULT_VERITY_HASH, DEFAULT_VERITY_DATA_BLOCK,
+ DEFAULT_VERITY_HASH_BLOCK, DEFAULT_VERITY_SALT_SIZE,
+ 1);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(EXIT_SUCCESS);
+ } else if (key->shortName == 'V') {
+ tools_package_version(PACKAGE_VERITY, false);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ exit(EXIT_SUCCESS);
+ } else
+ usage(popt_context, EXIT_SUCCESS, NULL, NULL);
+}
+
+static int run_action(struct action_type *action)
+{
+ int r;
+
+ log_dbg("Running command %s.", action->type);
+
+ r = action->handler();
+
+ show_status(r);
+ return translate_errno(r);
+}
+
+static void basic_options_cb(poptContext popt_context,
+ enum poptCallbackReason reason __attribute__((unused)),
+ struct poptOption *key,
+ const char *arg,
+ void *data __attribute__((unused)))
+{
+ tools_parse_arg_value(popt_context, tool_core_args[key->val].type, tool_core_args + key->val, arg, key->val, NULL);
+
+ switch (key->val) {
+ case OPT_DEBUG_ID:
+ log_parms.debug = true;
+ /* fall through */
+ case OPT_VERBOSE_ID:
+ log_parms.verbose = true;
+ }
+}
+
+int main(int argc, const char **argv)
+{
+ static const char *null_action_argv[] = {NULL};
+ static struct poptOption popt_help_options[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, help, 0, NULL, NULL },
+ { "help", '?', POPT_ARG_NONE, NULL, 0, N_("Show this help message"), NULL },
+ { "usage", '\0', POPT_ARG_NONE, NULL, 0, N_("Display brief usage"), NULL },
+ { "version",'V', POPT_ARG_NONE, NULL, 0, N_("Print package version"), NULL },
+ POPT_TABLEEND
+ };
+ static struct poptOption popt_basic_options[] = {
+ { NULL, '\0', POPT_ARG_CALLBACK, basic_options_cb, 0, NULL, NULL },
+#define ARG(A, B, C, D, E, F, G, H) { A, B, C, NULL, A ## _ID, D, E },
+#include "veritysetup_arg_list.h"
+#undef ARG
+ POPT_TABLEEND
+ };
+ static struct poptOption popt_options[] = {
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
+ { NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_basic_options, 0, NULL, NULL },
+ POPT_TABLEEND
+ };
+
+ poptContext popt_context;
+ struct action_type *action;
+ const char *aname;
+ int r;
+
+ crypt_set_log_callback(NULL, tool_log, &log_parms);
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ popt_context = poptGetContext("verity", argc, argv, popt_options, 0);
+ poptSetOtherOptionHelp(popt_context,
+ _("[OPTION...] <action> <action-specific>"));
+
+ while((r = poptGetNextOpt(popt_context)) > 0) {}
+
+ if (r < -1)
+ usage(popt_context, EXIT_FAILURE, poptStrerror(r),
+ poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
+
+ if (!(aname = poptGetArg(popt_context)))
+ usage(popt_context, EXIT_FAILURE, _("Argument <action> missing."),
+ poptGetInvocationName(popt_context));
+
+ action_argc = 0;
+ action_argv = poptGetArgs(popt_context);
+ /* Make return values of poptGetArgs more consistent in case of remaining argc = 0 */
+ if(!action_argv)
+ action_argv = null_action_argv;
+
+ /* Count args, somewhat unnice, change? */
+ while(action_argv[action_argc] != NULL)
+ action_argc++;
+
+ /* Handle aliases */
+ if (!strcmp(aname, "create") && action_argc > 1) {
+ /* create command had historically switched arguments */
+ if (action_argv[0] && action_argv[1]) {
+ const char *tmp = action_argv[0];
+ action_argv[0] = action_argv[1];
+ action_argv[1] = tmp;
+ }
+ aname = "open";
+ } else if (!strcmp(aname, "remove")) {
+ aname = "close";
+ }
+
+ for (action = action_types; action->type; action++)
+ if (strcmp(action->type, aname) == 0)
+ break;
+
+ if (!action->type)
+ usage(popt_context, EXIT_FAILURE, _("Unknown action."),
+ poptGetInvocationName(popt_context));
+
+ if (action_argc < action->required_action_argc) {
+ char buf[128];
+ if (snprintf(buf, 128,_("%s: requires %s as arguments"), action->type, action->arg_desc) < 0)
+ buf[0] = '\0';
+ usage(popt_context, EXIT_FAILURE, buf,
+ poptGetInvocationName(popt_context));
+ }
+
+ tools_check_args(action->type, tool_core_args, ARRAY_SIZE(tool_core_args), popt_context);
+
+ if (ARG_SET(OPT_IGNORE_CORRUPTION_ID) && ARG_SET(OPT_RESTART_ON_CORRUPTION_ID))
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --ignore-corruption and --restart-on-corruption cannot be used together."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_PANIC_ON_CORRUPTION_ID) && ARG_SET(OPT_RESTART_ON_CORRUPTION_ID))
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --panic-on-corruption and --restart-on-corruption cannot be used together."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_CANCEL_DEFERRED_ID) && ARG_SET(OPT_DEFERRED_ID))
+ usage(popt_context, EXIT_FAILURE,
+ _("Options --cancel-deferred and --deferred cannot be used at the same time."),
+ poptGetInvocationName(popt_context));
+
+ if (ARG_SET(OPT_DEBUG_ID)) {
+ crypt_set_debug_level(CRYPT_DEBUG_ALL);
+ dbg_version_and_cmd(argc, argv);
+ }
+
+ r = run_action(action);
+ tools_cleanup();
+ poptFreeContext(popt_context);
+ return r;
+}
diff --git a/src/veritysetup_arg_list.h b/src/veritysetup_arg_list.h
new file mode 100644
index 0000000..014273e
--- /dev/null
+++ b/src/veritysetup_arg_list.h
@@ -0,0 +1,70 @@
+/*
+ * Veritysetup command line arguments list
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* long name, short name, popt type, help description, units, internal argument type, default value, allowed actions (empty=global) */
+
+ARG(OPT_CANCEL_DEFERRED, '\0', POPT_ARG_NONE, N_("Cancel a previously set deferred device removal"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS)
+
+ARG(OPT_CHECK_AT_MOST_ONCE, '\0', POPT_ARG_NONE, N_("Verify data block only the first time it is read"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DATA_BLOCK_SIZE, '\0', POPT_ARG_STRING, N_("Block size on the data device"), N_("bytes"), CRYPT_ARG_UINT32, { .u32_value = DEFAULT_VERITY_DATA_BLOCK }, {})
+
+ARG(OPT_DATA_BLOCKS, '\0', POPT_ARG_STRING, N_("The number of blocks in the data file"), N_("blocks"), CRYPT_ARG_UINT64, {}, {})
+
+ARG(OPT_DEBUG, '\0', POPT_ARG_NONE, N_("Show debug messages"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_DEFERRED, '\0', POPT_ARG_NONE, N_("Device removal is deferred until the last user closes it"), NULL, CRYPT_ARG_BOOL, {}, OPT_DEFERRED_ACTIONS)
+
+ARG(OPT_FEC_DEVICE, '\0', POPT_ARG_STRING, N_("Path to device with error correction data"), N_("path"), CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_FEC_OFFSET, '\0', POPT_ARG_STRING, N_("Starting offset on the FEC device"), N_("bytes"), CRYPT_ARG_UINT64, {}, {})
+
+ARG(OPT_FEC_ROOTS, '\0', POPT_ARG_STRING, N_("FEC parity bytes"), N_("bytes"), CRYPT_ARG_UINT32, { .u32_value = DEFAULT_VERITY_FEC_ROOTS }, {})
+
+ARG(OPT_FORMAT, '\0', POPT_ARG_STRING, N_("Format type (1 - normal, 0 - original Chrome OS)"), N_("number"), CRYPT_ARG_UINT32, { .u32_value = 1 }, {})
+
+ARG(OPT_HASH, 'h', POPT_ARG_STRING, N_("Hash algorithm"), N_("string"), CRYPT_ARG_STRING, { .str_value = CONST_CAST(void *)DEFAULT_VERITY_HASH }, {})
+
+ARG(OPT_HASH_BLOCK_SIZE, '\0', POPT_ARG_STRING, N_("Block size on the hash device"), N_("bytes"), CRYPT_ARG_UINT32, { .u32_value = DEFAULT_VERITY_HASH_BLOCK }, {})
+
+ARG(OPT_HASH_OFFSET, '\0', POPT_ARG_STRING, N_("Starting offset on the hash device"), N_("bytes"), CRYPT_ARG_UINT64, {}, {})
+
+ARG(OPT_IGNORE_CORRUPTION, '\0', POPT_ARG_NONE, N_("Ignore corruption, log it only"), NULL, CRYPT_ARG_BOOL, {}, OPT_IGNORE_CORRUPTION_ACTIONS)
+
+ARG(OPT_IGNORE_ZERO_BLOCKS, '\0', POPT_ARG_NONE, N_("Do not verify zeroed blocks"), NULL, CRYPT_ARG_BOOL, {}, OPT_IGNORE_ZERO_BLOCKS_ACTIONS)
+
+ARG(OPT_NO_SUPERBLOCK, '\0', POPT_ARG_NONE, N_("Do not use verity superblock"), NULL, CRYPT_ARG_BOOL, {}, {})
+
+ARG(OPT_PANIC_ON_CORRUPTION, '\0', POPT_ARG_NONE, N_("Panic kernel if corruption is detected"), NULL, CRYPT_ARG_BOOL, {}, OPT_PANIC_ON_CORRUPTION_ACTIONS)
+
+ARG(OPT_RESTART_ON_CORRUPTION, '\0', POPT_ARG_NONE, N_("Restart kernel if corruption is detected"), NULL, CRYPT_ARG_BOOL, {}, OPT_RESTART_ON_CORRUPTION_ACTIONS)
+
+ARG(OPT_ROOT_HASH_FILE, '\0', POPT_ARG_STRING, N_("Path to root hash file"), NULL, CRYPT_ARG_STRING, {}, OPT_ROOT_HASH_FILE_ACTIONS)
+
+ARG(OPT_ROOT_HASH_SIGNATURE, '\0', POPT_ARG_STRING, N_("Path to root hash signature file"), NULL, CRYPT_ARG_STRING, {}, OPT_ROOT_HASH_SIGNATURE_ACTIONS)
+
+ARG(OPT_SALT, 's', POPT_ARG_STRING, N_("Salt"), N_("hex string"), CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_USE_TASKLETS, '\0', POPT_ARG_NONE, N_("Use kernel tasklets for performance"), NULL, CRYPT_ARG_BOOL, {}, OPT_USE_TASKLETS_ACTIONS)
+
+ARG(OPT_UUID, '\0', POPT_ARG_STRING, N_("UUID for device to use"), NULL, CRYPT_ARG_STRING, {}, {})
+
+ARG(OPT_VERBOSE, 'v', POPT_ARG_NONE, N_("Shows more detailed error messages"), NULL, CRYPT_ARG_BOOL, {}, {})
diff --git a/src/veritysetup_args.h b/src/veritysetup_args.h
new file mode 100644
index 0000000..d47813d
--- /dev/null
+++ b/src/veritysetup_args.h
@@ -0,0 +1,57 @@
+/*
+ * Command line arguments helpers
+ *
+ * Copyright (C) 2020-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2020-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef VERITYSETUP_ARGS_H
+#define VERITYSETUP_ARGS_H
+
+#include "utils_arg_names.h"
+#include "utils_arg_macros.h"
+
+#define CLOSE_ACTION "close"
+#define DUMP_ACTION "dump"
+#define FORMAT_ACTION "format"
+#define OPEN_ACTION "open"
+#define STATUS_ACTION "status"
+#define VERIFY_ACTION "verify"
+
+#define OPT_DEFERRED_ACTIONS { CLOSE_ACTION }
+#define OPT_IGNORE_CORRUPTION_ACTIONS { OPEN_ACTION }
+#define OPT_IGNORE_ZERO_BLOCKS_ACTIONS { OPEN_ACTION }
+#define OPT_RESTART_ON_CORRUPTION_ACTIONS { OPEN_ACTION }
+#define OPT_PANIC_ON_CORRUPTION_ACTIONS { OPEN_ACTION }
+#define OPT_ROOT_HASH_FILE_ACTIONS { FORMAT_ACTION, OPEN_ACTION, VERIFY_ACTION }
+#define OPT_ROOT_HASH_SIGNATURE_ACTIONS { OPEN_ACTION }
+#define OPT_USE_TASKLETS_ACTIONS { OPEN_ACTION }
+
+enum {
+OPT_UNUSED_ID = 0,
+#define ARG(A, B, C, D, E, F, G, H) A ## _ID,
+#include "veritysetup_arg_list.h"
+#undef ARG
+};
+
+static struct tools_arg tool_core_args[] = { { NULL, false, CRYPT_ARG_BOOL }, // UNUSED
+#define ARG(A, B, C, D, E, F, G, H) { A, false, F, G, H },
+#include "veritysetup_arg_list.h"
+#undef ARG
+};
+
+#endif
diff --git a/tests/00modules-test b/tests/00modules-test
new file mode 100755
index 0000000..f816b80
--- /dev/null
+++ b/tests/00modules-test
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+
+function pversion() {
+ if [ ! -x $CRYPTSETUP_PATH/$1 ] ; then
+ return
+ fi
+
+ echo -n "$CRYPTSETUP_PATH/"
+ $CRYPTSETUP_PATH/$1 --version
+}
+
+echo "Cryptsetup test environment ($(date))"
+uname -a
+if [ "$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)" = "1" ] ; then
+ echo "Kernel running in FIPS mode."
+fi
+
+if [ -f /etc/os-release ] ; then
+ source /etc/os-release
+ echo "$PRETTY_NAME ($NAME) $VERSION"
+fi
+
+echo "Memory"
+free -m
+
+pversion cryptsetup
+pversion veritysetup
+pversion integritysetup
+
+[ -x $CRYPTSETUP_PATH/cryptsetup ] && {
+ echo -e "Cryptsetup defaults:"
+ $CRYPTSETUP_PATH/cryptsetup --help | sed -n '/optional key file for/,$p' | tail -n +3
+}
+
+[ $(id -u) != 0 ] && exit 77
+
+modprobe dm-crypt >/dev/null 2>&1
+modprobe dm-verity >/dev/null 2>&1
+modprobe dm-integrity >/dev/null 2>&1
+modprobe dm-zero >/dev/null 2>&1
+
+dmsetup version
+
+echo "Device mapper targets:"
+dmsetup targets
+
+exit 0
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..c8a46a8
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,206 @@
+TESTS = 00modules-test \
+ api-test \
+ api-test-2 \
+ compat-args-test \
+ compat-test \
+ compat-test2 \
+ loopaes-test \
+ align-test \
+ align-test2 \
+ discards-test \
+ mode-test \
+ password-hash-test \
+ tcrypt-compat-test \
+ luks1-compat-test \
+ device-test \
+ keyring-test \
+ keyring-compat-test \
+ luks2-validation-test \
+ luks2-integrity-test \
+ vectors-test \
+ blockwise-compat-test \
+ bitlk-compat-test \
+ fvault2-compat-test \
+ run-all-symbols \
+ unit-utils-crypt-test \
+ unit-wipe-test \
+ reencryption-compat-test \
+ luks2-reencryption-test \
+ luks2-reencryption-mangle-test
+
+if VERITYSETUP
+TESTS += verity-compat-test
+endif
+
+if INTEGRITYSETUP
+TESTS += integrity-compat-test
+endif
+
+if SSHPLUGIN_TOKEN
+TESTS += ssh-test-plugin
+endif
+
+if EXTERNAL_TOKENS
+TESTS += systemd-test-plugin
+endif
+
+ssh-test-plugin: fake_token_path.so
+systemd-test-plugin: fake_token_path.so fake_systemd_tpm_path.so
+
+# Do not use global CFLAGS here as the *.so link does not support sanitizers
+fake_token_path.so: fake_token_path.c
+ $(CC) $(LDFLAGS) -I $(top_srcdir)/lib -fPIC -shared -D_GNU_SOURCE \
+ -Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
+ -o fake_token_path.so $(top_srcdir)/tests/fake_token_path.c \
+ -DBUILD_DIR=\"$(abs_top_srcdir)/.libs/\"
+
+fake_systemd_tpm_path.so: fake_systemd_tpm_path.c
+ $(CC) $(LDFLAGS) -fPIC -shared -D_GNU_SOURCE -o fake_systemd_tpm_path.so \
+ $(top_srcdir)/tests/fake_systemd_tpm_path.c
+
+EXTRA_DIST = compatimage.img.xz compatv10image.img.xz \
+ compatimage2.img.xz \
+ conversion_imgs.tar.xz \
+ luks2_keyslot_unassigned.img.xz \
+ img_fs_ext4.img.xz img_fs_vfat.img.xz img_fs_xfs.img.xz \
+ xfs_512_block_size.img.xz \
+ valid_header_file.xz \
+ luks2_valid_hdr.img.xz \
+ luks2_header_requirements.tar.xz \
+ luks2_mda_images.tar.xz \
+ evil_hdr-payload_overwrite.xz \
+ evil_hdr-stripes_payload_dmg.xz \
+ evil_hdr-luks_hdr_damage.xz \
+ evil_hdr-small_luks_device.xz \
+ evil_hdr-keyslot_overlap.xz \
+ tcrypt-images.tar.xz \
+ luks1-images.tar.xz \
+ 00modules-test \
+ compat-args-test \
+ compat-test \
+ compat-test2 \
+ loopaes-test align-test discards-test mode-test password-hash-test \
+ align-test2 verity-compat-test \
+ reencryption-compat-test \
+ luks2-reencryption-test \
+ luks2-reencryption-mangle-test \
+ tcrypt-compat-test \
+ luks1-compat-test \
+ luks2-validation-test generators \
+ luks2-integrity-test \
+ device-test \
+ keyring-test \
+ keyring-compat-test \
+ integrity-compat-test \
+ cryptsetup-valg-supps valg.sh valg-api.sh \
+ blockwise-compat-test \
+ blkid-luks2-pv.img.xz \
+ Makefile.localtest \
+ bitlk-compat-test \
+ bitlk-images.tar.xz \
+ fvault2-compat-test \
+ fvault2-images.tar.xz \
+ ssh-test-plugin \
+ generate-symbols-list \
+ run-all-symbols \
+ fake_token_path.c \
+ fake_systemd_tpm_path.c \
+ unit-wipe-test \
+ systemd-test-plugin
+
+CLEANFILES = cryptsetup-tst* valglog* *-fail-*.log test-symbols-list.h fake_token_path.so fake_systemd_tpm_path.so
+clean-local:
+ -rm -rf tcrypt-images luks1-images luks2-images bitlk-images fvault2-images conversion_imgs luks2_valid_hdr.img blkid-luks2-pv-img blkid-luks2-pv-img.bcp external-tokens
+
+differ_SOURCES = differ.c
+differ_CFLAGS = $(AM_CFLAGS) -Wall -O2
+
+api_test_SOURCES = api-test.c api_test.h test_utils.c
+api_test_LDADD = ../libcryptsetup.la
+api_test_LDFLAGS = $(AM_LDFLAGS) -static
+api_test_CFLAGS = -g -Wall -O0 $(AM_CFLAGS) -I$(top_srcdir)/lib
+api_test_CPPFLAGS = $(AM_CPPFLAGS) -include config.h
+
+api_test_2_SOURCES = api-test-2.c api_test.h test_utils.c
+api_test_2_LDADD = ../libcryptsetup.la
+api_test_2_LDFLAGS = $(AM_LDFLAGS) -static
+api_test_2_CFLAGS = -g -Wall -O0 $(AM_CFLAGS) -I$(top_srcdir)/lib
+api_test_2_CPPFLAGS = $(AM_CPPFLAGS) -include config.h
+
+vectors_test_SOURCES = crypto-vectors.c
+vectors_test_LDADD = ../libcrypto_backend.la @CRYPTO_LIBS@ @LIBARGON2_LIBS@
+vectors_test_LDFLAGS = $(AM_LDFLAGS) -static
+vectors_test_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib @CRYPTO_CFLAGS@
+vectors_test_CPPFLAGS = $(AM_CPPFLAGS) -include config.h
+
+unit_utils_io_SOURCES = unit-utils-io.c
+unit_utils_io_LDADD = ../libutils_io.la
+unit_utils_io_LDFLAGS = $(AM_LDFLAGS) -static
+unit_utils_io_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib
+unit_utils_io_CPPFLAGS = $(AM_CPPFLAGS) -include config.h
+
+unit_utils_crypt_test_SOURCES = unit-utils-crypt.c ../lib/utils_crypt.c ../lib/utils_crypt.h
+unit_utils_crypt_test_LDADD = ../libcryptsetup.la
+unit_utils_crypt_test_LDFLAGS = $(AM_LDFLAGS) -static
+unit_utils_crypt_test_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib
+unit_utils_crypt_test_CPPFLAGS = $(AM_CPPFLAGS) -include config.h
+
+unit_wipe_SOURCES = unit-wipe.c
+unit_wipe_LDADD = ../libcryptsetup.la
+unit_wipe_LDFLAGS = $(AM_LDFLAGS) -static
+unit_wipe_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/lib
+unit_wipe_CPPFLAGS = $(AM_CPPFLAGS)
+
+BUILT_SOURCES = test-symbols-list.h
+
+test-symbols-list.h: $(top_srcdir)/lib/libcryptsetup.sym generate-symbols-list
+ $(srcdir)/generate-symbols-list $(top_srcdir)/lib/libcryptsetup.sym > $(builddir)/test-symbols-list.h
+
+all_symbols_test_SOURCES = all-symbols-test.c
+nodist_all_symbols_test_SOURCES = test-symbols-list.h
+all_symbols_test.$(OBJEXT): test-symbols-list.h
+all_symbols_test_LDFLAGS = $(AM_LDFLAGS) -ldl
+all_symbols_test_CFLAGS = $(AM_CFLAGS)
+all_symbols_test_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE
+
+check_PROGRAMS = api-test api-test-2 differ vectors-test unit-utils-io unit-utils-crypt-test unit-wipe all-symbols-test
+
+check-programs: test-symbols-list.h $(check_PROGRAMS) fake_token_path.so fake_systemd_tpm_path.so
+
+conversion_imgs:
+ @tar xJf conversion_imgs.tar.xz
+
+compatimage.img:
+ @xz -k -d compatimage.img.xz
+
+valgrind-check: api-test api-test-2 differ
+ @VALG=1 ./compat-args-test
+ @VALG=1 ./compat-test
+ @VALG=1 ./compat-test2
+ @VALG=1 ./luks2-validation-test
+ @VALG=1 ./verity-compat-test
+ @VALG=1 ./integrity-compat-test
+ @INFOSTRING="api-test-000" ./valg-api.sh ./api-test
+ @INFOSTRING="api-test-002" ./valg-api.sh ./api-test-2
+ @VALG=1 ./luks2-reencryption-test
+ @VALG=1 ./luks2-reencryption-mangle-test
+ @VALG=1 ./bitlk-compat-test
+ @VALG=1 ./tcrypt-compat-test
+ @VALG=1 ./align-test
+ @VALG=1 ./align-test2
+ @VALG=1 ./device-test
+ @VALG=1 ./discards-test
+ @VALG=1 ./keyring-compat-test
+ @VALG=1 ./loopaes-test
+ @VALG=1 ./luks1-compat-test
+ @VALG=1 ./luks2-integrity-test
+ @VALG=1 ./mode-test
+ @VALG=1 ./password-hash-test
+ @VALG=1 ./reencryption-compat-test
+ @VALG=1 ./fvault2-compat-test
+ @[ -z "$RUN_SSH_PLUGIN_TEST" ] || VALG=1 ./ssh-test-plugin
+ @INFOSTRING="unit-utils-crypt-test" ./valg-api.sh ./unit-utils-crypt-test
+ @INFOSTRING="vectors-test" ./valg-api.sh ./vectors-test
+ @grep -l "ERROR SUMMARY: [^0][0-9]* errors" valglog* || echo "No leaks detected."
+
+.PHONY: valgrind-check
diff --git a/tests/Makefile.localtest b/tests/Makefile.localtest
new file mode 100644
index 0000000..89ce2c3
--- /dev/null
+++ b/tests/Makefile.localtest
@@ -0,0 +1,66 @@
+#
+# Makefile to run tests with system binaries
+# USE: make -f Makefile.localtest tests CRYPTSETUP_PATH=/sbin
+# (append TESTSUITE_NOSKIP=y to avoid treating skipped tests as success)
+#
+CPPFLAGS=-I../lib/ -I../lib/luks1 -DHAVE_DECL_DM_TASK_RETRY_REMOVE -DKERNEL_KEYRING \
+ -DHAVE_SYS_SYSMACROS_H -DNO_CRYPTSETUP_PATH
+CFLAGS=-O2 -g -Wall -D_GNU_SOURCE
+LDLIBS=-lcryptsetup -ldevmapper
+TESTS=$(wildcard *-test *-test2) api-test api-test-2 all-symbols-test unit-utils-crypt-test
+TESTS_UTILS=differ unit-utils-io unit-wipe
+
+ifneq ($(RUN_SSH_PLUGIN_TEST),)
+TESTS += ssh-test-plugin
+endif
+
+ifneq ($(RUN_SYSTEMD_PLUGIN_TEST),)
+TESTS += systemd-test-plugin
+TESTS_UTILS += fake_systemd_tpm_path.so
+endif
+
+check-programs: $(TESTS_UTILS) $(TESTS)
+
+differ: differ.o
+ $(CC) -o $@ $^
+
+api-test: api-test.o test_utils.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+api-test-2: api-test-2.o test_utils.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+unit-wipe: unit-wipe.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+unit-utils-io: unit-utils-io.o ../lib/utils_io.o
+ $(CC) -o $@ $^
+
+unit-utils-crypt-test: unit-utils-crypt.o ../lib/utils_crypt.o
+ $(CC) -o $@ $^ $(LDLIBS)
+
+test-symbols-list.h: generate-symbols-list
+ ./generate-symbols-list ../lib/libcryptsetup.sym > test-symbols-list.h
+
+all-symbols-test.o: test-symbols-list.h
+ $(CC) -c $*.c
+
+all-symbols-test: all-symbols-test.o
+ $(CC) -o $@ $^ -ldl
+
+fake_systemd_tpm_path.so: fake_systemd_tpm_path.c
+ $(CC) -fPIC -shared -D_GNU_SOURCE -o fake_systemd_tpm_path.so fake_systemd_tpm_path.c
+
+tests: $(TESTS_UTILS) $(TESTS)
+ @for test in $(sort $(TESTS)); do \
+ echo [$$test]; \
+ ./$$test; \
+ [ $(if $(TESTSUITE_NOSKIP),,$$? -ne 77 -a) $$? -ne 0 ] && exit 1; \
+ true; \
+ done;
+
+clean:
+ rm -f *.o $(TESTS_UTILS) api-test api-test-2 unit-utils-crypt-test \
+ all-symbols-test test-symbols-list.h
+
+.PHONY: clean
diff --git a/tests/align-test b/tests/align-test
new file mode 100755
index 0000000..5941cde
--- /dev/null
+++ b/tests/align-test
@@ -0,0 +1,341 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+DEV=""
+DEV_STACKED="luks0xbabe"
+DEV_NAME="dummyalign"
+MNT_DIR="./mnt_luks"
+PWD1="93R4P4pIqAH8"
+PWD2="mymJeD8ivEhE"
+FAST_PBKDF="--pbkdf-force-iterations 1000"
+
+FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+cleanup() {
+ udevadm settle >/dev/null 2>&1
+ if [ -d "$MNT_DIR" ] ; then
+ umount -f $MNT_DIR 2>/dev/null
+ rmdir $MNT_DIR 2>/dev/null
+ fi
+ [ -b /dev/mapper/$DEV_STACKED ] && dmsetup remove --retry $DEV_STACKED >/dev/null 2>&1
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME >/dev/null 2>&1
+ # FIXME scsi_debug sometimes in-use here
+ sleep 1
+ rmmod scsi_debug >/dev/null 2>&1
+ sleep 1
+}
+
+fail()
+{
+ if [ -n "$1" ] ; then echo "FAIL $1" ; fi
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ echo "TEST SKIPPED: $1"
+ cleanup
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function dm_crypt_features()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ [ $VER_MAJ -lt 1 ] && return
+ [ $VER_MAJ -gt 1 ] && {
+ DM_PERF_CPU=1
+ DM_SECTOR_SIZE=1
+ return
+ }
+
+ [ $VER_MIN -lt 14 ] && return
+ DM_PERF_CPU=1
+ if [ $VER_MIN -ge 17 -o \( $VER_MIN -eq 14 -a $VER_PTC -ge 5 \) ]; then
+ DM_SECTOR_SIZE=1
+ fi
+}
+
+add_device() {
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 2
+ DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+
+ if [ ! -e /sys/block/$DEV/alignment_offset ] ; then
+ echo "This kernel seems to not support topology info, test skipped."
+ cleanup
+ exit 77
+ fi
+
+ DEV="/dev/$DEV"
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+format() # key_bits expected [forced]
+{
+ if [ -z "$3" ] ; then
+ echo -n "Formatting using topology info ($1 bits key)..."
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $DEV -q $FAST_PBKDF -c aes-cbc-essiv:sha256 -s $1 || fail
+ else
+ echo -n "Formatting using forced sector alignment $3 ($1 bits key)..."
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $DEV -q $FAST_PBKDF -s $1 -c aes-cbc-essiv:sha256 --align-payload=$3 ||fail
+ fi
+
+ # check the device can be activated
+ echo $PWD1 | $CRYPTSETUP luksOpen $DEV $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ ALIGN=$($CRYPTSETUP luksDump $DEV |grep "Payload offset" | sed -e s/.*\\t//)
+ #echo "ALIGN = $ALIGN"
+
+ [ -z "$ALIGN" ] && fail
+ [ $ALIGN -ne $2 ] && fail "Expected alignment differs: expected $2 != detected $ALIGN"
+
+ # test some operation, just in case
+ echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $DEV $FAST_PBKDF --new-key-slot 1
+ [ $? -ne 0 ] && fail "Keyslot add failed."
+
+ $CRYPTSETUP -q luksKillSlot $DEV 1
+ [ $? -ne 0 ] && fail "Keyslot removal failed."
+
+ echo "PASSED"
+}
+
+get_offsets()
+{
+ $CRYPTSETUP luksDump $DEV | grep "$1" | cut -s -d ':' -f 2 | sed -e 's/\s//g' -e :a -e N -e 's/\n/:/g' -e 's/\s//g' -e ta
+}
+
+format_null()
+{
+ if [ $3 -eq 0 ] ; then
+ echo -n "Formatting using topology info ($1 bits key) [slot 0"
+ echo | $CRYPTSETUP luksFormat --type luks1 $DEV -q $FAST_PBKDF -c null -s $1 || fail
+ else
+ echo -n "Formatting using forced sector alignment $3 ($1 bits key) [slot 0"
+ echo | $CRYPTSETUP luksFormat --type luks1 $DEV -q $FAST_PBKDF -c null -s $1 --align-payload=$3 || fail
+ fi
+
+ # check the device can be activated
+ echo | $CRYPTSETUP luksOpen $DEV $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ POFF=$(get_offsets "Payload offset")
+ [ -z "$POFF" ] && fail
+ [ $POFF != $2 ] && fail "Expected data offset differs: expected $2 != detected $POFF"
+ if [ -n "$4" ] ; then
+ for j in 1 2 3 4 5 6 7 ; do
+ echo -e "\n" | $CRYPTSETUP luksAddKey $DEV -q $FAST_PBKDF --new-key-slot $j -c null $PARAMS
+ echo -n $j
+ [ $? -ne 0 ] && fail
+ done
+
+ KOFF=$(get_offsets "Key material offset")
+ [ -z "$KOFF" ] && fail
+ [ $KOFF != $4 ] && fail "Expected keyslots offsets differ: expected $4 != detected $KOFF"
+ fi
+
+ echo "]...PASSED"
+}
+
+format_plain() # sector size
+{
+ echo -n "Formatting plain device (sector size $1)..."
+ if [ -n "$DM_SECTOR_SIZE" ] ; then
+ echo $PWD1 | $CRYPTSETUP open --type plain --hash sha256 --sector-size $1 $DEV $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo "PASSED"
+ else
+ echo "N/A"
+ fi
+}
+
+format_plain_fail() # sector size
+{
+ echo -n "Formatting plain device (sector size $1, must fail)..."
+ if [ -n "$DM_SECTOR_SIZE" ] ; then
+ echo $PWD1 | $CRYPTSETUP open --type plain --hash sha256 --sector-size $1 $DEV $DEV_NAME >/dev/null 2>&1 && fail
+ echo "PASSED"
+ else
+ echo "N/A"
+ fi
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run this test, test skipped."
+ exit 77
+fi
+
+dm_crypt_features
+modprobe --dry-run scsi_debug >/dev/null 2>&1 || skip "This kernel seems to not support proper scsi_debug module, test skipped."
+cleanup
+if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+fi
+
+echo "# Create desktop-class 4K drive"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=0)"
+add_device dev_size_mb=16 sector_size=512 physblk_exp=3 num_tgts=1
+format 256 4096
+format 256 2056 8
+format 128 2048
+format 128 1032 8
+format 256 8192 8192
+format 128 8192 8192
+cleanup
+
+echo "# Create desktop-class 4K drive with misaligned opt-io (some bad USB enclosures)"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=0, opt-io=1025)"
+add_device dev_size_mb=16 sector_size=512 physblk_exp=3 num_tgts=1 opt_blks=1025
+format 256 4096
+format 256 2056 8
+format 128 2048
+format 128 1032 8
+format 256 8192 8192
+format 128 8192 8192
+cleanup
+
+echo "# Create desktop-class 4K drive w/ 63-sector DOS partition compensation"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=3584)"
+add_device dev_size_mb=16 sector_size=512 physblk_exp=3 lowest_aligned=7 num_tgts=1
+format 256 4103
+format 256 2056 8
+format 128 2055
+format 128 1032 8
+cleanup
+
+echo "# Create enterprise-class 4K drive"
+echo "# (logical_block_size=4096, physical_block_size=4096, alignment_offset=0)"
+add_device dev_size_mb=16 sector_size=4096 num_tgts=1 opt_blks=64
+format 256 4096
+format 256 2056 8
+format 128 2048
+format 128 1032 8
+cleanup
+
+echo "# Create classic 512B drive and stack dm-linear"
+echo "# (logical_block_size=512, physical_block_size=512, alignment_offset=0)"
+add_device dev_size_mb=16 sector_size=512 num_tgts=1
+DEV2=$DEV
+DEV=/dev/mapper/$DEV_STACKED
+dmsetup create $DEV_STACKED --table "0 32768 linear $DEV2 0"
+format 256 4096
+format 256 2056 8
+format 128 2048
+format 128 1032 8
+format 128 8192 8192
+cleanup
+
+echo "# Create classic 512B drive and stack dm-linear (plain mode)"
+add_device dev_size_mb=16 sector_size=512 num_tgts=1
+DEV2=$DEV
+DEV=/dev/mapper/$DEV_STACKED
+dmsetup create $DEV_STACKED --table "0 32768 linear $DEV2 0"
+format_plain 512
+format_plain 1024
+format_plain 2048
+format_plain 4096
+format_plain_fail 1111
+format_plain_fail 8192
+echo "# Create classic 512B drive, unaligned to 4096 and stack dm-linear (plain mode)"
+dmsetup remove --retry $DEV_STACKED >/dev/null 2>&1
+dmsetup create $DEV_STACKED --table "0 32762 linear $DEV2 0"
+format_plain 512
+format_plain 1024
+format_plain_fail 2048
+format_plain_fail 4096
+cleanup
+
+# skip tests using empty passphrase (LUKS1 cipher_null)
+if [ ! fips_mode ]; then
+echo "# Offset check: 512B sector drive"
+add_device dev_size_mb=16 sector_size=512 num_tgts=1
+# |k| expO reqO expected slot offsets
+format_null 128 2048 0 8:136:264:392:520:648:776:904
+format_null 128 1032 1
+format_null 128 1032 8
+format_null 128 1152 128
+format_null 128 2048 2048
+format_null 256 4096 0 8:264:520:776:1032:1288:1544:1800
+format_null 256 2056 1
+format_null 256 2056 8
+format_null 256 2176 128
+format_null 256 4096 2048
+format_null 512 4096 0 8:512:1016:1520:2024:2528:3032:3536
+format_null 512 4040 1
+format_null 512 4040 8
+format_null 512 4096 128
+format_null 512 4096 2048
+cleanup
+
+echo "# Offset check: 4096B sector drive"
+add_device dev_size_mb=16 sector_size=4096 num_tgts=1 opt_blks=64
+format_null 128 2048 0 8:136:264:392:520:648:776:904
+format_null 128 1032 1
+format_null 128 1032 8
+format_null 128 1152 128
+format_null 128 2048 2048
+format_null 256 4096 0 8:264:520:776:1032:1288:1544:1800
+format_null 256 2056 1
+format_null 256 2056 8
+format_null 256 2176 128
+format_null 256 4096 2048
+format_null 512 4096 0 8:512:1016:1520:2024:2528:3032:3536
+format_null 512 4040 1
+format_null 512 4040 8
+format_null 512 4096 128
+format_null 512 4096 2048
+cleanup
+fi
+
+echo "# Create enterprise-class 4K drive with fs and LUKS images."
+# loop device here presents 512 block but images have 4k block
+# cryptsetup should properly use 4k block on direct-io
+add_device dev_size_mb=32 sector_size=4096 physblk_exp=0 num_tgts=1 opt_blks=64
+for file in $(ls img_fs_*.img.xz) ; do
+ echo "Format using fs image $file."
+ xz -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
+ [ ! -d $MNT_DIR ] && mkdir $MNT_DIR
+ mount $DEV $MNT_DIR || skip "Mounting image is not available."
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 --key-size 256 $FAST_PBKDF $MNT_DIR/luks.img || fail
+ echo $PWD2 | $CRYPTSETUP luksFormat --type luks1 --key-size 256 $FAST_PBKDF $MNT_DIR/luks.img --header $MNT_DIR/luks_header.img || fail
+ umount $MNT_DIR
+done
+cleanup
diff --git a/tests/align-test2 b/tests/align-test2
new file mode 100755
index 0000000..33126a4
--- /dev/null
+++ b/tests/align-test2
@@ -0,0 +1,449 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+DEV=""
+DEV_STACKED="luks0xbabe"
+DEV_NAME="dummyalign"
+HDR="test_luks2_hdr"
+MNT_DIR="./mnt_luks"
+PWD1="93R4P4pIqAH8"
+PWD2="mymJeD8ivEhE"
+FAST_PBKDF="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+cleanup() {
+ udevadm settle >/dev/null 2>&1
+ if [ -d "$MNT_DIR" ] ; then
+ umount -f $MNT_DIR 2>/dev/null
+ rmdir $MNT_DIR 2>/dev/null
+ fi
+ [ -b /dev/mapper/$DEV_STACKED ] && dmsetup remove --retry $DEV_STACKED >/dev/null 2>&1
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME >/dev/null 2>&1
+ # FIXME scsi_debug sometimes in-use here
+ sleep 1
+ rmmod scsi_debug >/dev/null 2>&1
+ sleep 1
+ rm -f $HDR 2>/dev/null
+}
+
+fail()
+{
+ if [ -n "$1" ] ; then echo "FAIL $1" ; fi
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ echo "TEST SKIPPED: $1"
+ cleanup
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function dm_crypt_features()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ [ $VER_MAJ -lt 1 ] && return
+ [ $VER_MAJ -gt 1 ] && {
+ DM_PERF_CPU=1
+ DM_SECTOR_SIZE=1
+ return
+ }
+
+ [ $VER_MIN -lt 14 ] && return
+ DM_PERF_CPU=1
+ if [ $VER_MIN -ge 17 ]; then
+ DM_SECTOR_SIZE=1
+ fi
+}
+
+add_device() {
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 2
+ DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+
+ if [ ! -e /sys/block/$DEV/alignment_offset ] ; then
+ echo "This kernel seems to not support topology info, test skipped."
+ cleanup
+ exit 77
+ fi
+
+ DEV="/dev/$DEV"
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+format() # expected [forced] [encryption_sector_size]
+{
+ local _sec_size=512
+
+ local _exp=$1
+
+ if [ "${2:0:1}" = "s" ]; then
+ _sec_size=${2:1}
+ shift
+ fi
+
+ test "${3:0:1}" = "s" && _sec_size=${3:1}
+
+ test $_sec_size -eq 512 || local _smsg=" (encryption sector size $_sec_size)"
+
+ if [ -z "$2" ] ; then
+ echo -n "Formatting using topology info$_smsg..."
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $DEV -q -c aes-cbc-essiv:sha256 --sector-size $_sec_size >/dev/null 2>&1 || fail
+ else
+ echo -n "Formatting using forced sector alignment $2$_smsg..."
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $DEV -q -c aes-cbc-essiv:sha256 --align-payload=$2 --sector-size $_sec_size >/dev/null || fail
+ fi
+
+ # check the device can be activated
+ if [ -n "$DM_SECTOR_SIZE" ] ; then
+ echo $PWD1 | $CRYPTSETUP luksOpen $DEV $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fi
+
+ ALIGN=$($CRYPTSETUP luksDump $DEV | grep -A1 "0: crypt" | grep "offset:" | cut -d ' ' -f2)
+ # echo "ALIGN = $ALIGN"
+
+ [ -z "$ALIGN" ] && fail
+ ALIGN=$((ALIGN/512))
+ [ $ALIGN -ne $_exp ] && fail "Expected alignment differs: expected $_exp != detected $ALIGN"
+
+ # test some operation, just in case
+ echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $DEV $FAST_PBKDF --new-key-slot 1
+ [ $? -ne 0 ] && fail "Keyslot add failed."
+
+ $CRYPTSETUP -q luksKillSlot $DEV 1
+ [ $? -ne 0 ] && fail "Keyslot removal failed."
+
+ echo "PASSED"
+}
+
+format_fail() # expected [forced] [encryption_sector_size]
+{
+ local _sec_size=512
+
+ local _exp=$1
+
+ if [ "${2:0:1}" = "s" ]; then
+ _sec_size=${2:1}
+ shift
+ fi
+
+ test "${3:0:1}" = "s" && _sec_size=${3:1}
+
+ test $_sec_size -eq 512 || local _smsg=" (encryption sector size $_sec_size)"
+
+ if [ -z "$2" ] ; then
+ echo -n "Formatting using topology info$_smsg (must fail)..."
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $DEV -q -c aes-cbc-essiv:sha256 --sector-size $_sec_size >/dev/null 2>&1 && fail
+ else
+ echo -n "Formatting using forced sector alignment $2$_smsg (must fail)..."
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $DEV -q -c aes-cbc-essiv:sha256 --align-payload=$2 --sector-size $_sec_size >/dev/null 2>&1 && fail
+ fi
+
+ echo "PASSED"
+}
+
+auto_sector() # expected device header
+{
+ local _exp=$1
+ local _dev=$2
+ local _hdr=$2
+ local _hdrstr=""
+ local _hdrmsg=""
+
+ if [ -n "$3" ]; then
+ _hdrstr="--header $3"
+ _hdr=$3
+ _hdrmsg=" detached header"
+ fi
+
+ echo -n "Formatting$_hdrmsg using optimal encryption sector size (expecting $_exp)..."
+
+ if [ -z "$DM_SECTOR_SIZE" -a $_exp -ne 512 ]; then
+ echo "SKIPPED"
+ return
+ fi
+
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $_hdrstr $_dev -q >/dev/null 2>&1 || fail
+
+ # check the device can be activated
+ echo $PWD1 | $CRYPTSETUP luksOpen $_hdrstr $_dev $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ SECTOR=$($CRYPTSETUP luksDump $_hdr | grep -A4 "0: crypt" | grep "sector:" | cut -d ' ' -f2)
+
+ [ -z "$SECTOR" ] && fail
+ [ $SECTOR -ne $_exp ] && fail "Expected sector size differs: expected $_exp != detected $SECTOR"
+
+ echo "PASSED"
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run this test, test skipped."
+ exit 77
+fi
+
+dm_crypt_features
+modprobe --dry-run scsi_debug >/dev/null 2>&1 || skip "This kernel seems to not support proper scsi_debug module, test skipped."
+cleanup
+if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+fi
+
+add_device dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $DEV -q >/dev/null || fail
+EXPCT=$($CRYPTSETUP luksDump $DEV | grep "offset: " | cut -f 2 -d ' ')
+test "$EXPCT" -gt 512 || fail
+EXPCT=$((EXPCT/512))
+echo "Default alignment detected: $EXPCT sectors"
+cleanup
+
+echo "# Create desktop-class 4K drive"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=0)"
+add_device dev_size_mb=32 sector_size=512 physblk_exp=3 num_tgts=1
+format $EXPCT
+format $EXPCT s1024
+format $EXPCT s2048
+format $EXPCT s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create desktop-class 4K drive with misaligned opt-io (some bad USB enclosures)"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=0, opt-io=1025)"
+add_device dev_size_mb=32 sector_size=512 physblk_exp=3 num_tgts=1 opt_blks=1025
+format $EXPCT
+format $EXPCT s1024
+format $EXPCT s2048
+format $EXPCT s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create drive with misaligned opt-io to page-size (some bad USB enclosures)"
+echo "# (logical_block_size=512, physical_block_size=512, alignment_offset=0, opt-io=33553920)"
+add_device dev_size_mb=32 sector_size=512 num_tgts=1 opt_blks=65535
+format $EXPCT
+format $EXPCT s1024
+format $EXPCT s2048
+format $EXPCT s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create desktop-class 4K drive w/ 1-sector shift (original bug report)"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=512)"
+add_device dev_size_mb=32 sector_size=512 physblk_exp=3 lowest_aligned=1 num_tgts=1
+format $((EXPCT+1))
+format_fail $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create desktop-class 4K drive w/ 63-sector DOS partition compensation"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=3584)"
+add_device dev_size_mb=32 sector_size=512 physblk_exp=3 lowest_aligned=7 num_tgts=1
+format $((EXPCT+7))
+format_fail $((EXPCT+7)) s1024
+format_fail $((EXPCT+7)) s2048
+format_fail $((EXPCT+7)) s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create enterprise-class 4K drive"
+echo "# (logical_block_size=4096, physical_block_size=4096, alignment_offset=0)"
+add_device dev_size_mb=32 sector_size=4096 num_tgts=1 opt_blks=64
+format $EXPCT
+format $EXPCT s1024
+format $EXPCT s2048
+format $EXPCT s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+#FIXME: kernel limits issue?
+##format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create classic 512B drive and stack dm-linear"
+echo "# (logical_block_size=512, physical_block_size=512, alignment_offset=0)"
+add_device dev_size_mb=32 sector_size=512 num_tgts=1
+DEV2=$DEV
+DEV=/dev/mapper/$DEV_STACKED
+dmsetup create $DEV_STACKED --table "0 65536 linear $DEV2 0"
+format $EXPCT
+format $EXPCT s1024
+format $EXPCT s2048
+format $EXPCT s4096
+format $EXPCT 1
+format $EXPCT 1 s1024
+format $EXPCT 1 s2048
+format $EXPCT 1 s4096
+format $EXPCT 8
+format $EXPCT 8 s1024
+format $EXPCT 8 s2048
+format $EXPCT 8 s4096
+format $((EXPCT+1)) $((EXPCT+1))
+format_fail $((EXPCT+1)) $((EXPCT+1)) s1024
+format_fail $((EXPCT+1)) $((EXPCT+1)) s2048
+format_fail $((EXPCT+1)) $((EXPCT+1)) s4096
+format $EXPCT $EXPCT
+format $EXPCT $EXPCT s1024
+format $EXPCT $EXPCT s2048
+format $EXPCT $EXPCT s4096
+cleanup
+
+echo "# Create enterprise-class 4K drive with fs and LUKS images."
+# loop device here presents 512 block but images have 4k block
+# cryptsetup should properly use 4k block on direct-io
+add_device dev_size_mb=32 sector_size=4096 physblk_exp=0 num_tgts=1 opt_blks=64
+for file in $(ls img_fs_*.img.xz) ; do
+ echo "Format using fs image $file."
+ xz -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
+ [ ! -d $MNT_DIR ] && mkdir $MNT_DIR
+ mount $DEV $MNT_DIR || skip "Mounting image is not available."
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $MNT_DIR/luks.img --offset 8192 || fail
+ echo $PWD2 | $CRYPTSETUP luksFormat $FAST_PBKDF --type luks2 $MNT_DIR/luks.img --header $MNT_DIR/luks_header.img || fail
+ umount $MNT_DIR
+done
+cleanup
+
+echo "# Create classic 512B drive"
+echo "# (logical_block_size=512, physical_block_size=512, alignment_offset=0)"
+add_device dev_size_mb=32 sector_size=512 num_tgts=1
+auto_sector 512 $DEV
+auto_sector 512 $DEV $HDR
+cleanup
+echo "# Create desktop-class 4K drive"
+echo "# (logical_block_size=512, physical_block_size=4096, alignment_offset=0)"
+add_device dev_size_mb=32 sector_size=512 physblk_exp=3 num_tgts=1
+auto_sector 4096 $DEV
+auto_sector 4096 $DEV $HDR
+DEV2=$DEV
+DEV=/dev/mapper/$DEV_STACKED
+dmsetup create $DEV_STACKED --table "0 $((`blockdev --getsz $DEV2`-1)) linear $DEV2 0"
+auto_sector 512 $DEV
+auto_sector 512 $DEV $HDR
+cleanup
+echo "# Create enterprise-class 4K drive"
+echo "# (logical_block_size=4096, physical_block_size=4096, alignment_offset=0)"
+add_device dev_size_mb=32 sector_size=4096 num_tgts=1 opt_blks=64
+auto_sector 4096 $DEV
+auto_sector 4096 $DEV $HDR
+cleanup
diff --git a/tests/all-symbols-test.c b/tests/all-symbols-test.c
new file mode 100644
index 0000000..10c7fe2
--- /dev/null
+++ b/tests/all-symbols-test.c
@@ -0,0 +1,177 @@
+/*
+ * Test utility checking symbol versions in libcryptsetup.
+ *
+ * Copyright (C) 2021-2023 Red Hat, Inc. All rights reserved.
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define UNUSED(expr) do { (void)(expr); } while (0)
+
+static int _debug;
+static const char *libfile = "libcryptsetup.so.12";
+
+#define LOG_MAX_LEN 256
+
+#define LOG_DEBUG 1
+#define LOG_NORMAL 2
+#define LOG_ERROR 3
+
+__attribute__((format(printf, 2, 3)))
+static void test_logf(int level, const char *format, ...)
+{
+ va_list argp;
+ char target[LOG_MAX_LEN + 2];
+ int len;
+
+ va_start(argp, format);
+
+ len = vsnprintf(&target[0], LOG_MAX_LEN, format, argp);
+ if (len > 0 && len < LOG_MAX_LEN) {
+ switch (level) {
+ case LOG_DEBUG:
+ if (!_debug)
+ break;
+ /* fall through */
+ case LOG_NORMAL:
+ fprintf(stdout, "%s", target);
+ break;
+ case LOG_ERROR:
+ fflush(stdout);
+ strcat(target, "\n");
+ fprintf(stderr, "%s", target);
+ }
+ }
+
+ va_end(argp);
+}
+
+#define log_dbg(x...) test_logf(LOG_DEBUG, x)
+#define log_std(x...) test_logf(LOG_NORMAL, x)
+#define log_err(x...) test_logf(LOG_ERROR, x)
+
+static int check_dlvsym(void *h, const char *symbol, const char *version)
+{
+#ifdef HAVE_DLVSYM
+ void *sym;
+ char *err;
+
+ log_dbg("Checking %s@%s...", symbol, version);
+ sym = dlvsym(h, symbol, version);
+ UNUSED(sym);
+ err = dlerror();
+
+ if (err) {
+ log_err("%s.", err);
+ return 1;
+ }
+
+ log_dbg("OK\n");
+#endif
+ return 0;
+}
+
+static int check_dlsym(void *h, const char *symbol)
+{
+ void *sym;
+ char *err;
+
+ log_dbg("Checking %s...", symbol);
+ sym = dlsym(h, symbol);
+ UNUSED(sym);
+ err = dlerror();
+
+ if (err) {
+ log_err("%s", err);
+ return 1;
+ }
+
+ log_dbg("OK\n");
+ return 0;
+}
+
+static int check_all_symbols(void *h)
+{
+ unsigned scount = 0;
+
+#define CHECK_SYMBOL(SYM, VER) \
+do { \
+ if (check_dlvsym(h, #SYM, #VER)) \
+ return 1; \
+ if (check_dlsym(h, #SYM)) \
+ return 1; \
+ scount++; \
+} while (0);
+
+#include "test-symbols-list.h"
+#undef CHECK_SYMBOL
+
+ if (!scount) {
+ log_err("test-symbols-list.h file is probably empty.");
+ return 1;
+ }
+
+ log_std("Performed %u symbol checks in total.\n", scount);
+
+ return 0;
+}
+
+static void usage(const char *app)
+{
+ log_std("usage:\n\t%s [-v|--verbose|--debug] [optional path to library so file]\n", app);
+
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
+{
+ int i, r;
+ void *h;
+
+ for (i = 1; i < argc; i++) {
+ if (*argv[i] != '-')
+ libfile = argv[i];
+ else if (!strcmp("-v", argv[i]) || !strcmp("--verbose", argv[i]) ||
+ !strcmp("--debug", argv[i]))
+ _debug = 1;
+ else if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i]))
+ usage(argv[0]);
+ }
+
+ log_std("Checking dlopen(%s)...", libfile);
+
+ h = dlopen(libfile, RTLD_NOW);
+ if (!h) {
+ log_err("dlopen(): %s.", dlerror());
+ return EXIT_FAILURE;
+ }
+ dlerror();
+ log_std("OK\n");
+
+ r = check_all_symbols(h);
+
+ if (dlclose(h)) {
+ log_err("Failed to dlclose %s: %s.", libfile, dlerror());
+ return EXIT_FAILURE;
+ }
+
+ return r ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/tests/api-test-2.c b/tests/api-test-2.c
new file mode 100644
index 0000000..824ae65
--- /dev/null
+++ b/tests/api-test-2.c
@@ -0,0 +1,5139 @@
+/*
+ * cryptsetup library LUKS2 API check functions
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#ifdef KERNEL_KEYRING
+#include <linux/keyctl.h>
+#include <sys/syscall.h>
+#ifndef HAVE_KEY_SERIAL_T
+#define HAVE_KEY_SERIAL_T
+#include <stdint.h>
+typedef int32_t key_serial_t;
+#endif
+#endif
+
+#include "api_test.h"
+#include "luks1/luks.h"
+#include "libcryptsetup.h"
+
+#define DEVICE_1_UUID "28632274-8c8a-493f-835b-da802e1c576b"
+#define DEVICE_EMPTY_name "crypt_zero"
+#define DEVICE_EMPTY DMDIR DEVICE_EMPTY_name
+#define DEVICE_ERROR_name "crypt_error"
+#define DEVICE_ERROR DMDIR DEVICE_ERROR_name
+
+#define CDEVICE_1 "ctest1"
+#define CDEVICE_2 "ctest2"
+#define CDEVICE_WRONG "O_o"
+#define H_DEVICE "head_ok"
+#define H_DEVICE_WRONG "head_wr"
+#define L_DEVICE_1S "luks_onesec"
+#define L_DEVICE_0S "luks_zerosec"
+#define L_DEVICE_WRONG "luks_wr"
+#define L_DEVICE_OK "luks_ok"
+#define REQS_LUKS2_HEADER "luks2_header_requirements"
+#define NO_REQS_LUKS2_HEADER "luks2_header_requirements_free"
+#define BACKUP_FILE "csetup_backup_file"
+#define IMAGE1 "compatimage2.img"
+#define IMAGE_EMPTY "empty.img"
+#define IMAGE_EMPTY_SMALL "empty_small.img"
+#define IMAGE_EMPTY_SMALL_2 "empty_small2.img"
+#define IMAGE_PV_LUKS2_SEC "blkid-luks2-pv.img"
+
+#define KEYFILE1 "key1.file"
+#define KEY1 "compatkey"
+
+#define KEYFILE2 "key2.file"
+#define KEY2 "0123456789abcdef"
+
+#define PASSPHRASE "blablabl"
+#define PASSPHRASE1 "albalbal"
+
+#define DEVICE_TEST_UUID "12345678-1234-1234-1234-123456789abc"
+
+#define DEVICE_WRONG "/dev/Ooo_"
+#define DEVICE_CHAR "/dev/zero"
+#define THE_LFILE_TEMPLATE "cryptsetup-tstlp.XXXXXX"
+
+#define KEY_DESC_TEST0 "cs_token_test:test_key0"
+#define KEY_DESC_TEST1 "cs_token_test:test_key1"
+
+#define CONV_DIR "conversion_imgs"
+#define CONV_L1_128 "l1_128b"
+#define CONV_L1_256 "l1_256b"
+#define CONV_L1_512 "l1_512b"
+#define CONV_L2_128 "l2_128b"
+#define CONV_L2_128_FULL "l2_128b_full"
+#define CONV_L2_256 "l2_256b"
+#define CONV_L2_256_FULL "l2_256b_full"
+#define CONV_L2_512 "l2_512b"
+#define CONV_L2_512_FULL "l2_512b_full"
+#define CONV_L1_128_DET "l1_128b_det"
+#define CONV_L1_256_DET "l1_256b_det"
+#define CONV_L1_512_DET "l1_512b_det"
+#define CONV_L2_128_DET "l2_128b_det"
+#define CONV_L2_128_DET_FULL "l2_128b_det_full"
+#define CONV_L2_256_DET "l2_256b_det"
+#define CONV_L2_256_DET_FULL "l2_256b_det_full"
+#define CONV_L2_512_DET "l2_512b_det"
+#define CONV_L2_512_DET_FULL "l2_512b_det_full"
+#define CONV_L1_256_LEGACY "l1_256b_legacy_offset"
+#define CONV_L1_256_UNMOVABLE "l1_256b_unmovable"
+#define PASS0 "aaablabl"
+#define PASS1 "hhhblabl"
+#define PASS2 "cccblabl"
+#define PASS3 "dddblabl"
+#define PASS4 "eeeblabl"
+#define PASS5 "fffblabl"
+#define PASS6 "gggblabl"
+#define PASS7 "bbbblabl"
+#define PASS8 "iiiblabl"
+
+static int _fips_mode = 0;
+
+static char *DEVICE_1 = NULL;
+static char *DEVICE_2 = NULL;
+static char *DEVICE_3 = NULL;
+static char *DEVICE_4 = NULL;
+static char *DEVICE_5 = NULL;
+static char *DEVICE_6 = NULL;
+
+static char *tmp_file_1 = NULL;
+static char *test_loop_file = NULL;
+
+unsigned int test_progress_steps;
+
+struct crypt_device *cd = NULL, *cd2 = NULL;
+
+static const char *default_luks1_hash = NULL;
+static uint32_t default_luks1_iter_time = 0;
+
+static const char *default_luks2_pbkdf = NULL;
+static uint32_t default_luks2_iter_time = 0;
+static uint32_t default_luks2_memory_kb = 0;
+static uint32_t default_luks2_parallel_threads = 0;
+
+static struct crypt_pbkdf_type min_pbkdf2 = {
+ .type = "pbkdf2",
+ .iterations = 1000,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+}, min_argon2 = {
+ .type = "argon2id",
+ .iterations = 4,
+ .max_memory_kb = 32,
+ .parallel_threads = 1,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+};
+
+// Helpers
+
+static unsigned cpus_online(void)
+{
+ static long r = -1;
+
+ if (r < 0) {
+ r = sysconf(_SC_NPROCESSORS_ONLN);
+ if (r < 0)
+ r = 1;
+ }
+
+ return r;
+}
+
+static uint32_t adjusted_pbkdf_memory(void)
+{
+ long pagesize = sysconf(_SC_PAGESIZE);
+ long pages = sysconf(_SC_PHYS_PAGES);
+ uint64_t memory_kb;
+
+ if (pagesize <= 0 || pages <= 0)
+ return default_luks2_memory_kb;
+
+ memory_kb = pagesize / 1024 * pages / 2;
+
+ if (memory_kb < default_luks2_memory_kb)
+ return (uint32_t)memory_kb;
+
+ return default_luks2_memory_kb;
+}
+
+static unsigned _min(unsigned a, unsigned b)
+{
+ return a < b ? a : b;
+}
+
+static int get_luks2_offsets(int metadata_device,
+ unsigned int alignpayload_sec,
+ unsigned int sector_size,
+ uint64_t *r_header_size,
+ uint64_t *r_payload_offset)
+{
+ struct crypt_device *cd = NULL;
+ static uint64_t default_header_size = 0;
+
+ if (r_header_size)
+ *r_header_size = 0;
+ if (r_payload_offset)
+ *r_payload_offset = 0;
+
+ if (!default_header_size) {
+ if (crypt_init(&cd, THE_LOOP_DEV))
+ return -EINVAL;
+ if (crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL)) {
+ crypt_free(cd);
+ return -EINVAL;
+ }
+
+ default_header_size = crypt_get_data_offset(cd);
+
+ crypt_free(cd);
+ }
+
+ if (!sector_size)
+ sector_size = 512; /* default? */
+
+ if ((sector_size % 512) && (sector_size % 4096))
+ return -1;
+
+ if (r_payload_offset) {
+ if (metadata_device)
+ *r_payload_offset = alignpayload_sec * sector_size;
+ else
+ *r_payload_offset = DIV_ROUND_UP_MODULO(default_header_size * 512, (alignpayload_sec ?: 1) * sector_size);
+
+ *r_payload_offset /= sector_size;
+ }
+
+ if (r_header_size)
+ *r_header_size = default_header_size;
+
+ return 0;
+}
+
+static bool get_luks_pbkdf_defaults(void)
+{
+ const struct crypt_pbkdf_type *pbkdf_defaults = crypt_get_pbkdf_default(CRYPT_LUKS1);
+
+ if (!pbkdf_defaults)
+ return false;
+
+ default_luks1_hash = pbkdf_defaults->hash;
+ default_luks1_iter_time = pbkdf_defaults->time_ms;
+
+ pbkdf_defaults = crypt_get_pbkdf_default(CRYPT_LUKS2);
+ if (!pbkdf_defaults)
+ return false;
+
+ default_luks2_pbkdf = pbkdf_defaults->type;
+ default_luks2_iter_time = pbkdf_defaults->time_ms;
+ default_luks2_memory_kb = pbkdf_defaults->max_memory_kb;
+ default_luks2_parallel_threads = pbkdf_defaults->parallel_threads;
+
+ return true;
+}
+
+static void _remove_keyfiles(void)
+{
+ remove(KEYFILE1);
+ remove(KEYFILE2);
+}
+
+#if HAVE_DECL_DM_TASK_RETRY_REMOVE
+#define DM_RETRY "--retry "
+#else
+#define DM_RETRY ""
+#endif
+
+#define DM_NOSTDERR " 2>/dev/null"
+
+static void _cleanup_dmdevices(void)
+{
+ struct stat st;
+
+ if (!stat(DMDIR H_DEVICE, &st))
+ _system("dmsetup remove " DM_RETRY H_DEVICE DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR H_DEVICE_WRONG, &st))
+ _system("dmsetup remove " DM_RETRY H_DEVICE_WRONG DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_0S, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_0S DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_1S, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_1S DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_WRONG, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_WRONG DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_OK, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_OK DM_NOSTDERR, 0);
+
+ t_dev_offset = 0;
+}
+
+static void _cleanup(void)
+{
+ struct stat st;
+
+ CRYPT_FREE(cd);
+ CRYPT_FREE(cd2);
+
+ //_system("udevadm settle", 0);
+
+ if (!stat(DMDIR CDEVICE_1, &st))
+ _system("dmsetup remove " DM_RETRY CDEVICE_1 DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR CDEVICE_2, &st))
+ _system("dmsetup remove " DM_RETRY CDEVICE_2 DM_NOSTDERR, 0);
+
+ if (!stat(DEVICE_EMPTY, &st))
+ _system("dmsetup remove " DM_RETRY DEVICE_EMPTY_name DM_NOSTDERR, 0);
+
+ if (!stat(DEVICE_ERROR, &st))
+ _system("dmsetup remove " DM_RETRY DEVICE_ERROR_name DM_NOSTDERR, 0);
+
+ _cleanup_dmdevices();
+
+ if (loop_device(THE_LOOP_DEV))
+ loop_detach(THE_LOOP_DEV);
+
+ if (loop_device(DEVICE_1))
+ loop_detach(DEVICE_1);
+
+ if (loop_device(DEVICE_2))
+ loop_detach(DEVICE_2);
+
+ if (loop_device(DEVICE_3))
+ loop_detach(DEVICE_3);
+
+ if (loop_device(DEVICE_4))
+ loop_detach(DEVICE_4);
+
+ if (loop_device(DEVICE_5))
+ loop_detach(DEVICE_5);
+
+ if (loop_device(DEVICE_6))
+ loop_detach(DEVICE_6);
+
+ _system("rm -f " IMAGE_EMPTY, 0);
+ _system("rm -f " IMAGE1, 0);
+ _system("rm -rf " CONV_DIR, 0);
+
+ if (test_loop_file)
+ remove(test_loop_file);
+ if (tmp_file_1)
+ remove(tmp_file_1);
+
+ remove(REQS_LUKS2_HEADER);
+ remove(NO_REQS_LUKS2_HEADER);
+ remove(BACKUP_FILE);
+ remove(IMAGE_PV_LUKS2_SEC);
+ remove(IMAGE_PV_LUKS2_SEC ".bcp");
+ remove(IMAGE_EMPTY_SMALL);
+ remove(IMAGE_EMPTY_SMALL_2);
+
+ _remove_keyfiles();
+
+ free(tmp_file_1);
+ free(test_loop_file);
+ free(THE_LOOP_DEV);
+ free(DEVICE_1);
+ free(DEVICE_2);
+ free(DEVICE_3);
+ free(DEVICE_4);
+ free(DEVICE_5);
+ free(DEVICE_6);
+}
+
+static int _setup(void)
+{
+ int fd, ro = 0;
+ char cmd[128];
+
+ test_loop_file = strdup(THE_LFILE_TEMPLATE);
+ if (!test_loop_file)
+ return 1;
+
+ if ((fd=mkstemp(test_loop_file)) == -1) {
+ printf("cannot create temporary file with template %s\n", test_loop_file);
+ return 1;
+ }
+ close(fd);
+ if (snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
+ test_loop_file, TST_SECTOR_SIZE, TST_LOOP_FILE_SIZE) < 0)
+ return 1;
+ if (_system(cmd, 1))
+ return 1;
+
+ fd = loop_attach(&THE_LOOP_DEV, test_loop_file, 0, 0, &ro);
+ close(fd);
+
+ tmp_file_1 = strdup(THE_LFILE_TEMPLATE);
+ if (!tmp_file_1)
+ return 1;
+
+ if ((fd=mkstemp(tmp_file_1)) == -1) {
+ printf("cannot create temporary file with template %s\n", tmp_file_1);
+ return 1;
+ }
+ close(fd);
+ if (snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
+ tmp_file_1, TST_SECTOR_SIZE, 10) < 0)
+ return 1;
+ if (_system(cmd, 1))
+ return 1;
+
+ _system("dmsetup create " DEVICE_EMPTY_name " --table \"0 10000 zero\"", 1);
+ _system("dmsetup create " DEVICE_ERROR_name " --table \"0 10000 error\"", 1);
+
+ if (t_set_readahead(DEVICE_ERROR, 0))
+ printf("cannot set read ahead on device %s\n", DEVICE_ERROR);
+
+ _system(" [ ! -e " IMAGE1 " ] && xz -dk " IMAGE1 ".xz", 1);
+ fd = loop_attach(&DEVICE_1, IMAGE1, 0, 0, &ro);
+ close(fd);
+
+ _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=32 2>/dev/null", 1);
+ fd = loop_attach(&DEVICE_2, IMAGE_EMPTY, 0, 0, &ro);
+ close(fd);
+
+ _system("dd if=/dev/zero of=" IMAGE_EMPTY_SMALL " bs=1M count=7 2>/dev/null", 1);
+
+ _system("dd if=/dev/zero of=" IMAGE_EMPTY_SMALL_2 " bs=512 count=2050 2>/dev/null", 1);
+
+ _system(" [ ! -e " NO_REQS_LUKS2_HEADER " ] && tar xJf " REQS_LUKS2_HEADER ".tar.xz", 1);
+ fd = loop_attach(&DEVICE_4, NO_REQS_LUKS2_HEADER, 0, 0, &ro);
+ close(fd);
+
+ _system(" [ ! -e " REQS_LUKS2_HEADER " ] && tar xJf " REQS_LUKS2_HEADER ".tar.xz", 1);
+ fd = loop_attach(&DEVICE_5, REQS_LUKS2_HEADER, 0, 0, &ro);
+ close(fd);
+
+ _system(" [ ! -e " IMAGE_PV_LUKS2_SEC " ] && xz -dk " IMAGE_PV_LUKS2_SEC ".xz", 1);
+ _system(" [ ! -e " IMAGE_PV_LUKS2_SEC ".bcp ] && cp " IMAGE_PV_LUKS2_SEC " " IMAGE_PV_LUKS2_SEC ".bcp", 1);
+ fd = loop_attach(&DEVICE_6, IMAGE_PV_LUKS2_SEC, 0, 0, &ro);
+ close(fd);
+
+ _system(" [ ! -d " CONV_DIR " ] && tar xJf " CONV_DIR ".tar.xz 2>/dev/null", 1);
+
+ if (_system("modprobe dm-crypt >/dev/null 2>&1", 1))
+ return 1;
+
+ if (t_dm_check_versions())
+ return 1;
+
+ _system("rmmod dm-crypt >/dev/null 2>&1", 0);
+
+ _fips_mode = fips_mode();
+ if (_debug)
+ printf("FIPS MODE: %d\n", _fips_mode);
+
+ /* Use default log callback */
+ crypt_set_log_callback(NULL, &global_log_callback, NULL);
+
+ if (!get_luks_pbkdf_defaults())
+ return 1;
+
+ min_pbkdf2.hash = min_argon2.hash = default_luks1_hash;
+
+ return 0;
+}
+
+static int set_fast_pbkdf(struct crypt_device *cd)
+{
+ const struct crypt_pbkdf_type *pbkdf = &min_argon2;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode)
+ pbkdf = &min_pbkdf2;
+
+ return crypt_set_pbkdf_type(cd, pbkdf);
+}
+
+#ifdef KERNEL_KEYRING
+static key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t keyring)
+{
+ return syscall(__NR_add_key, type, description, payload, plen, keyring);
+}
+
+static key_serial_t keyctl_unlink(key_serial_t key, key_serial_t keyring)
+{
+ return syscall(__NR_keyctl, KEYCTL_UNLINK, key, keyring);
+}
+
+static key_serial_t request_key(const char *type,
+ const char *description,
+ const char *callout_info,
+ key_serial_t keyring)
+{
+ return syscall(__NR_request_key, type, description, callout_info, keyring);
+}
+
+static key_serial_t _kernel_key_by_segment(struct crypt_device *cd, int segment)
+{
+ char key_description[1024];
+
+ if (snprintf(key_description, sizeof(key_description), "cryptsetup:%s-d%u", crypt_get_uuid(cd), segment) < 1)
+ return -1;
+
+ return request_key("logon", key_description, NULL, 0);
+}
+
+static int _volume_key_in_keyring(struct crypt_device *cd, int segment)
+{
+ return _kernel_key_by_segment(cd, segment) >= 0 ? 0 : -1;
+}
+
+static int _drop_keyring_key(struct crypt_device *cd, int segment)
+{
+ key_serial_t kid = _kernel_key_by_segment(cd, segment);
+
+ if (kid < 0)
+ return -1;
+
+ return keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING);
+}
+#endif
+
+static int test_open(struct crypt_device *cd __attribute__((unused)),
+ int token __attribute__((unused)),
+ char **buffer,
+ size_t *buffer_len,
+ void *usrptr)
+{
+ const char *str = (const char *)usrptr;
+
+ *buffer = strdup(str);
+ if (!*buffer)
+ return -ENOMEM;
+ *buffer_len = strlen(*buffer);
+
+ return 0;
+}
+
+static int test_validate(struct crypt_device *cd __attribute__((unused)), const char *json)
+{
+ return (strstr(json, "magic_string") == NULL);
+}
+
+static void UseLuks2Device(void)
+{
+ char key[128];
+ size_t key_size;
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ OK_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0), "already open");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_deactivate(cd, CDEVICE_1), "no such device");
+
+#if KERNEL_KEYRING
+ // repeat previous tests and check kernel keyring is released when not needed
+ if (t_dm_crypt_keyring_support()) {
+ OK_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ FAIL_(_drop_keyring_key(cd, 0), "");
+ OK_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), CRYPT_ACTIVATE_KEYRING_KEY));
+ OK_(_drop_keyring_key(cd, 0));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ OK_(_drop_keyring_key(cd, 0));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0), "already open");
+ FAIL_(_volume_key_in_keyring(cd, 0), "");
+ OK_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(_volume_key_in_keyring(cd, 0), "");
+ }
+#endif
+
+ key_size = 16;
+ OK_(strcmp("aes", crypt_get_cipher(cd)));
+ OK_(strcmp("cbc-essiv:sha256", crypt_get_cipher_mode(cd)));
+ OK_(strcmp(DEVICE_1_UUID, crypt_get_uuid(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(8192, crypt_get_data_offset(cd));
+
+ EQ_(0, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
+ OK_(crypt_volume_key_verify(cd, key, key_size));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ key[1] = ~key[1];
+ FAIL_(crypt_volume_key_verify(cd, key, key_size), "key mismatch");
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "key mismatch");
+
+ CRYPT_FREE(cd);
+}
+
+static void SuspendDevice(void)
+{
+ struct crypt_active_device cad;
+ char key[128];
+ size_t key_size;
+ int suspend_status;
+ uint64_t r_payload_offset;
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+
+ suspend_status = crypt_suspend(cd, CDEVICE_1);
+ if (suspend_status == -ENOTSUP) {
+ printf("WARNING: Suspend/Resume not supported, skipping test.\n");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+ return;
+ }
+
+ OK_(suspend_status);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(CRYPT_ACTIVATE_SUSPENDED, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+#ifdef KERNEL_KEYRING
+ FAIL_(_volume_key_in_keyring(cd, 0), "");
+#endif
+ FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
+
+ FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "wrong key");
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
+ FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)), "not suspended");
+
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+
+ OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1)));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1 "blah", 0), "wrong keyfile");
+ FAIL_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key");
+ OK_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
+ FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ /* create LUKS device with detached header */
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_data_device(cd, DEVICE_2));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ CRYPT_FREE(cd);
+
+ /* Should be able to suspend but not resume if not header specified */
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
+ FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "no header");
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1));
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
+
+ /* Resume by volume key */
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ key_size = sizeof(key);
+ memset(key, 0, key_size);
+ FAIL_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size), "wrong key");
+ OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
+ OK_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ /* Resume device with cipher_null */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "cipher_null", "ecb", NULL, key, key_size, NULL));
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ OK_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _remove_keyfiles();
+ _cleanup_dmdevices();
+}
+
+static void AddDeviceLuks2(void)
+{
+ enum { OFFSET_1M = 2048 , OFFSET_2M = 4096, OFFSET_4M = 8192, OFFSET_8M = 16384 };
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 4,
+ .max_memory_kb = 1024,
+ .time_ms = 1
+ }, pbkdf_tmp;
+ struct crypt_params_luks2 params = {
+ .pbkdf = &pbkdf,
+ .data_device = DEVICE_2,
+ .sector_size = 512
+ };
+ char key[128], key2[128], key3[128];
+
+ const char *tmp_buf, *passphrase = PASSPHRASE, *passphrase2 = "nsdkFI&Y#.sd";
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset, r_header_size, r_size_1;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ }
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key3, vk_hex2, key_size);
+
+ // init test devices
+ OK_(get_luks2_offsets(0, 0, 0, &r_header_size, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_header_size - 1));
+
+
+ // format
+ OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
+ params.data_alignment = 0;
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Not enough space for keyslots material");
+ CRYPT_FREE(cd);
+
+ // test payload_offset = 0 for encrypted device with external header device
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), 0);
+ CRYPT_FREE(cd);
+
+ params.data_alignment = 0;
+ params.data_device = NULL;
+
+ // test payload_offset = 0. format() should look up alignment offset from device topology
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(!(crypt_get_data_offset(cd) > 0));
+ CRYPT_FREE(cd);
+
+ // set_data_offset has priority, alignment must be 0 or must be compatible
+ params.data_alignment = 0;
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_set_data_offset(cd, OFFSET_8M));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), OFFSET_8M);
+ CRYPT_FREE(cd);
+
+ // Load gets the value from metadata
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_set_data_offset(cd, OFFSET_2M));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), OFFSET_8M);
+ CRYPT_FREE(cd);
+
+ params.data_alignment = OFFSET_4M;
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(set_fast_pbkdf(cd));
+ FAIL_(crypt_set_data_offset(cd, OFFSET_2M + 1), "Not aligned to 4096"); // must be aligned to 4k
+ OK_(crypt_set_data_offset(cd, OFFSET_2M));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Alignment not compatible");
+ OK_(crypt_set_data_offset(cd, OFFSET_4M));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), OFFSET_4M);
+ CRYPT_FREE(cd);
+
+ /*
+ * test limit values for backing device size
+ */
+ params.data_alignment = OFFSET_4M;
+ OK_(get_luks2_offsets(0, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+ OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
+
+ // 1 sector less than required
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG));
+ OK_(set_fast_pbkdf(cd));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Device too small");
+ CRYPT_FREE(cd);
+
+ // 0 sectors for encrypted area
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Encrypted area too small");
+ CRYPT_FREE(cd);
+
+ // 1 sector for encrypted area
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), r_payload_offset);
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(t_device_size(DMDIR CDEVICE_1, &r_size_1));
+ EQ_(r_size_1, TST_SECTOR_SIZE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ // restrict format only to empty context
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Context is already formatted");
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL), "Context is already formatted");
+ // change data device to wrong one
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_0S));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device too small");
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.data_alignment = 0;
+ params.data_device = DEVICE_2;
+
+ // generate keyslot material at the end of luks header
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase) ,0), 7);
+
+ OK_(crypt_keyslot_get_pbkdf(cd, 7, &pbkdf_tmp));
+ OK_(strcmp(pbkdf_tmp.type, pbkdf.type));
+ if (!_fips_mode) {
+ NULL_(pbkdf_tmp.hash);
+ OK_(!(pbkdf_tmp.max_memory_kb >= 32));
+ OK_(!(pbkdf_tmp.parallel_threads >= 1));
+ } else
+ OK_(strcmp(pbkdf_tmp.hash, pbkdf.hash));
+ OK_(!(pbkdf_tmp.iterations >= 4));
+ EQ_(0, pbkdf_tmp.time_ms); /* not usable in per-keyslot call */
+
+ CRYPT_FREE(cd);
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Context is already formatted");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ CRYPT_FREE(cd);
+ // check active status without header
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, NULL));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ NULL_(crypt_get_type(cd));
+ OK_(strcmp(cipher, crypt_get_cipher(cd)));
+ OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.data_alignment = OFFSET_1M;
+ params.data_device = NULL;
+
+ // test uuid mismatch and _init_by_name_and_header
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ EQ_(0, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+ params.data_alignment = 0;
+ params.data_device = DEVICE_2;
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ // there we've got uuid mismatch
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ NULL_(crypt_get_type(cd));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device is active");
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0), "Device is active");
+ EQ_(crypt_status(cd, CDEVICE_2), CRYPT_INACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_header_is_detached(cd), 1);
+ CRYPT_FREE(cd);
+
+ params.data_device = NULL;
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+
+ // even with no keyslots defined it can be activated by volume key
+ OK_(crypt_volume_key_verify(cd, key, key_size));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+
+ // now with keyslot
+ EQ_(7, crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7));
+ EQ_(7, crypt_activate_by_passphrase(cd, CDEVICE_2, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+
+ EQ_(1, crypt_keyslot_add_by_volume_key(cd, 1, key, key_size, KEY1, strlen(KEY1)));
+ OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1)));
+ OK_(prepare_keyfile(KEYFILE2, KEY2, strlen(KEY2)));
+ EQ_(2, crypt_keyslot_add_by_keyfile(cd, 2, KEYFILE1, 0, KEYFILE2, 0));
+ FAIL_(crypt_keyslot_add_by_keyfile_offset(cd, 3, KEYFILE1, 0, 1, KEYFILE2, 0, 1), "wrong key");
+ EQ_(3, crypt_keyslot_add_by_keyfile_offset(cd, 3, KEYFILE1, 0, 0, KEYFILE2, 0, 1));
+ EQ_(4, crypt_keyslot_add_by_keyfile_offset(cd, 4, KEYFILE2, 0, 1, KEYFILE1, 0, 1));
+ FAIL_(crypt_activate_by_keyfile(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, strlen(KEY2)-1, 0), "key mismatch");
+ EQ_(2, crypt_activate_by_keyfile(cd, NULL, CRYPT_ANY_SLOT, KEYFILE2, 0, 0));
+ EQ_(3, crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE2, 0, 1, 0));
+ EQ_(4, crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, 1, 0));
+ FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, strlen(KEY2), 2, 0), "not enough data");
+ FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, strlen(KEY2) + 1, 0), "cannot seek");
+ FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, 2, 0), "wrong key");
+ EQ_(2, crypt_activate_by_keyfile(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, 0));
+ OK_(crypt_keyslot_destroy(cd, 1));
+ OK_(crypt_keyslot_destroy(cd, 2));
+ OK_(crypt_keyslot_destroy(cd, 3));
+ OK_(crypt_keyslot_destroy(cd, 4));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ _remove_keyfiles();
+
+ FAIL_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), "slot used");
+ key[1] = ~key[1];
+ FAIL_(crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)), "key mismatch");
+ key[1] = ~key[1];
+ EQ_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase2, strlen(passphrase2)));
+ EQ_(CRYPT_SLOT_ACTIVE, crypt_keyslot_status(cd, 6));
+
+ FAIL_(crypt_keyslot_destroy(cd, 8), "invalid keyslot");
+ FAIL_(crypt_keyslot_destroy(cd, CRYPT_ANY_SLOT), "invalid keyslot");
+ FAIL_(crypt_keyslot_destroy(cd, 0), "keyslot not used");
+ OK_(crypt_keyslot_destroy(cd, 7));
+ EQ_(CRYPT_SLOT_INACTIVE, crypt_keyslot_status(cd, 7));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
+
+ EQ_(6, crypt_keyslot_change_by_passphrase(cd, 6, CRYPT_ANY_SLOT, passphrase2, strlen(passphrase2), passphrase, strlen(passphrase)));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
+ EQ_(7, crypt_keyslot_change_by_passphrase(cd, 6, 7, passphrase, strlen(passphrase), passphrase2, strlen(passphrase2)));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7));
+ EQ_(7, crypt_activate_by_passphrase(cd, NULL, 7, passphrase2, strlen(passphrase2), 0));
+ EQ_(6, crypt_keyslot_change_by_passphrase(cd, CRYPT_ANY_SLOT, 6, passphrase2, strlen(passphrase2), passphrase, strlen(passphrase)));
+
+ EQ_(6, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
+ OK_(crypt_volume_key_verify(cd, key2, key_size));
+ OK_(memcmp(key, key2, key_size));
+
+ OK_(strcmp(cipher, crypt_get_cipher(cd)));
+ OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(r_payload_offset, crypt_get_data_offset(cd));
+ OK_(strcmp(DEVICE_2, crypt_get_device_name(cd)));
+
+ reset_log();
+ OK_(crypt_dump(cd));
+ OK_(!(global_lines != 0));
+ reset_log();
+
+ FAIL_(crypt_dump_json(cd, NULL, 42), "flags be used later");
+ OK_(crypt_dump_json(cd, NULL, 0));
+ OK_(!(global_lines != 0));
+ reset_log();
+ OK_(crypt_dump_json(cd, &tmp_buf, 0));
+ OK_(!(tmp_buf && strlen(tmp_buf) != 0));
+
+ FAIL_(crypt_set_uuid(cd, "blah"), "wrong UUID format");
+ OK_(crypt_set_uuid(cd, DEVICE_TEST_UUID));
+ OK_(strcmp(DEVICE_TEST_UUID, crypt_get_uuid(cd)));
+
+ FAIL_(crypt_deactivate(cd, CDEVICE_2), "not active");
+ CRYPT_FREE(cd);
+ _cleanup_dmdevices();
+
+ /* LUKSv2 format tests */
+
+ /* very basic test */
+ OK_(crypt_init(&cd, DEVICE_2));
+ crypt_set_iteration_time(cd, 1);
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 0, NULL), "Wrong key size");
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
+ CRYPT_FREE(cd);
+ /* some invalid parameters known to cause troubles */
+ OK_(crypt_init(&cd, DEVICE_2));
+ crypt_set_iteration_time(cd, 0); /* wrong for argon2 but we don't know the pbkdf type yet, ignored */
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, key_size, NULL));
+ FAIL_(crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), "VK doesn't match any digest");
+ FAIL_(crypt_keyslot_add_by_volume_key(cd, 1, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), "VK doesn't match any digest");
+ CRYPT_FREE(cd);
+
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 3, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 3);
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key3, key_size, 0), "VK doesn't match any digest assigned to segment 0");
+ CRYPT_FREE(cd);
+
+ /*
+ * Check regression in getting keyslot encryption parameters when
+ * volume key size is unknown (no active keyslots).
+ */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ /* drop context copy of volume key */
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ EQ_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ OK_(crypt_keyslot_destroy(cd, 0));
+ OK_(set_fast_pbkdf(cd));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void Luks2MetadataSize(void)
+{
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 1,
+ .max_memory_kb = 128,
+ .iterations = 4,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+ };
+ struct crypt_params_luks2 params = {
+ .pbkdf = &pbkdf,
+ .data_device = DEVICE_2,
+ .sector_size = 512
+ };
+ char key[128], tmp[128];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_header_size, default_mdata_size, default_keyslots_size, mdata_size,
+ keyslots_size, r_header_wrong_size = 14336;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ pbkdf.iterations = 1000;
+ }
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ // init test devices
+ OK_(get_luks2_offsets(0, 0, 0, &r_header_size, NULL));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_header_wrong_size)); /* 7 MiBs only */
+ //default metadata sizes
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, 0);
+ EQ_(keyslots_size, 0);
+ OK_(crypt_set_metadata_size(cd, 0, 0));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, 0);
+ EQ_(keyslots_size, 0);
+ OK_(crypt_set_metadata_size(cd, 0x004000, 0x004000));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, 0x004000);
+ EQ_(keyslots_size, 0x004000);
+ OK_(crypt_set_metadata_size(cd, 0x008000, 0x008000));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, 0x008000);
+ EQ_(keyslots_size, 0x008000);
+ FAIL_(crypt_set_metadata_size(cd, 0x008001, 0x008000), "Wrong size");
+ FAIL_(crypt_set_metadata_size(cd, 0x008000, 0x008001), "Wrong size");
+ CRYPT_FREE(cd);
+
+ // metadata settings
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_metadata_size(cd, 0x080000, 0x080000));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, 0x080000);
+ EQ_(keyslots_size, 0x080000);
+ CRYPT_FREE(cd);
+ // default
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_get_metadata_size(cd, &default_mdata_size, &default_keyslots_size));
+ EQ_(default_mdata_size, 0x04000);
+ EQ_(default_keyslots_size, (r_header_size * 512) - 2 * 0x04000);
+ CRYPT_FREE(cd);
+ // check keyslots size calculation is correct
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_metadata_size(cd, 0x80000, 0));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, 0x80000);
+ EQ_(keyslots_size, (r_header_size * 512) - 2 * 0x80000);
+ CRYPT_FREE(cd);
+
+ // various metadata size checks combined with data offset
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_metadata_size(cd, 0, default_keyslots_size + 4096));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Device is too small.");
+ OK_(crypt_set_metadata_size(cd, 0x20000, (r_header_size * 512) - 2 * 0x20000 + 4096));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Device is too small.");
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_metadata_size(cd, 0x80000, 0));
+ OK_(crypt_set_data_offset(cd, 0x80000 / 512 - 8));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Data offset is too small.");
+ CRYPT_FREE(cd);
+
+ // H_DEVICE_WRONG size is 7MiB
+ OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, default_mdata_size);
+ EQ_(keyslots_size, (r_header_wrong_size * 512) - 2 * default_mdata_size);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
+ OK_(crypt_set_metadata_size(cd, 0x400000, 0));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params), "Device is too small.");
+ CRYPT_FREE(cd);
+
+ // IMAGE_EMPTY_SMALL size is 7MiB but now it's regulare file
+ OK_(crypt_init(&cd, IMAGE_EMPTY_SMALL));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, default_mdata_size);
+ EQ_(keyslots_size, default_keyslots_size);
+ EQ_(crypt_get_data_offset(cd), 0);
+ CRYPT_FREE(cd);
+
+ sprintf(tmp, "truncate -s %" PRIu64 " " IMAGE_EMPTY_SMALL, r_header_wrong_size * 512);
+ _system(tmp, 1);
+
+ // check explicit keyslots size and data offset are respected even with regular file mdevice
+ OK_(crypt_init(&cd, IMAGE_EMPTY_SMALL));
+ OK_(crypt_set_metadata_size(cd, 0, default_keyslots_size));
+ OK_(crypt_set_data_offset(cd, r_header_size + 8));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, default_mdata_size);
+ EQ_(keyslots_size, default_keyslots_size);
+ EQ_(crypt_get_data_offset(cd), r_header_size + 8);
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void UseTempVolumes(void)
+{
+ char tmp[256];
+
+ // Tepmporary device without keyslot but with on-disk LUKS header
+ OK_(crypt_init(&cd, DEVICE_2));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "not yet formatted");
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 16, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name(&cd, CDEVICE_2));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ CRYPT_FREE(cd);
+
+ // Dirty checks: device without UUID
+ // we should be able to remove it but not manipulate with it
+ GE_(snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
+ "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
+ "%s 2048\"", CDEVICE_2, DEVICE_2), 0);
+ _system(tmp, 1);
+ OK_(crypt_init_by_name(&cd, CDEVICE_2));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "No known device type");
+ CRYPT_FREE(cd);
+
+ // Dirty checks: device with UUID but LUKS header key fingerprint must fail)
+ GE_(snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
+ "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
+ "%s 2048\" -u CRYPT-LUKS2-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ctest1",
+ CDEVICE_2, DEVICE_2), 0);
+ _system(tmp, 1);
+ OK_(crypt_init_by_name(&cd, CDEVICE_2));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "wrong volume key");
+ CRYPT_FREE(cd);
+
+ // No slots
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "volume key is lost");
+ CRYPT_FREE(cd);
+}
+
+static void Luks2HeaderRestore(void)
+{
+ char key[128];
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 4,
+ .max_memory_kb = 1024,
+ .time_ms = 1
+ };
+ struct crypt_params_luks2 params = {
+ .pbkdf = &pbkdf,
+ .data_alignment = 8192, // 4M, data offset will be 4096
+ .sector_size = 512
+ };
+ struct crypt_params_plain pl_params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ .size = 0
+ };
+ struct crypt_params_luks1 luks1 = {
+ .data_alignment = 8192, // 4M offset to pass alignment test
+ };
+ uint32_t flags = 0;
+
+ const char *vk_hex = "ccadd99b16cd3d200c22d6db45d8b6630ef3d936767127347ec8a76ab992c2ea";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ }
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ OK_(get_luks2_offsets(0, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 5000));
+
+ // do not restore header over plain device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &pl_params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ FAIL_(crypt_header_restore(cd, CRYPT_PLAIN, NO_REQS_LUKS2_HEADER), "Cannot restore header to PLAIN type device");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS2, NO_REQS_LUKS2_HEADER), "Cannot restore header over PLAIN type device");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // FIXME: does following test make a sense in LUKS2?
+ // volume key_size mismatch
+ // OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ // memcpy(key2, key, key_size / 2);
+ // OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key2, key_size / 2, &params));
+ // FAIL_(crypt_header_restore(cd, CRYPT_LUKS2, VALID_LUKS2_HEADER), "Volume keysize mismatch");
+ // CRYPT_FREE(cd);
+
+ // payload offset mismatch
+ params.data_alignment = 8193;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS2, NO_REQS_LUKS2_HEADER), "Payload offset mismatch");
+ CRYPT_FREE(cd);
+ params.data_alignment = 4096;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ // FIXME: either format has to fail or next line must be true
+ // EQ_(crypt_get_data_offset(cd), params.data_alignment);
+ // FAIL_(crypt_header_restore(cd, CRYPT_LUKS2, VALID_LUKS2_HEADER), "Payload offset mismatch");
+ CRYPT_FREE(cd);
+
+ // do not allow restore over LUKS1 header on device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, NULL, 32, &luks1));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS2, NO_REQS_LUKS2_HEADER), "LUKS1 format detected");
+ CRYPT_FREE(cd);
+
+ /* check crypt_header_restore() properly loads crypt_device context */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 1*1024*1024, 1*1024*1024, 0, NULL, NULL));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS2, NO_REQS_LUKS2_HEADER));
+ /* check LUKS2 specific API call returns non-error code */
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags));
+ EQ_(flags, 0);
+ /* same test, any LUKS */
+ OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 1*1024*1024, 1*1024*1024, 0, NULL, NULL));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS, NO_REQS_LUKS2_HEADER));
+ /* check LUKS2 specific API call returns non-error code */
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags));
+ EQ_(flags, 0);
+
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void Luks2HeaderLoad(void)
+{
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 4,
+ .max_memory_kb = 1024,
+ .time_ms = 1
+ };
+ struct crypt_params_luks2 params = {
+ .pbkdf = &pbkdf,
+ .data_alignment = 8192, // 4M, data offset will be 4096
+ .data_device = DEVICE_2,
+ .sector_size = 512
+ };
+ struct crypt_params_plain pl_params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ .size = 0
+ };
+ char key[128], cmd[256];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset, r_header_size, img_size;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ }
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ // hardcoded values for existing image IMAGE1
+ img_size = 8192;
+ // prepare test env
+ OK_(get_luks2_offsets(0, 0, 0, &r_header_size, &r_payload_offset));
+ // external header device
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ // prepared header on a device too small to contain header and payload
+ //OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
+ OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, img_size - 1));
+ GE_(snprintf(cmd, sizeof(cmd), "dd if=" IMAGE1 " of=" DMDIR H_DEVICE_WRONG " bs=%" PRIu32
+ " count=%" PRIu64 " 2>/dev/null", params.sector_size, img_size - 1), 0);
+ OK_(_system(cmd, 1));
+ // some device
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
+ // 1 sector device
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_header_size + 1));
+ // 0 sectors device for payload
+ OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_header_size));
+
+ // valid metadata and device size
+ params.data_alignment = 0;
+ params.data_device = DMDIR L_DEVICE_OK;
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(!crypt_get_metadata_device_name(cd));
+ EQ_(strcmp(DMDIR H_DEVICE, crypt_get_metadata_device_name(cd)), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(1, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ // repeat with init with two devices
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(!crypt_get_metadata_device_name(cd));
+ EQ_(strcmp(DMDIR H_DEVICE, crypt_get_metadata_device_name(cd)), 0);
+ EQ_(1, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ // bad header: device too small (payloadOffset > device_size)
+ OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
+ FAIL_(crypt_load(cd, CRYPT_LUKS2, NULL), "Device too small");
+ NULL_(crypt_get_type(cd));
+ CRYPT_FREE(cd);
+
+ // 0 secs for encrypted data area
+ params.data_alignment = 8192;
+ params.data_device = NULL;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ // load should be ok
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device too small");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // damaged header
+ OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=8 2>/dev/null", 1));
+ OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 seek=32 count=8 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ FAIL_(crypt_load(cd, CRYPT_LUKS2, NULL), "Header not found");
+ CRYPT_FREE(cd);
+
+ // plain device
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ FAIL_(crypt_load(cd, CRYPT_PLAIN, NULL), "Can't load nonLUKS device type");
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, key, key_size, &pl_params));
+ FAIL_(crypt_load(cd, CRYPT_LUKS2, NULL), "Can't load over nonLUKS device type");
+ CRYPT_FREE(cd);
+
+ //LUKSv2 device
+ OK_(crypt_init(&cd, DEVICE_4));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DEVICE_4));
+ crypt_set_iteration_time(cd, 0); /* invalid for argon2 pbkdf, ignored */
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ CRYPT_FREE(cd);
+
+ /* check load sets proper device type */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ EQ_(strcmp(CRYPT_LUKS2, crypt_get_type(cd)), 0);
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void Luks2HeaderBackup(void)
+{
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 4,
+ .max_memory_kb = 1024,
+ .time_ms = 1
+ };
+ struct crypt_params_luks2 params = {
+ .pbkdf = &pbkdf,
+ .data_alignment = 8192, // 4M, data offset will be 4096
+ .data_device = DEVICE_2,
+ .sector_size = 512
+ };
+ char key[128];
+ int fd, ro = O_RDONLY;
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+
+ const char *passphrase = PASSPHRASE;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ }
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ OK_(get_luks2_offsets(1, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ // create LUKS device and backup the header
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, passphrase, strlen(passphrase)), 0);
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // restore header from backup
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS2, BACKUP_FILE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(0, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ // exercise luksOpen using backup header in file
+ OK_(crypt_init(&cd, BACKUP_FILE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(1, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, BACKUP_FILE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // exercise luksOpen using backup header on block device
+ fd = loop_attach(&DEVICE_3, BACKUP_FILE, 0, 0, &ro);
+ NOTFAIL_(fd, "Bad loop device.");
+ close(fd);
+ OK_(crypt_init(&cd, DEVICE_3));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_3));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void ResizeDeviceLuks2(void)
+{
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 4,
+ .max_memory_kb = 1024,
+ .time_ms = 1
+ };
+ struct crypt_params_luks2 params = {
+ .pbkdf = &pbkdf,
+ .data_alignment = 8192, // 4M, data offset will be 4096
+ .sector_size = 512
+ };
+ char key[128];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes", *capi_cipher = "capi:cbc(aes)";
+ const char *cipher_mode = "cbc-essiv:sha256", *capi_cipher_mode = "essiv:sha256";
+ uint64_t r_payload_offset, r_header_size, r_size;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ }
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ // prepare env
+ OK_(get_luks2_offsets(0, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(get_luks2_offsets(0, 0, 0, &r_header_size, NULL));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
+ OK_(create_dmdevice_over_loop(L_DEVICE_0S, 1000));
+ OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset + 1000));
+
+ // test header and encrypted payload all in one device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ // disable loading VKs in kernel keyring (compatible mode)
+ OK_(crypt_volume_key_keyring(cd, 0));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 42));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(42, r_size >> TST_SECTOR_SHIFT);
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ // autodetect encrypted device area size
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.data_alignment = 0;
+ params.data_device = DMDIR L_DEVICE_0S;
+ // test case for external header
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 666));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(666, r_size >> TST_SECTOR_SHIFT);
+ // autodetect encrypted device size
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+#ifdef KERNEL_KEYRING
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ // enable loading VKs in kernel keyring (default mode)
+ OK_(crypt_volume_key_keyring(cd, 1));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ // erase volume key from kernel keyring
+ if (t_dm_crypt_keyring_support())
+ OK_(_drop_keyring_key(cd, 0));
+ else
+ FAIL_(_drop_keyring_key(cd, 0), "key not found");
+ // same size is ok
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ // kernel fails to find the volume key in keyring
+ if (t_dm_crypt_keyring_support())
+ FAIL_(crypt_resize(cd, CDEVICE_1, 42), "Unable to find volume key in keyring");
+ else
+ OK_(crypt_resize(cd, CDEVICE_1, 42));
+ // test mode must not load vk in keyring
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ if (t_dm_crypt_keyring_support())
+ FAIL_(crypt_resize(cd, CDEVICE_1, 44), "VK must be in keyring to perform resize");
+ else
+ OK_(crypt_resize(cd, CDEVICE_1, 44));
+ // reinstate the volume key in keyring
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 43));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(43, r_size >> TST_SECTOR_SHIFT);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ // check userspace gets hint volume key must be properly loaded in kernel keyring
+ if (t_dm_crypt_keyring_support())
+ EQ_(crypt_resize(cd, CDEVICE_1, 0), -EPERM);
+ else
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ CRYPT_FREE(cd);
+
+ // same as above for handles initialised by name
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ if (t_dm_crypt_keyring_support())
+ EQ_(crypt_resize(cd, CDEVICE_1, 0), -EPERM);
+ else
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+#endif
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, NULL, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+
+ /* create second LUKS2 device */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ OK_(crypt_format(cd2, CRYPT_LUKS2, cipher, cipher_mode, crypt_get_uuid(cd), key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
+ /* do not allow resize of other device */
+ FAIL_(crypt_resize(cd2, CDEVICE_1, 1), "Device got resized by wrong device context.");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ OK_(crypt_set_pbkdf_type(cd2, &min_pbkdf2));
+ OK_(crypt_format(cd2, CRYPT_LUKS1, cipher, cipher_mode, crypt_get_uuid(cd), key, key_size, NULL));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
+ FAIL_(crypt_resize(cd2, CDEVICE_1, 1), "Device got resized by wrong device context.");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ OK_(crypt_format(cd2, CRYPT_PLAIN, cipher, cipher_mode, NULL, key, key_size, NULL));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
+ FAIL_(crypt_resize(cd2, CDEVICE_1, 1), "Device got resized by wrong device context.");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ if (t_dm_capi_string_supported()) {
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS2, capi_cipher, capi_cipher_mode, NULL, key, key_size, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 8));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(8, r_size >> TST_SECTOR_SHIFT);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+ }
+
+ _cleanup_dmdevices();
+}
+
+static void TokenActivationByKeyring(void)
+{
+#ifdef KERNEL_KEYRING
+ key_serial_t kid, kid1;
+ struct crypt_active_device cad;
+
+ const char *cipher = "aes";
+ const char *cipher_mode = "xts-plain64";
+
+ const struct crypt_token_params_luks2_keyring params = {
+ .key_description = KEY_DESC_TEST0
+ }, params2 = {
+ .key_description = KEY_DESC_TEST1
+ }, params_invalid = {};
+ uint64_t r_payload_offset;
+
+ if (!t_dm_crypt_keyring_support()) {
+ printf("WARNING: Kernel keyring not supported, skipping test.\n");
+ return;
+ }
+
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+
+ // prepare the device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ FAIL_(crypt_token_luks2_keyring_set(cd, CRYPT_ANY_TOKEN, &params_invalid), "Invalid key description property.");
+ EQ_(crypt_token_luks2_keyring_set(cd, 3, &params), 3);
+ EQ_(crypt_token_assign_keyslot(cd, 3, 0), 3);
+ CRYPT_FREE(cd);
+
+ // test thread keyring key in token 0
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 3, NULL, 0), 0);
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 3, NULL, 0), "already open");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_PROCESS_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
+ // add token 1 with process keyring key
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_token_json_set(cd, 3, NULL), 3);
+ EQ_(crypt_token_luks2_keyring_set(cd, 1, &params), 1);
+ EQ_(crypt_token_assign_keyslot(cd, 1, 0), 1);
+ CRYPT_FREE(cd);
+
+ // test process keyring key in token 1
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 1, NULL, 0), 0);
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 1, NULL, 0), "already open");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_PROCESS_KEYRING), "Test or kernel keyring are broken.");
+
+ // create two tokens and let the cryptsetup unlock the volume with the valid one
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
+ kid1 = add_key("user", KEY_DESC_TEST1, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid1, "Test or kernel keyring are broken.");
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_token_luks2_keyring_set(cd, 0, &params), 0);
+ EQ_(crypt_token_assign_keyslot(cd, 0, 0), 0);
+ EQ_(crypt_token_luks2_keyring_set(cd, 1, &params2), 1);
+ FAIL_(crypt_token_assign_keyslot(cd, 1, 1), "Keyslot 1 doesn't exist");
+ OK_(set_fast_pbkdf(cd));
+ EQ_(crypt_keyslot_add_by_passphrase(cd, 1, PASSPHRASE, strlen(PASSPHRASE), PASSPHRASE1, strlen(PASSPHRASE1)), 1);
+ EQ_(crypt_token_assign_keyslot(cd, 1, 1), 1);
+ CRYPT_FREE(cd);
+
+ // activate by specific token
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 0, NULL, 0), 0);
+ if (t_dm_crypt_keyring_support()) {
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.flags & CRYPT_ACTIVATE_KEYRING_KEY, CRYPT_ACTIVATE_KEYRING_KEY);
+ }
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 1, NULL, 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+
+ // activate by any token with token 0 having absent pass from keyring
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, CRYPT_ANY_TOKEN, NULL, 0), 1);
+ if (t_dm_crypt_keyring_support()) {
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.flags & CRYPT_ACTIVATE_KEYRING_KEY, CRYPT_ACTIVATE_KEYRING_KEY);
+ }
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
+ // replace pass for keyslot 0 making token 0 invalid
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_keyslot_destroy(cd, 0));
+ OK_(set_fast_pbkdf(cd));
+ EQ_(crypt_keyslot_add_by_passphrase(cd, 0, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE1, strlen(PASSPHRASE1)), 0);
+ CRYPT_FREE(cd);
+
+ // activate by any token with token 0 having wrong pass for keyslot 0
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, CRYPT_ANY_TOKEN, NULL, 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // create new device, with two tokens:
+ // 1st token being invalid (missing key in keyring)
+ // 2nd token can activate keyslot 1 after failing to do so w/ keyslot 0 (wrong pass)
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 1);
+ EQ_(crypt_token_luks2_keyring_set(cd, 0, &params), 0);
+ EQ_(crypt_token_assign_keyslot(cd, 0, 0), 0);
+ EQ_(crypt_token_luks2_keyring_set(cd, 2, &params2), 2);
+ EQ_(crypt_token_assign_keyslot(cd, 2, 1), 2);
+ CRYPT_FREE(cd);
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+
+ kid1 = add_key("user", KEY_DESC_TEST1, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid1, "Test or kernel keyring are broken.");
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, CRYPT_ANY_TOKEN, NULL, 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+ _cleanup_dmdevices();
+#else
+ printf("WARNING: cryptsetup compiled with kernel keyring service disabled, skipping test.\n");
+#endif
+}
+
+static void Tokens(void)
+{
+#define TEST_TOKEN_JSON(x) "{\"type\":\"test_token\",\"keyslots\":[" x "]," \
+ "\"key_length\":32,\"a_field\":\"magic_string\"}"
+
+#define TEST_TOKEN_JSON_INVALID(x) "{\"type\":\"test_token\",\"keyslots\":[" x "]," \
+ "\"key_length\":32}"
+
+#define TEST_TOKEN1_JSON(x) "{\"type\":\"test_token1\",\"keyslots\":[" x "]," \
+ "\"key_length\":32,\"a_field\":\"magic_string\"}"
+
+#define TEST_TOKEN1_JSON_INVALID(x) "{\"type\":\"test_token1\",\"keyslots\":[" x "]," \
+ "\"key_length\":32}"
+
+#define BOGUS_TOKEN0_JSON "{\"type\":\"luks2-\",\"keyslots\":[]}"
+#define BOGUS_TOKEN1_JSON "{\"type\":\"luks2-a\",\"keyslots\":[]}"
+
+#define LUKS2_KEYRING_TOKEN_JSON(x, y) "{\"type\":\"luks2-keyring\",\"keyslots\":[" x "]," \
+ "\"key_description\":" y "}"
+
+#define LUKS2_KEYRING_TOKEN_JSON_BAD(x, y) "{\"type\":\"luks2-keyring\",\"keyslots\":[" x "]," \
+ "\"key_description\":" y ", \"some_field\":\"some_value\"}"
+
+
+ int ks, token_max;
+ const char *dummy;
+ const char *cipher = "aes";
+ const char *cipher_mode = "xts-plain64";
+ char passptr[] = PASSPHRASE;
+ char passptr1[] = PASSPHRASE1;
+ struct crypt_active_device cad;
+
+ static const crypt_token_handler th = {
+ .name = "test_token",
+ .open = test_open,
+ .validate = test_validate
+ }, th2 = {
+ .name = "test_token",
+ .open = test_open
+ }, th3 = {
+ .name = "test_token1",
+ .open = test_open,
+ .validate = test_validate
+ }, th_reserved = {
+ .name = "luks2-prefix",
+ .open = test_open
+ };
+
+ struct crypt_token_params_luks2_keyring params = {
+ .key_description = "desc"
+ };
+ uint64_t r_payload_offset;
+
+ OK_(crypt_token_register(&th));
+ FAIL_(crypt_token_register(&th2), "Token handler with the name already registered.");
+
+ FAIL_(crypt_token_register(&th_reserved), "luks2- is reserved prefix");
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+
+ // basic token API tests
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ EQ_(crypt_token_status(cd, -1, NULL), CRYPT_TOKEN_INVALID);
+ EQ_(crypt_token_status(cd, 32, NULL), CRYPT_TOKEN_INVALID);
+ EQ_(crypt_token_status(cd, 0, NULL), CRYPT_TOKEN_INACTIVE);
+ EQ_(crypt_token_status(cd, 31, NULL), CRYPT_TOKEN_INACTIVE);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 1);
+ FAIL_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, TEST_TOKEN_JSON_INVALID("\"0\"")), "Token validation failed");
+ EQ_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, TEST_TOKEN_JSON("\"0\"")), 0);
+ EQ_(crypt_token_status(cd, 0, NULL), CRYPT_TOKEN_EXTERNAL);
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 0, passptr, 0), 0);
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 0, passptr, 0), "already active");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // write invalid token and verify that validate() can detect it after handler being registered
+ EQ_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, TEST_TOKEN1_JSON_INVALID("\"1\"")), 1);
+ EQ_(crypt_token_status(cd, 1, NULL), CRYPT_TOKEN_EXTERNAL_UNKNOWN);
+ EQ_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, TEST_TOKEN1_JSON("\"1\"")), 2);
+ EQ_(crypt_token_status(cd, 2, &dummy), CRYPT_TOKEN_EXTERNAL_UNKNOWN);
+ OK_(strcmp(dummy, "test_token1"));
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 1, passptr1, 0), "Unknown token handler");
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr1, 0), "Unknown token handler");
+ OK_(crypt_token_register(&th3));
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 1, passptr1, 0), "Token validation failed");
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr1, 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // test crypt_token_json_get returns correct token id
+ EQ_(crypt_token_json_get(cd, 2, &dummy), 2);
+
+ // exercise assign/unassign keyslots API
+ EQ_(crypt_token_unassign_keyslot(cd, 2, 1), 2);
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr1, 0), "Token assigned to no keyslot");
+ EQ_(crypt_token_assign_keyslot(cd, 2, 0), 2);
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr1, 0), "Wrong passphrase");
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr, 0), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_token_json_set(cd, 1, NULL), 1);
+ FAIL_(crypt_token_json_get(cd, 1, &dummy), "Token is not there");
+ EQ_(crypt_token_unassign_keyslot(cd, 2, CRYPT_ANY_SLOT), 2);
+ EQ_(crypt_token_unassign_keyslot(cd, 0, CRYPT_ANY_SLOT), 0);
+
+ // various tests related to unassigned keyslot to volume segment
+ EQ_(crypt_keyslot_add_by_key(cd, 3, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 3);
+ EQ_(crypt_token_assign_keyslot(cd, 2, 0), 2);
+ EQ_(crypt_token_assign_keyslot(cd, 0, 3), 0);
+
+ EQ_(crypt_activate_by_token(cd, NULL, 2, passptr, 0), 0);
+ EQ_(crypt_activate_by_token(cd, NULL, 0, passptr1, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 3);
+ // FIXME: useless error message here (or missing one to be specific)
+ FAIL_(crypt_activate_by_token(cd, CDEVICE_1, 0, passptr1, 0), "No volume key available in token keyslots");
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr, 0), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_token_assign_keyslot(cd, 0, 1), 0);
+ OK_(crypt_token_is_assigned(cd, 0, 1));
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 0, passptr1, 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ EQ_(crypt_token_assign_keyslot(cd, 2, 3), 2);
+ OK_(crypt_token_is_assigned(cd, 2, 3));
+ EQ_(crypt_activate_by_token(cd, NULL, 2, passptr, 0), 0);
+ EQ_(crypt_activate_by_token(cd, CDEVICE_1, 2, passptr, 0), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+#ifdef KERNEL_KEYRING
+ if (t_dm_crypt_keyring_support()) {
+ EQ_(crypt_activate_by_token(cd, NULL, 2, passptr, CRYPT_ACTIVATE_KEYRING_KEY), 0);
+ OK_(_volume_key_in_keyring(cd, 0));
+ }
+ OK_(crypt_volume_key_keyring(cd, 0));
+#endif
+ FAIL_(crypt_activate_by_token(cd, NULL, 2, passptr, CRYPT_ACTIVATE_KEYRING_KEY), "Can't use keyring when disabled in library");
+ OK_(crypt_volume_key_keyring(cd, 1));
+
+ EQ_(crypt_token_luks2_keyring_set(cd, 5, &params), 5);
+ EQ_(crypt_token_status(cd, 5, &dummy), CRYPT_TOKEN_INTERNAL);
+ OK_(strcmp(dummy, "luks2-keyring"));
+
+ FAIL_(crypt_token_luks2_keyring_get(cd, 2, &params), "Token is not luks2-keyring type");
+
+ FAIL_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, BOGUS_TOKEN0_JSON), "luks2- reserved prefix.");
+ FAIL_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, BOGUS_TOKEN1_JSON), "luks2- reserved prefix.");
+
+ // test we can use crypt_token_json_set for valid luks2-keyring token
+ FAIL_(crypt_token_json_set(cd, 12, LUKS2_KEYRING_TOKEN_JSON_BAD("\"0\"", "\"my_desc_x\"")), "Strict luks2-keyring token validation failed");
+ EQ_(crypt_token_status(cd, 12, NULL), CRYPT_TOKEN_INACTIVE);
+ FAIL_(crypt_token_json_set(cd, 12, LUKS2_KEYRING_TOKEN_JSON("\"5\"", "\"my_desc\"")), "Missing keyslot 5.");
+ EQ_(crypt_token_json_set(cd, 10, LUKS2_KEYRING_TOKEN_JSON("\"1\"", "\"my_desc\"")), 10);
+ EQ_(crypt_token_status(cd, 10, &dummy), CRYPT_TOKEN_INTERNAL);
+ OK_(strcmp(dummy, "luks2-keyring"));
+ params.key_description = NULL;
+ EQ_(crypt_token_luks2_keyring_get(cd, 10, &params), 10);
+ OK_(strcmp(params.key_description, "my_desc"));
+
+ OK_(crypt_token_is_assigned(cd, 10, 1));
+ // unassigned tests
+ EQ_(crypt_token_is_assigned(cd, 10, 21), -ENOENT);
+ EQ_(crypt_token_is_assigned(cd, 21, 1), -ENOENT);
+ // wrong keyslot or token id tests
+ EQ_(crypt_token_is_assigned(cd, -1, 1), -EINVAL);
+ EQ_(crypt_token_is_assigned(cd, 32, 1), -EINVAL);
+ EQ_(crypt_token_is_assigned(cd, 10, -1), -EINVAL);
+ EQ_(crypt_token_is_assigned(cd, 10, 32), -EINVAL);
+ EQ_(crypt_token_is_assigned(cd, -1, -1), -EINVAL);
+ EQ_(crypt_token_is_assigned(cd, 32, 32), -EINVAL);
+
+ // test crypt_keyslot_change_by_passphrase does not erase token references
+ EQ_(crypt_keyslot_change_by_passphrase(cd, 1, 5, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE1, strlen(PASSPHRASE1)), 5);
+ OK_(crypt_token_is_assigned(cd, 10, 5));
+ ks = crypt_keyslot_change_by_passphrase(cd, 5, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE1, strlen(PASSPHRASE1));
+ NOTFAIL_(ks, "Failed to change keyslot passphrase.");
+ OK_(crypt_token_is_assigned(cd, 10, ks));
+ CRYPT_FREE(cd);
+
+ // test token activation respects keyslot priorities
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 3, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 3);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 5, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 5);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 8, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 8);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 12, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 12);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 21);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 31, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 31);
+
+ OK_(crypt_keyslot_set_priority(cd, 0, CRYPT_SLOT_PRIORITY_IGNORE));
+ OK_(crypt_keyslot_set_priority(cd, 3, CRYPT_SLOT_PRIORITY_PREFER));
+ OK_(crypt_keyslot_set_priority(cd, 8, CRYPT_SLOT_PRIORITY_PREFER));
+ OK_(crypt_keyslot_set_priority(cd, 12,CRYPT_SLOT_PRIORITY_PREFER));
+
+ // expected unusable with CRYPT_ANY_TOKEN
+ EQ_(crypt_token_json_set(cd, 1, TEST_TOKEN_JSON("\"0\", \"3\"")), 1);
+
+ // expected unusable (-EPERM)
+ EQ_(crypt_token_json_set(cd, 5, TEST_TOKEN_JSON("\"8\"")), 5);
+
+ // expected unusable (-EPERM)
+ EQ_(crypt_token_json_set(cd, 4, TEST_TOKEN_JSON("\"8\", \"3\"")), 4);
+
+ // expected unusable (-ENOENT)
+ EQ_(crypt_token_json_set(cd, 6, TEST_TOKEN_JSON("\"3\"")), 6);
+
+ // expected unusable (-ENOENT)
+ EQ_(crypt_token_json_set(cd, 11, TEST_TOKEN_JSON("")), 11);
+
+ token_max = crypt_token_max(CRYPT_LUKS2) - 1;
+ GE_(token_max, 0);
+
+ // expected to be used first with CRYPT_ANY_TOKEN (unlocks with high priority ks 12)
+ EQ_(crypt_token_json_set(cd, token_max, TEST_TOKEN_JSON("\"12\", \"0\", \"3\"")), token_max);
+
+ // expected usable with CRYPT_ANY_TOKEN
+ EQ_(crypt_token_json_set(cd, 8, TEST_TOKEN_JSON("\"5\", \"0\", \"3\"")), 8);
+
+ // of all tokens keyslot 12 has highest priority now
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 12);
+ EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 12);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // with explicit token priority ignore may be used
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 1, NULL, 0, passptr, 0), 0);
+ EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", 1, NULL, 0, passptr, 0), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ EQ_(crypt_token_json_set(cd, token_max, NULL), token_max);
+
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 5);
+
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 5, NULL, 0, passptr, 0), -EPERM);
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 4, NULL, 0, passptr, 0), -EPERM);
+
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 6, NULL, 0, passptr, 0), -ENOENT);
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 6, NULL, 0, passptr, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 3);
+
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 11, NULL, 0, passptr, 0), -ENOENT);
+ EQ_(crypt_activate_by_token_pin(cd, NULL, "test_token", 11, NULL, 0, passptr, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), -ENOENT);
+
+ // test crypt_resume_by_token_pin
+ EQ_(crypt_activate_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr, 0), 5);
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ EQ_(crypt_resume_by_token_pin(cd, CDEVICE_1, "test_token", CRYPT_ANY_TOKEN, NULL, 0, passptr), 5);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ EQ_(crypt_token_max(CRYPT_LUKS2), 32);
+ FAIL_(crypt_token_max(CRYPT_LUKS1), "No token support in LUKS1");
+ FAIL_(crypt_token_max(NULL), "No LUKS format specified");
+ _cleanup_dmdevices();
+}
+
+static void LuksConvert(void)
+{
+ uint64_t offset, r_payload_offset;
+
+ const char *json = "{\"type\":\"convert_block\",\"keyslots\":[]}";
+ const struct crypt_pbkdf_type argon = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha512",
+ .time_ms = 1,
+ .max_memory_kb = 1024,
+ .parallel_threads = 1
+ }, pbkdf2 = {
+ .type = CRYPT_KDF_PBKDF2,
+ .hash = "sha256",
+ .time_ms = 1
+ };
+
+ struct crypt_params_luks1 luks1 = {
+ .hash = "sha256",
+ .data_device = DMDIR L_DEVICE_1S
+ };
+
+ struct crypt_params_luks2 luks2 = {
+ .pbkdf = &pbkdf2,
+ .sector_size = 512
+ };
+
+ const char *cipher = "aes";
+ const char *cipher_mode = "xts-plain64";
+
+ // prepare the device
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ offset = crypt_get_data_offset(cd);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 7);
+ CRYPT_FREE(cd);
+
+ // convert LUKSv1 -> LUKSv2
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "format is already LUKSv1");
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ FAIL_(crypt_convert(cd, CRYPT_LUKS2, NULL), "device is active");
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS1));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS2));
+ CRYPT_FREE(cd);
+
+ // check result
+ OK_(crypt_init(&cd, DEVICE_1));
+ FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "wrong luks format");
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS2));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), 0), 7);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_convert(cd, CRYPT_LUKS2, NULL), "format is already LUKSv2");
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS2));
+ CRYPT_FREE(cd);
+
+ // convert LUKSv2 -> LUKSv1
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "device is active");
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS2));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS1));
+ CRYPT_FREE(cd);
+
+ // check result
+ OK_(crypt_init(&cd, DEVICE_1));
+ FAIL_(crypt_load(cd, CRYPT_LUKS2, NULL), "wrong luks format");
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS1));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), 0), 7);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "format is already LUKSv1");
+ OK_(strcmp(crypt_get_type(cd), CRYPT_LUKS1));
+ CRYPT_FREE(cd);
+
+ // exercice non-pbkdf2 LUKSv2 conversion
+ if (!_fips_mode) {
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_set_data_offset(cd, offset));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ OK_(crypt_set_pbkdf_type(cd, &argon));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "Incompatible pbkdf with LUKSv1 format");
+ CRYPT_FREE(cd);
+ }
+
+ // exercice non LUKS1 compatible keyslot
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_set_data_offset(cd, offset));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, &luks2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ // FIXME: following test fails as expected but for a different reason
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "Unassigned keyslots are incompatible with LUKSv1 format");
+ CRYPT_FREE(cd);
+
+ // exercice LUKSv2 conversion with single pbkdf2 keyslot being active
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_set_data_offset(cd, offset));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ offset = crypt_get_data_offset(cd);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ if (!_fips_mode) {
+ OK_(crypt_set_pbkdf_type(cd, &argon));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 1);
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "Different hash for digest and keyslot.");
+ OK_(crypt_keyslot_destroy(cd, 1));
+ }
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ CRYPT_FREE(cd);
+
+ // do not allow conversion on keyslot No > 7
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_set_data_offset(cd, offset));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, &luks2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 8, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 8);
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "Can't convert keyslot No 8");
+ CRYPT_FREE(cd);
+
+ // do not allow conversion with token
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_set_data_offset(cd, offset));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, &luks2));
+ OK_(crypt_token_json_set(cd, CRYPT_ANY_TOKEN, json));
+ FAIL_(crypt_convert(cd, CRYPT_LUKS1, NULL), "Can't convert header with token.");
+ CRYPT_FREE(cd);
+
+ // should be enough for both luks1 and luks2 devices with all vk lengths
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+
+ // do not allow conversion for legacy luks1 device (non-aligned keyslot offset)
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L1_256_LEGACY " of=" DMDIR L_DEVICE_1S " bs=1M count=2 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ FAIL_(crypt_convert(cd, CRYPT_LUKS2, NULL), "Can't convert device with unaligned keyslot offset");
+ CRYPT_FREE(cd);
+
+ /*
+ * do not allow conversion on images if there's not enough space between
+ * last keyslot and data offset (should not happen on headers created
+ * with cryptsetup)
+ */
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L1_256_UNMOVABLE " of=" DMDIR L_DEVICE_1S " bs=1M count=2 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ FAIL_(crypt_convert(cd, CRYPT_LUKS2, NULL), "Can't convert device with unaligned keyslot offset");
+ CRYPT_FREE(cd);
+
+ // compat conversion tests
+ // LUKS1 -> LUKS2
+
+ // 128b key
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L1_128 " of=" DMDIR L_DEVICE_1S " bs=1M count=2 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS2), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 256b key
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L1_256 " of=" DMDIR L_DEVICE_1S " bs=1M count=2 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS2), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 512b key
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L1_512 " of=" DMDIR L_DEVICE_1S " bs=1M count=2 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS2), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // detached LUKS1 header conversion
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L1_128_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS2), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L1_128_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 256b key
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L1_256_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS2), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L1_256_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 512b key
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L1_512_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS2), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L1_512_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // LUKS2 -> LUKS1
+ // 128b key
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L2_128 " of=" DMDIR L_DEVICE_1S " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 128b all LUKS1 keyslots used
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L2_128_FULL " of=" DMDIR L_DEVICE_1S " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASS1, strlen(PASS1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 2, PASS2, strlen(PASS2), 0), 2);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 3, PASS3, strlen(PASS3), 0), 3);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 4, PASS4, strlen(PASS4), 0), 4);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 5, PASS5, strlen(PASS5), 0), 5);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 6, PASS6, strlen(PASS6), 0), 6);
+ CRYPT_FREE(cd);
+
+ // 256b key
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L2_256 " of=" DMDIR L_DEVICE_1S " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 256b all LUKS1 keyslots used
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L2_256_FULL " of=" DMDIR L_DEVICE_1S " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASS1, strlen(PASS1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 2, PASS2, strlen(PASS2), 0), 2);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 3, PASS3, strlen(PASS3), 0), 3);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 4, PASS4, strlen(PASS4), 0), 4);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 5, PASS5, strlen(PASS5), 0), 5);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 6, PASS6, strlen(PASS6), 0), 6);
+ CRYPT_FREE(cd);
+
+ // 512b key
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L2_512 " of=" DMDIR L_DEVICE_1S " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 512b all LUKS1 keyslots used
+ OK_(_system("dd if=" CONV_DIR "/" CONV_L2_512_FULL " of=" DMDIR L_DEVICE_1S " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASS1, strlen(PASS1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 2, PASS2, strlen(PASS2), 0), 2);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 3, PASS3, strlen(PASS3), 0), 3);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 4, PASS4, strlen(PASS4), 0), 4);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 5, PASS5, strlen(PASS5), 0), 5);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 6, PASS6, strlen(PASS6), 0), 6);
+ CRYPT_FREE(cd);
+
+ // detached headers
+ // 128b
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_128_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_128_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 128b all LUKS1 keyslots used
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_128_DET_FULL));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_128_DET_FULL));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASS1, strlen(PASS1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 2, PASS2, strlen(PASS2), 0), 2);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 3, PASS3, strlen(PASS3), 0), 3);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 4, PASS4, strlen(PASS4), 0), 4);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 5, PASS5, strlen(PASS5), 0), 5);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 6, PASS6, strlen(PASS6), 0), 6);
+ CRYPT_FREE(cd);
+
+ // 256b key
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_256_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_256_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 256b all LUKS1 keyslots used
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_256_DET_FULL));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_256_DET_FULL));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASS1, strlen(PASS1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 2, PASS2, strlen(PASS2), 0), 2);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 3, PASS3, strlen(PASS3), 0), 3);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 4, PASS4, strlen(PASS4), 0), 4);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 5, PASS5, strlen(PASS5), 0), 5);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 6, PASS6, strlen(PASS6), 0), 6);
+ CRYPT_FREE(cd);
+
+ // 512b key
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_512_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ offset = crypt_get_data_offset(cd);
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_512_DET));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), offset);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ CRYPT_FREE(cd);
+
+ // 512b all LUKS1 keyslots used
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_512_DET_FULL));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_convert(cd, CRYPT_LUKS1, NULL));
+ EQ_(strcmp(crypt_get_type(cd), CRYPT_LUKS1), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, CONV_DIR "/" CONV_L2_512_DET_FULL));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 0, PASS0, strlen(PASS0), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 7, PASS7, strlen(PASS7), 0), 7);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASS1, strlen(PASS1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 2, PASS2, strlen(PASS2), 0), 2);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 3, PASS3, strlen(PASS3), 0), 3);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 4, PASS4, strlen(PASS4), 0), 4);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 5, PASS5, strlen(PASS5), 0), 5);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 6, PASS6, strlen(PASS6), 0), 6);
+ CRYPT_FREE(cd);
+
+ // detached LUKS1 header upconversion
+ OK_(create_dmdevice_over_loop(H_DEVICE, 2050)); // default LUKS1 header should fit there
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, "aes", "xts-plain64", NULL, NULL, 32, &luks1));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 7);
+ FAIL_(crypt_convert(cd, CRYPT_LUKS2, NULL), "Unable to move keyslots. Not enough space.");
+ CRYPT_FREE(cd);
+
+ // 2050 sectors, empty file
+ OK_(crypt_init(&cd, IMAGE_EMPTY_SMALL_2));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, "aes", "xts-plain64", NULL, NULL, 32, &luks1));
+ EQ_(crypt_get_data_offset(cd), 0);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 7);
+ OK_(crypt_convert(cd, CRYPT_LUKS2, NULL));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void Pbkdf(void)
+{
+ const struct crypt_pbkdf_type *pbkdf;
+
+ const char *cipher = "aes", *mode="xts-plain64";
+ struct crypt_pbkdf_type argon2 = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = default_luks1_hash,
+ .time_ms = 6,
+ .max_memory_kb = 1024,
+ .parallel_threads = 1
+ }, pbkdf2 = {
+ .type = CRYPT_KDF_PBKDF2,
+ .hash = default_luks1_hash,
+ .time_ms = 9
+ }, bad = {
+ .type = "hamster_pbkdf",
+ .hash = default_luks1_hash
+ };
+ struct crypt_params_plain params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ .size = 0
+ };
+ struct crypt_params_luks1 luks1 = {
+ .hash = "sha512", // test non-standard hash
+ .data_alignment = 2048,
+ };
+
+ uint64_t r_payload_offset;
+
+ /* Only PBKDF2 is allowed in FIPS, these tests cannot be run. */
+ if (_fips_mode)
+ return;
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ NULL_(crypt_get_pbkdf_type_params(NULL));
+ NULL_(crypt_get_pbkdf_type_params("suslik"));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_PBKDF2));
+ OK_(strcmp(pbkdf->type, CRYPT_KDF_PBKDF2));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_ARGON2I));
+ OK_(strcmp(pbkdf->type, CRYPT_KDF_ARGON2I));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type_params(CRYPT_KDF_ARGON2ID));
+ OK_(strcmp(pbkdf->type, CRYPT_KDF_ARGON2ID));
+
+ // test empty context
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ NULL_(crypt_get_pbkdf_type(cd));
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ NOTNULL_(crypt_get_pbkdf_type(cd));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ NOTNULL_(crypt_get_pbkdf_type(cd));
+ OK_(crypt_set_pbkdf_type(cd, NULL));
+ NOTNULL_(crypt_get_pbkdf_type(cd));
+
+ // test plain device
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, mode, NULL, NULL, 32, &params));
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ OK_(crypt_set_pbkdf_type(cd, NULL));
+ NOTNULL_(crypt_get_pbkdf_type(cd));
+ CRYPT_FREE(cd);
+
+ // test LUKSv1 device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, mode, NULL, NULL, 32, NULL));
+ FAIL_(crypt_set_pbkdf_type(cd, &argon2), "Unsupported with non-LUKS2 devices");
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ OK_(crypt_set_pbkdf_type(cd, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ EQ_(pbkdf->time_ms, default_luks1_iter_time);
+ CRYPT_FREE(cd);
+ // test value set in crypt_set_iteration_time() can be obtained via following crypt_get_pbkdf_type()
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ crypt_set_iteration_time(cd, 42);
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, mode, NULL, NULL, 32, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ EQ_(pbkdf->time_ms, 42);
+ // test crypt_get_pbkdf_type() returns expected values for LUKSv1
+ OK_(strcmp(pbkdf->type, CRYPT_KDF_PBKDF2));
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->max_memory_kb, 0);
+ EQ_(pbkdf->parallel_threads, 0);
+ crypt_set_iteration_time(cd, 43);
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ EQ_(pbkdf->time_ms, 43);
+ CRYPT_FREE(cd);
+ // test whether crypt_get_pbkdf_type() after double crypt_load()
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ crypt_set_iteration_time(cd, 42);
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ EQ_(pbkdf->time_ms, 42);
+ CRYPT_FREE(cd);
+ // test whether hash passed via *params in crypt_load() has higher priority
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ crypt_set_iteration_time(cd, 1);
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, mode, NULL, NULL, 32, &luks1));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->hash, luks1.hash));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->hash, luks1.hash));
+ CRYPT_FREE(cd);
+
+ // test LUKSv2 device
+ // test default values are set
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, mode, NULL, NULL, 32, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->type, default_luks2_pbkdf));
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->time_ms, default_luks2_iter_time);
+ EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory());
+ EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
+ // set and verify argon2 type
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->type, argon2.type));
+ OK_(strcmp(pbkdf->hash, argon2.hash));
+ EQ_(pbkdf->time_ms, argon2.time_ms);
+ EQ_(pbkdf->max_memory_kb, argon2.max_memory_kb);
+ EQ_(pbkdf->parallel_threads, argon2.parallel_threads);
+ // set and verify pbkdf2 type
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->type, pbkdf2.type));
+ OK_(strcmp(pbkdf->hash, pbkdf2.hash));
+ EQ_(pbkdf->time_ms, pbkdf2.time_ms);
+ EQ_(pbkdf->max_memory_kb, pbkdf2.max_memory_kb);
+ EQ_(pbkdf->parallel_threads, pbkdf2.parallel_threads);
+ // reset and verify default values
+ crypt_set_iteration_time(cd, 1); // it's supposed to override this call
+ OK_(crypt_set_pbkdf_type(cd, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->type, default_luks2_pbkdf));
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->time_ms, default_luks2_iter_time);
+ EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory());
+ EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
+ // try to pass illegal values
+ argon2.parallel_threads = 0;
+ FAIL_(crypt_set_pbkdf_type(cd, &argon2), "Parallel threads can't be 0");
+ argon2.parallel_threads = 1;
+ argon2.max_memory_kb = 0;
+ FAIL_(crypt_set_pbkdf_type(cd, &argon2), "Memory can't be 0");
+ argon2.max_memory_kb = 1024;
+ pbkdf2.parallel_threads = 1;
+ FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Parallel threads can't be set with pbkdf2 type");
+ pbkdf2.parallel_threads = 0;
+ pbkdf2.max_memory_kb = 512;
+ FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Memory can't be set with pbkdf2 type");
+ FAIL_(crypt_set_pbkdf_type(cd, &bad), "Unknown type member");
+ bad.type = CRYPT_KDF_PBKDF2;
+ bad.hash = NULL;
+ FAIL_(crypt_set_pbkdf_type(cd, &bad), "Hash member is empty");
+ bad.type = NULL;
+ bad.hash = default_luks1_hash;
+ FAIL_(crypt_set_pbkdf_type(cd, &bad), "Pbkdf type member is empty");
+ bad.hash = "hamster_hash";
+ FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Unknown hash member");
+ CRYPT_FREE(cd);
+ // test whether crypt_get_pbkdf_type() behaves accordingly after second crypt_load() call
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->type, default_luks2_pbkdf));
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->time_ms, default_luks2_iter_time);
+ EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory());
+ EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
+ crypt_set_iteration_time(cd, 1);
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ OK_(strcmp(pbkdf->type, default_luks2_pbkdf));
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->time_ms, 1);
+ EQ_(pbkdf->max_memory_kb, adjusted_pbkdf_memory());
+ EQ_(pbkdf->parallel_threads, _min(cpus_online(), default_luks2_parallel_threads));
+ CRYPT_FREE(cd);
+
+ // test crypt_set_pbkdf_type() overwrites invalid value set by crypt_set_iteration_time()
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ crypt_set_iteration_time(cd, 0);
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ OK_(strcmp(pbkdf->type, argon2.type));
+ EQ_(pbkdf->time_ms, argon2.time_ms);
+
+ // force iterations
+ argon2.iterations = 33;
+ argon2.flags = CRYPT_PBKDF_NO_BENCHMARK;
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ NOTNULL_(pbkdf = crypt_get_pbkdf_type(cd));
+ EQ_(pbkdf->iterations, 33);
+ EQ_(pbkdf->flags, CRYPT_PBKDF_NO_BENCHMARK);
+
+ // time may be unset with iterations
+ argon2.time_ms = 0;
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ argon2.flags &= ~CRYPT_PBKDF_NO_BENCHMARK;
+ FAIL_(crypt_set_pbkdf_type(cd, &argon2), "Illegal time value.");
+
+ pbkdf2.time_ms = 0;
+ pbkdf2.flags = CRYPT_PBKDF_NO_BENCHMARK;
+ pbkdf2.parallel_threads = 0;
+ pbkdf2.max_memory_kb = 0;
+ pbkdf2.iterations = 1000;
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ pbkdf2.flags &= ~CRYPT_PBKDF_NO_BENCHMARK;
+ FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Illegal time value.");
+
+ // hash is relevant only with pbkdf2
+ pbkdf2.time_ms = 9;
+ pbkdf2.hash = NULL;
+ FAIL_(crypt_set_pbkdf_type(cd, &pbkdf2), "Hash is mandatory for pbkdf2");
+ pbkdf2.hash = "sha256";
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+
+ argon2.time_ms = 9;
+ argon2.hash = "sha256"; // will be ignored
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ argon2.hash = NULL;
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+
+ CRYPT_FREE(cd);
+
+ NOTNULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_LUKS1));
+ OK_(strcmp(pbkdf->type, CRYPT_KDF_PBKDF2));
+ EQ_(pbkdf->time_ms, default_luks1_iter_time);
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->max_memory_kb, 0);
+ EQ_(pbkdf->parallel_threads, 0);
+
+ NOTNULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_LUKS2));
+ OK_(strcmp(pbkdf->type, default_luks2_pbkdf));
+ EQ_(pbkdf->time_ms, default_luks2_iter_time);
+ OK_(strcmp(pbkdf->hash, default_luks1_hash));
+ EQ_(pbkdf->max_memory_kb, default_luks2_memory_kb);
+ EQ_(pbkdf->parallel_threads, default_luks2_parallel_threads);
+
+ NULL_(pbkdf = crypt_get_pbkdf_default(CRYPT_PLAIN));
+
+ _cleanup_dmdevices();
+}
+
+static void Luks2KeyslotAdd(void)
+{
+ char key[128], key2[128], key_ret[128];
+ const char *cipher = "aes", *cipher_mode="xts-plain64";
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_ret_len, key_size = strlen(vk_hex) / 2;
+ uint64_t r_payload_offset;
+ struct crypt_pbkdf_type pbkdf = {
+ .type = "argon2i",
+ .hash = "sha256",
+ .iterations = 4,
+ .max_memory_kb = 32,
+ .parallel_threads = 1,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK,
+ };
+ struct crypt_params_luks2 params2 = {
+ .pbkdf = &pbkdf,
+ .sector_size = TST_SECTOR_SIZE
+ };
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key2, vk_hex2, key_size);
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ pbkdf.iterations = 1000;
+ }
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ /* test crypt_keyslot_add_by_key */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params2));
+ EQ_(crypt_keyslot_add_by_key(cd, 1, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_ACTIVE_LAST);
+ EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_UNBOUND);
+ /* must not activate volume with keyslot unassigned to a segment */
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key2, key_size, 0), "Key doesn't match volume key digest");
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), "Keyslot not assigned to volume");
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), 0), "No keyslot assigned to volume with this passphrase");
+ /* unusable for volume activation even in test mode */
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, key2, key_size, 0), "Key doesn't match volume key digest");
+ /* otoh passphrase check should pass */
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 1);
+ EQ_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 1);
+ /* in general crypt_keyslot_add_by_key must allow any reasonable key size
+ * even though such keyslot will not be usable for segment encryption */
+ EQ_(crypt_keyslot_add_by_key(cd, 2, key2, key_size-1, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 2);
+ EQ_(crypt_keyslot_add_by_key(cd, 3, key2, 13, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 3);
+
+ FAIL_(crypt_keyslot_get_key_size(cd, CRYPT_ANY_SLOT), "Bad keyslot specification.");
+ EQ_(crypt_get_volume_key_size(cd), key_size);
+ EQ_(crypt_keyslot_get_key_size(cd, 0), key_size);
+ EQ_(crypt_keyslot_get_key_size(cd, 1), key_size);
+ EQ_(crypt_keyslot_get_key_size(cd, 2), key_size-1);
+ EQ_(crypt_keyslot_get_key_size(cd, 3), 13);
+
+ key_ret_len = key_size - 1;
+ FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key_ret, &key_ret_len, PASSPHRASE1, strlen(PASSPHRASE1)), "Wrong size");
+
+ key_ret_len = 13;
+ FAIL_(crypt_volume_key_get(cd, 2, key_ret, &key_ret_len, PASSPHRASE1, strlen(PASSPHRASE1)), "wrong size");
+ EQ_(crypt_volume_key_get(cd, 3, key_ret, &key_ret_len, PASSPHRASE1, strlen(PASSPHRASE1)), 3);
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, key_ret, key_ret_len, 0), "Not a volume key");
+ key_ret_len = key_size;
+ EQ_(crypt_volume_key_get(cd, 1, key_ret, &key_ret_len, PASSPHRASE1, strlen(PASSPHRASE1)), 1);
+
+ /* test force volume key change works as expected */
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 0, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_SET), 1);
+ OK_(crypt_activate_by_volume_key(cd, NULL, key2, key_size, 0));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key_ret, key_ret_len, 0));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key2, key_size, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_passphrase(cd, NULL, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ /* old keyslot must be unusable */
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Key doesn't match volume key digest");
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0), "Key doesn't match volume key digest");
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0), "Keyslot not assigned to volume");
+ EQ_(crypt_keyslot_add_by_passphrase(cd, 5, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE1, strlen(PASSPHRASE1)), 5);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1)), 6);
+ /* regression test. check new keyslot is properly assigned to new volume key digest */
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 5, PASSPHRASE1, strlen(PASSPHRASE1), 0), 5);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 6, PASSPHRASE1, strlen(PASSPHRASE1), 0), 6);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params2));
+ /* keyslot 0, volume key, digest 0 */
+ EQ_(crypt_keyslot_add_by_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ /* keyslot 1, unbound key, digest 1 */
+ EQ_(crypt_keyslot_add_by_key(cd, 1, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ /* keyslot 2, unbound key, digest 1 */
+ EQ_(crypt_keyslot_add_by_key(cd, 2, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_DIGEST_REUSE), 2);
+ /* keyslot 3, unbound key, digest 2 */
+ EQ_(crypt_keyslot_add_by_key(cd, 3, key2, key_size - 1, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_DIGEST_REUSE), 3);
+ /* keyslot 4, unbound key, digest 1 */
+ EQ_(crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_DIGEST_REUSE), 4);
+ FAIL_(crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_SET), "Illegal");
+ FAIL_(crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_SET | CRYPT_VOLUME_KEY_DIGEST_REUSE), "Illegal");
+ /* Such key doesn't exist, nothing to reuse */
+ FAIL_(crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key2, key_size - 2, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_DIGEST_REUSE), "Key digest doesn't match any existing.");
+ /* Keyslot 5, volume key, digest 0 */
+ EQ_(crypt_keyslot_add_by_key(cd, 5, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_DIGEST_REUSE), 5);
+
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_SET), 1);
+ OK_(crypt_activate_by_volume_key(cd, NULL, key2, key_size, 0));
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0), "Not a volume key");
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE1, strlen(PASSPHRASE1), 0), 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 2, PASSPHRASE1, strlen(PASSPHRASE1), 0), 2);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0), "No volume key keyslot");
+
+ /* TODO: key is unusable with aes-xts */
+ // FAIL_(crypt_keyslot_add_by_key(cd, 3, NULL, 0, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_SET), "Unusable key with segment cipher");
+
+ EQ_(crypt_keyslot_add_by_key(cd, 5, NULL, 0, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_SET), 5);
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, key2, key_size, 0), "Not a volume key");
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 5, PASSPHRASE1, strlen(PASSPHRASE1), 0), 5);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void Luks2KeyslotParams(void)
+{
+ char key[128], key2[128];
+ const char *cipher = "aes", *cipher_mode="xts-plain64";
+ const char *cipher_spec = "aes-xts-plain64", *cipher_keyslot = "aes-cbc-essiv:sha256";
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_size_ret, key_size = strlen(vk_hex) / 2, keyslot_key_size = 16;
+ uint64_t r_payload_offset;
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key2, vk_hex2, key_size);
+
+ OK_(prepare_keyfile(KEYFILE1, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(prepare_keyfile(KEYFILE2, PASSPHRASE1, strlen(PASSPHRASE1)));
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ EQ_(key_size, 2 * keyslot_key_size);
+ /* test crypt_keyslot_add_by_key */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, NULL));
+ NULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ // Normal slots
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
+ EQ_(1, crypt_keyslot_add_by_passphrase(cd, 1, PASSPHRASE, strlen(PASSPHRASE), PASSPHRASE1,strlen(PASSPHRASE1)));
+ EQ_(2, crypt_keyslot_add_by_key(cd, 2, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT));
+ EQ_(6, crypt_keyslot_add_by_keyfile(cd, 6, KEYFILE1, 0, KEYFILE2, 0));
+
+ // Slots with different encryption type
+ OK_(crypt_keyslot_set_encryption(cd, cipher_keyslot, keyslot_key_size));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ EQ_(3, crypt_keyslot_add_by_volume_key(cd, 3, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
+ EQ_(4, crypt_keyslot_add_by_passphrase(cd, 4, PASSPHRASE, strlen(PASSPHRASE), PASSPHRASE1,strlen(PASSPHRASE1)));
+ EQ_(5, crypt_keyslot_add_by_key(cd, 5, key2, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT));
+ EQ_(7, crypt_keyslot_add_by_keyfile(cd, 7, KEYFILE1, 0, KEYFILE2, 0));
+
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_ACTIVE);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 0, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_ACTIVE);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 1, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ EQ_(crypt_keyslot_status(cd, 2), CRYPT_SLOT_UNBOUND);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 2, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ EQ_(crypt_keyslot_status(cd, 6), CRYPT_SLOT_ACTIVE);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 6, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ EQ_(crypt_keyslot_status(cd, 3), CRYPT_SLOT_ACTIVE);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 3, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ EQ_(crypt_keyslot_status(cd, 4), CRYPT_SLOT_ACTIVE);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 4, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ EQ_(crypt_keyslot_status(cd, 5), CRYPT_SLOT_UNBOUND);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 5, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ EQ_(crypt_keyslot_status(cd, 7), CRYPT_SLOT_ACTIVE);
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 7, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ EQ_(8, crypt_keyslot_change_by_passphrase(cd, 1, 8, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 8, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ /* Revert to default */
+ EQ_(9, crypt_keyslot_change_by_passphrase(cd, 5, 9, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 9, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+
+ /* Set new encryption params */
+ OK_(crypt_keyslot_set_encryption(cd, cipher_keyslot, keyslot_key_size));
+
+ EQ_(1, crypt_keyslot_change_by_passphrase(cd, 8, 1, PASSPHRASE, strlen(PASSPHRASE), PASSPHRASE1, strlen(PASSPHRASE1)));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 1, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ EQ_(10, crypt_keyslot_change_by_passphrase(cd, 2, 10, PASSPHRASE1, strlen(PASSPHRASE1), PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 10, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ EQ_(0, crypt_keyslot_change_by_passphrase(cd, 0, 0, PASSPHRASE, strlen(PASSPHRASE), PASSPHRASE1, strlen(PASSPHRASE1)));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 0, &key_size_ret), cipher_keyslot));
+ EQ_(key_size_ret, keyslot_key_size);
+
+ CRYPT_FREE(cd);
+
+ /* LUKS1 compatible calls */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, NULL));
+ NULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, CRYPT_ANY_SLOT, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(strcmp(crypt_keyslot_get_encryption(cd, 0, &key_size_ret), cipher_spec));
+ EQ_(key_size_ret, key_size);
+ CRYPT_FREE(cd);
+
+ /* LUKS2 cipher null checks */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "cipher_null", "ecb", NULL, key, key_size, NULL));
+ FAIL_(crypt_keyslot_set_encryption(cd, "null", 32), "cipher null is not allowed");
+ FAIL_(crypt_keyslot_set_encryption(cd, "cipher_null", 32), "cipher null is not allowed");
+ FAIL_(crypt_keyslot_set_encryption(cd, "cipher_null-ecb", 32), "cipher null is not allowed");
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, PASSPHRASE, strlen(PASSPHRASE)));
+ NOTNULL_(crypt_keyslot_get_encryption(cd, 0, &key_size_ret));
+ NULL_(strstr(crypt_keyslot_get_encryption(cd, 0, &key_size_ret), "null"));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ _remove_keyfiles();
+}
+
+static void Luks2ActivateByKeyring(void)
+{
+#ifdef KERNEL_KEYRING
+
+ key_serial_t kid, kid1;
+ uint64_t r_payload_offset;
+
+ const char *cipher = "aes";
+ const char *cipher_mode = "xts-plain64";
+
+ if (!t_dm_crypt_keyring_support()) {
+ printf("WARNING: Kernel keyring not supported, skipping test.\n");
+ return;
+ }
+
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+ kid1 = add_key("user", KEY_DESC_TEST1, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid1, "Test or kernel keyring are broken.");
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ // prepare the device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, 32, NULL));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 2, NULL, 32, PASSPHRASE1, strlen(PASSPHRASE1)), 2);
+ CRYPT_FREE(cd);
+
+ // FIXME: all following tests work as expected but most error messages are missing
+ // check activate by keyring works exactly same as by passphrase
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, 0, 0), 0);
+ EQ_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST0, 0, 0), 0);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ FAIL_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST0, 0, 0), "already open");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ EQ_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 1, CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY), 1);
+ EQ_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 2, 0), 2);
+ FAIL_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST1, 1, 0), "Keyslot not assigned to volume");
+ EQ_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST1, 2, 0), 2);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST1, CRYPT_ANY_SLOT, 0), 2);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, 2, 0), "Failed to unclock keyslot");
+ FAIL_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 0, 0), "Failed to unclock keyslot");
+ CRYPT_FREE(cd);
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+ NOTFAIL_(keyctl_unlink(kid1, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ FAIL_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, CRYPT_ANY_SLOT, 0), "no such key in keyring");
+ FAIL_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST0, CRYPT_ANY_SLOT, 0), "no such key in keyring");
+ FAIL_(crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST1, 2, 0), "no such key in keyring");
+ FAIL_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST1, 1, 0), "no such key in keyring");
+ CRYPT_FREE(cd);
+ _cleanup_dmdevices();
+#else
+ printf("WARNING: cryptsetup compiled with kernel keyring service disabled, skipping test.\n");
+#endif
+}
+
+static void Luks2Requirements(void)
+{
+ int r;
+ char key[128];
+ size_t key_size = 128;
+ const struct crypt_pbkdf_type *pbkdf;
+#ifdef KERNEL_KEYRING
+ key_serial_t kid;
+#endif
+ uint32_t flags;
+ uint64_t dummy, r_payload_offset;
+ struct crypt_active_device cad;
+
+ const char *token, *json = "{\"type\":\"test_token\",\"keyslots\":[]}";
+ struct crypt_pbkdf_type argon2 = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = default_luks1_hash,
+ .time_ms = 6,
+ .max_memory_kb = 1024,
+ .parallel_threads = 1
+ }, pbkdf2 = {
+ .type = CRYPT_KDF_PBKDF2,
+ .hash = default_luks1_hash,
+ .time_ms = 9
+ };
+ struct crypt_token_params_luks2_keyring params_get, params = {
+ .key_description = KEY_DESC_TEST0
+ };
+
+ OK_(prepare_keyfile(KEYFILE1, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(prepare_keyfile(KEYFILE2, PASSPHRASE1, strlen(PASSPHRASE1)));
+
+ /* crypt_load (unrestricted) */
+ OK_(crypt_init(&cd, DEVICE_5));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_5));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+
+ /* crypt_dump (unrestricted) */
+ reset_log();
+ OK_(crypt_dump(cd));
+ OK_(!(global_lines != 0));
+ reset_log();
+
+ /* get & set pbkdf params (unrestricted) */
+ if (!_fips_mode) {
+ OK_(crypt_set_pbkdf_type(cd, &argon2));
+ NOTNULL_(crypt_get_pbkdf_type(cd));
+ }
+
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf2));
+ NOTNULL_(crypt_get_pbkdf_type(cd));
+
+ /* crypt_set_iteration_time (unrestricted) */
+ crypt_set_iteration_time(cd, 1);
+ pbkdf = crypt_get_pbkdf_type(cd);
+ NOTNULL_(pbkdf);
+ EQ_(pbkdf->time_ms, 1);
+
+ /* crypt_convert (restricted) */
+ FAIL_((r = crypt_convert(cd, CRYPT_LUKS1, NULL)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_set_uuid (restricted) */
+ FAIL_((r = crypt_set_uuid(cd, NULL)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_set_label (restricted) */
+ FAIL_((r = crypt_set_label(cd, "label", "subsystem")), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_get_label (unrestricted) */
+ NOTNULL_(crypt_get_label(cd));
+ OK_(strcmp("", crypt_get_label(cd)));
+ /* crypt_get_subsystem (unrestricted) */
+ NOTNULL_(crypt_get_subsystem(cd));
+ OK_(strcmp("", crypt_get_subsystem(cd)));
+
+ /* crypt_repair (with current repair capabilities it's unrestricted) */
+ OK_(crypt_repair(cd, CRYPT_LUKS2, NULL));
+
+ /* crypt_keyslot_add_passphrase (restricted) */
+ FAIL_((r = crypt_keyslot_add_by_passphrase(cd, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), "bbb", 3)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_keyslot_change_by_passphrase (restricted) */
+ FAIL_((r = crypt_keyslot_change_by_passphrase(cd, CRYPT_ANY_SLOT, 9, PASSPHRASE, strlen(PASSPHRASE), "bbb", 3)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_keyslot_add_by_keyfile (restricted) */
+ FAIL_((r = crypt_keyslot_add_by_keyfile(cd, CRYPT_ANY_SLOT, KEYFILE1, 0, KEYFILE2, 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_keyslot_add_by_keyfile_offset (restricted) */
+ FAIL_((r = crypt_keyslot_add_by_keyfile_offset(cd, CRYPT_ANY_SLOT, KEYFILE1, 0, 0, KEYFILE2, 0, 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_volume_key_get (unrestricted, but see below) */
+ OK_(crypt_volume_key_get(cd, 0, key, &key_size, PASSPHRASE, strlen(PASSPHRASE)));
+
+ /* crypt_keyslot_add_by_volume_key (restricted) */
+ FAIL_((r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1))), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_keyslot_add_by_key (restricted) */
+ FAIL_((r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, NULL, key_size, PASSPHRASE1, strlen(PASSPHRASE1), CRYPT_VOLUME_KEY_NO_SEGMENT)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_keyslot_add_by_key (restricted) */
+ FAIL_((r = crypt_keyslot_add_by_key(cd, CRYPT_ANY_SLOT, key, key_size, PASSPHRASE1, strlen(PASSPHRASE1), 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_persistent_flasgs_set (restricted) */
+ FAIL_((r = crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, CRYPT_ACTIVATE_ALLOW_DISCARDS)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_persistent_flasgs_get (unrestricted) */
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &flags));
+ EQ_(flags, CRYPT_REQUIREMENT_UNKNOWN);
+
+ /* crypt_activate_by_passphrase (restricted for activation only) */
+ FAIL_((r = crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ OK_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), 0));
+ OK_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+
+ /* crypt_activate_by_keyfile (restricted for activation only) */
+ FAIL_((r = crypt_activate_by_keyfile(cd, CDEVICE_1, 0, KEYFILE1, 0, 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ OK_(crypt_activate_by_keyfile(cd, NULL, 0, KEYFILE1, 0, 0));
+ OK_(crypt_activate_by_keyfile(cd, NULL, 0, KEYFILE1, 0, t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+
+ /* crypt_activate_by_volume_key (restricted for activation only) */
+ FAIL_((r = crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+
+#ifdef KERNEL_KEYRING
+ if (t_dm_crypt_keyring_support()) {
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
+ /* crypt_activate_by_keyring (restricted for activation only) */
+ FAIL_((r = crypt_activate_by_keyring(cd, CDEVICE_1, KEY_DESC_TEST0, 0, 0)), "Unmet requirements detected");
+ EQ_(r, t_dm_crypt_keyring_support() ? -ETXTBSY : -EINVAL);
+ OK_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, 0, 0));
+ OK_(crypt_activate_by_keyring(cd, NULL, KEY_DESC_TEST0, 0, CRYPT_ACTIVATE_KEYRING_KEY));
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+ }
+#endif
+
+ /* crypt_volume_key_verify (unrestricted) */
+ OK_(crypt_volume_key_verify(cd, key, key_size));
+
+ /* crypt_get_cipher (unrestricted) */
+ OK_(strcmp(crypt_get_cipher(cd)?:"", "aes"));
+
+ /* crypt_get_cipher_mode (unrestricted) */
+ OK_(strcmp(crypt_get_cipher_mode(cd)?:"", "xts-plain64"));
+
+ /* crypt_get_uuid (unrestricted) */
+ NOTNULL_(crypt_get_uuid(cd));
+
+ /* crypt_get_device_name (unrestricted) */
+ NOTNULL_(crypt_get_device_name(cd));
+
+ /* crypt_get_data_offset (unrestricted) */
+ OK_(!crypt_get_data_offset(cd));
+
+ /* crypt_get_iv_offset (unrestricted, nothing to test) */
+
+ /* crypt_get_volume_key_size (unrestricted) */
+ EQ_(crypt_get_volume_key_size(cd), key_size);
+
+ /* crypt_keyslot_status (unrestricted) */
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_ACTIVE_LAST);
+ EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_INACTIVE);
+
+ /* crypt_keyslot_get_priority (unrestricted) */
+ EQ_(crypt_keyslot_get_priority(cd, 0), CRYPT_SLOT_PRIORITY_NORMAL);
+
+ /* crypt_keyslot_set_priority (restricted) */
+ FAIL_((r = crypt_keyslot_set_priority(cd, 0, CRYPT_SLOT_PRIORITY_PREFER)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_keyslot_area (unrestricted) */
+ OK_(crypt_keyslot_area(cd, 0, &dummy, &dummy));
+ OK_(!dummy);
+
+ /* crypt_header_backup (unrestricted) */
+ remove(BACKUP_FILE);
+ OK_(crypt_header_backup(cd, CRYPT_LUKS, BACKUP_FILE));
+
+ /* crypt_header_restore (restricted, do not drop the test until we have safe option) */
+ FAIL_((r = crypt_header_restore(cd, CRYPT_LUKS2, BACKUP_FILE)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ remove(BACKUP_FILE);
+
+ /* crypt_token_json_set (restricted) */
+ FAIL_((r = crypt_token_json_set(cd, CRYPT_ANY_TOKEN, json)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_token_json_get (unrestricted) */
+ OK_(crypt_token_json_get(cd, 0, &token));
+ NOTNULL_(strstr(token, "user_type"));
+
+ /* crypt_token_status (unrestricted) */
+ EQ_(crypt_token_status(cd, 0, &token), CRYPT_TOKEN_EXTERNAL_UNKNOWN);
+ OK_(strcmp(token, "user_type"));
+ EQ_(crypt_token_status(cd, 1, &token), CRYPT_TOKEN_INTERNAL);
+ OK_(strcmp(token, "luks2-keyring"));
+ EQ_(crypt_token_status(cd, 2, NULL), CRYPT_TOKEN_INACTIVE);
+ EQ_(crypt_token_status(cd, 6, &token), CRYPT_TOKEN_INTERNAL_UNKNOWN);
+
+ /* crypt_token_luks2_keyring_set (restricted) */
+ FAIL_((r = crypt_token_luks2_keyring_set(cd, CRYPT_ANY_TOKEN, &params)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_token_luks2_keyring_get (unrestricted) */
+ EQ_(crypt_token_luks2_keyring_get(cd, 1, &params_get), 1);
+ OK_(strcmp(params_get.key_description, KEY_DESC_TEST0));
+
+ /* crypt_token_assign_keyslot (unrestricted) */
+ FAIL_((r = crypt_token_assign_keyslot(cd, 0, 1)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_token_unassign_keyslot (unrestricted) */
+ FAIL_((r = crypt_token_unassign_keyslot(cd, CRYPT_ANY_TOKEN, CRYPT_ANY_SLOT)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_activate_by_token (restricted for activation only) */
+#ifdef KERNEL_KEYRING
+ if (t_dm_crypt_keyring_support()) {
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+
+ FAIL_((r = crypt_activate_by_token(cd, CDEVICE_1, 1, NULL, 0)), ""); // supposed to be silent
+ EQ_(r, -ETXTBSY);
+ OK_(crypt_activate_by_token(cd, NULL, 1, NULL, 0));
+ OK_(crypt_activate_by_token(cd, NULL, 1, NULL, CRYPT_ACTIVATE_KEYRING_KEY));
+
+ NOTFAIL_(keyctl_unlink(kid, KEY_SPEC_THREAD_KEYRING), "Test or kernel keyring are broken.");
+ }
+#endif
+ OK_(get_luks2_offsets(0, 8192, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 2));
+ //OK_(_system("dd if=" NO_REQS_LUKS2_HEADER " of=" NO_REQS_LUKS2_HEADER " bs=4096 2>/dev/null", 1));
+ OK_(_system("dd if=" NO_REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+
+ /* need to fake activated LUKSv2 device with requirements features */
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0));
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+ /* replace header with no requirements */
+ OK_(_system("dd if=" REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_5));
+ CRYPT_FREE(cd);
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+
+ /* crypt_header_restore (restricted with confirmation required) */
+ /* allow force restore over device header w/ requirements */
+ OK_(crypt_header_restore(cd, CRYPT_LUKS2, BACKUP_FILE));
+ remove(BACKUP_FILE);
+ OK_(_system("dd if=" REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE)); /* create backup with requirements */
+
+ /* crypt_suspend (restricted) */
+ FAIL_((r = crypt_suspend(cd, CDEVICE_1)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ CRYPT_FREE(cd);
+
+ /* replace header again to suspend the device */
+ OK_(_system("dd if=" NO_REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+
+ /* crypt_header_restore (restricted, do not drop the test until we have safe option) */
+ /* refuse to overwrite header w/ backup including requirements */
+ FAIL_((r = crypt_header_restore(cd, CRYPT_LUKS2, BACKUP_FILE)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ CRYPT_FREE(cd);
+
+ OK_(_system("dd if=" REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+
+ /* crypt_resume_by_passphrase (restricted) */
+ FAIL_((r = crypt_resume_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE))), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_resume_by_keyfile (restricted) */
+ FAIL_((r = crypt_resume_by_keyfile(cd, CDEVICE_1, 0, KEYFILE1, 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+
+ /* crypt_resume_by_keyfile_offset (restricted) */
+ FAIL_((r = crypt_resume_by_keyfile_offset(cd, CDEVICE_1, 0, KEYFILE1, 0, 0)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ CRYPT_FREE(cd);
+
+ OK_(_system("dd if=" NO_REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE)));
+ CRYPT_FREE(cd);
+ OK_(_system("dd if=" REQS_LUKS2_HEADER " of=" DMDIR L_DEVICE_OK " bs=1M count=4 oflag=direct 2>/dev/null", 1));
+
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ /* load VK in keyring */
+ OK_(crypt_activate_by_passphrase(cd, NULL, 0, PASSPHRASE, strlen(PASSPHRASE), t_dm_crypt_keyring_support() ? CRYPT_ACTIVATE_KEYRING_KEY : 0));
+ /* crypt_resize (restricted) */
+ FAIL_((r = crypt_resize(cd, CDEVICE_1, 1)), "Unmet requirements detected");
+ EQ_(r, -ETXTBSY);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+
+ /* crypt_get_active_device (unrestricted) */
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+#ifdef KERNEL_KEYRING
+ if (t_dm_crypt_keyring_support())
+ EQ_(cad.flags & CRYPT_ACTIVATE_KEYRING_KEY, CRYPT_ACTIVATE_KEYRING_KEY);
+#endif
+
+ /* crypt_deactivate (unrestricted) */
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ /* crypt_token_is_assigned (unrestricted) */
+ OK_(crypt_token_is_assigned(cd, 1, 0));
+ OK_(crypt_token_is_assigned(cd, 6, 0));
+ EQ_(crypt_token_is_assigned(cd, 0, 0), -ENOENT);
+
+ /* crypt_keyslot_destroy (unrestricted) */
+ OK_(crypt_keyslot_destroy(cd, 0));
+
+ CRYPT_FREE(cd);
+ _cleanup_dmdevices();
+}
+
+static void Luks2Integrity(void)
+{
+ struct crypt_params_integrity ip = {};
+ struct crypt_params_luks2 params = {
+ .sector_size = 512,
+ .integrity = "hmac(sha256)"
+ };
+ size_t key_size = 32 + 32;
+ const char *cipher = "aes";
+ const char *cipher_mode = "xts-random";
+ int ret;
+
+ // FIXME: This is just a stub
+ OK_(crypt_init(&cd, DEVICE_2));
+ ret = crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, key_size, &params);
+ if (ret < 0) {
+ printf("WARNING: cannot format integrity device, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, NULL, key_size, PASSPHRASE, strlen(PASSPHRASE)), 7);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 7, PASSPHRASE, strlen(PASSPHRASE) ,0), 7);
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_2, NULL));
+ OK_(crypt_get_integrity_info(cd, &ip));
+ OK_(strcmp(cipher, crypt_get_cipher(cd)));
+ OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
+ OK_(strcmp("hmac(sha256)", ip.integrity));
+ EQ_(32, ip.integrity_key_size);
+ EQ_(32+16, ip.tag_size);
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, key_size - 32, &params), "Wrong key size.");
+ FAIL_(crypt_format(cd, CRYPT_LUKS2, cipher, "xts-plainx", NULL, NULL, key_size, &params), "Wrong cipher.");
+ CRYPT_FREE(cd);
+}
+
+static int check_flag(uint32_t flags, uint32_t flag)
+{
+ return (flags & flag) ? 0 : -1;
+}
+
+static void Luks2Refresh(void)
+{
+ uint64_t r_payload_offset;
+ char key[128], key1[128];
+ const char *cipher = "aes", *mode = "xts-plain64";
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c645be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb22158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_size = strlen(vk_hex) / 2;
+ struct crypt_params_luks2 params = {
+ .sector_size = 512,
+ .integrity = "aead"
+ };
+ struct crypt_active_device cad = {};
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key1, vk_hex2, key_size);
+
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
+ OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset + 5000));
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset));
+
+ /* prepare test device */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, mode, NULL, key, 32, NULL));
+ OK_(crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, key, 32, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0));
+
+ /* check we can refresh significant flags */
+ if (t_dm_crypt_discard_support()) {
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_ALLOW_DISCARDS));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_ALLOW_DISCARDS));
+ cad.flags = 0;
+ }
+
+ if (t_dm_crypt_cpu_switch_support()) {
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SAME_CPU_CRYPT));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SAME_CPU_CRYPT));
+ cad.flags = 0;
+
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+ cad.flags = 0;
+
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+ cad.flags = 0;
+ }
+
+ OK_(crypt_volume_key_keyring(cd, 0));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_KEYRING_KEY), "Unexpected flag raised.");
+ cad.flags = 0;
+
+#ifdef KERNEL_KEYRING
+ if (t_dm_crypt_keyring_support()) {
+ OK_(crypt_volume_key_keyring(cd, 1));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_KEYRING_KEY));
+ cad.flags = 0;
+ }
+#endif
+
+ /* multiple flags at once */
+ if (t_dm_crypt_discard_support() && t_dm_crypt_cpu_switch_support()) {
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS | CRYPT_ACTIVATE_ALLOW_DISCARDS));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS | CRYPT_ACTIVATE_ALLOW_DISCARDS));
+ cad.flags = 0;
+ }
+
+ /* do not allow reactivation with read-only (and drop flag silently because activation behaves exactly same) */
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_READONLY));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_READONLY), "Reactivated with read-only flag.");
+ cad.flags = 0;
+
+ /* reload flag is dropped silently */
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
+
+ /* check read-only flag is not lost after reload */
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_READONLY));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_READONLY));
+ cad.flags = 0;
+
+ /* check LUKS2 with auth. enc. reload */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ if (!crypt_format(cd2, CRYPT_LUKS2, "aes", "gcm-random", crypt_get_uuid(cd), key, 32, &params)) {
+ OK_(crypt_keyslot_add_by_volume_key(cd2, 0, key, 32, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, 32, 0));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, 32, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_NO_JOURNAL));
+ OK_(crypt_get_active_device(cd2, CDEVICE_2, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_NO_JOURNAL));
+ cad.flags = 0;
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, 32, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_NO_JOURNAL | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+ OK_(crypt_get_active_device(cd2, CDEVICE_2, &cad));
+ OK_(check_flag(cad.flags, CRYPT_ACTIVATE_NO_JOURNAL | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS));
+ cad.flags = 0;
+ OK_(crypt_activate_by_passphrase(cd2, CDEVICE_2, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH));
+ OK_(crypt_get_active_device(cd2, CDEVICE_2, &cad));
+ FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_NO_JOURNAL), "");
+ FAIL_(check_flag(cad.flags, CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS), "");
+ FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with LUKS2/aead context");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ } else {
+ printf("WARNING: cannot format integrity device, skipping few reload tests.\n");
+ }
+ CRYPT_FREE(cd2);
+
+ /* Use LUKS1 context on LUKS2 device */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_1S));
+ OK_(crypt_format(cd2, CRYPT_LUKS1, cipher, mode, crypt_get_uuid(cd), key, 32, NULL));
+ OK_(crypt_keyslot_add_by_volume_key(cd2, CRYPT_ANY_SLOT, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)));
+ FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with LUKS1 context");
+ CRYPT_FREE(cd2);
+
+ /* Use PLAIN context on LUKS2 device */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_1S));
+ OK_(crypt_format(cd2, CRYPT_PLAIN, cipher, mode, NULL, key, 32, NULL));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
+ FAIL_(crypt_activate_by_volume_key(cd2, CDEVICE_1, key, key_size, CRYPT_ACTIVATE_REFRESH), "Refreshed LUKS2 device with PLAIN context");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+
+ /* (snapshot-like case) */
+ /* try to refresh almost identical device (differs only in major:minor of data device) */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ OK_(set_fast_pbkdf(cd2));
+ OK_(crypt_format(cd2, CRYPT_LUKS2, cipher, mode, crypt_get_uuid(cd), key, 32, NULL));
+ OK_(crypt_keyslot_add_by_volume_key(cd2, CRYPT_ANY_SLOT, key, 32, PASSPHRASE, strlen(PASSPHRASE)));
+ FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_REFRESH), "Refreshed dm-crypt mapped over mismatching data device");
+
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ CRYPT_FREE(cd);
+ CRYPT_FREE(cd2);
+
+ _cleanup_dmdevices();
+}
+
+static void Luks2Flags(void)
+{
+ uint32_t flags = 42;
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+
+ /* check library erase passed variable on success when no flags set */
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_ACTIVATION, &flags));
+ EQ_(flags, 0);
+
+ /* check set and get behave as expected */
+ flags = CRYPT_ACTIVATE_ALLOW_DISCARDS;
+ OK_(crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, flags));
+ flags = 0;
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_ACTIVATION, &flags));
+ EQ_(flags, CRYPT_ACTIVATE_ALLOW_DISCARDS);
+
+ flags = CRYPT_ACTIVATE_ALLOW_DISCARDS | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
+ OK_(crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, flags));
+ flags = ~UINT32_C(0);
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_ACTIVATION, &flags));
+ EQ_(flags,CRYPT_ACTIVATE_ALLOW_DISCARDS | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS);
+
+ /* label and subsystem (second label */
+ OK_(crypt_set_label(cd, "label", "subsystem"));
+ OK_(strcmp("label", crypt_get_label(cd)));
+ OK_(strcmp("subsystem", crypt_get_subsystem(cd)));
+
+ OK_(crypt_set_label(cd, NULL, NULL));
+ OK_(strcmp("", crypt_get_label(cd)));
+ OK_(strcmp("", crypt_get_subsystem(cd)));
+
+ CRYPT_FREE(cd);
+}
+
+#if KERNEL_KEYRING && USE_LUKS2_REENCRYPTION
+static int test_progress(uint64_t size __attribute__((unused)),
+ uint64_t offset __attribute__((unused)),
+ void *usrptr __attribute__((unused)))
+{
+ while (--test_progress_steps)
+ return 0;
+ return 1;
+}
+
+static void Luks2Reencryption(void)
+{
+/* reencryption currently depends on kernel keyring support */
+ /* NOTES:
+ * - reencryption requires luks2 parameters. can we avoid it?
+ */
+ uint32_t getflags;
+ uint64_t r_header_size, r_size_1;
+ struct crypt_active_device cad;
+ struct crypt_pbkdf_type pbkdf = {
+ .type = CRYPT_KDF_ARGON2I,
+ .hash = "sha256",
+ .parallel_threads = 1,
+ .max_memory_kb = 128,
+ .iterations = 4,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+ };
+ struct crypt_params_luks2 params2 = {
+ .pbkdf = &pbkdf,
+ .sector_size = 4096
+ };
+ struct crypt_params_reencrypt retparams = {}, rparams = {
+ .direction = CRYPT_REENCRYPT_FORWARD,
+ .resilience = "checksum",
+ .hash = "sha256",
+ .luks2 = &params2,
+ };
+ dev_t devno;
+
+ const char *vk_hex = "bb21babe733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ char key[128];
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ /* reencryption currently depends on kernel keyring support in dm-crypt */
+ if (!t_dm_crypt_keyring_support())
+ return;
+
+ /* Cannot use Argon2 in FIPS */
+ if (_fips_mode) {
+ pbkdf.type = CRYPT_KDF_PBKDF2;
+ pbkdf.parallel_threads = 0;
+ pbkdf.max_memory_kb = 0;
+ pbkdf.iterations = 1000;
+ }
+
+ OK_(get_luks2_offsets(1, 0, 0, &r_header_size, NULL));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 16));
+
+ /* create device */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 21);
+
+ /* add several unbound keys */
+ EQ_(crypt_keyslot_add_by_key(cd, 9, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 9);
+ EQ_(crypt_keyslot_add_by_key(cd, 10, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 10);
+ EQ_(crypt_keyslot_add_by_key(cd, 11, NULL, 42, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 11);
+ EQ_(crypt_keyslot_status(cd, 21), CRYPT_SLOT_ACTIVE_LAST);
+
+ /* test cipher parameters validation */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 11, "aes", "xts-plain64", &rparams), "Cipher not compatible with new volume key size.");
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 10, "tHeHamstErciphErr", "xts-plain64", &rparams), "Wrong cipher.");
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 10, "aes", "HamSterMoOode-plain64", &rparams), "Wrong mode.");
+
+ /* test reencryption flags */
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Reencryption not initialized.");
+ rparams.flags |= CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Invalid flags combination.");
+
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0);
+ FAIL_(crypt_reencrypt_run(cd, NULL, NULL), "Reencryption context not initialized.");
+
+ rparams.flags &= ~CRYPT_REENCRYPT_RESUME_ONLY;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
+
+ /* check reencrypt status is correct */
+ EQ_(crypt_reencrypt_status(cd, &retparams), CRYPT_REENCRYPT_CLEAN);
+ EQ_(retparams.mode, CRYPT_REENCRYPT_REENCRYPT);
+ EQ_(retparams.direction, CRYPT_REENCRYPT_FORWARD);
+ EQ_(retparams.data_shift, 0);
+ EQ_(retparams.device_size, 0);
+
+ /* check reencryption flag in metadata */
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
+
+ /* some parameters are expected to change immediately after reencryption initialization */
+ EQ_(crypt_get_volume_key_size(cd), 64);
+ OK_(strcmp(crypt_get_cipher_mode(cd), "xts-plain64"));
+ EQ_(crypt_get_sector_size(cd), 4096);
+ /* reencrypt keyslot must be unbound */
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_UNBOUND);
+ /* keyslot assigned to new segment is switched to last active */
+ EQ_(crypt_keyslot_status(cd, 9), CRYPT_SLOT_ACTIVE_LAST);
+ /* keyslot assigned to old segment remains active */
+ EQ_(crypt_keyslot_status(cd, 21), CRYPT_SLOT_ACTIVE);
+
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 10, "aes", "xts-plain", &rparams), "Reencryption already initialized.");
+
+ rparams.flags = 0;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+
+ /* check keyslots are reassigned to segment after reencryption */
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_INACTIVE);
+ EQ_(crypt_keyslot_status(cd, 9), CRYPT_SLOT_ACTIVE_LAST);
+ EQ_(crypt_keyslot_status(cd, 10), CRYPT_SLOT_UNBOUND);
+ EQ_(crypt_keyslot_status(cd, 11), CRYPT_SLOT_UNBOUND);
+ EQ_(crypt_keyslot_status(cd, 21), CRYPT_SLOT_INACTIVE);
+
+ EQ_(crypt_keyslot_add_by_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 21);
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ params2.sector_size = 512;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams));
+
+ /* fixed device size parameter impact */
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ rparams.device_size = 24;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams), "Invalid device size.");
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
+ rparams.device_size = 15;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams), "Invalid device size alignment.");
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
+ FAIL_(crypt_reencrypt_run(cd, NULL, NULL), "Reencryption context not initialized.");
+ rparams.device_size = 16;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 0);
+
+ /* limited hotzone size parameter impact */
+ EQ_(crypt_keyslot_add_by_key(cd, 9, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 9);
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ rparams.device_size = 0;
+ params2.sector_size = 4096;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
+
+ /* max hotzone size parameter impact */
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ rparams.max_hotzone_size = 1;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Invalid hotzone size alignment.");
+ rparams.max_hotzone_size = 24; /* should be ok. Device size is 16 sectors and the parameter defines upper limit, not lower */
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
+ rparams.max_hotzone_size = 8;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+
+ rparams.max_hotzone_size = 0;
+ rparams.resilience = "haMster";
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Invalid resilience mode.");
+ rparams.resilience = "checksum";
+ rparams.hash = "hamSter";
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Invalid resilience hash.");
+
+ rparams.hash = "sha256";
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+
+ /* FIXME: this is a bug, but not critical (data shift parameter is ignored after initialization) */
+ //rparams.data_shift = 8;
+ //FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Invalid reencryption parameters.");
+
+ EQ_(crypt_keyslot_add_by_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 21);
+ rparams.flags = 0;
+ rparams.resilience = "none";
+ rparams.max_hotzone_size = 2048;
+ /* online reencryption on inactive device */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams), "Device is not active.");
+ /* FIXME: this is minor bug. In fact we need only key from keyslot 9 */
+ //EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 9, PASSPHRASE, strlen(PASSPHRASE), 0), 9);
+ NOTFAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Failed to activate device.");
+ /* offline reencryption on active device */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams), "Device mounted or active.");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ /* Wrong context checks */
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 9, 21, "aes", "xts-plain64", &rparams));
+ /* cd is ready for reencryption */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd2, CRYPT_LUKS2, NULL));
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd2, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Reencryption already running.");
+ rparams.flags = 0;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd2, NULL, PASSPHRASE, strlen(PASSPHRASE), 21, 9, "aes", "xts-plain64", &rparams), "Reencryption already running.");
+ FAIL_(crypt_reencrypt_run(cd2, NULL, NULL), "Invalid reencryption context.");
+ OK_(crypt_persistent_flags_get(cd, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
+ OK_(crypt_persistent_flags_get(cd2, CRYPT_FLAGS_REQUIREMENTS, &getflags));
+ EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_CLEAN);
+ EQ_(crypt_reencrypt_status(cd2, NULL), CRYPT_REENCRYPT_CLEAN);
+ FAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Reencryption already in progress.");
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Reencryption already in progress.");
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+ CRYPT_FREE(cd2);
+
+ /* Partial device reencryption parameter */
+ params2.sector_size = 512;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+
+ rparams.device_size = 2;
+ rparams.max_hotzone_size = 1;
+ rparams.resilience = "none";
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+
+ /* interrupt reencryption after 'test_progress_steps' */
+ test_progress_steps = 2;
+ OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_CLEAN);
+
+ NOTFAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Could not activate device in reencryption.");
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.size, 2);
+ EQ_(cad.offset, r_header_size);
+ /* TODO: this should work in future releases unless reencryption process is running */
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1), "Device in reencryption.");
+ FAIL_(crypt_resize(cd, CDEVICE_1, 0), "Device in reencryption.");
+
+ rparams.max_hotzone_size = 0;
+ rparams.device_size = 3;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Invalid device size.");
+ crypt_deactivate(cd, CDEVICE_1);
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Invalid device size.");
+ rparams.device_size = 2;
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ NOTFAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Failed to initialize reencryption.");
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE, strlen(PASSPHRASE), 0), 1);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ /* after reencryption use whole device again */
+ EQ_(cad.size, 16);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ /* Reencrypt device with wrong size */
+ EQ_(crypt_keyslot_add_by_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 0);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE, strlen(PASSPHRASE), 0), 1);
+ OK_(crypt_resize(cd, CDEVICE_1, 7));
+ rparams.device_size = 0;
+ rparams.flags = 0;
+ params2.sector_size = 4096;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), "Active device size is not aligned to new sector size.");
+ rparams.device_size = 8;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), "Reduced reencryption size does not match active device.");
+ /* FIXME: allow after resize in reencryption is supported */
+ //NOTFAIL_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY | CRYPT_ACTIVATE_KEYRING_KEY), "Failed to load keys.");
+ // OK_(crypt_resize(cd, CDEVICE_1, 8));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params2.sector_size = 512;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_init(&cd2, DMDIR H_DEVICE));
+ OK_(crypt_set_data_offset(cd2, r_header_size - 8));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ OK_(crypt_set_pbkdf_type(cd2, &pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_format(cd2, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_volume_key(cd2, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ EQ_(crypt_keyslot_add_by_key(cd2, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ EQ_(crypt_activate_by_passphrase(cd2, CDEVICE_2, 0, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+ EQ_(crypt_reencrypt_init_by_passphrase(cd2, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ /* reference wrong device in active device name */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Wrong device.");
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd2, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Wrong device.");
+ EQ_(crypt_reencrypt_init_by_passphrase(cd2, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+ FAIL_(crypt_set_data_device(cd2, DMDIR L_DEVICE_OK), "Device in reencryption.");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd);
+ CRYPT_FREE(cd2);
+
+ /* data shift related tests */
+ params2.sector_size = 512;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.direction = CRYPT_REENCRYPT_BACKWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = 8;
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ rparams.luks2 = &params2;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+ EQ_(crypt_reencrypt_status(cd, &retparams), CRYPT_REENCRYPT_CLEAN);
+ EQ_(retparams.data_shift, 8);
+ EQ_(retparams.mode, CRYPT_REENCRYPT_REENCRYPT);
+ OK_(strcmp(retparams.resilience, "datashift"));
+ EQ_(crypt_get_data_offset(cd), 32776);
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 1, PASSPHRASE, strlen(PASSPHRASE), 0), 1);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.size, 8);
+ EQ_(crypt_get_data_offset(cd), 32776);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ rparams.flags = 0;
+ EQ_(crypt_keyslot_add_by_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 0);
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), "Device is too small.");
+ CRYPT_FREE(cd);
+ // BUG: We need reencrypt abort flag
+ /* it fails, but it's already initialized and we have no way to abort yet */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 1);
+ EQ_(crypt_keyslot_add_by_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 0);
+ rparams.direction = CRYPT_REENCRYPT_FORWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = 8;
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), 2);
+ EQ_(crypt_reencrypt_status(cd, &retparams), CRYPT_REENCRYPT_CLEAN);
+ EQ_(retparams.data_shift, 8);
+ EQ_(retparams.mode, CRYPT_REENCRYPT_REENCRYPT);
+ OK_(strcmp(retparams.resilience, "datashift"));
+ EQ_(crypt_get_data_offset(cd), 32760);
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 0, "aes", "xts-plain64", &rparams), 2);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.size, 24);
+ EQ_(crypt_get_data_offset(cd), 32760);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ /* data shift with online device */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ rparams.direction = CRYPT_REENCRYPT_BACKWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = 8;
+ rparams.flags = 0;
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, PASSPHRASE, strlen(PASSPHRASE), 0), 0);
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), "Active device too large.");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ NOTFAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Failed to activate device in reencryption.");
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.size, 8);
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 0, 1, "aes", "xts-plain64", &rparams), 2);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+
+ /* encryption with datashift and moved segment (limit values for data shift) */
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 12*1024*2));
+
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+
+ memset(&rparams, 0, sizeof(rparams));
+ params2.sector_size = 512;
+ params2.data_device = DMDIR L_DEVICE_OK;
+ rparams.mode = CRYPT_REENCRYPT_ENCRYPT;
+ rparams.direction = CRYPT_REENCRYPT_BACKWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = 8192;
+ rparams.luks2 = &params2;
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT;
+ OK_(crypt_set_data_offset(cd, 8192));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 30, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 30);
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS2, DMDIR H_DEVICE));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_reencrypt_status(cd, &retparams), CRYPT_REENCRYPT_CLEAN);
+ EQ_(retparams.mode, CRYPT_REENCRYPT_ENCRYPT);
+ OK_(strcmp(retparams.resilience, "datashift"));
+ EQ_(retparams.data_shift, 8192);
+ EQ_(retparams.flags & CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT, CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT);
+ EQ_(crypt_get_data_offset(cd), 8192);
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, NULL, NULL, &rparams), 0);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 8*1024*2+1));
+
+ /* encryption with datashift and moved segment (data shift + 1 sector) */
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT;
+ OK_(crypt_set_data_offset(cd, 8192));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 30, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 30);
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams), 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS2, DMDIR H_DEVICE));
+ EQ_(crypt_get_data_offset(cd), 8192);
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ EQ_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, NULL, NULL, &rparams), 0);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 2*8200));
+
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+
+ /* encryption with datashift and moved segment (data shift + data offset <= device size) */
+ memset(&rparams, 0, sizeof(rparams));
+ params2.sector_size = 512;
+ params2.data_device = DMDIR L_DEVICE_OK;
+ rparams.mode = CRYPT_REENCRYPT_ENCRYPT;
+ rparams.direction = CRYPT_REENCRYPT_BACKWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = 8200;
+ rparams.luks2 = &params2;
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT;
+ OK_(crypt_set_data_offset(cd, 8200));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 30, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)), 30);
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ANY_SLOT, 30, "aes", "xts-plain64", &rparams), "Data device is too small");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 1));
+
+ /* decryption backward */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ params2.data_device = NULL;
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.mode = CRYPT_REENCRYPT_DECRYPT;
+ rparams.direction = CRYPT_REENCRYPT_BACKWARD;
+ rparams.resilience = "none";
+ rparams.max_hotzone_size = 2048;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), r_header_size);
+ EQ_(crypt_get_volume_key_size(cd), 0);
+ OK_(strcmp(crypt_get_cipher(cd), "cipher_null"));
+ CRYPT_FREE(cd);
+
+ /* decryption forward */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ params2.data_device = NULL;
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.mode = CRYPT_REENCRYPT_DECRYPT;
+ rparams.direction = CRYPT_REENCRYPT_FORWARD;
+ rparams.resilience = "none";
+ rparams.max_hotzone_size = 2048;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+
+ /* decryption forward (online) */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ params2.data_device = NULL;
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 6, PASSPHRASE, strlen(PASSPHRASE), 0), 6);
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.mode = CRYPT_REENCRYPT_DECRYPT;
+ rparams.direction = CRYPT_REENCRYPT_FORWARD;
+ rparams.resilience = "none";
+ rparams.max_hotzone_size = 2048;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ CRYPT_FREE(cd);
+
+ /* decryption with data shift */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ params2.data_device = NULL;
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ remove(BACKUP_FILE);
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+ CRYPT_FREE(cd);
+ // FIXME: we need write flock
+ OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
+ OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), r_header_size);
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.mode = CRYPT_REENCRYPT_DECRYPT;
+ rparams.direction = CRYPT_REENCRYPT_FORWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = r_header_size;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
+ EQ_(crypt_get_data_offset(cd), 0);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ remove(BACKUP_FILE);
+ CRYPT_FREE(cd);
+
+ /* online decryption with data shift (future feature) */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ params2.data_device = NULL;
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_2, 6, PASSPHRASE, strlen(PASSPHRASE), 0), 6);
+ OK_(t_device_size(DMDIR CDEVICE_2, &r_size_1));
+ EQ_(r_size_1, 512);
+ // store devno for later size check
+ OK_(t_get_devno(CDEVICE_2, &devno));
+ // create placeholder device to block automatic deactivation after decryption
+ OK_(_system("dmsetup create " CDEVICE_1 " --table \"0 1 linear " DMDIR CDEVICE_2 " 0\"", 1));
+ remove(BACKUP_FILE);
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+ CRYPT_FREE(cd);
+ // FIXME: we need write flock
+ OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
+ OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_get_data_offset(cd), r_header_size);
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.mode = CRYPT_REENCRYPT_DECRYPT;
+ rparams.direction = CRYPT_REENCRYPT_FORWARD;
+ rparams.resilience = "datashift";
+ rparams.data_shift = r_header_size;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
+ EQ_(crypt_get_data_offset(cd), 0);
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ remove(BACKUP_FILE);
+ OK_(t_device_size_by_devno(devno, &r_size_1));
+ EQ_(r_size_1, 512);
+ OK_(_system("dmsetup remove " DM_RETRY CDEVICE_1 DM_NOSTDERR, 0));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_header_size));
+
+ /* check detached header misuse (mismatching keys in table and mda) */
+ OK_(crypt_init(&cd, IMAGE_EMPTY_SMALL));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ params2.data_device = DMDIR L_DEVICE_WRONG;
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 6, PASSPHRASE, strlen(PASSPHRASE), 0), 6);
+ /* activate second device using same header */
+ OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd2, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_pbkdf_type(cd2, &pbkdf));
+ EQ_(crypt_activate_by_passphrase(cd2, CDEVICE_2, 6, PASSPHRASE, strlen(PASSPHRASE), 0), 6);
+ CRYPT_FREE(cd2);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+
+ memset(&rparams, 0, sizeof(rparams));
+ rparams.resilience = "none";
+ rparams.max_hotzone_size = 16*2048;
+ rparams.luks2 = &params2;
+
+ OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+
+ OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd2, CRYPT_LUKS2, NULL));
+ OK_(crypt_set_pbkdf_type(cd2, &pbkdf));
+ EQ_(crypt_keyslot_add_by_key(cd2, 2, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 2);
+ rparams.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd2, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 1, 2, "aes", "cbc-essiv:sha256", &rparams), "Mismatching parameters in device table.");
+ OK_(crypt_reencrypt_init_by_passphrase(cd2, NULL, PASSPHRASE, strlen(PASSPHRASE), 1, 2, "aes", "cbc-essiv:sha256", &rparams));
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd2, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 1, 2, "aes", "cbc-essiv:sha256", &rparams), "Mismatching parameters in device table.");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd);
+ CRYPT_FREE(cd2);
+
+ /* check detached header misuse (mismatching progress data in active device and mda) */
+ OK_(crypt_init(&cd, IMAGE_EMPTY_SMALL));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ params2.data_device = DMDIR L_DEVICE_WRONG;
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ rparams.flags = 0;
+ rparams.max_hotzone_size = 8;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams));
+ /* reencrypt 8 sectors of device */
+ test_progress_steps = 2;
+ OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
+
+ /* activate another data device with same LUKS2 header (this is wrong, but we can't detect such mistake) */
+ OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd2, CRYPT_LUKS2, NULL));
+ NOTFAIL_(crypt_activate_by_passphrase(cd2, CDEVICE_2, CRYPT_ANY_SLOT, PASSPHRASE, strlen(PASSPHRASE), 0), "Failed to activate device in reencryption.");
+ CRYPT_FREE(cd2);
+
+ /* reencrypt yet another 8 sectors of first device */
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams));
+ test_progress_steps = 2;
+ OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
+
+ /* Now active mapping for second data device does not match its metadata */
+ OK_(crypt_init_data_device(&cd2, IMAGE_EMPTY_SMALL, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd2, CRYPT_LUKS2, NULL));
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd2, CDEVICE_2, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "cbc-essiv:sha256", &rparams), "Mismatching device table.");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 16));
+
+ /* Test LUKS2 reencryption honors flags device was activate with */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ params2.sector_size = 512;
+ params2.data_device = NULL;
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 6, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 6);
+ OK_(crypt_volume_key_keyring(cd, 0)); /* disable keyring */
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 6, PASSPHRASE, strlen(PASSPHRASE), CRYPT_ACTIVATE_ALLOW_DISCARDS), 6);
+ OK_(crypt_volume_key_keyring(cd, 1));
+ rparams.mode = CRYPT_REENCRYPT_REENCRYPT;
+ rparams.direction = CRYPT_REENCRYPT_FORWARD,
+ rparams.resilience = "none",
+ rparams.max_hotzone_size = 8;
+ rparams.luks2 = &params2;
+ rparams.flags = 0;
+ EQ_(crypt_keyslot_add_by_key(cd, 1, NULL, 64, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 1);
+ OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "xts-plain64", &rparams));
+ test_progress_steps = 2;
+ OK_(crypt_reencrypt_run(cd, &test_progress, NULL));
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_CLEAN);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS, CRYPT_ACTIVATE_ALLOW_DISCARDS);
+ EQ_(cad.flags & CRYPT_ACTIVATE_KEYRING_KEY, 0);
+ CRYPT_FREE(cd);
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ rparams.flags = CRYPT_REENCRYPT_RESUME_ONLY;
+ OK_(crypt_reencrypt_init_by_passphrase(cd, CDEVICE_1, PASSPHRASE, strlen(PASSPHRASE), 6, 1, "aes", "xts-plain64", &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.flags & CRYPT_ACTIVATE_ALLOW_DISCARDS, CRYPT_ACTIVATE_ALLOW_DISCARDS);
+ EQ_(cad.flags & CRYPT_ACTIVATE_KEYRING_KEY, 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_header_size + 16));
+
+ rparams.mode = CRYPT_REENCRYPT_REENCRYPT;
+ rparams.direction = CRYPT_REENCRYPT_FORWARD;
+ rparams.resilience = "none";
+ rparams.hash = NULL;
+ rparams.data_shift = 0;
+ rparams.max_hotzone_size = 0;
+ rparams.device_size = 0;
+ rparams.luks2 = &params2;
+ rparams.flags = 0;
+
+ /* Test support for specific key reencryption */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 3, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 3);
+ EQ_(crypt_keyslot_add_by_key(cd, 9, key, key_size, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 9);
+ EQ_(crypt_keyslot_add_by_key(cd, 10, key, key_size, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT | CRYPT_VOLUME_KEY_DIGEST_REUSE ), 10);
+ OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 3, 9, "aes", "xts-plain64", &rparams));
+ OK_(crypt_reencrypt_run(cd, NULL, NULL));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ OK_(crypt_keyslot_destroy(cd, 9));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, 2 * r_header_size));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+
+ rparams = (struct crypt_params_reencrypt) {
+ .mode = CRYPT_REENCRYPT_DECRYPT,
+ .direction = CRYPT_REENCRYPT_FORWARD,
+ .resilience = "datashift-checksum",
+ .hash = "sha256",
+ .data_shift = r_header_size,
+ .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+ };
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL));
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+ CRYPT_FREE(cd);
+
+ params2.data_device = DMDIR L_DEVICE_OK;
+ params2.sector_size = 512;
+
+ /* create detached LUKS2 header (with data_offset == 0) */
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, &params2));
+ EQ_(crypt_get_data_offset(cd), 0);
+ OK_(set_fast_pbkdf(cd));
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
+ CRYPT_FREE(cd);
+
+ /* initiate LUKS2 decryption with datashift on bogus LUKS2 header (data_offset == 0) */
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Illegal data offset");
+ /* reencryption must not initialize */
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+ CRYPT_FREE(cd);
+ /* original data device must stay untouched */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+ CRYPT_FREE(cd);
+
+ OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
+ OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+
+ /* simulate read error at first segment beyond data offset*/
+ OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, r_header_size, 8, ERR_RD));
+
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Could not read first data segment");
+ CRYPT_FREE(cd);
+
+ /* Device must not be in reencryption */
+ OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ /* simulate write error in original LUKS2 header area */
+ OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, 0, 8, ERR_WR));
+
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Could not write first data segment");
+ CRYPT_FREE(cd);
+
+ /* Device must not be in reencryption */
+ OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+ CRYPT_FREE(cd);
+ remove(BACKUP_FILE);
+
+ /* remove error mapping */
+ OK_(dmdevice_error_io(L_DEVICE_OK, DMDIR L_DEVICE_OK, DEVICE_ERROR, 0, 0, 8, ERR_REMOVE));
+
+ /* test various bogus reencryption resilience parameters */
+ rparams = (struct crypt_params_reencrypt) {
+ .mode = CRYPT_REENCRYPT_DECRYPT,
+ .direction = CRYPT_REENCRYPT_FORWARD,
+ .resilience = "checksum", /* should have been datashift-checksum */
+ .hash = "sha256",
+ .data_shift = r_header_size,
+ .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+ };
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "xts-plain64", NULL, NULL, 64, NULL));
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, NULL, 64, PASSPHRASE, strlen(PASSPHRASE)));
+ OK_(crypt_header_backup(cd, CRYPT_LUKS2, BACKUP_FILE));
+ CRYPT_FREE(cd);
+
+ OK_(chmod(BACKUP_FILE, S_IRUSR|S_IWUSR));
+ OK_(crypt_init_data_device(&cd, BACKUP_FILE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+
+ /* decryption on device with data offset and no datashift subvariant mode */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ rparams.resilience = "journal"; /* should have been datashift-journal */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ rparams = (struct crypt_params_reencrypt) {
+ .mode = CRYPT_REENCRYPT_DECRYPT,
+ .direction = CRYPT_REENCRYPT_FORWARD,
+ .resilience = "datashift-checksum",
+ .hash = "sha256",
+ .data_shift = 0, /* must be non zero */
+ .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY | CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT
+ };
+
+ /* datashift = 0 */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ rparams.resilience = "datashift-journal";
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ rparams.resilience = "datashift"; /* datashift only is not supported in decryption mode with moved segment */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 21, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 21);
+
+ rparams = (struct crypt_params_reencrypt) {
+ .mode = CRYPT_REENCRYPT_REENCRYPT,
+ .direction = CRYPT_REENCRYPT_FORWARD,
+ .resilience = "datashift-checksum",
+ .hash = "sha256",
+ .data_shift = r_header_size,
+ .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY
+ };
+
+ /* regular reencryption must not accept datashift subvariants */
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ rparams.resilience = "datashift-journal";
+ FAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, CRYPT_ANY_SLOT, NULL, NULL, &rparams), "Invalid reencryption params");
+ EQ_(crypt_reencrypt_status(cd, NULL), CRYPT_REENCRYPT_NONE);
+
+ CRYPT_FREE(cd);
+ _cleanup_dmdevices();
+}
+#endif
+
+static void LuksKeyslotAdd(void)
+{
+ struct crypt_params_luks2 params = {
+ .sector_size = 512
+ };
+ char key[128], key3[128];
+#ifdef KERNEL_KEYRING
+ int ks;
+ key_serial_t kid;
+#endif
+ const struct crypt_token_params_luks2_keyring tparams = {
+ .key_description = KEY_DESC_TEST0
+ };
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+ struct crypt_keyslot_context *um1, *um2;
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key3, vk_hex2, key_size);
+
+ // init test devices
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset + 1));
+
+ // test support for embedded key (after crypt_format)
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, NULL, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 3, um2, 0), 3);
+ EQ_(crypt_keyslot_status(cd, 3), CRYPT_SLOT_ACTIVE_LAST);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+ CRYPT_FREE(cd);
+
+ // test add by volume key
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE1, strlen(PASSPHRASE1), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um2, 0), 0);
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_ACTIVE);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // Add by same passphrase
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 1, um1, 0), 1);
+ EQ_(crypt_keyslot_status(cd, 1), CRYPT_SLOT_ACTIVE);
+ crypt_keyslot_context_free(um1);
+
+ // new passphrase can't be provided by key method
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 1, um1, CRYPT_ANY_SLOT, um2, 0), "Can't get passphrase via selected unlock method");
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // add by keyfile
+ OK_(prepare_keyfile(KEYFILE1, PASSPHRASE1, strlen(PASSPHRASE1)));
+ OK_(prepare_keyfile(KEYFILE2, KEY1, strlen(KEY1)));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um1));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, 0, um1, 2, um2, 0), 2);
+ EQ_(crypt_keyslot_status(cd, 2), CRYPT_SLOT_ACTIVE);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // add by same keyfile
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, 2, um1, 4, um1, 0), 4);
+ EQ_(crypt_keyslot_status(cd, 4), CRYPT_SLOT_ACTIVE);
+ crypt_keyslot_context_free(um1);
+
+ // keyslot already exists
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 3, um1, 0, um2, 0), "Keyslot already exists.");
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // generate new unbound key
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, NULL, 9, &um1));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 10, um2, CRYPT_VOLUME_KEY_NO_SEGMENT), 10);
+ EQ_(crypt_keyslot_status(cd, 10), CRYPT_SLOT_UNBOUND);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ EQ_(crypt_token_luks2_keyring_set(cd, 3, &tparams), 3);
+ EQ_(crypt_token_assign_keyslot(cd, 3, 1), 3);
+ EQ_(crypt_token_assign_keyslot(cd, 3, 3), 3);
+
+ // test unlocking/adding keyslot by LUKS2 token
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ // passphrase not in keyring
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 13, um2, 0), "No token available.");
+#ifdef KERNEL_KEYRING
+ // wrong passphrase in keyring
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 13, um2, 0), "No token available.");
+
+ // token unlocks keyslot
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE, strlen(PASSPHRASE), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 13, um2, 0), 13);
+ EQ_(crypt_keyslot_status(cd, 13), CRYPT_SLOT_ACTIVE);
+
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // token provides passphrase for new keyslot
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, 3, um1, 30, um2, 0), 30);
+ EQ_(crypt_keyslot_status(cd, 30), CRYPT_SLOT_ACTIVE);
+ OK_(crypt_token_is_assigned(cd, 3, 30));
+
+ // unlock and add by same token
+ crypt_keyslot_context_free(um1);
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+ ks = crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um1, 0);
+ GE_(ks, 0);
+ EQ_(crypt_keyslot_status(cd, ks), CRYPT_SLOT_ACTIVE);
+ OK_(crypt_token_is_assigned(cd, 3, ks));
+#endif
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void VolumeKeyGet(void)
+{
+ struct crypt_params_luks2 params = {
+ .sector_size = 512
+ };
+ char key[256], key2[256];
+#ifdef KERNEL_KEYRING
+ key_serial_t kid;
+ const struct crypt_token_params_luks2_keyring tparams = {
+ .key_description = KEY_DESC_TEST0
+ };
+#endif
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a"
+ "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1b";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "xts-plain64";
+ uint64_t r_payload_offset;
+ struct crypt_keyslot_context *um1, *um2;
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ OK_(prepare_keyfile(KEYFILE1, PASSPHRASE1, strlen(PASSPHRASE1)));
+
+#ifdef KERNEL_KEYRING
+ kid = add_key("user", KEY_DESC_TEST0, PASSPHRASE1, strlen(PASSPHRASE1), KEY_SPEC_THREAD_KEYRING);
+ NOTFAIL_(kid, "Test or kernel keyring are broken.");
+#endif
+
+ // init test devices
+ OK_(get_luks2_offsets(0, 0, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset + 1));
+
+ // test support for embedded key (after crypt_format)
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ key_size--;
+ FAIL_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL), "buffer too small");
+
+ // check cached generated volume key can be retrieved
+ key_size++;
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL));
+ OK_(crypt_volume_key_verify(cd, key2, key_size));
+ CRYPT_FREE(cd);
+
+ // check we can add keyslot via retrieved key
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key2, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 3, um2, 0), 3);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+ CRYPT_FREE(cd);
+
+ // check selected volume key can be retrieved and added
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(set_fast_pbkdf(cd));
+ OK_(crypt_format(cd, CRYPT_LUKS2, cipher, cipher_mode, NULL, key, key_size, &params));
+ memset(key2, 0, key_size);
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL));
+ OK_(memcmp(key, key2, key_size));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key2, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 0, um2, 0), 0);
+ crypt_keyslot_context_free(um2);
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 1, um2, 0), 1);
+ crypt_keyslot_context_free(um2);
+#ifdef KERNEL_KEYRING
+ EQ_(crypt_token_luks2_keyring_set(cd, 0, &tparams), 0);
+ EQ_(crypt_token_assign_keyslot(cd, 0, 1), 0);
+#endif
+ crypt_keyslot_context_free(um1);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ // check key context is not usable
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), -EINVAL);
+ crypt_keyslot_context_free(um1);
+
+ // by passphrase
+ memset(key2, 0, key_size);
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 0);
+ OK_(memcmp(key, key2, key_size));
+ memset(key2, 0, key_size);
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, 0, key2, &key_size, um1), 0);
+ OK_(memcmp(key, key2, key_size));
+ crypt_keyslot_context_free(um1);
+
+ // by keyfile
+ memset(key2, 0, key_size);
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 1);
+ OK_(memcmp(key, key2, key_size));
+ memset(key2, 0, key_size);
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, 1, key2, &key_size, um1), 1);
+ crypt_keyslot_context_free(um1);
+
+#ifdef KERNEL_KEYRING
+ // by token
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+ memset(key2, 0, key_size);
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 1);
+ OK_(memcmp(key, key2, key_size));
+ crypt_keyslot_context_free(um1);
+#endif
+ CRYPT_FREE(cd);
+
+ _remove_keyfiles();
+ _cleanup_dmdevices();
+}
+
+static int _crypt_load_check(struct crypt_device *cd)
+{
+#ifdef HAVE_BLKID
+ return crypt_load(cd, CRYPT_LUKS, NULL);
+#else
+ return -ENOTSUP;
+#endif
+}
+
+static void Luks2Repair(void)
+{
+ char rollback[256];
+
+ GE_(snprintf(rollback, sizeof(rollback),
+ "dd if=" IMAGE_PV_LUKS2_SEC ".bcp of=%s bs=1M 2>/dev/null", DEVICE_6), 0);
+
+ OK_(crypt_init(&cd, DEVICE_6));
+
+ FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
+ FAIL_(crypt_repair(cd, CRYPT_LUKS1, NULL), "Not a LUKS2 device");
+
+ /* check explicit LUKS2 repair works */
+ OK_(crypt_repair(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DEVICE_6));
+
+ /* rollback */
+ OK_(_system(rollback, 1));
+ FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
+
+ /* check repair with type detection works */
+ OK_(crypt_repair(cd, CRYPT_LUKS, NULL));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ CRYPT_FREE(cd);
+
+ /* repeat with locking disabled (must not have any effect) */
+ OK_(_system(rollback, 1));
+ OK_(crypt_init(&cd, DEVICE_6));
+ OK_(crypt_metadata_locking(cd, 0));
+
+ FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
+ FAIL_(crypt_repair(cd, CRYPT_LUKS1, NULL), "Not a LUKS2 device");
+
+ /* check explicit LUKS2 repair works */
+ OK_(crypt_repair(cd, CRYPT_LUKS2, NULL));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DEVICE_6));
+
+ /* rollback */
+ OK_(_system(rollback, 1));
+ FAIL_(_crypt_load_check(cd), "Ambiguous signature detected");
+
+ /* check repair with type detection works */
+ OK_(crypt_repair(cd, CRYPT_LUKS, NULL));
+ OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
+ CRYPT_FREE(cd);
+}
+
+static void int_handler(int sig __attribute__((__unused__)))
+{
+ _quit++;
+}
+
+int main(int argc, char *argv[])
+{
+ struct sigaction sa = { .sa_handler = int_handler };
+ int i;
+
+ if (getuid() != 0) {
+ printf("You must be root to run this test.\n");
+ exit(77);
+ }
+#ifndef NO_CRYPTSETUP_PATH
+ if (getenv("CRYPTSETUP_PATH")) {
+ printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
+ exit(77);
+ }
+#endif
+ for (i = 1; i < argc; i++) {
+ if (!strcmp("-v", argv[i]) || !strcmp("--verbose", argv[i]))
+ _verbose = 1;
+ else if (!strcmp("--debug", argv[i]))
+ _debug = _verbose = 1;
+ }
+
+ /* Handle interrupt properly */
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ register_cleanup(_cleanup);
+
+ _cleanup();
+ if (_setup()) {
+ printf("Cannot set test devices.\n");
+ _cleanup();
+ exit(77);
+ }
+
+ crypt_set_debug_level(_debug ? CRYPT_DEBUG_JSON : CRYPT_DEBUG_NONE);
+
+ RUN_(AddDeviceLuks2, "Format and use LUKS2 device");
+ RUN_(Luks2MetadataSize, "LUKS2 metadata settings");
+ RUN_(Luks2HeaderLoad, "LUKS2 header load");
+ RUN_(Luks2HeaderRestore, "LUKS2 header restore");
+ RUN_(Luks2HeaderBackup, "LUKS2 header backup");
+ RUN_(ResizeDeviceLuks2, "LUKS2 device resize tests");
+ RUN_(UseLuks2Device, "Use pre-formated LUKS2 device");
+ RUN_(SuspendDevice, "LUKS2 Suspend/Resume");
+ RUN_(UseTempVolumes, "Format and use temporary encrypted device");
+ RUN_(Tokens, "General tokens API");
+ RUN_(TokenActivationByKeyring, "Builtin kernel keyring token");
+ RUN_(LuksConvert, "LUKS1 <-> LUKS2 conversions");
+ RUN_(Pbkdf, "Default PBKDF manipulation routines");
+ RUN_(Luks2KeyslotParams, "Add a new keyslot with different encryption");
+ RUN_(Luks2KeyslotAdd, "Add a new keyslot by unused key");
+ RUN_(Luks2ActivateByKeyring, "LUKS2 activation by passphrase in keyring");
+ RUN_(Luks2Requirements, "LUKS2 requirements flags");
+ RUN_(Luks2Integrity, "LUKS2 with data integrity");
+ RUN_(Luks2Refresh, "Active device table refresh");
+ RUN_(Luks2Flags, "LUKS2 persistent flags");
+#if KERNEL_KEYRING && USE_LUKS2_REENCRYPTION
+ RUN_(Luks2Reencryption, "LUKS2 reencryption");
+#endif
+ RUN_(LuksKeyslotAdd, "Adding keyslot via new API");
+ RUN_(VolumeKeyGet, "Getting volume key via keyslot context API");
+ RUN_(Luks2Repair, "LUKS2 repair"); // test disables metadata locking. Run always last!
+
+ _cleanup();
+ return 0;
+}
diff --git a/tests/api-test.c b/tests/api-test.c
new file mode 100644
index 0000000..aa430dd
--- /dev/null
+++ b/tests/api-test.c
@@ -0,0 +1,2411 @@
+/*
+ * cryptsetup library API check functions
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include "api_test.h"
+#include "luks1/luks.h"
+#include "libcryptsetup.h"
+
+#define DEVICE_1_UUID "28632274-8c8a-493f-835b-da802e1c576b"
+#define DEVICE_EMPTY_name "crypt_zero"
+#define DEVICE_EMPTY DMDIR DEVICE_EMPTY_name
+#define DEVICE_ERROR_name "crypt_error"
+#define DEVICE_ERROR DMDIR DEVICE_ERROR_name
+
+#define CDEVICE_1 "ctest1"
+#define CDEVICE_2 "ctest2"
+#define CDEVICE_WRONG "O_o"
+#define H_DEVICE "head_ok"
+#define H_DEVICE_WRONG "head_wr"
+#define L_DEVICE_1S "luks_onesec"
+#define L_DEVICE_0S "luks_zerosec"
+#define L_DEVICE_WRONG "luks_wr"
+#define L_DEVICE_OK "luks_ok"
+#define EVL_HEADER_1 "evil_hdr-luks_hdr_damage"
+#define EVL_HEADER_2 "evil_hdr-payload_overwrite"
+#define EVL_HEADER_3 "evil_hdr-stripes_payload_dmg"
+#define EVL_HEADER_4 "evil_hdr-small_luks_device"
+#define EVL_HEADER_5 "evil_hdr-keyslot_overlap"
+#define VALID_HEADER "valid_header_file"
+#define BACKUP_FILE "csetup_backup_file"
+#define IMAGE1 "compatimage.img"
+#define IMAGE_EMPTY "empty.img"
+
+#define KEYFILE1 "key1.file"
+#define KEY1 "compatkey"
+
+#define KEYFILE2 "key2.file"
+#define KEY2 "0123456789abcdef"
+
+#define PASSPHRASE "blablabl"
+#define PASSPHRASE1 "albalbal"
+
+#define DEVICE_TEST_UUID "12345678-1234-1234-1234-123456789abc"
+
+#define DEVICE_WRONG "/dev/Ooo_"
+#define DEVICE_CHAR "/dev/zero"
+#define THE_LFILE_TEMPLATE "cryptsetup-tstlp.XXXXXX"
+
+#define LUKS_PHDR_SIZE_B 1024
+
+static int _fips_mode = 0;
+
+static char *DEVICE_1 = NULL;
+static char *DEVICE_2 = NULL;
+static char *DEVICE_3 = NULL;
+
+static char *tmp_file_1 = NULL;
+static char *test_loop_file = NULL;
+
+struct crypt_device *cd = NULL, *cd2 = NULL;
+
+// Helpers
+
+static int get_luks_offsets(int metadata_device,
+ size_t keylength,
+ unsigned int alignpayload_sec,
+ unsigned int alignoffset_sec,
+ uint64_t *r_header_size,
+ uint64_t *r_payload_offset)
+{
+ int i;
+ uint64_t current_sector;
+ uint32_t sectors_per_stripes_set;
+
+ if (!keylength) {
+ if (r_header_size)
+ *r_header_size = 0;
+ if (r_payload_offset)
+ *r_payload_offset = 0;
+ return -1;
+ }
+
+ sectors_per_stripes_set = DIV_ROUND_UP(keylength*LUKS_STRIPES, TST_SECTOR_SIZE);
+ current_sector = DIV_ROUND_UP_MODULO(DIV_ROUND_UP(LUKS_PHDR_SIZE_B, TST_SECTOR_SIZE),
+ LUKS_ALIGN_KEYSLOTS / TST_SECTOR_SIZE);
+ for (i=0; i < (LUKS_NUMKEYS - 1); i++)
+ current_sector = DIV_ROUND_UP_MODULO(current_sector + sectors_per_stripes_set,
+ LUKS_ALIGN_KEYSLOTS / TST_SECTOR_SIZE);
+ if (r_header_size)
+ *r_header_size = current_sector + sectors_per_stripes_set;
+
+ current_sector = DIV_ROUND_UP_MODULO(current_sector + sectors_per_stripes_set,
+ LUKS_ALIGN_KEYSLOTS / TST_SECTOR_SIZE);
+
+ if (r_payload_offset) {
+ if (metadata_device)
+ *r_payload_offset = alignpayload_sec;
+ else
+ *r_payload_offset = DIV_ROUND_UP_MODULO(current_sector, alignpayload_sec)
+ + alignoffset_sec;
+ }
+
+ return 0;
+}
+
+static void _remove_keyfiles(void)
+{
+ remove(KEYFILE1);
+ remove(KEYFILE2);
+}
+
+#if HAVE_DECL_DM_TASK_RETRY_REMOVE
+#define DM_RETRY "--retry "
+#else
+#define DM_RETRY ""
+#endif
+
+#define DM_NOSTDERR " 2>/dev/null"
+
+static void _cleanup_dmdevices(void)
+{
+ struct stat st;
+
+ if (!stat(DMDIR H_DEVICE, &st))
+ _system("dmsetup remove " DM_RETRY H_DEVICE DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR H_DEVICE_WRONG, &st))
+ _system("dmsetup remove " DM_RETRY H_DEVICE_WRONG DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_0S, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_0S DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_1S, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_1S DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_WRONG, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_WRONG DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR L_DEVICE_OK, &st))
+ _system("dmsetup remove " DM_RETRY L_DEVICE_OK DM_NOSTDERR, 0);
+
+ t_dev_offset = 0;
+}
+
+static void _cleanup(void)
+{
+ struct stat st;
+
+ CRYPT_FREE(cd);
+ CRYPT_FREE(cd2);
+
+ //_system("udevadm settle", 0);
+
+ if (!stat(DMDIR CDEVICE_1, &st))
+ _system("dmsetup remove " DM_RETRY CDEVICE_1 DM_NOSTDERR, 0);
+
+ if (!stat(DMDIR CDEVICE_2, &st))
+ _system("dmsetup remove " DM_RETRY CDEVICE_2 DM_NOSTDERR, 0);
+
+ if (!stat(DEVICE_EMPTY, &st))
+ _system("dmsetup remove " DM_RETRY DEVICE_EMPTY_name DM_NOSTDERR, 0);
+
+ if (!stat(DEVICE_ERROR, &st))
+ _system("dmsetup remove " DM_RETRY DEVICE_ERROR_name DM_NOSTDERR, 0);
+
+ _cleanup_dmdevices();
+
+ if (loop_device(THE_LOOP_DEV))
+ loop_detach(THE_LOOP_DEV);
+
+ if (loop_device(DEVICE_1))
+ loop_detach(DEVICE_1);
+
+ if (loop_device(DEVICE_2))
+ loop_detach(DEVICE_2);
+
+ if (loop_device(DEVICE_3))
+ loop_detach(DEVICE_3);
+
+ _system("rm -f " IMAGE_EMPTY, 0);
+ _system("rm -f " IMAGE1, 0);
+
+ if (test_loop_file)
+ remove(test_loop_file);
+ if (tmp_file_1)
+ remove(tmp_file_1);
+
+ remove(EVL_HEADER_1);
+ remove(EVL_HEADER_2);
+ remove(EVL_HEADER_3);
+ remove(EVL_HEADER_4);
+ remove(EVL_HEADER_5);
+ remove(VALID_HEADER);
+ remove(BACKUP_FILE);
+
+ _remove_keyfiles();
+
+ free(tmp_file_1);
+ free(test_loop_file);
+ free(THE_LOOP_DEV);
+ free(DEVICE_1);
+ free(DEVICE_2);
+ free(DEVICE_3);
+}
+
+static int _setup(void)
+{
+ int fd, ro = 0;
+ char cmd[128];
+
+ test_loop_file = strdup(THE_LFILE_TEMPLATE);
+ if (!test_loop_file)
+ return 1;
+
+ if ((fd=mkstemp(test_loop_file)) == -1) {
+ printf("cannot create temporary file with template %s\n", test_loop_file);
+ return 1;
+ }
+ close(fd);
+ if (snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
+ test_loop_file, TST_SECTOR_SIZE, TST_LOOP_FILE_SIZE) < 0)
+ return 1;
+ if (_system(cmd, 1))
+ return 1;
+
+ fd = loop_attach(&THE_LOOP_DEV, test_loop_file, 0, 0, &ro);
+ close(fd);
+
+ tmp_file_1 = strdup(THE_LFILE_TEMPLATE);
+ if (!tmp_file_1)
+ return 1;
+
+ if ((fd=mkstemp(tmp_file_1)) == -1) {
+ printf("cannot create temporary file with template %s\n", tmp_file_1);
+ return 1;
+ }
+ close(fd);
+ if (snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=%s bs=%d count=%d 2>/dev/null",
+ tmp_file_1, TST_SECTOR_SIZE, 10) < 0)
+ return 1;
+ if (_system(cmd, 1))
+ return 1;
+
+ _system("dmsetup create " DEVICE_EMPTY_name " --table \"0 10000 zero\"", 1);
+ _system("dmsetup create " DEVICE_ERROR_name " --table \"0 10000 error\"", 1);
+
+ _system(" [ ! -e " IMAGE1 " ] && xz -dk " IMAGE1 ".xz", 1);
+ fd = loop_attach(&DEVICE_1, IMAGE1, 0, 0, &ro);
+ close(fd);
+
+ _system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=10 2>/dev/null", 1);
+ fd = loop_attach(&DEVICE_2, IMAGE_EMPTY, 0, 0, &ro);
+ close(fd);
+
+ /* Keymaterial offset is less than 8 sectors */
+ _system(" [ ! -e " EVL_HEADER_1 " ] && xz -dk " EVL_HEADER_1 ".xz", 1);
+ /* keymaterial offset aims into payload area */
+ _system(" [ ! -e " EVL_HEADER_2 " ] && xz -dk " EVL_HEADER_2 ".xz", 1);
+ /* keymaterial offset is valid, number of stripes causes payload area to be overwritten */
+ _system(" [ ! -e " EVL_HEADER_3 " ] && xz -dk " EVL_HEADER_3 ".xz", 1);
+ /* luks device header for data and header on same device. payloadOffset is greater than
+ * device size (crypt_load() test) */
+ _system(" [ ! -e " EVL_HEADER_4 " ] && xz -dk " EVL_HEADER_4 ".xz", 1);
+ /* two keyslots with same offset (overlapping keyslots) */
+ _system(" [ ! -e " EVL_HEADER_5 " ] && xz -dk " EVL_HEADER_5 ".xz", 1);
+ /* valid header: payloadOffset=4096, key_size=32,
+ * volume_key = bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a */
+ _system(" [ ! -e " VALID_HEADER " ] && xz -dk " VALID_HEADER ".xz", 1);
+
+ /* Prepare tcrypt images */
+ _system("tar xJf tcrypt-images.tar.xz 2>/dev/null", 1);
+
+ _system("modprobe dm-crypt >/dev/null 2>&1", 0);
+ _system("modprobe dm-verity >/dev/null 2>&1", 0);
+ _system("modprobe dm-integrity >/dev/null 2>&1", 0);
+
+ if (t_dm_check_versions())
+ return 1;
+
+ _fips_mode = fips_mode();
+ if (_debug)
+ printf("FIPS MODE: %d\n", _fips_mode);
+
+ /* Use default log callback */
+ crypt_set_log_callback(NULL, &global_log_callback, NULL);
+
+ return 0;
+}
+
+static void AddDevicePlain(void)
+{
+ struct crypt_params_plain params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ .size = 0
+ };
+ int fd;
+ char key[128], key2[128], path[128];
+ struct crypt_keyslot_context *kc = NULL;
+
+ const char *passphrase = "blabla";
+ // hashed hex version of PASSPHRASE
+ const char *vk_hex = "ccadd99b16cd3d200c22d6db45d8b6630ef3d936767127347ec8a76ab992c2ea";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+
+ uint64_t size, r_size;
+
+ crypt_decode_key(key, vk_hex, key_size);
+ FAIL_(crypt_init(&cd, ""), "empty device string");
+ FAIL_(crypt_init(&cd, DEVICE_WRONG), "nonexistent device name ");
+ FAIL_(crypt_init(&cd, DEVICE_CHAR), "character device as backing device");
+ OK_(crypt_init(&cd, tmp_file_1));
+ CRYPT_FREE(cd);
+
+ // test crypt_format, crypt_get_cipher, crypt_get_cipher_mode, crypt_get_volume_key_size
+ OK_(crypt_init(&cd,DEVICE_1));
+ params.skip = 3;
+ params.offset = 42;
+ FAIL_(crypt_format(cd,CRYPT_PLAIN,NULL,cipher_mode,NULL,NULL,key_size,&params),"cipher param is null");
+ FAIL_(crypt_format(cd,CRYPT_PLAIN,cipher,NULL,NULL,NULL,key_size,&params),"cipher_mode param is null");
+ OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
+ OK_(strcmp(cipher_mode,crypt_get_cipher_mode(cd)));
+ OK_(strcmp(cipher,crypt_get_cipher(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(params.skip, crypt_get_iv_offset(cd));
+ EQ_(params.offset, crypt_get_data_offset(cd));
+ params.skip = 0;
+ params.offset = 0;
+
+ // crypt_set_uuid()
+ FAIL_(crypt_set_uuid(cd,DEVICE_1_UUID),"can't set uuid to plain device");
+
+ CRYPT_FREE(cd);
+
+ // default is "plain" hash - no password hash
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, NULL));
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0), "cannot verify key with plain");
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // test boundaries in offset parameter
+ t_device_size(DEVICE_1,&size);
+ params.hash = NULL;
+ // zero sectors length
+ params.offset = size >> TST_SECTOR_SHIFT;
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ EQ_(crypt_get_data_offset(cd),params.offset);
+ // device size is 0 sectors
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0), "invalid device size (0 blocks)");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ // data part of crypt device is of 1 sector size
+ params.offset = (size >> TST_SECTOR_SHIFT) - 1;
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ GE_(snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1), 0);
+ if (t_device_size(path, &r_size) >= 0)
+ EQ_(r_size >> TST_SECTOR_SHIFT, 1);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // size > device_size
+ params.offset = 0;
+ params.size = (size >> TST_SECTOR_SHIFT) + 1;
+ crypt_init(&cd, DEVICE_1);
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // offset == device_size (autodetect size)
+ params.offset = (size >> TST_SECTOR_SHIFT);
+ params.size = 0;
+ crypt_init(&cd, DEVICE_1);
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // offset == device_size (user defined size)
+ params.offset = (size >> TST_SECTOR_SHIFT);
+ params.size = 123;
+ crypt_init(&cd, DEVICE_1);
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Device too small");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // offset+size > device_size
+ params.offset = 42;
+ params.size = (size >> TST_SECTOR_SHIFT) - params.offset + 1;
+ crypt_init(&cd, DEVICE_1);
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),"Offset and size are beyond device real size");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // offset+size == device_size
+ params.offset = 42;
+ params.size = (size >> TST_SECTOR_SHIFT) - params.offset;
+ crypt_init(&cd, DEVICE_1);
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ if (!t_device_size(path, &r_size))
+ EQ_((r_size >> TST_SECTOR_SHIFT),params.size);
+ OK_(crypt_deactivate(cd,CDEVICE_1));
+
+ CRYPT_FREE(cd);
+ params.hash = "sha256";
+ params.offset = 0;
+ params.size = 0;
+ params.skip = 0;
+
+ // Now use hashed password
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ FAIL_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0),
+ "cannot verify passphrase with plain" );
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+
+ // device status check
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ GE_(snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1), 0);
+ fd = open(path, O_RDONLY);
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_BUSY);
+ FAIL_(crypt_deactivate(cd, CDEVICE_1), "Device is busy");
+ close(fd);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // crypt_init_by_name_and_header
+ OK_(crypt_init(&cd,DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ CRYPT_FREE(cd);
+
+ // init with detached header is not supported
+ OK_(crypt_init_data_device(&cd, DEVICE_2, DEVICE_1));
+ FAIL_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params),
+ "can't use plain with separate metadata device");
+ CRYPT_FREE(cd);
+
+ FAIL_(crypt_init_by_name_and_header(&cd, CDEVICE_1, H_DEVICE),"can't init plain device by header device");
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ OK_(strcmp(cipher_mode,crypt_get_cipher_mode(cd)));
+ OK_(strcmp(cipher,crypt_get_cipher(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(params.skip, crypt_get_iv_offset(cd));
+ EQ_(params.offset, crypt_get_data_offset(cd));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd,DEVICE_1));
+ OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
+ params.size = 0;
+ params.offset = 0;
+
+ // crypt_set_data_device
+ FAIL_(crypt_set_data_device(cd,H_DEVICE),"can't set data device for plain device");
+ NULL_(crypt_get_metadata_device_name(cd));
+ FAIL_(crypt_header_is_detached(cd), "plain has no header");
+
+ // crypt_get_type
+ OK_(strcmp(crypt_get_type(cd),CRYPT_PLAIN));
+
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+
+ // crypt_resize()
+ OK_(crypt_resize(cd, CDEVICE_1, size >> TST_SECTOR_SHIFT)); // same size
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size, size);
+
+ // size overlaps
+ FAIL_(crypt_resize(cd, CDEVICE_1, (uint64_t)-1),"Backing device is too small");
+ FAIL_(crypt_resize(cd, CDEVICE_1, (size >> TST_SECTOR_SHIFT) + 1),"crypt device overlaps backing device");
+
+ // resize ok
+ OK_(crypt_resize(cd,CDEVICE_1, 123));
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size >> TST_SECTOR_SHIFT, 123);
+ OK_(crypt_resize(cd,CDEVICE_1,0)); // full size (autodetect)
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size, size);
+ OK_(crypt_deactivate(cd,CDEVICE_1));
+ EQ_(crypt_status(cd,CDEVICE_1),CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // offset tests
+ OK_(crypt_init(&cd,DEVICE_1));
+ params.offset = 42;
+ params.size = (size >> TST_SECTOR_SHIFT) - params.offset - 10;
+ OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
+ OK_(crypt_activate_by_volume_key(cd,CDEVICE_1,key,key_size,0));
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size >> TST_SECTOR_SHIFT, params.size);
+ // resize to fill remaining capacity
+ OK_(crypt_resize(cd,CDEVICE_1,params.size + 10));
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size >> TST_SECTOR_SHIFT, params.size + 10);
+
+ // 1 sector beyond real size
+ FAIL_(crypt_resize(cd,CDEVICE_1,params.size + 11), "new device size overlaps backing device"); // with respect to offset
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size >> TST_SECTOR_SHIFT, params.size + 10);
+ GE_(crypt_status(cd,CDEVICE_1),CRYPT_ACTIVE);
+ fd = open(path, O_RDONLY);
+ NOTFAIL_(fd, "Bad loop device.");
+ close(fd);
+
+ // resize to minimal size
+ OK_(crypt_resize(cd,CDEVICE_1, 1)); // minimal device size
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size >> TST_SECTOR_SHIFT, 1);
+ // use size of backing device (autodetect with respect to offset)
+ OK_(crypt_resize(cd,CDEVICE_1,0));
+ if (!t_device_size(path,&r_size))
+ EQ_(r_size >> TST_SECTOR_SHIFT, (size >> TST_SECTOR_SHIFT)- 42);
+ OK_(crypt_deactivate(cd,CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.size = 0;
+ params.offset = 0;
+ OK_(crypt_init(&cd,DEVICE_1));
+ OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
+ OK_(crypt_activate_by_volume_key(cd,CDEVICE_1,key,key_size,0));
+
+ // suspend/resume tests
+ FAIL_(crypt_suspend(cd,CDEVICE_1),"cannot suspend plain device");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ FAIL_(crypt_resume_by_passphrase(cd,CDEVICE_1,CRYPT_ANY_SLOT,passphrase, strlen(passphrase)),"cannot resume plain device");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+
+ // retrieve volume key check
+ memset(key2, 0, key_size);
+ key_size--;
+ // small buffer
+ FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)), "small buffer");
+ key_size++;
+ OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
+ OK_(memcmp(key, key2, key_size));
+ memset(key2, 0, key_size);
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase, strlen(passphrase), &kc));
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, kc));
+ OK_(memcmp(key, key2, key_size));
+ crypt_keyslot_context_free(kc);
+
+ OK_(strcmp(cipher, crypt_get_cipher(cd)));
+ OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(0, crypt_get_data_offset(cd));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // now with keyfile
+ OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1)));
+ OK_(prepare_keyfile(KEYFILE2, KEY2, strlen(KEY2)));
+ FAIL_(crypt_activate_by_keyfile(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, 0), "cannot verify key with plain");
+ EQ_(0, crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, strlen(KEY1) + 1, 0), "cannot seek");
+ FAIL_(crypt_activate_by_keyfile_device_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, strlen(KEY1) + 1, 0), "cannot seek");
+ EQ_(0, crypt_activate_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(0, crypt_activate_by_keyfile_device_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ _remove_keyfiles();
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd,DEVICE_1));
+ OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
+
+ // crypt_keyslot_*()
+ FAIL_(crypt_keyslot_add_by_passphrase(cd,CRYPT_ANY_SLOT,passphrase,strlen(passphrase),passphrase,strlen(passphrase)), "can't add keyslot to plain device");
+ FAIL_(crypt_keyslot_add_by_volume_key(cd,CRYPT_ANY_SLOT ,key,key_size,passphrase,strlen(passphrase)),"can't add keyslot to plain device");
+ FAIL_(crypt_keyslot_add_by_keyfile(cd,CRYPT_ANY_SLOT,KEYFILE1,strlen(KEY1),KEYFILE2,strlen(KEY2)),"can't add keyslot to plain device");
+ FAIL_(crypt_keyslot_destroy(cd,1),"can't manipulate keyslots on plain device");
+ EQ_(crypt_keyslot_status(cd, 0), CRYPT_SLOT_INVALID);
+ FAIL_(crypt_set_label(cd, "label", "subsystem"), "can't set labels for plain device");
+ NULL_(crypt_get_label(cd));
+ NULL_(crypt_get_subsystem(cd));
+ _remove_keyfiles();
+
+ CRYPT_FREE(cd);
+}
+
+static int new_messages = 0;
+static void new_log(int level, const char *msg, void *usrptr)
+{
+ if (level == CRYPT_LOG_ERROR)
+ new_messages++;
+ global_log_callback(level, msg, usrptr);
+}
+
+static void CallbacksTest(void)
+{
+ struct crypt_params_plain params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ };
+
+ size_t key_size = 256 / 8;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ const char *passphrase = PASSPHRASE;
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ new_messages = 0;
+ crypt_set_log_callback(cd, &new_log, NULL);
+ EQ_(new_messages, 0);
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ EQ_(new_messages, 0);
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0), "already exists");
+ EQ_(new_messages, 1);
+ crypt_set_log_callback(cd, NULL, NULL);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+}
+
+static void UseLuksDevice(void)
+{
+ char key[128];
+ size_t key_size;
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ OK_(crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0), "already open");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ FAIL_(crypt_deactivate(cd, CDEVICE_1), "no such device");
+
+ key_size = 16;
+ OK_(strcmp("aes", crypt_get_cipher(cd)));
+ OK_(strcmp("cbc-essiv:sha256", crypt_get_cipher_mode(cd)));
+ OK_(strcmp(DEVICE_1_UUID, crypt_get_uuid(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(1032, crypt_get_data_offset(cd));
+
+ EQ_(0, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
+ OK_(crypt_volume_key_verify(cd, key, key_size));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ key[1] = ~key[1];
+ FAIL_(crypt_volume_key_verify(cd, key, key_size), "key mismatch");
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "key mismatch");
+
+ CRYPT_FREE(cd);
+}
+
+static void SuspendDevice(void)
+{
+ struct crypt_active_device cad;
+ char key[128];
+ size_t key_size;
+ int suspend_status;
+ uint64_t r_payload_offset;
+ const struct crypt_pbkdf_type fast_pbkdf = {
+ .type = "pbkdf2",
+ .hash = "sha256",
+ .iterations = 1000,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+ };
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+
+ suspend_status = crypt_suspend(cd, CDEVICE_1);
+ if (suspend_status == -ENOTSUP) {
+ printf("WARNING: Suspend/Resume not supported, skipping test.\n");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+ return;
+ }
+
+ OK_(suspend_status);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(CRYPT_ACTIVATE_SUSPENDED, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+
+ FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
+
+ FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "wrong key");
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
+ FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)), "not suspended");
+
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+
+ OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1)));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1 "blah", 0), "wrong keyfile");
+ FAIL_(crypt_resume_by_keyfile_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key");
+ FAIL_(crypt_resume_by_keyfile_device_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 1, 0), "wrong key");
+ OK_(crypt_resume_by_keyfile_device_offset(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
+ FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ /* create LUKS device with detached header */
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_data_device(cd, DEVICE_2));
+ OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
+ CRYPT_FREE(cd);
+
+ /* Should be able to suspend but not resume if not header specified */
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
+ FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "no header");
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DEVICE_1));
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
+
+ /* Resume by volume key */
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ key_size = sizeof(key);
+ memset(key, 0, key_size);
+ FAIL_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size), "wrong key");
+ OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
+ OK_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ /* skip tests using empty passphrase */
+ if(_fips_mode)
+ return;
+
+ OK_(get_luks_offsets(0, key_size, 1024*2, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ /* Resume device with cipher_null */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_set_pbkdf_type(cd, &fast_pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS1, "cipher_null", "ecb", NULL, key, key_size, NULL));
+ EQ_(0, crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, "", 0));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ OK_(crypt_resume_by_volume_key(cd, CDEVICE_1, key, key_size));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+ OK_(crypt_suspend(cd, CDEVICE_1));
+ OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, 0, "", 0));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(0, cad.flags & CRYPT_ACTIVATE_SUSPENDED);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _remove_keyfiles();
+ _cleanup_dmdevices();
+}
+
+static void AddDeviceLuks(void)
+{
+ enum { OFFSET_1M = 2048 , OFFSET_2M = 4096, OFFSET_4M = 8192, OFFSET_8M = 16384 };
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = OFFSET_1M, // 4M, data offset will be 4096
+ .data_device = DEVICE_2
+ };
+ char key[128], key2[128], key3[128];
+
+ const char *passphrase = PASSPHRASE, *passphrase2 = "nsdkFI&Y#.sd";
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset, r_header_size, r_size_1;
+ struct crypt_pbkdf_type pbkdf;
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key3, vk_hex2, key_size);
+
+ // init test devices
+ OK_(get_luks_offsets(1, key_size, 0, 0, &r_header_size, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_header_size - 1));
+
+ // format
+ OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
+ params.data_alignment = 0;
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Not enough space for keyslots material");
+ CRYPT_FREE(cd);
+
+ // test payload_offset = 0 for encrypted device with external header device
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), 0);
+ CRYPT_FREE(cd);
+
+ params.data_alignment = 0;
+ params.data_device = NULL;
+
+ // test payload_offset = 0. format() should look up alignment offset from device topology
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(!(crypt_get_data_offset(cd) > 0));
+ CRYPT_FREE(cd);
+
+ // set_data_offset has priority, alignment must be 0 or must be compatible
+ params.data_alignment = 0;
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_set_data_offset(cd, OFFSET_8M));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), OFFSET_8M);
+ CRYPT_FREE(cd);
+
+ // Load gets the value from metadata
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_set_data_offset(cd, OFFSET_2M));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ EQ_(crypt_get_data_offset(cd), OFFSET_8M);
+ CRYPT_FREE(cd);
+
+ params.data_alignment = OFFSET_4M;
+ OK_(crypt_init(&cd, DEVICE_2));
+ FAIL_(crypt_set_data_offset(cd, OFFSET_2M + 1), "Not aligned to 4096"); // must be aligned to 4k
+ OK_(crypt_set_data_offset(cd, OFFSET_2M));
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Alignment not compatible");
+ OK_(crypt_set_data_offset(cd, OFFSET_4M));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), OFFSET_4M);
+ CRYPT_FREE(cd);
+
+ /*
+ * test limit values for backing device size
+ */
+ params.data_alignment = OFFSET_2M;
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+ //OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
+ OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, 2050 - 1)); //FIXME last keyslot - 1 sector
+
+ // 1 sector less than required
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG));
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Device too small");
+ CRYPT_FREE(cd);
+
+ // 0 sectors for encrypted area
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Encrypted area too small");
+ CRYPT_FREE(cd);
+
+ // 1 sector for encrypted area
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_get_data_offset(cd), params.data_alignment);
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(t_device_size(DMDIR CDEVICE_1, &r_size_1));
+ EQ_(r_size_1, TST_SECTOR_SIZE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ // restrict format only to empty context
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Context is already formatted");
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, NULL), "Context is already formatted");
+ // change data device to wrong one
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_0S));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device too small");
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.data_alignment = 0;
+ params.data_device = DEVICE_2;
+
+ // generate keyslot material at the end of luks header
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase) ,0), 7);
+ CRYPT_FREE(cd);
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params), "Context is already formatted");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ CRYPT_FREE(cd);
+ // check active status without header
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, NULL));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ NULL_(crypt_get_type(cd));
+ OK_(strcmp(cipher, crypt_get_cipher(cd)));
+ OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.data_alignment = OFFSET_1M;
+ params.data_device = NULL;
+
+ // test uuid mismatch and _init_by_name_and_header
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_1S));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ EQ_(0, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+ params.data_alignment = 0;
+ params.data_device = DEVICE_2;
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ // there we've got uuid mismatch
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, DMDIR H_DEVICE));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ NULL_(crypt_get_type(cd));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device is active");
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0), "Device is active");
+ EQ_(crypt_status(cd, CDEVICE_2), CRYPT_INACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(crypt_header_is_detached(cd), 1);
+ CRYPT_FREE(cd);
+
+ params.data_device = NULL;
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+
+ // even with no keyslots defined it can be activated by volume key
+ OK_(crypt_volume_key_verify(cd, key, key_size));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+
+ // now with keyslot
+ EQ_(7, crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7));
+ EQ_(7, crypt_activate_by_passphrase(cd, CDEVICE_2, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+
+ crypt_set_iteration_time(cd, 1);
+ EQ_(1, crypt_keyslot_add_by_volume_key(cd, 1, key, key_size, KEY1, strlen(KEY1)));
+
+ // PBKDF info (in LUKS1 slots are the same)
+ FAIL_(crypt_keyslot_get_pbkdf(cd, 1, NULL), "PBKDF struct required");
+ OK_(crypt_keyslot_get_pbkdf(cd, 1, &pbkdf));
+ OK_(strcmp(pbkdf.type, CRYPT_KDF_PBKDF2));
+ OK_(strcmp(pbkdf.hash, params.hash));
+ OK_(pbkdf.iterations < 1000); /* set by minimum iterations above */
+ EQ_(0, pbkdf.max_memory_kb);
+ EQ_(0, pbkdf.parallel_threads);
+ FAIL_(crypt_keyslot_get_pbkdf(cd, 2, &pbkdf), "Keyslot 2 is inactive.");
+
+ OK_(prepare_keyfile(KEYFILE1, KEY1, strlen(KEY1)));
+ OK_(prepare_keyfile(KEYFILE2, KEY2, strlen(KEY2)));
+ EQ_(2, crypt_keyslot_add_by_keyfile(cd, 2, KEYFILE1, 0, KEYFILE2, 0));
+ FAIL_(crypt_keyslot_add_by_keyfile_offset(cd, 3, KEYFILE1, 0, 1, KEYFILE2, 0, 1), "wrong key");
+ EQ_(3, crypt_keyslot_add_by_keyfile_offset(cd, 3, KEYFILE1, 0, 0, KEYFILE2, 0, 1));
+ EQ_(4, crypt_keyslot_add_by_keyfile_offset(cd, 4, KEYFILE2, 0, 1, KEYFILE1, 0, 1));
+ FAIL_(crypt_activate_by_keyfile(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, strlen(KEY2)-1, 0), "key mismatch");
+ EQ_(2, crypt_activate_by_keyfile(cd, NULL, CRYPT_ANY_SLOT, KEYFILE2, 0, 0));
+ EQ_(3, crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE2, 0, 1, 0));
+ EQ_(4, crypt_activate_by_keyfile_offset(cd, NULL, CRYPT_ANY_SLOT, KEYFILE1, 0, 1, 0));
+ FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, strlen(KEY2), 2, 0), "not enough data");
+ FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, strlen(KEY2) + 1, 0), "cannot seek");
+ FAIL_(crypt_activate_by_keyfile_offset(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, 2, 0), "wrong key");
+ EQ_(2, crypt_activate_by_keyfile(cd, CDEVICE_2, CRYPT_ANY_SLOT, KEYFILE2, 0, 0));
+ OK_(crypt_keyslot_destroy(cd, 1));
+ OK_(crypt_keyslot_destroy(cd, 2));
+ OK_(crypt_keyslot_destroy(cd, 3));
+ OK_(crypt_keyslot_destroy(cd, 4));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ _remove_keyfiles();
+
+ FAIL_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), "slot used");
+ key[1] = ~key[1];
+ FAIL_(crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)), "key mismatch");
+ key[1] = ~key[1];
+ EQ_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)));
+ EQ_(CRYPT_SLOT_ACTIVE, crypt_keyslot_status(cd, 6));
+
+ FAIL_(crypt_keyslot_destroy(cd, 8), "invalid keyslot");
+ FAIL_(crypt_keyslot_destroy(cd, CRYPT_ANY_SLOT), "invalid keyslot");
+ FAIL_(crypt_keyslot_destroy(cd, 0), "keyslot not used");
+ OK_(crypt_keyslot_destroy(cd, 7));
+ EQ_(CRYPT_SLOT_INACTIVE, crypt_keyslot_status(cd, 7));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
+
+ EQ_(7, crypt_keyslot_change_by_passphrase(cd, 6, 7, passphrase, strlen(passphrase), passphrase2, strlen(passphrase2)));
+ EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7));
+ EQ_(7, crypt_activate_by_passphrase(cd, NULL, 7, passphrase2, strlen(passphrase2), 0));
+ EQ_(6, crypt_keyslot_change_by_passphrase(cd, CRYPT_ANY_SLOT, 6, passphrase2, strlen(passphrase2), passphrase, strlen(passphrase)));
+
+ EQ_(6, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
+ OK_(crypt_volume_key_verify(cd, key2, key_size));
+
+ OK_(memcmp(key, key2, key_size));
+
+ OK_(strcmp(cipher, crypt_get_cipher(cd)));
+ OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
+ EQ_((int)key_size, crypt_get_volume_key_size(cd));
+ EQ_(OFFSET_2M, crypt_get_data_offset(cd));
+ OK_(strcmp(DEVICE_2, crypt_get_device_name(cd)));
+
+ reset_log();
+ OK_(crypt_dump(cd));
+ OK_(!(global_lines != 0));
+ reset_log();
+ FAIL_(crypt_dump_json(cd, NULL, 0), "LUKS1 not supported");
+
+ FAIL_(crypt_set_uuid(cd, "blah"), "wrong UUID format");
+ OK_(crypt_set_uuid(cd, DEVICE_TEST_UUID));
+ OK_(strcmp(DEVICE_TEST_UUID, crypt_get_uuid(cd)));
+
+ FAIL_(crypt_set_label(cd, "label", "subsystem"), "can't set labels for LUKS1 device");
+ NULL_(crypt_get_label(cd));
+ NULL_(crypt_get_subsystem(cd));
+
+ FAIL_(crypt_deactivate(cd, CDEVICE_2), "not active");
+ CRYPT_FREE(cd);
+
+ // No benchmark PBKDF2
+ pbkdf.flags = CRYPT_PBKDF_NO_BENCHMARK;
+ pbkdf.hash = "sha256";
+ pbkdf.iterations = 1000;
+ pbkdf.time_ms = 0;
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_set_pbkdf_type(cd, &pbkdf));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void UseTempVolumes(void)
+{
+ char tmp[256];
+
+ // Tepmporary device without keyslot but with on-disk LUKS header
+ OK_(crypt_init(&cd, DEVICE_2));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "not yet formatted");
+ OK_(crypt_format(cd, CRYPT_LUKS1, "aes", "cbc-essiv:sha256", NULL, NULL, 16, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name(&cd, CDEVICE_2));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ CRYPT_FREE(cd);
+
+ // Dirty checks: device without UUID
+ // we should be able to remove it but not manipulate with it
+ GE_(snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
+ "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
+ "%s 2048\"", CDEVICE_2, DEVICE_2), 0);
+ _system(tmp, 1);
+ OK_(crypt_init_by_name(&cd, CDEVICE_2));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "No known device type");
+ CRYPT_FREE(cd);
+
+ // Dirty checks: device with UUID but LUKS header key fingerprint must fail)
+ GE_(snprintf(tmp, sizeof(tmp), "dmsetup create %s --table \""
+ "0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
+ "%s 2048\" -u CRYPT-LUKS1-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ctest1",
+ CDEVICE_2, DEVICE_2), 0);
+ _system(tmp, 1);
+ OK_(crypt_init_by_name(&cd, CDEVICE_2));
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "wrong volume key");
+ CRYPT_FREE(cd);
+
+ // No slots
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "volume key is lost");
+ CRYPT_FREE(cd);
+
+ // Plain device
+ OK_(crypt_init(&cd, DEVICE_2));
+ OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, NULL));
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, "xxx", 3, 0), "cannot verify key with plain");
+ FAIL_(crypt_volume_key_verify(cd, "xxx", 3), "cannot verify key with plain");
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, "xxx", 3, 0), "wrong key length");
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, "volumekeyvolumek", 16, 0));
+ GE_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_2));
+ CRYPT_FREE(cd);
+}
+
+static void LuksHeaderRestore(void)
+{
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = 2048, // 4M, data offset will be 4096
+ };
+ struct crypt_params_plain pl_params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ .size = 0
+ };
+ char key[128], key2[128], cmd[256];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 5000));
+
+ // do not restore header over plain device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &pl_params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ FAIL_(crypt_header_restore(cd, CRYPT_PLAIN, VALID_HEADER), "Cannot restore header to PLAIN type device");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Cannot restore header over PLAIN type device");
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // invalid headers
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_1), "Header corrupted");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_2), "Header corrupted");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_3), "Header corrupted");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_4), "Header too small");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_5), "Header corrupted");
+ OK_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER));
+ // wipe valid luks header
+ GE_(snprintf(cmd, sizeof(cmd), "dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=%" PRIu64 " 2>/dev/null", r_payload_offset), 0);
+ OK_(_system(cmd, 1));
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_1), "Header corrupted");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_2), "Header corrupted");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_3), "Header corrupted");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_4), "Header too small");
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, EVL_HEADER_5), "Header corrupted");
+ OK_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // volume key_size mismatch
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ memcpy(key2, key, key_size / 2);
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key2, key_size / 2, &params));
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Volume keysize mismatch");
+ CRYPT_FREE(cd);
+
+ // payload offset mismatch
+ params.data_alignment = 8192;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER), "Payload offset mismatch");
+ //_system("dmsetup table;sleep 1",1);
+ CRYPT_FREE(cd);
+
+ /* check crypt_header_restore() properly loads crypt_device context */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 1*1024*1024, 1*1024*1024, 0, NULL, NULL));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS1, VALID_HEADER));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+ /* same test, any LUKS */
+ OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 1*1024*1024, 1*1024*1024, 0, NULL, NULL));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS, VALID_HEADER));
+ OK_(crypt_activate_by_volume_key(cd, NULL, key, key_size, 0));
+
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void LuksHeaderLoad(void)
+{
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = 2048,
+ };
+ struct crypt_params_plain pl_params = {
+ .hash = "sha256",
+ .skip = 0,
+ .offset = 0,
+ .size = 0
+ };
+ char key[128], cmd[256];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset, r_header_size;
+ uint64_t mdata_size, keyslots_size;
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ // prepare test env
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, &r_header_size, &r_payload_offset));
+ // external header device
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ // prepared header on a device too small to contain header and payload
+ //OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
+ OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, 2050 - 1)); //FIXME
+ //GE_(snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1), 0);
+ GE_(snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%d 2>/dev/null", 2050 - 1), 0);
+ OK_(_system(cmd, 1));
+ // some device
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
+ // 1 sector device
+ OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
+ // 0 sectors device for payload
+ OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset));
+
+ // valid metadata and device size
+ params.data_alignment = 0;
+ params.data_device = DMDIR L_DEVICE_OK;
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(!crypt_get_metadata_device_name(cd));
+ EQ_(strcmp(DMDIR H_DEVICE, crypt_get_metadata_device_name(cd)), 0);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(1, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ // repeat with init with two devices
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ CRYPT_FREE(cd);
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(!crypt_get_metadata_device_name(cd));
+ EQ_(strcmp(DMDIR H_DEVICE, crypt_get_metadata_device_name(cd)), 0);
+ EQ_(1, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ // bad header: device too small (payloadOffset > device_size)
+ OK_(crypt_init(&cd, DMDIR H_DEVICE_WRONG));
+ FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Device too small");
+ NULL_(crypt_get_type(cd));
+ CRYPT_FREE(cd);
+
+ // 0 secs for encrypted data area
+ params.data_alignment = 2048;
+ params.data_device = NULL;
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_set_metadata_size(cd, 0x004000, 0x004000), "Wrong context type");
+ OK_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size));
+ EQ_(mdata_size, LUKS_ALIGN_KEYSLOTS);
+ EQ_(keyslots_size, r_header_size * TST_SECTOR_SIZE - mdata_size);
+ CRYPT_FREE(cd);
+ // load should be ok
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "Device too small");
+ EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
+ CRYPT_FREE(cd);
+
+ // damaged header
+ OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=8 2>/dev/null", 1));
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Header not found");
+ CRYPT_FREE(cd);
+
+ // plain device
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ FAIL_(crypt_load(cd, CRYPT_PLAIN, NULL), "Can't load nonLUKS device type");
+ CRYPT_FREE(cd);
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, key, key_size, &pl_params));
+ FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Can't load over nonLUKS device type");
+ FAIL_(crypt_set_metadata_size(cd, 0x004000, 0x004000), "Wrong context type");
+ FAIL_(crypt_get_metadata_size(cd, &mdata_size, &keyslots_size), "Wrong context type");
+ CRYPT_FREE(cd);
+
+ /* check load sets proper device type */
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_0S));
+ OK_(crypt_load(cd, CRYPT_LUKS, NULL));
+ EQ_(strcmp(CRYPT_LUKS1, crypt_get_type(cd)), 0);
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void LuksHeaderBackup(void)
+{
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = 2048,
+ };
+ char key[128];
+ int fd, ro = O_RDONLY;
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+
+ const char *passphrase = PASSPHRASE;
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1));
+
+ // create LUKS device and backup the header
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), 7);
+ EQ_(crypt_keyslot_add_by_volume_key(cd, 0, key, key_size, passphrase, strlen(passphrase)), 0);
+ OK_(crypt_header_backup(cd, CRYPT_LUKS1, BACKUP_FILE));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // restore header from backup
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_header_restore(cd, CRYPT_LUKS1, BACKUP_FILE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(0, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ // exercise luksOpen using backup header in file
+ OK_(crypt_init(&cd, BACKUP_FILE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ EQ_(1, crypt_header_is_detached(cd));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, BACKUP_FILE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // exercise luksOpen using backup header on block device
+ fd = loop_attach(&DEVICE_3, BACKUP_FILE, 0, 0, &ro);
+ NOTFAIL_(fd, "Bad loop device.");
+ close(fd);
+ OK_(crypt_init(&cd, DEVICE_3));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 0, passphrase, strlen(passphrase), 0), 0);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_3));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_data_device(cd, DMDIR L_DEVICE_OK));
+ EQ_(crypt_activate_by_passphrase(cd, CDEVICE_1, 7, passphrase, strlen(passphrase), 0), 7);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void ResizeDeviceLuks(void)
+{
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = 2048,
+ };
+ char key[128];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset, r_header_size, r_size;
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ // prepare env
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(get_luks_offsets(1, key_size, 0, 0, &r_header_size, NULL));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
+ OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
+ OK_(create_dmdevice_over_loop(L_DEVICE_0S, 1000));
+ OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset + 1000));
+
+ // test header and encrypted payload all in one device
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 42));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(42, r_size >> TST_SECTOR_SHIFT);
+ // autodetect encrypted device area size
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ params.data_alignment = 0;
+ params.data_device = DMDIR L_DEVICE_0S;
+ // test case for external header
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+ OK_(crypt_resize(cd, CDEVICE_1, 666));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(666, r_size >> TST_SECTOR_SHIFT);
+ // autodetect encrypted device size
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1000, r_size >> TST_SECTOR_SHIFT);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
+ OK_(crypt_load(cd, NULL, NULL));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
+
+ /* do not allow resize of other device */
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ OK_(crypt_format(cd2, CRYPT_LUKS1, cipher, cipher_mode, crypt_get_uuid(cd), key, key_size, &params));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
+ FAIL_(crypt_resize(cd2, CDEVICE_1, 1), "Device got resized by wrong device context.");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+
+ OK_(crypt_init(&cd2, DMDIR L_DEVICE_WRONG));
+ OK_(crypt_format(cd2, CRYPT_PLAIN, cipher, cipher_mode, NULL, key, key_size, NULL));
+ OK_(crypt_activate_by_volume_key(cd2, CDEVICE_2, key, key_size, 0));
+ FAIL_(crypt_resize(cd2, CDEVICE_1, 1), "Device got resized by wrong device context.");
+ OK_(crypt_deactivate(cd2, CDEVICE_2));
+ CRYPT_FREE(cd2);
+
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void HashDevicePlain(void)
+{
+ struct crypt_params_plain params = {
+ .hash = NULL,
+ .skip = 0,
+ .offset = 0,
+ };
+
+ size_t key_size;
+ const char *vk_hex, *keystr;
+ char key[256];
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, &params));
+
+ // hash PLAIN, short key
+ OK_(prepare_keyfile(KEYFILE1, "tooshort", 8));
+ FAIL_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 16, 0), "not enough data in keyfile");
+ _remove_keyfiles();
+
+ // hash PLAIN, exact key
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ vk_hex = "caffeecaffeecaffeecaffeecaffee88";
+ key_size = 16;
+ crypt_decode_key(key, vk_hex, key_size);
+ OK_(prepare_keyfile(KEYFILE1, key, key_size));
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, vk_hex));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // Limit plain key
+ vk_hex = "caffeecaffeecaffeecaffeeca000000";
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size - 3, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, vk_hex));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ _remove_keyfiles();
+
+ // hash PLAIN, long key
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ vk_hex = "caffeecaffeecaffeecaffeecaffee88babebabe";
+ key_size = 16;
+ crypt_decode_key(key, vk_hex, key_size);
+ OK_(prepare_keyfile(KEYFILE1, key, strlen(vk_hex) / 2));
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ FAIL_(strcmp(key, vk_hex), "only key length used");
+ OK_(strncmp(key, vk_hex, key_size));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // Now without explicit limit
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ FAIL_(strcmp(key, vk_hex), "only key length used");
+ OK_(strncmp(key, vk_hex, key_size));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _remove_keyfiles();
+
+ // Handling of legacy "plain" hash (no hash)
+ params.hash = "plain";
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ vk_hex = "aabbcaffeecaffeecaffeecaffeecaff";
+ key_size = 16;
+ crypt_decode_key(key, vk_hex, key_size);
+ OK_(prepare_keyfile(KEYFILE1, key, strlen(vk_hex) / 2));
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, &params));
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, vk_hex));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _remove_keyfiles();
+
+ // hash sha256
+ params.hash = "sha256";
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, &params));
+
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ vk_hex = "c62e4615bd39e222572f3a1bf7c2132e";
+ keystr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+ key_size = strlen(keystr); // 32
+ OK_(prepare_keyfile(KEYFILE1, keystr, strlen(keystr)));
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, vk_hex));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // Read full keyfile
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, vk_hex));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ _remove_keyfiles();
+
+ // Limit keyfile read
+ keystr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAAAAAAAA";
+ OK_(prepare_keyfile(KEYFILE1, keystr, strlen(keystr)));
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, key_size, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, vk_hex));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ // Full keyfile
+ OK_(crypt_activate_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0, 0));
+ OK_(get_key_dm(CDEVICE_1, key, sizeof(key)));
+ OK_(strcmp(key, "0e49cb34a1dee1df33f6505e4de44a66"));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ _remove_keyfiles();
+
+ // FIXME: add keyfile="-" tests somehow
+
+ CRYPT_FREE(cd);
+}
+
+static void VerityTest(void)
+{
+ const char *salt_hex = "20c28ffc129c12360ba6ceea2b6cf04e89c2b41cfe6b8439eb53c1897f50df7b";
+ const char *root_hex = "ab018b003a967fc782effb293b6dccb60b4f40c06bf80d16391acf686d28b5d6";
+ char salt[256], root_hash[256], root_hash_out[256];
+ size_t root_hash_out_size = 256;
+ struct crypt_active_device cad;
+ struct crypt_params_verity params = {
+ .data_device = DEVICE_EMPTY,
+ .salt = salt,
+ .data_size = 0, /* whole device */
+ .hash_area_offset = 0,
+ .flags = CRYPT_VERITY_CREATE_HASH,
+ };
+
+ crypt_decode_key(salt, salt_hex, strlen(salt_hex) / 2);
+ crypt_decode_key(root_hash, root_hex, strlen(root_hex) / 2);
+
+ /* Format */
+ OK_(crypt_init(&cd, DEVICE_2));
+
+ /* block size */
+ params.data_block_size = 333;
+ FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params),
+ "Unsupported block size.");
+ params.data_block_size = 4096;
+ params.hash_block_size = 333;
+ FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params),
+ "Unsupported block size.");
+ params.hash_block_size = 4096;
+
+ /* salt size */
+ params.salt_size = 257;
+ FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params),
+ "Too large salt.");
+ params.salt_size = 32;
+
+ /* hash_type */
+ params.hash_type = 3;
+ FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params),
+ "Unsupported hash type.");
+ params.hash_type = 1;
+ params.hash_name = "blah";
+ FAIL_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params),
+ "Unsupported hash name.");
+ params.hash_name = "sha256";
+
+ OK_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params));
+ CRYPT_FREE(cd);
+
+ params.data_device = NULL;
+ OK_(crypt_init_data_device(&cd, DEVICE_2, DEVICE_EMPTY));
+ OK_(crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params));
+ EQ_(strcmp(DEVICE_2, crypt_get_metadata_device_name(cd)), 0);
+ CRYPT_FREE(cd);
+
+ /* Verify */
+ OK_(crypt_init(&cd, DEVICE_2));
+ memset(&params, 0, sizeof(params));
+ params.data_device = DEVICE_EMPTY;
+ params.flags = CRYPT_VERITY_CHECK_HASH;
+ OK_(crypt_load(cd, CRYPT_VERITY, &params));
+
+ /* check verity params */
+ EQ_(crypt_get_volume_key_size(cd), 32);
+ OK_(strcmp(CRYPT_VERITY, crypt_get_type(cd)));
+ memset(&params, 0, sizeof(params));
+ OK_(crypt_get_verity_info(cd, &params));
+ OK_(strcmp("sha256", params.hash_name));
+ EQ_(strlen(salt_hex) / 2, params.salt_size);
+ OK_(memcmp(salt, params.salt, params.salt_size));
+ EQ_(4096, params.data_block_size);
+ EQ_(4096, params.hash_block_size);
+ EQ_(1, params.hash_type);
+ EQ_(crypt_get_volume_key_size(cd), 32);
+
+ OK_(crypt_activate_by_volume_key(cd, NULL, root_hash, 32, 0));
+ OK_(crypt_set_data_device(cd, DEVICE_1));
+ FAIL_(crypt_activate_by_volume_key(cd, NULL, root_hash, 32, 0), "Data corrupted");;
+
+ OK_(crypt_set_data_device(cd, DEVICE_EMPTY));
+ if (crypt_activate_by_volume_key(cd, CDEVICE_1, root_hash, 32,
+ CRYPT_ACTIVATE_READONLY) == -ENOTSUP) {
+ printf("WARNING: kernel dm-verity not supported, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(CRYPT_ACTIVATE_READONLY, cad.flags);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ memset(root_hash_out, 0, root_hash_out_size);
+ OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_out, &root_hash_out_size, NULL, 0));
+ EQ_(32, root_hash_out_size);
+ OK_(memcmp(root_hash, root_hash_out, root_hash_out_size));
+ memset(root_hash_out, 0, root_hash_out_size);
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, root_hash_out, &root_hash_out_size, NULL));
+ EQ_(32, root_hash_out_size);
+ OK_(memcmp(root_hash, root_hash_out, root_hash_out_size));
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ /* hash fail */
+ root_hash[1] = ~root_hash[1];
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, root_hash, 32, CRYPT_ACTIVATE_READONLY));
+ /* Be sure there was some read activity to mark device corrupted. */
+ _system("blkid " DMDIR CDEVICE_1, 0);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_CORRUPTED, cad.flags);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ root_hash[1] = ~root_hash[1];
+
+ /* data fail */
+ OK_(crypt_set_data_device(cd, DEVICE_1));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, root_hash, 32, CRYPT_ACTIVATE_READONLY));
+ _system("blkid " DMDIR CDEVICE_1, 0);
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_CORRUPTED, cad.flags);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+
+ CRYPT_FREE(cd);
+}
+
+static void TcryptTest(void)
+{
+ struct crypt_active_device cad;
+ const char *passphrase = "aaaaaaaaaaaa";
+ const char *kf1 = "tcrypt-images/keyfile1";
+ const char *kf2 = "tcrypt-images/keyfile2";
+ const char *keyfiles[] = { kf1, kf2 };
+ struct crypt_params_tcrypt params = {
+ .passphrase = passphrase,
+ .passphrase_size = strlen(passphrase),
+ .keyfiles = keyfiles,
+ .keyfiles_count = 2,
+ };
+ double enc_mbr = 0, dec_mbr = 0;
+ const char *tcrypt_dev = "tcrypt-images/tck_5-sha512-xts-aes";
+ const char *tcrypt_dev2 = "tcrypt-images/tc_5-sha512-xts-serpent-twofish-aes";
+ size_t key_size = 64;
+ char key[64], key_def[64];
+ const char *key_hex =
+ "98dee64abe44bbf41d171c1f7b3e8eacda6d6b01f459097459a167f8c2872a96"
+ "3979531d1cdc18af62757cf22286f16f8583d848524f128d7594ac2082668c73";
+ int r;
+
+ crypt_decode_key(key_def, key_hex, strlen(key_hex) / 2);
+
+ // First ensure we can use af_alg skcipher interface
+ r = crypt_benchmark(NULL, "aes", "xts", 512, 16, 1024, &enc_mbr, &dec_mbr);
+ if (r == -ENOTSUP || r == -ENOENT) {
+ printf("WARNING: algif_skcipher interface not present, skipping test.\n");
+ return;
+ }
+
+ OK_(crypt_init(&cd, tcrypt_dev));
+ params.passphrase_size--;
+ FAIL_(crypt_load(cd, CRYPT_TCRYPT, &params), "Wrong passphrase");
+ params.passphrase_size++;
+ OK_(crypt_load(cd, CRYPT_TCRYPT, &params));
+
+ // check params after load
+ OK_(strcmp("xts-plain64", crypt_get_cipher_mode(cd)));
+ OK_(strcmp("aes", crypt_get_cipher(cd)));
+ EQ_(key_size, crypt_get_volume_key_size(cd));
+ EQ_(256, crypt_get_iv_offset(cd));
+ EQ_(256, crypt_get_data_offset(cd));
+
+ memset(key, 0, key_size);
+
+ key_size--;
+ // small buffer
+ FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0), "small buffer");
+ key_size++;
+ OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0));
+ OK_(memcmp(key, key_def, key_size));
+ memset(key, 0, key_size);
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key, &key_size, NULL));
+ OK_(memcmp(key, key_def, key_size));
+
+ reset_log();
+ OK_(crypt_dump(cd));
+ OK_(!(global_lines != 0));
+ reset_log();
+
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, CRYPT_ACTIVATE_READONLY));
+ NULL_(crypt_get_metadata_device_name(cd));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init_by_name_and_header(&cd, CDEVICE_1, NULL));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+
+ FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, NULL, 0), "Need crypt_load");
+ FAIL_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key, &key_size, NULL), "Need crypt_load");
+
+ // check params after init_by_name
+ OK_(strcmp("xts-plain64", crypt_get_cipher_mode(cd)));
+ OK_(strcmp("aes", crypt_get_cipher(cd)));
+ EQ_(key_size, crypt_get_volume_key_size(cd));
+ EQ_(256, crypt_get_iv_offset(cd));
+ EQ_(256, crypt_get_data_offset(cd));
+
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(CRYPT_ACTIVATE_READONLY, cad.flags);
+ EQ_(256, cad.offset);
+ EQ_(256, cad.iv_offset);
+ EQ_(72, cad.size);
+
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // init with detached header is not supported
+ OK_(crypt_init_data_device(&cd, tcrypt_dev2, DEVICE_2));
+ FAIL_(crypt_load(cd, CRYPT_TCRYPT, &params), "can't use tcrypt with separate metadata device");
+ CRYPT_FREE(cd);
+
+ // Following test uses non-FIPS algorithms in the cipher chain
+ if(_fips_mode)
+ return;
+
+ OK_(crypt_init(&cd, tcrypt_dev2));
+ params.keyfiles = NULL;
+ params.keyfiles_count = 0;
+ r = crypt_load(cd, CRYPT_TCRYPT, &params);
+ if (r < 0) {
+ printf("WARNING: cannot use non-AES encryption, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, CRYPT_ACTIVATE_READONLY));
+ CRYPT_FREE(cd);
+
+ // Deactivate the whole chain
+ EQ_(crypt_status(NULL, CDEVICE_1 "_1"), CRYPT_BUSY);
+ OK_(crypt_deactivate(NULL, CDEVICE_1));
+ EQ_(crypt_status(NULL, CDEVICE_1 "_1"), CRYPT_INACTIVE);
+}
+
+static void ResizeIntegrity(void)
+{
+ struct crypt_params_integrity params = {
+ .tag_size = 4,
+ .integrity = "crc32c",
+ .sector_size = 4096,
+ };
+ int ret;
+ uint64_t r_size, whole_device_size = 0;
+
+ if (!t_dm_integrity_resize_support()) {
+ printf("WARNING: integrity device resize not supported, skipping test.\n");
+ return;
+ }
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ ret = crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params);
+ if (ret < 0) {
+ printf("WARNING: cannot format integrity device, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, 0));
+ t_device_size(DMDIR CDEVICE_1, &whole_device_size);
+ // shrink the device
+ OK_(crypt_resize(cd, CDEVICE_1, 1024 * 1024 / 512));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1024 * 1024 / 512, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ // fill the whole device again (size = 0)
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(whole_device_size, r_size);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // detached metadata
+ OK_(create_dmdevice_over_loop(H_DEVICE, 1024 * 1024 / 512));
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DEVICE_2));
+ OK_(crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &whole_device_size))
+ EQ_(10 * 1024 * 1024 / 512, whole_device_size >> TST_SECTOR_SHIFT);
+ // shrink the device
+ OK_(crypt_resize(cd, CDEVICE_1, 1024 * 1024 / 512));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1024 * 1024 / 512, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ // fill the whole device again (size = 0)
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(whole_device_size, r_size);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void ResizeIntegrityWithKey(void)
+{
+ struct crypt_params_integrity params = {
+ .tag_size = 4,
+ .integrity = "hmac(sha256)",
+ .journal_integrity = "hmac(sha256)",
+ .journal_crypt = "cbc(aes)",
+ .sector_size = 4096,
+ };
+ int ret;
+ uint64_t r_size, whole_device_size = 0;
+
+ const char *key_integrity_hex = "41b06f3968ff10783edf3dd8c31d0d6e";
+ const char *key_journal_integrity_hex = "9a3f924d03ab4a3307b148f844628f59";
+ const char *key_journal_crypt_hex = "087a6943383f6c344cef03695b4f7277";
+
+ char integrity_key[128], journal_integrity_key[128], journal_crypt_key[128];
+
+ size_t integrity_key_size = strlen(key_integrity_hex) / 2;
+ size_t journal_integrity_key_size = strlen(key_journal_integrity_hex) / 2;
+ size_t journal_crypt_key_size = strlen(key_journal_crypt_hex) / 2;
+
+ crypt_decode_key(integrity_key, key_integrity_hex, integrity_key_size);
+ crypt_decode_key(journal_integrity_key, key_journal_integrity_hex, journal_integrity_key_size);
+ crypt_decode_key(journal_crypt_key, key_journal_crypt_hex, journal_crypt_key_size);
+
+ params.integrity_key_size = integrity_key_size;
+
+ params.journal_integrity_key_size = journal_integrity_key_size;
+ params.journal_integrity_key = journal_integrity_key;
+
+ params.journal_crypt_key_size = journal_crypt_key_size;
+ params.journal_crypt_key = journal_crypt_key;
+
+ if (!t_dm_integrity_resize_support()) {
+ printf("WARNING: integrity device resize not supported, skipping test.\n");
+ return;
+ }
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ ret = crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params);
+ if (ret < 0) {
+ printf("WARNING: cannot format integrity device, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, integrity_key, integrity_key_size, 0));
+ t_device_size(DMDIR CDEVICE_1, &whole_device_size);
+ // shrink the device
+ OK_(crypt_resize(cd, CDEVICE_1, 1024*1024/512));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1024*1024/512, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ // fill the whole device again (size = 0)
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(whole_device_size, r_size);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ // detached metadata
+ OK_(create_dmdevice_over_loop(H_DEVICE, 1024 * 1024 / 512));
+ OK_(crypt_init_data_device(&cd, DMDIR H_DEVICE, DEVICE_2));
+ OK_(crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, integrity_key, integrity_key_size, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &whole_device_size))
+ EQ_(10*1024*1024/512, whole_device_size >> TST_SECTOR_SHIFT);
+ // shrink the device
+ OK_(crypt_resize(cd, CDEVICE_1, 1024*1024/512));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(1024*1024/512, r_size >> TST_SECTOR_SHIFT);
+ FAIL_(crypt_resize(cd, CDEVICE_1, 1001), "Device too small");
+ // fill the whole device again (size = 0)
+ OK_(crypt_resize(cd, CDEVICE_1, 0));
+ if (!t_device_size(DMDIR CDEVICE_1, &r_size))
+ EQ_(whole_device_size, r_size);
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void IntegrityTest(void)
+{
+ struct crypt_params_integrity params = {
+ .tag_size = 4,
+ .integrity = "crc32c",
+ .sector_size = 4096,
+ }, ip = {};
+ struct crypt_active_device cad;
+ int ret;
+
+ // FIXME: this should be more detailed
+
+ OK_(crypt_init(&cd,DEVICE_1));
+ FAIL_(crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,NULL), "params field required");
+ ret = crypt_format(cd,CRYPT_INTEGRITY,NULL,NULL,NULL,NULL,0,&params);
+ if (ret < 0) {
+ printf("WARNING: cannot format integrity device, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+ OK_(crypt_get_integrity_info(cd, &ip));
+ EQ_(ip.tag_size, params.tag_size);
+ EQ_(ip.sector_size, params.sector_size);
+ EQ_(crypt_get_sector_size(cd), params.sector_size);
+ EQ_(ip.interleave_sectors, params.interleave_sectors);
+ EQ_(ip.journal_size, params.journal_size);
+ EQ_(ip.journal_watermark, params.journal_watermark);
+ EQ_(ip.integrity_key_size, 0);
+ OK_(strcmp(ip.integrity,params.integrity));
+ FAIL_(crypt_set_uuid(cd,DEVICE_1_UUID),"can't set uuid to integrity device");
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_load(cd, CRYPT_INTEGRITY, NULL));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ //params.tag_size = 8;
+ //FAIL_(crypt_load(cd, CRYPT_INTEGRITY, &params), "tag size mismatch");
+ params.tag_size = 4;
+ OK_(crypt_load(cd, CRYPT_INTEGRITY, &params));
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, 0));
+ GE_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
+ CRYPT_FREE(cd);
+
+ memset(&ip, 0, sizeof(ip));
+ OK_(crypt_init_by_name(&cd, CDEVICE_1));
+ OK_(crypt_get_integrity_info(cd, &ip));
+ EQ_(ip.tag_size, params.tag_size);
+ OK_(strcmp(ip.integrity,params.integrity));
+ OK_(strcmp(CRYPT_INTEGRITY,crypt_get_type(cd)));
+
+ if (t_dm_integrity_recalculate_support()) {
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.flags & CRYPT_ACTIVATE_RECALCULATE, 0);
+ OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, NULL, 0, CRYPT_ACTIVATE_REFRESH | CRYPT_ACTIVATE_RECALCULATE));
+ OK_(crypt_get_active_device(cd, CDEVICE_1, &cad));
+ EQ_(cad.flags & CRYPT_ACTIVATE_RECALCULATE, CRYPT_ACTIVATE_RECALCULATE);
+ }
+
+ OK_(crypt_deactivate(cd, CDEVICE_1));
+ CRYPT_FREE(cd);
+}
+
+static void WipeTest(void)
+{
+ OK_(crypt_init(&cd, NULL));
+ FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL), "No device");
+ FAIL_(crypt_wipe(cd, DEVICE_WRONG, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL), "Wrong device");
+ OK_(crypt_wipe(cd, DEVICE_1, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL));
+ OK_(crypt_wipe(cd, DEVICE_1, CRYPT_WIPE_RANDOM, 0, 4096, 0, 0, NULL, NULL));
+ OK_(crypt_wipe(cd, DEVICE_1, CRYPT_WIPE_RANDOM, 0, 4096, 0, CRYPT_WIPE_NO_DIRECT_IO, NULL, NULL));
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DEVICE_1));
+ OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_ZERO, 0, 4096, 0, 0, NULL, NULL));
+ OK_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 0, 4096, TST_SECTOR_SIZE, 0, NULL, NULL));
+ FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 0, 4096, TST_SECTOR_SIZE-1, 0, NULL, NULL), "Sector size");
+ FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 0, 4096 - 1, 0, 0, NULL, NULL), "Length size not aligned");
+ FAIL_(crypt_wipe(cd, NULL, CRYPT_WIPE_RANDOM, 1, 4096, 0, 0, NULL, NULL), "Offset not aligned");
+ CRYPT_FREE(cd);
+}
+
+static void LuksKeyslotAdd(void)
+{
+ enum { OFFSET_1M = 2048 , OFFSET_2M = 4096, OFFSET_4M = 8192, OFFSET_8M = 16384 };
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = OFFSET_1M, // 4M, data offset will be 4096
+ };
+ struct crypt_pbkdf_type min_pbkdf2 = {
+ .type = "pbkdf2",
+ .hash = "sha256",
+ .iterations = 1000,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+ };
+ char key[128], key3[128];
+
+ const char *passphrase = PASSPHRASE, *passphrase2 = "nsdkFI&Y#.sd";
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ const char *vk_hex2 = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1e";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+ struct crypt_keyslot_context *um1, *um2;
+
+ crypt_decode_key(key, vk_hex, key_size);
+ crypt_decode_key(key3, vk_hex2, key_size);
+
+ // init test devices
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset + 1));
+
+ // test support for embedded key (after crypt_format)
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, NULL, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase, strlen(passphrase), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 3, um2, 0), 3);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+ CRYPT_FREE(cd);
+
+ // test add by volume key
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase2, strlen(passphrase2), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um2, 0), 0);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // Add by same passphrase
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase, strlen(passphrase), &um1));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 1, um1, 0), 1);
+ crypt_keyslot_context_free(um1);
+
+ // new passphrase can't be provided by key method
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase, strlen(passphrase), &um1));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 1, um1, CRYPT_ANY_SLOT, um2, 0), "Can't get passphrase via selected unlock method");
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // add by keyfile
+ OK_(prepare_keyfile(KEYFILE1, passphrase2, strlen(passphrase2)));
+ OK_(prepare_keyfile(KEYFILE2, KEY1, strlen(KEY1)));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um1));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, 0, um1, 2, um2, 0), 2);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // add by same keyfile
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 4, um1, 0), 4);
+ crypt_keyslot_context_free(um1);
+
+ // keyslot already exists
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, passphrase2, strlen(passphrase2), &um1));
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 3, um1, 0, um2, 0), "Keyslot already exists.");
+ crypt_keyslot_context_free(um2);
+
+ // flags not supported with LUKS1
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, CRYPT_ANY_SLOT, um2, CRYPT_VOLUME_KEY_NO_SEGMENT), "Not supported with LUKS1.");
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ // LUKS2 token not supported
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, 2, um1, CRYPT_ANY_SLOT, um2, 0), "Not supported with LUKS1.");
+ EQ_(crypt_keyslot_context_get_error(um2), -EINVAL);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE2, 0, 0, &um1));
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um2));
+ FAIL_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um2, CRYPT_ANY_SLOT, um1, 0), "Not supported with LUKS1.");
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+
+ CRYPT_FREE(cd);
+
+ _cleanup_dmdevices();
+}
+
+static void VolumeKeyGet(void)
+{
+ struct crypt_params_luks1 params = {
+ .hash = "sha512",
+ .data_alignment = 2048, // 2M, data offset will be 2048
+ };
+ struct crypt_pbkdf_type min_pbkdf2 = {
+ .type = "pbkdf2",
+ .hash = "sha256",
+ .iterations = 1000,
+ .flags = CRYPT_PBKDF_NO_BENCHMARK
+ };
+ char key[128], key2[128];
+
+ const char *vk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+ size_t key_size = strlen(vk_hex) / 2;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ uint64_t r_payload_offset;
+ struct crypt_keyslot_context *um1, *um2;
+
+ crypt_decode_key(key, vk_hex, key_size);
+
+ OK_(prepare_keyfile(KEYFILE1, PASSPHRASE1, strlen(PASSPHRASE1)));
+
+ // init test devices
+ OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
+ OK_(create_dmdevice_over_loop(H_DEVICE, r_payload_offset + 1));
+
+ // test support for embedded key (after crypt_format)
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ key_size--;
+ FAIL_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL), "buffer too small");
+
+ // check cached generated volume key can be retrieved
+ key_size++;
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL));
+ OK_(crypt_volume_key_verify(cd, key2, key_size));
+ CRYPT_FREE(cd);
+
+ // check we can add keyslot via retrieved key
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key2, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 3, um2, 0), 3);
+ crypt_keyslot_context_free(um1);
+ crypt_keyslot_context_free(um2);
+ CRYPT_FREE(cd);
+
+ // check selected volume key can be retrieved and added
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_set_pbkdf_type(cd, &min_pbkdf2));
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ memset(key2, 0, key_size);
+ OK_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, NULL));
+ OK_(memcmp(key, key2, key_size));
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key2, key_size, &um1));
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 0, um2, 0), 0);
+ crypt_keyslot_context_free(um2);
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um2));
+ EQ_(crypt_keyslot_add_by_keyslot_context(cd, CRYPT_ANY_SLOT, um1, 1, um2, 0), 1);
+ crypt_keyslot_context_free(um2);
+ crypt_keyslot_context_free(um1);
+ CRYPT_FREE(cd);
+
+ OK_(crypt_init(&cd, DMDIR H_DEVICE));
+ OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
+ // check key context is not usable
+ OK_(crypt_keyslot_context_init_by_volume_key(cd, key, key_size, &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), -EINVAL);
+ crypt_keyslot_context_free(um1);
+
+ // check token context is not usable
+ OK_(crypt_keyslot_context_init_by_token(cd, CRYPT_ANY_TOKEN, NULL, NULL, 0, NULL, &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), -EINVAL);
+ crypt_keyslot_context_free(um1);
+
+ // by passphrase
+ memset(key2, 0, key_size);
+ OK_(crypt_keyslot_context_init_by_passphrase(cd, PASSPHRASE, strlen(PASSPHRASE), &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 0);
+ OK_(memcmp(key, key2, key_size));
+ memset(key2, 0, key_size);
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, 0, key2, &key_size, um1), 0);
+ OK_(memcmp(key, key2, key_size));
+ crypt_keyslot_context_free(um1);
+
+ // by keyfile
+ memset(key2, 0, key_size);
+ OK_(crypt_keyslot_context_init_by_keyfile(cd, KEYFILE1, 0, 0, &um1));
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, CRYPT_ANY_SLOT, key2, &key_size, um1), 1);
+ OK_(memcmp(key, key2, key_size));
+ memset(key2, 0, key_size);
+ EQ_(crypt_volume_key_get_by_keyslot_context(cd, 1, key2, &key_size, um1), 1);
+ crypt_keyslot_context_free(um1);
+ CRYPT_FREE(cd);
+
+ _remove_keyfiles();
+ _cleanup_dmdevices();
+}
+
+// Check that gcrypt is properly initialised in format
+static void NonFIPSAlg(void)
+{
+ struct crypt_params_luks1 params = {0};
+ char key[128] = "";
+ size_t key_size = 128 / 8;
+ const char *cipher = "aes";
+ const char *cipher_mode = "cbc-essiv:sha256";
+ int ret;
+
+ OK_(crypt_init(&cd, DEVICE_2));
+ params.hash = "sha256";
+ OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params),
+ "Already formatted.");
+ CRYPT_FREE(cd);
+
+ params.hash = "whirlpool";
+ OK_(crypt_init(&cd, DEVICE_2));
+ ret = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params);
+ if (ret < 0) {
+ printf("WARNING: whirlpool not supported, skipping test.\n");
+ CRYPT_FREE(cd);
+ return;
+ }
+ CRYPT_FREE(cd);
+
+ params.hash = "md5";
+ OK_(crypt_init(&cd, DEVICE_2));
+ FAIL_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params),
+ "MD5 unsupported, too short");
+ CRYPT_FREE(cd);
+}
+
+static void int_handler(int sig __attribute__((__unused__)))
+{
+ _quit++;
+}
+
+int main(int argc, char *argv[])
+{
+ struct sigaction sa = { .sa_handler = int_handler };
+ int i;
+
+ if (getuid() != 0) {
+ printf("You must be root to run this test.\n");
+ exit(77);
+ }
+#ifndef NO_CRYPTSETUP_PATH
+ if (getenv("CRYPTSETUP_PATH")) {
+ printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
+ exit(77);
+ }
+#endif
+ for (i = 1; i < argc; i++) {
+ if (!strcmp("-v", argv[i]) || !strcmp("--verbose", argv[i]))
+ _verbose = 1;
+ else if (!strcmp("--debug", argv[i]))
+ _debug = _verbose = 1;
+ }
+
+ /* Handle interrupt properly */
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ register_cleanup(_cleanup);
+
+ _cleanup();
+ if (_setup()) {
+ printf("Cannot set test devices.\n");
+ _cleanup();
+ exit(77);
+ }
+
+ crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
+
+ RUN_(NonFIPSAlg, "Crypto is properly initialised in format"); //must be the first!
+ RUN_(AddDevicePlain, "A plain device API creation");
+ RUN_(HashDevicePlain, "A plain device API hash");
+ RUN_(AddDeviceLuks, "Format and use LUKS device");
+ RUN_(LuksHeaderLoad, "Header load");
+ RUN_(LuksHeaderRestore, "LUKS header restore");
+ RUN_(LuksHeaderBackup, "LUKS header backup");
+ RUN_(ResizeDeviceLuks, "LUKS device resize");
+ RUN_(UseLuksDevice, "Use pre-formated LUKS device");
+ RUN_(SuspendDevice, "Suspend/Resume");
+ RUN_(UseTempVolumes, "Format and use temporary encrypted device");
+ RUN_(CallbacksTest, "API callbacks");
+ RUN_(VerityTest, "DM verity");
+ RUN_(TcryptTest, "Tcrypt API");
+ RUN_(IntegrityTest, "Integrity API");
+ RUN_(ResizeIntegrity, "Integrity raw resize");
+ RUN_(ResizeIntegrityWithKey, "Integrity raw resize with key");
+ RUN_(WipeTest, "Wipe device");
+ RUN_(LuksKeyslotAdd, "Adding keyslot via new API");
+ RUN_(VolumeKeyGet, "Getting volume key via keyslot context API");
+
+ _cleanup();
+ return 0;
+}
diff --git a/tests/api_test.h b/tests/api_test.h
new file mode 100644
index 0000000..14efead
--- /dev/null
+++ b/tests/api_test.h
@@ -0,0 +1,165 @@
+/*
+ * cryptsetup library API check functions
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ * Copyright (C) 2016-2023 Ondrej Kozina
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef API_TEST_H
+#define API_TEST_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+extern char *THE_LOOP_DEV;
+extern int _debug;
+extern int global_lines;
+extern int _quit;
+extern int _verbose;
+extern uint64_t t_dev_offset;
+
+int t_device_size(const char *device, uint64_t *size);
+int t_dm_check_versions(void);
+int t_dm_crypt_keyring_support(void);
+int t_dm_crypt_cpu_switch_support(void);
+int t_dm_crypt_discard_support(void);
+int t_dm_integrity_resize_support(void);
+int t_dm_integrity_recalculate_support(void);
+int t_dm_capi_string_supported(void);
+int t_set_readahead(const char *device, unsigned value);
+
+int fips_mode(void);
+
+int create_dmdevice_over_loop(const char *dm_name, const uint64_t size);
+
+int get_key_dm(const char *name, char *buffer, unsigned int buffer_size);
+
+int prepare_keyfile(const char *name, const char *passphrase, int size);
+
+int crypt_decode_key(char *key, const char *hex, unsigned int size);
+
+void global_log_callback(int level, const char *msg, void *usrptr);
+
+void reset_log(void);
+
+int _system(const char *command, int warn);
+
+void register_cleanup(void (*cleanup)(void));
+
+void check_ok(int status, int line, const char *func);
+void check_ok_return(int status, int line, const char *func);
+void check_ko(int status, int line, const char *func);
+void check_equal(int line, const char *func, int64_t x, int64_t y);
+void check_ge_equal(int line, const char *func, int64_t x, int64_t y);
+void check_null(int line, const char *func, const void *x);
+void check_notnull(int line, const char *func, const void *x);
+void xlog(const char *msg, const char *tst, const char *func, int line, const char *txt);
+
+/* crypt_device context must be "cd" to parse error properly here */
+#define OK_(x) do { xlog("(success)", #x, __FUNCTION__, __LINE__, NULL); \
+ check_ok((x), __LINE__, __FUNCTION__); \
+ } while(0)
+#define NOTFAIL_(x, y) do { xlog("(notfail)", #x, __FUNCTION__, __LINE__, y); \
+ check_ok_return((x), __LINE__, __FUNCTION__); \
+ } while(0)
+#define FAIL_(x, y) do { xlog("(fail) ", #x, __FUNCTION__, __LINE__, y); \
+ check_ko((x), __LINE__, __FUNCTION__); \
+ } while(0)
+#define EQ_(x, y) do { int64_t _x = (x), _y = (y); \
+ xlog("(equal) ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
+ if (_x != _y) check_equal(__LINE__, __FUNCTION__, _x, _y); \
+ } while(0)
+#define GE_(x, y) do { int64_t _x = (x), _y = (y); \
+ xlog("(g_equal)", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
+ if (_x < _y) check_ge_equal(__LINE__, __FUNCTION__, _x, _y); \
+ } while(0)
+#define NULL_(x) do { xlog("(null) ", #x, __FUNCTION__, __LINE__, NULL); \
+ check_null(__LINE__, __FUNCTION__, (x)); \
+ } while(0)
+#define NOTNULL_(x) do { xlog("(notnull)", #x, __FUNCTION__, __LINE__, NULL); \
+ check_notnull(__LINE__, __FUNCTION__, (x)); \
+ } while(0)
+#define RUN_(x, y) do { reset_log(); \
+ printf("%s: %s\n", #x, (y)); x(); \
+ } while (0)
+
+#define CRYPT_FREE(x) do { crypt_free(x); x = NULL; } while (0)
+
+/* to silent clang -Wcast-align when working with byte arrays */
+#define VOIDP_CAST(x) (x)(void*)
+
+#define DMDIR "/dev/mapper/"
+
+#define TST_SECTOR_SHIFT 9L
+#define TST_SECTOR_SIZE 512
+#define TST_LOOP_FILE_SIZE (((1 << 20) * 100) >> TST_SECTOR_SHIFT)
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define DIV_ROUND_UP_MODULO(n,d) (DIV_ROUND_UP(n,d)*(d))
+
+/* Device mapper backend - kernel support flags */
+#define T_DM_KEY_WIPE_SUPPORTED (1 << 0) /* key wipe message */
+#define T_DM_LMK_SUPPORTED (1 << 1) /* lmk mode */
+#define T_DM_SECURE_SUPPORTED (1 << 2) /* wipe (secure) buffer flag */
+#define T_DM_PLAIN64_SUPPORTED (1 << 3) /* plain64 IV */
+#define T_DM_DISCARDS_SUPPORTED (1 << 4) /* discards/TRIM option is supported */
+#define T_DM_VERITY_SUPPORTED (1 << 5) /* dm-verity target supported */
+#define T_DM_TCW_SUPPORTED (1 << 6) /* tcw (TCRYPT CBC with whitening) */
+#define T_DM_SAME_CPU_CRYPT_SUPPORTED (1 << 7) /* same_cpu_crypt */
+#define T_DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED (1 << 8) /* submit_from_crypt_cpus */
+#define T_DM_VERITY_ON_CORRUPTION_SUPPORTED (1 << 9) /* ignore/restart_on_corruption, ignore_zero_block */
+#define T_DM_VERITY_FEC_SUPPORTED (1 << 10) /* Forward Error Correction (FEC) */
+#define T_DM_KERNEL_KEYRING_SUPPORTED (1 << 11) /* dm-crypt allows loading kernel keyring keys */
+#define T_DM_INTEGRITY_SUPPORTED (1 << 12) /* dm-integrity target supported */
+#define T_DM_SECTOR_SIZE_SUPPORTED (1 << 13) /* support for sector size setting in dm-crypt/dm-integrity */
+#define T_DM_CAPI_STRING_SUPPORTED (1 << 14) /* support for cryptoapi format cipher definition */
+#define T_DM_DEFERRED_SUPPORTED (1 << 15) /* deferred removal of device */
+#define T_DM_INTEGRITY_RECALC_SUPPORTED (1 << 16) /* dm-integrity automatic recalculation supported */
+#define T_DM_INTEGRITY_BITMAP_SUPPORTED (1 << 17) /* dm-integrity bitmap mode supported */
+#define T_DM_GET_TARGET_VERSION_SUPPORTED (1 << 18) /* dm DM_GET_TARGET version ioctl supported */
+#define T_DM_INTEGRITY_FIX_PADDING_SUPPORTED (1 << 19) /* supports the parameter fix_padding that fixes a bug that caused excessive padding */
+#define T_DM_BITLK_EBOIV_SUPPORTED (1 << 20) /* EBOIV for BITLK supported */
+#define T_DM_BITLK_ELEPHANT_SUPPORTED (1 << 21) /* Elephant diffuser for BITLK supported */
+#define T_DM_VERITY_SIGNATURE_SUPPORTED (1 << 22) /* Verity option root_hash_sig_key_desc supported */
+#define T_DM_INTEGRITY_DISCARDS_SUPPORTED (1 << 23) /* dm-integrity discards/TRIM option is supported */
+#define T_DM_INTEGRITY_RESIZE_SUPPORTED (1 << 23) /* dm-integrity resize of the integrity device supported (introduced in the same version as discards)*/
+#define T_DM_VERITY_PANIC_CORRUPTION_SUPPORTED (1 << 24) /* dm-verity panic on corruption */
+#define T_DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt suppot for bypassing workqueues */
+#define T_DM_INTEGRITY_FIX_HMAC_SUPPORTED (1 << 26) /* hmac covers also superblock */
+#define T_DM_INTEGRITY_RESET_RECALC_SUPPORTED (1 << 27) /* dm-integrity automatic recalculation supported */
+#define T_DM_VERITY_TASKLETS_SUPPORTED (1 << 28) /* dm-verity tasklets supported */
+
+/* loop helpers */
+int loop_device(const char *loop);
+int loop_attach(char **loop, const char *file, int offset,
+ int autoclear, int *readonly);
+int loop_detach(const char *loop);
+
+int t_device_size_by_devno(dev_t devno, uint64_t *retval);
+int t_get_devno(const char *dev, dev_t *devno);
+
+typedef enum { ERR_RD = 0, ERR_WR, ERR_RW, ERR_REMOVE } error_io_info;
+
+int dmdevice_error_io(const char *dm_name,
+ const char *dm_device,
+ const char *error_device,
+ uint64_t data_offset,
+ uint64_t offset,
+ uint64_t length,
+ error_io_info ei);
+
+#endif
diff --git a/tests/bitlk-compat-test b/tests/bitlk-compat-test
new file mode 100755
index 0000000..8559e06
--- /dev/null
+++ b/tests/bitlk-compat-test
@@ -0,0 +1,200 @@
+#!/bin/bash
+
+# check bitlk images parsing
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+TST_DIR=bitlk-images
+MAP=bitlktst
+DUMP_VK_FILE=bitlk-test-vk
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+[ -z "$srcdir" ] && srcdir="."
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
+ rm -rf $TST_DIR
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo " [FAILED]"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "Test skipped."
+ remove_mapping
+ exit 77
+}
+
+function load_vars()
+{
+ local file=$(echo $1 | sed -e s/^$TST_DIR\\/// | sed -e s/\.img$//)
+ source <(grep = <(grep -A8 "\[$file\]" $TST_DIR/images.conf))
+}
+
+function check_dump()
+{
+ dump=$1
+ file=$2
+
+ # load variables for this image from config file
+ load_vars $file
+
+ # volume size
+ dump_size=$(echo "$dump" | grep "Volume size:" | cut -d: -f2 | tr -d "\t\n ")
+ [ "$dump_size" = "104857600[bytes]" -o "$dump_size" = "134217728[bytes]" ] || fail " volume size check from dump failed."
+
+ # description
+ dump_desc=$(echo "$dump" | grep Description: | cut -d: -f2 | tr -d "\t\n ")
+ [ "${dump_desc:0:7}" = "DESKTOP" -o "${dump_desc:0:3}" = "WIN" ] || fail " Description check from dump failed."
+
+ # GUID
+ dump_guid=$(echo "$dump" | grep Version -A 1 | tail -1 | cut -d: -f2 | tr -d "\t\n ")
+ [ ! -z "$GUID" -a "$dump_guid" = "$GUID" ] || fail " GUID check from dump failed."
+
+ # cipher
+ dump_cipher=$(echo "$dump" | grep "Cipher name" | cut -d: -f2 | tr -d "\t\n ")
+ dump_mode=$(echo "$dump" | grep "Cipher mode" | cut -d: -f2 | tr -d "\t\n ")
+ cipher=$(echo "$dump_cipher-$dump_mode")
+ [ ! -z "$CIPHER" -a "$cipher" = "$CIPHER" ] || fail " cipher check from dump failed."
+
+ if echo "$file" | grep -q -e "smart-card"; then
+ # smart card protected VMK GUID
+ dump_sc_vmk=$(echo "$dump" | grep "VMK protected with smart card" -B 1 | head -1 | cut -d: -f2 | tr -d "\t ")
+ [ ! -z "$SC_VMK_GUID" -a "$dump_sc_vmk" = "$SC_VMK_GUID" ] || fail " smart card protected VMK GUID check from dump failed."
+ elif echo "$file" | grep -q -e "startup-key"; then
+ # startup key protected VMK GUID
+ dump_sk_vmk=$(echo "$dump" | grep "VMK protected with startup key" -B 1 | head -1 | cut -d: -f2 | tr -d "\t ")
+ [ ! -z "$SK_VMK_GUID" -a "$dump_sk_vmk" = "$SK_VMK_GUID" ] || fail " startup key protected VMK GUID check from dump failed."
+ else
+ # password protected VMK GUID
+ dump_pw_vmk=$(echo "$dump" | grep "VMK protected with passphrase" -B 1 | head -1 | cut -d: -f2 | tr -d "\t ")
+ [ ! -z "$PW_VMK_GUID" -a "$dump_pw_vmk" = "$PW_VMK_GUID" ] || fail " password protected VMK GUID check from dump failed."
+ fi
+
+ # recovery password protected VMK GUID
+ dump_rp_vmk=$(echo "$dump" | grep "VMK protected with recovery passphrase" -B 1 | head -1 | cut -d: -f2 | tr -d "\t ")
+ [ ! -z "$RP_VMK_GUID" -a "$dump_rp_vmk" = "$RP_VMK_GUID" ] || fail " recovery password protected VMK GUID check from dump failed."
+
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+export LANG=C
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ ! -d $TST_DIR ] && tar xJSf $srcdir/bitlk-images.tar.xz --no-same-owner 2>/dev/null || skip "Incompatible tar."
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+echo "HEADER CHECK"
+for file in $(ls $TST_DIR/bitlk-*) ; do
+ echo -n " $file"
+ out=$($CRYPTSETUP bitlkDump $file)
+ check_dump "$out" "$file"
+ echo " [OK]"
+done
+
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run activation part of test, test skipped."
+ remove_mapping
+ exit 0
+fi
+
+echo "ACTIVATION FS UUID CHECK"
+for file in $(ls $TST_DIR/bitlk-*) ; do
+ # load variables for this image from config file
+ load_vars $file
+
+ # test with both passphrase and recovery passphrase
+ for PASSPHRASE in $PW $RP ; do
+ echo -n " $file"
+ echo $PASSPHRASE | $CRYPTSETUP bitlkOpen -r $file --test-passphrase >/dev/null 2>&1
+ ret=$?
+ [ $ret -eq 1 ] && echo " [N/A]" && continue
+ echo $PASSPHRASE | $CRYPTSETUP bitlkOpen -r $file $MAP >/dev/null 2>&1
+ ret=$?
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc-elephant" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "clearkey" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "eow" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "-4k.img" ) && echo " [N/A]" && continue
+ [ $ret -eq 0 ] || fail " failed to open $file ($ret)"
+ $CRYPTSETUP status $MAP >/dev/null || fail
+ $CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
+ uuid=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
+ sha256sum=$(sha256sum /dev/mapper/$MAP | cut -d" " -f1)
+ $CRYPTSETUP remove $MAP || fail
+ [ "$uuid" = "$UUID" ] || fail " UUID check failed."
+ [ "$sha256sum" = "$SHA256SUM" ] || fail " SHA256 sum check failed."
+ echo " [OK]"
+ done
+
+ # test with volume key
+ rm -f $DUMP_VK_FILE >/dev/null 2>&1
+ echo -n " $file"
+ echo $PASSPHRASE | $CRYPTSETUP bitlkDump -r $file --dump-volume-key --volume-key-file $DUMP_VK_FILE >/dev/null 2>&1
+ ret=$?
+ [ $ret -eq 0 ] || fail " failed to dump volume key"
+ $CRYPTSETUP bitlkOpen -r $file $MAP --volume-key-file $DUMP_VK_FILE >/dev/null 2>&1
+ ret=$?
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc-elephant" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "clearkey" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "eow" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$file" | grep -q -e "-4k.img" ) && echo " [N/A]" && continue
+ [ $ret -eq 0 ] || fail " failed to open $file using volume key ($ret)"
+ $CRYPTSETUP status $MAP >/dev/null || fail
+ $CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
+ uuid=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
+ sha256sum=$(sha256sum /dev/mapper/$MAP | cut -d" " -f1)
+ $CRYPTSETUP remove $MAP || fail
+ [ "$uuid" = "$UUID" ] || fail " UUID check failed."
+ [ "$sha256sum" = "$SHA256SUM" ] || fail " SHA256 sum check failed."
+ echo " [OK]"
+ rm -f $DUMP_VK_FILE >/dev/null 2>&1
+
+ # startup key test -- we need to use BEK file from the archive
+ if echo "$file" | grep -q -e "startup-key"; then
+ echo -n " $file"
+ bek_file=$(echo $SK_VMK_GUID.BEK | tr /a-z/ /A-Z/)
+ $CRYPTSETUP bitlkOpen -r $file --test-passphrase --key-file $TST_DIR/$bek_file
+ ret=$?
+ [ $ret -eq 1 ] && echo " [N/A]" && continue
+ $CRYPTSETUP bitlkOpen -r $file $MAP --key-file $TST_DIR/$bek_file >/dev/null 2>&1
+ ret=$?
+ [ $ret -eq 0 ] || fail " failed to open $file ($ret)"
+ $CRYPTSETUP status $MAP >/dev/null || fail
+ $CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
+ uuid=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
+ sha256sum=$(sha256sum /dev/mapper/$MAP | cut -d" " -f1)
+ $CRYPTSETUP remove $MAP || fail
+ [ "$uuid" = "$UUID" ] || fail " UUID check failed."
+ [ "$sha256sum" = "$SHA256SUM" ] || fail " SHA256 sum check failed."
+ echo " [OK]"
+
+ fi
+done
+
+remove_mapping
+exit 0
diff --git a/tests/bitlk-images.tar.xz b/tests/bitlk-images.tar.xz
new file mode 100644
index 0000000..845e9de
--- /dev/null
+++ b/tests/bitlk-images.tar.xz
Binary files differ
diff --git a/tests/blkid-luks2-pv.img.xz b/tests/blkid-luks2-pv.img.xz
new file mode 100644
index 0000000..c9d0e57
--- /dev/null
+++ b/tests/blkid-luks2-pv.img.xz
Binary files differ
diff --git a/tests/blockwise-compat-test b/tests/blockwise-compat-test
new file mode 100755
index 0000000..11db493
--- /dev/null
+++ b/tests/blockwise-compat-test
@@ -0,0 +1,379 @@
+#!/bin/bash
+
+# set _FORCE_LOCAL environment variable to run blockwise unit tests even on local
+# nfs. Some tests will fail because nfs is eager to write for example 4095 bytes
+# in O_DIRECT mode.
+
+BW_UNIT=./unit-utils-io
+STRACE=strace
+MNT_DIR=./mnt_bwunit
+LOCAL_FILE=./blockwise_localfile
+
+# $1 path to scsi debug bdev
+scsi_debug_teardown() {
+ local _tries=15;
+
+ while [ -b "$1" -a $_tries -gt 0 ]; do
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -b "$1" ]; then
+ sleep .1
+ _tries=$((_tries-1))
+ fi
+ done
+
+ test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
+}
+
+cleanup() {
+ if [ -d "$MNT_DIR" ] ; then
+ umount -f $MNT_DIR 2>/dev/null
+ rmdir $MNT_DIR 2>/dev/null
+ fi
+ rm -f $LOCAL_FILE 2> /dev/null
+ scsi_debug_teardown "$DEV" || exit 100
+}
+
+fail()
+{
+ if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
+ cleanup
+ exit 100
+}
+
+fail_count()
+{
+ echo "$MSG[FAIL]"
+ FAILS=$((FAILS+1))
+}
+
+warn_count()
+{
+ echo "$MSG[WARNING]"
+ WARNS=$((WARNS+1))
+}
+
+skip()
+{
+ echo "TEST SKIPPED: $1"
+ cleanup
+ exit 77
+}
+
+add_device() {
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -d /sys/module/scsi_debug ] ; then
+ skip "Cannot use scsi_debug module (in use or compiled-in)."
+ fi
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ skip "This kernel seems to not support proper scsi_debug module."
+ fi
+ grep -q scsi_debug /sys/block/*/device/model || sleep 2
+ DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ DEV="/dev/$DEV"
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+falloc() {
+ dd if=/dev/zero of=$2 bs=1M count=$1 2> /dev/null
+}
+
+run_all_in_fs() {
+ for file in $(ls img_fs_*.img.xz) ; do
+ echo "Run tests in $file put on top block device."
+ xz -d -c $file | dd of=$DEV bs=1M 2>/dev/null || fail "bad image"
+ [ ! -d $MNT_DIR ] && mkdir $MNT_DIR
+ mount $DEV $MNT_DIR
+ if [ $? -ne 0 ]; then
+ echo "Mounting image $file failed, skipped."
+ continue;
+ fi
+ rm -rf $MNT_DIR/* 2>/dev/null
+ local tfile=$MNT_DIR/bwunit_tstfile
+ falloc $DEVSIZEMB $tfile || fail "enospc?"
+ local iobsize=$(stat -c "%o" $tfile)
+ test -n "$iobsize" -a $iobsize -gt 0 || fail
+ local oldbsize=$BSIZE
+ BSIZE=$iobsize
+ run_all $tfile
+ BSIZE=$oldbsize
+ umount $MNT_DIR
+ done
+}
+
+trunc_file() {
+ test $1 -eq 0 || truncate -c -s $1 $2 2>/dev/null || dd if=/dev/zero of=$2 bs=$1 count=1 2>/dev/null || fail "Failed to truncate test file $2."
+}
+
+RUN() {
+ local _res=$1
+ shift
+ local _dev=$1
+ shift
+ local _fn=$1
+ shift
+ local _type="bdev"
+ local _fsize=0
+
+ test -b $_dev || {
+ _type="file"
+ _fsize=$(stat -c "%s" $_dev)
+ }
+
+ case "$_res" in
+ P)
+ MSG="Testing $_fn on $_type with params $@ [expecting TRUE]..."
+ $BW_UNIT $_dev $_fn $@
+ if [ $? -ne 0 ]; then
+ if [ $_type = "file" ]; then
+ warn_count
+ else
+ fail_count
+ fi
+ trunc_file $_fsize $_dev
+ test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-pass.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
+ else
+ MSG="$MSG[OK]"
+ fi
+ ;;
+ F)
+ MSG="Testing $_fn on $_type with params $@ [expecting FALSE]..."
+ $BW_UNIT $_dev $_fn $@ 2> /dev/null
+ if [ $? -eq 0 ]; then
+ if [ $_type = "file" ]; then
+ warn_count
+ else
+ fail_count
+ fi
+ trunc_file $_fsize $_dev
+ test -z "$STRACE" || $STRACE -o ./$BW_UNIT-fail-$FAILS-should-fail.log $BW_UNIT $_dev $_fn $@ 2> /dev/null
+ else
+ MSG="$MSG[OK]"
+ fi
+ ;;
+ *)
+ fail "Internal test error"
+ ;;
+ esac
+
+ trunc_file $_fsize $_dev
+}
+
+run_all() {
+ if [ -b "$1" ]; then
+ BD_FAIL="F"
+ else
+ BD_FAIL="P"
+ fi
+
+ # buffer io support only blocksize aligned ios
+ # device/file fn_name length
+ RUN "P" $1 read_buffer $BSIZE
+ RUN "P" $1 read_buffer $((2*BSIZE))
+ RUN "F" $1 read_buffer $((BSIZE-1))
+ RUN "F" $1 read_buffer $((BSIZE+1))
+ RUN "P" $1 read_buffer 0
+
+ RUN "P" $1 write_buffer $BSIZE
+ RUN "P" $1 write_buffer $((2*BSIZE))
+
+ RUN "F" $1 write_buffer $((BSIZE-1))
+ RUN "F" $1 write_buffer $((BSIZE+1))
+ RUN "F" $1 write_buffer 0
+
+ # basic blockwise functions
+ # device/file fn_name length bsize
+ RUN "P" $1 read_blockwise 0 $BSIZE
+ RUN "P" $1 read_blockwise $((BSIZE)) $BSIZE
+ RUN "P" $1 read_blockwise $((BSIZE-1)) $BSIZE
+ RUN "P" $1 read_blockwise $((BSIZE+1)) $BSIZE
+ RUN "P" $1 read_blockwise $((DEVSIZE)) $BSIZE
+ RUN "P" $1 read_blockwise $((DEVSIZE-1)) $BSIZE
+ RUN "F" $1 read_blockwise $((DEVSIZE+1)) $BSIZE
+
+ RUN "P" $1 write_blockwise 0 $BSIZE
+ RUN "P" $1 write_blockwise $((BSIZE)) $BSIZE
+ RUN "P" $1 write_blockwise $((BSIZE-1)) $BSIZE
+ RUN "P" $1 write_blockwise $((BSIZE+1)) $BSIZE
+ RUN "P" $1 write_blockwise $((DEVSIZE)) $BSIZE
+ RUN "P" $1 write_blockwise $((DEVSIZE-1)) $BSIZE
+ RUN "$BD_FAIL" $1 write_blockwise $((DEVSIZE+1)) $BSIZE
+
+ # seek variant blockwise functions
+ # device/file fn_name length bsize offset
+ RUN "P" $1 read_lseek_blockwise 0 $BSIZE 0
+ RUN "P" $1 read_lseek_blockwise 0 $BSIZE 1
+ RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE))
+ # length = 0 is significant here
+ RUN "P" $1 read_lseek_blockwise 0 $BSIZE $((DEVSIZE+1))
+
+ # beginning of device
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE 0
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE 1
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE/2))
+
+ # somewhere in the 'middle'
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $BSIZE
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+1))
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
+
+ # cross-sector tests
+ RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
+
+ # including one whole sector
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
+ RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
+ RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
+ RUN "P" $1 read_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
+
+ # hiting exactly the sector boundary
+ RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE 1
+ RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
+
+ # device end
+ RUN "P" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
+ RUN "P" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
+
+ # this must fail on both device and file
+ RUN "F" $1 read_lseek_blockwise 1 $BSIZE $((DEVSIZE))
+ RUN "F" $1 read_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
+ RUN "F" $1 read_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
+ RUN "F" $1 read_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
+
+ RUN "P" $1 write_lseek_blockwise 0 $BSIZE 0
+ # TODO: this may pass but must not write a byte (write(0) is undefined).
+ # Test it with underlying dm-error or phony read/write syscalls.
+ # Skipping read is optimization.
+ # HINT: currently it performs useless write and read as well
+ RUN "P" $1 write_lseek_blockwise 0 $BSIZE 1
+ RUN "P" $1 write_lseek_blockwise 0 $BSIZE $BSIZE
+
+ # beginning of device
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE 0
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE 1
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE/2))
+
+ # somewhere in the 'middle'
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $BSIZE
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+1))
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((2*BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((BSIZE+BSIZE/2-1))
+
+ # cross-sector tests
+ RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise 2 $BSIZE $((2*BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((2*BSIZE-1))
+
+ # including one whole sector
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE))
+ RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
+ RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+2)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((2*BSIZE)) $BSIZE $((BSIZE+1))
+ RUN "P" $1 write_lseek_blockwise $((3*BSIZE-2)) $BSIZE $((BSIZE+1))
+
+ # hiting exactly the sector boundary
+ RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE 1
+ RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((BSIZE+1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((BSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((2*BSIZE-1))
+
+ # device end
+ RUN "P" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE-1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+1))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE))
+ RUN "P" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE-1))
+
+ # this must fail on device, but pass on file (which is unfortunate and maybe design mistake)
+ RUN "$BD_FAIL" $1 write_lseek_blockwise 1 $BSIZE $((DEVSIZE))
+ RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE-1)) $BSIZE $((DEVSIZE-BSIZE+2))
+ RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE)) $BSIZE $((DEVSIZE-BSIZE+1))
+ RUN "$BD_FAIL" $1 write_lseek_blockwise $((BSIZE+1)) $BSIZE $((DEVSIZE-BSIZE))
+}
+
+command -v $STRACE >/dev/null || unset STRACE
+test -x $BW_UNIT || skip "Run \"make `basename $BW_UNIT`\" first"
+
+FAILS=0
+WARNS=0
+DEVSIZEMB=2
+DEVSIZE=$((DEVSIZEMB*1024*1024))
+
+PAGE_SIZE=$(getconf PAGE_SIZE)
+echo "System PAGE_SIZE=$PAGE_SIZE"
+
+echo "Run tests in local filesystem"
+falloc $DEVSIZEMB $LOCAL_FILE || fail "Failed to create file in local filesystem."
+BSIZE=$(stat -c "%o" $LOCAL_FILE)
+if [ $BSIZE -gt $((512*1024)) ]; then
+ echo "Detected file block size: $BSIZE bytes"
+ echo "Tuning it down to system page size ($PAGE_SIZE bytes)"
+ BSIZE=$PAGE_SIZE
+fi
+run_all $LOCAL_FILE
+
+[ $(id -u) -eq 0 ] || {
+ echo "WARNING: You must be root to run remaining tests."
+ test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
+ cleanup
+ exit 0
+}
+
+DEVBSIZE=512
+BSIZE=$DEVBSIZE
+EXP=0
+DEVSIZEMBIMG=32
+
+echo "# Create classic 512B drive"
+echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
+add_device dev_size_mb=$DEVSIZEMB sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
+run_all $DEV
+cleanup
+add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
+run_all_in_fs
+cleanup
+
+EXP=3
+echo "# Create desktop-class 4K drive"
+echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
+add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
+run_all $DEV
+BSIZE=$((DEVBSIZE*(1<<EXP)))
+run_all $DEV
+cleanup
+
+add_device dev_size_mb=$DEVSIZEMBIMG physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
+run_all_in_fs
+cleanup
+
+DEVBSIZE=4096
+BSIZE=$DEVBSIZE
+EXP=0
+echo "# Create enterprise-class 4K drive"
+echo "# (logical_block_size=$DEVBSIZE, physical_block_size=$((DEVBSIZE*(1<<EXP))))"
+add_device dev_size_mb=$DEVSIZEMB physblk_exp=$EXP sector_size=$DEVBSIZE num_tgts=1
+run_all $DEV
+cleanup
+add_device dev_size_mb=$DEVSIZEMBIMG sector_size=$DEVBSIZE physblk_exp=$EXP num_tgts=1
+run_all_in_fs
+cleanup
+
+test $WARNS -eq 0 || echo "(WARNING: $WARNS suspicious result(s) in total)"
+test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
diff --git a/tests/compat-args-test b/tests/compat-args-test
new file mode 100755
index 0000000..c41e942
--- /dev/null
+++ b/tests/compat-args-test
@@ -0,0 +1,299 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+TEST_UUID="12345678-1234-1234-1234-123456789abc"
+
+TFILE=test-args.out
+
+function cleanup()
+{
+ rm -f $TFILE 2> /dev/null
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "Test skipped."
+ cleanup
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function xxx()
+{
+ $CRYPTSETUP --test-args $@ > $TFILE 2>&1
+ local ret=$?
+
+ grep -q -e ": unknown option\|Argument <action> missing" $TFILE && {
+ echo "'$CRYPTSETUP --test-args $@' command:"
+ cat $TFILE
+ fail "Probably typo in test"
+ }
+ test $ret -ne 0 || fail
+}
+
+function exp_fail()
+{
+ # xxx $@
+ $CRYPTSETUP --test-args $@ 2>/dev/null && fail
+}
+
+function exp_pass()
+{
+ $CRYPTSETUP --test-args $@ >/dev/null || fail
+}
+
+export LANG=C
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+# initial test constructed according to current cryptsetup content
+echo "[1] Current state"
+exp_fail resize NAME --test-passphrase
+exp_fail close NAME --test-passphrase
+exp_pass open DEV NAME --test-passphrase --type bitlk
+exp_pass open DEV NAME --test-passphrase --type luks
+exp_pass open DEV NAME --test-passphrase --type luks1
+exp_pass open DEV NAME --test-passphrase --type luks2
+exp_fail open DEV NAME --test-passphrase --type plain
+
+exp_fail open DEV NAME --deferred
+exp_pass close NAME --deferred
+
+exp_pass open DEV NAME --type plain --shared
+exp_fail open DEV NAME --type luks1 --shared
+exp_fail close NAME --shared
+
+exp_pass open DEV NAME --allow-discards
+exp_fail close NAME --allow-discards
+
+exp_fail close NAME --persistent
+exp_pass open DEV NAME --persistent
+exp_fail open DEV NAME --persistent --test-passphrase
+
+exp_fail luksFormat DEV --serialize-memory-hard-pbkdf
+exp_pass open DEV NAME --serialize-memory-hard-pbkdf
+
+exp_pass reencrypt DEV --key-size 32
+exp_fail reencrypt DEV --key-size 31
+exp_fail reencrypt DEV --key-size -32
+exp_pass luksFormat DEV --key-size 32
+exp_fail luksFormat DEV --key-size 31
+exp_fail luksFormat DEV --key-size -32
+exp_pass open DEV NAME --key-size 32 # --type plain -c aes-xts-plain64
+exp_fail open DEV NAME --key-size 31 # --type plain -c aes-xts-plain64
+exp_pass benchmark --key-size 32
+exp_fail benchmark --key-size 31
+exp_pass luksAddKey DEV --key-size 32 # --unbound
+exp_fail luksAddKey DEV --key-size 31 # --unbound
+
+exp_fail close NAME --key-size 32
+exp_fail luksUUID DEV --key-size 32
+
+# bug
+# exp_fail luksFormat DEV --type luks1 --integrity hmac-sha256
+exp_pass luksFormat DEV --type luks2 --integrity hmac-sha256
+exp_fail open DEV NAME --integrity hmac-sha256
+
+exp_pass luksFormat DEV --type luks2 --integrity hmac-sha256 --integrity-no-wipe
+exp_fail luksFormat DEV --type luks2 --integrity-no-wipe
+# bug
+# exp_fail luksFormat DEV --type luks1 --integrity hmac-sha256 --integrity-no-wipe
+exp_fail open DEV NAME --integrity-no-wipe
+exp_fail open DEV NAME --integrity-no-wipe --integrity hmac-sha256
+
+exp_pass luksFormat --label L --subsystem S DEV # --type luks2
+exp_pass luksFormat --label L DEV # --type luks2
+exp_pass luksFormat --subsystem S DEV # --type luks2
+exp_pass config --label L --subsystem S DEV
+exp_pass config --label L DEV
+exp_pass config --subsystem S DEV
+# bug
+#exp_fail luksFormat --label L --subsystem S DEV --type luks1
+#exp_fail luksFormat --label L DEV --type luks1
+#exp_fail luksFormat --subsystem S DEV --type luks1
+exp_fail open DEV NAME --label L --subsystem S
+exp_fail open DEV NAME --label L
+exp_fail open DEV NAME --subsystem S
+
+exp_fail luksFormat DEV -S-2
+# bug
+# exp_fail luksFormat DEV -S-1
+
+# prob. many bug: accepts --[new-]keyfile-size w/o --[new-]key-file
+exp_pass luksFormat DEV --keyfile-size 42 --key-file F
+exp_fail luksFormat DEV --keyfile-size -1 --key-file F
+# bug (is it? e.g. empty passphrase)
+# exp_fail luksFormat DEV --keyfile-size 0
+exp_pass luksAddKey DEV --keyfile-size 42 --key-file F --new-keyfile-size 42 NF
+exp_fail luksAddKey DEV --new-keyfile-size -42 NF
+exp_fail luksAddKey DEV --keyfile-size 42 --key-file F --new-keyfile-size -42 NF
+exp_fail luksFormat DEV --keyfile-size -1 --key-file F
+# bug (is it? e.g. empty passphrase)
+# exp_fail luksFormat DEV --keyfile-size 0
+
+exp_fail open DEV NAME --key-file F0 --key-file F1
+exp_pass open DEV NAME --key-file F0 --key-file F1 --type tcrypt
+
+# why? (luksAddKey fail)
+exp_fail luksAddKey DEV --use-random
+exp_fail luksAddKey DEV --use-urandom
+exp_fail luksAddKey DEV --use-urandom --use-random
+exp_fail luksFormat DEV --use-urandom --use-random
+exp_pass luksFormat DEV --use-random
+exp_pass luksFormat DEV --use-urandom
+
+exp_fail open DEV NAME --uuid $TEST_UUID
+exp_pass luksFormat DEV --uuid $TEST_UUID
+exp_pass luksUUID DEV --uuid $TEST_UUID
+
+exp_fail open DEV NAME --align-payload 8192
+exp_fail open DEV NAME --align-payload 8292 --type plain
+exp_pass luksFormat DEV --align-payload 8192
+exp_fail luksFormat DEV --align-payload 8192 --offset 16384
+exp_fail luksFormat DEV --align-payload 8192 --offset 8192
+
+exp_fail resize NAME --luks2-metadata-size 16k
+exp_fail resize NAME --luks2-keyslots-size 16m
+exp_pass luksFormat DEV --luks2-keyslots-size 16m
+exp_pass luksFormat DEV --luks2-metadata-size 16k
+exp_pass reencrypt DEV --luks2-keyslots-size 16m
+exp_pass reencrypt DEV --luks2-metadata-size 16k
+
+exp_fail luksFormat DEV --skip 8192
+exp_fail open DEV NAME --skip 8192
+exp_pass open DEV NAME --skip 8192 --type plain
+exp_pass open DEV NAME --skip 8192 --type loopaes
+
+exp_fail resize NAME --offset 8292
+exp_pass luksFormat DEV --offset 16384
+exp_fail open DEV NAME --offset 16384
+exp_pass open DEV NAME --offset 16384 --type plain
+exp_pass open DEV NAME --offset 16384 --type loopaes
+
+exp_fail open DEV NAME --tcrypt-hidden
+exp_fail open DEV NAME --tcrypt-system
+exp_fail open DEV NAME --tcrypt-backup
+# bug
+# exp_fail open DEV NAME --tcrypt-hidden --tcrypt-system --tcrypt-backup --type tcrypt
+exp_pass open DEV NAME --tcrypt-hidden --type tcrypt
+exp_pass open DEV NAME --tcrypt-backup --type tcrypt
+exp_pass open DEV NAME --tcrypt-system --type tcrypt
+exp_pass tcryptDump DEV NAME --tcrypt-hidden --type tcrypt
+exp_pass tcryptDump DEV NAME --tcrypt-backup --type tcrypt
+exp_pass tcryptDump DEV NAME --tcrypt-system --type tcrypt
+exp_fail tcryptDump DEV NAME --allow-discards --tcrypt-hidden --type tcrypt
+
+# bug
+# exp_fail close NAME --type tcrypt --veracrypt
+exp_fail open DEV NAME --veracrypt
+exp_pass open DEV NAME --type tcrypt --veracrypt
+exp_pass open DEV NAME --type tcrypt --veracrypt --veracrypt-pim 1
+exp_fail open DEV NAME --type tcrypt --veracrypt --veracrypt-pim -2
+exp_fail open DEV NAME --type tcrypt --disable-veracrypt --veracrypt-pim 1
+exp_fail open DEV NAME --type tcrypt --veracrypt --veracrypt-pim -1
+exp_fail open DEV NAME --type tcrypt --disable-veracrypt --veracrypt-query-pim
+exp_fail open DEV NAME --type tcrypt --disable-veracrypt --veracrypt-query-pim --veracrypt-pim 1
+exp_fail open DEV NAME --disable-veracrypt --veracrypt-query-pim
+
+# bug
+# exp_fail open DEV NAME --priority normal
+exp_fail config DEV --priority normal
+exp_fail config DEV -S1 --priority norma
+exp_pass config DEV -S1 --priority normal
+exp_pass config DEV -S1 --priority ignore
+exp_pass config DEV -S1 --priority prefer
+
+# bug
+# exp_fail open DEV NAME --pbkdf argon2i
+exp_fail luksFormat DEV --pbkdf blah
+exp_pass luksFormat DEV --pbkdf argon2i
+exp_pass luksFormat DEV --pbkdf pbkdf2
+exp_pass luksFormat DEV --pbkdf argon2id
+exp_fail luksFormat DEV --type luks2 --pbkdf-force-iterations 4 -i1
+exp_fail luksFormat DEV --type luks1 --pbkdf-force-iterations 1001 -i1
+
+exp_fail open DEV NAME --sector-size 1024
+exp_pass open DEV NAME --type plain --sector-size 1024
+# bug
+# exp_fail luksFormat DEV --sector-size 0
+exp_fail luksFormat DEV --sector-size 511
+exp_fail luksFormat DEV --sector-size 8192
+exp_pass reencrypt DEV --sector-size 1024
+exp_pass luksFormat DEV --sector-size 1024
+
+exp_fail luksFormat DEV --iv-large-sectors
+exp_fail open DEV --type tcrypt --iv-large-sectors
+exp_fail open DEV --type plain --iv-large-sectors --sector-size 512
+exp_pass open DEV --type plain --iv-large-sectors --sector-size 1024
+
+exp_fail luksAddKey DEV --unbound
+exp_fail luksAddKey DEV --unbound --key-size 0
+exp_pass luksAddKey DEV --unbound --key-size 8
+exp_pass luksDump DEV --unbound -S5
+exp_fail luksDump DEV --unbound
+exp_pass open DEV --unbound --test-passphrase
+exp_pass open DEV --unbound --test-passphrase -S5
+exp_fail open DEV --unbound NAME
+exp_fail open DEV --unbound -S5 NAME
+
+exp_fail resize NAME --refresh
+exp_fail open DEV NAME --test-passphrase --refresh
+exp_pass open DEV NAME --refresh
+exp_pass refresh DEV NAME
+exp_fail refresh DEV NAME --test-passphrase
+
+# bug
+# exp_fail luksFormat DEV --reduce-device-size 64m
+exp_fail reencrypt DEV --reduce-device-size 2G # max 1g
+exp_fail reencrypt DEV --reduce-device-size $((64*1024*1024+1))
+exp_fail reencrypt DEV --reduce-device-size -64m
+exp_pass reencrypt DEV --reduce-device-size 64m
+exp_fail reencrypt DEV --reduce-device-size 64m --device-size 100g
+# bugs
+# exp_fail open DEV --decrypt --header H
+# exp_fail open DEV --encrypt
+# exp_fail open DEV NAME --device-size 32m
+# exp_fail open DEV NAME --size 100
+exp_pass open DEV NAME --device-size 32m --type plain
+exp_fail open DEV NAME --device-size $((32*1024*1024+1)) --type plain
+exp_pass open DEV NAME --size 100 --type plain
+exp_fail open DEV NAME --size 100 --device-size $((512*100)) --type plain
+exp_fail reencrypt DEV --device-size $((32*1024*1024+1))
+exp_pass reencrypt DEV --device-size 32m
+
+exp_fail luksFormat DEV NAME --keyslot-cipher ks
+exp_fail luksFormat DEV NAME --keyslot-key-size 32
+exp_pass luksFormat DEV NAME --keyslot-cipher ks --keyslot-key-size 32
+# bugs
+# exp_fail open DEV NAME --keyslot-cipher ks --keyslot-key-size 32
+# exp_fail luksFormat --type luks1 DEV NAME --keyslot-cipher ks --keyslot-key-size 32
+
+cleanup
+exit 0
diff --git a/tests/compat-test b/tests/compat-test
new file mode 100755
index 0000000..6dc8004
--- /dev/null
+++ b/tests/compat-test
@@ -0,0 +1,1137 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+CRYPTSETUP_RAW=$CRYPTSETUP
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+DIFFER=./differ
+DEV_NAME=dummy
+DEV_NAME2=dummy2
+DEV_NAME3=dummy3
+ORIG_IMG=luks-test-orig
+IMG=luks-test
+IMG10=luks-test-v10
+HEADER_IMG=luks-header
+KEY1=key1
+KEY2=key2
+KEY5=key5
+KEYE=keye
+PWD0="compatkey"
+PWD1="93R4P4pIqAH8"
+PWD2="mymJeD8ivEhE"
+PWD3="ocMakf3fAcQO"
+PWDW="rUkL4RUryBom"
+VK_FILE="compattest_vkfile"
+
+FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+
+LUKS_HEADER="S0-5 S6-7 S8-39 S40-71 S72-103 S104-107 S108-111 R112-131 R132-163 S164-167 S168-207 A0-591"
+KEY_SLOT0="S208-211 S212-215 R216-247 A248-251 A251-255"
+KEY_MATERIAL0="R4096-68096"
+KEY_MATERIAL0_EXT="R4096-68096"
+
+KEY_SLOT1="S256-259 S260-263 R264-295 A296-299 A300-303"
+KEY_MATERIAL1="R69632-133632"
+KEY_MATERIAL1_EXT="S69632-133632"
+
+KEY_SLOT5="S448-451 S452-455 R456-487 A488-491 A492-495"
+KEY_MATERIAL5="R331776-395264"
+KEY_MATERIAL5_EXT="S331776-395264"
+
+TEST_UUID="12345678-1234-1234-1234-123456789abc"
+
+LOOPDEV=$(losetup -f 2>/dev/null)
+FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME3 ] && dmsetup remove --retry $DEV_NAME3 >/dev/null 2>&1
+ [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2 >/dev/null 2>&1
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME >/dev/null 2>&1
+ losetup -d $LOOPDEV >/dev/null 2>&1
+ rm -f $ORIG_IMG $IMG $IMG10 $KEY1 $KEY2 $KEY5 $KEYE $HEADER_IMG $VK_FILE missing-file >/dev/null 2>&1
+ rmmod scsi_debug >/dev/null 2>&1
+ scsi_debug_teardown $DEV
+}
+
+function force_uevent()
+{
+ DNAME=$(echo $LOOPDEV | cut -f3 -d /)
+ echo "change" >/sys/block/$DNAME/uevent
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ exit 2
+}
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+function can_fail_fips()
+{
+ # Ignore this fail if running in FIPS mode
+ fips_mode || fail $1
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ [ -n "$2" ] && exit $2
+ exit 77
+}
+
+function prepare()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME >/dev/null 2>&1
+
+ case "$2" in
+ file)
+ remove_mapping
+ dd if=/dev/zero of=$IMG bs=1k count=10000 >/dev/null 2>&1
+ sync
+ ;;
+ wipe)
+ remove_mapping
+ dd if=/dev/zero of=$IMG bs=1k count=10000 >/dev/null 2>&1
+ sync
+ losetup $LOOPDEV $IMG
+ ;;
+ new)
+ remove_mapping
+ xz -cd compatimage.img.xz > $IMG
+ # FIXME: switch to internal loop (no losetup at all)
+ echo "bad" | $CRYPTSETUP luksOpen --key-slot 0 --test-passphrase $IMG 2>&1 | \
+ grep "autoclear flag" && skip "WARNING: Too old kernel, test skipped."
+ losetup $LOOPDEV $IMG
+ xz -cd compatv10image.img.xz > $IMG10
+ ;;
+ reuse | *)
+ if [ ! -e $IMG ]; then
+ xz -cd compatimage.img.xz > $IMG
+ losetup $LOOPDEV $IMG
+ fi
+ [ ! -e $IMG10 ] && xz -cd compatv10image.img.xz > $IMG10
+ ;;
+ esac
+
+ if [ ! -e $KEY1 ]; then
+ #dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ echo -n $'\x48\xc6\x74\x4f\x41\x4e\x50\xc0\x79\xc2\x2d\x5b\x5f\x68\x84\x17' >$KEY1
+ echo -n $'\x9c\x03\x5e\x1b\x4d\x0f\x9a\x75\xb3\x90\x70\x32\x0a\xf8\xae\xc4'>>$KEY1
+ fi
+
+ if [ ! -e $KEY2 ]; then
+ dd if=/dev/urandom of=$KEY2 count=1 bs=16 >/dev/null 2>&1
+ fi
+
+ if [ ! -e $KEY5 ]; then
+ dd if=/dev/urandom of=$KEY5 count=1 bs=16 >/dev/null 2>&1
+ fi
+
+ if [ ! -e $KEYE ]; then
+ touch $KEYE
+ fi
+
+ cp $IMG $ORIG_IMG
+ [ -n "$1" ] && echo "CASE: $1"
+}
+
+function check()
+{
+ sync
+ [ -z "$1" ] && return
+ $DIFFER $ORIG_IMG $IMG $1 || fail
+}
+
+function check_exists()
+{
+ [ -b /dev/mapper/$DEV_NAME ] || fail
+ check $1
+}
+
+# $1 path to scsi debug bdev
+scsi_debug_teardown() {
+ local _tries=15;
+
+ while [ -b "$1" -a $_tries -gt 0 ]; do
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -b "$1" ]; then
+ sleep .1
+ _tries=$((_tries-1))
+ fi
+ done
+
+ test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
+}
+
+function add_scsi_device() {
+ scsi_debug_teardown $DEV
+ if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+ fi
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 1
+ DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+function valgrind_setup()
+{
+ [ -n "$VALG" ] || return
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+ CRYPTSETUP=valgrind_run
+ CRYPTSETUP_RAW="./valg.sh ${CRYPTSETUP_VALGRIND}"
+}
+
+function valgrind_run()
+{
+ export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}"
+ $CRYPTSETUP_RAW "$@"
+}
+
+function expect_run()
+{
+ export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}"
+ expect "$@"
+}
+
+export LANG=C
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+valgrind_setup
+
+# LUKS non-root-tests
+if [ $(id -u) != 0 ]; then
+ $CRYPTSETUP benchmark -c aes-xts-plain64 >/dev/null 2>&1 || \
+ skip "WARNING: Cannot run test without kernel userspace crypto API, test skipped."
+fi
+
+prepare "Image in file tests (root capabilities not required)" file
+echo "[1] format"
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $IMG $FAST_PBKDF_OPT || fail
+echo "[2] open"
+echo $PWD0 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksOpen should return EPERM exit code"
+echo $PWD1 | $CRYPTSETUP luksOpen $IMG --test-passphrase || fail
+# test detached header --test-passphrase
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --header $HEADER_IMG $IMG || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $HEADER_IMG || fail
+rm -f $HEADER_IMG
+echo "[3] add key"
+echo $PWD1 | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT 2>/dev/null && fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT || fail
+echo -e "$PWD0\n$PWD1" | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT 2>/dev/null && fail
+echo "[4] change key"
+echo -e "$PWD1\n$PWD0\n" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT $IMG || fail
+echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT $IMG 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksChangeKey should return EPERM exit code"
+echo "[5] remove key"
+# delete active keys PWD0, PWD2
+echo $PWD1 | $CRYPTSETUP luksRemoveKey $IMG 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksRemove should return EPERM exit code"
+echo $PWD0 | $CRYPTSETUP luksRemoveKey $IMG || fail
+echo $PWD2 | $CRYPTSETUP luksRemoveKey $IMG || fail
+# check if keys were deleted
+echo $PWD0 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
+[ $? -ne 1 ] && fail "luksOpen should return ENOENT exit code"
+echo $PWD2 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
+[ $? -ne 1 ] && fail "luksOpen should return ENOENT exit code"
+echo "[6] kill slot"
+# format new luks device with active keys PWD1, PWD2
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $IMG $FAST_PBKDF_OPT || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT || fail
+# deactivate keys by killing slots
+$CRYPTSETUP luksDump $IMG | grep -q "Key Slot 0: ENABLED" || fail
+$CRYPTSETUP luksDump $IMG | grep -q "Key Slot 1: ENABLED" || fail
+$CRYPTSETUP luksDump $IMG | grep -q "Key Slot 2: DISABLED" || fail
+echo $PWD1 | $CRYPTSETUP -q luksKillSlot $IMG 0 2>/dev/null && fail
+echo $PWD2 | $CRYPTSETUP -q luksKillSlot $IMG 0 || fail
+$CRYPTSETUP luksDump $IMG | grep -q "Key Slot 0: DISABLED" || fail
+echo $PWD1 | $CRYPTSETUP -q luksKillSlot $IMG 1 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksKill should return EPERM exit code"
+echo $PWD2 | $CRYPTSETUP -q luksKillSlot $IMG 1 || fail
+$CRYPTSETUP luksDump $IMG | grep -q "Key Slot 1: DISABLED" || fail
+# check if keys were deactivated
+echo $PWD1 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
+echo $PWD2 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
+echo "[7] header backup"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $IMG $FAST_PBKDF_OPT || fail
+$CRYPTSETUP luksHeaderBackup $IMG --header-backup-file $HEADER_IMG || fail
+echo $PWD1 | $CRYPTSETUP luksRemoveKey $IMG || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
+echo "[8] header restore"
+$CRYPTSETUP luksHeaderRestore -q $IMG --header-backup-file $HEADER_IMG || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $IMG --test-passphrase || fail
+echo "[9] luksDump"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --uuid $TEST_UUID $IMG $KEY1 || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $IMG -d $KEY1 || fail
+$CRYPTSETUP luksDump $IMG | grep -q "Key Slot 0: ENABLED" || fail
+$CRYPTSETUP luksDump $IMG | grep -q $TEST_UUID || fail
+echo $PWDW | $CRYPTSETUP luksDump $IMG --dump-volume-key 2>/dev/null && fail
+echo $PWDW | $CRYPTSETUP luksDump $IMG --dump-master-key 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksDump $IMG --dump-volume-key | grep -q "MK dump:" || fail
+echo $PWD1 | $CRYPTSETUP luksDump $IMG --dump-master-key | grep -q "MK dump:" || fail
+$CRYPTSETUP luksDump -q $IMG --dump-volume-key -d $KEY1 | grep -q "MK dump:" || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $IMG --dump-master-key --master-key-file $VK_FILE >/dev/null || fail
+rm -f $VK_FILE
+echo $PWD1 | $CRYPTSETUP luksDump -q $IMG --dump-volume-key --volume-key-file $VK_FILE >/dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $IMG --dump-volume-key --volume-key-file $VK_FILE 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-file $VK_FILE $IMG || fail
+
+echo "[10] uuid"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --uuid $TEST_UUID $IMG || fail
+$CRYPTSETUP -q luksUUID $IMG | grep -q $TEST_UUID || fail
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ -z "$LOOPDEV" ] && skip "WARNING: Cannot find free loop device, test skipped."
+[ ! -x "$DIFFER" ] && skip "Cannot find $DIFFER, test skipped."
+
+# LUKS root-tests
+prepare "[1] open - compat image - acceptance check" new
+echo $PWD0 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+check_exists
+ORG_SHA256=$(sha256sum -b /dev/mapper/$DEV_NAME | cut -f 1 -d' ')
+[ "$ORG_SHA256" = 7428e8f2436882a07eb32765086f5c899474c08b5576f556b573d2aabdf923e8 ] || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+# Check it can be opened from header backup as well
+$CRYPTSETUP luksHeaderBackup $IMG --header-backup-file $HEADER_IMG || fail
+echo $PWD0 | $CRYPTSETUP luksOpen $IMG10 $DEV_NAME --header $HEADER_IMG || fail
+check_exists
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# Check restore
+$CRYPTSETUP luksHeaderRestore -q $IMG --header-backup-file $HEADER_IMG || fail
+
+# Repeat for V1.0 header - not aligned first keyslot
+if [ ! fips_mode ] ; then
+echo $PWD0 | $CRYPTSETUP luksOpen $IMG10 $DEV_NAME || fail
+check_exists
+ORG_SHA1=$(sha1sum -b /dev/mapper/$DEV_NAME | cut -f 1 -d' ')
+[ "$ORG_SHA1" = 51b48c2471a7593ceaf14dc5e66bca86ed05f6cc ] || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+rm -f $HEADER_IMG
+$CRYPTSETUP luksHeaderBackup $IMG10 --header-backup-file $HEADER_IMG
+echo $PWD0 | $CRYPTSETUP luksOpen $IMG10 $DEV_NAME --header $HEADER_IMG || fail
+check_exists
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+fi
+
+prepare "[2] open - compat image - denial check" new
+echo $PWDW | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+echo $PWDW | $CRYPTSETUP luksOpen $IMG10 $DEV_NAME 2>/dev/null && fail
+check
+
+# All headers items and first key material section must change
+prepare "[3] format" wipe
+echo $PWD1 | $CRYPTSETUP -i 1000 -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks1 $LOOPDEV || fail
+check "$LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0"
+
+prepare "[4] format using hash sha512" wipe
+echo $PWD1 | $CRYPTSETUP -i 1000 -h sha512 -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks1 $LOOPDEV || fail
+check "$LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0"
+
+prepare "[5] open"
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME --test-passphrase || fail
+echo $PWDW | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME --test-passphrase 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+check_exists
+
+# Key Slot 1 and key material section 1 must change, the rest must not.
+prepare "[6] add key"
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $LOOPDEV || fail
+check "$KEY_SLOT1 $KEY_MATERIAL1"
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+
+# Unsuccessful Key Delete - nothing may change
+prepare "[7] unsuccessful delete"
+echo $PWDW | $CRYPTSETUP luksKillSlot $LOOPDEV 1 2>/dev/null && fail
+$CRYPTSETUP -q luksKillSlot $LOOPDEV 8 2>/dev/null && fail
+$CRYPTSETUP -q luksKillSlot $LOOPDEV 7 2>/dev/null && fail
+check
+
+# Delete Key Test
+# Key Slot 1 and key material section 1 must change, the rest must not
+prepare "[8] successful delete"
+$CRYPTSETUP -q luksKillSlot $LOOPDEV 1 || fail
+check "$KEY_SLOT1 $KEY_MATERIAL1_EXT"
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+
+# Key Slot 1 and key material section 1 must change, the rest must not
+prepare "[9] add key test for key files"
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV $KEY1 || fail
+check "$KEY_SLOT1 $KEY_MATERIAL1"
+$CRYPTSETUP -d $KEY1 luksOpen $LOOPDEV $DEV_NAME || fail
+
+# Key Slot 1 and key material section 1 must change, the rest must not
+prepare "[10] delete key test with key1 as remaining key"
+$CRYPTSETUP -d $KEY1 luksKillSlot $LOOPDEV 0 || fail
+check "$KEY_SLOT0 $KEY_MATERIAL0_EXT"
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+
+# Delete last slot
+prepare "[11] delete last key" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $LOOPDEV $FAST_PBKDF_OPT || fail
+echo $PWD1 | $CRYPTSETUP luksKillSlot $LOOPDEV 0 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+
+# Format test for ESSIV, and some other parameters.
+prepare "[12] parameter variation test" wipe
+$CRYPTSETUP -q -i 1000 -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks1 $LOOPDEV $KEY1 || fail
+check "$LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0"
+$CRYPTSETUP -d $KEY1 luksOpen $LOOPDEV $DEV_NAME || fail
+
+prepare "[13] open/close - stacked devices" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $LOOPDEV $FAST_PBKDF_OPT || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 /dev/mapper/$DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen /dev/mapper/$DEV_NAME $DEV_NAME2 || fail
+$CRYPTSETUP -q luksClose $DEV_NAME2 || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[14] format/open - passphrase on stdin & new line" wipe
+# stdin defined by "-" must take even newline
+#echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksFormat $LOOPDEV - || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP $FAST_PBKDF_OPT -q --key-file=- luksFormat --type luks1 $LOOPDEV || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+# now also try --key-file
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP $FAST_PBKDF_OPT -q luksFormat --type luks1 $LOOPDEV --key-file=- || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# process newline if from stdin
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP $FAST_PBKDF_OPT -q luksFormat --type luks1 $LOOPDEV || fail
+echo "$PWD1" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[15] UUID - use and report provided UUID" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --uuid blah $LOOPDEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --uuid $TEST_UUID $LOOPDEV || fail
+tst=$($CRYPTSETUP -q luksUUID $LOOPDEV)
+[ "$tst"x = "$TEST_UUID"x ] || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV || fail
+$CRYPTSETUP -q luksUUID --uuid $TEST_UUID $LOOPDEV || fail
+tst=$($CRYPTSETUP -q luksUUID $LOOPDEV)
+[ "$tst"x = "$TEST_UUID"x ] || fail
+
+prepare "[16] luksFormat" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --volume-key-file /dev/urandom $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --volume-key-file /dev/urandom $LOOPDEV -d $KEY1 || fail
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --volume-key-file /dev/urandom -s 256 --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# open by UUID
+if [ -d /dev/disk/by-uuid ] ; then
+ force_uevent # some systems do not update loop by-uuid
+ $CRYPTSETUP luksOpen -d $KEY1 UUID=X$TEST_UUID $DEV_NAME 2>/dev/null && fail
+ $CRYPTSETUP luksOpen -d $KEY1 UUID=$TEST_UUID $DEV_NAME || fail
+ $CRYPTSETUP -q luksClose $DEV_NAME || fail
+fi
+# skip tests using empty passphrase
+if [ ! fips_mode ]; then
+# empty keyfile
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEYE || fail
+$CRYPTSETUP luksOpen -d $KEYE $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+fi
+# open by volume key
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT -s 256 --volume-key-file $KEY1 $LOOPDEV || fail
+$CRYPTSETUP luksOpen --volume-key-file /dev/urandom $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP luksOpen --volume-key-file $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# unsupported pe-keyslot encryption
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT -s 128 --keyslot-cipher "aes-cbc-plain" $LOOPDEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT -s 128 --keyslot-key-size 256 $LOOPDEV 2>/dev/null && fail
+
+prepare "[17] AddKey volume key, passphrase and keyfile" wipe
+# volumekey
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/zero --key-slot 3 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
+echo $PWD2 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/zero --key-slot 4 || fail
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 4 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: ENABLED" || fail
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/null --key-slot 5 2>/dev/null && fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/zero --key-slot 5 $KEY1 || fail
+$CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 5 -d $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
+
+# special "-" handling
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 3 || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV -d $KEY1 - || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d - --test-passphrase || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV -d - $KEY2 || fail
+$CRYPTSETUP luksOpen $LOOPDEV -d $KEY2 --test-passphrase || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d - -d $KEY1 --test-passphrase 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d $KEY1 -d $KEY1 --test-passphrase 2>/dev/null && fail
+
+# [0]PWD1 [1]PWD2 [2]$KEY1/1 [3]$KEY1 [4]$KEY2
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 3 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
+$CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 3 2>/dev/null && fail
+# keyfile/keyfile
+$CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 4 || fail
+$CRYPTSETUP luksOpen $LOOPDEV -d $KEY2 --test-passphrase --key-slot 4 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: ENABLED" || fail
+# passphrase/keyfile
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV -d $KEY1 --key-slot 0 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: ENABLED" || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 0 || fail
+# passphrase/passphrase
+echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --key-slot 1 || fail
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
+# keyfile/passphrase
+echo -e "$PWD2\n" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 2 --new-keyfile-size 8 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 2: ENABLED" || fail
+
+prepare "[18] RemoveKey passphrase and keyfile" reuse
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: DISABLED" || fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY1 2>/dev/null && fail
+$CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 --key-slot 3 2>/dev/null || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 --keyfile-size 1 2>/dev/null && fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: DISABLED" || fail
+# if password or keyfile is provided, batch mode must not suppress it
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 2>/dev/null && fail
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 -q 2>/dev/null && fail
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 --key-file=- 2>/dev/null && fail
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 --key-file=- -q 2>/dev/null && fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 2: ENABLED" || fail
+# kill slot using passphrase from 1
+echo $PWD2 | $CRYPTSETUP luksKillSlot $LOOPDEV 2 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 2: DISABLED" || fail
+# kill slot with redirected stdin
+$CRYPTSETUP luksKillSlot $LOOPDEV 3 </dev/null 2>/dev/null || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: DISABLED" || fail
+# remove key0 / slot 0
+echo $PWD1 | $CRYPTSETUP luksRemoveKey $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: DISABLED" || fail
+# last keyslot, in batch mode no passphrase needed...
+$CRYPTSETUP luksKillSlot -q $LOOPDEV 1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
+
+prepare "[19] create & status & resize" wipe
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash xxx 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha256 --cipher aes-cbc-essiv:sha256 --offset 3 --skip 4 --readonly || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "offset:" | grep -q "3 sectors" || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "skipped:" | grep -q "4 sectors" || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "mode:" | grep -q "readonly" || fail
+$CRYPTSETUP -q resize $DEV_NAME --size 100 || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP -q resize $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "19997 sectors" || fail
+$CRYPTSETUP -q resize $DEV_NAME --device-size 1M || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+$CRYPTSETUP -q resize $DEV_NAME --device-size 512k --size 1023 >/dev/null 2>&1 && fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+$CRYPTSETUP -q resize $DEV_NAME --device-size 513 >/dev/null 2>&1 && fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+# Resize underlying loop device as well
+truncate -s 16M $IMG || fail
+$CRYPTSETUP -q resize $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "32765 sectors" || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME >/dev/null && fail
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $LOOPDEV || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q create $DEV_NAME --hash sha256 $LOOPDEV || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q create $DEV_NAME --hash sha256 --size 100 $LOOPDEV || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+# 4k sector resize (if kernel supports it)
+echo $PWD1 | $CRYPTSETUP -q open --type plain --hash sha256 $LOOPDEV $DEV_NAME --sector-size 4096 --size 8 >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "8 sectors" || fail
+ $CRYPTSETUP -q resize $DEV_NAME --size 16 || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "16 sectors" || fail
+ $CRYPTSETUP -q resize $DEV_NAME --size 9 2>/dev/null && fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "16 sectors" || fail
+ $CRYPTSETUP -q resize $DEV_NAME --device-size 4608 2>/dev/null && fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "16 sectors" || fail
+ $CRYPTSETUP -q remove $DEV_NAME || fail
+fi
+# Resize not aligned to logical block size
+add_scsi_device dev_size_mb=32 sector_size=4096
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $DEV || fail
+OLD_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/')
+$CRYPTSETUP resize $DEV_NAME -b 7 2> /dev/null && fail
+dmsetup info $DEV_NAME | grep -q SUSPENDED && fail
+NEW_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/')
+test $OLD_SIZE -eq $NEW_SIZE || fail
+$CRYPTSETUP close $DEV_NAME || fail
+# Add check for unaligned plain crypt activation
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $DEV -b 7 2>/dev/null && fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+# verify is ignored on non-tty input
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha256 --verify-passphrase 2>/dev/null || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size 255 2>/dev/null && fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size -1 2>/dev/null && fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 -l -1 2>/dev/null && fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d blah 2>/dev/null && fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d /dev/urandom || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+
+prepare "[20] Disallow open/create if already mapped." wipe
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail
+$CRYPTSETUP create $DEV_NAME2 $LOOPDEV -d $KEY1 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $LOOPDEV 2>/dev/null && fail
+$CRYPTSETUP remove $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME2 2>/dev/null && fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+
+prepare "[21] luksDump" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT --uuid $TEST_UUID $LOOPDEV $KEY1 || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV -d $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: ENABLED" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q $TEST_UUID || fail
+echo $PWDW | $CRYPTSETUP luksDump $LOOPDEV --dump-volume-key 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksDump $LOOPDEV --dump-volume-key | grep -q "MK dump:" || fail
+$CRYPTSETUP luksDump -q $LOOPDEV --dump-volume-key -d $KEY1 | grep -q "MK dump:" || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $LOOPDEV --dump-volume-key --volume-key-file $VK_FILE > /dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-file $VK_FILE $LOOPDEV || fail
+
+prepare "[22] remove disappeared device" wipe
+dmsetup create $DEV_NAME --table "0 5000 linear $LOOPDEV 2" || fail
+echo $PWD1 | $CRYPTSETUP -q $FAST_PBKDF_OPT luksFormat --type luks1 /dev/mapper/$DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen /dev/mapper/$DEV_NAME $DEV_NAME2 || fail
+# underlying device now returns error but node is still present
+dmsetup load $DEV_NAME --table "0 5000 error" || fail
+dmsetup resume $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME2 || fail
+dmsetup remove --retry $DEV_NAME || fail
+
+prepare "[23] ChangeKey passphrase and keyfile" wipe
+# [0]$KEY1 [1]key0
+$CRYPTSETUP -q luksFormat --type luks1 $LOOPDEV $KEY1 $FAST_PBKDF_OPT --key-slot 0 || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 --key-slot 1 || fail
+# keyfile [0] / keyfile [0]
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 0 || fail
+# passphrase [1] / passphrase [1]
+echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT --key-slot 1 || fail
+# keyfile [0] / keyfile [new]
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: DISABLED" || fail
+# passphrase [1] / passphrase [new]
+echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
+# use all slots
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT || fail
+# still allows replace
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 2>/dev/null && fail
+
+prepare "[24] Keyfile limit" wipe
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 0 -l 13 || fail
+$CRYPTSETUP --key-file=$KEY1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 0 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l -1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 14 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset -1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT 2>/dev/null && fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 14 2>/dev/null && fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l -1 2>/dev/null && fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 13 --new-keyfile-size 12 || fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 2>/dev/null && fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 -l 12 || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT 2>/dev/null && fail
+$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 14 2>/dev/null && fail
+$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 13 || fail
+# -l is ignored for stdin if _only_ passphrase is used
+echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY2 $FAST_PBKDF_OPT || fail
+# this is stupid, but expected
+echo $PWD1 | $CRYPTSETUP luksRemoveKey $LOOPDEV -l 11 2>/dev/null && fail
+echo $PWDW"0" | $CRYPTSETUP luksRemoveKey $LOOPDEV -l 12 2>/dev/null && fail
+echo -e "$PWD1\n" | $CRYPTSETUP luksRemoveKey $LOOPDEV -d- -l 12 || fail
+# offset
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 0 -l 13 --keyfile-offset 16 || fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 15 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 16 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksAddKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 -l 13 --keyfile-offset 16 $KEY2 --new-keyfile-offset 1 || fail
+$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 11 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 1 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 --keyfile-offset 1 $KEY2 --new-keyfile-offset 0 || fail
+$CRYPTSETUP luksOpen -d $KEY2 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+# large device with keyfile
+echo -e '0 10000000 error'\\n'10000000 1000000 zero' | dmsetup create $DEV_NAME2 || fail
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV /dev/mapper/$DEV_NAME2 -l 13 --keyfile-offset 5120000000 || fail
+$CRYPTSETUP --key-file=/dev/mapper/$DEV_NAME2 -l 13 --keyfile-offset 5119999999 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=/dev/mapper/$DEV_NAME2 -l 13 --keyfile-offset 5120000000 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d /dev/mapper/$DEV_NAME2 \
+ --keyfile-offset 5120000000 -l 13 /dev/mapper/$DEV_NAME2 --new-keyfile-offset 5120000001 --new-keyfile-size 15 || fail
+dmsetup remove --retry $DEV_NAME2
+
+prepare "[25] Create shared segments" wipe
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha256 --offset 0 --size 256 || fail
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --hash sha256 --offset 512 --size 256 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME2 $LOOPDEV --hash sha256 --offset 512 --size 256 --shared || fail
+$CRYPTSETUP -q remove $DEV_NAME2 || fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+
+prepare "[26] Suspend/Resume" wipe
+# only LUKS is supported
+echo $PWD1 | $CRYPTSETUP create $DEV_NAME --hash sha256 $LOOPDEV || fail
+$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP -q remove $DEV_NAME || fail
+$CRYPTSETUP luksSuspend $DEV_NAME 2>/dev/null && fail
+# LUKS
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail
+echo $PWDW | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksResume should return EPERM exit code"
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# skip tests using empty passphrase
+if [ ! fips_mode ]; then
+echo | $CRYPTSETUP -q luksFormat -c null $FAST_PBKDF_OPT --type luks1 $LOOPDEV || fail
+echo | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+echo | $CRYPTSETUP luksResume $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+fi
+
+prepare "[27] luksOpen/luksResume with specified key slot number" wipe
+# first, let's try passphrase option
+echo $PWD3 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT -S 5 $LOOPDEV || fail
+check $LUKS_HEADER $KEY_SLOT5 $KEY_MATERIAL5
+echo $PWD3 | $CRYPTSETUP luksOpen -S 4 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+echo $PWD3 | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME || fail
+check_exists
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+echo $PWD3 | $CRYPTSETUP luksResume -S 4 $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+echo $PWD3 | $CRYPTSETUP luksResume -S 5 $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+echo -e "$PWD3\n$PWD1" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 0 $LOOPDEV || fail
+check $LUKS_HEADER $KEY_SLOT0 $KEY_MATERIAL0
+echo $PWD3 | $CRYPTSETUP luksOpen -S 0 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+echo $PWD1 | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+# second, try it with keyfiles
+$CRYPTSETUP luksFormat --type luks1 -q -S 5 -d $KEY5 $LOOPDEV || fail
+check $LUKS_HEADER $KEY_SLOT5 $KEY_MATERIAL5
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
+check $LUKS_HEADER $KEY_SLOT1 $KEY_MATERIAL1
+$CRYPTSETUP luksOpen -S 5 -d $KEY5 $LOOPDEV $DEV_NAME || fail
+check_exists
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+$CRYPTSETUP luksResume -S 1 -d $KEY5 $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+$CRYPTSETUP luksResume -S 5 -d $KEY5 $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksOpen -S 1 -d $KEY5 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+$CRYPTSETUP luksOpen -S 5 -d $KEY1 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+
+prepare "[28] Detached LUKS header" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG || fail
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 1 >/dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 8192 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 0 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 8192 --offset 8192 >/dev/null 2>&1 && fail
+truncate -s 4096 $HEADER_IMG
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG -S7 >/dev/null 2>&1 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 80000 >/dev/null 2>&1 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 8192 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 0 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV-missing --header $HEADER_IMG $DEV_NAME 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
+$CRYPTSETUP -q resize $DEV_NAME --size 100 --header $HEADER_IMG || fail
+$CRYPTSETUP -q status $DEV_NAME --header $HEADER_IMG | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "type:" | grep -q "n/a" || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 5 _fakedev_ --header $HEADER_IMG $KEY5 || fail
+$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "Key Slot 5: ENABLED" || fail
+$CRYPTSETUP luksKillSlot -q _fakedev_ --header $HEADER_IMG 5 || fail
+$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "Key Slot 5: DISABLED" || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $HEADER_IMG || fail
+
+prepare "[29] Repair metadata" wipe
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 0 || fail
+# second sector overwrite should corrupt keyslot 6+7
+dd if=/dev/urandom of=$LOOPDEV bs=512 seek=1 count=1 >/dev/null 2>&1
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME >/dev/null 2>&1 && fail
+$CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+# fix ecb-plain
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY1 --hash sha256 -c aes-ecb || fail
+echo -n "ecb-xxx" | dd of=$LOOPDEV bs=1 seek=40 >/dev/null 2>&1
+$CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+# fix uppercase hash
+echo -n "SHA256" | dd of=$LOOPDEV bs=1 seek=72 >/dev/null 2>&1
+$CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+
+prepare "[30] LUKS erase" wipe
+$CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV $KEY5 --key-slot 5 || fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
+$CRYPTSETUP luksErase -q $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: DISABLED" || fail
+
+prepare "[31] Deferred removal of device" wipe
+echo $PWD1 | $CRYPTSETUP open --type plain --hash sha256 $LOOPDEV $DEV_NAME || fail
+echo $PWD2 | $CRYPTSETUP open --type plain --hash sha256 /dev/mapper/$DEV_NAME $DEV_NAME2 || fail
+$CRYPTSETUP close $DEV_NAME >/dev/null 2>&1 && fail
+$CRYPTSETUP -q status $DEV_NAME >/dev/null 2>&1 || fail
+$CRYPTSETUP close --deferred $DEV_NAME >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" || fail
+ $CRYPTSETUP -q status $DEV_NAME >/dev/null 2>&1 || fail
+ $CRYPTSETUP close --cancel-deferred $DEV_NAME >/dev/null 2>&1
+ dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" >/dev/null 2>&1 && fail
+ $CRYPTSETUP close --deferred $DEV_NAME >/dev/null 2>&1
+ $CRYPTSETUP close $DEV_NAME2 || fail
+ $CRYPTSETUP -q status $DEV_NAME >/dev/null 2>&1 && fail
+else
+ $CRYPTSETUP close $DEV_NAME2 >/dev/null 2>&1
+ $CRYPTSETUP close $DEV_NAME >/dev/null 2>&1
+fi
+
+# Interactive tests
+# Do not remove sleep 0.1 below, the password query flushes TTY buffer (so the code is racy).
+command -v expect >/dev/null || skip "WARNING: expect tool missing, interactive test will be skipped." 0
+
+prepare "[32] Interactive password retry from terminal." new
+EXPECT_DEV=$(losetup $LOOPDEV | sed -e "s/.*(\(.*\))/\1/")
+EXPECT_TIMEOUT=60
+
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksOpen -v -T 2 $LOOPDEV $DEV_NAME
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0 x\n"
+expect timeout abort "No key available with this passphrase."
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Key slot 0 unlocked."
+expect timeout abort "Command successful."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+check_exists
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[33] Interactive unsuccessful password retry from terminal." new
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksOpen -v -T 2 $LOOPDEV $DEV_NAME
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0 x\n"
+expect timeout abort "No key available with this passphrase."
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0 y\n"
+expect timeout abort "No key available with this passphrase."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[34] Interactive kill of last key slot." new
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksKillSlot -v $LOOPDEV 0
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort "Enter any remaining passphrase:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksKillSlot -v $LOOPDEV 0
+expect timeout abort "Keyslot 0 is not active."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[35] Interactive format of device." wipe
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksFormat --type luks1 $FAST_PBKDF_OPT -v $LOOPDEV
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Verify passphrase:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksOpen -v $LOOPDEV --test-passphrase
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[36] Interactive unsuccessful format of device." new
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW erase -v $LOOPDEV
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksFormat --type luks1 $FAST_PBKDF_OPT -v $LOOPDEV
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Verify passphrase:"
+sleep 0.1
+send "$PWD0 x\n"
+expect timeout abort "Passphrases do not match."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksOpen -v $LOOPDEV -T 1 --test-passphrase
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "No usable keyslot is available."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[37] Interactive add key." new
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksAddKey -S 2 $FAST_PBKDF_OPT -v $LOOPDEV
+expect timeout abort "Enter any existing passphrase:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Enter new passphrase for key slot:"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "Verify passphrase:"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksOpen -v $LOOPDEV --test-passphrase
+expect timeout abort "Enter passphrase"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksKillSlot -v $LOOPDEV 1
+expect timeout abort "Keyslot 1 is not active."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksKillSlot -v $LOOPDEV 2
+expect timeout abort "Enter any remaining passphrase:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Key slot 2 removed."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[38] Interactive change key." new
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksChangeKey $FAST_PBKDF_OPT -v $LOOPDEV
+expect timeout abort "Enter passphrase to be changed:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Enter new passphrase:"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "Verify passphrase:"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksOpen -v $LOOPDEV --test-passphrase
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[39] Interactive suspend and resume." new
+echo $PWD0 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksSuspend -v $DEV_NAME
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksResume -v -T 3 $DEV_NAME
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0 x\n"
+expect timeout abort "No key available with this passphrase."
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD1\n"
+expect timeout abort "No key available with this passphrase."
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0 y\n"
+expect timeout abort "No key available with this passphrase."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksResume -v $DEV_NAME
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$PWD0\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+exit
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+$CRYPTSETUP remove $DEV_NAME || fail
+
+prepare "[40] Long passphrase from TTY." wipe
+EXPECT_DEV=$(losetup $LOOPDEV | sed -e "s/.*(\(.*\))/\1/")
+
+# Password of maximal length 512 characters
+LONG_PWD=\
+"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF"\
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "\
+"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut e"\
+"nim ad minim veniam, quis nostrud exercitation ullamco laboris n"\
+"isi ut aliquip ex ea commodo consequat. Duis aute irure dolor in"\
+" reprehenderit in voluptate velit esse cillum dolore eu fugiat n"\
+"ulla pariatur. Excepteur sint occaecat cupidatat non proident, s"\
+"unt in culpa qui officia deserunt mollit anim id est laborum.DEF"
+
+echo -n "$LONG_PWD" >$KEYE
+
+expect_run - >/dev/null <<EOF
+proc abort {} { send_error "Timeout. "; exit 2 }
+set timeout $EXPECT_TIMEOUT
+eval spawn $CRYPTSETUP_RAW luksFormat --type luks1 $FAST_PBKDF_OPT -v $LOOPDEV
+expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
+send "YES\n"
+expect timeout abort "Enter passphrase for $EXPECT_DEV:"
+sleep 0.1
+send "$LONG_PWD\n"
+expect timeout abort "Verify passphrase:"
+sleep 0.1
+send "$LONG_PWD\n"
+expect timeout abort "Command successful."
+expect timeout abort eof
+eval spawn $CRYPTSETUP_RAW luksOpen -v $LOOPDEV --test-passphrase --key-file $KEYE
+expect timeout abort "Command successful."
+expect timeout abort eof
+EOF
+[ $? -eq 0 ] || fail "Expect script failed."
+
+prepare "[41] New luksAddKey options." file
+rm -f $VK_FILE
+echo "$PWD1" | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT $IMG || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $IMG --dump-volume-key --volume-key-file $VK_FILE >/dev/null || fail
+
+# pass pass
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q -S1 $FAST_PBKDF_OPT $IMG || fail
+echo $PWD2 | $CRYPTSETUP open -q --test-passphrase -S1 $IMG || fail
+
+# pass file
+echo "$PWD2" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S1 --new-key-slot 2 $IMG $KEY1 || fail
+$CRYPTSETUP open --test-passphrase -q -S2 -d $KEY1 $IMG || fail
+
+# file pass
+echo "$PWD3" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 -d $KEY1 --new-key-slot 3 $IMG || fail
+echo $PWD3 | $CRYPTSETUP open -q --test-passphrase -S3 $IMG || fail
+
+# file file
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 --new-key-slot 4 -d $KEY1 --new-keyfile $KEY2 $IMG || fail
+$CRYPTSETUP open --test-passphrase -q -S4 -d $KEY2 $IMG || fail
+
+# vk pass
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S5 --volume-key-file $VK_FILE $IMG || fail
+echo $PWD3 | $CRYPTSETUP open -q --test-passphrase -S5 $IMG || fail
+
+# vk file
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S6 --volume-key-file $VK_FILE --new-keyfile $KEY5 $IMG || fail
+$CRYPTSETUP open --test-passphrase -q -S6 -d $KEY5 $IMG || fail
+
+remove_mapping
+exit 0
diff --git a/tests/compat-test2 b/tests/compat-test2
new file mode 100755
index 0000000..c54dc7e
--- /dev/null
+++ b/tests/compat-test2
@@ -0,0 +1,1204 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+DEV_NAME=dummy
+DEV_NAME2=dummy2
+DEV_NAME3=dummy3
+ORIG_IMG=luks-test-orig
+IMG=luks-test
+IMG10=luks-test-v10
+HEADER_IMG=luks-header
+HEADER_KEYU=luks2_keyslot_unassigned.img
+HEADER_LUKS2_PV=blkid-luks2-pv.img
+KEY1=key1
+KEY2=key2
+KEY5=key5
+KEYE=keye
+PWD0="compatkey"
+PWD1="93R4P4pIqAH8"
+PWD2="mymJeD8ivEhE"
+PWD3="ocMakf3fAcQO"
+PWD4="Qx3qn46vq0v"
+PWDW="rUkL4RUryBom"
+TEST_KEYRING_NAME="compattest2_keyring"
+TEST_TOKEN0="compattest2_desc0"
+TEST_TOKEN1="compattest2_desc1"
+TEST_TOKEN2="compattest2_desc2"
+VK_FILE="compattest2_vkfile"
+IMPORT_TOKEN="{\"type\":\"some_type\",\"keyslots\":[],\"base64_data\":\"zxI7vKB1Qwl4VPB4D-N-OgcC14hPCG0IDu8O7eCqaQ\"}"
+TOKEN_FILE0=test-token-file0
+TOKEN_FILE1=test-token-file1
+KEY_FILE0=test-key-file0
+KEY_FILE1=test-key-file1
+
+FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+
+TEST_UUID="12345678-1234-1234-1234-123456789abc"
+
+LOOPDEV=$(losetup -f 2>/dev/null)
+FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME3 ] && dmsetup remove --retry $DEV_NAME3
+ [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ losetup -d $LOOPDEV >/dev/null 2>&1
+ rm -f $ORIG_IMG $IMG $IMG10 $KEY1 $KEY2 $KEY5 $KEYE $HEADER_IMG $HEADER_KEYU $VK_FILE $HEADER_LUKS2_PV missing-file $TOKEN_FILE0 $TOKEN_FILE1 test_image_* $KEY_FILE0 $KEY_FILE1 >/dev/null 2>&1
+
+ # unlink whole test keyring
+ [ -n "$TEST_KEYRING" ] && keyctl unlink $TEST_KEYRING "@u" >/dev/null
+ unset TEST_KEYRING
+
+ rmmod scsi_debug >/dev/null 2>&1
+ scsi_debug_teardown $DEV
+}
+
+function force_uevent()
+{
+ DNAME=$(echo $LOOPDEV | cut -f3 -d /)
+ echo "change" >/sys/block/$DNAME/uevent
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ exit 2
+}
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+function can_fail_fips()
+{
+ # Ignore this fail if running in FIPS mode
+ fips_mode || fail $1
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function prepare()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+
+ case "$2" in
+ wipe)
+ remove_mapping
+ dd if=/dev/zero of=$IMG bs=1M count=40 >/dev/null 2>&1
+ sync
+ losetup $LOOPDEV $IMG
+ ;;
+ new)
+ remove_mapping
+ xz -cd compatimage.img.xz > $IMG
+ xz -dk $HEADER_KEYU.xz
+ # FIXME: switch to internal loop (no losetup at all)
+ echo "bad" | $CRYPTSETUP luksOpen --key-slot 0 --test-passphrase $IMG 2>&1 | \
+ grep "autoclear flag" && skip "WARNING: Too old kernel, test skipped."
+ losetup $LOOPDEV $IMG
+ xz -cd compatv10image.img.xz > $IMG10
+ ;;
+ reuse | *)
+ if [ ! -e $IMG ]; then
+ xz -cd compatimage.img.xz > $IMG
+ losetup $LOOPDEV $IMG
+ fi
+ [ ! -e $IMG10 ] && xz -cd compatv10image.img.xz > $IMG10
+ ;;
+ esac
+
+ if [ ! -e $KEY1 ]; then
+ #dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ echo -n $'\x48\xc6\x74\x4f\x41\x4e\x50\xc0\x79\xc2\x2d\x5b\x5f\x68\x84\x17' >$KEY1
+ echo -n $'\x9c\x03\x5e\x1b\x4d\x0f\x9a\x75\xb3\x90\x70\x32\x0a\xf8\xae\xc4'>>$KEY1
+ fi
+
+ if [ ! -e $KEY2 ]; then
+ dd if=/dev/urandom of=$KEY2 count=1 bs=16 >/dev/null 2>&1
+ fi
+
+ if [ ! -e $KEY5 ]; then
+ dd if=/dev/urandom of=$KEY5 count=1 bs=16 >/dev/null 2>&1
+ fi
+
+ if [ ! -e $KEYE ]; then
+ touch $KEYE
+ fi
+
+ cp $IMG $ORIG_IMG
+ [ -n "$1" ] && echo "CASE: $1"
+}
+
+function check_exists()
+{
+ [ -b /dev/mapper/$DEV_NAME ] || fail
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function dm_crypt_keyring_support()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ test -d /proc/sys/kernel/keys || return 1
+
+ [ $VER_MAJ -gt 1 ] && return 0
+ [ $VER_MAJ -eq 1 -a $VER_MIN -gt 18 ] && return 0
+ [ $VER_MAJ -eq 1 -a $VER_MIN -eq 18 -a $VER_PTC -ge 1 ] && return 0
+ return 1
+}
+
+function dm_crypt_keyring_flawed()
+{
+ dm_crypt_keyring_support && return 1;
+
+ [ $VER_MAJ -gt 1 ] && return 0
+ [ $VER_MAJ -eq 1 -a $VER_MIN -ge 15 ] && return 0
+ return 1
+}
+
+function dm_crypt_keyring_new_kernel()
+{
+ KER_STR=$(uname -r)
+ [ -z "$KER_STR" ] && fail "Failed to parse kernel version."
+ KER_MAJ=$(echo $KER_STR | cut -f 1 -d.)
+ KER_MIN=$(echo $KER_STR | cut -f 2 -d.)
+
+ [ $KER_MAJ -ge 5 ] && return 0
+ [ $KER_MAJ -eq 4 -a $KER_MIN -ge 15 ] && return 0
+ return 1
+}
+
+function dm_crypt_sector_size_support()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ if [ $VER_MIN -ge 17 -o \( $VER_MIN -eq 14 -a $VER_PTC -ge 5 \) ]; then
+ return 0
+ fi
+
+ return 1
+}
+
+function test_and_prepare_keyring() {
+ command -v keyctl >/dev/null || skip "Cannot find keyctl, test skipped"
+ keyctl list "@s" > /dev/null || skip "Current session keyring is unreachable, test skipped"
+ TEST_KEYRING=$(keyctl newring $TEST_KEYRING_NAME "@u" 2> /dev/null)
+ test -n "$TEST_KEYRING" || skip "Failed to create keyring in user keyring"
+ keyctl search "@s" keyring "$TEST_KEYRING" > /dev/null 2>&1 || keyctl link "@u" "@s" > /dev/null 2>&1
+ load_key user test_key test_data "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
+}
+
+# $1 type
+# $2 description
+# $3 payload
+# $4 keyring
+function load_key()
+{
+ keyctl add $@ >/dev/null
+}
+
+function setup_luks2_env() {
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $LOOPDEV || fail
+ $CRYPTSETUP luksDump $LOOPDEV >/dev/null || fail
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME || fail
+ HAVE_KEYRING=$($CRYPTSETUP status $DEV_NAME | grep "keyring")
+ if [ -n "$HAVE_KEYRING" ]; then
+ HAVE_KEYRING=1
+ else
+ HAVE_KEYRING=0
+ fi
+ if $($CRYPTSETUP --version | grep -q "BLKID"); then
+ HAVE_BLKID=1
+ else
+ HAVE_BLKID=0
+ fi
+ $CRYPTSETUP close $DEV_NAME || fail
+}
+
+# $1 path to scsi debug bdev
+scsi_debug_teardown() {
+ local _tries=15;
+
+ while [ -b "$1" -a $_tries -gt 0 ]; do
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -b "$1" ]; then
+ sleep .1
+ _tries=$((_tries-1))
+ fi
+ done
+
+ test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
+}
+
+function add_scsi_device() {
+ scsi_debug_teardown $DEV
+ if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+ fi
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 1
+ DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+export LANG=C
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ -z "$LOOPDEV" ] && skip "WARNING: Cannot find free loop device, test skipped."
+
+prepare "[0] Detect LUKS2 environment" wipe
+setup_luks2_env
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+prepare "[1] Data offset" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 1 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 16385 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 32 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --align-payload 16384 --offset 16384 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 16384 || fail
+$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "offset: $((512 * 16384)) \[bytes\]" || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 1024 --offset 16384 >/dev/null || fail
+$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "offset: $((512 * 16384)) \[bytes\]" || fail
+truncate -s 4096 $HEADER_IMG
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG -q --offset 80000 >/dev/null 2>&1 || fail
+
+prepare "[2] Sector size and old payload alignment" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 511 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 256 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 8192 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 512 || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --align-payload 5 || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 512 --align-payload 5 || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 2048 --align-payload 32 >/dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 4096 >/dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 2048 --align-payload 32768 >/dev/null || fail
+$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "offset: $((512 * 32768)) \[bytes\]" || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 2048 >/dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 4096 --align-payload 32768 >/dev/null || fail
+$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "offset: $((512 * 32768)) \[bytes\]" || fail
+
+prepare "[3] format" wipe
+echo $PWD1 | $CRYPTSETUP -q $FAST_PBKDF_OPT -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks2 $LOOPDEV || fail
+prepare "[4] format using hash sha512" wipe
+echo $PWD1 | $CRYPTSETUP $FAST_PBKDF_OPT -h sha512 -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks2 $LOOPDEV || fail
+$CRYPTSETUP -q luksDump $LOOPDEV | grep "0: pbkdf2" -A2 | grep "Hash:" | grep -qe sha512 || fail
+# Check JSON dump for some mandatory section
+$CRYPTSETUP -q luksDump $LOOPDEV --dump-json-metadata | grep -q '"tokens":' || fail
+
+prepare "[5] open"
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME --test-passphrase || fail
+echo $PWDW | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME --test-passphrase 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksOpen should return EPERM exit code"
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+check_exists
+
+# Key Slot 1 and key material section 1 must change, the rest must not.
+prepare "[6] add key"
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $LOOPDEV $FAST_PBKDF_OPT || fail
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+
+# Unsuccessful Key Delete - nothing may change
+prepare "[7] unsuccessful delete"
+echo $PWDW | $CRYPTSETUP luksKillSlot $LOOPDEV 1 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksKillSlot should return EPERM exit code"
+#FIXME
+#$CRYPTSETUP -q luksKillSlot $LOOPDEV 8 2>/dev/null && fail
+#$CRYPTSETUP -q luksKillSlot $LOOPDEV 7 2>/dev/null && fail
+
+# Delete Key Test
+# Key Slot 1 and key material section 1 must change, the rest must not
+prepare "[8] successful delete"
+$CRYPTSETUP -q luksKillSlot $LOOPDEV 1 || fail
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2> /dev/null && fail
+[ $? -ne 2 ] && fail "luksOpen should return EPERM exit code"
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+
+# Key Slot 1 and key material section 1 must change, the rest must not
+prepare "[9] add key test for key files"
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV $KEY1 || fail
+$CRYPTSETUP -d $KEY1 luksOpen $LOOPDEV $DEV_NAME || fail
+
+# Key Slot 1 and key material section 1 must change, the rest must not
+prepare "[10] delete key test with key1 as remaining key"
+$CRYPTSETUP -d $KEY1 luksKillSlot $LOOPDEV 0 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+
+# Delete last slot
+prepare "[11] delete last key" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $LOOPDEV $FAST_PBKDF_OPT || fail
+echo $PWD1 | $CRYPTSETUP luksKillSlot $LOOPDEV 0 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+
+# Format test for ESSIV, and some other parameters.
+prepare "[12] parameter variation test" wipe
+$CRYPTSETUP -q $FAST_PBKDF_OPT -c aes-cbc-essiv:sha256 -s 128 luksFormat --type luks2 $LOOPDEV $KEY1 || fail
+$CRYPTSETUP -d $KEY1 luksOpen $LOOPDEV $DEV_NAME || fail
+
+prepare "[13] open/close - stacked devices" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $LOOPDEV $FAST_PBKDF_OPT || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 /dev/mapper/$DEV_NAME $FAST_PBKDF_OPT || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen /dev/mapper/$DEV_NAME $DEV_NAME2 || fail
+$CRYPTSETUP -q luksClose $DEV_NAME2 || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[14] format/open - passphrase on stdin & new line" wipe
+# stdin defined by "-" must take even newline
+#echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksFormat $LOOPDEV - || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP $FAST_PBKDF_OPT -q --key-file=- luksFormat --type luks2 $LOOPDEV || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+# now also try --key-file
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP $FAST_PBKDF_OPT -q luksFormat --type luks2 $LOOPDEV --key-file=- || fail
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP -q --key-file=- luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# process newline if from stdin
+echo -n -e "$PWD1\n$PWD2" | $CRYPTSETUP $FAST_PBKDF_OPT -q luksFormat --type luks2 $LOOPDEV || fail
+echo "$PWD1" | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[15] UUID - use and report provided UUID" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --uuid blah --type luks2 $LOOPDEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --uuid $TEST_UUID --type luks2 $LOOPDEV || fail
+tst=$($CRYPTSETUP -q luksUUID $LOOPDEV)
+[ "$tst"x = "$TEST_UUID"x ] || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+$CRYPTSETUP -q luksUUID --uuid $TEST_UUID $LOOPDEV || fail
+tst=$($CRYPTSETUP -q luksUUID $LOOPDEV)
+[ "$tst"x = "$TEST_UUID"x ] || fail
+
+prepare "[16] luksFormat" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom --type luks2 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom --type luks2 $LOOPDEV -d $KEY1 || fail
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --volume-key-file /dev/urandom -s 256 --uuid $TEST_UUID --type luks2 $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+# open by UUID
+if [ -d /dev/disk/by-uuid ] ; then
+ force_uevent # some systems do not update loop by-uuid
+ $CRYPTSETUP luksOpen -d $KEY1 UUID=X$TEST_UUID $DEV_NAME 2>/dev/null && fail
+ $CRYPTSETUP luksOpen -d $KEY1 UUID=$TEST_UUID $DEV_NAME || fail
+ $CRYPTSETUP -q luksClose $DEV_NAME || fail
+fi
+# skip tests using empty passphrases
+if [ ! fips_mode ]; then
+# empty keyfile
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEYE || fail
+$CRYPTSETUP luksOpen -d $KEYE $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+fi
+
+# open by volume key
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT -s 256 --volume-key-file $KEY1 --type luks2 $LOOPDEV || fail
+$CRYPTSETUP luksOpen --volume-key-file /dev/urandom $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP luksOpen --volume-key-file $KEY1 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[17] AddKey volume key, passphrase and keyfile" wipe
+# volumekey
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --volume-key-file /dev/zero --key-slot 3 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2" || fail
+echo $PWD2 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/zero --key-slot 4 || fail
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 4 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "4: luks2" || fail
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/null --key-slot 5 2>/dev/null && fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --volume-key-file /dev/zero --key-slot 5 $KEY1 || fail
+$CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 5 -d $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "5: luks2" || fail
+
+# special "-" handling
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY1 --key-slot 3 || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV -d $KEY1 - || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d - --test-passphrase || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV -d - $KEY2 || fail
+$CRYPTSETUP luksOpen $LOOPDEV -d $KEY2 --test-passphrase || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d - -d $KEY1 --test-passphrase 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV -d $KEY1 -d $KEY1 --test-passphrase 2>/dev/null && fail
+
+# [0]PWD1 [1]PWD2 [2]$KEY1/1 [3]$KEY1 [4]$KEY2
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY1 --key-slot 3 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2" || fail
+$CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 3 2>/dev/null && fail
+# keyfile/keyfile
+$CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 4 || fail
+$CRYPTSETUP luksOpen $LOOPDEV -d $KEY2 --test-passphrase --key-slot 4 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "4: luks2" || fail
+# passphrase/keyfile
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV -d $KEY1 --key-slot 0 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 0 || fail
+# passphrase/passphrase
+echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --key-slot 1 || fail
+echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || fail
+# keyfile/passphrase
+echo -e "$PWD2\n" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV $KEY1 --key-slot 2 --new-keyfile-size 8 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" || fail
+
+prepare "[18] RemoveKey passphrase and keyfile" reuse
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2" || fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2" && fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY1 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksRemoveKey should return EPERM exit code"
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 --keyfile-size 1 2>/dev/null && fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "4: luks2" || fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "4: luks2" && fail
+# if password or keyfile is provided, batch mode must not suppress it
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 2>/dev/null && fail
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 -q 2>/dev/null && fail
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 --key-file=- 2>/dev/null && fail
+echo "badpw" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 --key-file=- -q 2>/dev/null && fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" || fail
+# kill slot using passphrase from 1
+echo $PWD2 | $CRYPTSETUP luksKillSlot $LOOPDEV 2 2>/dev/null || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" && fail
+# remove key0 / slot 0
+echo $PWD1 | $CRYPTSETUP luksRemoveKey $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" && fail
+# last keyslot, in batch mode no passphrase needed...
+$CRYPTSETUP luksKillSlot -q $LOOPDEV 1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" && fail
+
+prepare "[19] create & status & resize" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+if dm_crypt_keyring_support; then
+ echo | $CRYPTSETUP -q resize --size 100 $DEV_NAME 2>/dev/null && fail
+ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then
+ test_and_prepare_keyring
+ load_key user $TEST_TOKEN2 $PWD1 "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
+ $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN2 --token-id 1 || fail
+ $CRYPTSETUP -q resize --size 99 $DEV_NAME <&- || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "99 sectors" || fail
+ #replace kernel key with wrong pass
+ load_key user $TEST_TOKEN2 $PWD2 "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
+ # must fail due to --token-only
+ echo $PWD1 | $CRYPTSETUP -q resize --token-only --size 100 $DEV_NAME && fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" && fail
+ fi
+fi
+echo $PWD1 | $CRYPTSETUP -q resize --size 100 $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+echo $PWD1 | $CRYPTSETUP -q resize --device-size 51200 $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+echo $PWD1 | $CRYPTSETUP -q resize --device-size 1M $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+echo $PWD1 | $CRYPTSETUP -q resize --device-size 512k --size 1024 $DEV_NAME > /dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP -q resize --device-size 4097 $DEV_NAME > /dev/null 2>&1 && fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+$CRYPTSETUP close $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksOpen --disable-keyring $LOOPDEV $DEV_NAME || fail
+echo | $CRYPTSETUP -q resize --size 100 $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP close $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+if dm_crypt_keyring_support; then
+ $CRYPTSETUP -q resize --disable-keyring --size 100 $DEV_NAME 2>/dev/null && fail
+fi
+if dm_crypt_sector_size_support; then
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 --sector-size 4096 $LOOPDEV > /dev/null || fail
+ echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP -q resize --device-size 1M $DEV_NAME || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+ echo $PWD1 | $CRYPTSETUP -q resize --device-size 2049s $DEV_NAME > /dev/null 2>&1 && fail
+ echo $PWD1 | $CRYPTSETUP -q resize --size 2049 $DEV_NAME > /dev/null 2>&1 && fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "2048 sectors" || fail
+fi
+$CRYPTSETUP close $DEV_NAME || fail
+# Resize not aligned to logical block size
+add_scsi_device dev_size_mb=32 sector_size=4096
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $DEV || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+OLD_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/') #'
+echo $PWD1 | $CRYPTSETUP resize $DEV_NAME -b 7 2> /dev/null && fail
+dmsetup info $DEV_NAME | grep -q SUSPENDED && fail
+NEW_SIZE=$($CRYPTSETUP status $DEV_NAME | grep "^ \+size:" | sed 's/.* \([0-9]\+\) .*/\1/') #'
+test $OLD_SIZE -eq $NEW_SIZE || fail
+$CRYPTSETUP close $DEV_NAME || fail
+
+prepare "[20] Disallow open/create if already mapped." wipe
+$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV 2>/dev/null && fail
+$CRYPTSETUP remove $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DEV_NAME2 2>/dev/null && fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+
+prepare "[21] luksDump" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat --key-size 256 $FAST_PBKDF_OPT --uuid $TEST_UUID --type luks2 $LOOPDEV $KEY1 || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $LOOPDEV -d $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q $TEST_UUID || fail
+echo $PWDW | $CRYPTSETUP luksDump $LOOPDEV --dump-volume-key 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksDump $LOOPDEV --dump-volume-key | grep -q "MK dump:" || fail
+$CRYPTSETUP luksDump -q $LOOPDEV --dump-volume-key -d $KEY1 | grep -q "MK dump:" || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $LOOPDEV --dump-master-key --master-key-file $VK_FILE >/dev/null || fail
+rm -f $VK_FILE
+echo $PWD1 | $CRYPTSETUP luksDump -q $LOOPDEV --dump-volume-key --volume-key-file $VK_FILE >/dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $LOOPDEV --dump-volume-key --volume-key-file $VK_FILE 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-file $VK_FILE $LOOPDEV || fail
+# Use volume key file without keyslots
+$CRYPTSETUP luksErase -q $LOOPDEV || fail
+$CRYPTSETUP luksOpen --volume-key-file $VK_FILE --key-size 256 --test-passphrase $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --volume-key-file $VK_FILE --key-size 256 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP luksOpen --test-passphrase $LOOPDEV || fail
+
+prepare "[22] remove disappeared device" wipe
+dmsetup create $DEV_NAME --table "0 39998 linear $LOOPDEV 2" || fail
+echo $PWD1 | $CRYPTSETUP -q $FAST_PBKDF_OPT luksFormat --type luks2 /dev/mapper/$DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen /dev/mapper/$DEV_NAME $DEV_NAME2 || fail
+# underlying device now returns error but node is still present
+dmsetup load $DEV_NAME --table "0 40000 error" || fail
+dmsetup resume $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME2 || fail
+dmsetup remove --retry $DEV_NAME || fail
+
+prepare "[23] ChangeKey passphrase and keyfile" wipe
+# [0]$KEY1 [1]key0
+$CRYPTSETUP -q luksFormat --type luks2 $LOOPDEV $KEY1 $FAST_PBKDF_OPT --key-slot 0 --key-size 256 --luks2-keyslots-size 256k >/dev/null || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 --key-slot 1 || fail
+# keyfile [0] / keyfile [0]
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 --key-slot 0 || fail
+# passphrase [1] / passphrase [1]
+echo -e "$PWD1\n$PWD2\n" | $CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT --key-slot 1 || fail
+# keyfile [0] / keyfile [new] - with LUKS2 it should stay
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" && fail
+# passphrase [1] / passphrase [new]
+echo -e "$PWD2\n$PWD1\n" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2" && fail
+# test out of raw area, change in-place (space only for 2 keyslots)
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "0: luks2" || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 $KEY2 2>/dev/null && fail
+
+prepare "[24] Keyfile limit" wipe
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY1 --key-slot 0 -l 13 || fail
+$CRYPTSETUP --key-file=$KEY1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 0 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l -1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 14 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset -1 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 2>/dev/null && fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -l 14 2>/dev/null && fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -l -1 2>/dev/null && fail
+$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 13 --new-keyfile-size 12 || fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 2>/dev/null && fail
+$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 -l 12 || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksChangeKey should return EPERM exit code"
+$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 -l 14 2>/dev/null && fail
+$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT -l 13 || fail
+# -l is ignored for stdin if _only_ passphrase is used
+echo $PWD1 | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY2 $FAST_PBKDF_OPT || fail
+# this is stupid, but expected
+echo $PWD1 | $CRYPTSETUP luksRemoveKey $LOOPDEV -l 11 2>/dev/null && fail
+echo $PWDW"0" | $CRYPTSETUP luksRemoveKey $LOOPDEV -l 12 2>/dev/null && fail
+echo -e "$PWD1\n" | $CRYPTSETUP luksRemoveKey $LOOPDEV -d- -l 12 || fail
+# offset
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY1 --key-slot 0 -l 13 --keyfile-offset 16 || fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 15 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY1 -l 13 --keyfile-offset 16 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksAddKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY1 -l 13 --keyfile-offset 16 $KEY2 --new-keyfile-offset 1 || fail
+$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 11 luksOpen $LOOPDEV $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP --key-file=$KEY2 --keyfile-offset 1 luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 --keyfile-offset 1 $KEY2 --new-keyfile-offset 0 || fail
+$CRYPTSETUP luksOpen -d $KEY2 $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+
+prepare "[26] Suspend/Resume" wipe
+# LUKS
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+$CRYPTSETUP -q resize $DEV_NAME 2>/dev/null && fail
+echo $PWDW | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
+[ $? -ne 2 ] && fail "luksResume should return EPERM exit code"
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat -c null $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q luksOpen $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME || fail
+$CRYPTSETUP -q luksClose $DEV_NAME || fail
+
+prepare "[27] luksOpen/Resume with specified key slot number" wipe
+# first, let's try passphrase option
+echo $PWD3 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT -S 5 --type luks2 $LOOPDEV || fail
+echo $PWD3 | $CRYPTSETUP luksOpen -S 4 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+echo $PWD3 | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME || fail
+check_exists
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+echo $PWD3 | $CRYPTSETUP luksResume -S 4 $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+echo $PWD3 | $CRYPTSETUP luksResume -S 5 $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+echo -e "$PWD3\n$PWD1" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 0 $LOOPDEV || fail
+echo $PWD3 | $CRYPTSETUP luksOpen -S 0 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+echo $PWD1 | $CRYPTSETUP luksOpen -S 5 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+# second, try it with keyfiles
+$CRYPTSETUP -q luksFormat -q -S 5 $FAST_PBKDF_OPT -d $KEY5 --type luks2 $LOOPDEV || fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksOpen -S 5 -d $KEY5 $LOOPDEV $DEV_NAME || fail
+check_exists
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+$CRYPTSETUP luksResume -S 1 -d $KEY5 $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" || fail
+$CRYPTSETUP luksResume -S 5 -d $KEY5 $DEV_NAME || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+$CRYPTSETUP luksOpen -S 1 -d $KEY5 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+$CRYPTSETUP luksOpen -S 5 -d $KEY1 $LOOPDEV $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+# test keyslot not assigned to segment is unable to unlock volume
+# otoh it should be allowed to test for proper passphrase
+prepare "" new
+echo $PWD1 | $CRYPTSETUP open -S1 --test-passphrase $HEADER_KEYU || fail
+echo $PWD1 | $CRYPTSETUP open --unbound --test-passphrase $HEADER_KEYU || fail
+echo $PWD1 | $CRYPTSETUP open -S1 $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+echo $PWD1 | $CRYPTSETUP open $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
+[ -b /dev/mapper/$DEV_NAME ] && fail
+echo $PWD0 | $CRYPTSETUP open -S1 --test-passphrase $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP luksKillSlot -q $HEADER_KEYU 0
+$CRYPTSETUP luksDump $HEADER_KEYU | grep -q "0: luks2" && fail
+echo $PWD1 | $CRYPTSETUP open -S1 --test-passphrase $HEADER_KEYU || fail
+echo $PWD1 | $CRYPTSETUP open --unbound --test-passphrase $HEADER_KEYU || fail
+echo $PWD1 | $CRYPTSETUP open -S1 $HEADER_KEYU $DEV_NAME 2>/dev/null && fail
+
+prepare "[28] Detached LUKS header" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG || fail
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG --align-payload 1 >/dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG --align-payload 8192 || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG --align-payload 4096 >/dev/null || fail
+$CRYPTSETUP luksDump $HEADER_IMG | grep -e "0: crypt" -A1 | grep -qe $((4096*512)) || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG --align-payload 0 --sector-size 512 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV-missing --header $HEADER_IMG $DEV_NAME 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP -q resize $DEV_NAME --size 100 --header $HEADER_IMG || fail
+$CRYPTSETUP -q status $DEV_NAME --header $HEADER_IMG | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "type:" | grep -q "n/a" || fail
+$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
+$CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
+$CRYPTSETUP luksSuspend $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 5 _fakedev_ --header $HEADER_IMG $KEY5 || fail
+$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "5: luks2" || fail
+$CRYPTSETUP luksKillSlot -q _fakedev_ --header $HEADER_IMG 5 || fail
+$CRYPTSETUP luksDump _fakedev_ --header $HEADER_IMG | grep -q "5: luks2" && fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $HEADER_IMG || fail
+rm $HEADER_IMG || fail
+# create exactly 16 MiBs LUKS2 header
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG --luks2-keyslots-size 16352k --luks2-metadata-size 16k --offset 131072 >/dev/null || fail
+SIZE=$(stat --printf=%s $HEADER_IMG)
+test $SIZE -eq 16777216 || fail
+$CRYPTSETUP -q luksDump $HEADER_IMG | grep -q "offset: $((512 * 131072)) \[bytes\]" || fail
+
+prepare "[29] Repair metadata" wipe
+xz -dk $HEADER_LUKS2_PV.xz
+if [ "$HAVE_BLKID" -gt 0 ]; then
+ $CRYPTSETUP isLuks --disable-locks $HEADER_LUKS2_PV && fail
+ $CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
+ $CRYPTSETUP isLuks --disable-locks --type luks2 $HEADER_LUKS2_PV && fail
+ $CRYPTSETUP isLuks --type luks2 $HEADER_LUKS2_PV && fail
+fi
+$CRYPTSETUP -q repair $HEADER_LUKS2_PV || fail
+$CRYPTSETUP isLuks $HEADER_LUKS2_PV || fail
+$CRYPTSETUP isLuks --type luks2 $HEADER_LUKS2_PV || fail
+$CRYPTSETUP isLuks --type luks1 $HEADER_LUKS2_PV && fail
+
+prepare "[30] LUKS erase" wipe
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY5 --key-slot 5 || fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "5: luks2" || fail
+$CRYPTSETUP luksErase -q $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" && fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "5: luks2" && fail
+
+prepare "[31] LUKS convert" wipe
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks1 $LOOPDEV $KEY5 --key-slot 5 || fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $LOOPDEV $KEY1 || fail
+$CRYPTSETUP -q luksDump $LOOPDEV --dump-json-metadata >/dev/null 2>&1 && fail
+$CRYPTSETUP -q convert --type luks1 $LOOPDEV >/dev/null 2>&1 && fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 5: ENABLED" || fail
+$CRYPTSETUP -q convert --type luks2 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "5: luks2" || fail
+$CRYPTSETUP -q convert --type luks1 $LOOPDEV || fail
+# hash test
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --sector-size 512 $LOOPDEV $KEY5 -S 0 --hash sha512 || fail
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 1 -d $KEY5 $LOOPDEV $KEY1 --hash sha256 || fail
+$CRYPTSETUP -q convert --type luks1 $LOOPDEV >/dev/null 2>&1 && fail
+$CRYPTSETUP -q luksKillSlot $LOOPDEV 1 || fail
+$CRYPTSETUP -q convert --type luks1 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: ENABLED" || fail
+$CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 0 -d $KEY5 || fail
+# sector size test
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --sector-size 1024 $LOOPDEV $KEY5 || fail
+$CRYPTSETUP -q convert --type luks1 $LOOPDEV >/dev/null 2>&1 && fail
+
+# create LUKS1 with data offset not aligned to 4KiB
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks1 $LOOPDEV $KEY5 --align-payload 4097 || fail
+$CRYPTSETUP -q convert --type luks2 $LOOPDEV || fail
+$CRYPTSETUP isLuks --type luks2 $LOOPDEV || fail
+$CRYPTSETUP luksOpen $LOOPDEV --test-passphrase --key-slot 0 -d $KEY5 || fail
+
+# keyslot 1 area offset is higher than keyslot 0 area
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 --key-slot 0 $LOOPDEV || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF_OPT --key-slot 1 $LOOPDEV || fail
+echo -e "$PWD1\n$PWD1" | $CRYPTSETUP -q luksChangeKey $FAST_PBKDF_OPT $LOOPDEV || fail
+# convert to LUKS1 and back; LUKS1 does not store length, only offset
+$CRYPTSETUP -q convert --type luks1 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q open --test-passphrase $LOOPDEV || fail
+echo $PWD2 | $CRYPTSETUP -q open --test-passphrase $LOOPDEV || fail
+$CRYPTSETUP -q convert --type luks2 $LOOPDEV || fail
+echo $PWD1 | $CRYPTSETUP -q open --test-passphrase $LOOPDEV || fail
+echo $PWD2 | $CRYPTSETUP -q open --test-passphrase $LOOPDEV || fail
+
+if dm_crypt_keyring_flawed; then
+ prepare "[32a] LUKS2 keyring dm-crypt bug" wipe
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG || fail
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "dm-crypt" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ # key must not load in kernel key even when dm-crypt module is missing
+ if rmmod dm-crypt >/dev/null 2>&1; then
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "dm-crypt" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fi
+fi
+
+if dm_crypt_keyring_support && dm_crypt_keyring_new_kernel; then
+ prepare "[32] LUKS2 key in keyring" wipe
+ echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --header $HEADER_IMG || fail
+
+ # check keyring support detection works as expected
+ rmmod dm-crypt >/dev/null 2>&1 || true
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "keyring" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV --disable-keyring --header $HEADER_IMG $DEV_NAME || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "dm-crypt" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV --disable-keyring --header $HEADER_IMG $DEV_NAME || fail
+ $CRYPTSETUP luksSuspend $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "keyring" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ echo $PWD1 | $CRYPTSETUP open $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail
+ $CRYPTSETUP luksSuspend $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP luksResume --disable-keyring $DEV_NAME --header $HEADER_IMG || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "key location:" | grep -q "dm-crypt" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+fi
+
+# FIXME: candidate for non-root tests
+prepare "[33] tokens" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then
+
+ test_and_prepare_keyring
+
+ $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN0 --token-id 3 || fail
+ $CRYPTSETUP luksDump $LOOPDEV | grep -q -e "3: luks2-keyring" || fail
+ # keyslot 5 is inactive
+ $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN1 --key-slot 5 2> /dev/null && fail
+ # key description is not reachable
+ $CRYPTSETUP open --token-only $LOOPDEV --test-passphrase && fail
+ # wrong passphrase
+ load_key user $TEST_TOKEN0 "blabla" "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
+ $CRYPTSETUP open --token-only $LOOPDEV --test-passphrase 2>/dev/null && fail
+ load_key user $TEST_TOKEN0 $PWD1 "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
+ $CRYPTSETUP open --token-only $LOOPDEV --test-passphrase || fail
+ $CRYPTSETUP open --token-only $LOOPDEV $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME > /dev/null || fail
+ $CRYPTSETUP luksSuspend $DEV_NAME || fail
+ $CRYPTSETUP luksResume $DEV_NAME <&- || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep -q "(suspended)" && fail
+ $CRYPTSETUP luksSuspend $DEV_NAME || fail
+ $CRYPTSETUP luksResume $DEV_NAME --token-type luks2-keyring <&- || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ # check --token-type sort of works (TODO: extend tests when native systemd tokens are available)
+ echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 22 || fail
+ # this excludes keyring tokens from unlocking device
+ $CRYPTSETUP open --token-only --token-type some_type $LOOPDEV --test-passphrase && fail
+ $CRYPTSETUP open --token-only --token-type some_type $LOOPDEV $DEV_NAME && fail
+ $CRYPTSETUP status $DEV_NAME > /dev/null && fail
+
+ $CRYPTSETUP token remove --token-id 3 $LOOPDEV || fail
+ $CRYPTSETUP luksDump $LOOPDEV | grep -q -e "3: luks2-keyring" && fail
+
+ # test we can remove keyslot with token
+ echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q -S4 $FAST_PBKDF_OPT $LOOPDEV || fail
+ $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN1 --key-slot 4 --token-id 0 || fail
+ $CRYPTSETUP -q luksKillSlot $LOOPDEV 4 || fail
+ $CRYPTSETUP token remove --token-id 0 $LOOPDEV || fail
+
+ # test we can add unassigned token
+ $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN0 --unbound --token-id 0 || fail
+ $CRYPTSETUP open --token-only --token-id 0 --test-passphrase $LOOPDEV && fail
+ $CRYPTSETUP token remove --token-id 0 $LOOPDEV || fail
+
+ # test token unassign works
+ $CRYPTSETUP token add $LOOPDEV --key-description $TEST_TOKEN0 -S0 --token-id 0 || fail
+ $CRYPTSETUP open --token-only --token-id 0 --test-passphrase $LOOPDEV || fail
+ $CRYPTSETUP token unassign --token-id 0 $LOOPDEV 2>/dev/null && fail
+ $CRYPTSETUP token unassign -S0 $LOOPDEV 2>/dev/null && fail
+ $CRYPTSETUP token unassign --token-id 0 -S0 $LOOPDEV || fail
+ $CRYPTSETUP open --token-only --token-id 0 --test-passphrase $LOOPDEV && fail
+ $CRYPTSETUP token unassign --token-id 0 -S0 $LOOPDEV 2>/dev/null && fail
+ $CRYPTSETUP token unassign --token-id 0 -S44 $LOOPDEV 2>/dev/null && fail
+ $CRYPTSETUP token unassign --token-id 44 -S0 $LOOPDEV 2>/dev/null && fail
+fi
+echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 10 || fail
+echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import $LOOPDEV --token-id 11 --json-file - || fail
+echo -n "$IMPORT_TOKEN" > $TOKEN_FILE0
+$CRYPTSETUP token import $LOOPDEV --token-id 12 --json-file $TOKEN_FILE0 || fail
+$CRYPTSETUP token import $LOOPDEV --token-id 12 --json-file $TOKEN_FILE0 2>/dev/null && fail
+$CRYPTSETUP token export $LOOPDEV --token-id 10 >$TOKEN_FILE1 || fail
+diff $TOKEN_FILE0 $TOKEN_FILE1 || fail
+$CRYPTSETUP token export $LOOPDEV --token-id 11 >$TOKEN_FILE1 || fail
+diff $TOKEN_FILE0 $TOKEN_FILE1 || fail
+$CRYPTSETUP token export $LOOPDEV --token-id 12 >$TOKEN_FILE1 || fail
+diff $TOKEN_FILE0 $TOKEN_FILE1 || fail
+$CRYPTSETUP token export $LOOPDEV --token-id 12 --json-file $TOKEN_FILE1 || fail
+diff $TOKEN_FILE0 $TOKEN_FILE1 || fail
+$CRYPTSETUP token export $LOOPDEV --token-id 12 > $TOKEN_FILE1 || fail
+diff $TOKEN_FILE0 $TOKEN_FILE1 || fail
+
+prepare "[34] LUKS keyslot priority" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -S 1 || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q $LOOPDEV $FAST_PBKDF_OPT -S 5 || fail
+$CRYPTSETUP config $LOOPDEV -S 0 --priority prefer && fail
+$CRYPTSETUP config $LOOPDEV -S 1 --priority bla >/dev/null 2>&1 && fail
+$CRYPTSETUP config $LOOPDEV -S 1 --priority ignore || fail
+echo $PWD1 | $CRYPTSETUP open $LOOPDEV --test-passphrase 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP open $LOOPDEV --test-passphrase -S 1 || fail
+echo $PWD2 | $CRYPTSETUP open $LOOPDEV --test-passphrase || fail
+$CRYPTSETUP config $LOOPDEV -S 1 --priority normal || fail
+echo $PWD1 | $CRYPTSETUP open $LOOPDEV --test-passphrase || fail
+$CRYPTSETUP config $LOOPDEV -S 1 --priority ignore || fail
+echo $PWD1 | $CRYPTSETUP open $LOOPDEV --test-passphrase 2>/dev/null && fail
+
+prepare "[35] LUKS label and subsystem" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Subsystem:" | grep -q "(no subsystem)" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Label:" | grep -q "(no label)" || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --subsystem SatelliteTwo --label TheLabel || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Subsystem:" | grep -q "SatelliteTwo" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Label:" | grep -q "TheLabel" || fail
+$CRYPTSETUP config $LOOPDEV --subsystem SatelliteThree
+$CRYPTSETUP luksDump $LOOPDEV | grep "Subsystem:" | grep -q "SatelliteThree" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Label:" | grep -q "(no label)" || fail
+$CRYPTSETUP config $LOOPDEV --subsystem SatelliteThree --label TheLabel
+$CRYPTSETUP luksDump $LOOPDEV | grep "Subsystem:" | grep -q "SatelliteThree" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Label:" | grep -q "TheLabel" || fail
+
+prepare "[36] LUKS PBKDF setting" wipe
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --pbkdf bla $LOOPDEV >/dev/null 2>&1 && fail
+# Force setting, no benchmark. PBKDF2 has 1000 iterations as a minimum
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --pbkdf pbkdf2 --pbkdf-force-iterations 999 $LOOPDEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf pbkdf2 --pbkdf-force-iterations 1234 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Iterations:" | grep -q "1234" || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf argon2id --pbkdf-force-iterations 3 $LOOPDEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf argon2id --pbkdf-force-iterations 4 --pbkdf-memory 100000 $LOOPDEV || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep "PBKDF:" | grep -q "argon2id" || can_fail_fips
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf argon2i --pbkdf-force-iterations 4 \
+ --pbkdf-memory 1234 --pbkdf-parallel 1 $LOOPDEV || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep "PBKDF:" | grep -q "argon2i" || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep "Time cost:" | grep -q "4" || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep "Memory:" | grep -q "1234" || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep "Threads:" | grep -q "1" || can_fail_fips
+# Benchmark
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf argon2i -i 500 --pbkdf-memory 1234 --pbkdf-parallel 1 $LOOPDEV || can_fail_fips
+[ 0"$($CRYPTSETUP luksDump $LOOPDEV | grep "Time cost:" | cut -d: -f 2 | sed -e 's/\ //g')" -gt 0 ] || can_fail_fips
+[ 0"$($CRYPTSETUP luksDump $LOOPDEV | grep "Memory:" | cut -d: -f 2 | sed -e 's/\ //g')" -gt 0 ] || can_fail_fips
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf pbkdf2 -i 500 $LOOPDEV || fail
+[ 0"$($CRYPTSETUP luksDump $LOOPDEV | grep -m1 "Iterations:" | cut -d' ' -f 2 | sed -e 's/\ //g')" -gt 1000 ] || fail
+
+prepare "[37] LUKS Keyslot convert" wipe
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks1 $LOOPDEV $KEY5 --key-slot 5 || fail
+$CRYPTSETUP -q luksConvertKey $LOOPDEV --key-file $KEY5 2>/dev/null && fail
+$CRYPTSETUP -q convert --type luks2 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "5: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "PBKDF:" | grep -q "pbkdf2" || fail
+$CRYPTSETUP -q luksConvertKey $LOOPDEV -S 5 --key-file $KEY5 --pbkdf argon2i -i1 --pbkdf-memory 32 || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "5: luks2" || can_fail_fips
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV -S 1 --key-file $KEY5 || fail
+$CRYPTSETUP -q luksKillSlot $LOOPDEV 5 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "PBKDF:" | grep -q "pbkdf2" || fail
+echo $PWD1 | $CRYPTSETUP -q luksConvertKey $LOOPDEV -S 1 --pbkdf argon2i -i1 --pbkdf-memory 32 || can_fail_fips
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "1: luks2" || can_fail_fips
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S 21 --unbound -s 72 $LOOPDEV || fail
+echo $PWD3 | $CRYPTSETUP luksConvertKey --pbkdf-force-iterations 1001 --pbkdf pbkdf2 -S 21 $LOOPDEV || fail
+
+prepare "[38] luksAddKey unbound tests" wipe
+$CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV $KEY5 --key-slot 5 || fail
+# unbound key may have arbitrary size
+echo $PWD1 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT --unbound -s 72 $LOOPDEV || fail
+echo $PWD2 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --unbound -s 72 -S 2 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2 (unbound)" || fail
+dd if=/dev/urandom of=$KEY_FILE0 bs=64 count=1 > /dev/null 2>&1 || fail
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --unbound -s 512 -S 3 --volume-key-file $KEY_FILE0 $LOOPDEV || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2 (unbound)" || fail
+# unbound key size is required
+echo $PWD1 | $CRYPTSETUP -q luksAddKey --unbound $LOOPDEV 2>/dev/null && fail
+echo $PWD3 | $CRYPTSETUP -q luksAddKey --unbound --volume-key-file /dev/urandom $LOOPDEV 2> /dev/null && fail
+# do not allow one to replace keyslot by unbound slot
+echo $PWD1 | $CRYPTSETUP -q luksAddKey -S5 --unbound -s 32 $LOOPDEV 2>/dev/null && fail
+echo $PWD2 | $CRYPTSETUP -q open $LOOPDEV $DEV_NAME 2> /dev/null && fail
+echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDEV $DEV_NAME 2> /dev/null && fail
+echo $PWD2 | $CRYPTSETUP -q open -S2 $LOOPDEV --test-passphrase || fail
+echo $PWD1 | $CRYPTSETUP -q open $LOOPDEV $DEV_NAME 2> /dev/null && fail
+# check we're able to change passphrase for unbound keyslot
+echo -e "$PWD2\n$PWD3" | $CRYPTSETUP luksChangeKey $FAST_PBKDF_OPT -S 2 $LOOPDEV || fail
+echo $PWD3 | $CRYPTSETUP open --test-passphrase -S 2 $LOOPDEV || fail
+echo $PWD3 | $CRYPTSETUP -q open -S 2 $LOOPDEV $DEV_NAME 2> /dev/null && fail
+# do not allow adding keyslot by unbound keyslot
+echo -e "$PWD3\n$PWD1" | $CRYPTSETUP -q luksAddKey $LOOPDEV 2> /dev/null && fail
+# check adding keyslot works when there's unbound keyslot
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT $LOOPDEV --key-file $KEY5 -S8 || fail
+echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME || fail
+$CRYPTSETUP close $DEV_NAME || fail
+$CRYPTSETUP luksKillSlot -q $LOOPDEV 2
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "2: luks2 (unbound)" && fail
+echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 $LOOPDEV 2> /dev/null && fail
+echo $PWD3 | $CRYPTSETUP luksDump --unbound 2> /dev/null $LOOPDEV 2> /dev/null && fail
+echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 -S3 $LOOPDEV > /dev/null || fail
+diff $KEY_FILE0 $KEY_FILE1 || fail
+echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 -S3 $LOOPDEV 2> /dev/null && fail
+diff $KEY_FILE0 $KEY_FILE1 || fail
+rm $KEY_FILE1 || fail
+echo $PWD3 | $CRYPTSETUP luksDump --unbound --volume-key-file $KEY_FILE1 -S3 $LOOPDEV | grep -q "Unbound Key:" && fail
+echo $PWD3 | $CRYPTSETUP luksDump --unbound -S3 $LOOPDEV | grep -q "Unbound Key:" || fail
+$CRYPTSETUP luksKillSlot -q $LOOPDEV 3 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep -q "3: luks2 (unbound)" && fail
+
+prepare "[39] LUKS2 metadata variants" wipe
+tar xJf luks2_mda_images.tar.xz
+echo -n "$IMPORT_TOKEN" > $TOKEN_FILE0
+for mda in 16 32 64 128 256 512 1024 2048 4096 ; do
+ echo -n "[$mda KiB]"
+ echo $PWD4 | $CRYPTSETUP open test_image_$mda $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -e "$PWD4\n$PWD3" | $CRYPTSETUP luksAddKey -q -S9 $FAST_PBKDF_OPT test_image_$mda || fail
+ echo $PWD4 | $CRYPTSETUP open --test-passphrase test_image_$mda || fail
+ echo $PWD3 | $CRYPTSETUP open -S9 --test-passphrase test_image_$mda || fail
+ echo -n "$IMPORT_TOKEN" | $CRYPTSETUP token import test_image_$mda --token-id 10 || fail
+ $CRYPTSETUP token export test_image_$mda --token-id 10 >$TOKEN_FILE1 || fail
+ diff $TOKEN_FILE1 $TOKEN_FILE0 || fail
+ echo -n "[OK]"
+done
+echo
+
+prepare "[40] LUKS2 metadata areas" wipe
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV 2> /dev/null || fail
+DEFAULT_OFFSET=$($CRYPTSETUP luksDump $LOOPDEV | grep "offset: " | cut -f 2 -d ' ')
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks1 $LOOPDEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=128k 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=127k 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --luks2-metadata-size=127k --luks2-keyslots-size=128k 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=128M >/dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --luks2-metadata-size=128k --luks2-keyslots-size=128k >/dev/null || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Metadata area:" | grep -q "131072 \[bytes\]" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Keyslots area:" | grep -q "131072 \[bytes\]" || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --luks2-metadata-size=128k || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Metadata area:" | grep -q "131072 \[bytes\]" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Keyslots area:" | grep -q "$((DEFAULT_OFFSET-2*131072)) \[bytes\]" || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --luks2-keyslots-size=128k >/dev/null || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Metadata area:" | grep -q "16384 \[bytes\]" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Keyslots area:" | grep -q "131072 \[bytes\]" || fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --offset 16384 || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Metadata area:" | grep -q "16384 \[bytes\]" || fail
+$CRYPTSETUP luksDump $LOOPDEV | grep "Keyslots area:" | grep -q "8355840 \[bytes\]" || fail
+# data offset vs area size
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --offset 64 --luks2-keyslots-size=8192 >/dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --offset $((256+56)) >/dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV --key-size 256 --offset $((256+64)) >/dev/null || fail
+
+prepare "[41] Per-keyslot encryption parameters" wipe
+KEYSLOT_CIPHER="aes-cbc-plain64"
+$CRYPTSETUP -q luksFormat --type luks2 $LOOPDEV $KEY1 $FAST_PBKDF_OPT --key-slot 0 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "0: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "0: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail
+$CRYPTSETUP luksAddKey -q $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT --key-slot 1 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "1: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "1: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail
+$CRYPTSETUP luksAddKey -q $LOOPDEV -d $KEY1 $KEY2 $FAST_PBKDF_OPT --key-slot 2 || fail
+$CRYPTSETUP luksChangeKey $LOOPDEV $FAST_PBKDF_OPT -d $KEY2 $KEY1 --key-slot 2 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "2: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "2: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail
+# unbound keyslot
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --key-slot 21 --unbound -s 72 --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 $LOOPDEV || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "21: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "21: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail
+echo $PWD3 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --key-slot 22 --unbound -s 72 $LOOPDEV || fail
+echo $PWD3 | $CRYPTSETUP luksConvertKey --key-slot 22 $LOOPDEV --keyslot-cipher $KEYSLOT_CIPHER --keyslot-key-size 128 $LOOPDEV || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "22: luks2" | grep "Cipher:" | sed -e 's/[[:space:]]\+Cipher:\ \+//g')" = $KEYSLOT_CIPHER ] || fail
+[ "$($CRYPTSETUP luksDump $IMG | grep -A8 -m1 "22: luks2" | grep "Cipher key:"| sed -e 's/[[:space:]]\+Cipher\ key:\ \+//g')" = "128 bits" ] || fail
+
+prepare "[42] Some encryption compatibility mode tests" wipe
+CIPHERS="aes-ecb aes-cbc-null aes-cbc-plain64 aes-cbc-essiv:sha256 aes-xts-plain64"
+key_size=256
+for cipher in $CIPHERS ; do
+ echo -n "[$cipher/$key_size]"
+ $CRYPTSETUP -q luksFormat --type luks2 $LOOPDEV $KEY1 $FAST_PBKDF_OPT --cipher $cipher --key-size $key_size || fail
+done
+echo
+
+prepare "[43] New luksAddKey options." wipe
+rm -f $VK_FILE
+echo "$PWD1" | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $IMG || fail
+echo $PWD1 | $CRYPTSETUP luksDump -q $IMG --dump-volume-key --volume-key-file $VK_FILE >/dev/null || fail
+
+# pass pass
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -q -S1 $FAST_PBKDF_OPT $IMG || fail
+echo $PWD2 | $CRYPTSETUP open -q --test-passphrase -S1 $IMG || fail
+
+# pass file
+echo "$PWD2" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S1 --new-key-slot 2 $IMG $KEY1 || fail
+$CRYPTSETUP open --test-passphrase -q -S2 -d $KEY1 $IMG || fail
+
+# file pass
+echo "$PWD3" | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 -d $KEY1 --new-key-slot 3 $IMG || fail
+echo $PWD3 | $CRYPTSETUP open -q --test-passphrase -S3 $IMG || fail
+
+# file file
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 --new-key-slot 4 -d $KEY1 --new-keyfile $KEY2 $IMG || fail
+$CRYPTSETUP open --test-passphrase -q -S4 -d $KEY2 $IMG || fail
+
+# vk pass
+echo $PWD4 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S5 --volume-key-file $VK_FILE $IMG || fail
+echo $PWD4 | $CRYPTSETUP open -q --test-passphrase -S5 $IMG || fail
+
+# vk file
+$CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S6 --volume-key-file $VK_FILE --new-keyfile $KEY5 $IMG || fail
+$CRYPTSETUP open --test-passphrase -q -S6 -d $KEY5 $IMG || fail
+
+if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then
+ test_and_prepare_keyring
+ load_key user $TEST_TOKEN0 $PWD1 "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
+ load_key user $TEST_TOKEN1 $PWDW "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
+ $CRYPTSETUP token add $IMG --key-description $TEST_TOKEN0 --token-id 0 -S0 || fail
+ $CRYPTSETUP token add $IMG --key-description $TEST_TOKEN1 --token-id 1 --unbound || fail
+
+ # pass token
+ echo -e "$PWD1" | $CRYPTSETUP luksAddKey -q -S7 --new-token-id 1 $FAST_PBKDF_OPT $IMG || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG || fail
+ echo $PWD1 | $CRYPTSETUP luksKillSlot $IMG 7 || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG && fail
+
+ # file token
+ $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S2 --new-key-slot 7 --new-token-id 1 -d $KEY1 $IMG || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG || fail
+ echo $PWD1 | $CRYPTSETUP luksKillSlot $IMG 7 || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG && fail
+
+ # vk token
+ $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S7 --volume-key-file $VK_FILE --new-token-id 1 $IMG || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG || fail
+ echo $PWD1 | $CRYPTSETUP luksKillSlot $IMG 7 || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG && fail
+
+ # token pass
+ echo $PWD4 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S7 --token-id 0 $IMG || fail
+ echo $PWD4 | $CRYPTSETUP open -q --test-passphrase -S7 $IMG || fail
+
+ # token file
+ echo $PWD4 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S8 --token-id 0 $IMG $KEY2 || fail
+ $CRYPTSETUP open -q --test-passphrase -S8 --key-file $KEY2 $IMG || fail
+
+ # token token
+ $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S9 --token-id 0 --new-token-id 1 $IMG || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG || fail
+ echo $PWD1 | $CRYPTSETUP luksKillSlot $IMG 9 || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 1 -q $IMG && fail
+
+ # reuse same token
+ $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT -S0 --new-key-slot 9 --token-id 0 --new-token-id 0 $IMG || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 0 -q $IMG || fail
+ echo $PWD1 | $CRYPTSETUP luksKillSlot $IMG 9 || fail
+
+ # reuse same token
+ $CRYPTSETUP luksAddKey -q $FAST_PBKDF_OPT --token-id 0 --new-token-id 0 $IMG || fail
+ echo $PWD1 | $CRYPTSETUP luksKillSlot $IMG 9 || fail
+ $CRYPTSETUP open -q --test-passphrase --token-only --token-id 0 -q $IMG || fail
+fi
+
+remove_mapping
+exit 0
diff --git a/tests/compatimage.img.xz b/tests/compatimage.img.xz
new file mode 100644
index 0000000..cb515f4
--- /dev/null
+++ b/tests/compatimage.img.xz
Binary files differ
diff --git a/tests/compatimage2.img.xz b/tests/compatimage2.img.xz
new file mode 100644
index 0000000..ceaeafc
--- /dev/null
+++ b/tests/compatimage2.img.xz
Binary files differ
diff --git a/tests/compatv10image.img.xz b/tests/compatv10image.img.xz
new file mode 100644
index 0000000..2203626
--- /dev/null
+++ b/tests/compatv10image.img.xz
Binary files differ
diff --git a/tests/conversion_imgs.tar.xz b/tests/conversion_imgs.tar.xz
new file mode 100644
index 0000000..43e35fe
--- /dev/null
+++ b/tests/conversion_imgs.tar.xz
Binary files differ
diff --git a/tests/crypto-vectors.c b/tests/crypto-vectors.c
new file mode 100644
index 0000000..ae8dd68
--- /dev/null
+++ b/tests/crypto-vectors.c
@@ -0,0 +1,1559 @@
+/*
+ * cryptsetup crypto backend test vectors
+ *
+ * Copyright (C) 2018-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "crypto_backend/crypto_backend.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+static void printhex(const char *s, const char *buf, size_t len)
+{
+ size_t i;
+
+ printf("%s: ", s);
+ for (i = 0; i < len; i++)
+ printf(" %02x", (unsigned char)buf[i]);
+ printf("\n");
+ fflush(stdout);
+}
+
+static bool fips_mode(void)
+{
+ int fd;
+ char buf = 0;
+
+ fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
+
+ if (fd < 0)
+ return false;
+
+ if (read(fd, &buf, 1) != 1)
+ buf = '0';
+
+ close(fd);
+
+ return (buf == '1');
+}
+
+/*
+ * KDF tests
+ */
+struct kdf_test_vector {
+ const char *type;
+ const char *hash;
+ unsigned int hash_block_length;
+ unsigned int iterations;
+ unsigned int memory;
+ unsigned int parallelism;
+ const char *password;
+ unsigned int password_length;
+ const char *salt;
+ unsigned int salt_length;
+// const char *key;
+// unsigned int key_length;
+// const char *ad;
+// unsigned int ad_length;
+ const char *output;
+ unsigned int output_length;
+};
+
+static struct kdf_test_vector kdf_test_vectors[] = {
+ /* Argon2 RFC (without key and ad values) */
+ {
+ "argon2i", NULL, 0, 3, 32, 4,
+ "\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01", 32,
+ "\x02\x02\x02\x02\x02\x02\x02\x02"
+ "\x02\x02\x02\x02\x02\x02\x02\x02", 16,
+// "\x03\x03\x03\x03\x03\x03\x03\x03", 8,
+// "\x04\x04\x04\x04\x04\x04\x04\x04"
+// "\x04\x04\x04\x04", 12,
+ "\xa9\xa7\x51\x0e\x6d\xb4\xd5\x88"
+ "\xba\x34\x14\xcd\x0e\x09\x4d\x48"
+ "\x0d\x68\x3f\x97\xb9\xcc\xb6\x12"
+ "\xa5\x44\xfe\x8e\xf6\x5b\xa8\xe0", 32
+// "\xc8\x14\xd9\xd1\xdc\x7f\x37\xaa"
+// "\x13\xf0\xd7\x7f\x24\x94\xbd\xa1"
+// "\xc8\xde\x6b\x01\x6d\xd3\x88\xd2"
+// "\x99\x52\xa4\xc4\x67\x2b\x6c\xe8", 32
+ },
+ {
+ "argon2id", NULL, 0, 3, 32, 4,
+ "\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x01\x01", 32,
+ "\x02\x02\x02\x02\x02\x02\x02\x02"
+ "\x02\x02\x02\x02\x02\x02\x02\x02", 16,
+// "\x03\x03\x03\x03\x03\x03\x03\x03", 8,
+// "\x04\x04\x04\x04\x04\x04\x04\x04"
+// "\x04\x04\x04\x04", 12,
+ "\x03\xaa\xb9\x65\xc1\x20\x01\xc9"
+ "\xd7\xd0\xd2\xde\x33\x19\x2c\x04"
+ "\x94\xb6\x84\xbb\x14\x81\x96\xd7"
+ "\x3c\x1d\xf1\xac\xaf\x6d\x0c\x2e", 32
+// "\x0d\x64\x0d\xf5\x8d\x78\x76\x6c"
+// "\x08\xc0\x37\xa3\x4a\x8b\x53\xc9"
+// "\xd0\x1e\xf0\x45\x2d\x75\xb6\x5e"
+// "\xb5\x25\x20\xe9\x6b\x01\xe6\x59", 32
+ },
+ /* empty password */
+ {
+ "argon2i", NULL, 0, 3, 128, 1,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+ "\xbb\x1f\xf2\xb9\x9f\xd4\x4a\xd9"
+ "\xdf\x7f\xb9\x54\x55\x9e\xb8\xeb"
+ "\xb5\x9d\xab\xce\x2e\x62\x9f\x9b"
+ "\x89\x09\xfe\xde\x57\xcc\x63\x86", 32
+ },
+ {
+ "argon2id", NULL, 0, 3, 128, 1,
+ "", 0,
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+ "\x09\x2f\x38\x35\xac\xb2\x43\x92"
+ "\x93\xeb\xcd\xe8\x04\x16\x6a\x31"
+ "\xce\x14\xd4\x55\xdb\xd8\xf7\xe6"
+ "\xb4\xf5\x9d\x64\x8e\xd0\x3a\xdb", 32
+ },
+ /* RFC 3962 */
+ {
+ "pbkdf2", "sha1", 64, 1, 0, 0,
+ "password", 8,
+ "ATHENA.MIT.EDUraeburn", 21,
+ "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01"
+ "\x56\x5a\x11\x22\xb2\x56\x35\x15"
+ "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3"
+ "\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32
+ }, {
+ "pbkdf2", "sha1", 64, 2, 0, 0,
+ "password", 8,
+ "ATHENA.MIT.EDUraeburn", 21,
+ "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e"
+ "\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
+ "\xa0\x53\x78\xb9\x32\x44\xec\x8f"
+ "\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32
+ }, {
+ "pbkdf2", "sha1", 64, 1200, 0, 0,
+ "password", 8,
+ "ATHENA.MIT.EDUraeburn", 21,
+ "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e"
+ "\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
+ "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f"
+ "\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32
+ }, {
+ "pbkdf2", "sha1", 64, 5, 0, 0,
+ "password", 8,
+ "\0224VxxV4\022", 8, // "\x1234567878563412
+ "\xd1\xda\xa7\x86\x15\xf2\x87\xe6"
+ "\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
+ "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6"
+ "\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32
+ }, {
+ "pbkdf2", "sha1", 64, 1200, 0, 0,
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 64,
+ "pass phrase equals block size", 29,
+ "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b"
+ "\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
+ "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc"
+ "\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32
+ }, {
+ "pbkdf2", "sha1", 64, 1200, 0, 0,
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
+ "pass phrase exceeds block size", 30,
+ "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5"
+ "\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
+ "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b"
+ "\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32
+ }, {
+ "pbkdf2", "sha1", 64, 50, 0, 0,
+ "\360\235\204\236", 4, // g-clef ("\xf09d849e)
+ "EXAMPLE.COMpianist", 18,
+ "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43"
+ "\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
+ "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2"
+ "\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32
+ }, {
+ /* RFC-6070 */
+ "pbkdf2", "sha1", 64, 1, 0, 0,
+ "password", 8,
+ "salt", 4,
+ "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
+ "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20
+ }, {
+ "pbkdf2", "sha1", 64, 2, 0, 0,
+ "password", 8,
+ "salt", 4,
+ "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
+ "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20
+ }, {
+ "pbkdf2", "sha1", 64, 4096, 0, 0,
+ "password", 8,
+ "salt", 4,
+ "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
+ "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20
+ }, {
+ "pbkdf2", "sha1", 64, 16777216, 0, 0,
+ "password", 8,
+ "salt", 4,
+ "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
+ "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20
+ }, {
+ "pbkdf2", "sha1", 64, 4096, 0, 0,
+ "passwordPASSWORDpassword", 24,
+ "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+ "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
+ "\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
+ "\x4c\xf2\xf0\x70\x38", 25
+ }, {
+ "pbkdf2", "sha1", 64, 4096, 0, 0,
+ "pass\0word", 9,
+ "sa\0lt", 5,
+ "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
+ "\xd7\xf0\x34\x25\xe0\xc3", 16
+ }, {
+ /* empty password test */
+ "pbkdf2", "sha1", 64, 2, 0, 0,
+ "", 0,
+ "salt", 4,
+ "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
+ "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20
+ }, {
+ /* Password exceeds block size test */
+ "pbkdf2", "sha256", 64, 1200, 0, 0,
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
+ "pass phrase exceeds block size", 30,
+ "\x22\x34\x4b\xc4\xb6\xe3\x26\x75"
+ "\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d"
+ "\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa"
+ "\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32
+ }, {
+ "pbkdf2", "sha512", 128, 1200, 0, 0,
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 129,
+ "pass phrase exceeds block size", 30,
+ "\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d"
+ "\x7d\x8e\xdd\x58\x01\xb4\x59\x72"
+ "\x99\x92\x16\x30\x5e\xa4\x36\x8d"
+ "\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32
+ }, {
+ "pbkdf2", "whirlpool", 64, 1200, 0, 0,
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
+ "pass phrase exceeds block size", 30,
+ "\x9c\x1c\x74\xf5\x88\x26\xe7\x6a"
+ "\x53\x58\xf4\x0c\x39\xe7\x80\x89"
+ "\x07\xc0\x31\x19\x9a\x50\xa2\x48"
+ "\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32
+ }
+};
+
+/*
+ * Hash tests
+ */
+struct hash_test_vector {
+ const char *data;
+ unsigned int data_length;
+ struct {
+ const char *name;
+ unsigned int length;
+ const char *out;
+ } out[8];
+};
+
+static struct hash_test_vector hash_test_vectors[] = {
+{
+ "", 0, {
+ { "crc32", 4, "\x00\x00\x00\x00" },
+ { "sha1", 20, "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18\x90\xaf\xd8\x07\x09" },
+ { "sha256", 32, "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24"
+ "\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55" },
+ { "sha512", 64, "\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
+ "\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
+ "\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
+ "\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
+ { "ripemd160", 20, "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" },
+ { "whirlpool", 64, "\x19\xfa\x61\xd7\x55\x22\xa4\x66\x9b\x44\xe3\x9c\x1d\x2e\x17\x26"
+ "\xc5\x30\x23\x21\x30\xd4\x07\xf8\x9a\xfe\xe0\x96\x49\x97\xf7\xa7"
+ "\x3e\x83\xbe\x69\x8b\x28\x8f\xeb\xcf\x88\xe3\xe0\x3c\x4f\x07\x57"
+ "\xea\x89\x64\xe5\x9b\x63\xd9\x37\x08\xb1\x38\xcc\x42\xa6\x6e\xb3" },
+ { "blake2b-512",64,"\x78\x6a\x02\xf7\x42\x01\x59\x03\xc6\xc6\xfd\x85\x25\x52\xd2\x72"
+ "\x91\x2f\x47\x40\xe1\x58\x47\x61\x8a\x86\xe2\x17\xf7\x1f\x54\x19"
+ "\xd2\x5e\x10\x31\xaf\xee\x58\x53\x13\x89\x64\x44\x93\x4e\xb0\x4b"
+ "\x90\x3a\x68\x5b\x14\x48\xb7\x55\xd5\x6f\x70\x1a\xfe\x9b\xe2\xce" },
+ { "blake2s-256",32,"\x69\x21\x7a\x30\x79\x90\x80\x94\xe1\x11\x21\xd0\x42\x35\x4a\x7c"
+ "\x1f\x55\xb6\x48\x2c\xa1\xa5\x1e\x1b\x25\x0d\xfd\x1e\xd0\xee\xf9" },
+}},{
+ "a", 1, {
+ { "crc32", 4, "\xe8\xb7\xbe\x43" },
+ { "sha1", 20, "\x86\xf7\xe4\x37\xfa\xa5\xa7\xfc\xe1\x5d\x1d\xdc\xb9\xea\xea\xea\x37\x76\x67\xb8" },
+ { "sha256", 32, "\xca\x97\x81\x12\xca\x1b\xbd\xca\xfa\xc2\x31\xb3\x9a\x23\xdc\x4d"
+ "\xa7\x86\xef\xf8\x14\x7c\x4e\x72\xb9\x80\x77\x85\xaf\xee\x48\xbb" },
+ { "sha512", 64, "\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
+ "\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
+ "\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
+ "\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
+ { "ripemd160", 20, "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe" },
+ { "whirlpool", 64, "\x8a\xca\x26\x02\x79\x2a\xec\x6f\x11\xa6\x72\x06\x53\x1f\xb7\xd7"
+ "\xf0\xdf\xf5\x94\x13\x14\x5e\x69\x73\xc4\x50\x01\xd0\x08\x7b\x42"
+ "\xd1\x1b\xc6\x45\x41\x3a\xef\xf6\x3a\x42\x39\x1a\x39\x14\x5a\x59"
+ "\x1a\x92\x20\x0d\x56\x01\x95\xe5\x3b\x47\x85\x84\xfd\xae\x23\x1a" },
+ { "blake2b-512",64,"\x33\x3f\xcb\x4e\xe1\xaa\x7c\x11\x53\x55\xec\x66\xce\xac\x91\x7c"
+ "\x8b\xfd\x81\x5b\xf7\x58\x7d\x32\x5a\xec\x18\x64\xed\xd2\x4e\x34"
+ "\xd5\xab\xe2\xc6\xb1\xb5\xee\x3f\xac\xe6\x2f\xed\x78\xdb\xef\x80"
+ "\x2f\x2a\x85\xcb\x91\xd4\x55\xa8\xf5\x24\x9d\x33\x08\x53\xcb\x3c" },
+ { "blake2s-256",32,"\x4a\x0d\x12\x98\x73\x40\x30\x37\xc2\xcd\x9b\x90\x48\x20\x36\x87"
+ "\xf6\x23\x3f\xb6\x73\x89\x56\xe0\x34\x9b\xd4\x32\x0f\xec\x3e\x90" },
+}},{
+ "abc", 3, {
+ { "crc32", 4, "\x35\x24\x41\xc2" },
+ { "sha1", 20, "\xa9\x99\x3e\x36\x47\x06\x81\x6a\xba\x3e\x25\x71\x78\x50\xc2\x6c\x9c\xd0\xd8\x9d" },
+ { "sha256", 32, "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23"
+ "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" },
+ { "sha512", 64, "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
+ "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
+ "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
+ "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
+ { "ripemd160", 20, "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6\xb0\x87\xf1\x5a\x0b\xfc" },
+ { "whirlpool", 64, "\x4e\x24\x48\xa4\xc6\xf4\x86\xbb\x16\xb6\x56\x2c\x73\xb4\x02\x0b"
+ "\xf3\x04\x3e\x3a\x73\x1b\xce\x72\x1a\xe1\xb3\x03\xd9\x7e\x6d\x4c"
+ "\x71\x81\xee\xbd\xb6\xc5\x7e\x27\x7d\x0e\x34\x95\x71\x14\xcb\xd6"
+ "\xc7\x97\xfc\x9d\x95\xd8\xb5\x82\xd2\x25\x29\x20\x76\xd4\xee\xf5" },
+ { "blake2b-512",64,"\xba\x80\xa5\x3f\x98\x1c\x4d\x0d\x6a\x27\x97\xb6\x9f\x12\xf6\xe9"
+ "\x4c\x21\x2f\x14\x68\x5a\xc4\xb7\x4b\x12\xbb\x6f\xdb\xff\xa2\xd1"
+ "\x7d\x87\xc5\x39\x2a\xab\x79\x2d\xc2\x52\xd5\xde\x45\x33\xcc\x95"
+ "\x18\xd3\x8a\xa8\xdb\xf1\x92\x5a\xb9\x23\x86\xed\xd4\x00\x99\x23" },
+ { "blake2s-256",32,"\x50\x8c\x5e\x8c\x32\x7c\x14\xe2\xe1\xa7\x2b\xa3\x4e\xeb\x45\x2f"
+ "\x37\x45\x8b\x20\x9e\xd6\x3a\x29\x4d\x99\x9b\x4c\x86\x67\x59\x82" },
+}},{
+ "abcdefghijklmnopqrstuvwxyz", 26, {
+ { "crc32", 4, "\x4c\x27\x50\xbd" },
+ { "sha1", 20, "\x32\xd1\x0c\x7b\x8c\xf9\x65\x70\xca\x04\xce\x37\xf2\xa1\x9d\x84\x24\x0d\x3a\x89" },
+ { "sha256", 32, "\x71\xc4\x80\xdf\x93\xd6\xae\x2f\x1e\xfa\xd1\x44\x7c\x66\xc9\x52"
+ "\x5e\x31\x62\x18\xcf\x51\xfc\x8d\x9e\xd8\x32\xf2\xda\xf1\x8b\x73" },
+ { "sha512", 64, "\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
+ "\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
+ "\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
+ "\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
+ { "ripemd160", 20, "\xf7\x1c\x27\x10\x9c\x69\x2c\x1b\x56\xbb\xdc\xeb\x5b\x9d\x28\x65\xb3\x70\x8d\xbc" },
+ { "whirlpool", 64, "\xf1\xd7\x54\x66\x26\x36\xff\xe9\x2c\x82\xeb\xb9\x21\x2a\x48\x4a"
+ "\x8d\x38\x63\x1e\xad\x42\x38\xf5\x44\x2e\xe1\x3b\x80\x54\xe4\x1b"
+ "\x08\xbf\x2a\x92\x51\xc3\x0b\x6a\x0b\x8a\xae\x86\x17\x7a\xb4\xa6"
+ "\xf6\x8f\x67\x3e\x72\x07\x86\x5d\x5d\x98\x19\xa3\xdb\xa4\xeb\x3b" },
+ { "blake2b-512",64,"\xc6\x8e\xde\x14\x3e\x41\x6e\xb7\xb4\xaa\xae\x0d\x8e\x48\xe5\x5d"
+ "\xd5\x29\xea\xfe\xd1\x0b\x1d\xf1\xa6\x14\x16\x95\x3a\x2b\x0a\x56"
+ "\x66\xc7\x61\xe7\xd4\x12\xe6\x70\x9e\x31\xff\xe2\x21\xb7\xa7\xa7"
+ "\x39\x08\xcb\x95\xa4\xd1\x20\xb8\xb0\x90\xa8\x7d\x1f\xbe\xdb\x4c" },
+ { "blake2s-256",32,"\xbd\xf8\x8e\xb1\xf8\x6a\x0c\xdf\x0e\x84\x0b\xa8\x8f\xa1\x18\x50"
+ "\x83\x69\xdf\x18\x6c\x73\x55\xb4\xb1\x6c\xf7\x9f\xa2\x71\x0a\x12" },
+}},{
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, {
+ { "crc32", 4, "\x1f\xc2\xe6\xd2" },
+ { "sha1", 20, "\x76\x1c\x45\x7b\xf7\x3b\x14\xd2\x7e\x9e\x92\x65\xc4\x6f\x4b\x4d\xda\x11\xf9\x40" },
+ { "sha256", 32, "\xdb\x4b\xfc\xbd\x4d\xa0\xcd\x85\xa6\x0c\x3c\x37\xd3\xfb\xd8\x80"
+ "\x5c\x77\xf1\x5f\xc6\xb1\xfd\xfe\x61\x4e\xe0\xa7\xc8\xfd\xb4\xc0" },
+ { "sha512", 64, "\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
+ "\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
+ "\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
+ "\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
+ { "ripemd160", 20, "\xb0\xe2\x0b\x6e\x31\x16\x64\x02\x86\xed\x3a\x87\xa5\x71\x30\x79\xb2\x1f\x51\x89" },
+ { "whirlpool", 64, "\xdc\x37\xe0\x08\xcf\x9e\xe6\x9b\xf1\x1f\x00\xed\x9a\xba\x26\x90"
+ "\x1d\xd7\xc2\x8c\xde\xc0\x66\xcc\x6a\xf4\x2e\x40\xf8\x2f\x3a\x1e"
+ "\x08\xeb\xa2\x66\x29\x12\x9d\x8f\xb7\xcb\x57\x21\x1b\x92\x81\xa6"
+ "\x55\x17\xcc\x87\x9d\x7b\x96\x21\x42\xc6\x5f\x5a\x7a\xf0\x14\x67" },
+ { "blake2b-512",64,"\x99\x96\x48\x02\xe5\xc2\x5e\x70\x37\x22\x90\x5d\x3f\xb8\x00\x46"
+ "\xb6\xbc\xa6\x98\xca\x9e\x2c\xc7\xe4\x9b\x4f\xe1\xfa\x08\x7c\x2e"
+ "\xdf\x03\x12\xdf\xbb\x27\x5c\xf2\x50\xa1\xe5\x42\xfd\x5d\xc2\xed"
+ "\xd3\x13\xf9\xc4\x91\x12\x7c\x2e\x8c\x0c\x9b\x24\x16\x8e\x2d\x50" },
+ { "blake2s-256",32,"\xc7\x54\x39\xea\x17\xe1\xde\x6f\xa4\x51\x0c\x33\x5d\xc3\xd3\xf3"
+ "\x43\xe6\xf9\xe1\xce\x27\x73\xe2\x5b\x41\x74\xf1\xdf\x8b\x11\x9b" },
+}},{
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56, {
+ { "crc32", 4, "\x17\x1a\x3f\x5f" },
+ { "sha1", 20, "\x84\x98\x3e\x44\x1c\x3b\xd2\x6e\xba\xae\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1" },
+ { "sha256", 32, "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
+ "\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
+ { "sha512", 64, "\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
+ "\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
+ "\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
+ "\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
+ { "ripemd160", 20, "\x12\xa0\x53\x38\x4a\x9c\x0c\x88\xe4\x05\xa0\x6c\x27\xdc\xf4\x9a\xda\x62\xeb\x2b" },
+ { "whirlpool", 64, "\x52\x6b\x23\x94\xd8\x56\x83\xe2\x4b\x29\xac\xd0\xfd\x37\xf7\xd5"
+ "\x02\x7f\x61\x36\x6a\x14\x07\x26\x2d\xc2\xa6\xa3\x45\xd9\xe2\x40"
+ "\xc0\x17\xc1\x83\x3d\xb1\xe6\xdb\x6a\x46\xbd\x44\x4b\x0c\x69\x52"
+ "\x0c\x85\x6e\x7c\x6e\x9c\x36\x6d\x15\x0a\x7d\xa3\xae\xb1\x60\xd1" },
+ { "blake2b-512",64,"\x72\x85\xff\x3e\x8b\xd7\x68\xd6\x9b\xe6\x2b\x3b\xf1\x87\x65\xa3"
+ "\x25\x91\x7f\xa9\x74\x4a\xc2\xf5\x82\xa2\x08\x50\xbc\x2b\x11\x41"
+ "\xed\x1b\x3e\x45\x28\x59\x5a\xcc\x90\x77\x2b\xdf\x2d\x37\xdc\x8a"
+ "\x47\x13\x0b\x44\xf3\x3a\x02\xe8\x73\x0e\x5a\xd8\xe1\x66\xe8\x88" },
+ { "blake2s-256",32,"\x6f\x4d\xf5\x11\x6a\x6f\x33\x2e\xda\xb1\xd9\xe1\x0e\xe8\x7d\xf6"
+ "\x55\x7b\xea\xb6\x25\x9d\x76\x63\xf3\xbc\xd5\x72\x2c\x13\xf1\x89" },
+}},{
+ "message digest", 14, {
+ { "crc32", 4, "\x20\x15\x9d\x7f" },
+ { "sha1", 20, "\xc1\x22\x52\xce\xda\x8b\xe8\x99\x4d\x5f\xa0\x29\x0a\x47\x23\x1c\x1d\x16\xaa\xe3" },
+ { "sha256", 32, "\xf7\x84\x6f\x55\xcf\x23\xe1\x4e\xeb\xea\xb5\xb4\xe1\x55\x0c\xad"
+ "\x5b\x50\x9e\x33\x48\xfb\xc4\xef\xa3\xa1\x41\x3d\x39\x3c\xb6\x50" },
+ { "sha512", 64, "\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
+ "\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
+ "\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
+ "\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
+ { "ripemd160", 20, "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36" },
+ { "whirlpool", 64, "\x37\x8c\x84\xa4\x12\x6e\x2d\xc6\xe5\x6d\xcc\x74\x58\x37\x7a\xac"
+ "\x83\x8d\x00\x03\x22\x30\xf5\x3c\xe1\xf5\x70\x0c\x0f\xfb\x4d\x3b"
+ "\x84\x21\x55\x76\x59\xef\x55\xc1\x06\xb4\xb5\x2a\xc5\xa4\xaa\xa6"
+ "\x92\xed\x92\x00\x52\x83\x8f\x33\x62\xe8\x6d\xbd\x37\xa8\x90\x3e" },
+ { "blake2b-512",64,"\x3c\x26\xce\x48\x7b\x1c\x0f\x06\x23\x63\xaf\xa3\xc6\x75\xeb\xdb"
+ "\xf5\xf4\xef\x9b\xdc\x02\x2c\xfb\xef\x91\xe3\x11\x1c\xdc\x28\x38"
+ "\x40\xd8\x33\x1f\xc3\x0a\x8a\x09\x06\xcf\xf4\xbc\xdb\xcd\x23\x0c"
+ "\x61\xaa\xec\x60\xfd\xfa\xd4\x57\xed\x96\xb7\x09\xa3\x82\x35\x9a" },
+ { "blake2s-256",32,"\xfa\x10\xab\x77\x5a\xcf\x89\xb7\xd3\xc8\xa6\xe8\x23\xd5\x86\xf6"
+ "\xb6\x7b\xdb\xac\x4c\xe2\x07\xfe\x14\x5b\x7d\x3a\xc2\x5c\xd2\x8c" },
+}}};
+
+/*
+ * HMAC tests
+ */
+// RFC 4231 - HMAC test vectors for SHA-256, SHA-512
+// RFC 2202 - HMAC test vectors for SHA-1
+
+struct hmac_test_vector {
+ const char *key;
+ unsigned int key_length;
+ const char *data;
+ unsigned int data_length;
+ struct {
+ const char *name;
+ unsigned int length;
+ const char *out;
+ } out[3];
+};
+
+static struct hmac_test_vector hmac_test_vectors[] = {
+{
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", 20,
+ "\x48\x69\x20\x54\x68\x65\x72\x65", 8, /* "Hi There" */ {
+ { "sha1", 20, "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00" },
+ { "sha256", 32, "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b"
+ "\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" },
+ { "sha512", 64, "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0"
+ "\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde"
+ "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4"
+ "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" },
+}},{
+ "\x4a\x65\x66\x65", 4, /* "Jefe" */
+ "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20"
+ "\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", 28, /* "what do ya want for nothing?" */ {
+ { "sha1", 20, "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79" },
+ { "sha256", 32, "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7"
+ "\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" },
+ { "sha512", 64, "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3"
+ "\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54"
+ "\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd"
+ "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" },
+}},{
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 20,
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", 50, {
+ { "sha1", 20, "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3" },
+ { "sha256", 32, "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7"
+ "\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" },
+ { "sha512", 64, "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9"
+ "\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39"
+ "\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07"
+ "\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" },
+}},{
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", 50, {
+ { "sha1", 20, "\x4c\x90\x07\xf4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c\x2d\x72\x35\xda" },
+ { "sha256", 32, "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08\x3a"
+ "\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" },
+ { "sha512", 64, "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7"
+ "\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb"
+ "\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63"
+ "\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" },
+}},{
+ // Long key
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131,
+ "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65"
+ "\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a"
+ "\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79"
+ "\x20\x46\x69\x72\x73\x74", 54, /* "Test Using Larger Than Block-Size Key - Hash Key First" */ {
+ { "sha1", 20, "\x90\xd0\xda\xce\x1c\x1b\xdc\x95\x73\x39\x30\x78\x03\x16\x03\x35\xbd\xe6\xdf\x2b" },
+ { "sha256", 32, "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f"
+ "\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" },
+ { "sha512", 64, "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4"
+ "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52"
+ "\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52"
+ "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" },
+}},{
+ // Long key and long data
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", 131,
+ "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75"
+ "\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68"
+ "\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65"
+ "\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74"
+ "\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64"
+ "\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65"
+ "\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20"
+ "\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65"
+ "\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e", 152, {
+ { "sha1", 20, "\x21\x7e\x44\xbb\x08\xb6\xe0\x6a\x2d\x6c\x30\xf3\xcb\x9f\x53\x7f\x97\xc6\x33\x56" },
+ { "sha256", 32, "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44"
+ "\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" },
+ { "sha512", 64, "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd"
+ "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44"
+ "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15"
+ "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" },
+}}};
+
+/*
+ * Block cipher tests
+ */
+struct cipher_test_vector {
+ const char *key;
+ unsigned int key_length;
+ const char *iv;
+ unsigned int iv_length;
+ const char *plaintext;
+ unsigned int data_length;
+ struct {
+ const char *name;
+ const char *mode;
+ const char *ciphertext;
+ } out[2];
+};
+
+static struct cipher_test_vector cipher_test_vectors[] = {
+{ // NIST SP 800-38A
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ NULL, 0,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, {
+ {
+ "aes", "ecb",
+ "\x3a\xd7\x7b\xb4\x0d\x7a\x36\x60\xa8\x9e\xca\xf3\x24\x66\xef\x97"
+ "\xf5\xd3\xd5\x85\x03\xb9\x69\x9d\xe7\x85\x89\x5a\x96\xfd\xba\xaf"
+ "\x43\xb1\xcd\x7f\x59\x8e\xce\x23\x88\x1b\x00\xe3\xed\x03\x06\x88"
+ "\x7b\x0c\x78\x5e\x27\xe8\xad\x3f\x82\x23\x20\x71\x04\x72\x5d\xd4"
+ },{
+ "serpent", "ecb",
+ "\xf7\xa7\x21\xe6\xc7\x56\xb6\x55\xcb\xdf\x53\x3f\xc3\xb3\x1a\xc4"
+ "\x4b\xc6\x04\x29\x3a\x81\xa6\xa6\xe4\xcb\xa7\x8d\x1a\x32\xa2\x9e"
+ "\xcf\xc2\x8e\x50\x97\xdd\x6b\x49\xa9\x38\xb1\x51\x5e\xbc\x5a\xac"
+ "\xfe\xd2\xc4\x95\x92\xf9\x1c\x0c\x9f\x17\xcd\x86\x38\x65\x29\xeb"
+ },
+}},{ // NIST SP 800-38A
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, {
+ {
+ "aes", "cbc",
+ "\x76\x49\xab\xac\x81\x19\xb2\x46\xce\xe9\x8e\x9b\x12\xe9\x19\x7d"
+ "\x50\x86\xcb\x9b\x50\x72\x19\xee\x95\xdb\x11\x3a\x91\x76\x78\xb2"
+ "\x73\xbe\xd6\xb8\xe3\xc1\x74\x3b\x71\x16\xe6\x9e\x22\x22\x95\x16"
+ "\x3f\xf1\xca\xa1\x68\x1f\xac\x09\x12\x0e\xca\x30\x75\x86\xe1\xa7"
+ },{
+ "serpent", "cbc",
+ "\xdd\x73\x69\x1a\xb5\x66\xb6\x38\xe3\xb9\x62\x36\xc8\xc8\xa1\xdd"
+ "\xa9\xb5\xd9\xdb\x20\xfb\x8b\x82\x51\x40\xbf\xe6\x4d\xf2\x1c\xa8"
+ "\x5f\x48\xbc\x29\xff\x62\x27\xda\x09\x7c\xaa\x22\x75\x6f\x43\xff"
+ "\x31\xd8\x3e\x83\x4d\x92\x48\xeb\x49\x1c\xf8\x26\x80\x4e\xb9\x02"
+ },
+}},{ // NIST SP 800-38A
+ "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32,
+ NULL, 0,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, {
+ {
+ "aes", "ecb",
+ "\xf3\xee\xd1\xbd\xb5\xd2\xa0\x3c\x06\x4b\x5a\x7e\x3d\xb1\x81\xf8"
+ "\x59\x1c\xcb\x10\xd4\x10\xed\x26\xdc\x5b\xa7\x4a\x31\x36\x28\x70"
+ "\xb6\xed\x21\xb9\x9c\xa6\xf4\xf9\xf1\x53\xe7\xb1\xbe\xaf\xed\x1d"
+ "\x23\x30\x4b\x7a\x39\xf9\xf3\xff\x06\x7d\x8d\x8f\x9e\x24\xec\xc7"
+ },{
+ "serpent", "ecb",
+ "\x78\xe5\x84\x8e\xd9\xd5\xde\x2d\x4d\xb0\x2f\x53\x61\x6a\xfd\xf2"
+ "\x50\x5d\xf1\x68\x92\x40\x8e\xf6\x9c\x3b\x9e\xa6\x67\xd9\xdd\xb8"
+ "\xb9\x5f\xc8\x20\x76\x52\x1d\xce\x60\xe4\xfc\xac\xe3\xd3\x91\x51"
+ "\x09\x22\x62\xde\x62\x6d\xc5\x7b\x4c\x87\x0c\x65\xe7\x1f\xc7\x13"
+ },
+}},{ // NIST SP 800-38A
+ "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81"
+ "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", 16,
+ "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
+ "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
+ "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
+ "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 64, {
+ {
+ "aes", "cbc",
+ "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6"
+ "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d\x67\x9f\x77\x7b\xc6\x70\x2c\x7d"
+ "\x39\xf2\x33\x69\xa9\xd9\xba\xcf\xa5\x30\xe2\x63\x04\x23\x14\x61"
+ "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc\xda\x6c\x19\x07\x8c\x6a\x9d\x1b"
+ },{
+ "serpent", "cbc",
+ "\xb8\x93\xc8\xde\xc5\xc8\x5f\x03\x01\xac\x32\x74\xdf\xc6\x71\x9d"
+ "\x37\x61\xc5\xf8\x34\x4d\xe9\x10\x91\xd3\x87\x80\x42\xcc\x70\x95"
+ "\x40\x95\xa3\x2c\xdb\x38\xe2\x6f\x03\x91\xf5\xd3\x51\x7e\x52\xb0"
+ "\x8a\x1c\x2d\x7f\x04\x59\x13\x93\x31\xa9\x82\xc9\x4e\xd9\x11\x0c"
+ },
+}},{ // CAVS XTSGenAES128,101
+ "\xb7\xb9\x3f\x51\x6a\xef\x29\x5e\xff\x3a\x29\xd8\x37\xcf\x1f\x13"
+ "\x53\x47\xe8\xa2\x1d\xae\x61\x6f\xf5\x06\x2b\x2e\x8d\x78\xce\x5e", 32,
+ "\x87\x3e\xde\xa6\x53\xb6\x43\xbd\x8b\xcf\x51\x40\x31\x97\xed\x14", 16,
+ "\x23\x6f\x8a\x5b\x58\xdd\x55\xf6\x19\x4e\xd7\x0c\x4a\xc1\xa1\x7f"
+ "\x1f\xe6\x0e\xc9\xa6\xc4\x54\xd0\x87\xcc\xb7\x7d\x6b\x63\x8c\x47", 32, {
+ {
+ "aes", "xts",
+ "\x22\xe6\xa3\xc6\x37\x9d\xcf\x75\x99\xb0\x52\xb5\xa7\x49\xc7\xf7"
+ "\x8a\xd8\xa1\x1b\x9f\x1a\xa9\x43\x0c\xf3\xae\xf4\x45\x68\x2e\x19"
+ },{
+ "serpent", "xts",
+ "\x6d\xa2\xa4\x2b\x18\x71\x57\xdc\x03\xaf\x8b\x82\x28\x66\x3d\xf1"
+ "\x70\x8b\x75\x98\xd2\xdd\xbf\x72\x9e\xb3\xb4\xc2\x3f\x18\xdf\xa1"
+ },
+}},{ // CAVS XTSGenAES256,101
+ "\x26\x6c\x33\x6b\x3b\x01\x48\x9f\x32\x67\xf5\x28\x35\xfd\x92\xf6"
+ "\x74\x37\x4b\x88\xb4\xe1\xeb\xd2\xd3\x6a\x5f\x45\x75\x81\xd9\xd0"
+ "\x42\xc3\xee\xf7\xb0\xb7\xe5\x13\x7b\x08\x64\x96\xb4\xd9\xe6\xac"
+ "\x65\x8d\x71\x96\xa2\x3f\x23\xf0\x36\x17\x2f\xdb\x8f\xae\xe5\x27", 64,
+ "\x06\xb2\x09\xa7\xa2\x2f\x48\x6e\xcb\xfa\xdb\x0f\x31\x37\xba\x42", 16,
+ "\xca\x7d\x65\xef\x8d\x3d\xfa\xd3\x45\xb6\x1c\xcd\xdc\xa1\xad\x81"
+ "\xde\x83\x0b\x9e\x86\xc7\xb4\x26\xd7\x6c\xb7\xdb\x76\x68\x52\xd9"
+ "\x81\xc6\xb2\x14\x09\x39\x9d\x78\xf4\x2c\xc0\xb3\x3a\x7b\xbb\x06", 48, {
+ {
+ "aes", "xts",
+ "\xc7\x32\x56\x87\x0c\xc2\xf4\xdd\x57\xac\xc7\x4b\x54\x56\xdb\xd7"
+ "\x76\x91\x2a\x12\x8b\xc1\xf7\x7d\x72\xcd\xeb\xbf\x27\x00\x44\xb7"
+ "\xa4\x3c\xee\xd2\x90\x25\xe1\xe8\xbe\x21\x1f\xa3\xc3\xed\x00\x2d"
+ },{
+ "serpent", "xts",
+ "\x37\xe4\xc0\xa9\xf1\x49\xe5\x3e\x73\xb9\x1f\xec\xdc\xe0\xbd\xc5"
+ "\x31\xd7\xef\x08\x65\x20\xe3\xad\xd9\x84\x60\xdc\x61\x6f\x26\x86"
+ "\xb8\xd5\x29\x4b\x04\x41\x52\x59\x05\x00\xb0\xc2\x9b\x30\xda\x48"
+ },
+}},{
+ "\xa5\x28\x24\x34\x1a\x3c\xd8\xf7\x05\x91\x8f\xee\x85\x1f\x35\x7f"
+ "\x80\x3d\xfc\x9b\x94\xf6\xfc\x9e\x19\x09\x00\xa9\x04\x31\x4f\x11", 32,
+ "\xa1\xba\x49\x95\xff\x34\x6d\xb8\xcd\x87\x5d\x5e\xfd\xea\x85\xdb"
+ "\x8a\x7b\x5e\xb2\x5d\x57\xdd\x62\xac\xa9\x8c\x41\x42\x94\x75\xb7", 32,
+ "\x69\xb4\xe8\x8c\x37\xe8\x67\x82\xf1\xec\x5d\x04\xe5\x14\x91\x13"
+ "\xdf\xf2\x87\x1b\x69\x81\x1d\x71\x70\x9e\x9c\x3b\xde\x49\x70\x11"
+ "\xa0\xa3\xdb\x0d\x54\x4f\x66\x69\xd7\xdb\x80\xa7\x70\x92\x68\xce"
+ "\x81\x04\x2c\xc6\xab\xae\xe5\x60\x15\xe9\x6f\xef\xaa\x8f\xa7\xa7"
+ "\x63\x8f\xf2\xf0\x77\xf1\xa8\xea\xe1\xb7\x1f\x9e\xab\x9e\x4b\x3f"
+ "\x07\x87\x5b\x6f\xcd\xa8\xaf\xb9\xfa\x70\x0b\x52\xb8\xa8\xa7\x9e"
+ "\x07\x5f\xa6\x0e\xb3\x9b\x79\x13\x79\xc3\x3e\x8d\x1c\x2c\x68\xc8"
+ "\x51\x1d\x3c\x7b\x7d\x79\x77\x2a\x56\x65\xc5\x54\x23\x28\xb0\x03", 128, {
+ {
+ "xchacha12,aes", "adiantum",
+ "\x9e\x16\xab\xed\x4b\xa7\x42\x5a\xc6\xfb\x4e\x76\xff\xbe\x03\xa0"
+ "\x0f\xe3\xad\xba\xe4\x98\x2b\x0e\x21\x48\xa0\xb8\x65\x48\x27\x48"
+ "\x84\x54\x54\xb2\x9a\x94\x7b\xe6\x4b\x29\xe9\xcf\x05\x91\x80\x1a"
+ "\x3a\xf3\x41\x96\x85\x1d\x9f\x74\x51\x56\x63\xfa\x7c\x28\x85\x49"
+ "\xf7\x2f\xf9\xf2\x18\x46\xf5\x33\x80\xa3\x3c\xce\xb2\x57\x93\xf5"
+ "\xae\xbd\xa9\xf5\x7b\x30\xc4\x93\x66\xe0\x30\x77\x16\xe4\xa0\x31"
+ "\xba\x70\xbc\x68\x13\xf5\xb0\x9a\xc1\xfc\x7e\xfe\x55\x80\x5c\x48"
+ "\x74\xa6\xaa\xa3\xac\xdc\xc2\xf5\x8d\xde\x34\x86\x78\x60\x75\x8d",
+ },{
+ "xchacha20,aes", "adiantum",
+ "\xb1\x8b\xa0\x05\x77\xa8\x4d\x59\x1b\x8e\x21\xfc\x3a\x49\xfa\xd4"
+ "\xeb\x36\xf3\xc4\xdf\xdc\xae\x67\x07\x3f\x70\x0e\xe9\x66\xf5\x0c"
+ "\x30\x4d\x66\xc9\xa4\x2f\x73\x9c\x13\xc8\x49\x44\xcc\x0a\x90\x9d"
+ "\x7c\xdd\x19\x3f\xea\x72\x8d\x58\xab\xe7\x09\x2c\xec\xb5\x44\xd2"
+ "\xca\xa6\x2d\x7a\x5c\x9c\x2b\x15\xec\x2a\xa6\x69\x91\xf9\xf3\x13"
+ "\xf7\x72\xc1\xc1\x40\xd5\xe1\x94\xf4\x29\xa1\x3e\x25\x02\xa8\x3e"
+ "\x94\xc1\x91\x14\xa1\x14\xcb\xbe\x67\x4c\xb9\x38\xfe\xa7\xaa\x32"
+ "\x29\x62\x0d\xb2\xf6\x3c\x58\x57\xc1\xd5\x5a\xbb\xd6\xa6\x2a\xe5"
+ },
+}}};
+
+/*
+ * Cipher IV tests
+ */
+struct cipher_iv_test_vector {
+ const char *cipher_name;
+ const char *cipher_mode;
+ const char *key;
+ unsigned int key_length;
+ const char *iv_name;
+ uint64_t iv_offset;
+ unsigned int data_length;
+ const char in_sha256[32];
+ struct {
+ size_t sector_size;
+ bool large_iv;
+ const char out_sha256[32];
+ } out[7];
+};
+
+static struct cipher_iv_test_vector cipher_iv_test_vectors[] = {
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "null", UINT32_MAX-7, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\xfd\x05\xd0\x4d\x51\xb9\xd4\x87\xa4\x57\x9a\x62\x07\x39\xc9\x4a"
+ "\x00\x90\x3e\xaf\xe8\xb2\xac\x12\xca\xeb\x58\xf9\x48\xf6\xef\x08"
+ },{ 1024, false,
+ "\x55\x87\x5c\xde\x86\x6a\x8b\xab\x08\xbe\x5b\x38\x17\x53\xdf\xe5"
+ "\x7e\xb9\x5f\x59\xaf\x07\xa4\xca\x6a\x24\xd1\x12\xa9\x15\x25\xf4"
+ },{ 1024, true,
+ "\x55\x87\x5c\xde\x86\x6a\x8b\xab\x08\xbe\x5b\x38\x17\x53\xdf\xe5"
+ "\x7e\xb9\x5f\x59\xaf\x07\xa4\xca\x6a\x24\xd1\x12\xa9\x15\x25\xf4"
+ },{ 2048, false,
+ "\x55\x5b\x8e\x74\x90\x9d\x0d\x4b\x74\x8c\x16\x7e\x29\xcf\xa9\xa3"
+ "\xf3\x42\x8b\x62\xda\x2d\x8c\xda\xc9\x32\xc8\x78\xe2\x7e\xd2\x70"
+ },{ 2048, true,
+ "\x55\x5b\x8e\x74\x90\x9d\x0d\x4b\x74\x8c\x16\x7e\x29\xcf\xa9\xa3"
+ "\xf3\x42\x8b\x62\xda\x2d\x8c\xda\xc9\x32\xc8\x78\xe2\x7e\xd2\x70"
+ },{ 4096, false,
+ "\xc6\x45\xba\xe0\x40\x3a\x96\x09\x5e\x46\x0d\x19\x9d\x58\x4b\x93"
+ "\x78\xc5\x3f\xa4\x2e\x9e\xb0\x19\x04\x4b\x73\x26\xf4\xa6\xb5\xc3"
+ },{ 4096, true,
+ "\xc6\x45\xba\xe0\x40\x3a\x96\x09\x5e\x46\x0d\x19\x9d\x58\x4b\x93"
+ "\x78\xc5\x3f\xa4\x2e\x9e\xb0\x19\x04\x4b\x73\x26\xf4\xa6\xb5\xc3"
+ },
+}},
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "plain", UINT32_MAX-7, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\x43\xfd\x6e\x25\x80\xb2\x13\xf5\xca\x71\x79\x18\xe4\x12\x91\xe0"
+ "\x6e\x37\x24\x32\xfd\x40\x4b\x42\xcb\xc1\x72\x1a\xc7\x5a\x19\xc8"
+ },{ 1024, false,
+ "\x18\x79\x8d\xad\xf2\x7b\x38\x03\x27\xa5\x76\x19\x07\xcd\x12\x62"
+ "\x03\x36\x57\x85\x88\x50\xd0\x6c\xf6\xdf\xf1\xcf\xb8\xcf\x01\x77"
+ },{ 1024, true,
+ "\xd0\x21\xcf\xb2\x7a\x01\xa8\x94\xb2\x87\x49\xc4\x9f\x9c\xb2\x3a"
+ "\x7c\xc4\x0d\x50\x08\xea\x4d\xfb\x87\xe4\x49\x8c\x1a\xd6\xec\x16"
+ },{ 2048, false,
+ "\xa4\x89\x72\xb9\xcf\x78\x0c\x2a\xc8\x20\x4f\xd5\x13\xcb\x75\x30"
+ "\x90\xd2\x4a\xfd\xd3\xb2\xe8\xf0\xd2\xb7\x9d\x07\xbd\xa9\x70\x97"
+ },{ 2048, true,
+ "\x2a\xcf\x07\x57\xc8\xea\x64\xc7\xd0\xd5\x28\xe6\xd1\x9a\xb5\x7d"
+ "\xe4\xb9\x63\xa2\x66\x5a\x3d\x14\xbd\x27\xc7\x09\xc0\x3c\xd9\x00"
+ },{ 4096, false,
+ "\x12\x1b\x00\x54\x6e\x2d\x08\xc1\x15\x8b\x15\x57\xc5\x11\x30\x8b"
+ "\x63\x33\x64\xa0\xd1\x45\xd6\xcb\xdd\x49\x91\x04\x29\xe6\x93\x08"
+ },{ 4096, true,
+ "\x44\xaa\xf1\x23\x0c\x34\x32\x2a\xfa\xe3\xf7\x95\x7a\x7c\xa8\x8b"
+ "\x34\x78\xbd\x12\x5c\xae\x4a\x65\x23\x8a\x6f\x3a\x96\x05\xfa\xae"
+ },
+}},
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "plain64", UINT32_MAX-7, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\xb3\x65\x7e\x6c\xba\xe0\x39\xcd\x1e\x1d\xaf\x65\xae\xb7\xda\x20"
+ "\x25\x17\x6a\x38\x75\x79\x68\x4c\x9a\x75\xc7\xfb\x2b\xa2\x17\xd2"
+ },{ 1024, false,
+ "\x0a\xa3\x23\x72\x80\xd3\x76\x33\x8b\x2b\xae\x01\x03\x99\xa5\xca"
+ "\xcd\x95\x27\x40\x27\xec\x14\x90\xfd\x58\xb0\x08\x9b\x99\x27\xe2"
+ },{ 1024, true,
+ "\xd0\x21\xcf\xb2\x7a\x01\xa8\x94\xb2\x87\x49\xc4\x9f\x9c\xb2\x3a"
+ "\x7c\xc4\x0d\x50\x08\xea\x4d\xfb\x87\xe4\x49\x8c\x1a\xd6\xec\x16"
+ },{ 2048, false,
+ "\x67\x87\xeb\xed\xe1\x16\x85\x0a\x3f\xb2\x5c\xbc\x27\x61\x99\x52"
+ "\xfe\x64\xb9\xab\x24\xdd\x2c\x1a\x2c\xff\xcd\x7e\x2e\x74\xb5\xd4"
+ },{ 2048, true,
+ "\x2a\xcf\x07\x57\xc8\xea\x64\xc7\xd0\xd5\x28\xe6\xd1\x9a\xb5\x7d"
+ "\xe4\xb9\x63\xa2\x66\x5a\x3d\x14\xbd\x27\xc7\x09\xc0\x3c\xd9\x00"
+ },{ 4096, false,
+ "\xb2\xf1\x0e\x66\xd4\x58\x4e\x93\xe7\x98\xae\x9c\x3e\xa7\xad\xf2"
+ "\x93\x1a\xaa\x3c\xc4\x90\x12\x05\x00\x58\x25\x8f\x1f\x5d\xc6\x67"
+ },{ 4096, true,
+ "\x44\xaa\xf1\x23\x0c\x34\x32\x2a\xfa\xe3\xf7\x95\x7a\x7c\xa8\x8b"
+ "\x34\x78\xbd\x12\x5c\xae\x4a\x65\x23\x8a\x6f\x3a\x96\x05\xfa\xae"
+ },
+}},
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "plain64be", UINT32_MAX-7, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\x28\xbf\x09\xe1\x68\xcc\x05\x1b\x20\xaf\x8d\x01\x36\x21\x8a\x8d"
+ "\x7a\x94\x98\xa8\x99\xe9\xf4\x66\xd8\xb7\x99\xca\x04\x58\x83\x90"
+ },{ 1024, false,
+ "\x9b\x74\xf7\xd5\x5a\x6b\xb2\x3a\xd2\x09\xdd\x80\x59\x28\x70\x8f"
+ "\x3a\x61\xf2\x14\xc3\x0d\xa8\xd7\xd9\xcb\x57\x26\x73\x88\x93\xd2"
+ },{ 1024, true,
+ "\x36\xb5\x68\x08\x29\x55\xb9\xe9\x01\xc1\xa8\xcf\x3e\x5b\x00\x28"
+ "\xb6\xd1\x35\xc5\xf7\x0c\xf6\x59\xb5\x8f\xb9\xa2\x00\x43\x29\x48"
+ },{ 2048, false,
+ "\x94\x4f\xc8\xb4\xfe\xad\xdc\x56\xf0\x62\x00\x8d\x52\x0b\x2d\x58"
+ "\xc0\x05\xd6\x1d\x47\x35\xc6\x6a\x42\xec\x98\xee\x21\x74\x7b\xe5"
+ },{ 2048, true,
+ "\x14\x6b\xaa\x2f\xf4\xa8\x24\x3f\x4e\x92\x97\x1a\xca\x1c\xbb\x46"
+ "\xa7\x08\xbb\xc5\x95\xac\x73\x81\x25\x34\x33\x41\x95\x71\xd9\xe7"
+ },{ 4096, false,
+ "\xa8\x17\x5d\x84\xc8\x16\x06\x7f\xa2\x68\xdd\x1e\x7d\x63\x34\x93"
+ "\x7b\x45\x2d\xf4\x10\x0b\x90\xfa\x14\x8b\x73\x86\xbc\x09\x4a\xe3"
+ },{ 4096, true,
+ "\xe2\xc3\x30\xd8\xa1\xb3\xa8\xeb\xde\xdc\xfe\x9b\xe0\x0b\x62\x4e"
+ "\x38\x2f\xa1\x45\x0e\x8f\x6c\xf0\x4e\x88\x58\x17\x13\xb5\x10\x98"
+ },
+}},
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "essiv:sha256", 0, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\xa5\x3e\x74\xc4\x1a\x5c\xf3\x6b\x63\x49\xd5\xd9\xbb\x7a\x89\x5a"
+ "\xd5\x3e\x76\x6f\x4c\x2d\x0b\xd3\x8b\x5e\x0e\x91\xa3\x8c\x2a\xde"
+ },{ 1024, false,
+ "\x41\x6b\xc6\x75\x2e\x99\x76\xa1\x83\xea\xd5\x97\x64\x0e\x24\x8c"
+ "\x91\x17\x03\x38\xe7\xd8\x66\x64\xaa\xd7\x27\x50\x2a\xd3\x0b\xe6"
+ },{ 1024, true,
+ "\x02\x3c\xbe\xe6\x1e\x9a\xf3\x14\xab\x16\xff\x6f\xb6\xa2\x3e\x03"
+ "\xa1\xbd\xe9\xe4\xfa\x44\x5b\x22\xc6\x53\xe8\x60\x58\x15\x99\xea"
+ },{ 2048, false,
+ "\x84\xdc\x45\xd3\x61\x03\xa8\x51\x85\x5b\xef\xf8\x92\x6b\x12\x06"
+ "\x2c\xfe\x75\x3e\xcf\x28\xd1\x8b\x4d\xcb\x88\x9e\x31\xb0\x0b\x92"
+ },{ 2048, true,
+ "\x4b\x9d\xe4\x3c\xe2\x4e\x7a\x13\x72\x02\x48\xf8\x7a\x7e\x15\xe8"
+ "\x3a\xc3\x92\x0b\xe8\x30\xac\xb7\x9a\xe0\xcf\xf9\xb1\xf5\x61\x5b"
+ },{ 4096, false,
+ "\xbb\x1b\xa3\xa9\x41\xbf\x17\xd8\x76\x19\x08\x8e\x3f\x50\xed\xfd"
+ "\x57\x1d\xd2\xc2\x8a\x32\x01\xb9\xd9\x8a\xcc\x0d\xa0\x65\x8b\x6d"
+ },{ 4096, true,
+ "\xa6\xdc\x7d\xc8\xc4\x9b\x78\x81\x72\xe9\xdd\x35\x6c\x07\xeb\x7b"
+ "\xd6\x56\x9e\xe4\xdf\xf5\xdd\x2e\x2c\x19\x8f\x63\x58\xdb\xa7\xd0"
+ },
+}},
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "benbi", 0, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\x3c\xe3\x94\xe3\x6d\x68\x5b\xdb\x5a\x8d\x71\xbf\xd3\xa6\x68\xb9"
+ "\x1f\x33\x0f\x97\xe2\xd6\xe8\xe2\xe1\xfc\x7e\x80\x28\xf1\x73\xbd"
+ },{ 1024, false,
+ "\x0f\x27\xa7\xae\x31\x9e\x71\x02\x12\x16\x44\x5f\xbb\xc6\xcb\x78"
+ "\xd4\x84\x49\xe0\x88\x85\x04\xbf\x6d\xea\x60\x76\x98\x34\x0a\x7e"
+ },{ 1024, true,
+ "\x3e\xf3\x08\x8d\x3b\x20\x4b\x51\x54\xde\x7f\x77\x5b\xcf\x02\x8b"
+ "\x0e\xb0\x74\x2e\x8e\x29\xfa\x5e\x86\xb4\xab\x65\x18\x59\x48\xb1"
+ },{ 2048, false,
+ "\xb0\x9a\xe5\x31\x5f\x2e\x9d\x13\x04\x08\x2a\x02\x71\x3d\xdb\x5d"
+ "\xb2\xc9\x68\x5b\xdc\xd1\x38\xc2\x96\xb3\x3b\x72\xda\x9d\xcb\xe6"
+ },{ 2048, true,
+ "\x6f\x34\xf0\xc1\xea\x72\xe4\xdc\x91\x91\x78\xb3\x7c\xb0\x9d\x41"
+ "\x94\xf6\xb8\xad\x05\xc4\x0e\x49\x05\x31\x90\xf0\x56\xfe\x21\x3f"
+ },{ 4096, false,
+ "\xaa\x74\x7d\xd6\x73\xa7\x77\xe1\x7f\xb9\x76\xf7\x5c\xcf\xc0\xb7"
+ "\xfa\x7b\xed\x15\xc2\x32\x7c\x27\xbb\x35\xfc\xfe\x12\xee\x14\x2d"
+ },{ 4096, true,
+ "\x71\x1b\x3d\x26\xf4\x44\x82\x72\x1b\x7a\x65\x0b\x37\x8c\x94\x5b"
+ "\x1c\xd3\x30\x2f\xf6\xce\xa4\x24\x25\xeb\x9b\xb9\x83\xe5\x71\xbb"
+ },
+}},
+{
+ "aes", "cbc",
+ "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16,
+ "eboiv", 0, 8192,
+ "\x9f\x1d\xcb\xc3\x5c\x35\x0d\x60\x27\xf9\x8b\xe0\xf5\xc8\xb4\x3b"
+ "\x42\xca\x52\xb7\x60\x44\x59\xc0\xc4\x2b\xe3\xaa\x88\x91\x3d\x47", {
+ { 512, false,
+ "\x04\x4e\x92\x9f\x79\x66\xfe\x93\x1b\xa5\xb8\x02\xfe\x7e\xf9\x26"
+ "\x7b\x64\x39\xe7\xb3\xca\xc4\x6e\xca\x27\xa0\x2f\xe2\xea\x91\x16"
+ },{ 1024, false,
+ "\xb0\x4a\xa4\xb5\xd6\x45\x7a\x86\xe9\x43\x3d\xd6\x01\xf7\x68\x8e"
+ "\xe6\x81\x8d\x50\x55\x18\x8e\x4b\xb6\xa7\x89\xdf\xe2\x4b\x94\xe2"
+ },{ 1024, true,
+ "\x95\x08\x4d\x4e\x89\xab\x91\x4e\xae\x56\x5d\xec\xf2\x78\x13\xb1"
+ "\x82\xf7\xc8\xb5\x03\xd6\xfa\xb0\xe3\xf9\xc1\x01\xc0\x0c\x35\xa4"
+ },{ 2048, false,
+ "\xd4\x00\x1f\x26\x18\xd1\x6d\xd5\xc4\xbf\x4a\x13\x30\xae\xd7\x4b"
+ "\x33\x1e\xd5\xe8\x43\x2d\x95\x84\x67\x39\x04\x51\x5f\x1f\x49\xe4"
+ },{ 2048, true,
+ "\x89\x8d\xa2\xec\x45\x7f\xf0\xac\xfc\x70\xb6\x36\xf0\x89\xca\x86"
+ "\x6b\xbf\x09\xd2\x54\xa0\x7c\xbc\x17\xd3\x4e\xb8\x10\x8a\x3f\x5d"
+ },{ 4096, false,
+ "\xd1\xd7\x4f\x70\x9a\xa0\x22\x27\x60\xdb\x40\x5a\x84\xce\x89\x2c"
+ "\x4f\x98\x55\xd2\x2d\xd1\xea\x9e\x47\xae\x8a\x83\xb5\x90\xbb\x49"
+ },{ 4096, true,
+ "\xdb\xe7\xd2\x25\xb0\x4f\x5d\x36\x20\xc4\xc2\xb4\xe8\x7e\xae\xe9"
+ "\x95\x10\x45\x5d\xdd\xc4\xcd\x33\xad\xbd\x39\x49\xf2\x85\x82\x4c"
+ },
+}}};
+
+/* Base64 test vectors */
+struct base64_test_vector {
+ size_t decoded_len;
+ const char *decoded;
+ const char *encoded;
+};
+
+static struct base64_test_vector base64_test_vectors[] = {
+ { 0, "", "" },
+ { 1, "\x00", "AA==" },
+ { 1, "f", "Zg==" },
+ { 2, "fo", "Zm8=" },
+ { 3, "foo", "Zm9v" },
+ { 4, "foob", "Zm9vYg==" },
+ { 5, "fooba", "Zm9vYmE=" },
+ { 6, "foobar", "Zm9vYmFy" },
+ { 11, "Hello world", "SGVsbG8gd29ybGQ=" },
+ { 22, "\x36\x03\x84\xdc\x4e\x03\x46\xa0\xb5\x2d\x03"
+ "\x6e\xd0\x56\xed\xa0\x37\x02\xac\xc6\x65\xd1",
+ "NgOE3E4DRqC1LQNu0FbtoDcCrMZl0Q==" },
+ { 3, "***", "Kioq" },
+ { 4, "\x01\x02\x03\x04", "AQIDBA==" },
+ { 5, "\xAD\xAD\xAD\xAD\xAD", "ra2tra0=" },
+ { 5, "\xFF\xFF\xFF\xFF\xFF", "//////8=" },
+ { 32, "\x40\xC1\x3F\xBD\x05\x4C\x72\x2A\xA3\xC2\xF2"
+ "\x11\x73\xC0\x69\xEA\x49\x7D\x35\x29\x6B\xCC"
+ "\x24\x65\xF6\xF9\xD0\x41\x08\x7B\xD7\xA9",
+ "QME/vQVMciqjwvIRc8Bp6kl9NSlrzCRl9vnQQQh716k=" },
+ { 7, "\x54\x0f\xdc\xf0\x0f\xaf\x4a", "VA/c8A+vSg==" },
+ {179, "blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah "
+ "blah blah blah blah blah blah blah blah blah",
+ "YmxhaCBibGFoIGJsYWggYmxhaCBibGFoIGJsYWggYmxh"
+ "aCBibGFoIGJsYWggYmxhaCBibGFoIGJsYWggYmxhaCBi"
+ "bGFoIGJsYWggYmxhaCBibGFoIGJsYWggYmxhaCBibGFo"
+ "IGJsYWggYmxhaCBibGFoIGJsYWggYmxhaCBibGFoIGJs"
+ "YWggYmxhaCBibGFoIGJsYWggYmxhaCBibGFoIGJsYWgg"
+ "YmxhaCBibGFoIGJsYWg=" },
+};
+
+/* UTF8 to UTF16LE test vectors */
+struct utf8_16_test_vector {
+ size_t len8;
+ size_t len16;
+ const char *utf8;
+ const char *utf16;
+};
+
+static struct utf8_16_test_vector utf8_16_test_vectors[] = {
+ { 1, 2, "a", "\x61\x00" },
+ { 16, 32, "0123456789abcdef",
+ "\x30\x00\x31\x00\x32\x00\x33\x00\x34\x00\x35\x00\x36\x00\x37\x00"
+ "\x38\x00\x39\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00\x66\x00" },
+ { 77, 78,
+ "\xf2\xa4\xa5\x94\x49\xf2\xa1\x98\x98\xd8\x8a\xe1\xb4\x88\xea\xa7"
+ "\xaa\xde\x95\xe2\x85\xb1\xe7\xb1\x9a\xf2\xb5\xa1\xae\x37\x2d\xd0"
+ "\xa9\xe1\x9a\x9c\xe8\xb0\xb7\xc8\x95\x0a\xf3\xaa\x92\xba\xf2\x83"
+ "\xb0\x99\xf0\x9b\xbe\x8f\x4f\xc8\x86\x30\xe7\xab\xa0\xda\xb9\xd8"
+ "\x89\xd8\xbc\xd7\x8a\xd9\xbc\xc3\x8f\x33\x62\xda\xb7",
+ "\x52\xda\x54\xdd\x49\x00\x45\xda\x18\xde\x0a\x06\x08\x1d\xea\xa9"
+ "\x95\x07\x71\x21\x5a\x7c\x96\xda\x6e\xdc\x37\x00\x2d\x00\x29\x04"
+ "\x9c\x16\x37\x8c\x15\x02\x0a\x00\x69\xdb\xba\xdc\xcf\xd9\x19\xdc"
+ "\x2f\xd8\x8f\xdf\x4f\x00\x06\x02\x30\x00\xe0\x7a\xb9\x06\x09\x06"
+ "\x3c\x06\xca\x05\x7c\x06\xcf\x00\x33\x00\x62\x00\xb7\x06" },
+};
+
+static int pbkdf_test_vectors(void)
+{
+ char result[256];
+ unsigned int i;
+ const struct kdf_test_vector *vec;
+
+ for (i = 0; i < ARRAY_SIZE(kdf_test_vectors); i++) {
+ crypt_backend_memzero(result, sizeof(result));
+ vec = &kdf_test_vectors[i];
+ printf("PBKDF vector %02d %s ", i, vec->type);
+ if (vec->hash && crypt_hmac_size(vec->hash) < 0) {
+ printf("[%s N/A]\n", vec->hash);
+ continue;
+ }
+ if (crypt_pbkdf(vec->type, vec->hash,
+ vec->password, vec->password_length,
+ vec->salt, vec->salt_length,
+ result, vec->output_length,
+ vec->iterations, vec->memory, vec->parallelism) < 0) {
+ printf("[%s-%s N/A]\n", vec->type, vec->hash);
+ continue;
+ }
+ if (memcmp(result, vec->output, vec->output_length)) {
+ printf("[FAILED]\n");
+ printhex(" got", result, vec->output_length);
+ printhex("want", vec->output, vec->output_length);
+ return EXIT_FAILURE;
+ }
+ printf("[OK]\n");
+ }
+ return EXIT_SUCCESS;
+}
+
+static int crc32_test(const struct hash_test_vector *vector, unsigned int i)
+{
+ uint32_t crc32;
+
+ if (vector->out[i].length != sizeof(uint32_t))
+ return EXIT_FAILURE;
+
+ crc32 = crypt_crc32(~0, (const unsigned char*)vector->data, vector->data_length) ^ ~0;
+
+ if ((unsigned char)vector->out[i].out[0] != ((crc32 >> 24) & 0xFF) ||
+ (unsigned char)vector->out[i].out[1] != ((crc32 >> 16) & 0xFF) ||
+ (unsigned char)vector->out[i].out[2] != ((crc32 >> 8) & 0xFF) ||
+ (unsigned char)vector->out[i].out[3] != ((crc32 >> 0) & 0xFF)) {
+ printf("[FAILED]\n");
+ printhex(" got", (const char *)&crc32, sizeof(crc32));
+ printhex("want", vector->out[i].out, vector->out[i].length);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int hash_test(void)
+{
+ const struct hash_test_vector *vector;
+ unsigned int i, j;
+ int r;
+ struct crypt_hash *h;
+ char result[64];
+
+ for (i = 0; i < ARRAY_SIZE(hash_test_vectors); i++) {
+ vector = &hash_test_vectors[i];
+ printf("Hash vector %02d: ", i);
+
+ for (j = 0; j < ARRAY_SIZE(vector->out); j++) {
+
+ // CRC32 vector test is special
+ if (!strcmp("crc32", vector->out[j].name)) {
+ if (crc32_test(vector, j) < 0)
+ return EXIT_FAILURE;
+ printf("[%s]", vector->out[j].name);
+ continue;
+ }
+
+ if (crypt_hash_size(vector->out[j].name) < 0) {
+ printf("[%s N/A]", vector->out[j].name);
+ continue;
+ }
+
+ if (crypt_hash_size(vector->out[j].name) != (int)vector->out[j].length)
+ return EXIT_FAILURE;
+
+ if (sizeof(result) < vector->out[j].length)
+ return EXIT_FAILURE;
+
+ crypt_backend_memzero(result, sizeof(result));
+ printf("[%s]", vector->out[j].name);
+
+ if (crypt_hash_init(&h, vector->out[j].name)) {
+ printf("[%s N/A (init)]", vector->out[j].name);
+ continue;
+ }
+
+ r = crypt_hash_write(h, vector->data, vector->data_length);
+ if (!r)
+ r = crypt_hash_final(h, result, vector->out[j].length);
+
+
+ if (r) {
+ crypt_hash_destroy(h);
+ return EXIT_FAILURE;
+ }
+
+ if (memcmp(result, vector->out[j].out, vector->out[j].length)) {
+ printf("[FAILED]\n");
+ printhex(" got", result, vector->out[j].length);
+ printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hash_destroy(h);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * After crypt_hash_final() the context must be reset, repeat
+ */
+ crypt_backend_memzero(result, sizeof(result));
+ r = crypt_hash_write(h, vector->data, vector->data_length);
+ if (!r)
+ r = crypt_hash_final(h, result, vector->out[j].length);
+
+ if (r || memcmp(result, vector->out[j].out, vector->out[j].length)) {
+ printf("[FAILED (RESET CONTEXT)]\n");
+ printhex(" got", result, vector->out[j].length);
+ printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hash_destroy(h);
+ return EXIT_FAILURE;
+ }
+
+ crypt_hash_destroy(h);
+ }
+ printf("\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int hmac_test(void)
+{
+ const struct hmac_test_vector *vector;
+ struct crypt_hmac *hmac;
+ unsigned int i, j;
+ int r;
+ char result[64];
+
+ for (i = 0; i < ARRAY_SIZE(hmac_test_vectors); i++) {
+ vector = &hmac_test_vectors[i];
+ printf("HMAC vector %02d: ", i);
+
+ for(j = 0; j < ARRAY_SIZE(vector->out); j++) {
+
+ if (crypt_hmac_size(vector->out[j].name) < 0) {
+ printf("[%s N/A]", vector->out[j].name);
+ continue;
+ }
+
+ if (crypt_hmac_size(vector->out[j].name) != (int)vector->out[j].length)
+ return EXIT_FAILURE;
+
+ if (sizeof(result) < vector->out[j].length)
+ return EXIT_FAILURE;
+
+ crypt_backend_memzero(result, sizeof(result));
+ printf("[%s]", vector->out[j].name);
+
+ if (crypt_hmac_init(&hmac, vector->out[j].name, vector->key, vector->key_length))
+ return EXIT_FAILURE;
+
+ r = crypt_hmac_write(hmac, vector->data, vector->data_length);
+ if (!r)
+ r = crypt_hmac_final(hmac, result, vector->out[j].length);
+
+ if (r) {
+ crypt_hmac_destroy(hmac);
+ return EXIT_FAILURE;
+ }
+
+ if (memcmp(result, vector->out[j].out, vector->out[j].length)) {
+ printf("[FAILED]\n");
+ printhex(" got", result, vector->out[j].length);
+ printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hmac_destroy(hmac);
+ return EXIT_FAILURE;
+ }
+
+ /*
+ * After crypt_hmac_final() the context must be reset, repeat
+ */
+ crypt_backend_memzero(result, sizeof(result));
+ r = crypt_hmac_write(hmac, vector->data, vector->data_length);
+ if (!r)
+ r = crypt_hmac_final(hmac, result, vector->out[j].length);
+
+ if (r || memcmp(result, vector->out[j].out, vector->out[j].length)) {
+ printf("[FAILED (RESET CONTEXT)]\n");
+ printhex(" got", result, vector->out[j].length);
+ printhex("want", vector->out[j].out, vector->out[j].length);
+ crypt_hmac_destroy(hmac);
+ return EXIT_FAILURE;
+ }
+
+ crypt_hmac_destroy(hmac);
+ }
+ printf("\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int cipher_test(void)
+{
+ const struct cipher_test_vector *vector;
+ struct crypt_cipher *cipher;
+ unsigned int i, j;
+ char result[256];
+ int r;
+
+ for (i = 0; i < ARRAY_SIZE(cipher_test_vectors); i++) {
+ vector = &cipher_test_vectors[i];
+ printf("CIPHER vector %02d: ", i);
+
+ for (j = 0; j < ARRAY_SIZE(vector->out); j++) {
+ if (vector->iv_length &&
+ crypt_cipher_ivsize(vector->out[j].name, vector->out[j].mode) != (int)vector->iv_length)
+ return EXIT_FAILURE;
+ if (vector->data_length > sizeof(result))
+ return EXIT_FAILURE;
+
+ r = crypt_cipher_init(&cipher, vector->out[j].name, vector->out[j].mode,
+ vector->key, vector->key_length);
+ if (r == -ENOENT || r == -ENOTSUP) {
+ printf("[%s-%s N/A]", vector->out[j].name, vector->out[j].mode);
+ continue;
+ } else {
+ printf("[%s-%s,%dbits]", vector->out[j].name, vector->out[j].mode, vector->key_length * 8);
+ if (r)
+ return EXIT_FAILURE;
+ }
+
+ crypt_backend_memzero(result, sizeof(result));
+ if (crypt_cipher_encrypt(cipher, vector->plaintext, result, vector->data_length,
+ vector->iv, vector->iv_length)) {
+ crypt_cipher_destroy(cipher);
+ return EXIT_FAILURE;
+ }
+
+ if (memcmp(vector->out[j].ciphertext, result, vector->data_length)) {
+ printf("[ENCRYPTION FAILED]\n");
+ printhex(" got", result, vector->data_length);
+ printhex("want", vector->out[j].ciphertext, vector->data_length);
+ crypt_cipher_destroy(cipher);
+ return EXIT_FAILURE;
+ }
+
+ crypt_backend_memzero(result, sizeof(result));
+ if (crypt_cipher_decrypt(cipher, vector->out[j].ciphertext, result, vector->data_length,
+ vector->iv, vector->iv_length)) {
+ crypt_cipher_destroy(cipher);
+ return EXIT_FAILURE;
+ }
+
+ if (memcmp(vector->plaintext, result, vector->data_length)) {
+ printf("[DECRYPTION FAILED]\n");
+ printhex(" got", result, vector->data_length);
+ printhex("want", vector->plaintext, vector->data_length);
+ crypt_cipher_destroy(cipher);
+ return EXIT_FAILURE;
+ }
+
+ crypt_cipher_destroy(cipher);
+ }
+ printf("\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static void get_sha256(const char *in, size_t length, char out[32])
+{
+ struct crypt_hash *h;
+
+ crypt_backend_memzero(out, 32);
+ if (crypt_hash_init(&h, "sha256"))
+ return;
+
+ if (!crypt_hash_write(h, in, length))
+ crypt_hash_final(h, out, 32);
+
+ crypt_hash_destroy(h);
+}
+
+static int cipher_iv_test(void)
+{
+ const struct cipher_iv_test_vector *vector;
+ struct crypt_storage *storage;
+ unsigned int i, j;
+ char mode_iv[256];
+ char result[8192], hash[32];
+ int r;
+
+ for (i = 0; i < ARRAY_SIZE(cipher_iv_test_vectors); i++) {
+ vector = &cipher_iv_test_vectors[i];
+ printf("IV vector %02d: [%s-%s-%s]", i, vector->cipher_name, vector->cipher_mode, vector->iv_name);
+
+ for (j = 0; j < ARRAY_SIZE(vector->out); j++) {
+ if (vector->data_length > sizeof(result))
+ return EXIT_FAILURE;
+
+ if (snprintf(mode_iv, sizeof(mode_iv)-2, "%s-%s", vector->cipher_mode, vector->iv_name) < 0)
+ return EXIT_FAILURE;
+
+ r = crypt_storage_init(&storage, vector->out[j].sector_size, vector->cipher_name, mode_iv,
+ vector->key, vector->key_length, vector->out[j].large_iv);
+ if (r == -ENOENT || r == -ENOTSUP) {
+ printf("[N/A]");
+ continue;
+ } else {
+ printf("[%i%s]", (int)vector->out[j].sector_size, vector->out[j].large_iv ? "L" : "");
+ if (r)
+ return EXIT_FAILURE;
+ }
+
+ crypt_backend_memzero(result, sizeof(result));
+ if (crypt_storage_encrypt(storage, vector->iv_offset, vector->data_length, result)) {
+ crypt_storage_destroy(storage);
+ return EXIT_FAILURE;
+ }
+
+ get_sha256(result, vector->data_length, hash);
+ if (memcmp(vector->out[j].out_sha256, hash, sizeof(hash))) {
+ printf("[ENCRYPTION FAILED]\n");
+ printhex(" got", hash, sizeof(hash));
+ printhex("want", vector->out[j].out_sha256, sizeof(vector->out[j].out_sha256));
+ crypt_storage_destroy(storage);
+ return EXIT_FAILURE;
+ }
+
+ if (crypt_storage_decrypt(storage, vector->iv_offset, vector->data_length, result)) {
+ crypt_storage_destroy(storage);
+ return EXIT_FAILURE;
+ }
+
+ get_sha256(result, vector->data_length, hash);
+ if (memcmp(vector->in_sha256, hash, sizeof(hash))) {
+ printf("[DECRYPTION FAILED]\n");
+ printhex(" got", hash, sizeof(hash));
+ printhex("want", vector->in_sha256, sizeof(vector->in_sha256));
+ crypt_storage_destroy(storage);
+ return EXIT_FAILURE;
+ }
+
+ crypt_storage_destroy(storage);
+ }
+ printf("\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int check_hash(const char *hash)
+{
+ struct crypt_hash *h;
+
+ if (crypt_hash_size(hash) < 0)
+ return EXIT_FAILURE;
+
+ if (crypt_hash_init(&h, hash))
+ return EXIT_FAILURE;
+
+ crypt_hash_destroy(h);
+ return EXIT_SUCCESS;
+}
+
+static int base64_test(void)
+{
+ unsigned int i;
+ char *s;
+ size_t s_len;
+
+ for (i = 0; i < ARRAY_SIZE(base64_test_vectors); i++) {
+ printf("BASE64 %02d ", i);
+ s = NULL;
+ s_len = 0;
+ if (crypt_base64_encode(&s, &s_len,
+ base64_test_vectors[i].decoded,
+ base64_test_vectors[i].decoded_len) < 0) {
+ printf("[ENCODE FAILED]\n");
+ return EXIT_FAILURE;
+ } else if (strcmp(s, base64_test_vectors[i].encoded)) {
+ printf("[ENCODE FAILED]\n");
+ free(s);
+ return EXIT_FAILURE;
+ }
+ printf("[encode]");
+ free(s);
+
+ s = NULL;
+ s_len = 0;
+ if (crypt_base64_decode(&s, &s_len,
+ base64_test_vectors[i].encoded,
+ strlen(base64_test_vectors[i].encoded)) < 0) {
+ printf("[DECODE FAILED]\n");
+ return EXIT_FAILURE;
+ } else if (s_len != base64_test_vectors[i].decoded_len ||
+ memcmp(s, base64_test_vectors[i].decoded, s_len)) {
+ printf("[DECODE FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ printf("[decode]\n");
+ free(s);
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int utf8_16_test(void)
+{
+ unsigned int i;
+ char s8[128], *s;
+ char16_t c16[256], s16[256], *su;
+
+ for (i = 0; i < ARRAY_SIZE(utf8_16_test_vectors); i++) {
+ printf("UTF8/16 %02d ", i);
+ crypt_backend_memzero(s16, sizeof(s16));
+ su = &s16[0];
+ if (crypt_utf8_to_utf16(&su, utf8_16_test_vectors[i].utf8,
+ utf8_16_test_vectors[i].len8) < 0 ||
+ memcmp(utf8_16_test_vectors[i].utf16, s16,
+ utf8_16_test_vectors[i].len16)) {
+ printf("[UTF8_TO_UTF16 FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ printf("[UTF8_TO_UTF16]");
+
+ crypt_backend_memzero(s8, sizeof(s8));
+ s = &s8[0];
+ memcpy(c16, utf8_16_test_vectors[i].utf16, utf8_16_test_vectors[i].len16);
+ if (crypt_utf16_to_utf8(&s, c16, utf8_16_test_vectors[i].len16) < 0 ||
+ utf8_16_test_vectors[i].len8 != strlen(s8) ||
+ memcmp(utf8_16_test_vectors[i].utf8, s8,
+ utf8_16_test_vectors[i].len8)) {
+ printf("[UTF16_TO_UTF8 FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ printf("[UTF16_TO_UTF8]\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+
+static int default_alg_test(void)
+{
+ printf("Defaults: [LUKS1 hash %s] ", DEFAULT_LUKS1_HASH);
+ if (check_hash(DEFAULT_LUKS1_HASH))
+ return EXIT_FAILURE;
+
+ printf("[PLAIN hash %s] ", DEFAULT_PLAIN_HASH);
+ if (check_hash(DEFAULT_PLAIN_HASH))
+ return EXIT_FAILURE;
+
+ printf("[VERITY hash %s] ", DEFAULT_VERITY_HASH);
+ if (check_hash(DEFAULT_VERITY_HASH))
+ return EXIT_FAILURE;
+
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+static int memcmp_test(void)
+{
+ printf("MEMEQ ");
+ if (!crypt_backend_memeq("aaaaaaaa", "bbbbbbbb", 8))
+ return EXIT_FAILURE;
+ if (crypt_backend_memeq("aaaaaaaa", "aaaaaaaa", 8))
+ return EXIT_FAILURE;
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+static void __attribute__((noreturn)) exit_test(const char *msg, int r)
+{
+ if (msg)
+ printf("%s\n", msg);
+ crypt_backend_destroy();
+ exit(r);
+}
+
+int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[])
+{
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ if (getenv("CRYPTSETUP_PATH")) {
+ printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
+ exit(77);
+ }
+
+ if (crypt_backend_init(fips_mode()))
+ exit_test("Crypto backend init error.", EXIT_FAILURE);
+
+ printf("Test vectors using %s crypto backend.\n", crypt_backend_version());
+
+ if (pbkdf_test_vectors())
+ exit_test("PBKDF test failed.", EXIT_FAILURE);
+
+ if (hash_test())
+ exit_test("HASH test failed.", EXIT_FAILURE);
+
+ if (hmac_test())
+ exit_test("HMAC test failed.", EXIT_FAILURE);
+
+ if (cipher_test())
+ exit_test("CIPHER test failed.", EXIT_FAILURE);
+
+ if (cipher_iv_test())
+ exit_test("IV test failed.", EXIT_FAILURE);
+
+ if (base64_test())
+ exit_test("BASE64 test failed.", EXIT_FAILURE);
+
+ if (memcmp_test())
+ exit_test("Memcmp test failed.", EXIT_FAILURE);
+
+ if (utf8_16_test())
+ exit_test("UTF8/16 test failed.", EXIT_FAILURE);
+
+ if (default_alg_test()) {
+ if (fips_mode())
+ printf("\nDefault compiled-in algorithms test ignored (FIPS mode on).\n");
+ else
+ exit_test("\nDefault compiled-in algorithms test failed.", EXIT_FAILURE);
+ }
+
+ exit_test(NULL, EXIT_SUCCESS);
+}
diff --git a/tests/cryptsetup-valg-supps b/tests/cryptsetup-valg-supps
new file mode 100644
index 0000000..fc9913a
--- /dev/null
+++ b/tests/cryptsetup-valg-supps
@@ -0,0 +1,14 @@
+# Suppression file for valgrind
+
+# known problem in libgcrypt
+{
+ leak_in_libgcrypt_00
+ Memcheck:Leak
+ fun:malloc
+ obj:/lib64/libgcrypt.so*
+ ...
+ obj:/lib64/libgcrypt.so*
+ fun:crypt_backend_init
+ fun:init_crypto
+ ...
+}
diff --git a/tests/device-test b/tests/device-test
new file mode 100755
index 0000000..c8b53bb
--- /dev/null
+++ b/tests/device-test
@@ -0,0 +1,363 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+MNT_DIR="./mnt_luks"
+DEV_NAME="dummy"
+DEV_NAME2="ymmud"
+PWD1="93R4P4pIqAH8"
+PWD2="mymJeD8ivEhE"
+FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+SKIP_COUNT=0
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+cleanup() {
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ udevadm settle >/dev/null 2>&1
+ if [ -d "$MNT_DIR" ] ; then
+ umount -f $MNT_DIR 2>/dev/null
+ rmdir $MNT_DIR 2>/dev/null
+ fi
+ rmmod scsi_debug >/dev/null 2>&1
+}
+
+fail()
+{
+ [ -n "$1" ] && echo "FAIL $1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ echo "TEST SKIPPED: $1"
+ cleanup
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+add_device() {
+ rmmod scsi_debug >/dev/null 2>&1
+ [ -d /sys/module/scsi_debug ] && skip "Cannot use scsi_debug module (in use or compiled-in)."
+
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ [ $? -ne 0 ] && skip "This kernel seems to not support proper scsi_debug module."
+
+ sleep 1
+ SCSI_DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+
+ [ -b "/dev/$SCSI_DEV" ] || fail "Cannot find $SCSI_DEV."
+}
+
+add_image()
+{
+ dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
+}
+
+function dm_crypt_features()
+{
+ modprobe dm-crypt >/dev/null 2>&1 || fail "dm-crypt failed to load"
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ [ $VER_MAJ -lt 1 ] && return
+ [ $VER_MAJ -gt 1 ] && {
+ DM_PERF_CPU=1
+ DM_SECTOR_SIZE=1
+ test -d /proc/sys/kernel/keys && DM_KEYRING=1
+ return
+ }
+
+ [ $VER_MIN -lt 14 ] && return
+ DM_PERF_CPU=1
+ if [ $VER_MIN -ge 17 -o \( $VER_MIN -eq 14 -a $VER_PTC -ge 5 \) ]; then
+ DM_SECTOR_SIZE=1
+ fi
+ if [ $VER_MIN -gt 18 -o \( $VER_MIN -eq 18 -a $VER_PTC -ge 1 \) ]; then
+ test -d /proc/sys/kernel/keys && DM_KEYRING=1
+ fi
+
+ [ $VER_MIN -lt 22 ] && return
+ DM_PERF_NO_WORKQUEUE=1
+}
+
+function dm_crypt_keyring_support()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+
+ # run the test with dm-crypt v1.15.0+ on purpose
+ # the fix is in dm-crypt v1.18.1+
+ [ $VER_MAJ -gt 1 ] && return 0
+ [ $VER_MAJ -lt 1 ] && return 1
+ [ $VER_MIN -ge 15 ]
+}
+
+format() # format
+{
+ add_image
+
+ echo $PWD1 | $CRYPTSETUP luksFormat --type $1 $DEV -q $FAST_PBKDF_OPT -c aes-cbc-essiv:sha256
+ [ $? -ne 0 ] && fail "Format failed."
+
+ # test some operation, just in case
+ echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $DEV -i1 --new-key-slot 1
+ [ $? -ne 0 ] && fail "Keyslot add failed."
+
+ $CRYPTSETUP -q luksKillSlot $DEV 1
+ [ $? -ne 0 ] && fail "Keyslot removal failed."
+}
+
+check_sector_size() # $1 expected sector size
+{
+ $CRYPTSETUP status $DEV_NAME | grep "sector size" | grep -q $1 || fail
+ if [ $S -gt 512 ]; then
+ dmsetup table $DEV_NAME | grep -q "sector_size:$1" || fail
+ fi
+}
+
+check_io()
+{
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M count=32 iflag=direct 2>/dev/null || fail
+ dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M count=32 oflag=direct 2>/dev/null || fail
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+if [ $(id -u) != 0 ]; then
+ skip "You must be root to run this test, test skipped."
+fi
+
+dm_crypt_features
+
+[ ! -d $MNT_DIR ] && mkdir $MNT_DIR
+
+echo "[1] Using tmpfs for image"
+DEV="$MNT_DIR/test.img"
+mount -t tmpfs none $MNT_DIR || skip "Mounting tmpfs not available."
+
+add_image
+echo "[2] Kernel dmcrypt performance options"
+if [ -z "$DM_PERF_CPU" ]; then
+ echo "TEST SKIPPED: dmcrypt options not available"
+ SKIP_COUNT=$((SKIP_COUNT+1))
+else
+ echo -n "PLAIN: same_cpu_crypt submit_from_cpus "
+ echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ check_io
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -n "allow_discards "
+ echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ check_io
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
+ # Hash affects volume key for plain device. Check we can detect it
+ echo -e "$PWD1" | $CRYPTSETUP refresh -q $DEV_NAME --hash sha512 --perf-same_cpu_crypt --allow-discards 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --allow-discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 $DEV $DEV_NAME2 2>/dev/null && fail
+ if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then
+ echo -n "no_read_workqueue no_write_workqueue"
+ echo -e "$PWD1" | $CRYPTSETUP refresh --hash sha256 -q $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
+ check_io
+ fi
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo
+
+ format luks1
+ echo -n "LUKS: same_cpu_crypt submit_from_cpus "
+ echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -n "allow_discards "
+ echo -e "$PWD1" | $CRYPTSETUP open --type luks1 $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME --allow-discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME --allow-discards --perf-same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME2 2>/dev/null && fail
+ if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then
+ echo -n "no_read_workqueue no_write_workqueue"
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
+ fi
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo
+
+ format luks2
+ echo -n "LUKS2: same_cpu_crypt submit_from_cpus "
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ # Stored in metadata
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -n "allow_discards [persistent flags] "
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-same_cpu_crypt --perf-submit_from_crypt_cpus --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-same_cpu_crypt --allow-discards --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-submit_from_crypt_cpus || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus || fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q same_cpu_crypt && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q discards && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q submit_from_crypt_cpus && fail
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --disable-keyring || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q keyring && fail
+ if [ -n "$DM_KEYRING" ]; then
+ echo -n "keyring "
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q keyring || fail
+ fi
+ if [ -n "$DM_PERF_NO_WORKQUEUE" ]; then
+ echo -n "no_read_workqueue no_write_workqueue"
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME --perf-no_read_workqueue --perf-no_write_workqueue --persistent || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_read_workqueue || fail
+ $CRYPTSETUP status $DEV_NAME | grep -q no_write_workqueue || fail
+ fi
+ echo -e "$PWD1" | $CRYPTSETUP refresh $DEV $DEV_NAME2 2>/dev/null && fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo
+fi
+
+echo "[3] Kernel dmcrypt sector size options"
+echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --sector-size 4096 >/dev/null 2>&1
+ret=$?
+[ -z "$DM_SECTOR_SIZE" -a $ret -eq 0 ] && fail "cryptsetup activated device with --sector-size option on incompatible kernel!"
+if [ $ret -ne 0 ] ; then
+ SKIP_COUNT=$((SKIP_COUNT+1))
+ if [ $SKIP_COUNT -ge 2 ]; then
+ skip "dmcrypt sector-size option not available"
+ fi
+ echo "TEST SKIPPED: dmcrypt sector-size option not available"
+else
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ echo -n "PLAIN sector size:"
+ echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --sector-size 1234 >/dev/null 2>&1 && fail
+ for S in 512 1024 2048 4096; do
+ echo -n "[$S]"
+ echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --sector-size $S || fail
+ check_sector_size $S
+ $CRYPTSETUP close $DEV_NAME || fail
+ done
+
+ echo -e "$PWD1" | $CRYPTSETUP open --type plain --hash sha256 $DEV $DEV_NAME --iv-large-sectors >/dev/null 2>&1 && fail
+ for S in 1024 2048 4096; do
+ echo -n "[$S/IV]"
+ echo -e "$PWD1" | $CRYPTSETUP open -q --type plain --hash sha256 $DEV $DEV_NAME --sector-size $S --iv-large-sectors || fail
+ check_sector_size $S
+ dmsetup table $DEV_NAME | grep -q "iv_large_sectors" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ done
+ echo
+
+ echo -n "LUKS2 sector size:"
+ echo -e "$PWD1" | $CRYPTSETUP luksFormat --type luks2 -$DEV --sector-size 1234 >/dev/null 2>&1 && fail
+ for S in 512 1024 2048 4096; do
+ echo -n "[$S]"
+ echo -e "$PWD1" | $CRYPTSETUP -q luksFormat --type luks2 --pbkdf pbkdf2 --pbkdf-force-iterations 1000 $DEV --sector-size $S || fail
+ echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ check_sector_size $S
+ $CRYPTSETUP close $DEV_NAME || fail
+ done
+ echo
+fi
+
+echo "[4] Disappeared device test:"
+KEY="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"
+for F in LUKS1 LUKS2 BITLK TCRYPT; do
+ add_device dev_size_mb=1 sector_size=512 num_tgts=1 lbpu=1
+ echo -n "$F"
+ # Fake CRYPT UUID to force code to parse type-specific path
+ dmsetup create $DEV_NAME --uuid CRYPT-$F-$DEV_NAME --table "0 1024 crypt aes-xts-plain64 $KEY 16 /dev/$SCSI_DEV 16"
+ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+ echo 1 > /sys/block/$SCSI_DEV/device/delete
+ udevadm settle >/dev/null 2>&1
+ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+ dmsetup remove $DEV_NAME --retry || fail
+ rmmod scsi_debug >/dev/null 2>&1
+ echo -n "[OK] "
+done
+echo
+
+cleanup
+exit 0
diff --git a/tests/differ.c b/tests/differ.c
new file mode 100644
index 0000000..95da8e5
--- /dev/null
+++ b/tests/differ.c
@@ -0,0 +1,166 @@
+/*
+ * cryptsetup file differ check (rewritten Clemens' fileDiffer in Python)
+ *
+ * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+struct ffile {
+ char *name;
+ int fd;
+ unsigned char *addr;
+ size_t size;
+};
+
+enum df { OK , FAIL };
+
+static void print_diff(off_t from, int max,
+ const unsigned char *o,
+ const unsigned char *n)
+{
+ int i, len = max;
+
+ if (len > 16)
+ len = 16;
+
+ printf("OLD:");
+ for (i = 0; i < len; i++)
+ printf(" %02x", o[from + i]);
+ printf("%s\n ", max != len ? " ..." : "");
+ for (i = 0; i < len; i++)
+ printf(" %2c", o[from + i] > ' ' ? o[from + i]: '.');
+ printf("\nNEW:");
+ for (i = 0; i < len; i++)
+ printf(" %02x", n[from + i]);
+ printf("%s\n ", max != len ? " ..." : "");
+ for (i = 0; i < len; i++)
+ printf(" %2c", n[from + i] > ' ' ? n[from + i]: '.');
+ printf("\n");
+}
+
+/*
+ * Xfrom-to (e.g. R10-15)
+ * A - change allowed
+ * S - change required, semantic
+ * R - change required, random
+ * F - change forbidden
+ */
+static enum df check(const char *range, unsigned char *o, unsigned char *n)
+{
+ char strict;
+ unsigned long long from, to;
+ enum df ret;
+
+ if (sscanf(range, "%c%llu-%llu", &strict, &from, &to) != 3) {
+ printf("Unknown range format %s.\n", range);
+ return FAIL;
+ }
+
+ switch (toupper(strict)) {
+ case 'A':
+ ret = OK;
+ break;
+ case 'S':
+ ret = memcmp(&o[from], &n[from], to - from + 1) != 0 ? OK : FAIL;
+ break;
+ case 'R': /* FIXME - random test */
+ ret = memcmp(&o[from], &n[from], to - from + 1) != 0 ? OK : FAIL;
+ break;
+ case 'F':
+ ret = memcmp(&o[from], &n[from], to - from + 1) == 0 ? OK : FAIL;
+ break;
+ default:
+ ret = FAIL;
+ break;
+ }
+
+ if (ret == FAIL)
+ print_diff(from, to - from + 1, o, n);
+
+ return ret;
+}
+
+static int open_mmap(struct ffile *f)
+{
+ struct stat st;
+
+ f->fd = open(f->name, O_RDONLY);
+ if (f->fd == -1 || fstat(f->fd, &st) == -1)
+ return 0;
+
+ f->size = st.st_size;
+ f->addr = mmap(NULL, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
+
+ return (f->addr == MAP_FAILED) ? 0 : 1;
+}
+
+static void close_mmap(struct ffile *f)
+{
+ if (f->addr != MAP_FAILED && !munmap(f->addr, f->size))
+ f->addr = MAP_FAILED;
+
+ if (f->fd != -1 && !close(f->fd))
+ f->fd = -1;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, r = 1;
+ struct ffile file_old = {
+ .fd = -1,
+ .addr = MAP_FAILED,
+ };
+ struct ffile file_new = {
+ .fd = -1,
+ .addr = MAP_FAILED,
+ };
+
+ if (argc < 3) {
+ printf("Use: differ old_file new_file change_list.\n");
+ goto bad;
+ }
+
+ file_old.name = argv[1];
+ if (!open_mmap(&file_old))
+ goto bad;
+
+ file_new.name = argv[2];
+ if (!open_mmap(&file_new))
+ goto bad;
+
+ for (i = 3; i < argc; i++)
+ if (check(argv[i], file_old.addr, file_new.addr) == FAIL) {
+ printf ("FAILED for %s\n", argv[i]);
+ r = 1;
+ goto bad;
+ }
+
+ r = 0;
+bad:
+ close_mmap(&file_new);
+ close_mmap(&file_old);
+
+ return r;
+}
diff --git a/tests/discards-test b/tests/discards-test
new file mode 100755
index 0000000..870f74d
--- /dev/null
+++ b/tests/discards-test
@@ -0,0 +1,113 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+DEV_NAME="discard-t3st"
+DEV=""
+PWD1="93R4P4pIqAH8"
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+cleanup() {
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ udevadm settle >/dev/null 2>&1
+ rmmod scsi_debug >/dev/null 2>&1
+ sleep 2
+}
+
+fail()
+{
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+add_device() {
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+ fi
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 2
+ DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+
+ DEV="/dev/$DEV"
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+function check_version()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f 2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+
+ # option supported in 1.11
+ test $VER_MAJ -gt 1 && return 0
+ test $VER_MIN -ge 11 && return 0
+ return 1
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run this test, test skipped."
+ exit 77
+fi
+
+modprobe dm-crypt >/dev/null 2>&1
+if ! check_version ; then
+ echo "Probably old kernel, test skipped."
+ exit 77
+fi
+
+add_device dev_size_mb=16 sector_size=512 num_tgts=1 lbpu=1
+
+# FIXME test hash of device (unmap -> zero)
+# for now just check that flag is enabled
+
+echo "[1] Allowing discards for LUKS device"
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $DEV -q -i1 || fail
+echo $PWD1 | $CRYPTSETUP luksOpen $DEV $DEV_NAME --allow-discards || fail
+$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
+$CRYPTSETUP resize $DEV_NAME --size 100 || fail
+$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
+dmsetup table $DEV_NAME | grep allow_discards >/dev/null || fail
+$CRYPTSETUP luksClose $DEV_NAME || fail
+
+echo "[2] Allowing discards for plain device"
+echo $PWD1 | $CRYPTSETUP create -q $DEV_NAME $DEV --hash sha256 --allow-discards || fail
+$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
+$CRYPTSETUP resize $DEV_NAME --size 100 || fail
+$CRYPTSETUP status $DEV_NAME | grep flags | grep discards >/dev/null || fail
+dmsetup table $DEV_NAME | grep allow_discards >/dev/null || fail
+$CRYPTSETUP remove $DEV_NAME || fail
+
+cleanup
diff --git a/tests/evil_hdr-keyslot_overlap.xz b/tests/evil_hdr-keyslot_overlap.xz
new file mode 100644
index 0000000..6d56368
--- /dev/null
+++ b/tests/evil_hdr-keyslot_overlap.xz
Binary files differ
diff --git a/tests/evil_hdr-luks_hdr_damage.xz b/tests/evil_hdr-luks_hdr_damage.xz
new file mode 100644
index 0000000..b0b5254
--- /dev/null
+++ b/tests/evil_hdr-luks_hdr_damage.xz
Binary files differ
diff --git a/tests/evil_hdr-payload_overwrite.xz b/tests/evil_hdr-payload_overwrite.xz
new file mode 100644
index 0000000..b9e0e68
--- /dev/null
+++ b/tests/evil_hdr-payload_overwrite.xz
Binary files differ
diff --git a/tests/evil_hdr-small_luks_device.xz b/tests/evil_hdr-small_luks_device.xz
new file mode 100644
index 0000000..700392d
--- /dev/null
+++ b/tests/evil_hdr-small_luks_device.xz
Binary files differ
diff --git a/tests/evil_hdr-stripes_payload_dmg.xz b/tests/evil_hdr-stripes_payload_dmg.xz
new file mode 100644
index 0000000..dc91556
--- /dev/null
+++ b/tests/evil_hdr-stripes_payload_dmg.xz
Binary files differ
diff --git a/tests/fake_systemd_tpm_path.c b/tests/fake_systemd_tpm_path.c
new file mode 100644
index 0000000..6d82989
--- /dev/null
+++ b/tests/fake_systemd_tpm_path.c
@@ -0,0 +1,17 @@
+#include <string.h>
+#include <stdlib.h>
+
+/* systemd tpm2-util.h */
+int tpm2_find_device_auto(int log_level, char **ret);
+
+extern int tpm2_find_device_auto(int log_level __attribute__((unused)), char **ret)
+{
+ const char *path = getenv("TPM_PATH");
+
+ if (!path)
+ *ret = NULL;
+ else
+ *ret = strdup(path);
+
+ return 0;
+}
diff --git a/tests/fake_token_path.c b/tests/fake_token_path.c
new file mode 100644
index 0000000..7b2bad3
--- /dev/null
+++ b/tests/fake_token_path.c
@@ -0,0 +1,6 @@
+#include <libcryptsetup.h>
+
+const char *crypt_token_external_path(void)
+{
+ return BUILD_DIR;
+}
diff --git a/tests/fuzz/FuzzerInterface.h b/tests/fuzz/FuzzerInterface.h
new file mode 100644
index 0000000..b238253
--- /dev/null
+++ b/tests/fuzz/FuzzerInterface.h
@@ -0,0 +1,81 @@
+// Based on https://github.com/llvm-mirror/compiler-rt/blob/master/lib/fuzzer/FuzzerInterface.h
+//
+//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// Define the interface between libFuzzer and the library being tested.
+//===----------------------------------------------------------------------===//
+
+// NOTE: the libFuzzer interface is thin and in the majority of cases
+// you should not include this file into your target. In 95% of cases
+// all you need is to define the following function in your file:
+// extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+
+// WARNING: keep the interface in C.
+
+#ifndef LLVM_FUZZER_INTERFACE_H
+#define LLVM_FUZZER_INTERFACE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Define FUZZER_INTERFACE_VISIBILITY to set default visibility in a way that
+// doesn't break MSVC.
+#if defined(_WIN32)
+#define FUZZER_INTERFACE_VISIBILITY __declspec(dllexport)
+#else
+#define FUZZER_INTERFACE_VISIBILITY __attribute__((visibility("default")))
+#endif
+
+// Mandatory user-provided target function.
+// Executes the code under test with [Data, Data+Size) as the input.
+// libFuzzer will invoke this function *many* times with different inputs.
+// Must return 0.
+FUZZER_INTERFACE_VISIBILITY int
+LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+
+// Optional user-provided initialization function.
+// If provided, this function will be called by libFuzzer once at startup.
+// It may read and modify argc/argv.
+// Must return 0.
+FUZZER_INTERFACE_VISIBILITY int LLVMFuzzerInitialize(int *argc, char ***argv);
+
+// Optional user-provided custom mutator.
+// Mutates raw data in [Data, Data+Size) inplace.
+// Returns the new size, which is not greater than MaxSize.
+// Given the same Seed produces the same mutation.
+FUZZER_INTERFACE_VISIBILITY size_t
+LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize,
+ unsigned int Seed);
+
+// Optional user-provided custom cross-over function.
+// Combines pieces of Data1 & Data2 together into Out.
+// Returns the new size, which is not greater than MaxOutSize.
+// Should produce the same mutation given the same Seed.
+FUZZER_INTERFACE_VISIBILITY size_t
+LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1,
+ const uint8_t *Data2, size_t Size2, uint8_t *Out,
+ size_t MaxOutSize, unsigned int Seed);
+
+// Experimental, may go away in future.
+// libFuzzer-provided function to be used inside LLVMFuzzerCustomMutator.
+// Mutates raw data in [Data, Data+Size) inplace.
+// Returns the new size, which is not greater than MaxSize.
+FUZZER_INTERFACE_VISIBILITY size_t
+LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
+
+#undef FUZZER_INTERFACE_VISIBILITY
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // LLVM_FUZZER_INTERFACE_H
diff --git a/tests/fuzz/LUKS2.proto b/tests/fuzz/LUKS2.proto
new file mode 100644
index 0000000..3a0f287
--- /dev/null
+++ b/tests/fuzz/LUKS2.proto
@@ -0,0 +1,379 @@
+/*
+ * cryptsetup LUKS2 custom mutator
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+syntax = "proto2";
+
+package LUKS2_proto;
+
+// ---------------------------------------------------------------------------
+// ----------------------------- GENERIC OBJECTS -----------------------------
+// ---------------------------------------------------------------------------
+
+message object_id {
+ oneof id {
+ // int_id will be mapped to range -16 to 16 (mod 33)
+ // this way iy should be easier to generate valid
+ // object cross-references
+ uint32 int_id = 1;
+ string string_id = 2;
+ }
+}
+
+message string_uint64 {
+ required bool negative = 1;
+ oneof number {
+ uint32 uint_num = 2;
+ string string_num = 3;
+ }
+}
+
+enum hash_algorithm {
+ HASH_ALG_SHA1 = 1;
+ HASH_ALG_SHA256 = 2;
+}
+
+
+// ---------------------------------------------------------------------------
+// ----------------------------- BINARY HEADER -------------------------------
+// ---------------------------------------------------------------------------
+
+enum luks2_magic {
+ INVALID = 0;
+ FIRST = 1;
+ SECOND = 2;
+}
+
+enum luks_version {
+ ONE = 1;
+ TWO = 2;
+ THREE = 3;
+}
+
+// we limit the size to 64KiB to make the fuzzing faster
+// because the checksum needs to be calculated for the whole image
+enum hdr_size {
+ size_16_KB = 16384;
+ size_32_KB = 32768;
+ size_64_KB = 65536;
+// size_128_KB = 131072;
+// size_256_KB = 262144;
+// size_512_KB = 524288;
+// size_1_MB = 1048576;
+// size_2_MB = 2097152;
+// size_4_MB = 4194304;
+}
+
+enum seqid_description {
+ PRIMARY_GREATER = 0;
+ SECONDARY_GREATER = 1;
+ EQUAL = 2;
+}
+
+// message luks2_hdr_disk {
+// char magic[LUKS2_MAGIC_L];
+// //uint16_t version; /* Version 2 */
+// uint64_t hdr_size; /* in bytes, including JSON area */
+// uint64_t seqid; /* increased on every update */
+// char label[LUKS2_LABEL_L];
+// char checksum_alg[LUKS2_CHECKSUM_ALG_L];
+// uint8_t salt[LUKS2_SALT_L]; /* unique for every header/offset */
+// char uuid[LUKS2_UUID_L];
+// char subsystem[LUKS2_LABEL_L]; /* owner subsystem label */
+// uint64_t hdr_offset; /* offset from device start in bytes */
+// char _padding[184];
+// uint8_t csum[LUKS2_CHECKSUM_L];
+// }
+message LUKS2_header {
+ required luks_version version = 1;
+ required luks2_magic magic = 2;
+ required hdr_size hdr_size = 3;
+ required bool use_correct_checksum = 4;
+
+ optional uint64 selected_offset = 5;
+}
+
+message LUKS2_both_headers {
+ required LUKS2_header primary_header = 1;
+ required LUKS2_header secondary_header = 2;
+
+ required seqid_description seqid = 3;
+ required json_area_description json_area = 4;
+}
+
+message json_area_description {
+ optional config_description config = 1;
+ repeated keyslot_description keyslots = 2;
+ repeated digest_description digests = 3;
+ repeated segment_description segments = 4;
+ repeated token_description tokens = 5;
+}
+
+// ---------------------------------------------------------------------------
+// ----------------------------- KEYSLOT OBJECT ------------------------------
+// ---------------------------------------------------------------------------
+
+enum keyslot_type {
+ KEYSLOT_TYPE_LUKS2 = 1;
+ KEYSLOT_TYPE_REENCRYPT = 2;
+ KEYSLOT_TYPE_PLACEHOLDER = 3;
+}
+
+enum reencrypt_keyslot_mode {
+ MODE_REENCRYPT = 1;
+ MODE_ENCRYPT = 2;
+ MODE_DECRYPT = 3;
+}
+
+enum reencrypt_keyslot_direction {
+ DIRECTION_FORWARD = 1;
+ DIRECTION_BACKWARD = 2;
+}
+
+// The area object contains these mandatory fields:
+// - type [string] the area type.
+// - offset [string-uint64] the offset from the device start to the beginning of the binary area (in bytes).
+// - size [string-uint64] the area size (in bytes).
+//
+// Area type raw contains these additional fields:
+// - encryption [string] the area encryption algorithm, in dm-crypt notation (for example aes-xts-plain64).
+// - key_size [integer] the area encryption key size.
+//
+// Area type none and journal (used only for reencryption optional extension) contain only mandatory fields.
+//
+// Area type checksum (used only for reencryption optional extension) contains these additional fields:
+// - hash [string] The hash algorithm for the checksum resilience mode.
+// - sector_size [integer] The data unit size for digest checksum calculated with the hash algorithm.
+//
+// Area type datashift (used only for reencryption optional extension) contains this additional field:
+// - shift_size [string-uint64] The data shift (in bytes) performed during reencryption (shift direction is according to direction field).
+
+enum keyslot_area_type {
+ KEYSLOT_AREA_TYPE_RAW = 1;
+ KEYSLOT_AREA_TYPE_NONE = 2;
+ KEYSLOT_AREA_TYPE_JOURNAL = 3;
+ KEYSLOT_AREA_TYPE_CHECKSUM = 4;
+ KEYSLOT_AREA_TYPE_DATASHIFT = 5;
+}
+
+message keyslot_area_description {
+ // mandatory fields
+ optional keyslot_area_type type = 1;
+ optional string_uint64 offset = 2;
+ optional string_uint64 size = 3;
+
+ // raw type fields
+ optional string encryption = 4;
+ optional int32 key_size = 5;
+
+ // checksum type field
+ optional hash_algorithm hash = 6;
+ optional int32 sector_size = 7;
+
+ // datashift type fields
+ optional string_uint64 shift_size = 8;
+}
+
+// The object describes PBKDF attributes used for the keyslot.
+// The kdf object mandatory fields are:
+// - type [string] the PBKDF type.
+// - salt [base64] the salt for PBKDF (binary data).
+//
+// The pbkdf2 type (compatible with LUKS1) contains these additional fields:
+// - hash [string] the hash algorithm for the PBKDF2 (SHA-256).
+// - iterations [integer] the PBKDF2 iterations count.
+//
+// The argon2i and argon2id type contains these additional fields:
+// - time [integer] the time cost (in fact the iterations count for Argon2).
+// - memory [integer] the memory cost, in kilobytes. If not available, the keyslot cannot be unlocked.
+// - cpus [integer] the required number of threads (CPU cores number cost). If not available, unlocking will be slower.
+
+enum keyslot_kdf_type {
+ KEYSLOT_KDF_TYPE_PBKDF2 = 1;
+ KEYSLOT_KDF_TYPE_ARGON2I = 2;
+ KEYSLOT_KDF_TYPE_ARGON2ID = 3;
+}
+
+message keyslot_kdf_description {
+ optional keyslot_kdf_type type = 1;
+ optional string salt = 2;
+
+ // pbkdf2 type
+ optional hash_algorithm hash = 3;
+ optional int32 iterations = 4;
+
+ // argon2i and argon2id types
+ optional int32 time = 5;
+ optional int32 memory = 6;
+ optional int32 cpus = 7;
+}
+
+enum keyslot_af_type {
+ KEYSLOT_AF_TYPE_LUKS1 = 1;
+}
+
+// The af (anti-forensic splitter) object contains this madatory field:
+// - type [string] the anti-forensic function type.
+// AF type luks1 (compatible with LUKS1 [1]) contains these additional fields:
+// - stripes [integer] the number of stripes, for historical reasons only the 4000 value is supported.
+// - hash [string] the hash algorithm used.
+
+message keyslot_af_description {
+ optional keyslot_af_type type = 1;
+ optional int32 stripes = 2;
+ optional hash_algorithm hash = 3;
+}
+
+// - type [string] the keyslot type.
+// - key_size [integer] the key size (in bytes) stored in keyslot.
+// - priority [integer,optional] the keyslot priority. Here 0 means ignore (the slot should be used only if explicitly stated), 1 means normal priority and 2 means high priority (tried before normal priority).
+
+// REENCRYPT
+// The key size field must be set to 1. The area type must be none, checksum,
+// journal or datashift.
+// The reencrypt object must contain these additional fields:
+// - mode [string] the reencryption mode. reencrypt, encrypt and decrypt
+// - direction [string] the reencryption direction. forward backward
+
+// - area [object] the allocated area in the binary keyslots area.
+// LUKS2 object must contain these additional fields:
+// - kdf [object] the PBKDF type and parameters used.
+// - af [object] the anti-forensic splitter [1] (only the luks1 type is currently
+// used).
+
+message keyslot_description {
+ // type
+ required object_id oid = 1;
+
+ optional keyslot_type type = 2;
+ optional int32 key_size = 3;
+ optional int32 priority = 4;
+
+ // reencrypt extension
+ optional reencrypt_keyslot_mode mode = 5;
+ optional reencrypt_keyslot_direction direction = 6;
+
+ // objects
+ optional keyslot_area_description area = 7;
+ optional keyslot_kdf_description kdf = 8;
+ optional keyslot_af_description af = 9;
+}
+
+// ---------------------------------------------------------------------------
+// ------------------------------ DIGEST OBJECT ------------------------------
+// ---------------------------------------------------------------------------
+
+message digest_description {
+ required object_id oid = 1;
+
+ optional keyslot_kdf_type type = 2;
+ repeated object_id keyslots = 3;
+ repeated object_id segments = 4;
+ optional string salt = 5;
+ optional string digest = 6;
+
+ // pbkdf2 digest fields
+ optional hash_algorithm hash = 7;
+ optional int32 iterations = 8;
+}
+
+// ---------------------------------------------------------------------------
+// ----------------------------- SEGMENT OBJECT ------------------------------
+// ---------------------------------------------------------------------------
+
+enum segment_type {
+ SEGMENT_TYPE_LINEAR = 1;
+ SEGMENT_TYPE_CRYPT = 2;
+}
+
+enum segment_flag {
+ IN_REENCRYPTION = 1;
+ BACKUP_FINAL = 2;
+ BACKUP_PREVIOUS = 3;
+ BACKUP_MOVED_SEGMENT = 4;
+}
+
+message segment_integrity_description {
+ optional string type = 1;
+ optional string journal_encryption = 2;
+ optional string journal_integrity = 3;
+}
+
+message segment_description {
+ required object_id oid = 1;
+ optional segment_type type = 2;
+ optional string_uint64 offset = 3;
+ optional string_uint64 size = 4;
+ repeated segment_flag flags = 5;
+
+ // segment type crypt
+ optional string_uint64 iv_tweak = 6;
+ optional string encryption = 7;
+ optional int32 sector_size = 8;
+ optional segment_integrity_description integrity = 9;
+}
+
+// ---------------------------------------------------------------------------
+// ------------------------------ TOKEN OBJECT -------------------------------
+// ---------------------------------------------------------------------------
+
+message token_description {
+ required object_id oid = 1;
+
+ optional string type = 2;
+ repeated object_id keyslots = 3;
+ optional string key_description = 4;
+}
+
+// ---------------------------------------------------------------------------
+// ------------------------------ CONFIG OBJECT ------------------------------
+// ---------------------------------------------------------------------------
+
+// - allow-discards allows TRIM (discards) on the active device.
+// - same-cpu-crypt compatibility performance flag for dm-crypt [3] to per- form encryption using the same CPU that originated the request.
+// - submit-from-crypt-cpus compatibility performance flag for dm-crypt [3] to disable offloading write requests to a separate thread after encryption.
+// - no-journal disable data journalling for dm-integrity [10].
+// - no-read-workqueue compatibility performance flag for dm-crypt [3] to bypass dm-crypt read workqueue and process read requests synchronously.
+// - no-write-workqueue compatibility performance flag for dm-crypt [3] to bypass dm-crypt write workqueue and process write requests synchronously.
+enum config_flag {
+ CONFIG_FLAG_ALLOW_DISCARDS = 1;
+ CONFIG_FLAG_SAME_CPU_CRYPT = 2;
+ CONFIG_FLAG_SUBMIT_FROM_CRYPT_CPUS = 3;
+ CONFIG_FLAG_NO_JOURNAL = 4;
+ CONFIG_FLAG_NO_READ_WORKQUEUE = 5;
+ CONFIG_FLAG_NO_WRITE_WORKQUEUE = 6;
+}
+
+enum config_requirement {
+ CONFIG_REQUIREMENT_OFFLINE_REENCRYPT = 1;
+ CONFIG_REQUIREMENT_ONLINE_REENCRYPT_V2 = 2;
+}
+
+// - json_size [string-uint64] the JSON area size (in bytes). Must match the binary header.
+// - keyslots_size [string-uint64] the binary keyslot area size (in bytes). Must be aligned to 4096 bytes.
+// - flags [array, optional] the array of string objects with persistent flags for the device.
+// - requirements [array, optional] the array of string objects with additional required features for the LUKS device.
+
+message config_description {
+ required bool use_primary_hdr_size = 2;
+
+ repeated config_flag config_flags = 3;
+ repeated config_requirement requirements = 4;
+}
diff --git a/tests/fuzz/LUKS2_plain_JSON.proto b/tests/fuzz/LUKS2_plain_JSON.proto
new file mode 100644
index 0000000..59096b7
--- /dev/null
+++ b/tests/fuzz/LUKS2_plain_JSON.proto
@@ -0,0 +1,190 @@
+/*
+ * cryptsetup LUKS2 custom mutator
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+syntax = "proto2";
+
+package json_proto;
+
+// ---------------------------------------------------------------------------
+// ----------------------------- GENERIC OBJECTS -----------------------------
+// ---------------------------------------------------------------------------
+
+message object_id {
+ oneof id {
+ // int_id will be mapped to range -16 to 16 (mod 33)
+ // this way iy should be easier to generate valid
+ // object cross-references
+ uint32 int_id = 1;
+ string string_id = 2;
+ }
+}
+
+message string_uint64 {
+ required bool negative = 1;
+ oneof number {
+ uint32 uint_num = 2;
+ string string_num = 3;
+ }
+}
+
+enum hash_algorithm {
+ HASH_ALG_SHA1 = 1;
+ HASH_ALG_SHA256 = 2;
+}
+
+
+// ---------------------------------------------------------------------------
+// ----------------------------- BINARY HEADER -------------------------------
+// ---------------------------------------------------------------------------
+
+enum luks2_magic {
+ INVALID = 0;
+ FIRST = 1;
+ SECOND = 2;
+}
+
+enum luks_version {
+ ONE = 1;
+ TWO = 2;
+ THREE = 3;
+}
+
+// we limit the size to 64KiB to make the fuzzing faster
+// because the checksum needs to be calculated for the whole image
+enum hdr_size {
+ size_16_KB = 16384;
+ size_32_KB = 32768;
+ size_64_KB = 65536;
+// size_128_KB = 131072;
+// size_256_KB = 262144;
+// size_512_KB = 524288;
+// size_1_MB = 1048576;
+// size_2_MB = 2097152;
+// size_4_MB = 4194304;
+}
+
+enum seqid_description {
+ PRIMARY_GREATER = 0;
+ SECONDARY_GREATER = 1;
+ EQUAL = 2;
+}
+
+// message luks2_hdr_disk {
+// char magic[LUKS2_MAGIC_L];
+// //uint16_t version; /* Version 2 */
+// uint64_t hdr_size; /* in bytes, including JSON area */
+// uint64_t seqid; /* increased on every update */
+// char label[LUKS2_LABEL_L];
+// char checksum_alg[LUKS2_CHECKSUM_ALG_L];
+// uint8_t salt[LUKS2_SALT_L]; /* unique for every header/offset */
+// char uuid[LUKS2_UUID_L];
+// char subsystem[LUKS2_LABEL_L]; /* owner subsystem label */
+// uint64_t hdr_offset; /* offset from device start in bytes */
+// char _padding[184];
+// uint8_t csum[LUKS2_CHECKSUM_L];
+// }
+message LUKS2_header {
+ required luks_version version = 1;
+ required luks2_magic magic = 2;
+ required hdr_size hdr_size = 3;
+ required bool use_correct_checksum = 4;
+
+ optional uint64 selected_offset = 5;
+}
+
+message LUKS2_both_headers {
+ required LUKS2_header primary_header = 1;
+ required LUKS2_header secondary_header = 2;
+
+ required seqid_description seqid = 3;
+ required JsonObject json_area = 4;
+}
+
+message JsonObject {
+ required string name = 1;
+ required JsonValue value = 2;
+}
+
+message JsonValue {
+ oneof value {
+ // Json value types:
+
+ // null: null, will be used when 'oneof' contains nothing
+
+ // object: another json object of any type
+ JsonObject object_value = 1;
+
+ // array: an array of values
+ ArrayValue array_value = 2;
+
+ // number: can be an integer, a float, an exponent
+ NumberValue number_value = 3;
+
+ // string: unicode string
+ StringValue string_value = 4;
+
+ // boolean: true or talse
+ BooleanValue boolean_value = 5;
+ }
+}
+
+message ArrayValue {
+ repeated JsonValue value = 1;
+}
+
+message NumberInteger {
+ required int64 value = 1;
+}
+
+message NumberFloat {
+ required double value = 1;
+}
+
+message NumberExponent {
+ required int32 base = 1;
+ required int32 exponent = 2;
+ required bool use_uppercase = 3;
+}
+
+message NumberExponentFrac {
+ required float base = 1;
+ required int32 exponent = 2;
+ required bool use_uppercase = 3;
+}
+
+message NumberValue {
+ required NumberInteger integer_value = 1;
+
+ // integer_value is used when oneof field below has nothing.
+ oneof value {
+ NumberFloat float_value = 2;
+ NumberExponent exponent_value = 3;
+ NumberExponentFrac exponent_frac_value = 4;
+ }
+}
+
+message StringValue {
+ required string value = 1;
+}
+
+message BooleanValue {
+ required bool value = 1;
+}
diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
new file mode 100644
index 0000000..c7a6cdf
--- /dev/null
+++ b/tests/fuzz/Makefile.am
@@ -0,0 +1,122 @@
+EXTRA_DIST = README.md oss-fuzz-build.sh
+dist_noinst_DATA = \
+ LUKS2.proto \
+ LUKS2_plain_JSON.proto \
+ crypt2_load_fuzz.dict \
+ crypt2_load_ondisk_fuzz.dict \
+ crypt2_load_proto_plain_json_fuzz.dict \
+ unpoison-mutated-buffers-from-libfuzzer.patch
+CLEANFILES = \
+ LUKS2.pb.h \
+ LUKS2.pb.cc \
+ LUKS2_plain_JSON.pb.h \
+ LUKS2_plain_JSON.pb.cc
+
+distclean-local:
+ -rm -rf out build
+
+LIB_FUZZING_ENGINE := $(if $(LIB_FUZZING_ENGINE),$(LIB_FUZZING_ENGINE),"-fsanitize=fuzzer")
+SANITIZER := $(if $(SANITIZER),,"-fsanitize=address")
+
+DEPS_PATH := $(top_srcdir)/tests/fuzz/build/static_lib_deps
+
+crypt2_load_fuzz_SOURCES = FuzzerInterface.h crypt2_load_fuzz.cc
+crypt2_load_fuzz_LDADD = ../../libcryptsetup.la ../../libcrypto_backend.la -L$(DEPS_PATH)/lib
+crypt2_load_fuzz_LDFLAGS = $(AM_LDFLAGS) $(LIB_FUZZING_ENGINE) $(SANITIZER)
+crypt2_load_fuzz_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)/lib -I$(top_srcdir)/tests/fuzz
+
+crypt2_load_ondisk_fuzz_SOURCES = FuzzerInterface.h crypt2_load_ondisk_fuzz.cc
+crypt2_load_ondisk_fuzz_LDADD = ../../libcryptsetup.la -L$(DEPS_PATH)/lib
+crypt2_load_ondisk_fuzz_LDFLAGS = $(AM_LDFLAGS) $(LIB_FUZZING_ENGINE) $(SANITIZER)
+crypt2_load_ondisk_fuzz_CXXFLAGS = $(AM_CXXFLAGS) -I$(top_srcdir)/lib -I$(top_srcdir)/tests/fuzz
+
+test-environment-m:
+ @ if test ! -d $(DEPS_PATH); then \
+ echo "You need to build static libraries first; use oss-fuzz-build.sh script."; \
+ exit 1; \
+ fi
+test-environment: | test-environment-m $(DEPS_PATH)
+
+LUKS2.pb.h: LUKS2.proto
+ $(DEPS_PATH)/bin/protoc LUKS2.proto --cpp_out=.
+LUKS2.pb.cc: LUKS2.pb.h
+
+LUKS2_plain_JSON.pb.h: LUKS2_plain_JSON.proto
+ $(DEPS_PATH)/bin/protoc LUKS2_plain_JSON.proto --cpp_out=.
+LUKS2_plain_JSON.pb.cc: LUKS2_plain_JSON.pb.h
+
+crypt2_load_proto_fuzz-crypt2_load_proto_fuzz.$(OBJEXT): LUKS2.pb.cc
+crypt2_load_proto_plain_json_fuzz-crypt2_load_proto_plain_json_fuzz.$(OBJEXT): LUKS2_plain_JSON.pb.cc
+
+nodist_crypt2_load_proto_fuzz_SOURCES = LUKS2.pb.h LUKS2.pb.cc
+crypt2_load_proto_fuzz_SOURCES = FuzzerInterface.h \
+ crypt2_load_proto_fuzz.cc \
+ proto_to_luks2_converter.h \
+ proto_to_luks2_converter.cc
+crypt2_load_proto_fuzz_LDADD = \
+ ../../libcryptsetup.la \
+ ../../libcrypto_backend.la \
+ -L$(DEPS_PATH)/lib -lprotobuf-mutator-libfuzzer -lprotobuf-mutator -lprotobuf
+crypt2_load_proto_fuzz_LDFLAGS = $(AM_LDFLAGS) $(LIB_FUZZING_ENGINE) $(SANITIZER)
+crypt2_load_proto_fuzz_CXXFLAGS = $(AM_CXXFLAGS) \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/tests/fuzz \
+ -I$(DEPS_PATH)/include \
+ -I$(DEPS_PATH)/include/libprotobuf-mutator -I$(DEPS_PATH)/include/libprotobuf-mutator/src
+
+nodist_crypt2_load_proto_plain_json_fuzz_SOURCES = LUKS2_plain_JSON.pb.h LUKS2_plain_JSON.pb.cc
+crypt2_load_proto_plain_json_fuzz_SOURCES = FuzzerInterface.h \
+ crypt2_load_proto_plain_json_fuzz.cc \
+ json_proto_converter.h \
+ json_proto_converter.cc \
+ plain_json_proto_to_luks2_converter.h \
+ plain_json_proto_to_luks2_converter.cc
+crypt2_load_proto_plain_json_fuzz_LDADD = \
+ ../../libcryptsetup.la \
+ ../../libcrypto_backend.la \
+ -L$(DEPS_PATH)/lib -lprotobuf-mutator-libfuzzer -lprotobuf-mutator -lprotobuf
+crypt2_load_proto_plain_json_fuzz_LDFLAGS = $(AM_LDFLAGS) $(LIB_FUZZING_ENGINE) $(SANITIZER)
+crypt2_load_proto_plain_json_fuzz_CXXFLAGS = $(AM_CXXFLAGS) \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/tests/fuzz \
+ -I$(DEPS_PATH)/include \
+ -I$(DEPS_PATH)/include/libprotobuf-mutator -I$(DEPS_PATH)/include/libprotobuf-mutator/src
+
+nodist_proto_to_luks2_SOURCES = LUKS2.pb.h LUKS2.pb.cc
+proto_to_luks2_SOURCES = \
+ proto_to_luks2.cc \
+ proto_to_luks2_converter.h \
+ proto_to_luks2_converter.cc
+proto_to_luks2_LDADD = ../../libcryptsetup.la ../../libcrypto_backend.la -L$(DEPS_PATH)/lib -lprotobuf
+proto_to_luks2_LDFLAGS = $(AM_LDFLAGS) -fsanitize=fuzzer-no-link $(SANITIZER)
+proto_to_luks2_CXXFLAGS = $(AM_CXXFLAGS) \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/tests/fuzz \
+ -I$(DEPS_PATH)/include
+
+nodist_plain_json_proto_to_luks2_SOURCES = LUKS2_plain_JSON.pb.h LUKS2_plain_JSON.pb.cc
+plain_json_proto_to_luks2_SOURCES = \
+ plain_json_proto_to_luks2.cc \
+ plain_json_proto_to_luks2_converter.h \
+ plain_json_proto_to_luks2_converter.cc \
+ json_proto_converter.h \
+ json_proto_converter.cc
+plain_json_proto_to_luks2_LDADD = ../../libcryptsetup.la ../../libcrypto_backend.la -L$(DEPS_PATH)/lib -lprotobuf
+plain_json_proto_to_luks2_LDFLAGS = $(AM_LDFLAGS) -fsanitize=fuzzer-no-link $(SANITIZER)
+plain_json_proto_to_luks2_CXXFLAGS = $(AM_CXXFLAGS) \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/tests/fuzz \
+ -I$(DEPS_PATH)/include
+
+if ENABLE_FUZZ_TARGETS
+noinst_PROGRAMS = \
+ crypt2_load_fuzz \
+ crypt2_load_ondisk_fuzz \
+ crypt2_load_proto_fuzz \
+ crypt2_load_proto_plain_json_fuzz \
+ proto_to_luks2 \
+ plain_json_proto_to_luks2
+
+fuzz-targets: test-environment $(noinst_PROGRAMS)
+.PHONY: fuzz-targets
+endif
diff --git a/tests/fuzz/README.md b/tests/fuzz/README.md
new file mode 100644
index 0000000..fdcfa27
--- /dev/null
+++ b/tests/fuzz/README.md
@@ -0,0 +1,66 @@
+# Fuzzing target for cryptsetup project
+
+This directory contains experimental targets for fuzzing testing.
+It can be run in the OSS-Fuzz project but also compiled separately.
+
+# Requirements
+
+Fuzzers use address sanitizer. To properly detect problems, all
+important libraries must be compiled statically with sanitizer enabled.
+
+Compilation requires *clang* and *clang++* compilers (gcc is not
+supported yet).
+
+# Standalone build
+
+The script `oss-fuzz-build.sh` can be used to prepare the tree
+with pre-compiled library dependencies.
+We use upstream git for projects, which can clash with locally
+installed versions. The best is to use only basic system installation
+without development packages (script will use custom include, libs,
+and pkg-config paths).
+
+# Build Docker image and fuzzers
+
+You can also run OSS-Fuzz in a Docker image, use these commands
+to prepare fuzzers:
+```
+sudo python3 infra/helper.py build_image cryptsetup
+sudo python3 infra/helper.py build_fuzzers cryptsetup
+```
+On SELinux systems also add (https://github.com/google/oss-fuzz/issues/30):
+```
+sudo chcon -Rt svirt_sandbox_file_t build/
+```
+
+# Run LUKS2 fuzzer
+`FUZZER_NAME` can be one of: `crypt2_load_fuzz`, `crypt2_load_proto_fuzz`, `crypt2_load_proto_plain_json_fuzz`
+```
+FUZZER_NAME="crypt2_load_proto_plain_json_fuzz"
+sudo mkdir -p build/corpus/cryptsetup/$FUZZER_NAME
+sudo python infra/helper.py run_fuzzer --corpus-dir build/corpus/cryptsetup/$FUZZER_NAME/ --sanitizer address cryptsetup $FUZZER_NAME '-jobs=8 -workers=8'
+```
+
+The output of the parallel threads will be written to `fuzz-<N>.log` (where `<N>` is the number of the process).
+You can watch it using e.g.:
+```
+tail -f build/out/cryptsetup/fuzz-*
+```
+
+Optionally, you can use experimental `fork` mode for parallelization and the output will be displayed directly on the terminal:
+```
+sudo python infra/helper.py run_fuzzer --corpus-dir build/corpus/cryptsetup/$FUZZER_NAME/ --sanitizer address cryptsetup $FUZZER_NAME '-fork=8 '
+```
+
+# Rebuild fuzz targets for coverage
+```
+sudo python infra/helper.py build_fuzzers --sanitizer coverage cryptsetup
+```
+
+# Generate coverage report
+```
+sudo python infra/helper.py coverage cryptsetup --no-corpus-download --fuzz-target $FUZZER_NAME
+```
+
+# Further information
+For more details, you can look into the [Using fuzzing for Linux disk encryption tools](https://is.muni.cz/th/bum03/?lang=en) thesis.
diff --git a/tests/fuzz/crypt2_load_fuzz.cc b/tests/fuzz/crypt2_load_fuzz.cc
new file mode 100644
index 0000000..1251d72
--- /dev/null
+++ b/tests/fuzz/crypt2_load_fuzz.cc
@@ -0,0 +1,112 @@
+/*
+ * cryptsetup LUKS2 fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern "C" {
+#define FILESIZE (16777216)
+#include "src/cryptsetup.h"
+#include <err.h>
+#include "luks2/luks2.h"
+#include "crypto_backend/crypto_backend.h"
+#include "FuzzerInterface.h"
+
+static int calculate_checksum(const uint8_t* data, size_t size) {
+ struct crypt_hash *hd = NULL;
+ struct luks2_hdr_disk *hdr = NULL;
+ int hash_size;
+ uint64_t hdr_size1, hdr_size2;
+ int r = 0;
+
+ /* primary header */
+ if (sizeof(struct luks2_hdr_disk) > size)
+ return 0;
+ hdr = CONST_CAST(struct luks2_hdr_disk *) data;
+
+ hdr_size1 = be64_to_cpu(hdr->hdr_size);
+ if (hdr_size1 > size)
+ return 0;
+ memset(&hdr->csum, 0, LUKS2_CHECKSUM_L);
+ if ((r = crypt_hash_init(&hd, "sha256")))
+ goto out;
+ if ((r = crypt_hash_write(hd, CONST_CAST(char*) data, hdr_size1)))
+ goto out;
+ hash_size = crypt_hash_size("sha256");
+ if (hash_size <= 0) {
+ r = 1;
+ goto out;
+ }
+ if ((r = crypt_hash_final(hd, (char*)&hdr->csum, (size_t)hash_size)))
+ goto out;
+ crypt_hash_destroy(hd);
+
+ /* secondary header */
+ if (hdr_size1 < sizeof(struct luks2_hdr_disk))
+ hdr_size1 = sizeof(struct luks2_hdr_disk);
+
+ if (hdr_size1 + sizeof(struct luks2_hdr_disk) > size)
+ return 0;
+ hdr = CONST_CAST(struct luks2_hdr_disk *) (data + hdr_size1);
+
+ hdr_size2 = be64_to_cpu(hdr->hdr_size);
+ if (hdr_size2 > size || (hdr_size1 + hdr_size2) > size)
+ return 0;
+
+ memset(&hdr->csum, 0, LUKS2_CHECKSUM_L);
+ if ((r = crypt_hash_init(&hd, "sha256")))
+ goto out;
+ if ((r = crypt_hash_write(hd, (char*) hdr, hdr_size2)))
+ goto out;
+ if ((r = crypt_hash_final(hd, (char*)&hdr->csum, (size_t)hash_size)))
+ goto out;
+
+out:
+ if (hd)
+ crypt_hash_destroy(hd);
+ return r;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ int fd;
+ struct crypt_device *cd = NULL;
+ char name[] = "/tmp/test-script-fuzz.XXXXXX";
+
+ if (calculate_checksum(data, size))
+ return 0;
+
+ fd = mkostemp(name, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
+ if (fd == -1)
+ err(EXIT_FAILURE, "mkostemp() failed");
+
+ /* enlarge header */
+ if (ftruncate(fd, FILESIZE) == -1)
+ goto out;
+
+ if (write_buffer(fd, data, size) != (ssize_t)size)
+ goto out;
+
+ if (crypt_init(&cd, name) == 0)
+ (void)crypt_load(cd, CRYPT_LUKS2, NULL);
+ crypt_free(cd);
+out:
+ close(fd);
+ unlink(name);
+ return 0;
+}
+}
diff --git a/tests/fuzz/crypt2_load_fuzz.dict b/tests/fuzz/crypt2_load_fuzz.dict
new file mode 100644
index 0000000..fedf1a4
--- /dev/null
+++ b/tests/fuzz/crypt2_load_fuzz.dict
@@ -0,0 +1,130 @@
+# LUKS2 dictionary based on AFL dictionary for JSON
+# -------------------------------------------------
+# JSON dictionary from https://github.com/google/AFL/blob/master/dictionaries/json.dict
+# Inspired by a dictionary by Jakub Wilk <jwilk@jwilk.net>
+#
+# LUKS2 keywords by Daniel Zatovic
+
+"0"
+",0"
+":0"
+"0:"
+"-1.2e+3"
+
+"true"
+"false"
+"null"
+
+"\"\""
+",\"\""
+":\"\""
+"\"\":"
+
+"{}"
+",{}"
+":{}"
+"{\"\":0}"
+"{{}}"
+
+"[]"
+",[]"
+":[]"
+"[0]"
+"[[]]"
+
+"''"
+"\\"
+"\\b"
+"\\f"
+"\\n"
+"\\r"
+"\\t"
+"\\u0000"
+"\\x00"
+"\\0"
+"\\uD800\\uDC00"
+"\\uDBFF\\uDFFF"
+
+"\"\":0"
+"//"
+"/**/"
+
+"$ref"
+"type"
+"coordinates"
+"@context"
+"@id"
+
+","
+":"
+
+"1024"
+"2048"
+"4096"
+"512"
+"aegis128-random"
+"aes-cbc:essiv:sha256"
+"aes-xts-plain64"
+"af"
+"allow-discards"
+"area"
+"argon2i"
+"argon2id"
+"backup-final"
+"backup-moved-segment"
+"backup-previous"
+"checksum"
+"config"
+"cpus"
+"crypt"
+"datashift"
+"digest"
+"digests"
+"direction"
+"encryption"
+"flags"
+"hash"
+"in-reencryption"
+"integrity"
+"iterations"
+"iv_tweak"
+"journal"
+"journal_encryption"
+"journal_integrity"
+"json_size"
+"kdf"
+"key_description"
+"key_size"
+"keyslots"
+"keyslots_size"
+"linear"
+"luks2"
+"luks2-keyring"
+"LUKS\xBA\xBE"
+"memory"
+"mode"
+"no-journal"
+"none"
+"no-read-workqueue"
+"no-write-workqueue"
+"offline-reencrypt"
+"offset"
+"online-reencrypt-v2"
+"pbkdf2"
+"priority"
+"raw"
+"reencrypt"
+"requirements"
+"salt"
+"same-cpu-crypt"
+"sector_size"
+"segments"
+"serpent-xts-plain64"
+"shift_size"
+"size"
+"SKUL\xBA\xBE"
+"stripes"
+"submit-from-crypt-cpus"
+"time"
+"tokens"
+"twofish-xts-plain64"
diff --git a/tests/fuzz/crypt2_load_ondisk_fuzz.cc b/tests/fuzz/crypt2_load_ondisk_fuzz.cc
new file mode 100644
index 0000000..9b5328d
--- /dev/null
+++ b/tests/fuzz/crypt2_load_ondisk_fuzz.cc
@@ -0,0 +1,64 @@
+/*
+ * cryptsetup LUKS1, FileVault, BitLocker fuzz target
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+extern "C" {
+#define FILESIZE (16777216)
+#include "src/cryptsetup.h"
+#include <err.h>
+#include "luks1/luks.h"
+#include "crypto_backend/crypto_backend.h"
+#include "FuzzerInterface.h"
+
+void empty_log(int level, const char *msg, void *usrptr) {}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ int fd, r;
+ struct crypt_device *cd = NULL;
+ char name[] = "/tmp/test-script-fuzz.XXXXXX";
+
+ fd = mkostemp(name, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC);
+ if (fd == -1)
+ err(EXIT_FAILURE, "mkostemp() failed");
+
+ /* enlarge header */
+ if (ftruncate(fd, FILESIZE) == -1)
+ goto out;
+
+ if (write_buffer(fd, data, size) != (ssize_t) size)
+ goto out;
+
+ crypt_set_log_callback(NULL, empty_log, NULL);
+
+ if (crypt_init(&cd, name) == 0) {
+ r = crypt_load(cd, CRYPT_LUKS1, NULL);
+ if (r == 0)
+ goto out;
+
+ r = crypt_load(cd, CRYPT_FVAULT2, NULL);
+ if (r == 0)
+ goto out;
+
+ (void) crypt_load(cd, CRYPT_BITLK, NULL);
+ }
+out:
+ crypt_free(cd);
+ close(fd);
+ unlink(name);
+ return 0;
+}
+}
diff --git a/tests/fuzz/crypt2_load_ondisk_fuzz.dict b/tests/fuzz/crypt2_load_ondisk_fuzz.dict
new file mode 100644
index 0000000..3923db5
--- /dev/null
+++ b/tests/fuzz/crypt2_load_ondisk_fuzz.dict
@@ -0,0 +1,9 @@
+"aegis128-random"
+"aes-cbc:essiv:sha256"
+"aes-xts-plain64"
+"aes-lrv-plain64"
+"twofish-xts-plain64"
+"serpent-xts-plain64"
+"whirpool"
+"sha256"
+"sha1"
diff --git a/tests/fuzz/crypt2_load_proto_fuzz.cc b/tests/fuzz/crypt2_load_proto_fuzz.cc
new file mode 100644
index 0000000..498c006
--- /dev/null
+++ b/tests/fuzz/crypt2_load_proto_fuzz.cc
@@ -0,0 +1,51 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "LUKS2.pb.h"
+#include "proto_to_luks2_converter.h"
+#include "libfuzzer/libfuzzer_macro.h"
+#include "FuzzerInterface.h"
+
+extern "C" {
+#include <libcryptsetup.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+}
+
+DEFINE_PROTO_FUZZER(const LUKS2_proto::LUKS2_both_headers &headers) {
+ struct crypt_device *cd = NULL;
+ char name[] = "/tmp/test-proto-fuzz.XXXXXX";
+ int fd = mkostemp(name, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
+
+ if (fd < 0)
+ err(EXIT_FAILURE, "mkostemp() failed");
+
+ LUKS2_proto::LUKS2ProtoConverter converter;
+ converter.convert(headers, fd);
+
+ if (crypt_init(&cd, name) == 0)
+ (void)crypt_load(cd, CRYPT_LUKS2, NULL);
+ crypt_free(cd);
+
+ close(fd);
+ unlink(name);
+}
diff --git a/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc b/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc
new file mode 100644
index 0000000..f3565ab
--- /dev/null
+++ b/tests/fuzz/crypt2_load_proto_plain_json_fuzz.cc
@@ -0,0 +1,51 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "LUKS2_plain_JSON.pb.h"
+#include "plain_json_proto_to_luks2_converter.h"
+#include "libfuzzer/libfuzzer_macro.h"
+#include "FuzzerInterface.h"
+
+extern "C" {
+#include <libcryptsetup.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+}
+
+DEFINE_PROTO_FUZZER(const json_proto::LUKS2_both_headers &headers) {
+ struct crypt_device *cd = NULL;
+ char name[] = "/tmp/test-proto-fuzz.XXXXXX";
+ int fd = mkostemp(name, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC);
+
+ if (fd < 0)
+ err(EXIT_FAILURE, "mkostemp() failed");
+
+ json_proto::LUKS2ProtoConverter converter;
+ converter.convert(headers, fd);
+
+ if (crypt_init(&cd, name) == 0)
+ (void)crypt_load(cd, CRYPT_LUKS2, NULL);
+ crypt_free(cd);
+
+ close(fd);
+ unlink(name);
+}
diff --git a/tests/fuzz/crypt2_load_proto_plain_json_fuzz.dict b/tests/fuzz/crypt2_load_proto_plain_json_fuzz.dict
new file mode 100644
index 0000000..7d83151
--- /dev/null
+++ b/tests/fuzz/crypt2_load_proto_plain_json_fuzz.dict
@@ -0,0 +1,72 @@
+# LUKS2 keywords by Daniel Zatovic
+
+"1024"
+"2048"
+"4096"
+"512"
+"aegis128-random"
+"aes-cbc:essiv:sha256"
+"aes-xts-plain64"
+"af"
+"allow-discards"
+"area"
+"argon2i"
+"argon2id"
+"backup-final"
+"backup-moved-segment"
+"backup-previous"
+"checksum"
+"config"
+"cpus"
+"crypt"
+"datashift"
+"digest"
+"digests"
+"direction"
+"encryption"
+"flags"
+"hash"
+"in-reencryption"
+"integrity"
+"iterations"
+"iv_tweak"
+"journal"
+"journal_encryption"
+"journal_integrity"
+"json_size"
+"kdf"
+"key_description"
+"key_size"
+"keyslots"
+"keyslots_size"
+"linear"
+"luks2"
+"luks2-keyring"
+"LUKS\xBA\xBE"
+"memory"
+"mode"
+"no-journal"
+"none"
+"no-read-workqueue"
+"no-write-workqueue"
+"offline-reencrypt"
+"offset"
+"online-reencrypt-v2"
+"pbkdf2"
+"priority"
+"raw"
+"reencrypt"
+"requirements"
+"salt"
+"same-cpu-crypt"
+"sector_size"
+"segments"
+"serpent-xts-plain64"
+"shift_size"
+"size"
+"SKUL\xBA\xBE"
+"stripes"
+"submit-from-crypt-cpus"
+"time"
+"tokens"
+"twofish-xts-plain64"
diff --git a/tests/fuzz/json_proto_converter.cc b/tests/fuzz/json_proto_converter.cc
new file mode 100644
index 0000000..ed453be
--- /dev/null
+++ b/tests/fuzz/json_proto_converter.cc
@@ -0,0 +1,87 @@
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include "json_proto_converter.h"
+
+namespace json_proto {
+
+void JsonProtoConverter::AppendArray(const ArrayValue& array_value) {
+ data_ << '[';
+ bool need_comma = false;
+ for (const auto& value : array_value.value()) {
+ // Trailing comma inside of an array makes JSON invalid, avoid adding that.
+ if (need_comma)
+ data_ << ',';
+ else
+ need_comma = true;
+
+ AppendValue(value);
+ }
+ data_ << ']';
+}
+
+void JsonProtoConverter::AppendNumber(const NumberValue& number_value) {
+ if (number_value.has_float_value()) {
+ data_ << number_value.float_value().value();
+ } else if (number_value.has_exponent_value()) {
+ auto value = number_value.exponent_value();
+ data_ << value.base();
+ data_ << (value.use_uppercase() ? 'E' : 'e');
+ data_ << value.exponent();
+ } else if (number_value.has_exponent_frac_value()) {
+ auto value = number_value.exponent_value();
+ data_ << value.base();
+ data_ << (value.use_uppercase() ? 'E' : 'e');
+ data_ << value.exponent();
+ } else {
+ data_ << number_value.integer_value().value();
+ }
+}
+
+void JsonProtoConverter::AppendObject(const JsonObject& json_object) {
+ data_ << '{' << '"' << json_object.name() << '"' << ':';
+ AppendValue(json_object.value());
+ data_ << '}';
+}
+
+void JsonProtoConverter::AppendValue(const JsonValue& json_value) {
+ if (json_value.has_object_value()) {
+ AppendObject(json_value.object_value());
+ } else if (json_value.has_array_value()) {
+ AppendArray(json_value.array_value());
+ } else if (json_value.has_number_value()) {
+ AppendNumber(json_value.number_value());
+ } else if (json_value.has_string_value()) {
+ data_ << '"' << json_value.string_value().value() << '"';
+ } else if (json_value.has_boolean_value()) {
+ data_ << (json_value.boolean_value().value() ? "true" : "false");
+ } else {
+ data_ << "null";
+ }
+}
+
+std::string JsonProtoConverter::Convert(const JsonObject& json_object) {
+ AppendObject(json_object);
+ return data_.str();
+}
+
+std::string JsonProtoConverter::Convert(
+ const json_proto::ArrayValue& json_array) {
+ AppendArray(json_array);
+ return data_.str();
+}
+
+} // namespace json_proto
diff --git a/tests/fuzz/json_proto_converter.h b/tests/fuzz/json_proto_converter.h
new file mode 100644
index 0000000..ca52d67
--- /dev/null
+++ b/tests/fuzz/json_proto_converter.h
@@ -0,0 +1,43 @@
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef JSON_PROTO_CONVERTER_H_
+#define JSON_PROTO_CONVERTER_H_
+
+#include <sstream>
+#include <string>
+
+#include "LUKS2_plain_JSON.pb.h"
+
+namespace json_proto {
+
+class JsonProtoConverter {
+ public:
+ std::string Convert(const json_proto::JsonObject&);
+ std::string Convert(const json_proto::ArrayValue&);
+
+ private:
+ std::stringstream data_;
+
+ void AppendArray(const json_proto::ArrayValue&);
+ void AppendNumber(const json_proto::NumberValue&);
+ void AppendObject(const json_proto::JsonObject&);
+ void AppendValue(const json_proto::JsonValue&);
+};
+
+} // namespace json_proto
+
+#endif // TESTING_LIBFUZZER_PROTO_JSON_PROTO_CONVERTER_H_
diff --git a/tests/fuzz/oss-fuzz-build.sh b/tests/fuzz/oss-fuzz-build.sh
new file mode 100755
index 0000000..b2f643f
--- /dev/null
+++ b/tests/fuzz/oss-fuzz-build.sh
@@ -0,0 +1,152 @@
+#!/usr/bin/env bash
+
+function in_oss_fuzz()
+{
+ test -n "$FUZZING_ENGINE"
+}
+
+echo "Running cryptsetup OSS-Fuzz build script."
+env
+set -ex
+PWD=$(pwd)
+
+export LC_CTYPE=C.UTF-8
+
+export SRC=${SRC:-$PWD/build}
+export OUT="${OUT:-$PWD/out}"
+export DEPS_PATH=$SRC/static_lib_deps
+
+export PKG_CONFIG_PATH="$DEPS_PATH"/lib/pkgconfig
+
+export CC=${CC:-clang}
+export CXX=${CXX:-clang++}
+export LIB_FUZZING_ENGINE="${LIB_FUZZING_ENGINE:--fsanitize=fuzzer}"
+
+SANITIZER="${SANITIZER:-address -fsanitize-address-use-after-scope}"
+flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize=fuzzer-no-link"
+
+export CFLAGS="${CFLAGS:-$flags} -I$DEPS_PATH/include"
+export CXXFLAGS="${CXXFLAGS:-$flags} -I$DEPS_PATH/include"
+export LDFLAGS="${LDFLAGS-} -L$DEPS_PATH/lib"
+
+ENABLED_FUZZERS=${ENABLED_FUZZERS:-crypt2_load_fuzz crypt2_load_ondisk_fuzz crypt2_load_proto_plain_json_fuzz}
+
+mkdir -p $SRC
+mkdir -p $OUT
+mkdir -p $DEPS_PATH
+cd $SRC
+
+LIBFUZZER_PATCH="$PWD/unpoison-mutated-buffers-from-libfuzzer.patch"
+in_oss_fuzz && LIBFUZZER_PATCH="$PWD/cryptsetup/tests/fuzz/unpoison-mutated-buffers-from-libfuzzer.patch"
+
+in_oss_fuzz && apt-get update && apt-get install -y \
+ make autoconf automake autopoint libtool pkg-config \
+ sharutils gettext expect keyutils ninja-build \
+ bison
+
+[ ! -d zlib ] && git clone --depth 1 https://github.com/madler/zlib.git
+[ ! -d xz ] && git clone https://git.tukaani.org/xz.git
+[ ! -d json-c ] && git clone --depth 1 https://github.com/json-c/json-c.git
+[ ! -d lvm2 ] && git clone --depth 1 https://sourceware.org/git/lvm2.git
+[ ! -d popt ] && git clone --depth 1 https://github.com/rpm-software-management/popt.git
+[ ! -d libprotobuf-mutator ] && git clone --depth 1 https://github.com/google/libprotobuf-mutator.git \
+ && [ "$SANITIZER" == "memory" ] && ( cd libprotobuf-mutator; patch -p1 < $LIBFUZZER_PATCH )
+[ ! -d openssl ] && git clone --depth 1 https://github.com/openssl/openssl
+[ ! -d util-linux ] && git clone --depth 1 https://github.com/util-linux/util-linux
+[ ! -d cryptsetup_fuzzing ] && git clone --depth 1 https://gitlab.com/cryptsetup/cryptsetup_fuzzing.git
+
+cd openssl
+./Configure --prefix="$DEPS_PATH" --libdir=lib no-shared no-module no-asm
+make build_generated
+make -j libcrypto.a
+make install_dev
+cd ..
+
+cd util-linux
+./autogen.sh
+./configure --prefix="$DEPS_PATH" --enable-static --disable-shared -disable-all-programs --enable-libuuid --enable-libblkid
+make -j
+make install
+cd ..
+
+cd zlib
+./configure --prefix="$DEPS_PATH" --static
+make -j
+make install
+cd ..
+
+cd xz
+./autogen.sh --no-po4a
+./configure --prefix="$DEPS_PATH" --enable-static --disable-shared
+make -j
+make install
+cd ..
+
+cd json-c
+mkdir -p build
+rm -fr build/*
+cd build
+cmake .. -DCMAKE_INSTALL_PREFIX="$DEPS_PATH" -DBUILD_SHARED_LIBS=OFF -DBUILD_STATIC_LIBS=ON
+make -j
+make install
+cd ../..
+
+cd lvm2
+./configure --prefix="$DEPS_PATH" --enable-static_link --disable-udev_sync --enable-pkgconfig --disable-selinux
+make -j libdm.device-mapper
+# build of dmsetup.static is broken
+# make install_device-mapper
+cp ./libdm/ioctl/libdevmapper.a "$DEPS_PATH"/lib/
+cp ./libdm/libdevmapper.h "$DEPS_PATH"/include/
+cp ./libdm/libdevmapper.pc "$PKG_CONFIG_PATH"
+cd ..
+
+cd popt
+# --no-undefined is incompatible with sanitizers
+sed -i -e 's/-Wl,--no-undefined //' src/CMakeLists.txt
+mkdir -p build
+rm -fr build/*
+cd build
+cmake .. -DCMAKE_INSTALL_PREFIX="$DEPS_PATH" -DBUILD_SHARED_LIBS=OFF
+make -j
+make install
+cd ../..
+
+cd libprotobuf-mutator
+mkdir -p build
+rm -fr build/*
+cd build
+cmake .. -GNinja \
+ -DCMAKE_INSTALL_PREFIX="$DEPS_PATH" \
+ -DPKG_CONFIG_PATH="$PKG_CONFIG_PATH" \
+ -DLIB_PROTO_MUTATOR_TESTING=OFF \
+ -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON
+ninja
+ninja install
+cd external.protobuf;
+cp -Rf bin lib include "$DEPS_PATH";
+cd ../../..
+
+if in_oss_fuzz; then
+ mkdir -p cryptsetup/tests/fuzz/build
+ ln -s ../../../../static_lib_deps cryptsetup/tests/fuzz/build/static_lib_deps
+ cd cryptsetup
+else
+ cd ../../..
+fi
+./autogen.sh
+./configure --enable-static --disable-asciidoc --disable-ssh-token --disable-udev --disable-selinux --with-crypto_backend=openssl --disable-shared --enable-fuzz-targets
+make clean
+make -j fuzz-targets
+
+for fuzzer in $ENABLED_FUZZERS; do
+ cp tests/fuzz/$fuzzer $OUT
+ cp $SRC/cryptsetup_fuzzing/${fuzzer}_seed_corpus.zip $OUT
+
+ # optionally copy the dictionary if it exists
+ if [ -e tests/fuzz/${fuzzer}.dict ]; then
+ cp tests/fuzz/${fuzzer}.dict $OUT
+ fi
+done
+
+cd $PWD
diff --git a/tests/fuzz/plain_json_proto_to_luks2.cc b/tests/fuzz/plain_json_proto_to_luks2.cc
new file mode 100644
index 0000000..8c56c15
--- /dev/null
+++ b/tests/fuzz/plain_json_proto_to_luks2.cc
@@ -0,0 +1,75 @@
+/*
+ * cryptsetup LUKS2 protobuf to image converter
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <iostream>
+#include <string>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#include "plain_json_proto_to_luks2_converter.h"
+
+using namespace json_proto;
+
+int main(int argc, char *argv[]) {
+ LUKS2_both_headers headers;
+ LUKS2ProtoConverter converter;
+ int fd;
+
+ std::string out_img_name;
+
+ if (argc != 2) {
+ std::cerr << "Usage: " << argv[0] << " <LUKS2 proto>\n";
+ return EXIT_FAILURE;
+ }
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd < 0) {
+ std::cerr << "Failed to open " << argv[1] << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ google::protobuf::io::FileInputStream fileInput(fd);
+
+ if (!google::protobuf::TextFormat::Parse(&fileInput, &headers)) {
+ std::cerr << "Failed to parse protobuf " << argv[1] << std::endl;
+ close(fd);
+ return EXIT_FAILURE;
+ }
+ close(fd);
+
+ out_img_name = argv[1];
+ out_img_name += ".img";
+
+ fd = open(out_img_name.c_str(), O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC|O_TRUNC, 0644);
+ if (fd < 0) {
+ std::cerr << "Failed to open output file " << out_img_name << std::endl;
+ return EXIT_FAILURE;
+ }
+ converter.set_write_headers_only(false);
+ converter.convert(headers, fd);
+
+ close(fd);
+ return EXIT_SUCCESS;
+}
diff --git a/tests/fuzz/plain_json_proto_to_luks2_converter.cc b/tests/fuzz/plain_json_proto_to_luks2_converter.cc
new file mode 100644
index 0000000..823c0c5
--- /dev/null
+++ b/tests/fuzz/plain_json_proto_to_luks2_converter.cc
@@ -0,0 +1,153 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "plain_json_proto_to_luks2_converter.h"
+#include "json_proto_converter.h"
+
+extern "C" {
+#include "src/cryptsetup.h"
+#include "luks2/luks2.h"
+#include <err.h>
+}
+
+namespace json_proto {
+
+void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid, const std::string &json_text) {
+ struct luks2_hdr_disk hdr = {};
+ int r;
+
+ if (hd)
+ crypt_hash_destroy(hd);
+ if (crypt_hash_init(&hd, "sha256"))
+ err(EXIT_FAILURE, "crypt_hash_init failed");
+
+
+ r = lseek(fd, offset, SEEK_SET);
+ if (r == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ switch (header_proto.magic()) {
+ case INVALID:
+ memset(&hdr.magic, 0, LUKS2_MAGIC_L);
+ break;
+ case FIRST:
+ memcpy(&hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L);
+ break;
+ case SECOND:
+ memcpy(&hdr.magic, LUKS2_MAGIC_2ND, LUKS2_MAGIC_L);
+ break;
+ }
+ hdr.version = cpu_to_be16(header_proto.version());
+ hdr.hdr_size = cpu_to_be64(header_proto.hdr_size());
+ hdr.seqid = cpu_to_be64(seqid);
+ strncpy(hdr.checksum_alg, "sha256", LUKS2_CHECKSUM_ALG_L);
+ hdr.checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
+ strncpy(hdr.uuid, "af7f64ea-3233-4581-946b-6187d812841e", LUKS2_UUID_L);
+ memset(hdr.salt, 1, LUKS2_SALT_L);
+
+
+ if (header_proto.has_selected_offset())
+ hdr.hdr_offset = cpu_to_be64(header_proto.selected_offset());
+ else
+ hdr.hdr_offset = cpu_to_be64(offset);
+
+ if (write_buffer(fd, &hdr, LUKS2_HDR_BIN_LEN) != LUKS2_HDR_BIN_LEN)
+ err(EXIT_FAILURE, "write_buffer failed");
+ if (crypt_hash_write(hd, (char*)&hdr, LUKS2_HDR_BIN_LEN))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+
+ size_t hdr_json_area_len = header_proto.hdr_size() - LUKS2_HDR_BIN_LEN;
+ uint8_t csum[LUKS2_CHECKSUM_L];
+
+ size_t write_size = json_text.length() > hdr_json_area_len - 1 ? hdr_json_area_len - 1 : json_text.length();
+ if (write_buffer(fd, json_text.c_str(), write_size) != (ssize_t)write_size)
+ err(EXIT_FAILURE, "write_buffer failed");
+ if (crypt_hash_write(hd, json_text.c_str(), write_size))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+
+ for (size_t i = 0; i < (hdr_json_area_len - write_size); i++) {
+ if (crypt_hash_write(hd, "\0", 1))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+ }
+
+ if (header_proto.use_correct_checksum()) {
+ if (lseek(fd, offset + offsetof(luks2_hdr_disk, csum), SEEK_SET) == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ int hash_size = crypt_hash_size("sha256");
+ if (hash_size <= 0)
+ err(EXIT_FAILURE, "crypt_hash_size failed");
+
+ if (crypt_hash_final(hd, (char*)csum, (size_t)hash_size))
+ err(EXIT_FAILURE, "crypt_hash_final failed");
+ if (write_buffer(fd, csum, hash_size) != hash_size)
+ err(EXIT_FAILURE, "write_buffer failed");
+ }
+}
+
+void LUKS2ProtoConverter::set_write_headers_only(bool headers_only) {
+ write_headers_only = headers_only;
+}
+
+void LUKS2ProtoConverter::convert(const LUKS2_both_headers &headers, int fd) {
+ uint64_t primary_seqid, secondary_seqid;
+ int result;
+
+ size_t out_size = headers.primary_header().hdr_size() + headers.secondary_header().hdr_size();
+
+ if (!write_headers_only)
+ out_size += KEYSLOTS_SIZE + DATA_SIZE;
+
+ result = ftruncate(fd, out_size);
+ if (result == -1)
+ err(EXIT_FAILURE, "truncate failed");
+
+ result = lseek(fd, 0, SEEK_SET);
+ if (result == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ switch (headers.seqid()) {
+ case EQUAL:
+ primary_seqid = 1;
+ secondary_seqid = 1;
+ break;
+ case PRIMARY_GREATER:
+ primary_seqid = 2;
+ secondary_seqid = 1;
+ break;
+ case SECONDARY_GREATER:
+ primary_seqid = 1;
+ secondary_seqid = 2;
+ break;
+ }
+
+ JsonProtoConverter converter;
+ std::string json_text = converter.Convert(headers.json_area());
+
+ emit_luks2_binary_header(headers.primary_header(), fd, 0, primary_seqid, json_text);
+ emit_luks2_binary_header(headers.secondary_header(), fd, headers.primary_header().hdr_size(), secondary_seqid, json_text);
+}
+
+LUKS2ProtoConverter::~LUKS2ProtoConverter() {
+ if (hd)
+ crypt_hash_destroy(hd);
+}
+} // namespace LUKS2_proto
diff --git a/tests/fuzz/plain_json_proto_to_luks2_converter.h b/tests/fuzz/plain_json_proto_to_luks2_converter.h
new file mode 100644
index 0000000..7decf9f
--- /dev/null
+++ b/tests/fuzz/plain_json_proto_to_luks2_converter.h
@@ -0,0 +1,58 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef LUKS2_PROTO_CONVERTER_H_
+#define LUKS2_PROTO_CONVERTER_H_
+
+#include <sstream>
+#include <string>
+#include <json-c/json.h>
+
+#include "LUKS2_plain_JSON.pb.h"
+extern "C" {
+#include "crypto_backend/crypto_backend.h"
+}
+
+namespace json_proto {
+
+class LUKS2ProtoConverter {
+ public:
+ ~LUKS2ProtoConverter();
+ void create_jobj(const LUKS2_both_headers &headers, uint64_t hdr_size);
+ void convert(const LUKS2_both_headers &headers, int fd);
+ void create_jobj(const LUKS2_both_headers &headers);
+ void emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid, const std::string &json_text);
+
+ void set_write_headers_only(bool headers_only);
+
+ const uint8_t *get_out_buffer();
+ size_t get_out_size();
+
+ static const uint64_t KEYSLOTS_SIZE = 3 * 1024 * 1024;
+ static const uint64_t DATA_SIZE = 16 * 1024 * 1024;
+ private:
+ bool write_headers_only = false;
+ struct crypt_hash *hd = NULL;
+};
+
+} // namespace LUKS2_proto
+
+#endif // LUKS2_PROTO_CONVERTER_H_
diff --git a/tests/fuzz/proto_to_luks2.cc b/tests/fuzz/proto_to_luks2.cc
new file mode 100644
index 0000000..4a27cad
--- /dev/null
+++ b/tests/fuzz/proto_to_luks2.cc
@@ -0,0 +1,75 @@
+/*
+ * cryptsetup LUKS2 protobuf to image converter
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <iostream>
+#include <string>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#include "proto_to_luks2_converter.h"
+
+using namespace LUKS2_proto;
+
+int main(int argc, char *argv[]) {
+ LUKS2_both_headers headers;
+ LUKS2ProtoConverter converter;
+ int fd;
+
+ std::string out_img_name;
+
+ if (argc != 2) {
+ std::cerr << "Usage: " << argv[0] << " <LUKS2 proto>\n";
+ return EXIT_FAILURE;
+ }
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd < 0) {
+ std::cerr << "Failed to open " << argv[1] << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ google::protobuf::io::FileInputStream fileInput(fd);
+
+ if (!google::protobuf::TextFormat::Parse(&fileInput, &headers)) {
+ std::cerr << "Failed to parse protobuf " << argv[1] << std::endl;
+ close(fd);
+ return EXIT_FAILURE;
+ }
+ close(fd);
+
+ out_img_name = argv[1];
+ out_img_name += ".img";
+
+ fd = open(out_img_name.c_str(), O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC|O_TRUNC, 0644);
+ if (fd < 0) {
+ std::cerr << "Failed to open output file " << out_img_name << std::endl;
+ return EXIT_FAILURE;
+ }
+ converter.set_write_headers_only(false);
+ converter.convert(headers, fd);
+
+ close(fd);
+ return EXIT_SUCCESS;
+}
diff --git a/tests/fuzz/proto_to_luks2_converter.cc b/tests/fuzz/proto_to_luks2_converter.cc
new file mode 100644
index 0000000..96a70b7
--- /dev/null
+++ b/tests/fuzz/proto_to_luks2_converter.cc
@@ -0,0 +1,604 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "proto_to_luks2_converter.h"
+#include <iostream>
+
+extern "C" {
+#include "src/cryptsetup.h"
+#include "luks2/luks2.h"
+#include <err.h>
+}
+
+namespace LUKS2_proto {
+
+std::string LUKS2ProtoConverter::string_uint64_to_string(const string_uint64 &str_u64) {
+ std::ostringstream os;
+
+ if (str_u64.negative())
+ os << "-";
+
+ if (str_u64.has_uint_num())
+ os << str_u64.uint_num();
+ else if (str_u64.has_string_num())
+ os << str_u64.string_num();
+
+ return os.str();
+}
+
+std::string LUKS2ProtoConverter::object_id_to_string(const object_id &oid) {
+ std::ostringstream os;
+
+ if (oid.has_int_id()) {
+ os << (oid.int_id() % 33) - 16;
+ } else if (oid.has_string_id()) {
+ os << oid.string_id();
+ }
+
+ return os.str();
+}
+
+std::string LUKS2ProtoConverter::hash_algorithm_to_string(const hash_algorithm type) {
+ switch (type) {
+ case HASH_ALG_SHA1:
+ return "sha1";
+ case HASH_ALG_SHA256:
+ return "sha256";
+ }
+}
+
+std::string LUKS2ProtoConverter::keyslot_area_type_to_string(const keyslot_area_type type) {
+ switch (type) {
+ case KEYSLOT_AREA_TYPE_RAW:
+ return "raw";
+ case KEYSLOT_AREA_TYPE_NONE:
+ return "none";
+ case KEYSLOT_AREA_TYPE_JOURNAL:
+ return "journal";
+ case KEYSLOT_AREA_TYPE_CHECKSUM:
+ return "checksum";
+ case KEYSLOT_AREA_TYPE_DATASHIFT:
+ return "datashift";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot_area(struct json_object *jobj_area, const keyslot_area_description &keyslot_area_desc) {
+ // mandatory fields
+ if (keyslot_area_desc.has_type())
+ json_object_object_add(jobj_area, "type", json_object_new_string(keyslot_area_type_to_string(keyslot_area_desc.type()).c_str()));
+ if (keyslot_area_desc.has_offset())
+ json_object_object_add(jobj_area, "offset", json_object_new_string(string_uint64_to_string(keyslot_area_desc.offset()).c_str()));
+ if (keyslot_area_desc.has_size())
+ json_object_object_add(jobj_area, "size", json_object_new_string(string_uint64_to_string(keyslot_area_desc.size()).c_str()));
+
+ // raw type fields
+ if (keyslot_area_desc.has_encryption())
+ json_object_object_add(jobj_area, "encryption", json_object_new_string(keyslot_area_desc.encryption().c_str()));
+ if (keyslot_area_desc.has_key_size())
+ json_object_object_add(jobj_area, "key_size", json_object_new_int(keyslot_area_desc.key_size()));
+
+ // checksum type fields
+ if (keyslot_area_desc.has_hash())
+ json_object_object_add(jobj_area, "hash", json_object_new_string(hash_algorithm_to_string(keyslot_area_desc.hash()).c_str()));
+ if (keyslot_area_desc.has_sector_size())
+ json_object_object_add(jobj_area, "sector_size", json_object_new_int(keyslot_area_desc.sector_size()));
+
+ // datashift type fields
+ if (keyslot_area_desc.has_shift_size())
+ json_object_object_add(jobj_area, "shift_size", json_object_new_string(string_uint64_to_string(keyslot_area_desc.shift_size()).c_str()));
+}
+
+std::string LUKS2ProtoConverter::keyslot_kdf_type_to_string(const keyslot_kdf_type type) {
+ switch (type) {
+ case KEYSLOT_KDF_TYPE_PBKDF2:
+ return "pbkdf2";
+ case KEYSLOT_KDF_TYPE_ARGON2I:
+ return "argon2i";
+ case KEYSLOT_KDF_TYPE_ARGON2ID:
+ return "argon2id";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot_kdf(struct json_object *jobj_kdf, const keyslot_kdf_description &keyslot_kdf_desc) {
+ // mandatory fields
+ if (keyslot_kdf_desc.has_type())
+ json_object_object_add(jobj_kdf, "type", json_object_new_string(keyslot_kdf_type_to_string(keyslot_kdf_desc.type()).c_str()));
+
+ if (keyslot_kdf_desc.has_salt())
+ json_object_object_add(jobj_kdf, "salt", json_object_new_string(keyslot_kdf_desc.salt().c_str()));
+ else
+ json_object_object_add(jobj_kdf, "salt", json_object_new_string("6vz4xK7cjan92rDA5JF8O6Jk2HouV0O8DMB6GlztVk="));
+
+ // pbkdf2 type
+ if (keyslot_kdf_desc.has_hash())
+ json_object_object_add(jobj_kdf, "hash", json_object_new_string(hash_algorithm_to_string(keyslot_kdf_desc.hash()).c_str()));
+ if (keyslot_kdf_desc.has_iterations())
+ json_object_object_add(jobj_kdf, "iterations", json_object_new_int(keyslot_kdf_desc.iterations()));
+
+ // argon2i and argon2id types
+ if (keyslot_kdf_desc.has_time())
+ json_object_object_add(jobj_kdf, "time", json_object_new_int(keyslot_kdf_desc.time()));
+ if (keyslot_kdf_desc.has_memory())
+ json_object_object_add(jobj_kdf, "memory", json_object_new_int(keyslot_kdf_desc.memory()));
+ if (keyslot_kdf_desc.has_cpus())
+ json_object_object_add(jobj_kdf, "cpus", json_object_new_int(keyslot_kdf_desc.cpus()));
+}
+
+std::string LUKS2ProtoConverter::keyslot_af_type_to_string(const keyslot_af_type type) {
+ switch (type) {
+ case KEYSLOT_AF_TYPE_LUKS1:
+ return "luks1";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot_af(struct json_object *jobj_af, const keyslot_af_description &keyslot_af_desc) {
+ if (keyslot_af_desc.has_type())
+ json_object_object_add(jobj_af, "type", json_object_new_string(keyslot_af_type_to_string(keyslot_af_desc.type()).c_str()));
+ if (keyslot_af_desc.has_stripes())
+ json_object_object_add(jobj_af, "stripes", json_object_new_int(keyslot_af_desc.stripes()));
+ if (keyslot_af_desc.has_hash())
+ json_object_object_add(jobj_af, "hash", json_object_new_string(hash_algorithm_to_string(keyslot_af_desc.hash()).c_str()));
+}
+
+std::string LUKS2ProtoConverter::keyslot_type_to_string(const keyslot_type type) {
+ switch (type) {
+ case KEYSLOT_TYPE_LUKS2:
+ return "luks2";
+ case KEYSLOT_TYPE_REENCRYPT:
+ return "reencrypt";
+ case KEYSLOT_TYPE_PLACEHOLDER:
+ return "placeholder";
+ }
+}
+
+std::string LUKS2ProtoConverter::reencrypt_keyslot_mode_to_string(const reencrypt_keyslot_mode mode) {
+ switch (mode) {
+ case MODE_REENCRYPT:
+ return "reencrypt";
+ case MODE_ENCRYPT:
+ return "encrypt";
+ case MODE_DECRYPT:
+ return "decrypt";
+ }
+}
+
+std::string LUKS2ProtoConverter::reencrypt_keyslot_direction_to_string(const reencrypt_keyslot_direction direction) {
+ switch (direction) {
+ case DIRECTION_FORWARD:
+ return "forward";
+ case DIRECTION_BACKWARD:
+ return "backward";
+ }
+}
+
+void LUKS2ProtoConverter::generate_keyslot(struct json_object *jobj_keyslots, const keyslot_description &keyslot_desc) {
+ struct json_object *jobj_keyslot, *jobj_area, *jobj_kdf, *jobj_af;
+
+ jobj_keyslot = json_object_new_object();
+ if (keyslot_desc.has_type())
+ json_object_object_add(jobj_keyslot, "type", json_object_new_string(keyslot_type_to_string(keyslot_desc.type()).c_str()));
+ if (keyslot_desc.has_key_size())
+ json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(keyslot_desc.key_size()));
+ if (keyslot_desc.has_priority())
+ json_object_object_add(jobj_keyslot, "priority", json_object_new_int(keyslot_desc.priority()));
+ if (keyslot_desc.has_mode())
+ json_object_object_add(jobj_keyslot, "mode", json_object_new_int(keyslot_desc.mode()));
+ if (keyslot_desc.has_direction())
+ json_object_object_add(jobj_keyslot, "direction", json_object_new_int(keyslot_desc.direction()));
+
+ /* Area object */
+ if (keyslot_desc.has_area()) {
+ jobj_area = json_object_new_object();
+ generate_keyslot_area(jobj_area, keyslot_desc.area());
+ json_object_object_add(jobj_keyslot, "area", jobj_area);
+ }
+
+ /* KDF object */
+ if (keyslot_desc.has_kdf()) {
+ jobj_kdf = json_object_new_object();
+ generate_keyslot_kdf(jobj_kdf, keyslot_desc.kdf());
+ json_object_object_add(jobj_keyslot, "kdf", jobj_kdf);
+ }
+
+ /* AF object */
+ if (keyslot_desc.has_af()) {
+ jobj_af = json_object_new_object();
+ generate_keyslot_af(jobj_af, keyslot_desc.af());
+ json_object_object_add(jobj_keyslot, "af", jobj_af);
+ }
+
+ json_object_object_add(jobj_keyslots, object_id_to_string(keyslot_desc.oid()).c_str(), jobj_keyslot);
+}
+
+void LUKS2ProtoConverter::generate_token(struct json_object *jobj_tokens, const token_description &token_desc) {
+ struct json_object *jobj_token, *jobj_keyslots;
+ jobj_token = json_object_new_object();
+
+ if (token_desc.has_type())
+ json_object_object_add(jobj_token, "type", json_object_new_string(token_desc.type().c_str()));
+
+ if (token_desc.has_key_description())
+ json_object_object_add(jobj_token, "key_description", json_object_new_string(token_desc.key_description().c_str()));
+
+ if (!token_desc.keyslots().empty()) {
+ jobj_keyslots = json_object_new_array();
+
+ for (const object_id& oid : token_desc.keyslots()) {
+ json_object_array_add(jobj_keyslots,
+ json_object_new_string(object_id_to_string(oid).c_str()));
+ }
+
+ /* Replace or add new keyslots array */
+ json_object_object_add(jobj_token, "keyslots", jobj_keyslots);
+ }
+
+ json_object_object_add(jobj_tokens, object_id_to_string(token_desc.oid()).c_str(), jobj_token);
+}
+
+void LUKS2ProtoConverter::generate_digest(struct json_object *jobj_digests, const digest_description &digest_desc) {
+ struct json_object *jobj_digest, *jobj_keyslots, *jobj_segments;
+
+ jobj_digest = json_object_new_object();
+
+ if (digest_desc.has_type())
+ json_object_object_add(jobj_digest, "type", json_object_new_string(keyslot_kdf_type_to_string(digest_desc.type()).c_str()));
+
+ if (!digest_desc.keyslots().empty()) {
+ jobj_keyslots = json_object_new_array();
+
+ for (const object_id& oid : digest_desc.keyslots()) {
+ json_object_array_add(jobj_keyslots,
+ json_object_new_string(object_id_to_string(oid).c_str()));
+ }
+
+ /* Replace or add new keyslots array */
+ json_object_object_add(jobj_digest, "keyslots", jobj_keyslots);
+ }
+
+ if (!digest_desc.segments().empty()) {
+ jobj_segments = json_object_new_array();
+
+ for (const object_id& oid : digest_desc.segments()) {
+ json_object_array_add(jobj_segments,
+ json_object_new_string(object_id_to_string(oid).c_str()));
+ }
+
+ /* Replace or add new segments array */
+ json_object_object_add(jobj_digest, "segments", jobj_segments);
+ }
+
+ if (digest_desc.has_salt())
+ json_object_object_add(jobj_digest, "salt", json_object_new_string(digest_desc.salt().c_str()));
+ if (digest_desc.has_digest())
+ json_object_object_add(jobj_digest, "digest", json_object_new_string(digest_desc.digest().c_str()));
+ if (digest_desc.has_hash())
+ json_object_object_add(jobj_digest, "hash", json_object_new_string(hash_algorithm_to_string(digest_desc.hash()).c_str()));
+ if (digest_desc.has_iterations())
+ json_object_object_add(jobj_digest, "iterations", json_object_new_int(digest_desc.iterations()));
+
+ json_object_object_add(jobj_digests, object_id_to_string(digest_desc.oid()).c_str(), jobj_digest);
+}
+
+std::string LUKS2ProtoConverter::segment_type_to_string(segment_type type) {
+ switch (type) {
+ case SEGMENT_TYPE_LINEAR:
+ return "linear";
+ case SEGMENT_TYPE_CRYPT:
+ return "crypt";
+ }
+}
+
+std::string LUKS2ProtoConverter::segment_flag_to_string(segment_flag flag) {
+ switch (flag) {
+ case IN_REENCRYPTION:
+ return "in-reencryption";
+ case BACKUP_FINAL:
+ return "backup-final";
+ case BACKUP_PREVIOUS:
+ return "backup-previous";
+ case BACKUP_MOVED_SEGMENT:
+ return "backup-moved-segment";
+ }
+}
+
+void LUKS2ProtoConverter::generate_segment_integrity(struct json_object *jobj_integrity, const segment_integrity_description &segment_integrity_desc) {
+ if (segment_integrity_desc.has_type())
+ json_object_object_add(jobj_integrity, "type", json_object_new_string(segment_integrity_desc.type().c_str()));
+ if (segment_integrity_desc.has_journal_encryption())
+ json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string(segment_integrity_desc.journal_encryption().c_str()));
+ if (segment_integrity_desc.has_journal_integrity())
+ json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string(segment_integrity_desc.journal_integrity().c_str()));
+}
+
+void LUKS2ProtoConverter::generate_segment(struct json_object *jobj_segments, const segment_description &segment_desc) {
+ json_object *jobj_flags, *jobj_integrity;
+ json_object *jobj_segment = json_object_new_object();
+
+ if (segment_desc.has_type())
+ json_object_object_add(jobj_segment, "type", json_object_new_string(segment_type_to_string(segment_desc.type()).c_str()));
+
+ if (segment_desc.has_offset())
+ json_object_object_add(jobj_segment, "offset", json_object_new_string(string_uint64_to_string(segment_desc.offset()).c_str()));
+ if (segment_desc.has_size())
+ json_object_object_add(jobj_segment, "size", json_object_new_string(string_uint64_to_string(segment_desc.size()).c_str()));
+
+ if (!segment_desc.flags().empty()) {
+ jobj_flags = json_object_new_array();
+
+ for (const int flag : segment_desc.flags()) {
+ json_object_array_add(jobj_flags,
+ json_object_new_string(segment_flag_to_string(segment_flag(flag)).c_str()));
+ }
+
+ /* Replace or add new flags array */
+ json_object_object_add(jobj_segment, "flags", jobj_flags);
+ }
+
+ if (segment_desc.has_iv_tweak())
+ json_object_object_add(jobj_segment, "iv_tweak", json_object_new_string(string_uint64_to_string(segment_desc.iv_tweak()).c_str()));
+ if (segment_desc.has_encryption())
+ json_object_object_add(jobj_segment, "encryption", json_object_new_string(segment_desc.encryption().c_str()));
+ if (segment_desc.has_sector_size())
+ json_object_object_add(jobj_segment, "sector_size", json_object_new_int(segment_desc.sector_size()));
+
+ if (segment_desc.has_integrity()) {
+ jobj_integrity = json_object_new_object();
+ generate_segment_integrity(jobj_integrity, segment_desc.integrity());
+ json_object_object_add(jobj_segment, "integrity", jobj_integrity);
+ }
+
+ json_object_object_add(jobj_segments, object_id_to_string(segment_desc.oid()).c_str(), jobj_segment);
+}
+
+void LUKS2ProtoConverter::create_jobj(const LUKS2_both_headers &headers) {
+ json_object *jobj_keyslots = NULL;
+ json_object *jobj_digests = NULL;
+ json_object *jobj_segments = NULL;
+ json_object *jobj_tokens = NULL;
+
+ const json_area_description &json_desc = headers.json_area();
+
+ jobj = json_object_new_object();
+ if (!jobj)
+ return;
+
+ jobj_keyslots = json_object_new_object();
+ for (const keyslot_description &keyslot_desc : json_desc.keyslots()) {
+ generate_keyslot(jobj_keyslots, keyslot_desc);
+ }
+ json_object_object_add(jobj, "keyslots", jobj_keyslots);
+
+ jobj_digests = json_object_new_object();
+ for (const digest_description &digest_desc : json_desc.digests()) {
+ generate_digest(jobj_digests, digest_desc);
+ }
+ json_object_object_add(jobj, "digests", jobj_digests);
+
+ jobj_segments = json_object_new_object();
+ for (const segment_description &segment_desc : json_desc.segments()) {
+ generate_segment(jobj_segments, segment_desc);
+ }
+ json_object_object_add(jobj, "segments", jobj_segments);
+
+ jobj_tokens = json_object_new_object();
+ for (const token_description &token_desc : json_desc.tokens()) {
+ generate_token(jobj_tokens, token_desc);
+ }
+ json_object_object_add(jobj, "tokens", jobj_tokens);
+
+ if (json_desc.has_config()) {
+ uint64_t hdr_size = json_desc.config().use_primary_hdr_size() ? headers.primary_header().hdr_size() : headers.secondary_header().hdr_size();
+ generate_config(json_desc.config(), hdr_size - LUKS2_HDR_BIN_LEN, KEYSLOTS_SIZE);
+ }
+}
+
+void LUKS2ProtoConverter::emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid) {
+ struct luks2_hdr_disk hdr = {};
+ int r;
+
+ if (hd)
+ crypt_hash_destroy(hd);
+ if (crypt_hash_init(&hd, "sha256"))
+ err(EXIT_FAILURE, "crypt_hash_init failed");
+
+
+ r = lseek(fd, offset, SEEK_SET);
+ if (r == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ switch (header_proto.magic()) {
+ case INVALID:
+ memset(&hdr.magic, 0, LUKS2_MAGIC_L);
+ break;
+ case FIRST:
+ memcpy(&hdr.magic, LUKS2_MAGIC_1ST, LUKS2_MAGIC_L);
+ break;
+ case SECOND:
+ memcpy(&hdr.magic, LUKS2_MAGIC_2ND, LUKS2_MAGIC_L);
+ break;
+ }
+ hdr.version = cpu_to_be16(header_proto.version());
+ hdr.hdr_size = cpu_to_be64(header_proto.hdr_size());
+ hdr.seqid = cpu_to_be64(seqid);
+ strncpy(hdr.checksum_alg, "sha256", LUKS2_CHECKSUM_ALG_L);
+ hdr.checksum_alg[LUKS2_CHECKSUM_ALG_L - 1] = '\0';
+ strncpy(hdr.uuid, "af7f64ea-3233-4581-946b-6187d812841e", LUKS2_UUID_L);
+ memset(hdr.salt, 1, LUKS2_SALT_L);
+
+
+ if (header_proto.has_selected_offset())
+ hdr.hdr_offset = cpu_to_be64(header_proto.selected_offset());
+ else
+ hdr.hdr_offset = cpu_to_be64(offset);
+
+ if (write_buffer(fd, &hdr, LUKS2_HDR_BIN_LEN) != LUKS2_HDR_BIN_LEN)
+ err(EXIT_FAILURE, "write_buffer failed");
+ if (crypt_hash_write(hd, (char*)&hdr, LUKS2_HDR_BIN_LEN))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+
+ size_t hdr_json_area_len = header_proto.hdr_size() - LUKS2_HDR_BIN_LEN;
+ size_t json_text_len;
+ const char *json_text;
+ uint8_t csum[LUKS2_CHECKSUM_L];
+
+ if (jobj) {
+ json_text = json_object_to_json_string_ext((struct json_object *)jobj, JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
+ if (!json_text || !*json_text)
+ err(EXIT_FAILURE, "json_object_to_json_string_ext failed");
+
+ json_text_len = strlen(json_text);
+
+ size_t write_size = json_text_len > hdr_json_area_len - 1 ? hdr_json_area_len - 1 : json_text_len;
+ if (write_buffer(fd, json_text, write_size) != (ssize_t)write_size)
+ err(EXIT_FAILURE, "write_buffer failed");
+ if (crypt_hash_write(hd, json_text, write_size))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+
+ for (size_t i = 0; i < (hdr_json_area_len - write_size); i++) {
+ if (crypt_hash_write(hd, "\0", 1))
+ err(EXIT_FAILURE, "crypt_hash_write failed");
+ }
+ }
+
+ if (header_proto.use_correct_checksum()) {
+ if (lseek(fd, offset + offsetof(luks2_hdr_disk, csum), SEEK_SET) == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ int hash_size = crypt_hash_size("sha256");
+ if (hash_size <= 0)
+ err(EXIT_FAILURE, "crypt_hash_size failed");
+
+ if (crypt_hash_final(hd, (char*)csum, (size_t)hash_size))
+ err(EXIT_FAILURE, "crypt_hash_final failed");
+ if (write_buffer(fd, csum, hash_size) != hash_size)
+ err(EXIT_FAILURE, "write_buffer failed");
+ }
+}
+
+void LUKS2ProtoConverter::set_write_headers_only(bool headers_only) {
+ write_headers_only = headers_only;
+}
+
+void LUKS2ProtoConverter::convert(const LUKS2_both_headers &headers, int fd) {
+ uint64_t primary_seqid, secondary_seqid;
+ int result;
+
+ size_t out_size = headers.primary_header().hdr_size() + headers.secondary_header().hdr_size();
+
+ if (!write_headers_only)
+ out_size += KEYSLOTS_SIZE + DATA_SIZE;
+
+ result = ftruncate(fd, out_size);
+ if (result == -1)
+ err(EXIT_FAILURE, "truncate failed");
+
+ result = lseek(fd, 0, SEEK_SET);
+ if (result == -1)
+ err(EXIT_FAILURE, "lseek failed");
+
+ switch (headers.seqid()) {
+ case EQUAL:
+ primary_seqid = 1;
+ secondary_seqid = 1;
+ break;
+ case PRIMARY_GREATER:
+ primary_seqid = 2;
+ secondary_seqid = 1;
+ break;
+ case SECONDARY_GREATER:
+ primary_seqid = 1;
+ secondary_seqid = 2;
+ break;
+ }
+
+ create_jobj(headers);
+ emit_luks2_binary_header(headers.primary_header(), fd, 0, primary_seqid);
+ emit_luks2_binary_header(headers.secondary_header(), fd, headers.primary_header().hdr_size(), secondary_seqid);
+}
+
+std::string LUKS2ProtoConverter::config_flag_to_string(config_flag flag) {
+ switch (flag) {
+ case CONFIG_FLAG_ALLOW_DISCARDS:
+ return "allow-discards";
+ case CONFIG_FLAG_SAME_CPU_CRYPT:
+ return "same-cpu-crypt";
+ case CONFIG_FLAG_SUBMIT_FROM_CRYPT_CPUS:
+ return "submit-from-crypt-cpus";
+ case CONFIG_FLAG_NO_JOURNAL:
+ return "no-journal";
+ case CONFIG_FLAG_NO_READ_WORKQUEUE:
+ return "no-read-workqueue";
+ case CONFIG_FLAG_NO_WRITE_WORKQUEUE:
+ return "no-write-workqueue";
+ }
+}
+
+std::string LUKS2ProtoConverter::config_requirement_to_string(config_requirement requirement) {
+ switch (requirement) {
+ case CONFIG_REQUIREMENT_OFFLINE_REENCRYPT:
+ return "offline-reencrypt";
+ case CONFIG_REQUIREMENT_ONLINE_REENCRYPT_V2:
+ return "online-reencrypt-v2";
+ }
+}
+
+void LUKS2ProtoConverter::generate_config(const config_description &config_desc, uint64_t json_size, uint64_t keyslots_size) {
+ json_object *jobj_config, *jobj_flags, *jobj_requirements, *jobj_mandatory;
+ jobj_config = json_object_new_object();
+
+ json_object_object_add(jobj_config, "json_size", json_object_new_string(std::to_string(json_size).c_str()));
+ json_object_object_add(jobj_config, "keyslots_size", json_object_new_string(std::to_string(keyslots_size).c_str()));
+
+ if (!config_desc.config_flags().empty()) {
+ jobj_flags = json_object_new_array();
+
+ for (const int flag : config_desc.config_flags()) {
+ json_object_array_add(jobj_flags,
+ json_object_new_string(config_flag_to_string(config_flag(flag)).c_str()));
+ }
+
+ /* Replace or add new flags array */
+ json_object_object_add(jobj_config, "flags", jobj_flags);
+ }
+
+ if (!config_desc.requirements().empty()) {
+ jobj_requirements = json_object_new_object();
+ jobj_mandatory = json_object_new_array();
+
+ for (const int requirement : config_desc.requirements()) {
+ json_object_array_add(jobj_mandatory,
+ json_object_new_string(config_requirement_to_string(config_requirement(requirement)).c_str()));
+ }
+
+ /* Replace or add new requirements array */
+ json_object_object_add(jobj_requirements, "mandatory", jobj_mandatory);
+ json_object_object_add(jobj_config, "requirements", jobj_requirements);
+ }
+
+ json_object_object_add(jobj, "config", jobj_config);
+}
+
+LUKS2ProtoConverter::~LUKS2ProtoConverter() {
+ json_object_put(jobj);
+ if (hd)
+ crypt_hash_destroy(hd);
+}
+} // namespace LUKS2_proto
diff --git a/tests/fuzz/proto_to_luks2_converter.h b/tests/fuzz/proto_to_luks2_converter.h
new file mode 100644
index 0000000..9f926d0
--- /dev/null
+++ b/tests/fuzz/proto_to_luks2_converter.h
@@ -0,0 +1,91 @@
+/*
+ * cryptsetup LUKS2 custom mutator fuzz target
+ *
+ * Copyright (C) 2022-2023 Daniel Zatovic <daniel.zatovic@gmail.com>
+ * Copyright (C) 2022-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef LUKS2_PROTO_CONVERTER_H_
+#define LUKS2_PROTO_CONVERTER_H_
+
+#include <sstream>
+#include <string>
+#include <json-c/json.h>
+
+#include "LUKS2.pb.h"
+extern "C" {
+#include "crypto_backend/crypto_backend.h"
+}
+
+namespace LUKS2_proto {
+
+class LUKS2ProtoConverter {
+ public:
+ ~LUKS2ProtoConverter();
+ std::string string_uint64_to_string(const string_uint64 &str_u64);
+ std::string hash_algorithm_to_string(const hash_algorithm type);
+ std::string object_id_to_string(const object_id &oid);
+
+ std::string keyslot_area_type_to_string(const keyslot_area_type type);
+ std::string keyslot_kdf_type_to_string(const keyslot_kdf_type type);
+ std::string reencrypt_keyslot_mode_to_string(const reencrypt_keyslot_mode mode);
+ std::string keyslot_type_to_string(const keyslot_type type);
+ std::string reencrypt_keyslot_direction_to_string(const reencrypt_keyslot_direction direction);
+ std::string keyslot_af_type_to_string(const keyslot_af_type type);
+
+ std::string config_flag_to_string(config_flag flag);
+ std::string config_requirement_to_string(config_requirement requirements);
+
+ std::string segment_type_to_string(segment_type type);
+ std::string segment_flag_to_string(segment_flag flag);
+
+ void generate_keyslot(struct json_object *jobj_keyslots, const keyslot_description &keyslot_desc);
+ void generate_keyslot_area(struct json_object *jobj_area, const keyslot_area_description &keyslot_area_desc);
+ void generate_keyslot_kdf(struct json_object *jobj_kdf, const keyslot_kdf_description &keyslot_kdf_desc);
+ void generate_keyslot_af(struct json_object *jobj_af, const keyslot_af_description &keyslot_af_desc);
+
+ void generate_token(struct json_object *jobj_tokens, const token_description &token_desc);
+
+ void generate_digest(struct json_object *jobj_digests, const digest_description &digest_desc);
+
+ void generate_segment_integrity(struct json_object *jobj_integrity, const segment_integrity_description &segment_integrity_desc);
+ void generate_segment(struct json_object *jobj_segments, const segment_description &segment_desc);
+
+ void generate_config(const config_description &config_desc, uint64_t json_size, uint64_t keyslots_size);
+
+ void create_jobj(const LUKS2_both_headers &headers, uint64_t hdr_size);
+ void emit_luks2_binary_header(uint64_t offset, uint64_t seqid, bool is_primary, uint64_t hdr_size);
+ void convert(const LUKS2_both_headers &headers, int fd);
+ void create_jobj(const LUKS2_both_headers &headers);
+ void emit_luks2_binary_header(const LUKS2_header &header_proto, int fd, uint64_t offset, uint64_t seqid);
+
+ void set_write_headers_only(bool headers_only);
+
+ const uint8_t *get_out_buffer();
+ size_t get_out_size();
+
+ static const uint64_t KEYSLOTS_SIZE = 3 * 1024 * 1024;
+ static const uint64_t DATA_SIZE = 16 * 1024 * 1024;
+ private:
+ bool write_headers_only = false;
+ struct crypt_hash *hd = NULL;
+ struct ::json_object *jobj = NULL;
+};
+
+} // namespace LUKS2_proto
+
+#endif // LUKS2_PROTO_CONVERTER_H_
diff --git a/tests/fuzz/unpoison-mutated-buffers-from-libfuzzer.patch b/tests/fuzz/unpoison-mutated-buffers-from-libfuzzer.patch
new file mode 100644
index 0000000..1f48339
--- /dev/null
+++ b/tests/fuzz/unpoison-mutated-buffers-from-libfuzzer.patch
@@ -0,0 +1,29 @@
+diff --git a/src/libfuzzer/libfuzzer_mutator.cc b/src/libfuzzer/libfuzzer_mutator.cc
+index 34d144c..b671fd4 100644
+--- a/src/libfuzzer/libfuzzer_mutator.cc
++++ b/src/libfuzzer/libfuzzer_mutator.cc
+@@ -14,6 +14,8 @@
+
+ #include "src/libfuzzer/libfuzzer_mutator.h"
+
++#include <sanitizer/msan_interface.h>
++
+ #include <string.h>
+
+ #include <algorithm>
+@@ -64,6 +66,7 @@ template <class T>
+ T MutateValue(T v) {
+ size_t size =
+ LLVMFuzzerMutate(reinterpret_cast<uint8_t*>(&v), sizeof(v), sizeof(v));
++ __msan_unpoison(reinterpret_cast<uint8_t*>(&v), size);
+ memset(reinterpret_cast<uint8_t*>(&v) + size, 0, sizeof(v) - size);
+ return v;
+ }
+@@ -93,6 +96,7 @@ std::string Mutator::MutateString(const std::string& value,
+ result.resize(std::max(1, new_size));
+ result.resize(LLVMFuzzerMutate(reinterpret_cast<uint8_t*>(&result[0]),
+ value.size(), result.size()));
++ __msan_unpoison(reinterpret_cast<uint8_t*>(&result[0]), result.size());
+ return result;
+ }
+
diff --git a/tests/fvault2-compat-test b/tests/fvault2-compat-test
new file mode 100755
index 0000000..45022d2
--- /dev/null
+++ b/tests/fvault2-compat-test
@@ -0,0 +1,134 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+MAP=fvault2test
+TST_DIR=fvault2-images
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+[ -z "$srcdir" ] && srcdir="."
+
+function create_mapping()
+{
+ local image=$1
+ local passphrase=$2
+ echo -n "$passphrase" | "$CRYPTSETUP" open --type fvault2 --key-file - \
+ "$image" "$MAP"
+}
+
+function remove_mapping()
+{
+ [ -b "/dev/mapper/$MAP" ] && dmsetup remove --retry "$MAP"
+ rm -rf $TST_DIR
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo " [FAILED]"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "Test skipped."
+ remove_mapping
+ exit 77
+}
+
+function produce_dump()
+{
+ "$CRYPTSETUP" fvault2Dump "$1" || fail
+}
+
+function produce_dump_key()
+{
+ echo "$2" | "$CRYPTSETUP" fvault2Dump "$1" --dump-volume-key || fail
+}
+
+function check_dump()
+{
+ local dump=$1
+ local key=$2
+ local exp_value=$3
+ local regex="$key:\s*\(.*\)"
+ local value=$(echo "$dump" | sed -n "s|$regex|\1|p" | sed 's|\s*$||')
+ [ "$value" = "$exp_value" ] || fail \
+ "$key check failed: expected \"$exp_value\", got \"$value\""
+}
+
+function check_uuid()
+{
+ local exp_uuid=$1
+ local uuid=$(blkid -po value -s UUID "/dev/mapper/$MAP")
+ [ "$uuid" = "$exp_uuid" ] || fail \
+ "UUID check failed: expected \"$exp_uuid\", got \"$uuid\""
+}
+
+function check_sha256()
+{
+ local exp_sum=$1
+ local sum=$(sha256sum /dev/mapper/$MAP | head -c 64)
+ [ "$sum" = "$exp_sum" ] || fail \
+ "SHA256 sum check failed: expected \"$exp_sum\", got \"$sum\""
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+export LANG=C
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+
+if [ ! -d $TST_DIR ]; then
+ tar xJSf $srcdir/fvault2-images.tar.xz --no-same-owner 2>/dev/null || skip "Incompatible tar."
+fi
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+echo "HEADER CHECK"
+IMG="$TST_DIR/small"
+PWD="heslo123"
+
+echo -n " $IMG"
+dump=$(produce_dump $IMG)
+check_dump "$dump" 'Physical volume UUID' fc52bfae-5a1f-4f9b-b3a6-f33303a0e401
+check_dump "$dump" 'Family UUID' 33a76caa-1481-4bc5-8d04-1ac1707c19c0
+check_dump "$dump" 'Logical volume offset' '67108864 [bytes]'
+check_dump "$dump" 'Logical volume size' '167772160 [bytes]'
+check_dump "$dump" 'PBKDF2 iterations' 204222
+check_dump "$dump" 'PBKDF2 salt' '2c 24 9e db 66 63 d6 fb cc 79 05 b7 a4 d7 27 52'
+dump=$(produce_dump_key $IMG heslo123)
+check_dump "$dump" 'Volume key' '20 73 4d 33 89 21 27 74 d7 61 0c 29 d7 32 88 09 16 f3 be 14 c4 b1 2a c7 aa f0 7e 5c cc 77 b3 19'
+echo $PWD | $CRYPTSETUP open --type fvault2 --test-passphrase $IMG || fail
+echo " [OK]"
+
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run activation part of test, test skipped."
+ remove_mapping
+ exit 0
+fi
+
+echo "ACTIVATION CHECK"
+echo -n " $IMG"
+create_mapping $IMG heslo123
+check_uuid de124d8a-2164-394e-924f-8e28db0a09cb
+check_sha256 2c662e36c0f7e2f5583e6a939bbcbdc660805692d0fccaa45ad4052beb3b8e18
+echo " [OK]"
+
+remove_mapping
+exit 0
diff --git a/tests/fvault2-images.tar.xz b/tests/fvault2-images.tar.xz
new file mode 100644
index 0000000..99fab77
--- /dev/null
+++ b/tests/fvault2-images.tar.xz
Binary files differ
diff --git a/tests/generate-symbols-list b/tests/generate-symbols-list
new file mode 100755
index 0000000..33a2e23
--- /dev/null
+++ b/tests/generate-symbols-list
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 2
+}
+
+function generate() {
+ local ver=
+
+ while IFS= read -r line; do
+ local len=${#line}
+
+
+ if [ "${line:0:11}" = "CRYPTSETUP_" ]; then
+ local i=12
+ while [ $i -lt $len ]; do
+ if [ "${line:$i:1}" = "{" ]; then
+ ver=${line:0:$i}
+ break
+ fi
+ i=$((i+1))
+ done
+ elif [ "${line:0:6}" = "crypt_" -a -n "$ver" ]; then
+ printf 'CHECK_SYMBOL(%s, %s)\n' $line $ver
+ fi
+ done < <(tr -d '[:blank:];' < $1)
+}
+
+test $# -ge 1 || fail "usage: $0 <symbol_file>"
+
+test -f $1 || fail "$1 is not a file."
+
+generate $1
diff --git a/tests/generators/generate-luks2-area-in-json-hdr-space-json0.img.sh b/tests/generators/generate-luks2-area-in-json-hdr-space-json0.img.sh
new file mode 100755
index 0000000..a7d3147
--- /dev/null
+++ b/tests/generators/generate-luks2-area-in-json-hdr-space-json0.img.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with one area accessing luks
+# header space
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # make area 7 access the luks2 header space
+ OFFS=$((2*LUKS2_HDR_SIZE*512-1))
+ LEN=1
+ json_str=$(jq -c --arg off $OFFS --arg len $LEN \
+ '.keyslots."0".area.offset = $off | .keyslots."0".area.size = $len' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c --arg off $OFFS --arg len $LEN \
+ 'if (.keyslots."0".area.offset != $off) or (.keyslots."0".area.size != $len)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-argon2-leftover-params.img.sh b/tests/generators/generate-luks2-argon2-leftover-params.img.sh
new file mode 100755
index 0000000..f0b74d7
--- /dev/null
+++ b/tests/generators/generate-luks2-argon2-leftover-params.img.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with luks2 keyslot kdf object
+# having left over params.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # add keyslot 1 to second digest
+ obj_len=$(jq -c -M '.keyslots."1".kdf | length' $TMPDIR/json0)
+ json_str=$(jq -r -c -M '.keyslots."1".kdf.type = "pbkdf2" | .keyslots."1".kdf.iterations = 1001 | .keyslots."1".kdf.hash = "sha256"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_obj_len=$(jq -c -M '.keyslots."1".kdf | length' $TMPDIR/json_res0)
+ test $((obj_len+2)) -eq $new_obj_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-correct-full-json0.img.sh b/tests/generators/generate-luks2-correct-full-json0.img.sh
new file mode 100755
index 0000000..5cba271
--- /dev/null
+++ b/tests/generators/generate-luks2-correct-full-json0.img.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with correct json of maximal size in primary slot.
+# Secondary header is broken on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+PATTERN="\"config\":{"
+KEY="\"config_key\":\""
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_len=${#json_str}
+ pindex=$(strindex $json_str $PATTERN)
+ test $pindex -gt 0 || exit 2
+
+ offset=${#PATTERN}
+ offset=$((offset+pindex))
+ key_len=${#KEY}
+ remain=$((LUKS2_JSON_SIZE*512-json_len-key_len-2)) # -2: closing '"' and terminating '\0'
+ if [ ${json_str:offset:1} = "}" ]; then
+ format_str="%s%s%s"
+ else
+ format_str="%s%s,%s"
+ remain=$((remain-1)) # also count with separating ','
+ fi
+ test $remain -gt 0 || exit 2
+
+ fill=$(repeat_str "X" $remain)"\""
+
+ printf $format_str $KEY $fill ${json_str:$offset} | _dd of=$TMPDIR/json0 bs=1 seek=$offset conv=notrunc
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ #json_str_res0=$(< $TMPDIR/json_res0)
+ read -r json_str_res0 < $TMPDIR/json_res0
+ test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512-1)) || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-corrupted-hdr0-with-correct-chks.img.sh b/tests/generators/generate-luks2-corrupted-hdr0-with-correct-chks.img.sh
new file mode 100755
index 0000000..1365e0c
--- /dev/null
+++ b/tests/generators/generate-luks2-corrupted-hdr0-with-correct-chks.img.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with malformed json but correct checksum in primary header
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_len=${#json_str}
+ json_len=$((json_len-1)) # to replace json closing '}'
+ json_new_str="${json_str:0:json_len},\""
+
+ while [ ${#json_new_str} -le $((LUKS2_JSON_SIZE*512)) ]; do
+ json_new_str=$json_new_str"all_work_and_no_play_makes_Jack_a_dull_boy_"
+ done
+
+ printf "%s" $json_new_str | _dd of=$TMPDIR/json0 bs=512 count=$LUKS2_JSON_SIZE
+
+ lib_mangle_json_hdr0
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ read -r json_str_res0 < $TMPDIR/json_res0
+ test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-corrupted-hdr1-with-correct-chks.img.sh b/tests/generators/generate-luks2-corrupted-hdr1-with-correct-chks.img.sh
new file mode 100755
index 0000000..fcbbb1e
--- /dev/null
+++ b/tests/generators/generate-luks2-corrupted-hdr1-with-correct-chks.img.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with malformed json but correct checksum in secondary header
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json1
+ json_len=${#json_str}
+ json_len=$((json_len-1)) # to replace json closing '}'
+ json_new_str="${json_str:0:json_len},\""
+
+ while [ ${#json_new_str} -le $((LUKS2_JSON_SIZE*512)) ]; do
+ json_new_str=$json_new_str"all_work_and_no_play_makes_Jack_a_dull_boy_"
+ done
+
+ printf "%s" $json_new_str | _dd of=$TMPDIR/json1 bs=512 count=$LUKS2_JSON_SIZE
+
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1
+ read -r json_str_res1 < $TMPDIR/json_res1
+ test ${#json_str_res1} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-checksum-both-hdrs.img.sh b/tests/generators/generate-luks2-invalid-checksum-both-hdrs.img.sh
new file mode 100755
index 0000000..925763e
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-checksum-both-hdrs.img.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with bad checksum in both binary headerer
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ CHKS0=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
+ CHKS1=$(echo "D'oh!: arbitrary chosen string" | calc_sha256_checksum_stdin)
+ write_checksum $CHKS0 $TGT_IMG
+ write_checksum $CHKS1 $TMPDIR/hdr1
+ write_luks2_bin_hdr1 $TMPDIR/hdr1 $TGT_IMG
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-checksum-hdr0.img.sh b/tests/generators/generate-luks2-invalid-checksum-hdr0.img.sh
new file mode 100755
index 0000000..ae8c595
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-checksum-hdr0.img.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with bad checksum in primary binary header
+#
+
+# 1 full target dir
+# 2 full source luks2 image
+
+function generate()
+{
+ CHKS0=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
+ write_checksum $CHKS0 $TGT_IMG
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-checksum-hdr1.img.sh b/tests/generators/generate-luks2-invalid-checksum-hdr1.img.sh
new file mode 100755
index 0000000..a56695d
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-checksum-hdr1.img.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with bad checksum in secondary binary header
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ CHKS1=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
+ write_checksum $CHKS1 $TMPDIR/hdr1
+ write_luks2_bin_hdr1 $TMPDIR/hdr1 $TGT_IMG
+}
+
+function check()
+{
+ lib_hdr1_checksum || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-json-size-c0.img.sh b/tests/generators/generate-luks2-invalid-json-size-c0.img.sh
new file mode 100755
index 0000000..13dea92
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-json-size-c0.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with invalid json_size in config section
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ JS=$(((LUKS2_HDR_SIZE-LUKS2_BIN_HDR_SIZE)*512+4096))
+ json_str=$(jq -c --arg js $JS '.config.json_size = ($js | tostring)' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c --arg js $JS 'if .config.json_size != ($js | tostring )
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-json-size-c1.img.sh b/tests/generators/generate-luks2-invalid-json-size-c1.img.sh
new file mode 100755
index 0000000..5cdc7ce
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-json-size-c1.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with invalid json_size in config section
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ JS=$(((LUKS2_HDR_SIZE-LUKS2_BIN_HDR_SIZE)*512-4096))
+ json_str=$(jq -c --arg js $JS '.config.json_size = ($js | tostring)' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c --arg js $JS 'if .config.json_size != ($js | tostring )
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-json-size-c2.img.sh b/tests/generators/generate-luks2-invalid-json-size-c2.img.sh
new file mode 100755
index 0000000..4122338
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-json-size-c2.img.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with config json size mismatching
+# value in binary header
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ JS=$(((LUKS2_HDR_SIZE-LUKS2_BIN_HDR_SIZE)*512))
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_32K
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+
+ json_str=$(jq -c '.' $TMPDIR/json0)
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ read_luks2_bin_hdr0 $TGT_IMG $TMPDIR/hdr_res0
+ local str_res1=$(head -c 4 $TMPDIR/hdr_res0)
+ test "$str_res1" = "LUKS" || exit 2
+
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1 $TEST_MDA_SIZE
+ local str_res1=$(head -c 4 $TMPDIR/hdr_res1)
+ test "$str_res1" = "SKUL" || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c --arg js $JS 'if .config.json_size != ( $js | tostring )
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-keyslots-size-c0.img.sh b/tests/generators/generate-luks2-invalid-keyslots-size-c0.img.sh
new file mode 100755
index 0000000..8187b72
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-keyslots-size-c0.img.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with too large keyslots_size set in config section
+# (iow config.keyslots_size = data_offset - keyslots_offset + 512)
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # make area 7 being included in area 6
+ OFFS=$((2*LUKS2_HDR_SIZE*512))
+ json_str=$(jq -c --arg off $OFFS '.config.keyslots_size = (.segments."0".offset | tonumber - ($off | tonumber) + 4096 | tostring)' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ # [.keyslots[].area.offset | tonumber] | max | tostring ---> max offset in keyslot areas
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c --arg off $OFFS 'if .config.keyslots_size != ( .segments."0".offset | tonumber - ($off | tonumber) + 4096 | tostring )
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-keyslots-size-c1.img.sh b/tests/generators/generate-luks2-invalid-keyslots-size-c1.img.sh
new file mode 100755
index 0000000..2ba1a9b
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-keyslots-size-c1.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with unaligned keyslots_size config section
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c '.config.keyslots_size = (.config.keyslots_size | tonumber - 1 | tostring)' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.config.keyslots_size | tonumber % 4096) == 0
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-keyslots-size-c2.img.sh b/tests/generators/generate-luks2-invalid-keyslots-size-c2.img.sh
new file mode 100755
index 0000000..f983438
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-keyslots-size-c2.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with keyslots_size less than sum of all keyslots area
+# in json
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq '.config.keyslots_size = ([.keyslots[].area.size] | map(tonumber) | add - 4096 | tostring )' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .config.keyslots_size != ([.keyslots[].area.size ] | map(tonumber) | add - 4096 | tostring)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-object-type-json0.img.sh b/tests/generators/generate-luks2-invalid-object-type-json0.img.sh
new file mode 100755
index 0000000..616120b
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-object-type-json0.img.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with well-formed json format
+# where top level value is not of type object.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_str="[$json_str]" # make top level value an array
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ printf "%s" "$json_str" | _dd of=$TMPDIR/json0 bs=1 conv=notrunc
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ read -r json_str_res0 < $TMPDIR/json_res0
+ test "$json_str" = "$json_str_res0" || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-opening-char-json0.img.sh b/tests/generators/generate-luks2-invalid-opening-char-json0.img.sh
new file mode 100755
index 0000000..3f34692
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-opening-char-json0.img.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with well-formed json prefixed
+# with useless whitespace.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_str=" $json_str" # add useless opening whitespace
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ printf "%s" "$json_str" | _dd of=$TMPDIR/json0 bs=1 conv=notrunc
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ IFS= read -r json_str_res0 < $TMPDIR/json_res0
+ test "$json_str" = "$json_str_res0" || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-tokens.img.sh b/tests/generators/generate-luks2-invalid-tokens.img.sh
new file mode 100755
index 0000000..9719cf7
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-tokens.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with well-formed json format
+# where keyslot is not of type object.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c 'del(.tokens) | .tokens = 42' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+ write_luks2_json "$json_str" $TMPDIR/json1
+
+ lib_mangle_json_hdr0
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .tokens != 42
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-invalid-top-objects.img.sh b/tests/generators/generate-luks2-invalid-top-objects.img.sh
new file mode 100755
index 0000000..174dc2c
--- /dev/null
+++ b/tests/generators/generate-luks2-invalid-top-objects.img.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with well-formed json format
+# where multiple top objects are not of type object.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c 'del(.tokens) | .tokens = 42 |
+ del(.digests) | .digests = 42 |
+ del(.keyslots) | .keyslots = [] |
+ del(.segments) | .segments = "hi"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+ write_luks2_json "$json_str" $TMPDIR/json1
+
+ lib_mangle_json_hdr0
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.tokens != 42) or (.digests != 42) or (.keyslots != []) or (.segments != "hi")
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-keyslot-invalid-af.img.sh b/tests/generators/generate-luks2-keyslot-invalid-af.img.sh
new file mode 100755
index 0000000..99f7679
--- /dev/null
+++ b/tests/generators/generate-luks2-keyslot-invalid-af.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with well-formed json format
+# where keyslot AF type is invalid.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c 'del(.keyslots."0".af.type) | .keyslots."0".af.type = 42' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+ write_luks2_json "$json_str" $TMPDIR/json1
+
+ lib_mangle_json_hdr0
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.keyslots."0".af.type != 42)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-keyslot-invalid-area-size.img.sh b/tests/generators/generate-luks2-keyslot-invalid-area-size.img.sh
new file mode 100755
index 0000000..723d58a
--- /dev/null
+++ b/tests/generators/generate-luks2-keyslot-invalid-area-size.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with well-formed json format
+# where keyslot area object size is UINT64_MAX and will overflow with added length
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c '.keyslots."0"."area".size = "18446744073709551615"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+ write_luks2_json "$json_str" $TMPDIR/json1
+
+ lib_mangle_json_hdr0
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.keyslots."0"."area".size != "18446744073709551615")
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-keyslot-invalid-area.img.sh b/tests/generators/generate-luks2-keyslot-invalid-area.img.sh
new file mode 100755
index 0000000..c41037e
--- /dev/null
+++ b/tests/generators/generate-luks2-keyslot-invalid-area.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with well-formed json format
+# where keyslot area object is not of type object.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c 'del(.keyslots."0".area) | .keyslots."0".area = 42' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+ write_luks2_json "$json_str" $TMPDIR/json1
+
+ lib_mangle_json_hdr0
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.keyslots."0".area != 42)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-keyslot-invalid-objects.img.sh b/tests/generators/generate-luks2-keyslot-invalid-objects.img.sh
new file mode 100755
index 0000000..5fcfef2
--- /dev/null
+++ b/tests/generators/generate-luks2-keyslot-invalid-objects.img.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate header with well-formed json format
+# where multiple keyslots objects are not of type object.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c 'del(.keyslots."0".kdf) | .keyslots."0".kdf = 42 |
+ del(.keyslots."0".af) | .keyslots."0".af = 42' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+ write_luks2_json "$json_str" $TMPDIR/json1
+
+ lib_mangle_json_hdr0
+ lib_mangle_json_hdr1
+}
+
+function check()
+{
+ lib_hdr0_checksum || exit 2
+ lib_hdr1_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.keyslots."0".kdf != 42) or (.keyslots."0".af != 42)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-keyslot-missing-digest.img.sh b/tests/generators/generate-luks2-keyslot-missing-digest.img.sh
new file mode 100755
index 0000000..49aeff1
--- /dev/null
+++ b/tests/generators/generate-luks2-keyslot-missing-digest.img.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with luks2 keyslot not assigned
+# to any digest.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str_orig < $TMPDIR/json0
+ arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json0)
+ # remove first element from digests."0".keyslots array
+ json_str=$(jq -r -c -M 'del(.digests."0".keyslots[0])' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json_res0)
+ test $((arr_len-1)) -eq $new_arr_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-keyslot-too-many-digests.img.sh b/tests/generators/generate-luks2-keyslot-too-many-digests.img.sh
new file mode 100755
index 0000000..5ba55f1
--- /dev/null
+++ b/tests/generators/generate-luks2-keyslot-too-many-digests.img.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with luks2 keyslot assigned
+# to more than 1 digest.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # add keyslot 1 to second digest
+ json_str=$(jq -r -c -M '.digests."1" = .digests."0" | .digests."1".keyslots = ["1"]' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_arr_len=$(jq -c -M '.digests."1".keyslots | length' $TMPDIR/json_res0)
+ test 1 -eq $new_arr_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-128k-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-128k-secondary.img.sh
new file mode 100755
index 0000000..2a44678
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-128k-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 128 KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_128K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-128k.img.sh b/tests/generators/generate-luks2-metadata-size-128k.img.sh
new file mode 100755
index 0000000..79cccbd
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-128k.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 128KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_128K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-16k-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-16k-secondary.img.sh
new file mode 100755
index 0000000..f0e6e8d
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-16k-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 16 KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-1m-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-1m-secondary.img.sh
new file mode 100755
index 0000000..25c19c1
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-1m-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 1 MiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_1M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-1m.img.sh b/tests/generators/generate-luks2-metadata-size-1m.img.sh
new file mode 100755
index 0000000..9228fe5
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-1m.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 1 MiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_1M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-256k-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-256k-secondary.img.sh
new file mode 100755
index 0000000..b4c1027
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-256k-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 256 KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_256K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-256k.img.sh b/tests/generators/generate-luks2-metadata-size-256k.img.sh
new file mode 100755
index 0000000..60ec878
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-256k.img.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+
+function generate()
+{
+ # 256KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_256K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-2m-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-2m-secondary.img.sh
new file mode 100755
index 0000000..0c68905
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-2m-secondary.img.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 2 MiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_2M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-2m.img.sh b/tests/generators/generate-luks2-metadata-size-2m.img.sh
new file mode 100755
index 0000000..0dbb521
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-2m.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 2 MiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_2M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-32k-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-32k-secondary.img.sh
new file mode 100755
index 0000000..effd244
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-32k-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 32 KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_32K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-32k.img.sh b/tests/generators/generate-luks2-metadata-size-32k.img.sh
new file mode 100755
index 0000000..f970144
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-32k.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with non-default metadata json_size.
+# There's only limited set of values allowed as json size in
+# config section of LUKS2 metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 32KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_32K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-4m-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-4m-secondary.img.sh
new file mode 100755
index 0000000..f423850
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-4m-secondary.img.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 4 MiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_4M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-4m.img.sh b/tests/generators/generate-luks2-metadata-size-4m.img.sh
new file mode 100755
index 0000000..b15ad4b
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-4m.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 4 MiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_4M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-512k-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-512k-secondary.img.sh
new file mode 100755
index 0000000..4980816
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-512k-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 512 KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_512K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-512k.img.sh b/tests/generators/generate-luks2-metadata-size-512k.img.sh
new file mode 100755
index 0000000..f3da37f
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-512k.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 512KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_512K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-64k-inv-area-c0.img.sh b/tests/generators/generate-luks2-metadata-size-64k-inv-area-c0.img.sh
new file mode 100755
index 0000000..3913f03
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-64k-inv-area-c0.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with non-default metadata json_size
+# and keyslots area trespassing in json area.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 64KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_64K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024-1))
+ # overlap in json area by exactly one byte
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024-1))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-64k-inv-area-c1.img.sh b/tests/generators/generate-luks2-metadata-size-64k-inv-area-c1.img.sh
new file mode 100755
index 0000000..b01f933
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-64k-inv-area-c1.img.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with non-default metadata json_size
+# and keyslot area overflowing out of keyslots area.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 64KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_64K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ --arg mda $((2*TEST_MDA_SIZE_BYTES)) \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .keyslots."7".area.offset = ( ((.config.keyslots_size | tonumber) + ($mda | tonumber) - (.keyslots."7".area.size | tonumber) + 1) | tostring ) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+# .keyslots.7.area.offset = ( ((.config.keyslots_size | tonumber) + ($mda | tonumber) - (.keyslots.7.area.size | tonumber) + 1) | tostring ) |
+ jq -c --arg mda $((2*TEST_MDA_SIZE_BYTES)) --arg jsize $JSON_SIZE \
+ 'if (.keyslots."7".area.offset != ( ((.config.keyslots_size | tonumber) + ($mda | tonumber) - (.keyslots."7".area.size | tonumber) + 1) | tostring )) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-64k-inv-keyslots-size-c0.img.sh b/tests/generators/generate-luks2-metadata-size-64k-inv-keyslots-size-c0.img.sh
new file mode 100755
index 0000000..5b8517a
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-64k-inv-keyslots-size-c0.img.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size where keyslots size
+# overflows in data area (segment offset)
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 64KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_64K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ --arg mda $((2*TEST_MDA_SIZE_BYTES)) \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .config.keyslots_size = (((($off | tonumber) - ($mda | tonumber) + 4096)) | tostring ) |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE --arg off $DATA_OFFSET --arg mda $((2*TEST_MDA_SIZE_BYTES)) \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize) or
+ (.config.keyslots_size != (((($off | tonumber) - ($mda | tonumber) + 4096)) | tostring ))
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-64k-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-64k-secondary.img.sh
new file mode 100755
index 0000000..9635ab7
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-64k-secondary.img.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate secondary header with one of allowed json area
+# size values. Test whether auto-recovery code is able
+# to validate secondary header with non-default json area
+# size.
+#
+# primary header is corrupted on purpose.
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 64 KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_64K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-64k.img.sh b/tests/generators/generate-luks2-metadata-size-64k.img.sh
new file mode 100755
index 0000000..50941b8
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-64k.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # 64KiB metadata
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_64K
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh b/tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh
new file mode 100755
index 0000000..d2ddd61
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-invalid-secondary.img.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_1M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_MDA_SIZE_BOGUS_BYTES=$((TEST_MDA_SIZE*512*2*1024))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BOGUS_BYTES
+
+ write_bin_hdr_offset $TMPDIR/hdr1 $TEST_MDA_SIZE_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE
+}
+
+function check()
+{
+ lib_hdr0_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json1 $TGT_IMG $TMPDIR/json_res1 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res1 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-metadata-size-invalid.img.sh b/tests/generators/generate-luks2-metadata-size-invalid.img.sh
new file mode 100755
index 0000000..745fc5c
--- /dev/null
+++ b/tests/generators/generate-luks2-metadata-size-invalid.img.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary with predefined json_size. There's only limited
+# set of values allowed as json size in config section of LUKS2
+# metadata
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ TEST_MDA_SIZE=$LUKS2_HDR_SIZE_1M
+
+ TEST_MDA_SIZE_BYTES=$((TEST_MDA_SIZE*512))
+ TEST_MDA_SIZE_BOGUS_BYTES=$((TEST_MDA_SIZE*512*2*1024))
+ TEST_JSN_SIZE=$((TEST_MDA_SIZE-LUKS2_BIN_HDR_SIZE))
+ KEYSLOTS_OFFSET=$((TEST_MDA_SIZE*1024))
+ JSON_DIFF=$(((TEST_MDA_SIZE-LUKS2_HDR_SIZE)*1024))
+ JSON_SIZE=$((TEST_JSN_SIZE*512))
+ DATA_OFFSET=16777216
+
+ json_str=$(jq -c --arg jdiff $JSON_DIFF --arg jsize $JSON_SIZE --arg off $DATA_OFFSET \
+ '.keyslots[].area.offset |= ( . | tonumber + ($jdiff | tonumber) | tostring) |
+ .config.json_size = $jsize |
+ .segments."0".offset = $off' $TMPDIR/json0)
+ test -n "$json_str" || exit 2
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0 $TEST_JSN_SIZE
+ write_luks2_json "$json_str" $TMPDIR/json1 $TEST_JSN_SIZE
+
+ write_bin_hdr_size $TMPDIR/hdr0 $TEST_MDA_SIZE_BOGUS_BYTES
+ write_bin_hdr_size $TMPDIR/hdr1 $TEST_MDA_SIZE_BOGUS_BYTES
+
+ lib_mangle_json_hdr0 $TEST_MDA_SIZE $TEST_JSN_SIZE
+ lib_mangle_json_hdr1 $TEST_MDA_SIZE $TEST_JSN_SIZE kill
+}
+
+function check()
+{
+ lib_hdr1_killed $TEST_MDA_SIZE || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0 $TEST_JSN_SIZE
+ jq -c --arg koff $KEYSLOTS_OFFSET --arg jsize $JSON_SIZE \
+ 'if ([.keyslots[].area.offset] | map(tonumber) | min | tostring != $koff) or
+ (.config.json_size != $jsize)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-missing-keyslot-referenced-in-digest.img.sh b/tests/generators/generate-luks2-missing-keyslot-referenced-in-digest.img.sh
new file mode 100755
index 0000000..a0ca53c
--- /dev/null
+++ b/tests/generators/generate-luks2-missing-keyslot-referenced-in-digest.img.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with missing keyslot object referenced
+# in digest object
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str_orig < $TMPDIR/json0
+ arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json0)
+ # add missing keyslot reference in keyslots array of digest '0'
+ json_str=$(jq -r -c -M 'def arr: ["digests", "0", "keyslots"];
+ def missks: getpath(["keyslots"]) | keys | max | tonumber + 1 | tostring;
+ setpath(arr; getpath(arr) + [ missks ])' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json_res0)
+ test $((arr_len+1)) -eq $new_arr_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-missing-keyslot-referenced-in-token.img.sh b/tests/generators/generate-luks2-missing-keyslot-referenced-in-token.img.sh
new file mode 100755
index 0000000..84d7ed2
--- /dev/null
+++ b/tests/generators/generate-luks2-missing-keyslot-referenced-in-token.img.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with missing keyslot object referenced
+# in token object
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str_orig < $TMPDIR/json0
+ # add missing keyslot reference in keyslots array of token '0'
+ json_str=$(jq -r -c -M 'def missks: getpath(["keyslots"]) | keys | max | tonumber + 1 | tostring;
+ .tokens += {"0":{"type":"dummy","keyslots":[ "0", missks ]}}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_arr_len=$(jq -c -M '.tokens."0".keyslots | length' $TMPDIR/json_res0)
+ test $new_arr_len -eq 2 || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-missing-segment-referenced-in-digest.img.sh b/tests/generators/generate-luks2-missing-segment-referenced-in-digest.img.sh
new file mode 100755
index 0000000..300c2dc
--- /dev/null
+++ b/tests/generators/generate-luks2-missing-segment-referenced-in-digest.img.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with missing segment object referenced
+# in digest object
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str_orig < $TMPDIR/json0
+ arr_len=$(jq -c -M '.digests."0".segments | length' $TMPDIR/json0)
+ # add missing keyslot reference in keyslots array of digest '0'
+ json_str=$(jq -c 'def arr: ["digests", "0", "segments"];
+ def missseg: getpath(["segments"]) | keys | max | tonumber + 1 | tostring;
+ setpath(arr; getpath(arr) + [ missseg ])' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_arr_len=$(jq -c -M '.digests."0".segments | length' $TMPDIR/json_res0)
+ test $((arr_len+1)) -eq $new_arr_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-missing-trailing-null-byte-json0.img.sh b/tests/generators/generate-luks2-missing-trailing-null-byte-json0.img.sh
new file mode 100755
index 0000000..9c5ed0b
--- /dev/null
+++ b/tests/generators/generate-luks2-missing-trailing-null-byte-json0.img.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with well-formed json but missing
+# trailing null byte.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+PATTERN="\"config\":{"
+KEY="\"config_key\":\""
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_len=${#json_str}
+ pindex=$(strindex $json_str $PATTERN)
+ test $pindex -gt 0 || exit 2
+
+ offset=${#PATTERN}
+ offset=$((offset+pindex))
+ key_len=${#KEY}
+ remain=$((LUKS2_JSON_SIZE*512-key_len-json_len-1)) # -1: closing '"'
+ if [ ${json_str:offset:1} = "}" ]; then
+ format_str="%s%s%s"
+ else
+ format_str="%s%s,%s"
+ remain=$((remain-1)) # also count with separating ','
+ fi
+ test $remain -gt 0 || exit 2
+
+ fill=$(repeat_str "X" $remain)
+ fill=$(repeat_str "X" $remain)"\""
+
+ printf $format_str $KEY $fill ${json_str:$offset} | _dd of=$TMPDIR/json0 bs=1 seek=$offset conv=notrunc
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ read -r json_str_res0 < $TMPDIR/json_res0
+ test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-non-null-byte-beyond-json0.img.sh b/tests/generators/generate-luks2-non-null-byte-beyond-json0.img.sh
new file mode 100755
index 0000000..6f4aa7d
--- /dev/null
+++ b/tests/generators/generate-luks2-non-null-byte-beyond-json0.img.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with json area concluded with illegal
+# byte beyond terminating '}' character.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_str="$json_str"X # add illegal 'X' beyond json format
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ printf '%s' $json_str | _dd of=$TMPDIR/json0 bs=1 conv=notrunc
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ read -r json_str_res0 < $TMPDIR/json_res0
+ local len=${#json_str_res0}
+ len=$((len-1))
+ test ${json_str_res0:len:1} = "X" || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-non-null-bytes-beyond-json0.img.sh b/tests/generators/generate-luks2-non-null-bytes-beyond-json0.img.sh
new file mode 100755
index 0000000..18abf23
--- /dev/null
+++ b/tests/generators/generate-luks2-non-null-bytes-beyond-json0.img.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with json area containing illegal bytes
+# beyond well-formed json format.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+QUOTE="[Homer J. Simpson]: Keep looking shocked and move slowly towards the cake."
+SPACE=20
+
+function generate()
+{
+ read -r json_str < $TMPDIR/json0
+ json_len_orig=${#json_str}
+ json_len=$((json_len_orig+${#QUOTE}+SPACE))
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ printf '%s' "$QUOTE" | _dd of=$TMPDIR/json0 seek=$((json_len_orig+SPACE)) bs=1 conv=notrunc
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+
+ _dd if=$TMPDIR/json_res0 of=$TMPDIR/quote skip=$((json_len_orig+SPACE)) count=${#QUOTE} bs=1
+ json_str_res0=$(head -c ${#QUOTE} $TMPDIR/quote)
+ test "$json_str_res0" = "$QUOTE" || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-overlapping-areas-c0-json0.img.sh b/tests/generators/generate-luks2-overlapping-areas-c0-json0.img.sh
new file mode 100755
index 0000000..23883bb
--- /dev/null
+++ b/tests/generators/generate-luks2-overlapping-areas-c0-json0.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with two exactly same areas in terms of 'offset' and 'length'.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # copy area 6 offset and length into area 7
+ json_str=$(jq -c '.keyslots."7".area.offset = .keyslots."6".area.offset |
+ .keyslots."7".area.size = .keyslots."6".area.size' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.keyslots."6".area.offset != .keyslots."7".area.offset) or (.keyslots."6".area.size != .keyslots."7".area.size)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-overlapping-areas-c1-json0.img.sh b/tests/generators/generate-luks2-overlapping-areas-c1-json0.img.sh
new file mode 100755
index 0000000..0733627
--- /dev/null
+++ b/tests/generators/generate-luks2-overlapping-areas-c1-json0.img.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with one area included within another one (in terms of 'offset' + 'length')
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # make area 7 being included in area 6
+ json_str=$(jq -c '.keyslots."7".area.offset = (.keyslots."6".area.offset | tonumber + 1 | tostring ) |
+ .keyslots."7".area.size = ( .keyslots."6".area.size | tonumber - 1 | tostring)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if (.keyslots."7".area.offset != (.keyslots."6".area.offset | tonumber + 1 | tostring)) or
+ (.keyslots."7".area.size != (.keyslots."6".area.size | tonumber - 1 | tostring)) or
+ (.keyslots."7".area.size | tonumber <= 0)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-overlapping-areas-c2-json0.img.sh b/tests/generators/generate-luks2-overlapping-areas-c2-json0.img.sh
new file mode 100755
index 0000000..6699b38
--- /dev/null
+++ b/tests/generators/generate-luks2-overlapping-areas-c2-json0.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with one area slightly cross the boundary of another one
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # make area 7 being included in area 6
+ json_str=$(jq -c '.keyslots."7".area.offset = ([ .keyslots."6".area.offset, .keyslots."6".area.size ] | map(tonumber) | add - 1 | tostring)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .keyslots."7".area.offset != ([.keyslots."6".area.offset, .keyslots."6".area.size ] | map(tonumber) | add - 1 | tostring)
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-pbkdf2-leftover-params-0.img.sh b/tests/generators/generate-luks2-pbkdf2-leftover-params-0.img.sh
new file mode 100755
index 0000000..e035f94
--- /dev/null
+++ b/tests/generators/generate-luks2-pbkdf2-leftover-params-0.img.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with luks2 keyslot kdf object
+# having left over params.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # add keyslot 1 to second digest
+ obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json0)
+ json_str=$(jq -r -c -M '.keyslots."2".kdf.type = "argon2i" | .keyslots."2".kdf.iterations = 1001 | .keyslots."2".kdf.hash = "sha256"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json_res0)
+ test $((obj_len+2)) -eq $new_obj_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-pbkdf2-leftover-params-1.img.sh b/tests/generators/generate-luks2-pbkdf2-leftover-params-1.img.sh
new file mode 100755
index 0000000..d82c2bd
--- /dev/null
+++ b/tests/generators/generate-luks2-pbkdf2-leftover-params-1.img.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with luks2 keyslot kdf object
+# having left over params.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # add keyslot 1 to second digest
+ obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json0)
+ json_str=$(jq -r -c -M '.keyslots."2".kdf.type = "argon2id" | .keyslots."2".kdf.iterations = 1001 | .keyslots."2".kdf.hash = "sha256"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+ lib_hdr0_checksum || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ new_obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json_res0)
+ test $((obj_len+2)) -eq $new_obj_len || exit 2
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-empty-encryption.img.sh b/tests/generators/generate-luks2-segment-crypt-empty-encryption.img.sh
new file mode 100755
index 0000000..ca17aac
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-empty-encryption.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment empty encryption field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".encryption = ""' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".encryption != ""
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-missing-encryption.img.sh b/tests/generators/generate-luks2-segment-crypt-missing-encryption.img.sh
new file mode 100755
index 0000000..e92bc2a
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-missing-encryption.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment encryption field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c 'del(.segments."0".encryption)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".encryption
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-missing-ivoffset.img.sh b/tests/generators/generate-luks2-segment-crypt-missing-ivoffset.img.sh
new file mode 100755
index 0000000..77beb53
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-missing-ivoffset.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment iv_tweak field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c 'del(.segments."0".iv_tweak)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".iv_tweak
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-missing-sectorsize.img.sh b/tests/generators/generate-luks2-segment-crypt-missing-sectorsize.img.sh
new file mode 100755
index 0000000..0609533
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-missing-sectorsize.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment sector_size field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c 'del(.segments."0".sector_size)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".sector_size
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-wrong-encryption.img.sh b/tests/generators/generate-luks2-segment-crypt-wrong-encryption.img.sh
new file mode 100755
index 0000000..9d7e584
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-wrong-encryption.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment wrong encryption field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".encryption = {}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".encryption | type != "object"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-wrong-ivoffset.img.sh b/tests/generators/generate-luks2-segment-crypt-wrong-ivoffset.img.sh
new file mode 100755
index 0000000..0830a16
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-wrong-ivoffset.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment iv_tweak field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".iv_tweak = "dynamic"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".iv_tweak != "dynamic"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-0.img.sh b/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-0.img.sh
new file mode 100755
index 0000000..069b6c0
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-0.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment sector_size field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".sector_size = 1023' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".sector_size != 1023
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-1.img.sh b/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-1.img.sh
new file mode 100755
index 0000000..c310ff1
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-1.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment sector_size field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".sector_size = "4096"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".sector_size != "4096"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-2.img.sh b/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-2.img.sh
new file mode 100755
index 0000000..b4b8b39
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-crypt-wrong-sectorsize-2.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment sector_size field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".sector_size = -1024' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".sector_size != -1024
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-missing-offset.img.sh b/tests/generators/generate-luks2-segment-missing-offset.img.sh
new file mode 100755
index 0000000..6d5811e
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-missing-offset.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment offset field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c 'del(.segments."0".offset)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".offset
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-missing-size.img.sh b/tests/generators/generate-luks2-segment-missing-size.img.sh
new file mode 100755
index 0000000..579858f
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-missing-size.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment size field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c 'del(.segments."0".size)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-missing-type.img.sh b/tests/generators/generate-luks2-segment-missing-type.img.sh
new file mode 100755
index 0000000..5b74c5d
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-missing-type.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment type field missing
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c 'del(.segments."0".type)' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".type
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-two.img.sh b/tests/generators/generate-luks2-segment-two.img.sh
new file mode 100755
index 0000000..798c5be
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-two.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with two segments
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".size = "512" | .segments."1" = {type:"some", offset: (.segments."0".offset | tonumber + 512 | tostring), size: "dynamic"}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."1" | type != "object"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-unknown-type.img.sh b/tests/generators/generate-luks2-segment-unknown-type.img.sh
new file mode 100755
index 0000000..814344a
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-unknown-type.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with generic (unknown) segment type.
+# It should pass the validation.
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0" = {type:"some_type", offset: .segments."0".offset, size: .segments."0".size, a_field:0}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".type != "some_type"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh b/tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh
new file mode 100755
index 0000000..3ba9d47
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-backup-key-0.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong backup segment id
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # create illegal backup segment key (used to be bug in 32bit implementations)
+ json_str=$(jq -c '.segments[(.segments | length + 1 | tostring)] = { "type" : "linear", "offset" : "512", "size" : "512", "flags":["backup-x"]}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments | length < 2
+ then error("Unexpected segments count") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh b/tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh
new file mode 100755
index 0000000..11a94d7
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-backup-key-1.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong backup segment id
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # create illegal backup segment key (used to be bug in 32bit implementations)
+ json_str=$(jq -c '(.segments."0".offset | tonumber) as $i | .segments[range(1;65) | tostring] = { "type" : "linear", "offset" : ($i + 512 | tostring), "size" : "512" } | .segments."268435472" = { "type":"linear","offset":"512","size":"512","flags":["backup-x"]}' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments | length < 64
+ then error("Unexpected segments count") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-flags-element.img.sh b/tests/generators/generate-luks2-segment-wrong-flags-element.img.sh
new file mode 100755
index 0000000..72da1f1
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-flags-element.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment flags containing invalid type
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".flags = [ "hello", 1 ]' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".flags != [ "hello", 1 ]
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-flags.img.sh b/tests/generators/generate-luks2-segment-wrong-flags.img.sh
new file mode 100755
index 0000000..19d6340
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-flags.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment flags field of invalid type
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".flags = "hello"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".flags != "hello"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-offset.img.sh b/tests/generators/generate-luks2-segment-wrong-offset.img.sh
new file mode 100755
index 0000000..c9b1b50
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-offset.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment offset field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".offset = "-42"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".offset != "-42"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-size-0.img.sh b/tests/generators/generate-luks2-segment-wrong-size-0.img.sh
new file mode 100755
index 0000000..b9227a7
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-size-0.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment size field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".size = 4096' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size != 4096
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-size-1.img.sh b/tests/generators/generate-luks2-segment-wrong-size-1.img.sh
new file mode 100755
index 0000000..6be5031
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-size-1.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment size field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".size = "automatic"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size != "automatic"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-size-2.img.sh b/tests/generators/generate-luks2-segment-wrong-size-2.img.sh
new file mode 100755
index 0000000..311c0e8
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-size-2.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment size field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".size = "511"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size != "511"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-segment-wrong-type.img.sh b/tests/generators/generate-luks2-segment-wrong-type.img.sh
new file mode 100755
index 0000000..c041157
--- /dev/null
+++ b/tests/generators/generate-luks2-segment-wrong-type.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with wrong segment type field
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # remove mandatory encryption field
+ json_str=$(jq -c '.segments."0".type = 42' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".type != 42
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-uint64-max-segment-size.img.sh b/tests/generators/generate-luks2-uint64-max-segment-size.img.sh
new file mode 100755
index 0000000..f966e1d
--- /dev/null
+++ b/tests/generators/generate-luks2-uint64-max-segment-size.img.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment size set to UINT64_MAX - 511
+# (512 sector aligned value)
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # UINT64_MAX - 511 (so that it's sector aligned)
+ json_str=$(jq -c '.segments."0".size = "18446744073709551104"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size != "18446744073709551104"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-uint64-overflow-segment-size.img.sh b/tests/generators/generate-luks2-uint64-overflow-segment-size.img.sh
new file mode 100755
index 0000000..4e064e4
--- /dev/null
+++ b/tests/generators/generate-luks2-uint64-overflow-segment-size.img.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment size set to UINT64_MAX + 1
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ json_str=$(jq -c '.segments."0".size = "18446744073709551616"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size != "18446744073709551616"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/generate-luks2-uint64-signed-segment-size.img.sh b/tests/generators/generate-luks2-uint64-signed-segment-size.img.sh
new file mode 100755
index 0000000..6687f35
--- /dev/null
+++ b/tests/generators/generate-luks2-uint64-signed-segment-size.img.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+. lib.sh
+
+#
+# *** Description ***
+#
+# generate primary header with segment size set to -512
+#
+# secondary header is corrupted on purpose as well
+#
+
+# $1 full target dir
+# $2 full source luks2 image
+
+function generate()
+{
+ # UINT64_MAX + 1 (it's 512 sector aligned)
+ json_str=$(jq -c '.segments."0".size = "-512"' $TMPDIR/json0)
+ test ${#json_str} -lt $((LUKS2_JSON_SIZE*512)) || exit 2
+
+ write_luks2_json "$json_str" $TMPDIR/json0
+
+ lib_mangle_json_hdr0_kill_hdr1
+}
+
+function check()
+{
+ lib_hdr1_killed || exit 2
+
+ read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
+ jq -c 'if .segments."0".size != "-512"
+ then error("Unexpected value in result json") else empty end' $TMPDIR/json_res0 || exit 5
+}
+
+lib_prepare $@
+generate
+check
+lib_cleanup
diff --git a/tests/generators/lib.sh b/tests/generators/lib.sh
new file mode 100644
index 0000000..c0e9cc1
--- /dev/null
+++ b/tests/generators/lib.sh
@@ -0,0 +1,283 @@
+#!/bin/bash
+
+# all in 512 bytes blocks (including binary hdr (4KiB))
+LUKS2_HDR_SIZE=32 # 16 KiB
+LUKS2_HDR_SIZE_32K=64 # 32 KiB
+LUKS2_HDR_SIZE_64K=128 # 64 KiB
+LUKS2_HDR_SIZE_128K=256 # 128 KiB
+LUKS2_HDR_SIZE_256K=512 # 256 KiB
+LUKS2_HDR_SIZE_512K=1024 # 512 KiB
+LUKS2_HDR_SIZE_1M=2048 # 1 MiB
+LUKS2_HDR_SIZE_2M=4096 # 2 MiB
+LUKS2_HDR_SIZE_4M=8192 # 4 MiB
+
+LUKS2_BIN_HDR_SIZE=8 # 4 KiB
+LUKS2_JSON_SIZE=$((LUKS2_HDR_SIZE-LUKS2_BIN_HDR_SIZE))
+
+LUKS2_BIN_HDR_CHKS_OFFSET=0x1C0
+LUKS2_BIN_HDR_CHKS_LENGTH=64
+
+[ -z "$srcdir" ] && srcdir="."
+TMPDIR=$srcdir/tmp
+
+# to be set by individual generator
+TGT_IMG=""
+SRC_IMG=""
+
+repeat_str() {
+ printf "$1"'%.0s' $(eval "echo {1.."$(($2))"}");
+}
+
+function strindex()
+{
+ local x="${1%%$2*}"
+ [[ $x = $1 ]] && echo -1 || echo ${#x}
+}
+
+function test_img_name()
+{
+ local str=$(basename $1)
+ str=${str#generate-}
+ str=${str%%.sh}
+ echo $str
+}
+
+# read primary bin hdr
+# 1:from 2:to
+function read_luks2_bin_hdr0()
+{
+ _dd if=$1 of=$2 bs=512 count=$LUKS2_BIN_HDR_SIZE
+}
+
+# read primary json area
+# 1:from 2:to 3:[json only size (defaults to 12KiB)]
+function read_luks2_json0()
+{
+ local _js=${4:-$LUKS2_JSON_SIZE}
+ local _js=$((_js*512/4096))
+ _dd if=$1 of=$2 bs=4096 skip=1 count=$_js
+}
+
+# read secondary bin hdr
+# 1:from 2:to 3:[metadata size (defaults to 16KiB)]
+function read_luks2_bin_hdr1()
+{
+ _dd if=$1 of=$2 skip=${3:-$LUKS2_HDR_SIZE} bs=512 count=$LUKS2_BIN_HDR_SIZE
+}
+
+# read secondary json area
+# 1:from 2:to 3:[json only size (defaults to 12KiB)]
+function read_luks2_json1()
+{
+ local _js=${3:-$LUKS2_JSON_SIZE}
+ _dd if=$1 of=$2 bs=512 skip=$((2*LUKS2_BIN_HDR_SIZE+_js)) count=$_js
+}
+
+# read primary metadata area (bin + json)
+# 1:from 2:to 3:[metadata size (defaults to 16KiB)]
+function read_luks2_hdr_area0()
+{
+ local _as=${3:-$LUKS2_HDR_SIZE}
+ local _as=$((_as*512))
+ _dd if=$1 of=$2 bs=$_as count=1
+}
+
+# read secondary metadata area (bin + json)
+# 1:from 2:to 3:[metadata size (defaults to 16KiB)]
+function read_luks2_hdr_area1()
+{
+ local _as=${3:-$LUKS2_HDR_SIZE}
+ local _as=$((_as*512))
+ _dd if=$1 of=$2 bs=$_as skip=1 count=1
+}
+
+# write secondary bin hdr
+# 1:from 2:to 3:[metadata size (defaults to 16KiB)]
+function write_luks2_bin_hdr1()
+{
+ _dd if=$1 of=$2 bs=512 seek=${3:-$LUKS2_HDR_SIZE} count=$LUKS2_BIN_HDR_SIZE conv=notrunc
+}
+
+# write primary metadata area (bin + json)
+# 1:from 2:to 3:[metadata size (defaults to 16KiB)]
+function write_luks2_hdr0()
+{
+ local _as=${3:-$LUKS2_HDR_SIZE}
+ local _as=$((_as*512))
+ _dd if=$1 of=$2 bs=$_as count=1 conv=notrunc
+}
+
+# write secondary metadata area (bin + json)
+# 1:from 2:to 3:[metadata size (defaults to 16KiB)]
+function write_luks2_hdr1()
+{
+ local _as=${3:-$LUKS2_HDR_SIZE}
+ local _as=$((_as*512))
+ _dd if=$1 of=$2 bs=$_as seek=1 count=1 conv=notrunc
+}
+
+# write json (includes padding)
+# 1:json_string 2:to 3:[json size (defaults to 12KiB)]
+function write_luks2_json()
+{
+ local _js=${3:-$LUKS2_JSON_SIZE}
+ local len=${#1}
+ echo -n -E "$1" > $2
+ truncate -s $((_js*512)) $2
+}
+
+function kill_bin_hdr()
+{
+ printf "VACUUM" | _dd of=$1 bs=1 conv=notrunc
+}
+
+function erase_checksum()
+{
+ _dd if=/dev/zero of=$1 bs=1 seek=$(printf %d $LUKS2_BIN_HDR_CHKS_OFFSET) count=$LUKS2_BIN_HDR_CHKS_LENGTH conv=notrunc
+}
+
+function read_sha256_checksum()
+{
+ _dd if=$1 bs=1 skip=$(printf %d $LUKS2_BIN_HDR_CHKS_OFFSET) count=32 | xxd -c 32 -p
+}
+
+# 1 - string with checksum
+function write_checksum()
+{
+ test $# -eq 2 || return 1
+ test $((${#1}/2)) -le $LUKS2_BIN_HDR_CHKS_LENGTH || { echo "too long"; return 1; }
+
+ echo $1 | xxd -r -p | _dd of=$2 bs=1 seek=$(printf %d $LUKS2_BIN_HDR_CHKS_OFFSET) conv=notrunc
+}
+
+function calc_sha256_checksum_file()
+{
+ sha256sum $1 | cut -d ' ' -f 1
+}
+
+function calc_sha256_checksum_stdin()
+{
+ sha256sum - | cut -d ' ' -f 1
+}
+
+# merge bin hdr with json to form metadata area
+# 1:bin_hdr 2:json 3:to 4:[json size (defaults to 12KiB)]
+function merge_bin_hdr_with_json()
+{
+ local _js=${4:-$LUKS2_JSON_SIZE}
+ local _js=$((_js*512/4096))
+ _dd if=$1 of=$3 bs=4096 count=1
+ _dd if=$2 of=$3 bs=4096 seek=1 count=$_js
+}
+
+function _dd()
+{
+ dd $@ status=none
+}
+
+function write_bin_hdr_size() {
+ printf '%016x' $2 | xxd -r -p -l 16 | _dd of=$1 bs=8 count=1 seek=1 conv=notrunc
+}
+
+function write_bin_hdr_offset() {
+ printf '%016x' $2 | xxd -r -p -l 16 | _dd of=$1 bs=8 count=1 seek=32 conv=notrunc
+}
+
+# generic header helpers
+# $TMPDIR/json0 - JSON hdr1
+# $TMPDIR/json1 - JSON hdr2
+# $TMPDIR/hdr0 - bin hdr1
+# $TMPDIR/hdr1 - bin hdr2
+
+# 1:target_dir 2:source_image
+function lib_prepare()
+{
+ test $# -eq 2 || exit 1
+
+ TGT_IMG=$1/$(test_img_name $0)
+ SRC_IMG=$2
+
+ # wipe checksums
+ CHKS0=0
+ CHKS1=0
+
+ cp $SRC_IMG $TGT_IMG
+ test -d $TMPDIR || mkdir $TMPDIR
+ read_luks2_json0 $TGT_IMG $TMPDIR/json0
+ read_luks2_json1 $TGT_IMG $TMPDIR/json1
+ read_luks2_bin_hdr0 $TGT_IMG $TMPDIR/hdr0
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr1
+}
+
+function lib_cleanup()
+{
+ rm -f $TMPDIR/*
+ rm -fd $TMPDIR
+}
+
+function lib_mangle_json_hdr0()
+{
+ local mda_sz=${1:-}
+ local jsn_sz=${2:-}
+ local kill_hdr=${3:-}
+
+ merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0 $jsn_sz
+ erase_checksum $TMPDIR/area0
+ CHKS0=$(calc_sha256_checksum_file $TMPDIR/area0)
+ write_checksum $CHKS0 $TMPDIR/area0
+ test -n "$kill_hdr" && kill_bin_hdr $TMPDIR/area0
+ write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG $mda_sz
+}
+
+function lib_mangle_json_hdr1()
+{
+ local mda_sz=${1:-}
+ local jsn_sz=${2:-}
+ local kill_hdr=${3:-}
+
+ merge_bin_hdr_with_json $TMPDIR/hdr1 $TMPDIR/json1 $TMPDIR/area1 $jsn_sz
+ erase_checksum $TMPDIR/area1
+ CHKS1=$(calc_sha256_checksum_file $TMPDIR/area1)
+ write_checksum $CHKS1 $TMPDIR/area1
+ test -n "$kill_hdr" && kill_bin_hdr $TMPDIR/area1
+ write_luks2_hdr1 $TMPDIR/area1 $TGT_IMG $mda_sz
+}
+
+function lib_mangle_json_hdr0_kill_hdr1()
+{
+ lib_mangle_json_hdr0
+
+ kill_bin_hdr $TMPDIR/hdr1
+ write_luks2_hdr1 $TMPDIR/hdr1 $TGT_IMG
+}
+
+function lib_hdr0_killed()
+{
+ local mda_sz=${1:-}
+
+ read_luks2_bin_hdr0 $TGT_IMG $TMPDIR/hdr_res0 $mda_sz
+ local str_res0=$(head -c 6 $TMPDIR/hdr_res0)
+ test "$str_res0" = "VACUUM"
+}
+
+function lib_hdr1_killed()
+{
+ local mda_sz=${1:-}
+
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1 $mda_sz
+ local str_res1=$(head -c 6 $TMPDIR/hdr_res1)
+ test "$str_res1" = "VACUUM"
+}
+
+function lib_hdr0_checksum()
+{
+ local chks_res0=$(read_sha256_checksum $TGT_IMG)
+ test "$CHKS0" = "$chks_res0"
+}
+
+function lib_hdr1_checksum()
+{
+ read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1
+ local chks_res1=$(read_sha256_checksum $TMPDIR/hdr_res1)
+ test "$CHKS1" = "$chks_res1"
+}
diff --git a/tests/img_fs_ext4.img.xz b/tests/img_fs_ext4.img.xz
new file mode 100644
index 0000000..de688f0
--- /dev/null
+++ b/tests/img_fs_ext4.img.xz
Binary files differ
diff --git a/tests/img_fs_vfat.img.xz b/tests/img_fs_vfat.img.xz
new file mode 100644
index 0000000..5ecfa67
--- /dev/null
+++ b/tests/img_fs_vfat.img.xz
Binary files differ
diff --git a/tests/img_fs_xfs.img.xz b/tests/img_fs_xfs.img.xz
new file mode 100644
index 0000000..a7034a7
--- /dev/null
+++ b/tests/img_fs_xfs.img.xz
Binary files differ
diff --git a/tests/integrity-compat-test b/tests/integrity-compat-test
new file mode 100755
index 0000000..208eafb
--- /dev/null
+++ b/tests/integrity-compat-test
@@ -0,0 +1,651 @@
+#!/bin/bash
+#
+# Test integritysetup compatibility.
+#
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+INTSETUP=$CRYPTSETUP_PATH/integritysetup
+
+INTSETUP_VALGRIND=../.libs/integritysetup
+INTSETUP_LIB_VALGRIND=../.libs
+
+DEV_NAME=dmc_test
+DEV_NAME2=dmc_fake
+DEV_LOOP=""
+DEV=test123.img
+DEV2=test124.img
+KEY_FILE=key.img
+KEY_FILE2=key2.img
+
+dmremove() { # device
+ udevadm settle >/dev/null 2>&1
+ dmsetup remove --retry $1 >/dev/null 2>&1
+}
+
+cleanup() {
+ [ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
+ [ -b /dev/mapper/$DEV_NAME2 ] && dmremove $DEV_NAME2
+ [ -n "$DEV_LOOP" ] && losetup -d "$DEV_LOOP"
+ DEV_LOOP=""
+ rm -f $DEV $DEV2 $KEY_FILE $KEY_FILE2 >/dev/null 2>&1
+}
+
+fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function dm_integrity_features()
+{
+ VER_STR=$(dmsetup targets | grep integrity | cut -f2 -dv)
+ [ -z "$VER_STR" ] && skip "Cannot find dm-integrity target, test skipped."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ [ $VER_MAJ -lt 1 ] && return
+ [ $VER_MIN -gt 1 ] && {
+ DM_INTEGRITY_META=1
+ DM_INTEGRITY_RECALC=1
+ }
+ [ $VER_MIN -gt 2 ] && {
+ DM_INTEGRITY_BITMAP=1
+ }
+ [ $VER_MIN -gt 5 ] && {
+ DM_INTEGRITY_RESIZE_SUPPORTED=1
+ }
+ [ $VER_MIN -gt 6 ] && {
+ DM_INTEGRITY_HMAC_FIX=1
+ }
+ [ $VER_MIN -gt 7 ] && {
+ DM_INTEGRITY_RESET=1
+ }
+}
+
+add_device() {
+ cleanup
+ dd if=/dev/urandom of=$KEY_FILE bs=4096 count=1 >/dev/null 2>&1
+ dd if=/dev/urandom of=$KEY_FILE2 bs=1 count=32 >/dev/null 2>&1
+ dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
+ dd if=/dev/zero of=$DEV2 bs=1M count=32 >/dev/null 2>&1
+ sync
+}
+
+status_check() # name value
+{
+ X=$($INTSETUP status $DEV_NAME | grep "$1" | sed 's/.*: //' | sed 's/^[[:space:]]*//')
+ if [ "$X" != "$2" ] ; then
+ echo "[status FAIL]"
+ echo " Expecting $1:$2 got \"$X\"."
+ fail
+ fi
+}
+
+dump_check() # name value
+{
+ X=$($INTSETUP dump $DEV | grep "$1" | cut -d' ' -f 2)
+ if [ "$X" != "$2" ] ; then
+ echo "[dump FAIL]"
+ echo " Expecting $1:$2 got \"$X\"."
+ fail
+ fi
+}
+
+kernel_param_check() # number value
+{
+ X=$(dmsetup table $DEV_NAME | cut -d " " -f $1)
+ if [ "$X" != $2 ] ; then
+ echo "[param_check FAIL]"
+ echo "Expecting $2 got \"$X\"."
+ fail
+ fi
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $INTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$INTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${INTSETUP_VALGRIND} "$@"
+}
+
+int_check_sum_only() # checksum
+{
+ VSUM=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
+ if [ "$VSUM" = "$1" ] ; then
+ echo -n "[CHECKSUM OK]"
+ else
+ echo "[FAIL]"
+ echo " Expecting $1 got $VSUM."
+ fail
+ fi
+}
+
+int_check_sum() # alg checksum [keyfile keysize]
+{
+ if [ -n "$4" ] ; then
+ KEY_PARAMS="--integrity-key-file $3 --integrity-key-size $4"
+ else
+ KEY_PARAMS=""
+ fi
+
+ # Fill device with zeroes and reopen it
+ dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M oflag=direct >/dev/null 2>&1
+ dmremove $DEV_NAME
+
+ $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
+
+ int_check_sum_only $2
+}
+
+intformat() # alg alg_out tagsize outtagsize sector_size csum [keyfile keysize]
+{
+ if [ -n "$8" ] ; then
+ KEY_PARAMS="--integrity-key-file $7 --integrity-key-size $8"
+ else
+ KEY_PARAMS=""
+ fi
+
+ if [ $3 -ne 0 ] ; then
+ TAG_PARAMS="--tag-size $3"
+ else
+ TAG_PARAMS=""
+ fi
+
+ echo -n "[INTEGRITY:$2:$4:$5]"
+ [ -n "$8" ] && echo -n "[KEYFILE:$8]"
+ echo -n "[FORMAT]"
+ $INTSETUP format --integrity-legacy-padding -q --integrity $1 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ if [[ $1 =~ "sha2" || $1 =~ "crc" ]] ; then
+ fail "Cannot format device."
+ fi
+ echo "[N/A]"
+ return
+ fi
+
+ dump_check "tag_size" $4
+ dump_check "sector_size" $5
+ echo -n "[ACTIVATE]"
+ $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
+ if [ -n "$8" ]; then
+ KEY_HEX=$(xxd -c 4096 -l $8 -p $7)
+ [ -z "$KEY_HEX" ] && fail "Cannot decode key."
+ dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
+ fi
+ status_check "tag size" $4
+ status_check "integrity" $2
+ status_check "sector size" "$5 bytes"
+ int_check_sum $1 $6 $7 $8
+ echo -n "[REMOVE]"
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+}
+
+int_error_detection() # mode alg tagsize outtagsize sector_size key_file key_size
+{
+ if [ "$1" == "B" ] ; then
+ INT_MODE="-B"
+ else
+ INT_MODE=""
+ fi
+ if [ -n "$7" ] ; then
+ KEY_PARAMS="--integrity-key-file $6 --integrity-key-size $7"
+ else
+ KEY_PARAMS=""
+ fi
+ if [ $3 -ne 0 ] ; then
+ TAG_PARAMS="--tag-size $3"
+ else
+ TAG_PARAMS=""
+ fi
+ dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
+
+ echo -n "[INTEGRITY:$1:$2:$4:$5]"
+ echo -n "[FORMAT]"
+ $INTSETUP format -q --integrity $2 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV $INT_MODE >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ if [[ $2 =~ "sha2" || $2 =~ "crc" ]] ; then
+ fail "Cannot format device."
+ fi
+ echo "[N/A]"
+ return
+ fi
+ echo -n "[ACTIVATE]"
+ $INTSETUP open $DEV $DEV_NAME --integrity $2 --integrity-no-journal $KEY_PARAMS $INT_MODE || fail "Cannot activate device."
+
+ if [ -n "$6" -a -n "$7" ]; then
+ echo -n "[KEYED HASH]"
+ KEY_HEX=$(xxd -c 256 -l $7 -p $6)
+ [ -z "$KEY_HEX" ] && fail "Cannot decode key."
+ dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
+ fi
+
+ echo -n "[WRITE DATA]"
+ echo -n "EXAMPLE TEXT" | dd of=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Cannot write to device."
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+
+ # find offset of data area
+ ARR=($(dd if=$DEV bs=512 2>/dev/null | hexdump -C | grep 'EXAMPLE TEXT'))
+ OFF_HEX=${ARR[0]}
+ OFF_DEC=$((16#$OFF_HEX))
+
+ echo -n "[CORRUPT DATA:$OFF_DEC]"
+ echo -n "Z" | dd of=$DEV bs=1 seek=$OFF_DEC conv=notrunc >/dev/null 2>&1 || fail "Cannot write to device."
+
+ echo -n "[DETECT ERROR]"
+ $INTSETUP open $DEV $DEV_NAME --integrity $2 $KEY_PARAMS $INT_MODE || fail "Cannot activate device."
+ dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 && fail "Error detection failed."
+ echo -n "[REMOVE]"
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+}
+
+int_journal() # 1 alg, 2 tagsize, 3 sector_size, 4 watermark, 5 commit_time, 6 journal_integrity, 7 key-file, 8 key-size, 9 journal_integrity_out
+{
+ echo -n "[INTEGRITY JOURNAL:$6:${4}%:${5}ms:$8]"
+ echo -n "[FORMAT]"
+ ARGS="--integrity $1 --journal-watermark $4 --journal-commit-time $5 --journal-integrity $6 --journal-integrity-key-file $7 --journal-integrity-key-size $8"
+ $INTSETUP format -q --tag-size $2 --sector-size $3 $ARGS $DEV || fail "Cannot format device."
+
+ echo -n "[ACTIVATE]"
+
+ $INTSETUP open $DEV $DEV_NAME $ARGS || fail "Cannot activate device."
+
+ echo -n "[KEYED HASH]"
+ KEY_HEX=$(xxd -c 4096 -l $8 -p $7)
+ [ -z "$KEY_HEX" ] && fail "Cannot decode key."
+ dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
+
+ status_check "journal watermark" "${4}%"
+ status_check "journal commit time" "${5} ms"
+ status_check "journal integrity MAC" $9
+
+ echo -n "[REMOVE]"
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+}
+
+
+int_journal_crypt() # crypt_alg crypt_alg_kernel crypt_key crypt_key_size
+{
+ echo -n "[JOURNAL CRYPT:$1:${4}B]"
+
+ echo -n "[FORMAT]"
+ ARGS="--journal-crypt $1 --journal-crypt-key-file $3 --journal-crypt-key-size $4"
+ $INTSETUP format -q $ARGS $DEV || fail "Cannot format device."
+
+ echo -n "[ACTIVATE]"
+ $INTSETUP open $DEV $DEV_NAME $ARGS || fail "Cannot activate device."
+
+ KEY_HEX=$(xxd -c 256 -l $4 -p $3)
+ [ -z "$KEY_HEX" ] && fail "Cannot decode key."
+ dmsetup table --showkeys $DEV_NAME | grep -q "journal_crypt:$2:$KEY_HEX" || fail "Key mismatch."
+
+ $INTSETUP close $DEV_NAME
+ echo "[OK]"
+}
+
+int_mode() # alg tag_size sector_size [keyfile keysize]
+{
+ if [ -n "$5" ] ; then
+ KEY_PARAMS="--integrity-key-file $4 --integrity-key-size $5"
+ else
+ KEY_PARAMS=""
+ fi
+
+ echo -n "[MODE TESTS:$1:$2:$3]"
+ ARGS="--tag-size $2 --sector-size $3"
+
+ $INTSETUP format -q $ARGS $KEY_PARAMS $DEV --integrity $1 || fail "Cannot format device."
+
+ echo -n "[JOURNALED WRITES]"
+ $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device with journal."
+ status_check "mode" "read/write"
+ kernel_param_check 7 "J"
+
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+
+ echo -n "[DIRECT WRITES]"
+ $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS --integrity-no-journal || fail "Cannot activate device without journal."
+ status_check "mode" "read/write"
+ status_check "journal" "not active"
+ kernel_param_check 7 "D"
+
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+
+ echo -n "[RECOVERY MODE]"
+ $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS --integrity-recovery-mode || fail "Cannot activate device in recovery mode."
+ status_check "mode" "read/write recovery"
+ kernel_param_check 7 "R"
+
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+
+ echo "[OK]"
+}
+
+check_device_size() # device_name expected_size error_message
+{
+ CURRENT_SIZE=$(dmsetup table | grep $1 | cut -d' ' -f 3)
+ [ $CURRENT_SIZE -eq $2 ] || fail "$3: expected $1 to be of size $2, but is $CURRENT_SIZE"
+}
+
+test_resize() # description detached_metadata wipe args
+{
+ echo -n "$1"
+ if [ -z "$DM_INTEGRITY_RESIZE_SUPPORTED" ] ; then
+ echo "[N/A]"
+ return
+ fi
+
+ args="$4"
+ if [ $2 -ne 0 ] ; then
+ echo -n "[DETACHED]"
+ else
+ echo -n "[INTERLEAVE]"
+ fi
+ if [ $3 -ne 0 ] ; then
+ wipe_flag="--wipe"
+ echo -n "[WIPE]"
+ else
+ wipe_flag=""
+ echo -n "[RECALCULATE]"
+ fi
+
+ add_device
+ if [ $2 -ne 0 ] ; then
+ echo -n "[FORMAT]"
+ $INTSETUP format -q $args $DEV2 --data-device $DEV >/dev/null 2>&1 || fail "Cannot format device."
+ echo -n "[ACTIVATE]"
+ $INTSETUP open -q $args $DEV2 $DEV_NAME --data-device $DEV >/dev/null 2>&1 || fail "Cannot activate device."
+ else
+ echo -n "[FORMAT]"
+ $INTSETUP format -q $args $DEV >/dev/null 2>&1 || fail "Cannot format device."
+ echo -n "[ACTIVATE]"
+ $INTSETUP open -q $args $DEV $DEV_NAME >/dev/null 2>&1 || fail "Cannot activate device."
+ fi
+
+ if [ $2 -ne 0 ] ; then
+ # the whole device has 32MiB, if metadata is detached
+ WHOLE_DISK_SIZE=65536
+ else
+ WHOLE_DISK_SIZE=$(dmsetup table | grep $DEV_NAME | cut -d' ' -f 3)
+ fi
+
+ echo -n "[SHRINK]"
+ $INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 1MiB || fail "Failed to resize the device to 1MiB."
+ dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detected after shrink."
+ check_device_size $DEV_NAME $(( 1024*1024 / 512 )) "Shrinking device failed"
+
+ echo -n "[FILL]"
+ $INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 0 || fail "Failed to resize the device to maximum size."
+ dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detected after resize to maximum size."
+ check_device_size $DEV_NAME $WHOLE_DISK_SIZE "Resizing disk to maximum size failed"
+
+ echo -n "[EXPAND FIXED]"
+ fallocate $DEV --len 64M
+ $INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 40MiB || fail "Failed to expand the device to a fixed size."
+ dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detected after expanding to a fixed size."
+ check_device_size $DEV_NAME $(( 40*1024*1024 / 512 )) "Resizing disk after expanding to a fixed size failed"
+
+ echo -n "[FILL]"
+ $INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 0 >/dev/null 2>&1 || fail "Failed to resize the device to maximum size after increasing image size."
+ dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Error detection failed after increasing image size."
+ CURRENT_SIZE=$(dmsetup table | grep $DEV_NAME | cut -d' ' -f 3)
+ [ $CURRENT_SIZE -ge $(( 40*1024*1024 / 512 )) ] || fail "Growing integrity device failed $CURRENT_SIZE is not greater than 40MB ($(( 40*1024*1024 / 512 )) blocks)."
+ if [ $2 -ne 0 ] ; then
+ [ $CURRENT_SIZE -eq 131072 ] || fail "Growing integrity device failed $CURRENT_SIZE is not equal to 64MB (131072 blocks)."
+ fi
+
+ echo -n "[REMOVE]"
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ ! -x "$INTSETUP" ] && skip "Cannot find $INTSETUP, test skipped."
+command -v blockdev >/dev/null || skip "Cannot find blockdev utility, test skipped."
+
+[ -n "$VALG" ] && valgrind_setup && INTSETUP=valgrind_run
+command -v hexdump >/dev/null || skip "WARNING: hexdump tool required."
+command -v xxd >/dev/null || skip "WARNING: xxd tool required."
+modprobe dm-integrity >/dev/null 2>&1
+dm_integrity_features
+
+add_device
+intformat blake2s-256 blake2s-256 32 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
+intformat blake2b-256 blake2b-256 32 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
+intformat crc32c crc32c 0 4 512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
+intformat crc32 crc32 0 4 512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
+intformat xxhash64 xxhash64 0 8 512 6ff6bb889a8485f1fb26aa82671ff5da64f60381fc469e31d7be6094241eee09
+intformat sha1 sha1 0 20 512 6eedd6344dab8875cd185fcd6565dfc869ab36bc57e577f40c685290b1fa7fe7
+intformat sha1 sha1 16 16 4096 e152ec88227b539cd9cafd8bdb587a1072d720cd6bcebe1398d4136c9e7f337b
+intformat sha256 sha256 0 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
+intformat hmac-sha256 hmac\(sha256\) 0 32 512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11 $KEY_FILE 32
+intformat sha256 sha256 0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4
+intformat hmac-sha256 hmac\(sha256\) 0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4 $KEY_FILE 32
+intformat hmac-sha256 hmac\(sha256\) 0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4 $KEY_FILE 4096
+
+echo "Error detection tests:"
+int_error_detection J crc32c 0 4 512
+int_error_detection J crc32c 0 4 4096
+int_error_detection J crc32 0 4 512
+int_error_detection J crc32 0 4 4096
+int_error_detection J xxhash64 0 8 512
+int_error_detection J xxhash64 0 8 4096
+int_error_detection J sha1 0 20 512
+int_error_detection J sha1 16 16 512
+int_error_detection J sha1 0 20 4096
+int_error_detection J sha256 0 32 512
+int_error_detection J sha256 0 32 4096
+
+command -v xxd >/dev/null || skip "WARNING: xxd tool required."
+int_error_detection J hmac-sha256 0 32 512 $KEY_FILE 32
+int_error_detection J hmac-sha256 0 32 4096 $KEY_FILE 32
+
+echo "Journal parameters tests:"
+# Watermark is calculated in kernel, so it can be rounded down/up
+int_journal crc32 4 512 66 1000 hmac-sha256 $KEY_FILE 32 hmac\(sha256\)
+int_journal sha256 32 4096 34 5000 hmac-sha1 $KEY_FILE 16 hmac\(sha1\)
+int_journal sha1 20 512 75 9999 hmac-sha256 $KEY_FILE 32 hmac\(sha256\)
+int_journal sha1 20 512 75 9999 hmac-sha256 $KEY_FILE 4096 hmac\(sha256\)
+
+echo "Journal encryption tests:"
+int_journal_crypt cbc-aes cbc\(aes\) $KEY_FILE 32
+int_journal_crypt cbc-aes cbc\(aes\) $KEY_FILE 16
+int_journal_crypt ctr-aes ctr\(aes\) $KEY_FILE 32
+int_journal_crypt ctr-aes ctr\(aes\) $KEY_FILE 16
+
+echo "Mode tests:"
+int_mode crc32c 4 512
+int_mode crc32 4 512
+int_mode sha1 20 512
+int_mode sha256 32 512
+int_mode hmac-sha256 32 512 $KEY_FILE 32
+int_mode hmac-sha256 32 4096 $KEY_FILE 32
+
+echo -n "Recalculate tags in-kernel:"
+add_device
+if [ -n "$DM_INTEGRITY_RECALC" ] ; then
+ $INTSETUP format -q $DEV --no-wipe || fail "Cannot format device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-recalculate || fail "Cannot activate device."
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot recalculate tags in-kernel"
+ int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo -n "[OK]"
+ if [ -n "$DM_INTEGRITY_RESET" ] ; then
+ $INTSETUP open $DEV $DEV_NAME -I sha256 --integrity-recalculate-reset || fail "Cannot activate device."
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot reset recalculate tags in-kernel"
+ int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[RESET OK]"
+ else
+ echo "[RESET N/A]"
+ fi
+else
+ echo "[N/A]"
+fi
+
+echo -n "Separate metadata device:"
+if [ -n "$DM_INTEGRITY_META" ] ; then
+ add_device
+ $INTSETUP format -q $DEV --data-device $DEV2 || fail "Cannot format device."
+ $INTSETUP open $DEV --data-device $DEV2 $DEV_NAME || fail "Cannot activate device."
+ int_check_sum_only 83ee47245398adee79bd9c0a8bc57b821e92aba10f5f9ade8a5d1fae4d8c4302
+ $INTSETUP status $DEV_NAME | grep -q 'metadata device:' || fail
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+else
+ echo "[N/A]"
+fi
+
+echo -n "Bitmap mode parameters:"
+if [ -n "$DM_INTEGRITY_BITMAP" ] ; then
+ add_device
+ $INTSETUP format -q $DEV --integrity-bitmap-mode $DEV2 || fail "Cannot format device."
+ $INTSETUP open $DEV --integrity-bitmap-mode --bitmap-sectors-per-bit 65536 --bitmap-flush-time 5000 $DEV_NAME || fail "Cannot activate device."
+ $INTSETUP status $DEV_NAME | grep -q 'bitmap 512-byte sectors per bit: 65536' || fail
+ $INTSETUP status $DEV_NAME | grep -q 'bitmap flush interval: 5000 ms' || fail
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+ echo "Bitmap error detection tests:"
+ int_error_detection B crc32c 0 4 512
+ int_error_detection B crc32c 0 4 4096
+ int_error_detection B sha256 0 32 512
+ int_error_detection B sha256 0 32 4096
+ int_error_detection B hmac-sha256 0 32 512 $KEY_FILE 32
+ int_error_detection B hmac-sha256 0 32 4096 $KEY_FILE 32
+else
+ echo "[N/A]"
+fi
+
+echo -n "Big device:"
+add_device
+DEV_LOOP=$(losetup -f $DEV --show)
+if [ -n "$DEV_LOOP" ] ; then
+dmsetup create $DEV_NAME2 <<EOF
+0 16284 linear $DEV_LOOP 0
+16284 80000000000 zero
+EOF
+ [ ! -b /dev/mapper/$DEV_NAME2 ] && fail
+ $INTSETUP format -q -s 512 --no-wipe /dev/mapper/$DEV_NAME2
+ $INTSETUP open /dev/mapper/$DEV_NAME2 $DEV_NAME || fail
+ D_SIZE=$($INTSETUP dump /dev/mapper/$DEV_NAME2 | grep provided_data_sectors | sed -e 's/.*provided_data_sectors\ \+//g')
+ A_SIZE=$(blockdev --getsz /dev/mapper/$DEV_NAME)
+ # Compare strings (to avoid 64bit integers), not integers
+ [ -n "$A_SIZE" -a "$D_SIZE" != "$A_SIZE" ] && fail
+ echo "[OK]"
+else
+ echo "[N/A]"
+fi
+
+echo -n "Deferred removal of device:"
+add_device
+$INTSETUP format -q $DEV || fail "Cannot format device."
+$INTSETUP open $DEV $DEV_NAME || fail "Cannot activate device."
+dmsetup create $DEV_NAME2 --table "0 8 linear /dev/mapper/$DEV_NAME 0"
+[ ! -b /dev/mapper/$DEV_NAME2 ] && fail
+$INTSETUP close $DEV_NAME >/dev/null 2>&1 && fail
+$INTSETUP -q status $DEV_NAME >/dev/null 2>&1 || fail
+$INTSETUP close --deferred $DEV_NAME >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" || fail
+ $INTSETUP close --cancel-deferred $DEV_NAME >/dev/null 2>&1
+ dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" >/dev/null 2>&1 && fail
+ $INTSETUP close --deferred $DEV_NAME >/dev/null 2>&1
+ dmsetup remove $DEV_NAME2 || fail
+ $INTSETUP -q status $DEV_NAME >/dev/null 2>&1 && fail
+ echo "[OK]"
+else
+ dmsetup remove $DEV_NAME2 >/dev/null 2>&1
+ $INTSETUP close $DEV_NAME >/dev/null 2>&1
+ echo "[N/A]"
+fi
+
+echo -n "Fixed HMAC and legacy flags:"
+if [ -n "$DM_INTEGRITY_HMAC_FIX" ] ; then
+ add_device
+ # only data HMAC
+ ARGS="--integrity hmac-sha256 --integrity-key-file $KEY_FILE --integrity-key-size 32"
+ $INTSETUP format -q $DEV --integrity-legacy-hmac --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ # New version - must fail (no journal HMAC)
+ $INTSETUP format -q $DEV --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+
+ # data and journal HMAC
+ ARGS="$ARGS --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE2 --journal-integrity-key-size 32"
+ $INTSETUP format -q $DEV --integrity-legacy-hmac --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
+ $INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ # New fixed version
+ $INTSETUP format -q $DEV --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
+ $INTSETUP dump $DEV | grep "flags" | grep -q "fix_hmac" || fail "Flag for HMAC not set."
+ $INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS || fail "Cannot activate device."
+ $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ echo "[OK]"
+else
+ echo "[N/A]"
+fi
+
+# shrinking the mapping should also work on older kernels
+echo -n "[INTEGRITY BASIC RESIZE NOKEY]"
+add_device
+ARGS="--integrity crc32"
+
+echo -n "[FORMAT]"
+$INTSETUP format -q $DEV $ARGS || fail "Cannot format device."
+echo -n "[ACTIVATE]"
+$INTSETUP open -q $DEV $DEV_NAME $ARGS >/dev/null 2>&1 || fail "Cannot activate device."
+echo -n "[SHRINK]"
+$INTSETUP resize $DEV_NAME --device-size 1MiB >/dev/null 2>&1 || fail "Failed to resize the device to 1MiB."
+check_device_size $DEV_NAME $(( 1024*1024 / 512 )) "Shrinking device failed"
+dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detectied after resize."
+echo "[OK]"
+
+echo -n "[INTEGRITY BASIC RESIZE KEY]"
+add_device
+
+ARGS="--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
+
+echo -n "[FORMAT]"
+$INTSETUP format -q $DEV $ARGS || fail "Cannot format device."
+echo -n "[ACTIVATE]"
+$INTSETUP open -q $DEV $DEV_NAME $ARGS >/dev/null 2>&1 || fail "Cannot activate device."
+echo -n "[SHRINK]"
+$INTSETUP resize $DEV_NAME --device-size 1MiB >/dev/null 2>&1 || fail "Failed to resize the device to 1MiB."
+check_device_size $DEV_NAME $(( 1024*1024 / 512 )) "Shrinking device failed"
+dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detectied after resize."
+echo "[OK]"
+
+test_resize "[INTEGRITY RESIZE NOKEY]" 0 0 "--integrity crc32"
+test_resize "[INTEGRITY RESIZE NOKEY]" 0 1 "--integrity crc32"
+test_resize "[INTEGRITY RESIZE NOKEY DETACHED]" 1 0 "--integrity crc32"
+test_resize "[INTEGRITY RESIZE NOKEY DETACHED]" 1 1 "--integrity crc32"
+if [ -n "$DM_INTEGRITY_HMAC_FIX" ] ; then
+ test_resize "[INTEGRITY RESIZE KEY]" 0 0 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
+ test_resize "[INTEGRITY RESIZE KEY]" 0 1 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
+ test_resize "[INTEGRITY RESIZE KEY DETACHED]" 1 0 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
+ test_resize "[INTEGRITY RESIZE KEY DETACHED]" 1 1 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
+fi
+
+cleanup
diff --git a/tests/keyring-compat-test b/tests/keyring-compat-test
new file mode 100755
index 0000000..ea88c21
--- /dev/null
+++ b/tests/keyring-compat-test
@@ -0,0 +1,234 @@
+#!/bin/bash
+
+CIPHER_XTS_PLAIN="aes-xts-plain64"
+CIPHER_CBC_ESSIV="aes-cbc-essiv:sha256"
+CIPHER_CBC_TCW="serpent-cbc-tcw"
+# TODO: mode with LMK
+
+TEST_KEYRING_NAME="keyringtest_keyring"
+
+LOGON_KEY_16_OK="dmtst:lkey_16"
+LOGON_KEY_32_OK="dmtst:lkey_32"
+LOGON_KEY_64_OK="dmtst:lkey_64"
+
+HEXKEY_16="be21aa8c733229347bd4e681891e213d";
+HEXKEY_32="bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+HEXKEY_64="34f95b96abff946b64f1339ff8653cc77c38697c93b797a496f3786e86eed7781850d5112bbae17d209b8310a8f3a034f1cd297667bc0cd1438fad28d87ef6a1"
+
+DEVSIZEMB=16
+DEVSECTORS=$((DEVSIZEMB*1024*1024/512))
+NAME=testcryptdev
+CHKS_DMCRYPT=vk_in_dmcrypt.chk
+CHKS_KEYRING=vk_in_keyring.chk
+
+PWD="aaablabl"
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$NAME ] && dmsetup remove --retry $NAME
+
+ # unlink whole test keyring
+ [ -n "$TEST_KEYRING" ] && keyctl unlink $TEST_KEYRING "@u" >/dev/null
+
+ rmmod scsi_debug >/dev/null 2>&1
+
+ rm -f $CHKS_DMCRYPT $CHKS_KEYRING
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+# $1 hexbyte key
+# $2 type
+# $3 description
+# $4 keyring
+function load_key()
+{
+ local tmp="$1"
+ shift
+ echo -n "$tmp" | xxd -r -p | keyctl padd $@ >/dev/null
+}
+
+function dm_crypt_keyring_support()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+
+ # run the test with dm-crypt v1.15.0+ on purpose
+ # the fix is in dm-crypt v1.18.1+
+ [ $VER_MAJ -gt 1 ] && return 0
+ [ $VER_MAJ -lt 1 ] && return 1
+ [ $VER_MIN -ge 15 ]
+}
+
+function test_and_prepare_keyring() {
+ keyctl list "@s" > /dev/null || skip "Current session keyring is unreachable, test skipped"
+ TEST_KEYRING=$(keyctl newring $TEST_KEYRING_NAME "@u" 2> /dev/null)
+ test -n "$TEST_KEYRING" || skip "Failed to create keyring in user keyring"
+ keyctl search "@s" keyring "$TEST_KEYRING" > /dev/null 2>&1 || keyctl link "@u" "@s" > /dev/null 2>&1
+ load_key "$HEXKEY_16" user test_key "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
+}
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+add_device() {
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+ fi
+
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 2
+ DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+
+ DEV="/dev/$DEV"
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+command -v dmsetup >/dev/null || skip "Cannot find dmsetup, test skipped"
+command -v keyctl >/dev/null || skip "Cannot find keyctl, test skipped"
+command -v xxd >/dev/null || skip "Cannot find xxd, test skipped"
+command -v sha256sum >/dev/null || skip "Cannot find sha256sum, test skipped"
+modprobe dm-crypt >/dev/null 2>&1 || fail "dm-crypt failed to load"
+dm_crypt_keyring_support || skip "dm-crypt doesn't support kernel keyring, test skipped."
+
+test_and_prepare_keyring
+
+add_device dev_size_mb=$DEVSIZEMB
+
+dd if=/dev/urandom of=$DEV bs=1M count=$DEVSIZEMB oflag=direct > /dev/null 2>&1 || fail
+
+#test aes cipher with xts mode, plain IV
+echo -n "Testing $CIPHER_XTS_PLAIN..."
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN $HEXKEY_32 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
+dmsetup remove --retry $NAME || fail
+load_key "$HEXKEY_32" logon $LOGON_KEY_32_OK "$TEST_KEYRING" || fail "Cannot load 32 byte logon key type"
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN :32:logon:$LOGON_KEY_32_OK 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
+dmsetup remove --retry $NAME || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
+# same test using message
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN $HEXKEY_32 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
+dmsetup remove --retry $NAME || fail
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN $HEXKEY_32 0 $DEV 0" || fail
+dmsetup suspend $NAME || fail
+dmsetup message $NAME 0 key wipe || fail
+dmsetup message $NAME 0 "key set :32:logon:$LOGON_KEY_32_OK" || fail
+dmsetup resume $NAME || fail
+sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
+dmsetup remove --retry $NAME || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
+echo "OK"
+
+#test aes cipher, xts mode, essiv IV
+echo -n "Testing $CIPHER_CBC_ESSIV..."
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV $HEXKEY_16 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
+dmsetup remove --retry $NAME || fail
+load_key "$HEXKEY_16" logon $LOGON_KEY_16_OK "$TEST_KEYRING" || fail "Cannot load 16 byte logon key type"
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV :16:logon:$LOGON_KEY_16_OK 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
+dmsetup remove --retry $NAME || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
+# same test using message
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV $HEXKEY_16 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
+dmsetup remove --retry $NAME || fail
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV $HEXKEY_16 0 $DEV 0" || fail
+dmsetup suspend $NAME || fail
+dmsetup message $NAME 0 key wipe || fail
+dmsetup message $NAME 0 "key set :16:logon:$LOGON_KEY_16_OK" || fail
+dmsetup resume $NAME || fail
+sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
+dmsetup remove --retry $NAME || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
+echo "OK"
+
+#test serpent cipher, cbc mode, tcw IV
+fips_mode || {
+echo -n "Testing $CIPHER_CBC_TCW..."
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
+dmsetup remove --retry $NAME || fail
+load_key "$HEXKEY_64" logon $LOGON_KEY_64_OK "$TEST_KEYRING" || fail "Cannot load 16 byte logon key type"
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW :64:logon:$LOGON_KEY_64_OK 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
+dmsetup remove --retry $NAME || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksum mismatch (corruption)"
+# same test using message
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
+sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
+dmsetup remove --retry $NAME || fail
+dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
+dmsetup suspend $NAME || fail
+dmsetup message $NAME 0 key wipe || fail
+dmsetup message $NAME 0 "key set :64:logon:$LOGON_KEY_64_OK" || fail
+dmsetup resume $NAME || fail
+sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
+dmsetup remove --retry $NAME || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
+echo "OK"
+}
+
+echo -n "Test LUKS2 key refresh..."
+echo $PWD | $CRYPTSETUP luksFormat --type luks2 --luks2-metadata-size 16k --luks2-keyslots-size 4064k --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --force-password $DEV || fail
+echo $PWD | $CRYPTSETUP open $DEV $NAME || fail
+$CRYPTSETUP status $NAME | grep -q -i "location:.*keyring" || skip "LUKS2 can't use keyring. Test skipped."
+dd if=/dev/mapper/$NAME bs=1M iflag=direct status=none | sha256sum > $CHKS_KEYRING || fail
+echo $PWD | $CRYPTSETUP refresh $NAME --disable-keyring || fail
+$CRYPTSETUP status $NAME | grep -q -i "location:.*keyring" && fail "Key is still in keyring"
+dd if=/dev/mapper/$NAME bs=1M iflag=direct status=none | sha256sum > $CHKS_DMCRYPT || fail
+diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksum mismatch (corruption)"
+echo "OK"
+
+remove_mapping
diff --git a/tests/keyring-test b/tests/keyring-test
new file mode 100755
index 0000000..38abcfb
--- /dev/null
+++ b/tests/keyring-test
@@ -0,0 +1,238 @@
+#!/bin/bash
+
+DEV_ZERO="dmtst-zero"
+DEV_CRYPT="dmtst-crypt"
+
+CIPHER="aes-xts-plain64"
+
+TEST_KEYRING_NAME="keyringtest_keyring"
+
+USER_KEY_32_OK="dmtst:ukey_32_ok"
+USER_KEY_32_WRONG="dmtst:ukey_32_wrong_size"
+
+LOGON_KEY_32_OK="dmtst:lkey_32_ok"
+LOGON_KEY_32_WRONG="dmtst:lkey_32_wrong_size"
+
+PAYLOAD_32="bb21158c733229347bd4e681891e213d"
+PAYLOAD_31="bb21158c733229347bd4e681891e213"
+
+HEXKEY_32="bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
+HEXKEY_32_BAD="bb21158c733229347bd4e68189XXXX3d94c685be6a5b84818afe7a78a6de7a1a"
+HEXKEY_31="bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a"
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_CRYPT ] && dmsetup remove --retry $DEV_CRYPT
+ [ -b /dev/mapper/$DEV_ZERO ] && dmsetup remove --retry $DEV_ZERO
+
+ # unlink whole test keyring
+ [ -n "$TEST_KEYRING" ] && keyctl unlink $TEST_KEYRING "@u" >/dev/null
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+# $1 type
+# $2 description
+# $3 payload
+# $4 keyring
+function load_key()
+{
+ keyctl add $@ >/dev/null
+}
+
+function dm_crypt_keyring_support()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+
+ [ $VER_MAJ -gt 1 ] && return 0
+ [ $VER_MAJ -lt 1 ] && return 1
+ [ $VER_MIN -ge 15 ]
+}
+
+function test_and_prepare_keyring() {
+ keyctl list "@s" > /dev/null || skip "Current session keyring is unreachable, test skipped"
+ TEST_KEYRING=$(keyctl newring $TEST_KEYRING_NAME "@u" 2> /dev/null)
+ test -n "$TEST_KEYRING" || skip "Failed to create keyring in user keyring"
+ keyctl search "@s" keyring "$TEST_KEYRING" > /dev/null 2>&1 || keyctl link "@u" "@s" > /dev/null 2>&1
+ load_key user test_key test_data "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+command -v dmsetup >/dev/null || skip "Cannot find dmsetup, test skipped"
+command -v keyctl >/dev/null || skip "Cannot find keyctl, test skipped"
+modprobe dm-crypt >/dev/null 2>&1 || fail "dm-crypt failed to load"
+dm_crypt_keyring_support || skip "dm-crypt doesn't support kernel keyring, test skipped."
+
+test_and_prepare_keyring
+
+load_key logon $LOGON_KEY_32_OK $PAYLOAD_32 "$TEST_KEYRING" || fail "Cannot load 32 byte logon key type"
+load_key user $USER_KEY_32_OK $PAYLOAD_32 "$TEST_KEYRING" || fail "Cannot load 32 byte user key type"
+load_key logon $LOGON_KEY_32_WRONG $PAYLOAD_31 "$TEST_KEYRING" || fail "Cannot load 31 byte logon key type"
+load_key user $USER_KEY_32_WRONG $PAYLOAD_31 "$TEST_KEYRING" || fail "Cannot load 31 byte user key type"
+
+dmsetup create $DEV_ZERO --table "0 100 zero" || fail
+
+echo "[1] Valid keyring keys"
+
+# load logon type kernel key
+KEY=":32:logon:$LOGON_KEY_32_OK"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" || fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER $KEY 0" || fail
+dmsetup remove --retry $DEV_CRYPT || fail
+
+# load user type kernel key
+KEY=":32:user:$USER_KEY_32_OK"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" || fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER $KEY 0" || fail
+dmsetup remove --retry $DEV_CRYPT || fail
+
+# load logon type kernel key...
+KEY=":32:logon:$LOGON_KEY_32_OK"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" || fail
+dmsetup suspend $DEV_CRYPT || fail
+dmsetup message $DEV_CRYPT 0 "key wipe" || fail
+# ...replace the key with hexkey...
+dmsetup message $DEV_CRYPT 0 "key set $HEXKEY_32" || fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER $HEXKEY_32 0" || fail
+dmsetup resume $DEV_CRYPT || fail
+dmsetup suspend $DEV_CRYPT || fail
+# ...and replace it again with user type kernel key...
+dmsetup message $DEV_CRYPT 0 "key set :32:user:$USER_KEY_32_OK" || fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER :32:user:$USER_KEY_32_OK 0" || fail
+dmsetup message $DEV_CRYPT 0 "key set $HEXKEY_32" || fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER $HEXKEY_32 0" || fail
+dmsetup resume $DEV_CRYPT || fail
+dmsetup remove --retry $DEV_CRYPT || fail
+
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $HEXKEY_32 0 /dev/mapper/$DEV_ZERO 0" || fail
+dmsetup suspend $DEV_CRYPT || fail
+dmsetup message $DEV_CRYPT 0 "key wipe" || fail
+dmsetup message $DEV_CRYPT 0 "key set :32:user:$USER_KEY_32_OK" || fail
+dmsetup resume $DEV_CRYPT || fail
+dmsetup suspend $DEV_CRYPT || fail
+dmsetup message $DEV_CRYPT 0 "key set :32:logon:$LOGON_KEY_32_OK" || fail
+dmsetup resume $DEV_CRYPT || fail
+dmsetup remove --retry $DEV_CRYPT || fail
+
+echo "[2] message ioctl"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $HEXKEY_32 0 /dev/mapper/$DEV_ZERO 0" || fail
+dmsetup suspend $DEV_CRYPT || fail
+dmsetup message $DEV_CRYPT 0 "key set :32:logon:$LOGON_KEY_32_WRONG" 2> /dev/null && fail
+# old key should be intact and valid
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER $HEXKEY_32 0" || fail
+dmsetup resume $DEV_CRYPT || fail
+dmsetup suspend $DEV_CRYPT || fail
+# now the key gets destroyed by invalid input
+dmsetup message $DEV_CRYPT 0 "key set $HEXKEY_32_BAD" 2> /dev/null && fail
+dmsetup resume $DEV_CRYPT 2> /dev/null && fail
+# hmm... see the output. don't like it
+# dmsetup table --showkeys $DEV_CRYPT
+
+dmsetup message $DEV_CRYPT 0 "key set :32:user:$USER_KEY_32_OK" || fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER :32:user:$USER_KEY_32_OK 0" || fail
+dmsetup message $DEV_CRYPT 0 "key set :31:logon:$LOGON_KEY_32_OK" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set ::::" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :0:logon:$LOGON_KEY_32_OK" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :32" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :32:" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :32:logon" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :32:logo" 2> /dev/null && fail
+dmsetup message $DEV_CRYPT 0 "key set :32:logon:" 2> /dev/null && fail
+dmsetup table --showkeys $DEV_CRYPT | grep -q "crypt $CIPHER :32:user:$USER_KEY_32_OK 0" || fail
+dmsetup message $DEV_CRYPT 0 "key set :32:user:$USER_KEY_32_OK" || fail
+dmsetup resume $DEV_CRYPT || fail
+dmsetup remove --retry $DEV_CRYPT || fail
+
+echo "[3] bOrked keys"
+# declare the key having 32 bytes but load key which has in fact 31 bytes only
+KEY=":32:logon:$LOGON_KEY_32_WRONG"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" 2> /dev/null && fail "dm-crypt accepted wrong key size"
+
+# declare the key having 31 bytes (incompatible with cipher) and load key with 32 bytes in real
+KEY=":31:logon:$LOGON_KEY_32_WRONG"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" 2> /dev/null && fail "dm-crypt accepted wrong key size"
+
+# declare the key being user type but try to load logon one
+KEY=":32:user:$LOGON_KEY_32"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" 2> /dev/null && fail "dm-crypt accepted key description for invalid key type"
+
+# now the other way
+KEY=":32:logon:$USER_KEY_32"
+dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $KEY 0 /dev/mapper/$DEV_ZERO 0" 2> /dev/null && fail "dm-crypt accepted key description for invalid key type"
+
+BORKED_KEYS=":\ 32:logon:$LOGON_KEY_32_OK
+: 32:logon:$LOGON_KEY_32_OK
+:+32:logon:$LOGON_KEY_32_OK
+:-32:logon:$LOGON_KEY_32_OK
+:32 :logon:$LOGON_KEY_32_OK
+:32\ :logon:$LOGON_KEY_32_OK
+:32_:logon:$LOGON_KEY_32_OK
+:32+:logon:$LOGON_KEY_32_OK
+:30+2:logon:$LOGON_KEY_32_OK
+:32+0:logon:$LOGON_KEY_32_OK
+:32: logon:$LOGON_KEY_32_OK
+:32:\ logon:$LOGON_KEY_32_OK
+:32:logonA:$LOGON_KEY_32_OK
+:32:logo:$LOGON_KEY_32_OK
+:32:llogon:$LOGON_KEY_32_OK
+:32xlogon:$LOGON_KEY_32_OK
+:32logon:$LOGON_KEY_32_OK
+:32:logonx$LOGON_KEY_32_OK
+:32:logon$LOGON_KEY_32_OK
+: 32:user:$USER_KEY_32_OK
+:\ 32:user:$USER_KEY_32_OK
+:+32:user:$USER_KEY_32_OK
+:-32:user:$USER_KEY_32_OK
+:32 :user:$USER_KEY_32_OK
+:32\ :user:$USER_KEY_32_OK
+:32_:user:$USER_KEY_32_OK
+:32+:user:$USER_KEY_32_OK
+:30+2:user:$USER_KEY_32_OK
+:32+0:user:$USER_KEY_32_OK
+:32: user:$USER_KEY_32_OK
+:32:\ user:$USER_KEY_32_OK
+:32:userA:$USER_KEY_32_OK
+:32:use:$USER_KEY_32_OK
+:32:uuser:$USER_KEY_32_OK
+:32xuser:$USER_KEY_32_OK
+:32user:$USER_KEY_32_OK
+:32:userx$USER_KEY_32_OK
+:32:user$USER_KEY_32_OK
+:32:userlogon:$USER_KEY_32_OK
+:32:userlogon:$LOGON_KEY_32_OK
+:32:logonuser:$USER_KEY_32_OK
+:32:logonuser:$LOGON_KEY_32_OK
+:32:logon:user:$USER_KEY_32_OK
+:32:logon:user:$LOGON_KEY_32_OK
+:32:user:logon:$USER_KEY_32_OK
+:32:user:logon:$LOGON_KEY_32_OK"
+
+# TODO: add tests with whitespace in key description (not possible with current libdevmapper)
+
+IFS="
+"
+
+for key in $BORKED_KEYS; do
+ dmsetup create $DEV_CRYPT --table "0 100 crypt $CIPHER $key 0 /dev/mapper/$DEV_ZERO 0" 2> /dev/null && fail "dm-crypt accepted seriously borked key string"
+done
+
+remove_mapping
diff --git a/tests/loopaes-test b/tests/loopaes-test
new file mode 100755
index 0000000..fdb4cd3
--- /dev/null
+++ b/tests/loopaes-test
@@ -0,0 +1,192 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+# try to validate using loop-AES losetup/kernel if available
+LOSETUP_AES=/losetup-aes.old
+
+LOOP_DD_PARAM="bs=1k count=10000"
+DEV_NAME=dummy
+IMG=loopaes.img
+KEYv1=key_v1
+KEYv2=key_v2
+KEYv3=key_v3
+LOOPDEV=$(losetup -f 2>/dev/null)
+
+function dmremove() { # device
+ udevadm settle >/dev/null 2>&1
+ dmsetup remove --retry $1 >/dev/null 2>&1
+}
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME2 ] && dmremove $DEV_NAME2
+ [ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
+ losetup -d $LOOPDEV >/dev/null 2>&1
+ rm -f $IMG $KEYv1 $KEYv2 $KEYv3 >/dev/null 2>&1
+}
+
+function fail()
+{
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ remove_mapping
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function prepare()
+{
+ remove_mapping
+ dd if=/dev/zero of=$IMG $LOOP_DD_PARAM >/dev/null 2>&1
+ sync
+ losetup $LOOPDEV $IMG
+
+ # Prepare raw key: v1 - one key, v2 - 64 keys, v3 - 64 + one IV
+ if [ ! -e $KEYv3 ]; then
+ head -c 3705 /dev/urandom | uuencode -m - | head -n 66 | tail -n 65 >$KEYv3
+ head -n 1 $KEYv3 > $KEYv1
+ head -n 64 $KEYv3 > $KEYv2
+ fi
+ [ -n "$1" ] && echo -n "$1 "
+}
+
+function check_exists()
+{
+ [ -b /dev/mapper/$DEV_NAME ] || fail
+}
+
+function get_offset_params() # $offset
+{
+ offset=$1
+ if [ "${offset:0:1}" = "@" ] ; then
+ echo "-o $((${offset:1} / 512)) -p 0"
+ else
+ echo "-o $((offset / 512))"
+ fi
+}
+
+function get_expsum() # $offset
+{
+ case $1 in
+ 0)
+ echo "31e00e0e4c233c89051cd748122fde2c98db0121ca09ba93a3820817ea037bc5"
+ ;;
+ @8192 | 8192)
+ echo "bfd94392d1dd8f5d477251d21b3c736e177a4945cd4937847fc7bace82996aed"
+ ;;
+ @8388608 | 8388608)
+ echo "33838fe36928a929bd7971bed7e82bd426c88193fcd692c2e6f1b9c9bfecd4d6"
+ ;;
+ *) fail
+ ;;
+ esac
+}
+
+function check_sum() # $key $keysize $offset [stdin|keyfile]
+{
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ EXPSUM=$(get_expsum $3)
+ if [ "$4" == "stdin" ] ; then
+ cat $1 | $CRYPTSETUP loopaesOpen $LOOPDEV $DEV_NAME -s $2 --key-file - $(get_offset_params $3) >/dev/null 2>&1
+ else
+ $CRYPTSETUP loopaesOpen $LOOPDEV $DEV_NAME -s $2 --key-file $1 $(get_offset_params $3) >/dev/null 2>&1
+ fi
+ ret=$?
+ VSUM=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
+ if [ $ret -eq 0 -a "$VSUM" = "$EXPSUM" ] ; then
+ echo -n "[$4:OK]"
+ else
+ echo "[$4:FAIL]"
+ [ "$VSUM" != "$EXPSUM" ] && echo " Expecting $EXPSUM got $VSUM."
+ fail
+ fi
+}
+
+function check_sum_losetup() # $key $alg
+{
+ [ ! -x $LOSETUP_AES ] && echo && return
+
+ echo -n " Verification using loop-AES: "
+
+ losetup -d $LOOPDEV >/dev/null 2>&1
+ cat $1 | $LOSETUP_AES -p 0 -e $2 -o $3 $LOOPDEV $IMG
+ ret=$?
+ VSUM=$(sha256sum $LOOPDEV | cut -d' ' -f 1)
+ if [ $ret -eq 0 -a "$VSUM" = "$EXPSUM" ] ; then
+ echo "[OK]"
+ else
+ echo "[FAIL]"
+ [ "$VSUM" != "$EXPSUM" ] && echo " Expecting $EXPSUM got $VSUM (loop-AES)."
+ fail
+ fi
+ losetup -d $LOOPDEV >/dev/null 2>&1
+}
+
+function check_version()
+{
+ VER_STR=$(dmsetup version | grep Driver)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PATCH=$(echo $VER_STR | cut -f 3 -d.)
+
+ test $VER_MIN -lt 19 && return 1
+ test $VER_MIN -eq 19 -a $VER_PATCH -ge 6 && return 1 # RHEL
+ return 0
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ -z "$LOOPDEV" ] && skip "Cannot find free loop device, test skipped."
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+command -v uuencode >/dev/null || skip "WARNING: test require uuencode binary, test skipped."
+check_version || skip "Probably old kernel, test skipped."
+
+# loop-AES tests
+KEY_SIZES="128 256"
+KEY_FILES="$KEYv1 $KEYv2 $KEYv3"
+DEV_OFFSET="0 8192 @8192 8388608 @8388608"
+
+for key_size in $KEY_SIZES ; do
+ for key in $KEY_FILES ; do
+ for offset in $DEV_OFFSET ; do
+ prepare "Open loop-AES $key / AES-$key_size / offset $offset"
+ $CRYPTSETUP loopaesOpen $LOOPDEV $DEV_NAME \
+ -s $key_size --key-file $key $(get_offset_params $offset) \
+ 2>/dev/null
+ [ $? -ne 0 ] && echo "[SKIPPED]" && continue
+ check_exists
+ # Fill device with zeroes and reopen it
+ dd if=/dev/zero of=/dev/mapper/$DEV_NAME $LOOP_DD_PARAM >/dev/null 2>&1
+ check_sum $key $key_size $offset keyfile
+ check_sum $key $key_size $offset stdin
+ $CRYPTSETUP loopaesClose $DEV_NAME || fail
+ check_sum_losetup $key AES$key_size $offset
+ done
+ done
+done
+
+remove_mapping
+exit 0
diff --git a/tests/luks1-compat-test b/tests/luks1-compat-test
new file mode 100755
index 0000000..18afcd5
--- /dev/null
+++ b/tests/luks1-compat-test
@@ -0,0 +1,124 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+TST_DIR=luks1-images
+MAP=luks1tst
+KEYFILE=keyfile1
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+[ -z "$srcdir" ] && srcdir="."
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
+ rm -rf $TST_DIR
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo " [FAILED]"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function remove_imgs()
+{
+ echo "WARNING: $1 not available, not testing some images."
+ rm $(ls $TST_DIR/*$1*.img)
+}
+
+function test_one()
+{
+ $CRYPTSETUP benchmark -c "$1" -s "$2" | grep -v "#" || remove_imgs $1
+}
+
+function test_required()
+{
+ echo "REQUIRED KDF TEST"
+ $CRYPTSETUP benchmark -h whirlpool | grep "N/A" && remove_imgs whirlpool
+
+ echo "REQUIRED CIPHERS TEST"
+ echo "# Algorithm | Key | Encryption | Decryption"
+
+ test_one aes-xts 256
+ test_one twofish-xts 256
+ test_one serpent-xts 256
+ test_one aes-cbc 256
+ test_one aes-lrw 256
+}
+
+export LANG=C
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+command -v blkid >/dev/null || skip "blkid tool required, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+[ ! -d $TST_DIR ] && tar xJf $srcdir/luks1-images.tar.xz --no-same-owner
+test_required
+
+echo "PASSPHRASE CHECK"
+for file in $(ls $TST_DIR/luks1_*) ; do
+ echo -n " $file"
+ $CRYPTSETUP luksOpen -d $TST_DIR/$KEYFILE $file --test-passphrase 2>/dev/null
+ ret=$?
+ # ignore missing whirlpool (pwd failed is exit code 2)
+ [ $ret -eq 1 ] && (echo $file | grep -q -e "whirlpool") && echo " [N/A]" && continue
+ # ignore flawed whirlpool (pwd failed is exit code 2)
+ [ $ret -eq 2 ] && (echo $file | grep -q -e "whirlpool") && \
+ ($CRYPTSETUP luksDump $file --debug | grep -q -e "flawed whirlpool") && \
+ echo " [IGNORED (flawed Whirlpool library)]" && continue
+ [ $ret -ne 0 ] && fail
+ echo " [OK]"
+done
+
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run activation part of test, test skipped."
+ remove_mapping
+ exit 0
+fi
+
+echo "ACTIVATION FS UUID CHECK"
+for file in $(ls $TST_DIR/luks1_*) ; do
+ echo -n " $file"
+ $CRYPTSETUP luksOpen -d $TST_DIR/$KEYFILE $file $MAP 2>/dev/null
+ ret=$?
+ # ignore missing whirlpool (pwd failed is exit code 2)
+ [ $ret -eq 1 ] && (echo $file | grep -q -e "whirlpool") && echo " [N/A]" && continue
+ # ignore flawed whirlpool (pwd failed is exit code 2)
+ [ $ret -eq 2 ] && (echo $file | grep -q -e "whirlpool") && \
+ ($CRYPTSETUP luksDump $file --debug | grep -q -e "flawed whirlpool") && \
+ echo " [IGNORED (flawed Whirlpool library)]" && continue
+ [ $ret -ne 0 ] && fail
+ $CRYPTSETUP status $MAP >/dev/null || fail
+ $CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
+ UUID=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
+ $CRYPTSETUP remove $MAP || fail
+ [ "$UUID" != "DEAD-BABE" ] && fail "UUID check failed."
+ echo " [OK]"
+done
+
+remove_mapping
+exit 0
diff --git a/tests/luks1-images.tar.xz b/tests/luks1-images.tar.xz
new file mode 100644
index 0000000..dd099c6
--- /dev/null
+++ b/tests/luks1-images.tar.xz
Binary files differ
diff --git a/tests/luks2-integrity-test b/tests/luks2-integrity-test
new file mode 100755
index 0000000..a8082f8
--- /dev/null
+++ b/tests/luks2-integrity-test
@@ -0,0 +1,203 @@
+#!/bin/bash
+#
+# Test cryptsetup/authenticated encryption compatibility.
+#
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+DEV_NAME=dmi_test
+DEV=mode-test.img
+HEADER_IMG=mode-test-detached.img
+PWD1=nHjJHjI23JK
+KEY_FILE=key.img
+FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+dmremove() { # device
+ udevadm settle >/dev/null 2>&1
+ dmsetup remove $1 >/dev/null 2>&1
+}
+
+cleanup() {
+ [ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
+ [ -b /dev/mapper/"$DEV_NAME"_dif ] && dmremove "$DEV_NAME"_dif
+ rm -f $DEV $KEY_FILE $HEADER_IMG >/dev/null 2>&1
+}
+
+fail()
+{
+ echo
+ [ -n "$1" ] && echo "FAIL: $1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+add_device() {
+ cleanup
+ dd if=/dev/urandom of=$KEY_FILE bs=1 count=512 >/dev/null 2>&1
+ dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
+ sync
+}
+
+status_check() # name value [detached]
+{
+ if [ -n "$3" ]; then
+ PARAMS="$DEV_NAME --header $HEADER_IMG"
+ else
+ PARAMS="$DEV_NAME"
+ fi
+ X=$($CRYPTSETUP status $PARAMS | grep -m1 "$1" | sed -e 's/.*:[ \t]\+//' | cut -d' ' -f1)
+ if [ "$X" != "$2" ] ; then
+ echo "[status FAIL]"
+ echo " Expecting $1:$2 got \"$X\"."
+ fail
+ fi
+}
+
+dump_check() # name value
+{
+ X=$($CRYPTSETUP luksDump $DEV | grep -m1 "$1" | sed -e 's/.*:[ \t]\+//' | cut -d' ' -f1)
+ if [ "$X" != "$2" ] ; then
+ echo "[dump FAIL]"
+ echo " Expecting $1:$2 got \"$X\"."
+ fail
+ fi
+}
+
+int_check_sum() # alg checksum
+{
+ VSUM=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
+ if [ "$VSUM" = "$2" ] ; then
+ echo -n "[CHECKSUM]"
+ else
+ echo "[FAIL]"
+ echo " Expecting $2 got $VSUM."
+ fail
+ fi
+}
+
+int_error_detection() # alg int sector_size
+{
+ echo -n "[DETECT_CORRUPTION]"
+ echo -n "XXXXX" | dd of=$DEV bs=1M seek=28 count=1 conv=notrunc >/dev/null 2>&1 || fail "Cannot write to device."
+ $CRYPTSETUP open -d $KEY_FILE $DEV $DEV_NAME || fail "Cannot activate device."
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null >/dev/null 2>&1 && fail "Error detection failed."
+ $CRYPTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+}
+
+intformat() # alg integrity integrity_out key_size int_key_size sector_size csum [test_hdr]
+{
+ echo -n "[$1:$2:$4:$6]"
+ echo -n "[FORMAT]"
+ $CRYPTSETUP luksFormat --type luks2 -q -c $1 --integrity $2 --sector-size $6 -s $4 \
+ $FAST_PBKDF_OPT -d $KEY_FILE $DEV --offset 8192 --integrity-legacy-padding >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "[N/A]"
+ return
+ fi
+ dump_check "cipher" $1
+ dump_check "sector" $6
+ dump_check "integrity" $3
+ dump_check "Key:" $(($4 + $5))
+ echo -n "[ACTIVATE]"
+ $CRYPTSETUP open -d $KEY_FILE $DEV $DEV_NAME || fail "Cannot activate device."
+ status_check "cipher" $1
+ status_check "sector size" $6
+ status_check "integrity:" $3
+ status_check "keysize:" $(($4 + $5))
+ [ $5 -gt 0 ] && status_check "integrity keysize:" $5
+ int_check_sum $1 $7
+ echo -n "[REMOVE]"
+ $CRYPTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+
+ # check detached header activation
+ if [ -n "$8" ] ; then
+ echo -n "[DETACHED_HDR]"
+ $CRYPTSETUP luksHeaderBackup -q --header-backup-file $HEADER_IMG $DEV || fail
+ wipefs -a $DEV >/dev/null 2>&1 || fail
+ $CRYPTSETUP open --header $HEADER_IMG -d $KEY_FILE $DEV $DEV_NAME || fail "Cannot activate device."
+ status_check "cipher" $1 1
+ status_check "sector size" $6 1
+ status_check "integrity:" $3 1
+ status_check "keysize:" $(($4 + $5)) 1
+ [ $5 -gt 0 ] && status_check "integrity keysize:" $5 1
+ int_check_sum $1 $7
+ $CRYPTSETUP close $DEV_NAME || fail "Cannot deactivate device."
+ $CRYPTSETUP luksHeaderRestore -q --header-backup-file $HEADER_IMG $DEV || fail
+ rm -f $HEADER_IMG
+ fi
+
+ int_error_detection
+ echo "[OK]"
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+modprobe dm-integrity >/dev/null 2>&1
+dmsetup targets | grep integrity >/dev/null 2>&1 || skip "Cannot find dm-integrity target, test skipped."
+command -v wipefs >/dev/null || skip "Cannot find wipefs, test skipped."
+
+add_device
+
+intformat aes-cbc-essiv:sha256 hmac-sha256 hmac\(sha256\) 128 256 512 ee501705a084cd0ab6f4a28014bcf62b8bfa3434de00b82743c50b3abf06232c 1
+intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 256 256 512 ee501705a084cd0ab6f4a28014bcf62b8bfa3434de00b82743c50b3abf06232c 1
+intformat aes-xts-random hmac-sha256 hmac\(sha256\) 256 256 512 492c2d1cc9e222a850c399bfef4ed5a86bf5afc59e54f0f0c7ba8e2a64548323
+intformat aes-cbc-essiv:sha256 hmac-sha256 hmac\(sha256\) 256 256 512 ee501705a084cd0ab6f4a28014bcf62b8bfa3434de00b82743c50b3abf06232c
+intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 512 256 512 ee501705a084cd0ab6f4a28014bcf62b8bfa3434de00b82743c50b3abf06232c
+intformat aes-xts-random hmac-sha256 hmac\(sha256\) 512 256 512 492c2d1cc9e222a850c399bfef4ed5a86bf5afc59e54f0f0c7ba8e2a64548323
+intformat aes-cbc-essiv:sha256 hmac-sha256 hmac\(sha256\) 128 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 256 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+intformat aes-xts-random hmac-sha256 hmac\(sha256\) 256 256 4096 8c0463f5ac09613674bdf40b0ff6f985edbc3de04e51fdc688873cb333ef3cda
+intformat aes-cbc-essiv:sha256 hmac-sha256 hmac\(sha256\) 256 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+intformat aes-xts-plain64 hmac-sha256 hmac\(sha256\) 512 256 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+intformat aes-xts-random hmac-sha256 hmac\(sha256\) 512 256 4096 8c0463f5ac09613674bdf40b0ff6f985edbc3de04e51fdc688873cb333ef3cda
+
+intformat aes-cbc-essiv:sha256 hmac-sha512 hmac\(sha512\) 256 512 4096 9873d864fccb866521e79c9f0f75ad0c578d6bd7620399bbf4779e698c6e92fd
+intformat aes-xts-essiv:sha256 hmac-sha512 hmac\(sha512\) 512 512 4096 9873d864fccb866521e79c9f0f75ad0c578d6bd7620399bbf4779e698c6e92fd
+intformat aes-xts-plain64 hmac-sha512 hmac\(sha512\) 512 512 4096 9873d864fccb866521e79c9f0f75ad0c578d6bd7620399bbf4779e698c6e92fd
+intformat aes-xts-random hmac-sha512 hmac\(sha512\) 512 512 4096 621f6c03f7361c2bf8f10059ae822339223f8471c750b0cf8584fba7134bd4a2
+
+intformat aes-xts-plain64 hmac-sha1 hmac\(sha1\) 512 160 4096 7370c66a92708fb71b186931468be6aa9b26f4f88373b00b1c57360b9ee1304e
+intformat aes-xts-random hmac-sha1 hmac\(sha1\) 512 160 4096 8c0463f5ac09613674bdf40b0ff6f985edbc3de04e51fdc688873cb333ef3cda
+
+intformat aes-gcm-random aead aead 128 0 512 5f6f3f6be03c74d9aaaeaf40dd310c99a20e2786045f78a1fc6a0b189d231f57
+intformat aes-gcm-random aead aead 128 0 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+intformat aes-gcm-random aead aead 256 0 512 5f6f3f6be03c74d9aaaeaf40dd310c99a20e2786045f78a1fc6a0b189d231f57
+intformat aes-gcm-random aead aead 256 0 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+
+intformat aes-ccm-random aead aead 152 0 512 288e5e9bc5be6c0bd2a74abbb72c7944da83198b5e3041dcf159e7ae250dafa8
+intformat aes-ccm-random aead aead 152 0 4096 7370c66a92708fb71b186931468be6aa9b26f4f88373b00b1c57360b9ee1304e
+intformat aes-ccm-random aead aead 280 0 512 288e5e9bc5be6c0bd2a74abbb72c7944da83198b5e3041dcf159e7ae250dafa8
+intformat aes-ccm-random aead aead 280 0 4096 7370c66a92708fb71b186931468be6aa9b26f4f88373b00b1c57360b9ee1304e
+
+intformat chacha20-plain64 poly1305 poly1305 256 0 512 3f82eae753ff52a689ddc559c691bbdff838361bbe9a3ce8c7212e16e51b5dbe
+intformat chacha20-random poly1305 poly1305 256 0 512 5f6f3f6be03c74d9aaaeaf40dd310c99a20e2786045f78a1fc6a0b189d231f57
+intformat chacha20-plain64 poly1305 poly1305 256 0 4096 7370c66a92708fb71b186931468be6aa9b26f4f88373b00b1c57360b9ee1304e
+intformat chacha20-random poly1305 poly1305 256 0 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b
+
+intformat aegis128-random aead aead 128 0 512 ee501705a084cd0ab6f4a28014bcf62b8bfa3434de00b82743c50b3abf06232c 1
+intformat aegis128-random aead aead 128 0 4096 358d6beceddf593aff6b22c31684e0df9c226330aff5812e060950215217d21b 1
+
+cleanup
diff --git a/tests/luks2-reencryption-mangle-test b/tests/luks2-reencryption-mangle-test
new file mode 100755
index 0000000..5aa62e4
--- /dev/null
+++ b/tests/luks2-reencryption-mangle-test
@@ -0,0 +1,548 @@
+#!/bin/bash
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+CRYPTSETUP_RAW=$CRYPTSETUP
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+IMG=reenc-mangle-data
+IMG_HDR=$IMG.hdr
+IMG_HDR_BCP=$IMG_HDR.bcp
+IMG_JSON=$IMG.json
+KEY1=key1
+DEV_NAME=reenc3492834
+
+FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+CS_PWPARAMS="--disable-keyring --key-file $KEY1"
+CS_PARAMS="-q --disable-locks $CS_PWPARAMS"
+JSON_MSIZE=16384
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ rm -f $IMG $IMG_HDR $IMG_HDR_BCP $IMG_JSON $KEY1 >/dev/null 2>&1
+}
+
+function fail()
+{
+ local frame=0
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function bin_check()
+{
+ command -v $1 >/dev/null || skip "WARNING: test require $1 binary, test skipped."
+}
+
+function img_json_save()
+{
+ local _hdr=$IMG
+ [ -z "$1" ] || _hdr="$1"
+ # FIXME: why --json-file cannot be used?
+ $CRYPTSETUP luksDump --dump-json-metadata $_hdr | jq -c -M . | tr -d '\n' >$IMG_JSON
+}
+
+function img_json_dump()
+{
+ img_json_save
+ jq . $IMG_JSON
+}
+
+function img_hash_save()
+{
+ IMG_HASH=$(sha256sum $IMG | cut -d' ' -f 1)
+}
+
+function img_hash_unchanged()
+{
+ local IMG_HASH2=$(sha256sum $IMG | cut -d' ' -f 1)
+ [ "$IMG_HASH" != "$IMG_HASH2" ] && fail "Image changed!"
+}
+
+function img_prepare_raw() # $1 options
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ truncate -s 32M $IMG || fail
+ $CRYPTSETUP luksFormat $FAST_PBKDF2 $CS_PARAMS --luks2-metadata-size $JSON_MSIZE $IMG $1 || fail
+}
+
+function img_prepare() # $1 options
+{
+ img_prepare_raw
+ $CRYPTSETUP reencrypt $IMG $CS_PARAMS -q --init-only --resilience none $1 >/dev/null 2>&1
+ [ $? -ne 0 ] && skip "Reencryption unsupported, test skipped."
+ img_json_save
+ img_hash_save
+}
+
+function _dd()
+{
+ dd $@ status=none conv=notrunc bs=1
+}
+
+# header mangle functions
+function img_update_json()
+{
+ local _hdr="$IMG"
+ local LUKS2_BIN1_OFFSET=448
+ local LUKS2_BIN2_OFFSET=$((LUKS2_BIN1_OFFSET + $JSON_MSIZE))
+ local LUKS2_JSON_SIZE=$(($JSON_MSIZE - 4096))
+
+ # if present jq script, mangle JSON
+ if [ -n "$1" ]; then
+ local JSON=$(cat $IMG_JSON)
+ echo $JSON | jq -M -c "$1" >$IMG_JSON || fail
+ local JSON=$(cat $IMG_JSON)
+ echo $JSON | tr -d '\n' >$IMG_JSON || fail
+ fi
+
+ [ -z "$2" ] || _hdr="$2"
+
+ # wipe JSON areas
+ _dd if=/dev/zero of=$_hdr count=$LUKS2_JSON_SIZE seek=4096
+ _dd if=/dev/zero of=$_hdr count=$LUKS2_JSON_SIZE seek=$(($JSON_MSIZE + 4096))
+
+ # write JSON data
+ _dd if=$IMG_JSON of=$_hdr count=$LUKS2_JSON_SIZE seek=4096
+ _dd if=$IMG_JSON of=$_hdr count=$LUKS2_JSON_SIZE seek=$(($JSON_MSIZE + 4096))
+
+ # erase sha256 checksums
+ _dd if=/dev/zero of=$_hdr count=64 seek=$LUKS2_BIN1_OFFSET
+ _dd if=/dev/zero of=$_hdr count=64 seek=$LUKS2_BIN2_OFFSET
+
+ # calculate sha256 and write chexksums
+ local SUM1_HEX=$(_dd if=$_hdr count=$JSON_MSIZE | sha256sum | cut -d ' ' -f 1)
+ echo $SUM1_HEX | xxd -r -p | _dd of=$_hdr seek=$LUKS2_BIN1_OFFSET count=64 || fail
+
+ local SUM2_HEX=$(_dd if=$_hdr skip=$JSON_MSIZE count=$JSON_MSIZE | sha256sum | cut -d ' ' -f 1)
+ echo $SUM2_HEX | xxd -r -p | _dd of=$_hdr seek=$LUKS2_BIN2_OFFSET count=64 || fail
+
+ img_hash_save
+}
+
+function img_check_ok()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fi
+
+ $CRYPTSETUP repair $IMG $CS_PARAMS || fail
+}
+
+function img_check_dump_ok()
+{
+ $CRYPTSETUP luksDump $IMG >/dev/null || fail
+ img_check_fail
+}
+
+function img_check_fail()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail
+ fi
+
+ $CRYPTSETUP repair $IMG $CS_PARAMS 2>/dev/null && fail
+ img_hash_unchanged
+}
+
+function img_run_reenc_ok()
+{
+ $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS -q --disable-locks --force-offline-reencrypt --resilience none || fail
+}
+
+function img_run_reenc_ok_data_shift()
+{
+ $CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS -q --disable-locks --force-offline-reencrypt || fail
+}
+
+function img_run_reenc_fail()
+{
+$CRYPTSETUP_RAW reencrypt $IMG $CS_PWPARAMS --force-offline-reencrypt --disable-locks -q 2>/dev/null && fail "Reencryption passed (should have failed)."
+img_hash_unchanged
+}
+
+function img_check_fail_repair()
+{
+ if [ $(id -u) == 0 ]; then
+ $CRYPTSETUP open $CS_PWPARAMS $IMG $DEV_NAME 2>/dev/null && fail
+ fi
+
+ img_run_reenc_fail
+
+ # repair metadata
+ $CRYPTSETUP repair $IMG $CS_PARAMS || fail
+
+ img_check_ok
+}
+
+function img_check_fail_repair_ok()
+{
+ img_check_fail_repair
+ img_run_reenc_ok
+}
+
+function img_check_fail_repair_ok_data_shift()
+{
+ img_check_fail_repair
+ img_run_reenc_ok_data_shift
+}
+
+function valgrind_setup()
+{
+ bin_check valgrind
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+ CRYPTSETUP=valgrind_run
+ CRYPTSETUP_RAW="./valg.sh ${CRYPTSETUP_VALGRIND}"
+}
+
+function valgrind_run()
+{
+ export INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}"
+ $CRYPTSETUP_RAW "$@"
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+
+bin_check jq
+bin_check sha256sum
+bin_check xxd
+
+export LANG=C
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+echo "[1] Reencryption with old flag is rejected"
+img_prepare
+img_update_json '.config.requirements.mandatory = ["online-reencryptx"]'
+img_check_fail
+img_update_json '.config.requirements.mandatory = ["online-reencrypt-v2"]'
+img_check_ok
+img_run_reenc_ok
+img_check_ok
+
+# Simulate old reencryption with no digest (repairable)
+img_prepare
+img_update_json 'del(.digests."2") | .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail_repair_ok
+
+# Simulate future version of reencrypt flag (should pass luksDump)
+img_prepare
+img_update_json '.config.requirements.mandatory = ["online-reencrypt-v999"]'
+img_check_dump_ok
+
+# Multiple reencrypt requirement flags makes LUKS2 invalid
+img_prepare
+img_update_json '.config.requirements.mandatory = .config.requirements.mandatory + ["online-reencrypt-v999"]'
+img_check_fail
+
+img_prepare
+img_update_json '.config.requirements.mandatory = .config.requirements.mandatory + ["online-reencrypt"]'
+img_check_fail
+
+# just regular unknown requirement
+img_prepare
+img_update_json '.config.requirements.mandatory = .config.requirements.mandatory + ["online-reencrypt-v3X"]'
+img_check_dump_ok
+
+# This must fail for new releases
+echo "[2] Old reencryption in-progress (journal)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".area.type = "journal" |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : .keyslots."2".area.size} +
+ {"flags" : ["in-reencryption"]}),
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail_repair_ok
+
+echo "[3] Old reencryption in-progress (checksum)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096 |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : .keyslots."2".area.size} +
+ {"flags" : ["in-reencryption"]}),
+ "1" : (.segments."0" +
+ {"offset": ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail_repair_ok
+
+# Note: older tools cannot create this from commandline
+echo "[4] Old decryption in-progress (journal)"
+img_prepare
+img_update_json '
+ del(.digests."1") |
+ del(.digests."2") |
+ del(.keyslots."1") |
+ .keyslots."2".mode = "decrypt" |
+ .keyslots."2".area.type = "journal" |
+ .segments = {
+ "0" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : .keyslots."2".area.size,
+ "flags" : ["in-reencryption"]
+ },
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : "dynamic",
+ "flags" : ["backup-final"]
+ }
+ } |
+ .digests."0".segments = ["1","2"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail_repair_ok
+
+echo "[5] Old decryption in-progress (checksum)"
+img_prepare
+img_update_json '
+ del(.digests."1") |
+ del(.digests."2") |
+ del(.keyslots."1") |
+ .keyslots."2".mode = "decrypt" |
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096 |
+ .segments = {
+ "0" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : .keyslots."2".area.size,
+ "flags" : ["in-reencryption"]
+ },
+ "1" : (.segments."0" +
+ {"offset" : ((.segments."0".offset|tonumber) +
+ (.keyslots."2".area.size|tonumber))|tostring}),
+ "2" : .segments."1",
+ "3" : {
+ "type" : "linear",
+ "offset" : .segments."0".offset,
+ "size" : "dynamic",
+ "flags" : ["backup-final"]
+ }
+ } |
+ .digests."0".segments = ["1","2"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail_repair_ok
+
+# Note - offset is set to work with the old version (with a datashift bug)
+echo "[6] Old reencryption in-progress (datashift)"
+img_prepare
+img_update_json '
+ del(.digests."2") |
+ .keyslots."2".direction = "backward" |
+ .keyslots."2".area.type = "datashift" |
+ .keyslots."2".area.size = "4096" |
+ .keyslots."2".area.shift_size = ((1 * 1024 * 1024)|tostring) |
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : ((13 * 1024 * 1024)|tostring)}),
+ "1" : (.segments."0" +
+ {"offset" : ((30 * 1024 * 1024)|tostring)}),
+ "2" : .segments."1",
+ "3" : (.segments."2" +
+ {"offset" : ((17 * 1024 * 1024)|tostring)}),
+ } |
+ .digests."0".segments = ["0","2"] |
+ .digests."1".segments = ["1","3"] |
+ .config.requirements.mandatory = ["online-reencrypt"]'
+img_check_fail_repair_ok_data_shift
+
+#
+# NEW metadata (with reenc digest)
+#
+echo "[7] Reencryption with various mangled metadata"
+
+# Normal situation
+img_prepare
+img_run_reenc_ok
+img_check_ok
+
+# The same in various steps.
+# Repair must validate not only metadata, but also reencryption digest.
+img_prepare
+img_update_json 'del(.digests."2")'
+img_check_fail_repair_ok
+
+img_prepare '--reduce-device-size 2M'
+img_update_json '.keyslots."2".area.shift_size = ((.keyslots."2".area.shift_size|tonumber / 2)|tostring)'
+img_check_fail
+
+img_prepare
+img_update_json '
+ .keyslots."2".area.type = "checksum" |
+ .keyslots."2".area.hash = "sha256" |
+ .keyslots."2".area.sector_size = 4096'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".area.type = "journal"'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".mode = "decrypt"'
+img_check_fail
+
+img_prepare
+img_update_json '.keyslots."2".direction = "backward"'
+img_check_fail
+
+# key_size must be 1
+img_prepare
+img_update_json '.keyslots."2".key_size = 16'
+img_check_fail
+
+# Mangling segments
+img_prepare
+img_update_json 'del(.segments."1")'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."0".encryption = "aes-cbc-null"'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."1".encryption = "aes-cbc-null"'
+img_check_fail
+
+img_prepare
+img_update_json '.segments."2".encryption = "aes-cbc-null"'
+img_check_fail
+
+# Mangling digests
+img_prepare
+img_update_json '
+ .digests."2" = .digests."0" |
+ .digests."2".keyslots = ["2"] |
+ .digests."2".segments = []'
+img_check_fail
+
+img_prepare
+img_update_json '.digests."2".iterations = 1111'
+img_check_fail
+
+# Simulate correct progress
+img_prepare
+img_update_json '
+ .segments = {
+ "0" : (.segments."0" +
+ {"size" : ((1 * 1024 * 1024)|tostring)}),
+ "1" : (.segments."0" +
+ {"offset" : ((17 * 1024 * 1024)|tostring)}),
+ "2" : .segments."1",
+ "3" : .segments."2"
+ } |
+ .digests."0".segments = ["1","2"] |
+ .digests."1".segments = ["0","3"]'
+img_check_ok
+
+# Mangling keyslots
+
+# Set reencrypt slot to non-ignore priority
+# This should be benign, just avoid noisy messages
+img_prepare
+img_update_json 'del(.keyslots."2".priority)'
+img_check_ok
+
+# Flags
+
+# Remove mandatory reenc flag, but keep reenc metadata
+img_prepare
+img_update_json '.config.requirements.mandatory = []'
+img_check_fail
+
+# Unknown segment flag, should be ignored
+img_prepare
+img_update_json '.segments."0".flags = ["dead-parrot"]'
+img_check_ok
+
+echo "[8] Reencryption with AEAD is not supported"
+img_prepare_raw
+img_json_save
+img_update_json '
+ .segments."0".integrity = {
+ "type" : "hmac(sha256)",
+ "journal_encryption": "none",
+ "journal_integrity": "none"
+ }'
+$CRYPTSETUP reencrypt $IMG $CS_PARAMS >/dev/null 2>&1 && fail
+
+echo "[9] Decryption with datashift"
+img_prepare_raw
+$CRYPTSETUP reencrypt $CS_PARAMS --decrypt --init-only --force-offline-reencrypt --resilience checksum --header $IMG_HDR $IMG || fail
+cp $IMG_HDR $IMG_HDR_BCP
+
+# change hash
+img_json_save $IMG_HDR_BCP
+img_update_json '.keyslots."1".area.hash = "sha12345"' $IMG_HDR
+$CRYPTSETUP reencrypt --header $IMG_HDR $IMG $CS_PARAMS --force-offline-reencrypt 2>/dev/null && fail
+
+# change sector size
+img_json_save $IMG_HDR_BCP
+img_update_json '.keyslots."1".area.sector_size = 1024' $IMG_HDR
+$CRYPTSETUP reencrypt --header $IMG_HDR $IMG $CS_PARAMS --force-offline-reencrypt 2>/dev/null && fail
+
+# replace with new resilience mode
+img_json_save $IMG_HDR_BCP
+img_update_json 'del(.keyslots."1".area.hash) |
+ del(.keyslots."1".sector_size) |
+ .keyslots."1".area.type = "datashift-journal"' $IMG_HDR
+$CRYPTSETUP reencrypt --header $IMG_HDR $IMG $CS_PARAMS --force-offline-reencrypt 2>/dev/null && fail
+
+# downgrade reencryption requirement
+img_json_save $IMG_HDR_BCP
+img_update_json '.config.requirements.mandatory = ["online-reencrypt-v2"]' $IMG_HDR
+$CRYPTSETUP reencrypt --header $IMG_HDR $IMG $CS_PARAMS --force-offline-reencrypt 2>/dev/null && fail
+
+# change datashift value
+img_json_save $IMG_HDR_BCP
+img_update_json '.keyslots."1".area.shift_size = (((.keyslots."1".area.shift_size | tonumber) - 4096) | tostring)' $IMG_HDR
+$CRYPTSETUP reencrypt --header $IMG_HDR $IMG $CS_PARAMS --force-offline-reencrypt 2>/dev/null && fail
+
+remove_mapping
+exit 0
diff --git a/tests/luks2-reencryption-test b/tests/luks2-reencryption-test
new file mode 100755
index 0000000..a647a8c
--- /dev/null
+++ b/tests/luks2-reencryption-test
@@ -0,0 +1,2207 @@
+#!/bin/bash
+
+#PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+FAST_PBKDF_ARGON="--pbkdf-force-iterations 4 --pbkdf-memory 32 --pbkdf-parallel 1"
+DEFAULT_ARGON="argon2i"
+
+DEV=""
+OVRDEV="123reenc321"
+DEVBIG="reenc2134"
+DEV_NAME=reenc9768
+DEV_NAME2=reenc97682
+IMG=reenc-data
+IMG_HDR=$IMG.hdr
+HEADER_LUKS2_PV=blkid-luks2-pv.img
+IMG_FS=xfs_512_block_size.img
+KEY1=key1
+VKEY1=vkey1
+PWD1="93R4P4pIqAH8"
+PWD2="1cND4319812f"
+PWD3="1-9Qu5Ejfnqv"
+DEV_LINK="reenc-test-link"
+
+FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+function dm_crypt_features()
+{
+ VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+ VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
+
+ [ $VER_MAJ -lt 1 ] && return
+ [ $VER_MAJ -gt 1 ] && {
+ DM_PERF_CPU=1
+ DM_SECTOR_SIZE=1
+ return
+ }
+
+ [ $VER_MIN -lt 14 ] && return
+ DM_PERF_CPU=1
+ if [ $VER_MIN -ge 17 ]; then
+ DM_SECTOR_SIZE=1
+ fi
+}
+
+function dm_delay_features()
+{
+ local _ver_str=$(dmsetup targets | grep delay | cut -f2 -dv)
+ [ -z "$_ver_str" ] && return 1
+ return 0
+}
+
+# $1 path to scsi debug bdev
+scsi_debug_teardown() {
+ local _tries=15;
+
+ while [ -b "$1" -a $_tries -gt 0 ]; do
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -b "$1" ]; then
+ sleep .1
+ _tries=$((_tries-1))
+ fi
+ done
+
+ test ! -b "$1" || rmmod scsi_debug >/dev/null 2>&1
+}
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME ] && {
+ dmsetup resume $DEV_NAME
+ dmsetup remove --retry $DEV_NAME
+ }
+ [ -b /dev/mapper/$DEV_NAME2 ] && {
+ dmsetup resume $DEV_NAME2
+ dmsetup remove --retry $DEV_NAME2
+ }
+ [ -b /dev/mapper/$DEV_NAME-overlay ] && {
+ dmsetup resume $DEV_NAME-overlay
+ dmsetup remove --retry $DEV_NAME-overlay
+ }
+ [ -b /dev/mapper/$DEV_NAME-hotzone-forward ] && {
+ dmsetup resume $DEV_NAME-hotzone-forward
+ dmsetup remove --retry $DEV_NAME-hotzone-forward
+ }
+ [ -b /dev/mapper/$DEV_NAME-hotzone-backward ] && {
+ dmsetup resume $DEV_NAME-hotzone-backward
+ dmsetup remove --retry $DEV_NAME-hotzone-backward
+ }
+ [ -b /dev/mapper/$OVRDEV ] && dmsetup remove --retry $OVRDEV 2>/dev/null
+ [ -b /dev/mapper/$OVRDEV-err ] && dmsetup remove --retry $OVRDEV-err 2>/dev/null
+ [ -n "$LOOPDEV" ] && losetup -d $LOOPDEV
+ unset LOOPDEV
+ rm -f $IMG $IMG_HDR $KEY1 $VKEY1 $DEVBIG $DEV_LINK $HEADER_LUKS2_PV $IMG_FS >/dev/null 2>&1
+ rmmod scsi_debug >/dev/null 2>&1
+ scsi_debug_teardown $DEV
+}
+
+function fail()
+{
+ local frame=0
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+function add_scsi_device() {
+ scsi_debug_teardown $DEV
+ if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+ fi
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 1
+ DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+function open_crypt() # $1 pwd, $2 hdr
+{
+ if [ -n "$2" ] ; then
+ echo "$1" | $CRYPTSETUP luksOpen $DEV $DEV_NAME --header $2 || fail
+ elif [ -n "$1" ] ; then
+ echo "$1" | $CRYPTSETUP luksOpen $DEV $DEV_NAME || fail
+ else
+ $CRYPTSETUP luksOpen -d $KEY1 $DEV $DEV_NAME || fail
+ fi
+}
+
+function wipe_dev_head() # $1 dev, $2 length (in MiBs)
+{
+ dd if=/dev/zero of=$1 bs=1M count=$2 conv=notrunc >/dev/null 2>&1
+}
+
+function wipe_dev() # $1 dev
+{
+ if [ -b $1 ] ; then
+ blkdiscard --zeroout $1 2>/dev/null || dd if=/dev/zero of=$1 bs=1M conv=notrunc >/dev/null 2>&1
+ if [ $# -gt 2 ]; then
+ dd if=/dev/urandom of=$1 bs=1M seek=$2 conv=notrunc >/dev/null 2>&1
+ fi
+ else
+ local size=$(stat --printf="%s" $1)
+ truncate -s 0 $1
+ if [ $# -gt 2 ]; then
+ local diff=$((size-$2*1024*1024))
+ echo "size: $size, diff: $diff"
+ truncate -s $diff $1
+ # wipe_dev_head $1 $((diff/(1024*1024)))
+ dd if=/dev/urandom of=$1 bs=1M seek=$2 size=$((diff/(1024*1024))) conv=notrunc >/dev/null 2>&1
+ else
+ truncate -s $size $1
+ fi
+ fi
+}
+
+function wipe() # $1 pass, $2 hdr
+{
+ open_crypt $1 $2
+ wipe_dev /dev/mapper/$DEV_NAME
+ udevadm settle >/dev/null 2>&1
+ $CRYPTSETUP luksClose $DEV_NAME || fail
+}
+
+function prepare() # $1 dev1_siz
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ if [ ! -e $VKEY1 ]; then
+ echo -n $'\x44\xc6\x74\x4f\x41\x4e\x50\xc0\x79\xc2\x2d\x5b\x5f\x68\x84\x17' >$VKEY1
+ echo -n $'\x9c\x03\xba\xbe\x4d\x0f\x9a\x75\xb3\x90\x70\x32\x0a\xf8\xae\xc4'>>$VKEY1
+ fi
+
+ add_scsi_device $@
+}
+
+function preparebig() # $1 dev1_siz
+{
+ remove_mapping
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+
+ truncate -s "$1"M $DEVBIG
+ LOOPDEV=$(losetup -f)
+ losetup -f $DEVBIG || fail
+ DEV=$LOOPDEV
+}
+
+function check_hash_dev() # $1 dev, $2 hash
+{
+ HASH=$(sha1sum $1 | cut -d' ' -f 1)
+ [ $HASH != "$2" ] && fail "HASH differs (expected: $2) (result $HASH)"
+}
+
+function check_hash() # $1 pwd, $2 hash, $3 hdr
+{
+ open_crypt $1 $3
+ check_hash_dev /dev/mapper/$DEV_NAME $2
+ $CRYPTSETUP remove $DEV_NAME || fail
+}
+
+function check_hash_dev_head() # $1 dev, $2 len, $3 hash
+{
+ local hash=$(dd if=$1 bs=512 count=$2 2>/dev/null | sha1sum | cut -d' ' -f1)
+ [ $hash != "$3" ] && fail "HASH differs (expected: $3) (result $hash)"
+}
+
+function check_hash_head() # $1 pwd, $2 len, $3 hash, $4 hdr
+{
+ open_crypt $1 $4
+ check_hash_dev_head /dev/mapper/$DEV_NAME $2 $3
+ $CRYPTSETUP remove $DEV_NAME || fail
+}
+
+function resize_file() # $1 dev, $2 shrink bytes
+{
+ local size=$(stat --printf="%s" $1)
+ truncate -s $(($size + $2)) $1
+ losetup -c $LOOPDEV
+}
+
+function error_writes() { # $1 dmdev, $2 data dev, $3 offset, $4 size
+ local _dev_size=$(blockdev --getsz /dev/mapper/$1)
+ local _offset=$(($3+$4))
+ local _size=$((_dev_size-_offset))
+ local _err=$1-err
+ local _table=
+ dmsetup create $_err --table "0 $_dev_size error" || fail
+
+ if [ $3 -ne 0 ]; then
+ _table="0 $3 linear $2 0\n"
+ fi
+
+ _table=$_table"$3 $4 delay $2 $3 0 /dev/mapper/$_err $3 0"
+
+ if [ $_size -ne 0 ]; then
+ _table="$_table\n$_offset $_size linear $2 $_offset"
+ fi
+
+ echo -e "$_table" | dmsetup load $1 || fail
+ dmsetup resume $1 || fail
+ blockdev --setra 0 /dev/mapper/$1
+ blockdev --setra 0 /dev/mapper/$_err
+}
+
+function fix_writes() { # $1 dmdev, $2 data dev
+ local _dev_size=$(blockdev --getsz /dev/mapper/$1)
+ dmsetup load $1 --table "0 $_dev_size linear $2 0" || fail
+ dmsetup resume $1 || fail
+ dmsetup remove --retry $1-err 2>/dev/null || fail
+}
+
+function prepare_linear_dev() {
+ local _sizemb=$1
+ shift
+
+ if [ "$_sizemb" -gt 32 ]; then
+ preparebig $_sizemb
+ else
+ prepare dev_size_mb=$_sizemb $@
+ fi
+
+ dmsetup create $OVRDEV --table "0 $((_sizemb*1024*2)) linear $DEV 0" || fail
+
+ OLD_DEV=$DEV
+ DEV=/dev/mapper/$OVRDEV
+}
+
+function get_error_offsets() # $1 devsize, $2 minimal offset, $3 sector_size [512 if omitted], $4 max offset
+{
+ local _devsize=$(($1*1024*2))
+ local _sector_size=${3:-512}
+ local _max_offset=${4:-$_devsize}
+ _sector_size=$((_sector_size/512))
+
+ # 8 sectors minimal size (4096)
+ ERRLENGTH=$((($RANDOM%56)+8))
+ ERRLENGTH=$(($ERRLENGTH-($ERRLENGTH%$_sector_size)))
+
+ ERROFFSET=$(($2+((2*$RANDOM)%($_max_offset-$2-$ERRLENGTH))))
+ ERROFFSET=$(($ERROFFSET-($ERROFFSET%$_sector_size)))
+}
+
+function reencrypt_recover() { # $1 sector size, $2 resilience, $3 digest, [$4 header]
+ echo -n "resilience mode: $2 ..."
+ local _hdr=""
+ test -z "$4" || _hdr="--header $4"
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 --force-offline-reencrypt -q $FAST_PBKDF_ARGON >/dev/null 2>&1 && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP -q repair $DEV $_hdr || fail
+
+ check_hash $PWD1 $3 $4
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV $_hdr --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $3 $4
+
+ echo "[OK]"
+}
+
+function reencrypt_recover_online() { # $1 sector size, $2 resilience, $3 digest, [$4 header]
+ echo -n "resilience mode: $2 ..."
+ local _hdr=""
+ test -z "$4" || _hdr="--header $4"
+
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --hotzone-size 1M --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON >/dev/null 2>&1 && fail
+ $CRYPTSETUP status $DEV_NAME $_hdr | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery during activation
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+
+ $CRYPTSETUP luksDump ${4:-$DEV} | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME $_hdr | grep -q "reencryption: in-progress" || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME $_hdr --resilience $2 --resume-only -q || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ fi
+
+ $CRYPTSETUP close $DEV_NAME || fail
+ echo "[OK]"
+}
+
+function encrypt_recover() { # $1 sector size, $2 reduce size, $3 digest, $4 device size in sectors, $5 origin digest
+ wipe_dev $DEV
+ check_hash_dev $DEV $5
+
+ echo -n "resilience mode: datashift ..."
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only >/dev/null 2>&1 || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q >/dev/null 2>&1 && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP -q repair $DEV || fail
+
+ $CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ check_hash $PWD1 $3
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --sector-size $1 -q $FAST_PBKDF_ARGON || fail
+ fi
+
+ check_hash_head $PWD1 $4 $3
+
+ echo "[OK]"
+}
+
+function encrypt_recover_online() { # $1 sector size, $2 reduce size, $3 digest, $4 device size in sectors, $5 origin digest
+ wipe_dev $DEV
+ check_hash_dev $DEV $5
+
+ echo -n "resilience mode: datashift ..."
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only > /dev/null || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q >/dev/null 2>&1 && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery in activation
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+
+ $CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ echo $PWD1 | $CRYPTSETUP reencrypt --resume-only --active-name $DEV_NAME -q || fail
+ fi
+
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash_head $PWD1 $4 $3
+
+ echo "[OK]"
+}
+
+function encrypt_recover_detached() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ wipe_dev $DEV
+ check_hash_dev $DEV $3
+
+ echo -n "resilience mode: $2 ..."
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --hotzone-size 1M --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP repair $DEV --header $4 || fail
+
+ check_hash $PWD1 $3 $4
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $3 $4
+
+ [ -f $4 ] && rm -f $4
+
+ echo "[OK]"
+}
+
+function encrypt_recover_detached_online() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ wipe_dev $DEV
+ check_hash_dev $DEV $3
+
+ echo -n "resilience mode: $2 ..."
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --hotzone-size 1M --header $4 --resilience $2 --sector-size $1 -q $FAST_PBKDF_ARGON --init-only || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV --header $4 --hotzone-size 1M 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+
+ $CRYPTSETUP luksDump $4 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME --resume-only --header $4 --resilience $2 -q || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ fi
+
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ [ -f $4 ] && rm -f $4
+
+ echo "[OK]"
+}
+
+function decrypt_recover_detached() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size $1 --header $4 $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $4
+ check_hash $PWD1 $3 $4
+
+ echo -n "resilience mode: $2 ..."
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --hotzone-size 1M --header $4 --resilience $2 -q 2>/dev/null && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP repair $DEV --header $4 || fail
+
+ $CRYPTSETUP luksDump $4 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ check_hash $PWD1 $3 $4
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --resume-only --header $4 --resilience $2 -q || fail
+ fi
+
+ check_hash_dev $DEV $3
+
+ [ -f $4 ] && rm -f $4
+
+ echo "[OK]"
+}
+
+function decrypt_recover_detached_online() { # $1 sector size, $2 resilience, $3 digest, $4 hdr
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size $1 --header $4 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+ wipe_dev /dev/mapper/$DEV_NAME
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+
+ echo -n "resilience mode: $2 ..."
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --hotzone-size 1M --header $4 --resilience $2 -q 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery during activation
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $4 $DEV_NAME || fail
+
+ $CRYPTSETUP luksDump $4 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ $CRYPTSETUP status $DEV_NAME --header $4 | grep -q "reencryption: in-progress" || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $3
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $4 --resilience $2 -q || fail
+ fi
+
+ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+ check_hash_dev $DEV $3
+
+ [ -f $4 ] && rm -f $4
+
+ echo "[OK]"
+}
+
+function decrypt_recover() { # $1 hash, $2 hdr, $3 dev size, $4 resilience, $5 hotzone size
+ local _res=""
+ local _maxhz=""
+ test -z "$4" || _res="--resilience $4"
+ test -z "$5" || _maxhz="--hotzone-size $5"
+ echo -n "[${4:-default}]"
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --header $2 --init-only $_maxhz >/dev/null || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $2 -q $_res >/dev/null 2>&1 && fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ echo $PWD1 | $CRYPTSETUP -q repair $DEV --header $2 || fail
+
+ $CRYPTSETUP luksDump $2 | grep -q "online-reencrypt"
+ if [ $? -eq 0 ]; then
+ check_hash $PWD1 $1 $2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $2 $_res -q $FAST_PBKDF_ARGON || fail
+ fi
+
+ check_hash_dev_head $DEV $3 $1
+
+ [ -f $2 ] && rm -f $2
+
+ echo -n "[OK]"
+}
+
+function decrypt_recover_online() { # $1 hash, $2 hdr, $3 dev size
+ local _res=""
+ local _maxhz=""
+ test -z "$4" || _res="--resilience $4"
+ test -z "$5" || _maxhz="--hotzone-size $5"
+ echo -n "[${4:-default}]"
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --header $2 $_maxhz --init-only >/dev/null 2>&1 || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $2 -q $_res >/dev/null 2>&1 && fail
+ $CRYPTSETUP status $DEV_NAME --header $2 | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery during activation
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $2 $DEV_NAME || fail
+
+ check_hash_dev /dev/mapper/$DEV_NAME $1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $2 -q || fail
+
+ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+ check_hash_dev_head $DEV $3 $1
+
+ [ -f $2 ] && rm -f $2
+
+ echo -n "[OK]"
+}
+
+function decrypt_recover_online_moved() { # $1 hash, $2 hdr, $3 dev size
+ local _res=""
+ local _maxhz=""
+ test -z "$4" || _res="--resilience $4"
+ test -z "$5" || _maxhz="--hotzone-size $5"
+ echo -n "[${4:-default}]"
+
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --decrypt --header $2 $_maxhz $_res --init-only >/dev/null 2>&1 || fail
+
+ error_writes $OVRDEV $OLD_DEV $ERROFFSET $ERRLENGTH
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV --header $2 -q $_res >/dev/null 2>&1 && fail
+ $CRYPTSETUP status $DEV_NAME --header $2 | grep -q "reencryption: in-progress" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ fix_writes $OVRDEV $OLD_DEV
+
+ # recovery but activation fails due to last segment recovery makes it plaintext device
+ echo $PWD1 | $CRYPTSETUP open $DEV --header $2 $DEV_NAME 2>/dev/null && fail
+
+ $CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+ check_hash_dev_head $DEV $3 $1
+
+ [ -f $2 ] && rm -f $2
+
+ echo -n "[OK]"
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr (optional)
+function reencrypt_offline_fixed_size() {
+ local _esz=$(($1>>9))
+ local _hdr=""
+ # round-up fixed size to megabytes
+ local _mbs=$((($2>>11)+1))
+ test -z "$7" || _hdr="--header $7"
+
+ if [ -z "$7" ]; then
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --offset 16384 $FAST_PBKDF_ARGON $DEV || fail
+ else
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $7 $FAST_PBKDF_ARGON $DEV || fail
+ fi
+ echo $PWD1 | $CRYPTSETUP open $_hdr $DEV $DEV_NAME || fail
+ wipe_dev_head /dev/mapper/$DEV_NAME $_mbs
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ # reencrypt with fixed device size
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --device-size $2s --resilience $4 --force-offline-reencrypt || fail
+
+ check_hash_head $PWD1 $2 $3 $7
+ wipe $PWD1 $7
+
+ # try to reencrypt device size + 1 encryption sector size
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --init-only --force-offline-reencrypt || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $(($5+_esz))s --resilience $4 2>/dev/null && fail
+ check_hash $PWD1 $6 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $(($2+_esz-1))s --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP luksDump ${7:-$DEV} | grep -q "2: crypt" || fail
+ $CRYPTSETUP luksDump ${7:-$DEV} | grep -q "3: crypt" && fail
+ check_hash $PWD1 $6 $7
+ fi
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr
+function encrypt_offline_fixed_size() {
+ local _esz=$(($1>>9))
+
+ # reencrypt with fixed device size
+ wipe_dev $DEV
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 --device-size $2s --resilience $4 || fail
+ check_hash_head $PWD1 $2 $3 $7
+ [ -f $7 ] && rm -f $7
+
+ # try to reencrypt device size + 1 encryption sector size
+ wipe_dev $DEV
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --device-size $(($5+_esz))s --resilience $4 2>/dev/null && fail
+ check_hash $PWD1 $6 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ [ -f $7 ] && rm -f $7
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV --header $7 --device-size $(($2+_esz-1))s --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP luksDump $7 | grep -q "2: crypt" || fail
+ $CRYPTSETUP luksDump $7 | grep -q "3: crypt" && fail
+ check_hash $PWD1 $6 $7
+ fi
+
+ [ -f $7 ] && rm -f $7
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr
+function decrypt_offline_fixed_size() {
+ local _esz=$(($1>>9))
+
+ # decrypt with fixed device size
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 || fail
+ wipe $PWD1 $7
+ echo $PWD1 | $CRYPTSETUP reencrypt --decrypt -q $DEV --header $7 --device-size $2s --resilience $4 || fail
+
+ dmsetup load $OVRDEV --table "0 $2 linear $OLD_DEV 0" || fail
+ dmsetup resume $OVRDEV || fail
+ check_hash_dev $DEV $3
+ dmsetup load $OVRDEV --table "0 $5 linear $OLD_DEV 0" || fail
+ dmsetup resume $OVRDEV || fail
+
+ # try to decrypt device size + 1 encryption sector size
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -q $FAST_PBKDF_ARGON $DEV --header $7 --sector-size $1 || fail
+ wipe $PWD1 $7
+ echo $PWD1 | $CRYPTSETUP reencrypt --decrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV --header $7 --device-size $(($5+_esz))s --resilience $4 2>/dev/null && fail
+ check_hash $PWD1 $6 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV --header $7 --device-size $(($2+_esz-1))s --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP luksDump $7 | grep -q "2: linear\|2: crypt" || fail
+ $CRYPTSETUP luksDump $7 | grep -q "3: crypt\|3: linear" && fail
+ check_hash $PWD1 $6 $7
+ fi
+}
+
+# sector size (bytes)
+# reenc dev size (sectors)
+# reenc dev digest
+# resilience
+# orig size
+# orig size digest
+# hdr (optional)
+function reencrypt_online_fixed_size() {
+ local _esz=$(($1>>9))
+ local _hdr=""
+ test -z "$7" || _hdr="--header $7"
+
+ if [ -z "$_hdr" ]; then
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 --offset 16384 $FAST_PBKDF_ARGON $DEV || fail
+ else
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 $_hdr $FAST_PBKDF_ARGON $DEV || fail
+ fi
+ wipe $PWD1 $7
+
+ # reencrypt with fixed device size
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP resize $DEV_NAME $_hdr --size $2 || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --resilience $4 || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "$2 sectors" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash_head $PWD1 $2 $3 $7
+ wipe $PWD1 $7
+
+ # active device != requested reencryption size
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP resize $DEV_NAME $_hdr --size $2 || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $(($2-_esz))s --resilience $4 2>/dev/null && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --device-size $2s --resilience $4 || fail
+ $CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "$2 sectors" || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash_head $PWD1 $2 $3 $7
+
+ # misaligned reencryption size
+ if [ $_esz -gt 1 ]; then
+ if [ -z "$_hdr" ]; then
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 --offset 16384 $FAST_PBKDF_ARGON $DEV || fail
+ else
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --sector-size 512 --type luks2 $_hdr $FAST_PBKDF_ARGON $DEV || fail
+ fi
+ wipe $PWD1 $7
+ check_hash $PWD1 $6 $7
+
+ echo $PWD1 | $CRYPTSETUP open $DEV $_hdr $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP resize $DEV_NAME $_hdr --size $(($2+_esz-1)) || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --sector-size $1 --init-only || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV $_hdr --resilience $4 2>/dev/null && fail
+ $CRYPTSETUP close $DEV_NAME || fail
+ check_hash $PWD1 $6 $7
+ fi
+
+ [ -n "$7" -a -f "$7" ] && rm -f $7
+}
+
+function setup_luks2_env() {
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c aes-xts-plain64 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ HAVE_KEYRING=$($CRYPTSETUP status $DEV_NAME | grep "key location: keyring")
+ if [ -n "$HAVE_KEYRING" ]; then
+ HAVE_KEYRING=1
+ else
+ HAVE_KEYRING=0
+ fi
+ DEF_XTS_KEY=$($CRYPTSETUP status $DEV_NAME | grep "keysize:" | sed 's/\( keysize: \)\([0-9]\+\)\(.*\)/\2/')
+ [ -n "$DEF_XTS_KEY" ] || fail "Failed to parse xts mode key size."
+ $CRYPTSETUP close $DEV_NAME || fail
+}
+
+function check_blkid() {
+ bin_check blkid
+ xz -dkf $HEADER_LUKS2_PV.xz
+ if ! $($CRYPTSETUP --version | grep -q "BLKID"); then
+ HAVE_BLKID=0
+ elif $(blkid -p -n crypto_LUKS $HEADER_LUKS2_PV >/dev/null 2>&1); then
+ HAVE_BLKID=1
+ xz -dkf $IMG_FS.xz
+ blkid $IMG_FS | grep -q BLOCK_SIZE && BLKID_BLOCK_SIZE_SUPPORT=1
+ else
+ HAVE_BLKID=0
+ fi
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function bin_check()
+{
+ command -v $1 >/dev/null || skip "WARNING: test require $1 binary, test skipped."
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+fips_mode && skip "This test cannot be run in FIPS mode."
+modprobe --dry-run scsi_debug >/dev/null 2>&1 || skip "This kernel seems to not support proper scsi_debug module, test skipped."
+modprobe dm-crypt >/dev/null 2>&1 || fail "dm-crypt failed to load"
+modprobe dm-delay > /dev/null 2>&1
+dm_crypt_features
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ TEST_SECTORS="512 4096"
+else
+ TEST_SECTORS="512"
+fi
+
+modinfo scsi_debug -p | grep -q opt_xferlen_exp && OPT_XFERLEN_EXP="opt_xferlen_exp=6"
+
+export LANG=C
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+# REENCRYPTION tests
+
+# 28 MiBs of zeros (32MiBs - 4MiB LUKS2 header)
+HASH1=4da90c0638bd7d29ce3d0ace3df5ee99706c23da
+# 1 MiB of zeros
+HASH2=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
+# 256 MiBs of zeros
+HASH3=7b91dbdc56c5781edf6c8847b4aa6965566c5c75
+# 64 MiBs of zeroes
+HASH4=44fac4bedde4df04b9572ac665d3ac2c5cd00c7d
+# 56 MiBs of zeroes
+HASH5=bcd8ce9b30a43b2dacdf479493c93e167ef60946
+# 43 MiBs of zeroes
+HASH6=2cf8a5f40a2ab5373c5425d6071da480f1ce08e8
+# 31 MiBs of zeroes
+HASH7=7ed56dd14d2841cf169fe503d097be04192666bd
+# 60 MiBs of zeroes
+HASH8=233ba936226a3ac499e67babaebd0d4aafb9761a
+# 240 MiBs of zeroes (256MiBs - 16MiBs default LUKS2 header size)
+HASH9=045eebed703cce308e049deb019b877f0445862f
+# 16 MiBs of zeroes
+HASH10=3b4417fc421cee30a9ad0fd9319220a8dae32da2
+
+prepare dev_size_mb=32
+setup_luks2_env
+
+# Check that we can use other ciphers than AES in userspace backend.
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c twofish-xts-plain64 $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON 2>/dev/null || skip "Cannot use Twofish cipher, test skipped"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c serpent-xts-plain64 $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON 2>/dev/null || skip "Cannot use Serpent cipher, test skipped."
+wipe_dev $DEV
+
+echo "[1] Reencryption"
+echo -n "[512 sector]"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON 2>&1 | tail -1 | grep -q "not supported" && skip " No reenryption support, test skipped."
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+# simple test --active-name can consume absolute path to mapping
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -c aes-xts-plain64 --init-only $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name /dev/mapper/$DEV_NAME --resilience none -q || fail
+XTS_KEY=$($CRYPTSETUP status $DEV_NAME | grep "keysize:" | sed 's/\( keysize: \)\([0-9]\+\)\(.*\)/\2/')
+[ "$XTS_KEY" -eq "$DEF_XTS_KEY" ] || fail "xts mode has wrong key size after reencryption ($XTS_KEY != expected $DEF_XTS_KEY)"
+echo $PWD1 | $CRYPTSETUP close $DEV_NAME || fail
+echo -n "[OK][4096 sector]"
+prepare sector_size=4096 dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON --sector-size 4096 || fail
+ check_hash $PWD1 $HASH1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal --sector-size 2048 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON --sector-size 1024 || fail
+ check_hash $PWD1 $HASH1
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum --sector-size 512 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH1
+fi
+echo -n "[OK][4096/512 sector]"
+prepare sector_size=512 physblk_exp=3 dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+echo "[OK]"
+
+# reencrypt minimal device size (FIXME: change data device size to single encryption sector size)
+# temporary small device size is default luks2 hdr size + 1MiB
+echo -n "[small device reencryption]"
+prepare dev_size_mb=5
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH2
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON --sector-size 4096 --force-offline-reencrypt || fail
+ check_hash $PWD1 $HASH2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 256 -c twofish-cbc-essiv:sha256 --resilience journal --sector-size 2048 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience none $FAST_PBKDF_ARGON --sector-size 1024 || fail
+ check_hash $PWD1 $HASH2
+ echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -s 128 -c aes-cbc-essiv:sha256 --resilience checksum --sector-size 512 $FAST_PBKDF_ARGON || fail
+ check_hash $PWD1 $HASH2
+fi
+echo "[OK]"
+
+echo "[2] Encryption with data shift"
+# well, movin' zeroes :-)
+preparebig 64
+wipe_dev $DEV
+check_hash_dev $DEV $HASH4
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 $((56*1024*2)) $HASH5
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c twofish-cbc-essiv:sha256 -s 128 --reduce-device-size 21M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 $((43*1024*2)) $HASH6
+wipe_dev $DEV
+# offset 21504 equals 10,5MiBs, equals --reduce-device-size 21M from test above (30M is ignored here, we'll reduce it to 21M in cryptsetup anyway)
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c twofish-cbc-essiv:sha256 -s 128 --offset 21504 --reduce-device-size 30M -q $FAST_PBKDF_ARGON > /dev/null || fail
+check_hash_head $PWD1 $((43*1024*2)) $HASH6
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 33M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 $((31*1024*2)) $HASH7
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M -q $FAST_PBKDF_ARGON > /dev/null 2>&1 && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --reduce-device-size 8M --init-only -q $FAST_PBKDF_ARGON $DEV || fail
+resize_file $DEVBIG -512
+echo $PWD1 | $CRYPTSETUP reencrypt -q $DEV 2> /dev/null && fail
+resize_file $DEVBIG 512
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --offset 32760 --reduce-device-size 8M -q $FAST_PBKDF_ARGON --init-only >/dev/null 2>&1 && fail
+# data offset at 21MiB
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --header $IMG_HDR --offset 43008 --reduce-device-size 21M -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH6 $IMG_HDR
+$CRYPTSETUP luksHeaderRestore --header-backup-file $IMG_HDR $DEV -q || fail
+check_hash $PWD1 $HASH6
+
+# Device activation after encryption initialization
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 -S11 --reduce-device-size 8M -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH5
+echo $PWD1 | $CRYPTSETUP reencrypt --resume-only $DEV -q || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH5
+
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M -q $FAST_PBKDF_ARGON $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP close $DEV_NAME
+check_hash_head $PWD1 $((56*1024*2)) $HASH5
+
+# Device activation using key file
+wipe_dev $DEV
+echo -n $PWD1 > $KEY1
+$CRYPTSETUP reencrypt $DEV --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M --key-file $KEY1 -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+$CRYPTSETUP close $DEV_NAME
+echo $PWD1 | $CRYPTSETUP open $DEV --test-passphrase || fail
+
+# Small device encryption test
+preparebig 65
+# wipe only 1st MiB (final data size after encryption)
+wipe_dev $DEV 1
+check_hash_dev_head $DEV 2048 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M -q $FAST_PBKDF_ARGON || fail
+check_hash_head $PWD1 2048 $HASH2
+
+wipe_dev_head $DEV 1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt --reduce-device-size 64M --init-only -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+check_hash_dev_head /dev/mapper/$DEV_NAME 2048 $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q || fail
+check_hash_dev_head /dev/mapper/$DEV_NAME 2048 $HASH2
+
+echo "[3] Encryption with detached header"
+preparebig 256
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+wipe_dev $DEV
+rm -f $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --resilience journal --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+wipe_dev $DEV
+rm -f $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -c twofish-cbc-essiv:sha256 -s 128 --resilience none --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+wipe_dev $DEV
+rm -f $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt -c serpent-xts-plain --resilience checksum --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+rm -f $IMG_HDR
+
+# Device activation after encryption initialization
+wipe_dev $DEV
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH3
+echo $PWD1 | $CRYPTSETUP reencrypt --resume-only --header $IMG_HDR --active-name $DEV_NAME -q || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH3
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --encrypt -c aes-cbc-essiv:sha256 -s 128 --reduce-device-size 8M -q $FAST_PBKDF_ARGON $DEV_NAME 2>/dev/null && fail
+$CRYPTSETUP close $DEV_NAME
+check_hash $PWD1 $HASH3 $IMG_HDR
+rm -f $IMG_HDR
+
+# Device encryption with data offset set in detached header
+wipe_dev $DEV
+dd if=/dev/urandom of=$DEV bs=512 count=32768 >/dev/null 2>&1
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR --offset 32768 -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH9 $IMG_HDR
+rm -f $IMG_HDR
+
+# Device activation using key file
+wipe_dev $DEV
+echo -n $PWD1 > $KEY1
+$CRYPTSETUP reencrypt $DEV --encrypt --init-only -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR --key-file $KEY1 -q $FAST_PBKDF_ARGON $DEV_NAME >/dev/null || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+$CRYPTSETUP close $DEV_NAME
+echo $PWD1 | $CRYPTSETUP open --header $IMG_HDR $DEV --test-passphrase || fail
+
+# Encrypt without size reduction must not allow header device same as data device
+wipe_dev_head $DEV 1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --type luks2 --encrypt --header $DEV -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $DEV 2>/dev/null && fail
+ln -s $DEV $DEV_LINK || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --type luks2 --encrypt --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $DEV 2>/dev/null && fail
+rm -f $DEV_LINK || fail
+
+dd if=/dev/zero of=$IMG bs=4k count=1 >/dev/null 2>&1
+echo $PWD1 | $CRYPTSETUP reencrypt $IMG --type luks2 --encrypt --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
+ln -s $IMG $DEV_LINK || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $IMG --type luks2 --encrypt --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
+
+echo "[4] Reencryption with detached header"
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --resilience journal --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -c twofish-cbc-essiv:sha256 -s 128 --resilience none --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -c serpent-xts-plain --resilience checksum --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+check_hash $PWD1 $HASH3 $IMG_HDR
+# trivial check for detached header misuse
+dd if=/dev/zero of=$IMG bs=4k count=1 >/dev/null 2>&1
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open $IMG $DEV_NAME --header $IMG_HDR || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME2 --header $IMG_HDR || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME --header $IMG_HDR -q || fail
+# key description mismatch in active device
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME2 --header $IMG_HDR >/dev/null 2>&1 && fail
+# also check it can abort initialization in this case
+$CRYPTSETUP luksDump $IMG_HDR | grep -q "online-reencrypt" && fail
+$CRYPTSETUP close $DEV_NAME || fail
+$CRYPTSETUP close $DEV_NAME2 || fail
+
+echo "[5] Decryption with detached header"
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --sector-size 512 -c aes-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience journal --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c twofish-cbc-essiv:sha256 -s 128 --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience none --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c serpent-xts-plain --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience checksum --header $IMG_HDR $DEV || fail
+check_hash_dev $DEV $HASH3
+
+# check deferred remove works as expected after decryption
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --sector-size 512 -c serpent-xts-plain --header $IMG_HDR -q $FAST_PBKDF_ARGON $DEV || fail
+open_crypt $PWD1 $IMG_HDR
+dmsetup create $DEV_NAME2 --table "0 1 linear /dev/mapper/$DEV_NAME 0" || fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --decrypt --resilience checksum --header $IMG_HDR --active-name $DEV_NAME || fail
+$CRYPTSETUP status $DEV_NAME >/dev/null || fail
+dmsetup remove --retry $DEV_NAME2
+$CRYPTSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+
+# check tool can block some funny user ideas
+preparebig 64
+ln -s $DEV $DEV_LINK || fail
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 -c serpent-xts-plain -q $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $DEV_LINK -q 2>/dev/null && fail
+open_crypt $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --active-name $DEV_NAME -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --active-name $DEV_NAME --header $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --active-name $DEV_NAME --header $DEV_LINK -q 2>/dev/null && fail
+$CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" && fail
+$CRYPTSETUP close $DEV_NAME
+
+# yet another funny idea
+rm -f $IMG_HDR
+$CRYPTSETUP luksHeaderBackup --header-backup-file $IMG_HDR $DEV || fail
+chmod +w $IMG_HDR || fail
+command -v wipefs >/dev/null && {
+ wipefs -a $DEV >/dev/null 2>&1 || fail
+}
+open_crypt $PWD1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --active-name $DEV_NAME --decrypt --header $IMG_HDR -q 2>/dev/null && fail
+$CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" && fail
+$CRYPTSETUP close $DEV_NAME || fail
+
+if ! dm_delay_features; then
+ echo "dm-delay target is missing, skipping recovery tests."
+ remove_mapping
+ exit 0
+fi
+
+echo "[6] Reencryption recovery"
+# (check opt-io size optimization in reencryption code does not affect recovery)
+# device with opt-io size 32k
+prepare_linear_dev 32 opt_blks=64 $OPT_XFERLEN_EXP
+OFFSET=8192
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH1
+reencrypt_recover 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ reencrypt_recover 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ reencrypt_recover 4096 journal $HASH1
+fi
+
+echo "[7] Reencryption recovery (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH1
+reencrypt_recover_online 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ reencrypt_recover_online 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 --sector-size 4096 -c aes-cbc-essiv:sha256 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+fi
+
+echo "[8] Reencryption with detached header recovery"
+prepare_linear_dev 31 opt_blks=64 $OPT_XFERLEN_EXP
+
+echo "sector size 512->512"
+
+get_error_offsets 31 0
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+check_hash $PWD1 $HASH7 $IMG_HDR
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH7 $IMG_HDR
+reencrypt_recover 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH7 $IMG_HDR
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ reencrypt_recover 4096 journal $HASH7 $IMG_HDR
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH7 $IMG_HDR
+ reencrypt_recover 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[9] Reencryption with detached header recovery (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 31 0
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1 $IMG_HDR
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH7 $IMG_HDR
+reencrypt_recover_online 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH7 $IMG_HDR
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+ reencrypt_recover_online 4096 journal $HASH7 $IMG_HDR
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 31 0 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1 $IMG_HDR
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH7 $IMG_HDR
+ reencrypt_recover_online 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[10] Encryption recovery"
+prepare_linear_dev 64
+OFFSET=$((2*1024*2))
+
+echo "sector size 512"
+
+get_error_offsets 64 $OFFSET 512 $((62*1024*2))
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover 512 4M $HASH8 $((60*1024*2)) $HASH4
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ get_error_offsets 64 $OFFSET 4096 $((62*1024*2))
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover 4096 4M $HASH8 $((60*1024*2)) $HASH4
+fi
+
+echo "[11] Encryption recovery (online i/o error)"
+
+echo "sector size 512"
+
+get_error_offsets 64 $OFFSET 512 $((62*1024*2))
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover_online 512 4M $HASH8 $((60*1024*2)) $HASH4
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ get_error_offsets 64 $OFFSET 4096 $((62*1024*2))
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover_online 4096 4M $HASH8 $((60*1024*2)) $HASH4
+fi
+
+echo "[12] Encryption with detached header recovery"
+prepare_linear_dev 31 opt_blks=64 $OPT_XFERLEN_EXP
+
+get_error_offsets 31 0
+
+echo "sector size 512"
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover_detached 512 checksum $HASH7 $IMG_HDR
+encrypt_recover_detached 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ get_error_offsets 31 0 4096
+
+ echo "sector size 4096"
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover_detached 4096 checksum $HASH7 $IMG_HDR
+ encrypt_recover_detached 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[13] Encryption with detached header recovery (online i/o error)"
+
+get_error_offsets 31 0
+
+echo "sector size 512"
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+encrypt_recover_detached_online 512 checksum $HASH7 $IMG_HDR
+encrypt_recover_detached_online 512 journal $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ get_error_offsets 31 0 4096
+
+ echo "sector size 4096"
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ encrypt_recover_detached_online 4096 checksum $HASH7 $IMG_HDR
+ encrypt_recover_detached_online 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[14] Decryption with detached header recovery"
+
+echo "sector size 512"
+
+# TODO: What should decryption do when it finishes decryption during recovery (with open)
+get_error_offsets 31 2049
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+decrypt_recover_detached 512 journal $HASH7 $IMG_HDR
+decrypt_recover_detached 512 checksum $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ # TODO: What should decryption do when it finishes decryption during recovery (with open)
+ get_error_offsets 31 2048 4096
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ decrypt_recover_detached 4096 checksum $HASH7 $IMG_HDR
+ decrypt_recover_detached 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[15] Decryption with detached header recovery (online i/o error)"
+
+echo "sector size 512"
+
+# TODO: What should decryption do when it finishes decryption during recovery (with open)
+get_error_offsets 31 2049
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+decrypt_recover_detached_online 512 journal $HASH7 $IMG_HDR
+decrypt_recover_detached_online 512 checksum $HASH7 $IMG_HDR
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 4096"
+
+ # TODO: What should decryption do when it finishes decryption during recovery (with open)
+ get_error_offsets 31 2048 4096
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ decrypt_recover_detached_online 4096 checksum $HASH7 $IMG_HDR
+ decrypt_recover_detached_online 4096 journal $HASH7 $IMG_HDR
+fi
+
+echo "[16] Offline reencryption with fixed device size."
+preparebig 68
+
+for test_sector_size in $TEST_SECTORS; do
+printf "sector size %4s: " $test_sector_size
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_offline_fixed_size $test_sector_size 2048 $HASH2 $test_res $((60*1024*2)) $HASH8
+ reencrypt_offline_fixed_size $test_sector_size $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8
+ reencrypt_offline_fixed_size $test_sector_size $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[17] Online reencryption with fixed device size."
+for test_sector_size in $TEST_SECTORS; do
+printf "sector size %4s: " $test_sector_size
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_online_fixed_size $test_sector_size 2048 $HASH2 $test_res $((60*1024*2)) $HASH8
+ reencrypt_online_fixed_size $test_sector_size $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8
+ reencrypt_online_fixed_size $test_sector_size $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[18] Offline reencryption with fixed device size (detached header)."
+preparebig 60
+
+for test_sector_size in $TEST_SECTORS; do
+printf "sector size %4s: " $test_sector_size
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_offline_fixed_size $test_sector_size 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_offline_fixed_size $test_sector_size $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_offline_fixed_size $test_sector_size $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[19] Online reencryption with fixed device size (detached header)."
+for test_sector_size in $TEST_SECTORS; do
+printf "sector size %4s: " $test_sector_size
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ reencrypt_online_fixed_size $test_sector_size 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_online_fixed_size $test_sector_size $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ reencrypt_online_fixed_size $test_sector_size $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[20] Offline encryption with fixed device size (detached header)."
+for test_sector_size in $TEST_SECTORS; do
+printf "sector size %4s: " $test_sector_size
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ encrypt_offline_fixed_size $test_sector_size 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ encrypt_offline_fixed_size $test_sector_size $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ encrypt_offline_fixed_size $test_sector_size $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[21] Offline decryption with fixed device size (detached header)."
+prepare_linear_dev 60
+for test_sector_size in $TEST_SECTORS; do
+printf "sector size %4s: " $test_sector_size
+for test_res in checksum journal none; do
+ echo -n "[$test_res]"
+ decrypt_offline_fixed_size $test_sector_size 2048 $HASH2 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ decrypt_offline_fixed_size $test_sector_size $((28*1024*2)) $HASH1 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ decrypt_offline_fixed_size $test_sector_size $((31*1024*2)) $HASH7 $test_res $((60*1024*2)) $HASH8 $IMG_HDR
+ echo -n "[OK]"
+done
+echo ""
+done
+
+echo "[22] Multi-keyslot device reencryption"
+prepare dev_size_mb=17
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --offset 32768 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV || fail
+echo -e "$PWD1\n$PWD3" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+
+echo -e "$PWD1\n$PWD2\n$PWD3" | $CRYPTSETUP reencrypt $DEV -q || fail
+check_hash $PWD1 $HASH2
+check_hash $PWD2 $HASH2
+check_hash $PWD3 $HASH2
+
+# check at least pbkdf type is preserved
+$CRYPTSETUP luksDump $DEV | grep -e "3: luks2" -A5 | grep -q "argon2" || fail
+$CRYPTSETUP luksDump $DEV | grep -e "4: luks2" -A5 | grep -q "pbkdf2" || fail
+$CRYPTSETUP luksDump $DEV | grep -e "5: luks2" -A5 | grep -q "argon2" || fail
+
+echo $PWD1 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV $KEY1 || fail
+
+# with more keyslots, specific has to be selected
+$CRYPTSETUP reencrypt $DEV -d $KEY1 -q 2>/dev/null && fail
+$CRYPTSETUP reencrypt $DEV -d $KEY1 -q -S0 || fail
+open_crypt
+check_hash_dev /dev/mapper/$DEV_NAME $HASH2
+$CRYPTSETUP close $DEV_NAME
+
+# there should be single keyslot now
+$CRYPTSETUP reencrypt $DEV -d $KEY1 -q || fail
+echo $PWD1 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S1 -d $KEY1 || fail
+
+echo $PWD3 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S2 --unbound --key-size 32 || fail
+echo $PWD3 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S22 --unbound --key-size 32 || fail
+echo $PWD3 | $CRYPTSETUP -q luksAddKey $FAST_PBKDF2 $DEV -S23 --unbound --key-size 32 || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -S1 -q || fail
+$CRYPTSETUP open --test-passphrase -d $KEY1 $DEV 2>/dev/null && fail
+echo $PWD3 | $CRYPTSETUP open --test-passphrase -S2 $DEV || fail
+echo $PWD3 | $CRYPTSETUP open --test-passphrase -S22 $DEV || fail
+check_hash $PWD1 $HASH2
+
+# fill 31 keyslots
+COUNT=27
+while [ $COUNT -gt 0 ]; do
+ echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey $DEV -q $FAST_PBKDF_ARGON || fail
+ COUNT=$((COUNT-1))
+done
+
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -S0 -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksKillSlot $DEV 30 || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -S0 || fail
+
+COUNT=14
+while [ $COUNT -gt 0 ]; do
+ echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey $DEV -q $FAST_PBKDF_ARGON || fail
+ COUNT=$((COUNT-1))
+done
+
+echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1" | $CRYPTSETUP reencrypt $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP luksKillSlot $DEV 1 || fail
+# one wrong passphrase
+echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD2" | $CRYPTSETUP reencrypt $DEV -q 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --resume-only -q 2>/dev/null && fail
+echo -e "$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1\n$PWD1" | $CRYPTSETUP reencrypt $DEV -q || fail
+
+#test error path behaves as expected for initialization with not enough space in binary area
+# create LUKS2 header with keyslots binary space for exactly 4 keyslots
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --luks2-keyslots-size $((4*258048)) -S0 -s512 --cipher aes-xts-plain64 $FAST_PBKDF_ARGON $DEV >/dev/null || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -S1 $DEV -q $FAST_PBKDF_ARGON || fail
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey -S2 $DEV -q $FAST_PBKDF_ARGON || fail
+# there is not enough space in binary area for keyslot id 4 (replacement for id 2)
+echo -e "$PWD1\n$PWD2\n$PWD2" | $CRYPTSETUP reencrypt $DEV --init-only -q 2>/dev/null && fail
+$CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt" && fail
+# check cli removed all unbound keyslots created in-before reencryption initialization
+$CRYPTSETUP luksDump $DEV | grep -q "unbound" && fail
+
+echo $PWD1 | $CRYPTSETUP luksKillSlot $DEV 2 || fail
+# there is not enough space in binary area for reencryption keyslot
+echo -e "$PWD1\n$PWD2" | $CRYPTSETUP reencrypt $DEV --init-only -q 2>/dev/null && fail
+$CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt" && fail
+# check cli removed all unbound keyslots created in-before reencryption initialization
+$CRYPTSETUP luksDump $DEV | grep -q "unbound" && fail
+
+echo "[23] Reencryption with specified new volume key"
+prepare dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 256 -c aes-cbc-essiv:sha256 --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD3" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q -S0 $FAST_PBKDF_ARGON --volume-key-file $VKEY1 -s 128 || fail
+check_hash $PWD1 $HASH1
+$CRYPTSETUP luksErase -q $DEV || fail
+echo $PWD1 | $CRYPTSETUP luksAddKey -q $FAST_PBKDF_ARGON --volume-key-file $VKEY1 -s 128 $DEV || fail
+check_hash $PWD1 $HASH1
+
+echo "[24] Reencryption with initial cipher_null"
+# aka custom encryption
+prepare dev_size_mb=32
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash $PWD1 $HASH1
+
+# online
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -c aes-xts-plain64 -q $FAST_PBKDF_ARGON || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH1
+if [ $HAVE_KEYRING -gt 0 ]; then
+ $CRYPTSETUP status $DEV_NAME | grep -q "key location: keyring" || fail
+fi
+$CRYPTSETUP close $DEV_NAME
+
+# simulate LUKS2 device with cipher_null in both keyslot and segment (it can be created only by up conversion from LUKS1)
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -s 128 -c cipher_null-ecb --offset 8192 $FAST_PBKDF2 $DEV || fail
+$CRYPTSETUP convert -q --type luks2 $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q $FAST_PBKDF_ARGON >/dev/null || fail
+check_hash $PWD1 $HASH1
+# both keyslot and segment cipher must not be null after reencryption with default params
+$CRYPTSETUP luksDump $DEV | grep -q "cipher_null" && fail
+
+# multistep reencryption with initial cipher_null
+preparebig 64
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $DEV -c null --offset 16384 -q $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --hotzone-size 1M --resilience none -q $FAST_PBKDF_ARGON >/dev/null || fail
+$CRYPTSETUP close $DEV_NAME
+check_hash $PWD1 $HASH5
+
+echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 $DEV -c null --offset 16384 -q $FAST_PBKDF_ARGON || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV --hotzone-size 1M --resilience none -q $FAST_PBKDF_ARGON >/dev/null || fail
+check_hash $PWD1 $HASH5
+
+echo "[25] Reencryption recovery with cipher_null"
+# (check opt-io size optimization in reencryption code does not affect recovery)
+# device with opt-io size 32k
+prepare_linear_dev 32 opt_blks=64 $OPT_XFERLEN_EXP
+OFFSET=8192
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover 512 checksum $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+reencrypt_recover 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ reencrypt_recover 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover 4096 checksum $HASH1
+ reencrypt_recover 4096 journal $HASH1
+fi
+
+echo "[26] Reencryption recovery with cipher_null (online i/o error)"
+
+echo "sector size 512->512"
+
+get_error_offsets 32 $OFFSET
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 -c null --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+reencrypt_recover_online 512 checksum $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 -c null --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+reencrypt_recover_online 512 journal $HASH1
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo "sector size 512->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+ reencrypt_recover_online 4096 journal $HASH1
+
+ echo "sector size 4096->4096"
+
+ get_error_offsets 32 $OFFSET 4096
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -c null --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ reencrypt_recover_online 4096 checksum $HASH1
+ reencrypt_recover_online 4096 journal $HASH1
+fi
+
+echo "[27] Verify test passphrase mode works with reencryption metadata"
+echo $PWD1 | $CRYPTSETUP -S5 -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey --unbound -s80 -S0 $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --init-only $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $DEV || fail
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat -S5 --header $IMG_HDR --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+echo -e "$PWD1\n$PWD1" | $CRYPTSETUP luksAddKey --unbound -s80 -S0 $FAST_PBKDF_ARGON $IMG_HDR || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --init-only --header $IMG_HDR $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $IMG_HDR || fail
+rm -f $IMG_HDR
+wipe_dev_head $DEV 1
+
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --init-only --header $IMG_HDR $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $IMG_HDR || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 8M $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open --test-passphrase $DEV || fail
+
+echo "[28] Prevent nested encryption"
+prepare_linear_dev 32 opt_blks=64 $OPT_XFERLEN_EXP
+
+#device already LUKS2
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF2 $DEV || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks1 --reduce-device-size 2m $FAST_PBKDF2 $DEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks1 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+test -f $IMG_HDR && fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks2 --reduce-device-size 2m $FAST_PBKDF2 $DEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+test -f $IMG_HDR && fail
+#type mismatch
+echo $PWD1 | $CRYPTSETUP reencrypt -q --type luks1 $DEV 2>/dev/null && fail
+wipe_dev $DEV
+
+#detached header already LUKS2
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks1 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --type luks1 --header $IMG_HDR $DEV 2>/dev/null && fail
+rm -f $IMG_HDR
+
+#data device already in reencryption
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF2 $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --init-only $FAST_PBKDF_ARGON $DEV || fail
+
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks1 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+test -f $IMG_HDR && fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+test -f $IMG_HDR && fail
+#type mismatch
+echo $PWD1 | $CRYPTSETUP reencrypt -q --type luks1 $DEV 2>/dev/null && fail
+wipe_dev $DEV
+rm -f $IMG_HDR
+
+#header in reencryption (type mismatch)
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt -q --encrypt --type luks1 --header $IMG_HDR $FAST_PBKDF2 $DEV 2>/dev/null && fail
+
+echo "[29] Conflicting reencryption parameters"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF2 $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --init-only $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --reduce-device-size 4M $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience datashift 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience datashift-checksum 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience datashift-journal 2> /dev/null && fail
+wipe_dev_head $DEV 1
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --init-only --reduce-device-size 16M $DEV -q $FAST_PBKDF_ARGON 2> /dev/null || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience journal 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience datashift-checksum 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --resilience datashift-journal 2> /dev/null && fail
+wipe_dev_head $DEV 1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --header $IMG_HDR --resilience datashift-checksum 2>/dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --header $IMG_HDR --resilience datashift-journal 2>/dev/null && fail
+rm -f $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --encrypt --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --header $IMG_HDR $FAST_PBKDF2 $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only $FAST_PBKDF_ARGON || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --header $IMG_HDR $DEV -q $FAST_PBKDF_ARGON 2> /dev/null && fail
+rm -f $IMG_HDR
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF2 $DEV || fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $IMG_HDR -q --init-only $FAST_PBKDF_ARGON --resilience datashift 2> /dev/null && fail
+test -f $IMG_HDR && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $IMG_HDR -q --init-only $FAST_PBKDF_ARGON --resilience none 2> /dev/null && fail
+test -f $IMG_HDR && fail
+$CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt" && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $IMG_HDR -q --init-only $FAST_PBKDF_ARGON --resilience checksum --hotzone-size 4m || fail
+$CRYPTSETUP isLuks $DEV -q && fail
+# $CRYPTSETUP luksDump $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $IMG_HDR -q --resilience datashift 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $IMG_HDR -q --resilience none 2> /dev/null && fail
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt $DEV --header $IMG_HDR -q --resilience journal || fail
+rm -f $IMG_HDR
+
+check_blkid
+if [ "$HAVE_BLKID" -gt 0 ]; then
+ echo "[30] Prevent nested encryption of broken LUKS device"
+ rm -f $IMG_HDR
+ xz -dkf $HEADER_LUKS2_PV.xz
+ wipe_dev $DEV
+
+ # broken header
+ echo $PWD1 | $CRYPTSETUP reencrypt -q --header $HEADER_LUKS2_PV $DEV $FAST_PBKDF_ARGON --encrypt --type luks2 2>/dev/null && fail
+ $CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
+ # broken device
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $HEADER_LUKS2_PV $FAST_PBKDF_ARGON --encrypt --force-offline-reencrypt --type luks2 --reduce-device-size 8m 2>/dev/null && fail
+ $CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
+ # broken data device only
+ echo $PWD1 | $CRYPTSETUP reencrypt -q --header $IMG_HDR $HEADER_LUKS2_PV $FAST_PBKDF_ARGON --encrypt --force-offline-reencrypt --type luks2 2>/dev/null && fail
+ test -f $IMG_HDR && fail
+fi
+
+if [ -n "$DM_SECTOR_SIZE" -a $HAVE_BLKID -gt 0 ]; then
+ echo "[31] Prevent dangerous sector size increase"
+ preparebig 64
+ echo $PWD1 | $CRYPTSETUP luksFormat -q --sector-size 512 --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+
+ # block encryption sector size increase on offline device
+ echo $PWD1 | $CRYPTSETUP reencrypt --init-only -q --sector-size 1024 $FAST_PBKDF_ARGON $DEV 2>/dev/null && fail
+ $CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt" && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q --sector-size 1024 $FAST_PBKDF_ARGON $DEV 2>/dev/null && fail
+ $CRYPTSETUP luksDump $DEV | grep -q "online-reencrypt" && fail
+ $CRYPTSETUP luksDump $DEV | grep -q "sector: 1024" && fail
+
+ # --force-offline-reencrypt can bypass the constraint
+ echo $PWD1 | $CRYPTSETUP reencrypt --force-offline-reencrypt --init-only -q --sector-size 1024 $FAST_PBKDF_ARGON $DEV || fail
+ # resume must work
+ echo $PWD1 | $CRYPTSETUP reencrypt -q $FAST_PBKDF_ARGON $DEV || fail
+
+ # online with no superblock is fine
+ echo $PWD1 | $CRYPTSETUP open -q $DEV $DEV_NAME || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --init-only -q --sector-size 4096 $FAST_PBKDF_ARGON $DEV || fail
+ $CRYPTSETUP close $DEV_NAME || fail
+
+ # sector size decrease is ok
+ echo $PWD1 | $CRYPTSETUP luksFormat -q --sector-size 4096 --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --init-only -q --sector-size 1024 $FAST_PBKDF_ARGON $DEV || fail
+
+ if [ -n "$BLKID_BLOCK_SIZE_SUPPORT" ]; then
+ xz -dkf $IMG_FS.xz
+ # encryption checks must work in offline mode
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --force-offline-reencrypt --sector-size 1024 -q --header $IMG_HDR $IMG_FS $FAST_PBKDF_ARGON --init-only --type luks2 2>/dev/null && fail
+ test -f $IMG_HDR && fail
+
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --force-offline-reencrypt --sector-size 1024 -q --header $IMG_HDR $IMG_FS $FAST_PBKDF_ARGON --type luks2 2>/dev/null && fail
+ test -f $IMG_HDR && fail
+
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --force-offline-reencrypt --sector-size 1024 -q --reduce-device-size 8m $IMG_FS $FAST_PBKDF_ARGON --init-only --type luks2 2>/dev/null && fail
+ $CRYPTSETUP isLuks $IMG_FS && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --encrypt --force-offline-reencrypt --sector-size 1024 -q --reduce-device-size 8m $IMG_FS $FAST_PBKDF_ARGON --type luks2 2>/dev/null && fail
+ $CRYPTSETUP isLuks $IMG_FS && fail
+
+ echo $PWD1 | $CRYPTSETUP luksFormat -q --sector-size 512 --type luks2 $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open -q $DEV $DEV_NAME || fail
+ dd if=$IMG_FS of=/dev/mapper/$DEV_NAME bs=1M >/dev/null 2>&1
+
+ echo $PWD1 | $CRYPTSETUP reencrypt --init-only -q --sector-size 1024 $FAST_PBKDF_ARGON $DEV 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt --init-only -q --sector-size 1024 --active-name $DEV_NAME $FAST_PBKDF_ARGON 2>/dev/null && fail
+ $CRYPTSETUP status $DEV_NAME | grep -q "reencryption: in-progress" && fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q --sector-size 1024 $FAST_PBKDF_ARGON $DEV 2>/dev/null && fail
+ $CRYPTSETUP luksDump $DEV | grep -q "sector: 512" || fail
+ echo $PWD1 | $CRYPTSETUP reencrypt -q --sector-size 1024 --active-name $DEV_NAME $FAST_PBKDF_ARGON 2>/dev/null && fail
+ $CRYPTSETUP luksDump $DEV | grep -q "sector: 512" || fail
+ fi
+fi
+
+echo "[32] Removal of encryption (LUKS2 legacy cryptsetup-reencrypt test)."
+prepare dev_size_mb=32
+OFFSET=8192
+
+# offline decryption with shift
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 57344 $HASH1
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+# online decryption with shift
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 57344 $HASH1
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+# offline decryption (separate initialization and decryption steps)
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only || fail
+check_hash $PWD1 $HASH1 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 57344 $HASH1
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+# online decryption with shift
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 57344 $HASH1
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+# same tests just with date size == LUKS2 header size
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 32768 || fail
+wipe $PWD1
+check_hash $PWD1 $HASH10
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 32768 $HASH10
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 32768 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 32768 $HASH10
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 32768 || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only || fail
+check_hash $PWD1 $HASH10 $IMG_HDR
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 32768 $HASH10
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 32768 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH10
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 32768 $HASH10
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+# 1MiB data size
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 63488 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+# --hotzone-size larger than data expected to get auto corrected by library
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --init-only --hotzone-size 4M || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 2048 $HASH2
+rm -f $IMG_HDR
+
+# small device (less than header size)
+prepare dev_size_mb=5
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -S5 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 2048 $HASH2
+# FIXME: Should not reencryption remove it automatically?
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 -S5 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR || fail
+check_hash_dev_head $DEV 2048 $HASH2
+rm -f $IMG_HDR
+
+# initialization by --active-name parameter
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --active-name $DEV_NAME || fail
+check_hash_dev_head $DEV 2048 $HASH2
+rm -f $IMG_HDR
+
+# initialization and resume by --active-name parameter
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 $FAST_PBKDF_ARGON $DEV --offset 8192 || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --decrypt --header $IMG_HDR --active-name $DEV_NAME --init-only || fail
+check_hash_dev /dev/mapper/$DEV_NAME $HASH2
+echo $PWD1 | $CRYPTSETUP reencrypt $DEV -q --header $IMG_HDR --active-name $DEV_NAME || fail
+check_hash_dev_head $DEV 2048 $HASH2
+rm -f $IMG_HDR
+
+echo "[33] Decryption with datashift recovery (error in shift area)."
+prepare_linear_dev 32
+echo "sector size 512"
+
+# avoid error in moved segment area on purpose
+# Also do not create write error in last segment because
+# that would not trigger reencryption crash (read would pass)
+get_error_offsets 32 $OFFSET 512 $((32-1024*2-$OFFSET))
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+echo -n "resilience:"
+decrypt_recover $HASH1 $IMG_HDR $((32*1024*2-$OFFSET))
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo -e "\nsector size 4096"
+
+ get_error_offsets 32 $OFFSET 4096 $((32-1024*2-$OFFSET))
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ echo -n "resilience:"
+ decrypt_recover $HASH1 $IMG_HDR $((32*1024*2-$OFFSET))
+fi
+echo ""
+
+echo "[34] Decryption with datashift recovery (error in moved segment)."
+echo "sector size 512"
+
+HZ_SIZE=$((3*1024*2))
+
+# move injected error in moved segment area
+get_error_offsets 32 0 512 $HZ_SIZE
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+
+echo -n "resilience:"
+for res in datashift-journal datashift-checksum; do
+
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ decrypt_recover $HASH1 $IMG_HDR $((32*1024*2-$OFFSET)) $res $(($HZ_SIZE*512))
+done
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo -e "\nsector size 4096"
+
+ # move injected error in moved segment area
+ get_error_offsets 32 0 4096 $HZ_SIZE
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+
+ echo -n "resilience:"
+ for res in datashift-journal datashift-checksum; do
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ wipe $PWD1
+
+ decrypt_recover $HASH1 $IMG_HDR $((32*1024*2-$OFFSET)) $res $(($HZ_SIZE*512))
+ done
+fi
+echo ""
+
+echo "[35] Decryption with datashift recovery (online i/o error in shift area)."
+echo "sector size 512"
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+wipe_dev /dev/mapper/$DEV_NAME
+
+# avoid error in moved segment area on purpose
+# Also do not create write error in last segment because
+# that would not trigger reencryption crash (read would pass)
+get_error_offsets 32 $OFFSET 512 $((32-1024*2-$OFFSET))
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+
+echo -n "resilience:"
+decrypt_recover_online $HASH1 $IMG_HDR $((32*1024*2-$OFFSET))
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo -e "\nsector size 4096"
+
+ get_error_offsets 32 $OFFSET 4096 $((32-1024*2-$OFFSET))
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ wipe_dev /dev/mapper/$DEV_NAME
+
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+ echo -n "resilience:"
+ decrypt_recover_online $HASH1 $IMG_HDR $((32*1024*2-$OFFSET))
+fi
+echo ""
+
+echo "[36] Decryption with datashift recovery (online i/o error in moved segment)."
+echo "sector size 512"
+
+# move injected error in moved segment area
+get_error_offsets 32 0 512 $HZ_SIZE
+echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+
+echo -n "resilience:"
+for res in datashift-journal datashift-checksum; do
+
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ wipe_dev /dev/mapper/$DEV_NAME
+
+ decrypt_recover_online_moved $HASH1 $IMG_HDR $((32*1024*2-$OFFSET)) $res $(($HZ_SIZE*512))
+done
+
+if [ -n "$DM_SECTOR_SIZE" ]; then
+ echo -e "\nsector size 4096"
+
+ get_error_offsets 32 0 4096 $HZ_SIZE
+ echo "ERR writes to sectors [$ERROFFSET,$(($ERROFFSET+$ERRLENGTH-1))]"
+
+ echo -n "resilience:"
+ for res in datashift-journal datashift-checksum; do
+
+ echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 4096 --offset $OFFSET $FAST_PBKDF_ARGON $DEV || fail
+ echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME || fail
+ wipe_dev /dev/mapper/$DEV_NAME
+
+ decrypt_recover_online_moved $HASH1 $IMG_HDR $((32*1024*2-$OFFSET)) $res $(($HZ_SIZE*512))
+ done
+fi
+echo ""
+
+echo "[37] Decryption with datashift (large data offsets)"
+prepare_linear_dev 512
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset 1015808 --luks2-keyslots-size 16M $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q || fail
+check_hash_dev_head $DEV $((16*1024*2)) $HASH10
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset 1015808 --luks2-keyslots-size 16M $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q || fail
+check_hash_dev_head $DEV $((16*1024*2)) $HASH10
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset 1046528 --luks2-keyslots-size 16M $FAST_PBKDF_ARGON $DEV || fail
+wipe $PWD1
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q || fail
+check_hash_dev_head $DEV 2048 $HASH2
+rm -f $IMG_HDR
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks2 --sector-size 512 --offset 1046528 --luks2-keyslots-size 16M $FAST_PBKDF_ARGON $DEV || fail
+echo $PWD1 | $CRYPTSETUP open $DEV $DEV_NAME
+wipe_dev /dev/mapper/$DEV_NAME
+echo $PWD1 | $CRYPTSETUP reencrypt --decrypt --header $IMG_HDR $DEV -q || fail
+check_hash_dev_head $DEV 2048 $HASH2
+
+remove_mapping
+exit 0
diff --git a/tests/luks2-validation-test b/tests/luks2-validation-test
new file mode 100755
index 0000000..cd9f0a6
--- /dev/null
+++ b/tests/luks2-validation-test
@@ -0,0 +1,249 @@
+#!/bin/bash
+
+#turn on debug mode by following env. variable _DEBUG=1
+
+PS4='$LINENO:'
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+START_DIR=$(pwd)
+
+IMG=luks2-backend.img
+ORIG_IMG=luks2_valid_hdr.img
+TST_IMGS=$START_DIR/luks2-images
+
+GEN_DIR=generators
+
+FAILS=0
+
+[ -z "$srcdir" ] && srcdir="."
+
+function remove_mapping()
+{
+ rm -rf $IMG $TST_IMGS >/dev/null 2>&1
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cd $START_DIR
+ remove_mapping
+ exit 2
+}
+
+fail_count()
+{
+ echo "$1"
+ FAILS=$((FAILS+1))
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function prepare() # $1 dev1_size
+{
+ remove_mapping
+
+ test -d $TST_IMGS || mkdir $TST_IMGS
+
+ test -e $ORIG_IMG || xz -dkc $srcdir/$ORIG_IMG.xz >$ORIG_IMG
+ cp $ORIG_IMG $TST_IMGS
+ cp $ORIG_IMG $IMG
+}
+
+function test_load()
+{
+ local _debug=
+
+ test -z "$_DEBUG" || _debug="--debug"
+
+ case "$1" in
+ R)
+ if [ -n "$_debug" ]; then
+ $CRYPTSETUP luksDump $_debug $IMG
+ else
+ $CRYPTSETUP luksDump $_debug $IMG > /dev/null 2>&1
+ fi
+ test $? -eq 0 || return 1
+ ;;
+ F)
+ if [ -n "$_debug" ]; then
+ $CRYPTSETUP luksDump $_debug $IMG
+ else
+ $CRYPTSETUP luksDump $_debug $IMG > /dev/null 2>&1
+ fi
+ ret=$?
+ test $ret -ne 0 || return 1
+ test $ret -ne 139 || return 1
+ ;;
+ *)
+ fail "Internal test error"
+ ;;
+ esac
+}
+
+function RUN()
+{
+ echo -n "Test image: $1..."
+ cp $TST_IMGS/$1 $IMG || fail "Missing test image"
+ test_load $2 "$3"
+ if [ $? -ne 0 ]; then
+ fail_count "$3"
+ else
+ echo "OK"
+ fi
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+command -v jq >/dev/null || skip "Cannot find jq, test skipped."
+
+prepare
+
+echo "[0] Generating test headers"
+cd $srcdir/$GEN_DIR
+for scr in ./generate-*.sh; do
+ echo -n "$(basename $scr)..."
+ $scr $TST_IMGS $TST_IMGS/$ORIG_IMG || fail "Header generator $scr failed: '$?'"
+ echo "done"
+done
+cd $START_DIR
+
+echo "[1] Test basic auto-recovery"
+RUN luks2-invalid-checksum-hdr0.img "R" "Failed to recover from trivial header corruption at offset 0"
+# TODO: check epoch is increased after recovery
+# TODO: check only sectors related to corrupted hdr at offset 0 are written (dmstats tool/differ.c)
+
+RUN luks2-invalid-checksum-hdr1.img "R" "Failed to recover from trivial header corruption at offset 16384"
+# TODO: check epoch is increased after recovery
+# TODO: check only sectors related to corrupted hdr at offset 16384 are written (dmstats tool/differ.c)
+
+RUN luks2-invalid-checksum-both-hdrs.img "F" "Failed to recognise corrupted header beyond repair"
+
+echo "[2] Test ability to auto-correct mallformed json area"
+RUN luks2-corrupted-hdr0-with-correct-chks.img "R" "Failed to auto correct malformed json area at offset 512"
+# TODO: check epoch is increased after recovery
+# TODO: check only sectors related to corrupted hdr at offset 0 are written (dmstats tool/differ.c)
+
+RUN luks2-corrupted-hdr1-with-correct-chks.img "R" "Failed to auto correct malformed json area at offset 16896"
+# TODO: check epoch is increased after recovery
+# TODO: check only sectors related to corrupted hdr at offset 16384 are written (dmstats tool/differ.c)
+
+RUN luks2-correct-full-json0.img "R" "Failed to parse full and correct json area"
+# TODO: detect noop (norecovery, epoch untouched)
+# TODO: check epoch is NOT increased after recovery of secondary header
+
+# these tests auto-correct json in-memory only. It'll get fixed on-disk after write operation
+RUN luks2-argon2-leftover-params.img "R" "Failed to repair keyslot with old argon2 parameters."
+RUN luks2-pbkdf2-leftover-params-0.img "R" "Failed to repair keyslot with old pbkdf2 parameters."
+RUN luks2-pbkdf2-leftover-params-1.img "R" "Failed to repair keyslot with old pbkdf2 parameters."
+
+# Secondary header is always broken in following tests
+echo "[3] Test LUKS2 json area restrictions"
+RUN luks2-non-null-byte-beyond-json0.img "F" "Failed to detect illegal data right beyond json data string"
+RUN luks2-non-null-bytes-beyond-json0.img "F" "Failed to detect illegal data in json area"
+RUN luks2-missing-trailing-null-byte-json0.img "F" "Failed to detect missing terminal null byte"
+RUN luks2-invalid-opening-char-json0.img "F" "Failed to detect invalid opening character in json area"
+RUN luks2-invalid-object-type-json0.img "F" "Failed to detect invalid json object type"
+RUN luks2-overlapping-areas-c0-json0.img "F" "Failed to detect two exactly same area specifications"
+RUN luks2-overlapping-areas-c1-json0.img "F" "Failed to detect two intersecting area specifications"
+RUN luks2-overlapping-areas-c2-json0.img "F" "Failed to detect two slightly intersecting area specifications"
+RUN luks2-area-in-json-hdr-space-json0.img "F" "Failed to detect area referencing LUKS2 header space"
+RUN luks2-missing-keyslot-referenced-in-digest.img "F" "Failed to detect missing keyslot referenced in digest"
+RUN luks2-missing-segment-referenced-in-digest.img "F" "Failed to detect missing segment referenced in digest"
+RUN luks2-missing-keyslot-referenced-in-token.img "F" "Failed to detect missing keyslots referenced in token"
+RUN luks2-keyslot-missing-digest.img "F" "Failed to detect missing keyslot digest."
+RUN luks2-keyslot-too-many-digests.img "F" "Failed to detect keyslot has too many digests."
+
+echo "[4] Test integers value limits"
+RUN luks2-uint64-max-segment-size.img "R" "Validation rejected correct value"
+RUN luks2-uint64-overflow-segment-size.img "F" "Failed to detect uint64_t overflow"
+RUN luks2-uint64-signed-segment-size.img "F" "Failed to detect negative value"
+
+echo "[5] Test segments validation"
+RUN luks2-segment-missing-type.img "F" "Failed to detect missing type field"
+RUN luks2-segment-wrong-type.img "F" "Failed to detect invalid type field"
+RUN luks2-segment-missing-offset.img "F" "Failed to detect missing offset field"
+RUN luks2-segment-wrong-offset.img "F" "Failed to detect invalid offset field"
+RUN luks2-segment-missing-size.img "F" "Failed to detect missing size field"
+RUN luks2-segment-wrong-size-0.img "F" "Failed to detect invalid size field"
+RUN luks2-segment-wrong-size-1.img "F" "Failed to detect invalid size field"
+RUN luks2-segment-wrong-size-2.img "F" "Failed to detect invalid size field"
+RUN luks2-segment-crypt-missing-encryption.img "F" "Failed to detect missing encryption field"
+RUN luks2-segment-crypt-wrong-encryption.img "F" "Failed to detect invalid encryption field"
+RUN luks2-segment-crypt-missing-ivoffset.img "F" "Failed to detect missing iv_tweak field"
+RUN luks2-segment-crypt-wrong-ivoffset.img "F" "Failed to detect invalid iv_tweak field"
+RUN luks2-segment-crypt-missing-sectorsize.img "F" "Failed to detect missing sector_size field"
+RUN luks2-segment-crypt-wrong-sectorsize-0.img "F" "Failed to detect invalid sector_size field"
+RUN luks2-segment-crypt-wrong-sectorsize-1.img "F" "Failed to detect invalid sector_size field"
+RUN luks2-segment-crypt-wrong-sectorsize-2.img "F" "Failed to detect invalid sector_size field"
+RUN luks2-segment-unknown-type.img "R" "Validation rejected segment with all mandatory fields correct"
+RUN luks2-segment-two.img "R" "Validation rejected two valid segments"
+RUN luks2-segment-wrong-flags.img "F" "Failed to detect invalid flags field"
+RUN luks2-segment-wrong-flags-element.img "F" "Failed to detect invalid flags content"
+RUN luks2-segment-wrong-backup-key-0.img "F" "Failed to detect gap in backup segments"
+RUN luks2-segment-wrong-backup-key-1.img "F" "Failed to detect gap in backup segments"
+RUN luks2-segment-crypt-empty-encryption.img "F" "Failed to detect empty encryption field"
+
+echo "[6] Test metadata size and keyslots size (config section)"
+RUN luks2-invalid-keyslots-size-c0.img "F" "Failed to detect too large keyslots_size in config section"
+RUN luks2-invalid-keyslots-size-c1.img "F" "Failed to detect unaligned keyslots_size in config section"
+RUN luks2-invalid-keyslots-size-c2.img "F" "Failed to detect too small keyslots_size config section"
+RUN luks2-invalid-json-size-c0.img "F" "Failed to detect invalid json_size config section"
+RUN luks2-invalid-json-size-c1.img "F" "Failed to detect invalid json_size config section"
+RUN luks2-invalid-json-size-c2.img "F" "Failed to detect mismatching json size in config and binary hdr"
+RUN luks2-metadata-size-32k.img "R" "Valid 32KiB metadata size failed to validate"
+RUN luks2-metadata-size-64k.img "R" "Valid 64KiB metadata size failed to validate"
+RUN luks2-metadata-size-64k-inv-area-c0.img "F" "Failed to detect keyslot area trespassing in json area"
+RUN luks2-metadata-size-64k-inv-area-c1.img "F" "Failed to detect keyslot area overflowing keyslots area"
+RUN luks2-metadata-size-64k-inv-keyslots-size-c0.img "F" "Failed to detect keyslots size overflowing in data area"
+RUN luks2-metadata-size-128k.img "R" "Valid 128KiB metadata size failed to validate"
+RUN luks2-metadata-size-256k.img "R" "Valid 256KiB metadata size failed to validate"
+RUN luks2-metadata-size-512k.img "R" "Valid 512KiB metadata size failed to validate"
+RUN luks2-metadata-size-1m.img "R" "Valid 1MiB metadata size failed to validate"
+RUN luks2-metadata-size-2m.img "R" "Valid 2MiB metadata size failed to validate"
+RUN luks2-metadata-size-4m.img "R" "Valid 4MiB metadata size failed to validate"
+RUN luks2-metadata-size-16k-secondary.img "R" "Valid 16KiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-32k-secondary.img "R" "Valid 32KiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-64k-secondary.img "R" "Valid 64KiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-128k-secondary.img "R" "Valid 128KiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-256k-secondary.img "R" "Valid 256KiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-512k-secondary.img "R" "Valid 512KiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-1m-secondary.img "R" "Valid 1MiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-2m-secondary.img "R" "Valid 2MiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-4m-secondary.img "R" "Valid 4MiB metadata size in secondary hdr failed to validate"
+RUN luks2-metadata-size-invalid.img "F" "Invalid metadata size in secondary hdr not rejected"
+RUN luks2-metadata-size-invalid-secondary.img "F" "Invalid metadata size in secondary hdr not rejected"
+
+echo "[7] Test invalid metadata object property"
+RUN luks2-invalid-tokens.img "F" "Invalid tokens objects not rejected"
+RUN luks2-invalid-top-objects.img "F" "Invalid top-level objects not rejected"
+RUN luks2-keyslot-invalid-area.img "F" "Invalid keyslot area object not rejected"
+RUN luks2-keyslot-invalid-area-size.img "F" "Invalid keyslot area size that can overflow not rejected"
+RUN luks2-keyslot-invalid-objects.img "F" "Invalid keyslot objects not rejected"
+RUN luks2-keyslot-invalid-af.img "F" "Invalid keyslot objects types not rejected"
+
+remove_mapping
+
+test $FAILS -eq 0 || fail "($FAILS wrong result(s) in total)"
diff --git a/tests/luks2_header_requirements.tar.xz b/tests/luks2_header_requirements.tar.xz
new file mode 100644
index 0000000..b198fd5
--- /dev/null
+++ b/tests/luks2_header_requirements.tar.xz
Binary files differ
diff --git a/tests/luks2_keyslot_unassigned.img.xz b/tests/luks2_keyslot_unassigned.img.xz
new file mode 100644
index 0000000..726cdd7
--- /dev/null
+++ b/tests/luks2_keyslot_unassigned.img.xz
Binary files differ
diff --git a/tests/luks2_mda_images.tar.xz b/tests/luks2_mda_images.tar.xz
new file mode 100644
index 0000000..a27f5c7
--- /dev/null
+++ b/tests/luks2_mda_images.tar.xz
Binary files differ
diff --git a/tests/luks2_valid_hdr.img.xz b/tests/luks2_valid_hdr.img.xz
new file mode 100644
index 0000000..4e03a20
--- /dev/null
+++ b/tests/luks2_valid_hdr.img.xz
Binary files differ
diff --git a/tests/mode-test b/tests/mode-test
new file mode 100755
index 0000000..82171fb
--- /dev/null
+++ b/tests/mode-test
@@ -0,0 +1,187 @@
+#!/bin/bash
+#
+# Test mode compatibility, check input + kernel and cryptsetup cipher status
+#
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+DEV_NAME=dmc_test
+HEADER_IMG=mode-test.img
+PASSWORD=3xrododenron
+PASSWORD1=$PASSWORD
+FAST_PBKDF2="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+
+# cipher-chainmode-ivopts:ivmode
+CIPHERS="aes twofish serpent"
+MODES="cbc lrw xts"
+IVMODES="null benbi plain plain64 essiv:sha256"
+
+LOOPDEV=$(losetup -f 2>/dev/null)
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+dmremove() { # device
+ udevadm settle >/dev/null 2>&1
+ dmsetup remove --retry $1 >/dev/null 2>&1
+}
+
+cleanup() {
+ [ -b /dev/mapper/"$DEV_NAME"_tstdev ] && dmremove "$DEV_NAME"_tstdev
+ [ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
+ losetup -d $LOOPDEV >/dev/null 2>&1
+ rm -f $HEADER_IMG >/dev/null 2>&1
+}
+
+fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+
+add_device() {
+ cleanup
+ dd if=/dev/zero of=$HEADER_IMG bs=1M count=6 >/dev/null 2>&1
+ sync
+ losetup $LOOPDEV $HEADER_IMG >/dev/null 2>&1
+ dmsetup create $DEV_NAME --table "0 10240 linear $LOOPDEV 8" >/dev/null 2>&1
+}
+
+dmcrypt_check() # device outstring
+{
+ X=$(dmsetup table $1 2>/dev/null | sed 's/.*: //' | cut -d' ' -f 4)
+ if [ "$X" = $2 ] ; then
+ echo -n "[table OK]"
+ else
+ echo "[table FAIL]"
+ echo " Expecting $2 got $X."
+ fail
+ fi
+
+ X=$($CRYPTSETUP status $1 | grep cipher: | sed s/\.\*cipher:\\s*//)
+ if [ $X = $2 ] ; then
+ echo -n "[status OK]"
+ else
+ echo "[status FAIL]"
+ echo " Expecting $2 got \"$X\"."
+ fail
+ fi
+
+ dmremove $1
+}
+
+dmcrypt_check_sum() # cipher device
+{
+ EXPSUM="c036cbb7553a909f8b8877d4461924307f27ecb66cff928eeeafd569c3887e29"
+ # Fill device with zeroes and reopen it
+ dd if=/dev/zero of=/dev/mapper/$2 bs=1M count=6 >/dev/null 2>&1
+ sync
+ dmremove $2
+
+ echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 $2 /dev/mapper/$DEV_NAME >/dev/null 2>&1
+ ret=$?
+ VSUM=$(sha256sum /dev/mapper/$2 | cut -d' ' -f 1)
+ if [ $ret -eq 0 -a "$VSUM" = "$EXPSUM" ] ; then
+ echo -n "[OK]"
+ else
+ echo "[FAIL]"
+ echo " Expecting $EXPSUM got $VSUM."
+ fail
+ fi
+
+ dmremove $2
+}
+
+dmcrypt()
+{
+ OUT=$2
+ [ -z "$OUT" ] && OUT=$1
+ printf "%-31s" "$1"
+
+ echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 "$DEV_NAME"_tstdev /dev/mapper/$DEV_NAME >/dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ echo -n -e "PLAIN:"
+ dmcrypt_check "$DEV_NAME"_tstdev $OUT
+ else
+ echo -n "[n/a]"
+ fi
+
+ echo $PASSWORD | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF2 -c $1 -s 256 /dev/mapper/$DEV_NAME >/dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ echo -n -e " LUKS1:"
+ echo $PASSWORD | $CRYPTSETUP luksOpen /dev/mapper/$DEV_NAME "$DEV_NAME"_tstdev >/dev/null 2>&1 || fail
+ dmcrypt_check "$DEV_NAME"_tstdev $OUT
+ fi
+
+ echo $PASSWORD | $CRYPTSETUP luksFormat --type luks2 --pbkdf pbkdf2 $FAST_PBKDF2 -c $1 -s 256 --offset 8192 /dev/mapper/$DEV_NAME >/dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ echo -n -e " LUKS2:"
+ echo $PASSWORD | $CRYPTSETUP luksOpen /dev/mapper/$DEV_NAME "$DEV_NAME"_tstdev >/dev/null 2>&1 || fail
+ dmcrypt_check "$DEV_NAME"_tstdev $OUT
+ fi
+
+ # repeated device creation must return the same checksum
+ echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 "$DEV_NAME"_tstdev /dev/mapper/$DEV_NAME >/dev/null 2>&1
+ if [ $? -eq 0 ] ; then
+ echo -n -e " CHECKSUM:"
+ dmcrypt_check_sum "$1" "$DEV_NAME"_tstdev
+ fi
+ echo
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ -z "$LOOPDEV" ] && skip "Cannot find free loop device, test skipped."
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+add_device
+
+# compatibility modes
+dmcrypt aes aes-cbc-plain
+dmcrypt aes-plain aes-cbc-plain
+
+# empty cipher
+PASSWORD=""
+dmcrypt null cipher_null-ecb
+dmcrypt cipher_null cipher_null-ecb
+dmcrypt cipher_null-ecb
+
+PASSWORD=$PASSWORD1
+# codebook doesn't support IV at all
+for cipher in $CIPHERS ; do
+ dmcrypt "$cipher-ecb"
+done
+
+for cipher in $CIPHERS ; do
+ for mode in $MODES ; do
+ for ivmode in $IVMODES ; do
+ dmcrypt "$cipher-$mode-$ivmode"
+ done
+ done
+done
+
+dmcrypt xchacha12,aes-adiantum-plain64
+dmcrypt xchacha20,aes-adiantum-plain64
+
+cleanup
diff --git a/tests/password-hash-test b/tests/password-hash-test
new file mode 100755
index 0000000..6e3c78c
--- /dev/null
+++ b/tests/password-hash-test
@@ -0,0 +1,213 @@
+#!/bin/bash
+
+# check hash processing in create command
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+DEV_NAME=dmc_test
+KEY_FILE=keyfile
+
+DEV2=$DEV_NAME"_x"
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+dmremove() { # device
+ udevadm settle >/dev/null 2>&1
+ dmsetup remove --retry $1 >/dev/null 2>&1
+}
+
+cleanup() {
+ [ -b /dev/mapper/$DEV2 ] && dmremove $DEV2
+ [ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
+ rm -f $KEY_FILE
+ exit $1
+}
+
+function fail()
+{
+ echo " $1 [FAILED]"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup 2
+}
+
+skip()
+{
+ echo "TEST SKIPPED: $1"
+ cleanup 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+crypt_key() # hash keysize pwd/file name outkey [limit] [offset]
+{
+ DEV2=$DEV_NAME"_x"
+ LIMIT=""
+ MODE=aes-cbc-essiv:sha256
+ [ $2 -gt 256 ] && MODE=aes-xts-plain
+ [ -n "$6" ] && LIMIT="-l $6"
+ [ -n "$7" ] && LIMIT="$LIMIT --keyfile-offset $7"
+
+ echo -n "HASH: $1 KSIZE: $2 / $3"
+ case "$3" in
+ pwd)
+ echo -e -n "$4" | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
+ ret=$?
+ ;;
+ std-)
+ echo -e -n "$4" | $CRYPTSETUP create -c $MODE -d "-" -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
+ ret=$?
+ ;;
+ stdin)
+ echo -e -n "$4" | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
+ ret=$?
+ ;;
+ cat)
+ cat $4 | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
+ ret=$?
+ ;;
+ cat-)
+ cat $4 | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 -d - /dev/mapper/$DEV_NAME 2>/dev/null
+ ret=$?
+ ;;
+ file)
+ $CRYPTSETUP create -q -c $MODE -d $4 -h $1 -s $2 $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null
+ ret=$?
+ ;;
+ failpwd)
+ echo -e -n "$4" | $CRYPTSETUP create -c $MODE -h $1 -s $2 $LIMIT $DEV2 /dev/mapper/$DEV_NAME 2>/dev/null && fail "Expecting failure"
+ echo " [OK]"
+ return
+ ;;
+ *)
+ fail ""
+ ;;
+ esac
+
+ # ignore these cases, not all libs/kernel supports it
+ if [ "$1" != "sha256" ] || [ $2 -gt 256 ] ; then
+ if [ $ret -ne 0 ] ; then
+ echo " [N/A] ($ret, SKIPPED)"
+ return
+ fi
+ fi
+
+ VKEY=$(dmsetup table $DEV2 --showkeys 2>/dev/null | sed 's/.*: //' | cut -d' ' -f 5)
+ if [ "$VKEY" != "$5" ] ; then
+ echo " [FAILED]"
+ echo "expected: $5"
+ echo "real key: $VKEY"
+ cleanup 100
+ else
+ echo " [OK]"
+ fi
+
+ dmremove $DEV2
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run this test, test skipped."
+ exit 77
+fi
+
+dmsetup create $DEV_NAME --table "0 10240 zero" >/dev/null 2>&1
+
+crypt_key ripemd160 0 pwd "xxx" aeb26d1f69eb6dddfb9381eed4d7299f091e99aa5d3ff06866d4ce9f620f7aca
+crypt_key ripemd160 256 pwd "xxx" aeb26d1f69eb6dddfb9381eed4d7299f091e99aa5d3ff06866d4ce9f620f7aca
+crypt_key ripemd160 128 pwd "xxx" aeb26d1f69eb6dddfb9381eed4d7299f
+crypt_key sha1 256 pwd "xxx" b60d121b438a380c343d5ec3c2037564b82ffef30b1e0a6ad9af7a73aa91c197
+crypt_key sha1 128 pwd "xxx" b60d121b438a380c343d5ec3c2037564
+crypt_key sha256 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
+crypt_key sha256 128 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7
+
+crypt_key sha256 0 std- "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
+crypt_key sha256 256 std- "xxx\n" 042aea10a0f14f2d391373599be69d53a75dde9951fc3d3cd10b6100aa7a9f24
+crypt_key sha256 128 std- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" \
+ 2a42b97084779dcedf2c66405c5d296c
+crypt_key sha256 256 stdin "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
+crypt_key sha256 0 stdin "xxx\n" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
+
+# with keyfile, hash is ignored
+crypt_key ripemd160 256 file /dev/zero 0000000000000000000000000000000000000000000000000000000000000000
+crypt_key sha256 256 file /dev/zero 0000000000000000000000000000000000000000000000000000000000000000
+crypt_key unknown* 256 file /dev/zero 0000000000000000000000000000000000000000000000000000000000000000
+
+# limiting key
+crypt_key sha256:20 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b4580588000000000000000000000000
+crypt_key sha256:32 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860
+
+crypt_key sha256: 256 failpwd "xxx" x
+crypt_key sha256:xx 256 failpwd "xxx" x
+
+# key file, 80 chars
+echo -n -e "0123456789abcdef\n\x01\x00\x03\xff\xff\r\xff\xff\n\r" \
+ "2352j3rkjhadcfasc823rqaw7e1 3dq sdq3d 2dkjqw3h2=====" >$KEY_FILE
+KEY_FILE_HEX="303132333435363738396162636465660a010003ffff0dffff0a0d20323335326a33726b6a686164636661736338323372716177376531203364712073647133"
+
+
+# ignore hash if keyfile is specified
+crypt_key ripemd160 256 file $KEY_FILE ${KEY_FILE_HEX:0:64}
+crypt_key sha256 256 file $KEY_FILE ${KEY_FILE_HEX:0:64}
+crypt_key sha256 128 file $KEY_FILE ${KEY_FILE_HEX:0:32}
+crypt_key sha256 512 file $KEY_FILE $KEY_FILE_HEX
+
+# stdin can be limited
+crypt_key plain 128 cat /dev/zero 00000000000000000000000000000000 16
+crypt_key plain 128 cat /dev/zero 00000000000000000000000000000000 17
+
+# read key only up to \n
+crypt_key plain 128 cat $KEY_FILE ${KEY_FILE_HEX:0:28}0000 14
+
+# read full key, ignore keyfile length
+crypt_key plain 128 cat- $KEY_FILE ${KEY_FILE_HEX:0:32}
+crypt_key plain 128 cat- $KEY_FILE ${KEY_FILE_HEX:0:32} 14
+
+# but do not ignore hash if keysgfile is "-"
+crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5
+crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5 0
+crypt_key sha256 128 cat- $KEY_FILE f3b827c8a6f159ad8c8ed5bd5ab3f8c5 80
+crypt_key sha256 128 cat- $KEY_FILE a82c9227cc54c7475620ce85ba1fca1e 14
+crypt_key sha256 128 cat- $KEY_FILE 7df3f4a41a33805596be85c781cac3b4 14 2
+crypt_key sha256 128 cat- $KEY_FILE ebbe65a178e886ddbb778e0a5538db72 40 40
+
+# limiting plain (no hash)
+crypt_key plain 256 pwd "xxxxxxxx" 7878787878787878000000000000000000000000000000000000000000000000
+crypt_key plain:2 256 pwd "xxxxxxxx" 7878000000000000000000000000000000000000000000000000000000000000
+crypt_key plain:9 256 failpwd "xxxxxxxx" x
+
+crypt_key sha256 128 cat $KEY_FILE a82c9227cc54c7475620ce85ba1fca1e 14
+crypt_key sha256:14 128 cat $KEY_FILE a82c9227cc54c7475620ce85ba1f0000 14
+
+crypt_key sha256 128 pwd "0123456789abcdef" 9f9f5111f7b27a781f1f1ddde5ebc2dd 16
+crypt_key sha256 128 pwd "0123456789abcdef" 1be2e452b46d7a0d9656bbb1f768e824 4
+crypt_key sha256 128 pwd "0123" 1be2e452b46d7a0d9656bbb1f768e824 4
+
+# Test list of various hash algorithms
+crypt_key sha1 256 pwd "0123456789abcdef" fe5567e8d769550852182cdf69d74bb16dff8e295e4b6077d6d3fc73e7fe33b0
+crypt_key sha224 256 pwd "0123456789abcdef" 7330215f6741fd2bacbd3658681a70f65e2e90a02887989018974ce83775a568
+crypt_key sha256 256 pwd "0123456789abcdef" 9f9f5111f7b27a781f1f1ddde5ebc2dd2b796bfc7365c9c28b548e564176929f
+crypt_key sha384 256 pwd "0123456789abcdef" fc6304023487cb6f85ac80e47817760c6b153c02da46c6429649e963b031e525
+crypt_key sha512 256 pwd "0123456789abcdef" 1c043fbe4bca7c7920dae536c680fd44c15d71ec12cd82a2a9491b0043b57f4d
+crypt_key ripemd160 256 pwd "0123456789abcdef" edf4e38018cd71dd489b9c1e54b32054eb42dfad9fdcc22d629d756391a24982
+crypt_key whirlpool 256 pwd "0123456789abcdef" b21fc274d47d79ba45f94d67077f0846f75a7acc1a4dc560eacca300179cc142
+crypt_key sha3-224 256 pwd "0123456789abcdef" bbb7d56cc80a8c80e907f7d9240edc0be264aa173266b30918bc1065d59a9388
+crypt_key sha3-256 256 pwd "0123456789abcdef" a5df4caae9fdb5dbacf667075b709a2f30a115c43168af332062b42d4b0da01f
+crypt_key sha3-384 256 pwd "0123456789abcdef" 56f351f754c418892eab4009e5f85c8d5436a591014503563e9395b895526413
+crypt_key sha3-512 256 pwd "0123456789abcdef" 59d06155d25dffdb982729de8dce9d7855ca094d8bab8124b347c40668477056
+crypt_key sm3 256 pwd "0123456789abcdef" a34fdd8e843802b31a262dce5b1f501bed68ef81520de14b39657aecffaf8a86
+crypt_key stribog512 256 pwd "0123456789abcdef" ab1284a64c2325c0ad52494e696df9aa9b92e701605a9a1258b58be08e8240ea
+
+cleanup 0
diff --git a/tests/reencryption-compat-test b/tests/reencryption-compat-test
new file mode 100755
index 0000000..453831d
--- /dev/null
+++ b/tests/reencryption-compat-test
@@ -0,0 +1,489 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+REENC_BIN=$CRYPTSETUP
+REENC="$REENC_BIN reencrypt"
+FAST_PBKDF="--pbkdf-force-iterations 1000 --pbkdf pbkdf2"
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+DEV_NAME=reenc9768
+DEV_NAME2=reenc1273
+IMG=reenc-data
+IMG_HDR=$IMG.hdr
+HEADER_LUKS2_PV=blkid-luks2-pv.img
+ORIG_IMG=reenc-data-orig
+DEV_LINK="reenc-test-link"
+KEY1=key1
+PWD1="93R4P4pIqAH8"
+PWD2="1cND4319812f"
+PWD3="1-9Qu5Ejfnqv"
+
+MNT_DIR=./mnt_luks
+START_DIR=$(pwd)
+FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
+
+function fips_mode()
+{
+ [ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
+}
+
+function del_scsi_device()
+{
+ rmmod scsi_debug >/dev/null 2>&1
+ sleep 2
+}
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove --retry $DEV_NAME
+ [ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
+ rm -f $IMG $IMG_HDR $ORIG_IMG $KEY1 $HEADER_LUKS2_PV $DEV_LINK >/dev/null 2>&1
+ umount $MNT_DIR > /dev/null 2>&1
+ rmdir $MNT_DIR > /dev/null 2>&1
+ LOOPDEV1=""
+ del_scsi_device
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cd $START_DIR
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function add_scsi_device() {
+ del_scsi_device
+ if [ -d /sys/module/scsi_debug ] ; then
+ echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
+ exit 77
+ fi
+ modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "This kernel seems to not support proper scsi_debug module, test skipped."
+ exit 77
+ fi
+
+ sleep 2
+ SCSI_DEV="/dev/"$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ [ -b $SCSI_DEV ] || fail "Cannot find $SCSI_DEV."
+}
+
+function open_crypt() # $1 pwd, $2 hdr
+{
+ if [ -n "$2" ] ; then
+ echo "$1" | $CRYPTSETUP luksOpen $LOOPDEV1 $DEV_NAME --header $2 || fail
+ elif [ -n "$1" ] ; then
+ echo "$1" | $CRYPTSETUP luksOpen $LOOPDEV1 $DEV_NAME || fail
+ else
+ $CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV1 $DEV_NAME || fail
+ fi
+}
+
+function wipe_dev() # $1 dev
+{
+ dd if=/dev/zero of=$1 bs=256k >/dev/null 2>&1
+}
+
+function wipe() # $1 pass
+{
+ open_crypt $1
+ wipe_dev /dev/mapper/$DEV_NAME
+ udevadm settle >/dev/null 2>&1
+ $CRYPTSETUP luksClose $DEV_NAME || fail
+}
+
+function prepare() # $1 dev1_siz
+{
+ remove_mapping
+
+ dd if=/dev/zero of=$IMG bs=1k count=$1 >/dev/null 2>&1
+ LOOPDEV1=$(losetup -f 2>/dev/null)
+ [ -z "$LOOPDEV1" ] && fail "No free loop device"
+ losetup $LOOPDEV1 $IMG
+
+ if [ ! -e $KEY1 ]; then
+ dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
+ fi
+}
+
+function check_hash_dev() # $1 dev, $2 hash
+{
+ HASH=$(sha256sum $1 | cut -d' ' -f 1)
+ [ $HASH != "$2" ] && fail "HASH differs ($HASH)"
+}
+
+function check_hash() # $1 pwd, $2 hash, $3 hdr
+{
+ open_crypt $1 $3
+ check_hash_dev /dev/mapper/$DEV_NAME $2
+ $CRYPTSETUP remove $DEV_NAME || fail
+}
+
+function backup_orig()
+{
+ sync
+ losetup -d $LOOPDEV1
+ cp $IMG $ORIG_IMG
+ losetup $LOOPDEV1 $IMG
+}
+
+function rollback()
+{
+ sync
+ losetup -d $LOOPDEV1
+ cp $ORIG_IMG $IMG
+ losetup $LOOPDEV1 $IMG
+}
+
+function check_slot() #space separated list of ENABLED key slots
+{
+ local _KS0=DISABLED
+ local _KS1=$_KS0 _KS2=$_KS0 _KS3=$_KS0 _KS4=$_KS0 _KS5=$_KS0 _KS6=$_KS0 _KS7=$_KS0
+ local _tmp
+
+ for _tmp in $*; do
+ eval _KS$_tmp=ENABLED
+ done
+
+ local _out=$($CRYPTSETUP luksDump $LOOPDEV1 | grep -e "Key Slot" | cut -d ' ' -f 4)
+
+ local _i=0
+ for _tmp in $_out; do
+ eval local _orig="\${_KS${_i}}"
+ if [ "$_tmp" != "$_orig" ]; then
+ echo "Keyslot $_i is $_tmp, expected result: $_orig"
+ return 1
+ fi
+ _i=$[_i+1]
+ done
+
+ return 0
+}
+
+function simple_scsi_reenc()
+{
+ echo -n "$1"
+ echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF $SCSI_DEV || fail
+
+ echo $PWD1 | $CRYPTSETUP luksOpen $SCSI_DEV $DEV_NAME || fail
+ HASH=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
+ $CRYPTSETUP luksClose $DEV_NAME || fail
+
+ echo $PWD1 | $REENC -q $FAST_PBKDF $SCSI_DEV || fail
+
+ echo $PWD1 | $CRYPTSETUP luksOpen $SCSI_DEV $DEV_NAME || fail
+ check_hash_dev /dev/mapper/$DEV_NAME $HASH
+ $CRYPTSETUP luksClose $DEV_NAME || fail
+}
+
+function mount_and_test() {
+ test -d $MNT_DIR || mkdir -p $MNT_DIR
+ mount $@ $MNT_DIR 2>/dev/null || {
+ echo -n "failed to mount [SKIP]"
+ return 0
+ }
+ rm $MNT_DIR/* 2>/dev/null
+ cd $MNT_DIR
+
+ if [ "${REENC:0:1}" != "/" ] ; then
+ MNT_REENC=$START_DIR/$REENC
+ else
+ MNT_REENC=$REENC
+ fi
+
+ echo $PWD2 | $MNT_REENC $LOOPDEV1 -q --use-fsync --use-directio --write-log $FAST_PBKDF || return 1
+ cd $START_DIR
+ umount $MNT_DIR
+ echo -n [OK]
+}
+
+function test_logging_tmpfs() {
+ echo -n "[tmpfs]"
+ mount_and_test -t tmpfs none -o size=$[25*1024*1024] || return 1
+ echo
+}
+
+function test_logging() {
+ echo -n "$1:"
+ for img in $(ls img_fs*img.xz) ; do
+ wipefs -a $SCSI_DEV > /dev/null
+ echo -n "[${img%.img.xz}]"
+ xz -d -c $img | dd of=$SCSI_DEV bs=4k >/dev/null 2>&1
+ mount_and_test $SCSI_DEV || return 1
+ done
+ echo
+}
+
+function check_blkid() {
+ xz -dkf $HEADER_LUKS2_PV.xz
+ if ! $($CRYPTSETUP --version | grep -q "BLKID"); then
+ HAVE_BLKID=0
+ elif $(blkid -p -n crypto_LUKS $HEADER_LUKS2_PV >/dev/null 2>&1); then
+ HAVE_BLKID=1
+ else
+ HAVE_BLKID=0
+ fi
+}
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ ! -x "$REENC_BIN" ] && skip "Cannot find $REENC_BIN, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+command -v wipefs >/dev/null || skip "Cannot find wipefs, test skipped."
+
+# REENCRYPTION tests
+
+HASH1=b69dae56a14d1a8314ed40664c4033ea0a550eea2673e04df42a66ac6b9faf2c
+HASH2=d85ef2a08aeac2812a648deb875485a6e3848fc3d43ce4aa380937f08199f86b
+HASH3=e4e5749032a5163c45125eccf3e8598ba5ed840df442c97e1d5ad4ad84359605
+HASH4=2daeb1f36095b44b318410b3f4e8b5d989dcc7bb023d1426c492dab0a3053e74
+HASH5=5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef
+
+echo "[1] Reencryption"
+prepare 8192
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -s 128 -c aes-cbc-plain $FAST_PBKDF --align-payload 4096 $LOOPDEV1 || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q -s 256 $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q -s 256 -c aes-xts-plain64 -h sha256 $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --use-directio $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --volume-key-file /dev/urandom $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q -s 512 --volume-key-file /dev/urandom $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+$CRYPTSETUP --type luks1 luksDump $LOOPDEV1 > /dev/null || fail
+
+echo "[2] Reencryption with data shift"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -c aes-cbc-essiv:sha256 -s 128 $FAST_PBKDF --align-payload 2048 $LOOPDEV1 || fail
+wipe $PWD1
+echo $PWD1 | $REENC $LOOPDEV1 -q -s 256 --reduce-device-size 1024S $FAST_PBKDF || fail
+check_hash $PWD1 $HASH2
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF || fail
+check_hash $PWD1 $HASH2
+$CRYPTSETUP --type luks1 luksDump $LOOPDEV1 > /dev/null || fail
+
+echo "[3] Reencryption with keyfile"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -d $KEY1 -c aes-cbc-essiv:sha256 -s 128 $FAST_PBKDF --align-payload 4096 $LOOPDEV1 || fail
+wipe
+check_hash "" $HASH1
+echo $PWD1 | $CRYPTSETUP -q luksAddKey -d $KEY1 $LOOPDEV1 $FAST_PBKDF || fail
+$REENC $LOOPDEV1 -d $KEY1 $FAST_PBKDF -q 2>/dev/null && fail
+$REENC $LOOPDEV1 -d $KEY1 -S 0 $FAST_PBKDF -q || fail
+check_hash "" $HASH1
+check_slot 0 || fail "Only keyslot 0 expected to be enabled"
+$REENC $LOOPDEV1 -d $KEY1 $FAST_PBKDF -q || fail
+# FIXME echo $PWD1 | $REENC ...
+
+echo "[4] Encryption of not yet encrypted device"
+# Encrypt without size reduction must not allow header device same as data device
+wipe_dev $LOOPDEV1
+echo $PWD1 | $REENC $LOOPDEV1 --type luks1 --new --header $LOOPDEV1 -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $LOOPDEV1 2>/dev/null && fail
+ln -s $LOOPDEV1 $DEV_LINK || fail
+echo $PWD1 | $REENC $LOOPDEV1 --type luks1 --new --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $LOOPDEV1 2>/dev/null && fail
+rm -f $DEV_LINK || fail
+echo $PWD1 | $REENC $IMG --type luks1 --new --header $IMG -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
+ln -s $IMG $DEV_LINK || fail
+echo $PWD1 | $REENC $IMG --type luks1 --new --header $DEV_LINK -q $FAST_PBKDF_ARGON 2>/dev/null && fail
+$CRYPTSETUP isLUKS $IMG 2>/dev/null && fail
+
+if [ ! fips_mode ]; then
+# well, movin' zeroes :-)
+OFFSET=2048
+SIZE=$(blockdev --getsz $LOOPDEV1)
+dmsetup create $DEV_NAME2 --table "0 $(($SIZE - $OFFSET)) linear $LOOPDEV1 0" || fail
+check_hash_dev /dev/mapper/$DEV_NAME2 $HASH3
+dmsetup remove --retry $DEV_NAME2 || fail
+echo $PWD1 | $REENC $LOOPDEV1 -c aes-cbc-essiv:sha256 -s 128 --new --type luks1 --reduce-device-size "$OFFSET"S -q $FAST_PBKDF || fail
+check_hash $PWD1 $HASH3
+$CRYPTSETUP --type luks1 luksDump $LOOPDEV1 > /dev/null || fail
+# 64MiB + 1 KiB
+prepare 65537
+OFFSET=131072
+SIZE=$(blockdev --getsz $LOOPDEV1)
+wipe_dev $LOOPDEV1
+dmsetup create $DEV_NAME2 --table "0 $(($SIZE - $OFFSET)) linear $LOOPDEV1 0" || fail
+check_hash_dev /dev/mapper/$DEV_NAME2 $HASH5
+dmsetup remove --retry $DEV_NAME2 || fail
+echo $PWD1 | $REENC $LOOPDEV1 -c aes-cbc-essiv:sha256 -s 128 --new --type luks1 --reduce-device-size "$OFFSET"S -q $FAST_PBKDF || fail
+check_hash $PWD1 $HASH5
+$CRYPTSETUP --type luks1 luksDump $LOOPDEV1 > /dev/null || fail
+prepare 8192
+OFFSET=4096
+echo fake | $REENC $LOOPDEV1 -d $KEY1 --new --type luks1 --reduce-device-size "$OFFSET"S -q $FAST_PBKDF || fail
+$CRYPTSETUP open --test-passphrase $LOOPDEV1 -d $KEY1 || fail
+wipe_dev $LOOPDEV1
+fi
+
+echo "[5] Reencryption using specific keyslot"
+echo $PWD2 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 1 $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 2 $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 3 $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 4 $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD1" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 5 $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD2" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 6 $LOOPDEV1 || fail
+echo -e "$PWD2\n$PWD3" | $CRYPTSETUP -q luksAddKey $FAST_PBKDF -S 7 $LOOPDEV1 || fail
+backup_orig
+echo $PWD2 | $REENC $FAST_PBKDF -S 0 -q $LOOPDEV1 || fail
+check_slot 0 || fail "Only keyslot 0 expected to be enabled"
+wipe $PWD2
+rollback
+echo $PWD1 | $REENC $FAST_PBKDF -S 1 -q $LOOPDEV1 || fail
+check_slot 1 || fail "Only keyslot 1 expected to be enabled"
+wipe $PWD1
+rollback
+echo $PWD2 | $REENC $FAST_PBKDF -S 6 -q $LOOPDEV1 || fail
+check_slot 6 || fail "Only keyslot 6 expected to be enabled"
+wipe $PWD2
+rollback
+echo $PWD3 | $REENC $FAST_PBKDF -S 7 -q $LOOPDEV1 || fail
+check_slot 7 || fail "Only keyslot 7 expected to be enabled"
+wipe $PWD3
+rollback
+echo $PWD3 | $REENC $FAST_PBKDF -S 8 -q $LOOPDEV1 2>/dev/null && fail
+$CRYPTSETUP luksDump $LOOPDEV1 > /dev/null || fail
+
+echo "[6] Reencryption using all active keyslots"
+echo -e "$PWD2\n$PWD1\n$PWD2\n$PWD1\n$PWD2\n$PWD1\n$PWD2\n$PWD3" | $REENC -q $LOOPDEV1 $FAST_PBKDF || fail
+check_slot 0 1 2 3 4 5 6 7 || fail "All keyslots expected to be enabled"
+
+echo "[7] Reencryption of block devices with different block size"
+add_scsi_device sector_size=512 dev_size_mb=8
+simple_scsi_reenc "[512 sector]"
+add_scsi_device sector_size=4096 dev_size_mb=8
+simple_scsi_reenc "[4096 sector]"
+add_scsi_device sector_size=512 physblk_exp=3 dev_size_mb=8
+simple_scsi_reenc "[4096/512 sector]"
+echo "[OK]"
+
+echo "[8] Header only reencryption (hash and iteration time)"
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 --hash sha512 $FAST_PBKDF $LOOPDEV1 || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key || fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --pbkdf-force-iterations 999 2>/dev/null && fail
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha256 --pbkdf-force-iterations 1001 || fail
+check_hash $PWD1 $HASH1
+[ "$($CRYPTSETUP luksDump $LOOPDEV1 | grep -A1 -m1 "Key Slot 0" | grep Iterations: | sed -e 's/[[:space:]]\+Iterations:\ \+//g')" -eq 1001 ] || fail
+[ "$($CRYPTSETUP luksDump $LOOPDEV1 | grep -m1 "Hash spec:" | cut -f2)" = "sha256" ] || fail
+echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha512 $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+[ "$($CRYPTSETUP luksDump $LOOPDEV1 | grep -A1 -m1 "Key Slot 0" | grep Iterations: | sed -e 's/[[:space:]]\+Iterations:\ \+//g')" -eq 1000 ] || fail
+echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key $FAST_PBKDF || fail
+check_hash $PWD1 $HASH1
+$CRYPTSETUP --type luks1 luksDump $LOOPDEV1 > /dev/null || fail
+
+echo "[9] Test log I/Os on various underlying block devices"
+prepare 8192
+echo $PWD2 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF $LOOPDEV1 || fail
+add_scsi_device sector_size=512 dev_size_mb=32
+test_logging "[512 sector]" || fail
+add_scsi_device sector_size=4096 dev_size_mb=32
+test_logging "[4096 sector]" || fail
+add_scsi_device sector_size=512 dev_size_mb=32 physblk_exp=3
+test_logging "[4096/512 sector]" || fail
+test_logging_tmpfs || fail
+
+if [ ! fips_mode ]; then
+echo "[10] Removal of encryption"
+prepare 8192
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF $LOOPDEV1 || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --decrypt || fail
+check_hash_dev $LOOPDEV1 $HASH4
+
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 -S5 $FAST_PBKDF $LOOPDEV1 || fail
+wipe $PWD1
+check_hash $PWD1 $HASH1
+echo $PWD1 | $REENC $LOOPDEV1 -q --decrypt || fail
+check_hash_dev $LOOPDEV1 $HASH4
+
+echo "[11] Detached header - adding encryption/reencryption/decryption"
+prepare 8192
+check_hash_dev $IMG $HASH4
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --header $IMG_HDR --new --type luks1
+check_hash $PWD1 $HASH4 $IMG_HDR
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --header $IMG_HDR || fail
+check_hash $PWD1 $HASH4 $IMG_HDR
+echo $PWD1 | $REENC $LOOPDEV1 -q --header $IMG_HDR --decrypt || fail
+check_hash_dev $IMG $HASH4
+# existing header of zero size
+cat /dev/null >$IMG_HDR
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --header $IMG_HDR --new --type luks1
+check_hash $PWD1 $HASH4 $IMG_HDR
+$CRYPTSETUP isLuks $LOOPDEV1 && fail
+$CRYPTSETUP isLuks $IMG_HDR || fail
+
+echo "[12] Prevent nested encryption"
+prepare 8192
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF $LOOPDEV1 || fail
+
+#data device is already LUKS device (prevent nested encryption)
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 --reduce-device-size 1024S 2>/dev/null && fail
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 --header $IMG_HDR 2>/dev/null && fail
+test -f $IMG_HDR && fail
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks2 --reduce-device-size 2048S 2>/dev/null && fail
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks2 --header $IMG_HDR 2>/dev/null && fail
+test -f $IMG_HDR && fail
+
+wipe_dev $LOOPDEV1
+echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 --header $IMG_HDR $FAST_PBKDF $LOOPDEV1 || fail
+
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 --header $IMG_HDR 2>/dev/null && fail
+echo $PWD1 | $REENC $LOOPDEV1 -q $FAST_PBKDF --new --type luks2 --header $IMG_HDR 2>/dev/null && fail
+
+check_blkid
+if [ "$HAVE_BLKID" -gt 0 ]; then
+ echo "[13] Prevent nested encryption of broken LUKS device"
+ rm -f $IMG_HDR
+ wipe_dev $LOOPDEV1
+ xz -dkf $HEADER_LUKS2_PV.xz
+ # broken header
+ echo $PWD1 | $REENC --header $HEADER_LUKS2_PV $LOOPDEV1 -q $FAST_PBKDF --new --type luks1 2>/dev/null && fail
+ $CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
+ # broken device
+ echo $PWD1 | $REENC $HEADER_LUKS2_PV -q $FAST_PBKDF --new --type luks1 --reduce-device-size 1024S 2>/dev/null && fail
+ $CRYPTSETUP isLuks $HEADER_LUKS2_PV && fail
+ # broken data device only
+ echo $PWD1 | $REENC --header $IMG_HDR $HEADER_LUKS2_PV -q $FAST_PBKDF --new --type luks1 2>/dev/null && fail
+ test -f $IMG_HDR && fail
+fi
+fi # if [ ! fips_mode ]
+
+remove_mapping
+exit 0
diff --git a/tests/run-all-symbols b/tests/run-all-symbols
new file mode 100755
index 0000000..775d5bb
--- /dev/null
+++ b/tests/run-all-symbols
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+DIR=../.libs
+FILE=$DIR/libcryptsetup.so
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+test -d $DIR || fail "Directory $DIR is missing."
+test -f $FILE || skip "WARNING: Shared $FILE is missing, test skipped."
+
+./all-symbols-test $FILE $@
diff --git a/tests/ssh-test-plugin b/tests/ssh-test-plugin
new file mode 100755
index 0000000..5b3966e
--- /dev/null
+++ b/tests/ssh-test-plugin
@@ -0,0 +1,204 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && {
+ TOKEN_PATH="./fake_token_path.so"
+ [ ! -f $TOKEN_PATH ] && { echo "Please compile $TOKEN_PATH."; exit 77; }
+ export LD_PRELOAD=$TOKEN_PATH
+ CRYPTSETUP_PATH=".."
+}
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+CRYPTSETUP_SSH=$CRYPTSETUP_PATH/cryptsetup-ssh
+IMG="ssh_test.img"
+MAP="sshtest"
+USER="sshtest"
+PASSWD="sshtest1"
+PASSWD2="sshtest2"
+SSH_OPTIONS="-o StrictHostKeyChecking=no"
+
+SSH_SERVER="localhost"
+SSH_PATH="/home/$USER/keyfile"
+SSH_KEY_PATH="$HOME/sshtest-key"
+
+FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_SSH_VALGRIND=../.libs/cryptsetup-ssh
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+[ -z "$srcdir" ] && srcdir="."
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
+ rm -f $IMG >/dev/null 2>&1
+}
+
+function remove_user()
+{
+ id -u $USER >/dev/null 2>&1 && userdel -r -f $USER >/dev/null 2>&1
+ rm -f $SSH_KEY_PATH "$SSH_KEY_PATH.pub" >/dev/null 2>&1
+}
+
+function create_user()
+{
+ id -u $USER >/dev/null 2>&1
+ [ $? -eq 0 ] && skip "User account $USER exists, aborting."
+ [ -f $SSH_KEY_PATH ] && skip "SSH key $SSH_KEY_PATH already exists, aborting."
+
+ useradd -m $USER -p $(openssl passwd $PASSWD) || skip "Failed to add user for SSH plugin test."
+
+ ssh-keygen -f $SSH_KEY_PATH -q -N "" >/dev/null 2>&1
+ [ $? -ne 0 ] && remove_user && skip "Failed to create SSH key."
+}
+
+function ssh_check()
+{
+ # try to use netcat to check port 22
+ nc -zv $SSH_SERVER 22 >/dev/null 2>&1 || skip "SSH server does not seem to be running, skipping."
+}
+
+function bin_check()
+{
+ command -v $1 >/dev/null || skip "WARNING: test require $1 binary, test skipped."
+}
+
+function ssh_setup()
+{
+ # copy the ssh key
+ [ -d "/home/$USER/.ssh" ] || mkdir /home/$USER/.ssh
+ touch /home/$USER/.ssh/authorized_keys
+
+ cat $SSH_KEY_PATH.pub >> /home/$USER/.ssh/authorized_keys
+ [ $? -ne 0 ] && remove_user && fail "Failed to copy SSH key."
+
+ # make sure /home/sshtest/.ssh and /home/sshtest/.ssh/authorized_keys have correct permissions
+ chown -R $USER:$USER /home/$USER/.ssh
+ chmod 700 /home/$USER/.ssh
+ chmod 644 /home/$USER/.ssh/authorized_keys
+
+ # try to ssh and also create keyfile
+ ssh -i $SSH_KEY_PATH $SSH_OPTIONS -o BatchMode=yes -n $USER@$SSH_SERVER "echo -n $PASSWD > $SSH_PATH" >/dev/null 2>&1
+ [ $? -ne 0 ] && remove_user && fail "Failed to connect using SSH."
+}
+
+function fail()
+{
+ echo "[FAILED]"
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ remove_user
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ [ ! -f $CRYPTSETUP_SSH_VALGRIND ] && fail "Unable to get location of cryptsetup-ssh executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+function valgrind_run_ssh()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_SSH_VALGRIND} "$@"
+}
+
+format()
+{
+ dd if=/dev/zero of=$IMG bs=1M count=32 >/dev/null 2>&1
+
+ echo $PASSWD | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $IMG --force-password -q
+ [ $? -ne 0 ] && fail "Format failed."
+
+ echo -e "$PASSWD\n$PASSWD2" | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $IMG -q
+ [ $? -ne 0 ] && fail "Add key failed."
+}
+
+check_dump()
+{
+ dump=$1
+ keyslot=$2
+
+ token=$(echo "$dump" | grep Tokens -A 1 | tail -1 | cut -d: -f2 | tr -d "\t\n ")
+ [ "$token" = "ssh" ] || fail " token check from dump failed."
+
+ server=$(echo "$dump" | grep ssh_server | cut -d: -f2 | tr -d "\t\n ")
+ [ "$server" = $SSH_SERVER ] || fail " server check from dump failed."
+
+ user=$(echo "$dump" | grep ssh_user | cut -d: -f2 | tr -d "\t\n ")
+ [ "$user" = "$USER" ] || fail " user check from dump failed."
+
+ path=$(echo "$dump" | grep ssh_path | cut -d: -f2 | tr -d "\t\n ")
+ [ "$path" = "$SSH_PATH" ] || fail " path check from dump failed."
+
+ key_path=$(echo "$dump" | grep ssh_key_path | cut -d: -f2 | tr -d "\t\n ")
+ [ "$key_path" = "$SSH_KEY_PATH" ] || fail " key_path check from dump failed."
+
+ keyslot_dump=$(echo "$dump" | grep Keyslot: | cut -d: -f2 | tr -d "\t\n ")
+ [ "$keyslot_dump" = "$keyslot" ] || fail " keyslot check from dump failed."
+}
+
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run && CRYPTSETUP_SSH=valgrind_run_ssh
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+
+# Prevent running dangerous useradd operation by default
+[ -z "$RUN_SSH_PLUGIN_TEST" ] && skip "WARNING: Variable RUN_SSH_PLUGIN_TEST must be defined, test skipped."
+
+bin_check nc
+bin_check useradd
+bin_check ssh
+bin_check ssh-keygen
+bin_check sshpass
+bin_check openssl
+
+format
+
+echo -n "Adding SSH token: "
+
+ssh_check
+create_user
+ssh_setup
+
+$CRYPTSETUP_SSH add $IMG --ssh-server $SSH_SERVER --ssh-user $USER --ssh-path $SSH_PATH --ssh-keypath $SSH_KEY_PATH
+[ $? -ne 0 ] && fail "Failed to add SSH token to $IMG"
+
+out=$($CRYPTSETUP luksDump $IMG)
+check_dump "$out" 0
+echo "[OK]"
+
+echo -n "Activating using SSH token: "
+
+$CRYPTSETUP luksOpen --token-only --disable-external-tokens -r $IMG $MAP && fail "Tokens should be disabled"
+$CRYPTSETUP luksOpen -r $IMG $MAP -q >/dev/null 2>&1 <&-
+[ $? -ne 0 ] && fail "Failed to open $IMG using SSH token"
+echo "[OK]"
+
+# Remove the newly added token and test adding with --key-slot
+$CRYPTSETUP token remove --token-id 0 $IMG || fail "Failed to remove token"
+
+echo -n "Adding SSH token with --key-slot: "
+
+$CRYPTSETUP_SSH add $IMG --ssh-server $SSH_SERVER --ssh-user $USER --ssh-path $SSH_PATH --ssh-keypath $SSH_KEY_PATH --key-slot 1
+[ $? -ne 0 ] && fail "Failed to add SSH token to $IMG"
+
+out=$($CRYPTSETUP luksDump $IMG)
+check_dump "$out" 1
+echo "[OK]"
+
+remove_mapping
+remove_user
diff --git a/tests/systemd-test-plugin b/tests/systemd-test-plugin
new file mode 100755
index 0000000..5f37324
--- /dev/null
+++ b/tests/systemd-test-plugin
@@ -0,0 +1,150 @@
+#!/bin/bash
+
+CC="cc"
+
+PASSWD="tpm2_test"
+PASSWD2="tpm2_test2"
+FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
+IMG=systemd_token_test.img
+MAP="systemd_tpm2_test"
+
+function bin_check()
+{
+ command -v $1 >/dev/null || skip "WARNING: test require $1 binary, test skipped."
+}
+
+function cleanup() {
+ [ -S $SWTPM_STATE_DIR/ctrl.sock ] && {
+ # shutdown TPM via control socket
+ swtpm_ioctl -s --unix $SWTPM_STATE_DIR/ctrl.sock
+ sleep 1
+ }
+
+ # if graceful shutdown was successful, pidfile should be deleted
+ # if it is still present, we forcefully kill the process
+ [ -f "$SWTPM_PIDFILE" ] && {
+ kill -9 $(cat $SWTPM_PIDFILE) >/dev/null 2>&1
+ }
+
+ [ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
+
+ rm -f $SWTPM_PIDFILE >/dev/null 2>&1
+ rm -rf $SWTPM_STATE_DIR >/dev/null 2>&1
+ rm -f $IMG >/dev/null 2>&1
+}
+
+function fail()
+{
+ echo "[FAILED]"
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ cleanup
+ exit 77
+}
+
+# Prevent downloading and compiling systemd by default
+[ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] && skip "WARNING: Variable RUN_SYSTEMD_PLUGIN_TEST must be defined, test skipped."
+
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+bin_check swtpm
+bin_check swtpm_ioctl
+
+CRYPTENROLL_LD_PRELOAD=""
+
+# if CRYPTSETUP_PATH is defined, we run against installed binaries,
+# otherwise we compile systemd tokens from source
+[ -z "$CRYPTSETUP_PATH" ] && {
+ bin_check git
+ bin_check meson
+ bin_check ninja
+ bin_check pkgconf
+
+ TOKEN_PATH=fake_token_path.so
+ [ -f $TOKEN_PATH ] || skip "Please compile $TOKEN_PATH."
+ INSTALL_PATH=$(pwd)/external-tokens/install
+ make -C .. install DESTDIR=$INSTALL_PATH
+ PC_FILE="$(find $INSTALL_PATH -name 'libcryptsetup.pc')"
+ sed -i "s/^prefix=/prefix=${INSTALL_PATH//\//\\\/}/g" "$PC_FILE"
+ export PKG_CONFIG_PATH=$(dirname $PC_FILE)
+
+ # systemd build system misses libcryptsetup.h if it is installed in non-default path
+ export CFLAGS="${CFLAGS:-} $(pkgconf --cflags libcryptsetup)"
+
+ SYSTEMD_PATH=$(pwd)/external-tokens/systemd
+ CRYPTSETUP_PATH=$(pwd)/..
+ SYSTEMD_CRYPTENROLL=$SYSTEMD_PATH/build/systemd-cryptenroll
+
+ mkdir -p $SYSTEMD_PATH
+ [ "$(ls -A $SYSTEMD_PATH)" ] || git clone --depth=1 https://github.com/systemd/systemd.git $SYSTEMD_PATH
+ cd $SYSTEMD_PATH
+ meson -D tpm2=true -D libcryptsetup=true -D libcryptsetup-plugins=true build/ || skip "Failed to configure systemd via meson, some dependencies are probably missing."
+ ninja -C build/ systemd-cryptenroll libcryptsetup-token-systemd-tpm2.so || skip "Failed to build systemd."
+
+ cd $CRYPTSETUP_PATH/tests
+ cp $SYSTEMD_PATH/build/libcryptsetup-token-*.so ../.libs/
+ cp $SYSTEMD_PATH/build/src/shared/*.so ../.libs/
+
+ export LD_PRELOAD="${LD_PRELOAD-}:$CRYPTSETUP_PATH/tests/$TOKEN_PATH"
+ CRYPTENROLL_LD_PRELOAD="$CRYPTSETUP_PATH/.libs/libcryptsetup.so"
+}
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+
+[ -z "$SYSTEMD_CRYPTENROLL" ] && {
+ bin_check systemd-cryptenroll
+ SYSTEMD_CRYPTENROLL="systemd-cryptenroll"
+}
+
+[ -z "$TPM_PATH" ] && {
+ echo "Setting up virtual TPM using swtpm..."
+ SWTPM_PIDFILE=$(mktemp /tmp/systemd_swtpm_pid.XXXXXX)
+ SWTPM_STATE_DIR=$(mktemp -d /tmp/systemd_swtpm_state.XXXXXX)
+ modprobe tpm_vtpm_proxy || skip "Failed to load tpm_vtpm_proxy kernel module, required for emulated TPM."
+ SWTPM_LOG=$(swtpm chardev --vtpm-proxy --tpm2 --tpmstate dir=$SWTPM_STATE_DIR -d --pid file=$SWTPM_PIDFILE --ctrl type=unixio,path=$SWTPM_STATE_DIR/ctrl.sock)
+ TPM_PATH=$(echo $SWTPM_LOG | grep -Eo '/dev/tpm([0-9])+' | sed 's/tpm/tpmrm/')
+ [ -z "$TPM_PATH" ] && skip "No TPM_PATH set and swtpm failed, test skipped."
+ sleep 1
+ echo "Virtual TPM set up at $TPM_PATH"
+}
+
+FAKE_TPM_PATH="$(pwd)/fake_systemd_tpm_path.so"
+[ -f $FAKE_TPM_PATH ] || skip "Please compile $FAKE_TPM_PATH."
+export LD_PRELOAD="$LD_PRELOAD:$FAKE_TPM_PATH"
+
+export TPM_PATH=$TPM_PATH
+echo "TPM path is $TPM_PATH"
+
+dd if=/dev/zero of=$IMG bs=1M count=32 >/dev/null 2>&1
+echo $PASSWD | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $IMG --force-password -q
+
+echo "Enrolling the device to TPM 2 using systemd-cryptenroll.."
+LD_PRELOAD="$LD_PRELOAD:$CRYPTENROLL_LD_PRELOAD" PASSWORD="$PASSWD" $SYSTEMD_CRYPTENROLL $IMG --tpm2-device=$TPM_PATH >/dev/null 2>&1
+
+$CRYPTSETUP luksDump $IMG | grep -q "tpm2-blob" || fail "Failed to dump $IMG using systemd_tpm2 token (no tpm2-blob in output)."
+echo "Activating the device via TPM2 external token.."
+$CRYPTSETUP open --token-only $IMG $MAP >/dev/null 2>&1 || fail "Failed to open $IMG using systemd_tpm2 token."
+$CRYPTSETUP close $MAP >/dev/null 2>&1 || fail "Failed to close $MAP."
+
+echo "Adding passphrase via TPM2 token.."
+echo $PASSWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF_OPT $IMG --force-password -q --token-only >/dev/null 2>&1 || fail "Failed to add passphrase by tpm2 token."
+echo $PASSWD2 | $CRYPTSETUP open $IMG --test-passphrase --disable-external-tokens >/dev/null 2>&1 || fail "Failed to test passphrase added by tpm2 token."
+
+echo "Exporting and removing TPM2 token.."
+EXPORTED_TOKEN=$($CRYPTSETUP token export $IMG --token-id 0)
+$CRYPTSETUP token remove $IMG --token-id 0
+$CRYPTSETUP open $IMG --test-passphrase --token-only >/dev/null 2>&1 && fail "Activating without passphrase should fail after TPM2 token removal."
+
+echo "Re-importing TPM2 token.."
+echo $EXPORTED_TOKEN | $CRYPTSETUP token import $IMG --token-id 0 || fail "Failed to re-import deleted token."
+$CRYPTSETUP open $IMG --test-passphrase --token-only >/dev/null 2>&1 || fail "Failed to activate after re-importing deleted token."
+
+cleanup
+exit 0
diff --git a/tests/tcrypt-compat-test b/tests/tcrypt-compat-test
new file mode 100755
index 0000000..c0fc50a
--- /dev/null
+++ b/tests/tcrypt-compat-test
@@ -0,0 +1,223 @@
+#!/bin/bash
+
+# check tcrypt images parsing
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
+TST_DIR=tcrypt-images
+MAP=tctst
+PASSWORD="aaaaaaaaaaaa"
+PASSWORD_HIDDEN="bbbbbbbbbbbb"
+PASSWORD_72C="aaaaaaaaaaaabbbbbbbbbbbbccccccccccccddddddddddddeeeeeeeeeeeeffffffffffff"
+PIM=1234
+
+CRYPTSETUP_VALGRIND=../.libs/cryptsetup
+CRYPTSETUP_LIB_VALGRIND=../.libs
+
+[ -z "$srcdir" ] && srcdir="."
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
+ [ -b /dev/mapper/"$MAP"_1 ] && dmsetup remove --retry "$MAP"_1
+ [ -b /dev/mapper/"$MAP"_2 ] && dmsetup remove --retry "$MAP"_2
+ rm -rf $TST_DIR
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo " [FAILED]"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ remove_mapping
+ exit 77
+}
+
+function test_one() # cipher mode keysize rm_pattern
+{
+ $CRYPTSETUP benchmark -c "$1-$2" -s "$3" >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "$1-$2 [N/A]"
+ IMGS=$(ls $TST_DIR/[tv]c* | grep "$4")
+ [ -n "$IMGS" ] && rm $IMGS
+ #echo $IMGS
+ else
+ echo "$1-$2 [OK]"
+ fi
+}
+
+function test_kdf() # hash
+{
+ $CRYPTSETUP benchmark -h "$1" >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ echo "pbkdf2-$1 [N/A]"
+ IMGS=$(ls $TST_DIR/[tv]c* | grep "$1")
+ [ -n "$IMGS" ] && rm $IMGS
+ else
+ echo "pbkdf2-$1 [OK]"
+ fi
+}
+
+function get_HASH_CIPHER() # filename
+{
+ # speed up the test by limiting options for hash and (first) cipher
+ HASH=$(echo $file | cut -d'-' -f3)
+ CIPHER=$(echo $file | cut -d'-' -f5)
+}
+
+function test_required()
+{
+ command -v blkid >/dev/null || skip "blkid tool required, test skipped."
+
+ echo "REQUIRED KDF TEST"
+ test_kdf sha256
+ test_kdf sha512
+ test_kdf ripemd160
+ test_kdf whirlpool
+ test_kdf stribog512
+
+ echo "REQUIRED CIPHERS TEST"
+ test_one aes cbc 256 cbc-aes
+ test_one aes lrw 384 lrw-aes
+ test_one aes xts 512 xts-aes
+
+ test_one twofish ecb 256 twofish
+ test_one twofish cbc 256 cbc-twofish
+ test_one twofish lrw 384 lrw-twofish
+ test_one twofish xts 512 xts-twofish
+
+ test_one serpent ecb 256 serpent
+ test_one serpent cbc 256 cbc-serpent
+ test_one serpent lrw 384 lrw-serpent
+ test_one serpent xts 512 xts-serpent
+
+ test_one blowfish cbc 256 blowfish
+
+ test_one des3_ede cbc 192 des3_ede
+ test_one cast5 cbc 128 cast5
+
+ test_one camellia xts 512 camellia
+ test_one kuznyechik xts 512 kuznyechik
+
+ ls $TST_DIR/[tv]c* >/dev/null 2>&1 || skip "No remaining images, test skipped."
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
+ export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
+}
+
+export LANG=C
+[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
+[ ! -d $TST_DIR ] && tar xJf $srcdir/tcrypt-images.tar.xz --no-same-owner
+
+[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
+
+test_required
+
+echo "HEADER CHECK"
+for file in $(ls $TST_DIR/[tv]c_* $TST_DIR/vcpim_* $TST_DIR/sys_[tv]c_*) ; do
+ echo -n " $file"
+ PIM_OPT=""
+ [[ $file =~ vcpim.* ]] && PIM_OPT="--veracrypt-pim $PIM"
+ SYS_OPT=""
+ [[ $file =~ sys_.* ]] && SYS_OPT="--tcrypt-system"
+ get_HASH_CIPHER $file
+ echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h $HASH -c $CIPHER $file >/dev/null || fail
+ if [[ $file =~ .*-sha512-xts-aes$ ]] ; then
+ echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h sha512 -c aes $file >/dev/null || fail
+ echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h xxxx $file 2>/dev/null && fail
+ echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h sha512 -c xxx $file 2>/dev/null && fail
+ fi
+ echo " [OK]"
+done
+
+echo "HEADER CHECK (TCRYPT only)"
+for file in $(ls $TST_DIR/vc_* $TST_DIR/vcpim_*) ; do
+ echo -n " $file"
+ PIM_OPT=""
+ [[ $file =~ vcpim.* ]] && PIM_OPT="--veracrypt-pim $PIM"
+ get_HASH_CIPHER $file
+ echo $PASSWORD | $CRYPTSETUP tcryptDump --disable-veracrypt $PIM_OPT -h $HASH -c $CIPHER $file >/dev/null 2>&1 && fail
+ echo " [OK]"
+done
+
+echo "HEADER CHECK (HIDDEN)"
+for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
+ echo -n " $file (hidden)"
+ get_HASH_CIPHER $file
+ echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptDump --tcrypt-hidden -h $HASH -c $CIPHER $file >/dev/null || fail
+ echo " [OK]"
+done
+
+echo "HEADER KEYFILES CHECK"
+for file in $(ls $TST_DIR/[tv]ck_*) ; do
+ echo -n " $file"
+ PWD=$PASSWORD
+ [[ $file =~ vck_1_nopw.* ]] && PWD=""
+ [[ $file =~ vck_1_pw72.* ]] && PWD=$PASSWORD_72C
+ get_HASH_CIPHER $file
+ echo $PWD | $CRYPTSETUP tcryptDump -d $TST_DIR/keyfile1 -d $TST_DIR/keyfile2 -h $HASH -c $CIPHER $file >/dev/null || fail
+ echo " [OK]"
+done
+
+
+if [ $(id -u) != 0 ]; then
+ echo "WARNING: You must be root to run activation part of test, test skipped."
+ remove_mapping
+ exit 0
+fi
+
+echo "ACTIVATION FS UUID CHECK"
+for file in $(ls $TST_DIR/[tv]c_* $TST_DIR/vcpim_* $TST_DIR/sys_[tv]c_*) ; do
+ echo -n " $file"
+ PIM_OPT=""
+ [[ $file =~ vcpim.* ]] && PIM_OPT="--veracrypt-pim $PIM"
+ SYS_OPT=""
+ [[ $file =~ sys_.* ]] && SYS_OPT="--tcrypt-system"
+ get_HASH_CIPHER $file
+ out=$(echo $PASSWORD | $CRYPTSETUP tcryptOpen $SYS_OPT $PIM_OPT -r -h $HASH -c $CIPHER $file $MAP 2>&1)
+ ret=$?
+ [ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
+ [ $ret -ne 0 ] && fail
+ $CRYPTSETUP status $MAP >/dev/null || fail
+ $CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
+ UUID=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
+ $CRYPTSETUP remove $MAP || fail
+ [ "$UUID" != "DEAD-BABE" ] && fail "UUID check failed."
+ echo " [OK]"
+done
+
+echo "ACTIVATION FS UUID (HIDDEN) CHECK"
+for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
+ echo -n " $file"
+ get_HASH_CIPHER $file
+ out=$(echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptOpen -r -h $HASH -c $CIPHER $file $MAP --tcrypt-hidden 2>&1)
+ ret=$?
+ [ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
+ [ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
+ [ $ret -ne 0 ] && fail
+ UUID=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
+ $CRYPTSETUP remove $MAP || fail
+ [ "$UUID" != "CAFE-BABE" ] && fail "UUID check failed."
+ echo " [OK]"
+done
+
+remove_mapping
+exit 0
diff --git a/tests/tcrypt-images.tar.xz b/tests/tcrypt-images.tar.xz
new file mode 100644
index 0000000..1841870
--- /dev/null
+++ b/tests/tcrypt-images.tar.xz
Binary files differ
diff --git a/tests/test_utils.c b/tests/test_utils.c
new file mode 100644
index 0000000..97c62a0
--- /dev/null
+++ b/tests/test_utils.c
@@ -0,0 +1,950 @@
+/*
+ * cryptsetup library API test utilities
+ *
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2009-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <libdevmapper.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#ifdef KERNEL_KEYRING
+# include <linux/keyctl.h>
+# include <sys/syscall.h>
+#endif
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h>
+#endif
+#include <linux/loop.h>
+
+#include "api_test.h"
+#include "libcryptsetup.h"
+
+#ifndef LOOP_CONFIGURE
+#define LOOP_CONFIGURE 0x4C0A
+struct loop_config {
+ __u32 fd;
+ __u32 block_size;
+ struct loop_info64 info;
+ __u64 __reserved[8];
+};
+#endif
+
+static char last_error[256];
+static char global_log[4096];
+static uint32_t t_dm_crypt_flags = 0;
+
+char *THE_LOOP_DEV = NULL;
+int _debug = 0;
+int global_lines = 0;
+int _quit = 0;
+int _verbose = 0;
+uint64_t t_dev_offset = 0;
+
+static void (*_cleanup)(void);
+
+void register_cleanup(void (*cleanup)(void))
+{
+ _cleanup = cleanup;
+}
+
+void check_ok(int status, int line, const char *func)
+{
+ if (status) {
+ printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, last_error);
+ _cleanup();
+ exit(-1);
+ }
+}
+
+void check_ok_return(int status, int line, const char *func)
+{
+ if (status < 0) {
+ printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, last_error);
+ _cleanup();
+ exit(-1);
+ }
+}
+
+void check_ko(int status, int line, const char *func)
+{
+ if (status >= 0) {
+ printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, last_error);
+ _cleanup();
+ exit(-1);
+ } else if (_verbose)
+ printf(" => errno %d, errmsg: %s\n", status, last_error);
+}
+
+void check_equal(int line, const char *func, int64_t x, int64_t y)
+{
+ printf("FAIL line %d [%s]: expected equal values differs: %"
+ PRIi64 " != %" PRIi64 "\n", line, func, x, y);
+ _cleanup();
+ exit(-1);
+}
+
+void check_ge_equal(int line, const char *func, int64_t x, int64_t y)
+{
+ printf("FAIL line %d [%s]: expected greater or equal values differs: %"
+ PRIi64 " < %" PRIi64 "\n", line, func, x, y);
+ _cleanup();
+ exit(-1);
+}
+
+void check_null(int line, const char *func, const void *x)
+{
+ if (x) {
+ printf("FAIL line %d [%s]: expected NULL value: %p\n", line, func, x);
+ _cleanup();
+ exit(-1);
+ }
+}
+
+void check_notnull(int line, const char *func, const void *x)
+{
+ if (!x) {
+ printf("FAIL line %d [%s]: expected not NULL value: %p\n", line, func, x);
+ _cleanup();
+ exit(-1);
+ }
+}
+
+void xlog(const char *msg, const char *tst, const char *func, int line, const char *txt)
+{
+ if (_verbose) {
+ if (txt)
+ printf(" [%s,%s:%d] %s [%s]\n", msg, func, line, tst, txt);
+ else
+ printf(" [%s,%s:%d] %s\n", msg, func, line, tst);
+ }
+ if (_quit) {
+ if (_verbose)
+ printf("Interrupted by a signal.\n");
+ _cleanup();
+ exit(-1);
+ }
+}
+
+int t_device_size(const char *device, uint64_t *size)
+{
+ int devfd, r = 0;
+
+ devfd = open(device, O_RDONLY);
+ if(devfd == -1)
+ return -EINVAL;
+
+ if (ioctl(devfd, BLKGETSIZE64, size) < 0)
+ r = -EINVAL;
+ close(devfd);
+ return r;
+}
+
+int t_set_readahead(const char *device, unsigned value)
+{
+ int devfd, r = 0;
+
+ devfd = open(device, O_RDONLY);
+ if(devfd == -1)
+ return -EINVAL;
+
+ if (ioctl(devfd, BLKRASET, value) < 0)
+ r = -EINVAL;
+ close(devfd);
+ return r;
+}
+
+int fips_mode(void)
+{
+ int fd;
+ char buf = 0;
+
+ fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
+
+ if (fd < 0)
+ return 0;
+
+ if (read(fd, &buf, 1) != 1)
+ buf = '0';
+
+ close(fd);
+
+ return (buf == '1');
+}
+
+/*
+ * Creates dm-linear target over the test loop device. Offset is held in
+ * global variables so that size can be tested whether it fits into remaining
+ * size of the loop device or not
+ */
+int create_dmdevice_over_loop(const char *dm_name, const uint64_t size)
+{
+ char cmd[128];
+ int r;
+ uint64_t r_size;
+
+ if (t_device_size(THE_LOOP_DEV, &r_size) < 0 || r_size <= t_dev_offset || !size)
+ return -1;
+ if ((r_size - t_dev_offset) < size) {
+ printf("No enough space on backing loop device\n.");
+ return -2;
+ }
+ r = snprintf(cmd, sizeof(cmd),
+ "dmsetup create %s --table \"0 %" PRIu64 " linear %s %" PRIu64 "\"",
+ dm_name, size, THE_LOOP_DEV, t_dev_offset);
+ if (r < 0 || (size_t)r >= sizeof(cmd))
+ return -3;
+
+ if (!(r = _system(cmd, 1)))
+ t_dev_offset += size;
+ return r;
+}
+
+__attribute__((format(printf, 3, 4)))
+static int _snprintf(char **r_ptr, size_t *r_remains, const char *format, ...)
+{
+ int len, r = 0;
+ va_list argp;
+
+ assert(r_remains);
+ assert(r_ptr);
+
+ va_start(argp, format);
+
+ len = vsnprintf(*r_ptr, *r_remains, format, argp);
+ if (len < 0 || (size_t)len >= *r_remains) {
+ r = -EINVAL;
+ } else {
+ *r_ptr += len;
+ *r_remains -= len;
+ }
+
+ va_end(argp);
+
+ return r;
+}
+
+int dmdevice_error_io(const char *dm_name,
+ const char *dm_device,
+ const char *error_device,
+ uint64_t data_offset,
+ uint64_t offset,
+ uint64_t length,
+ error_io_info ei)
+{
+ char str[256], cmd[384];
+ int r;
+ uint64_t dev_size;
+ size_t remains;
+ char *ptr;
+
+ if (t_device_size(dm_device, &dev_size) < 0 || !length)
+ return -1;
+
+ dev_size >>= TST_SECTOR_SHIFT;
+
+ if (dev_size <= offset)
+ return -1;
+
+ if (ei == ERR_REMOVE) {
+ r = snprintf(cmd, sizeof(cmd),
+ "dmsetup load %s --table \"0 %" PRIu64 " linear %s %" PRIu64 "\"",
+ dm_name, dev_size, THE_LOOP_DEV, data_offset);
+ if (r < 0 || (size_t)r >= sizeof(str))
+ return -3;
+
+ if ((r = _system(cmd, 1)))
+ return r;
+
+ r = snprintf(cmd, sizeof(cmd), "dmsetup resume %s", dm_name);
+ if (r < 0 || (size_t)r >= sizeof(cmd))
+ return -3;
+
+ return _system(cmd, 1);
+ }
+
+ if ((dev_size - offset) < length) {
+ printf("Not enough space on target device\n.");
+ return -2;
+ }
+
+ remains = sizeof(str);
+ ptr = str;
+
+ if (offset) {
+ r = _snprintf(&ptr, &remains,
+ "0 %" PRIu64 " linear %s %" PRIu64 "\n",
+ offset, THE_LOOP_DEV, data_offset);
+ if (r < 0)
+ return r;
+ }
+ r = _snprintf(&ptr, &remains, "%" PRIu64 " %" PRIu64 " delay ",
+ offset, length);
+ if (r < 0)
+ return r;
+
+ if (ei == ERR_RW || ei == ERR_RD) {
+ r = _snprintf(&ptr, &remains, "%s 0 0",
+ error_device);
+ if (r < 0)
+ return r;
+ if (ei == ERR_RD) {
+ r = _snprintf(&ptr, &remains, " %s %" PRIu64 " 0",
+ THE_LOOP_DEV, data_offset + offset);
+ if (r < 0)
+ return r;
+ }
+ } else if (ei == ERR_WR) {
+ r = _snprintf(&ptr, &remains, "%s %" PRIu64 " 0 %s 0 0",
+ THE_LOOP_DEV, data_offset + offset, error_device);
+ if (r < 0)
+ return r;
+ }
+
+ if (dev_size > (offset + length)) {
+ r = _snprintf(&ptr, &remains,
+ "\n%" PRIu64 " %" PRIu64 " linear %s %" PRIu64,
+ offset + length, dev_size - offset - length, THE_LOOP_DEV,
+ data_offset + offset + length);
+ if (r < 0)
+ return r;
+ }
+
+ /*
+ * Hello darkness, my old friend...
+ *
+ * On few old distributions there's issue with
+ * processing multiline tables via dmsetup load --table.
+ * This workaround passes on all systems we run tests on.
+ */
+ r = snprintf(cmd, sizeof(cmd), "dmsetup load %s <<EOF\n%s\nEOF", dm_name, str);
+ if (r < 0 || (size_t)r >= sizeof(cmd))
+ return -3;
+
+ if ((r = _system(cmd, 1)))
+ return r;
+
+ r = snprintf(cmd, sizeof(cmd), "dmsetup resume %s", dm_name);
+ if (r < 0 || (size_t)r >= sizeof(cmd))
+ return -3;
+
+ if ((r = _system(cmd, 1)))
+ return r;
+
+ return t_set_readahead(dm_device, 0);
+}
+
+// Get key from kernel dm mapping table using dm-ioctl
+int get_key_dm(const char *name, char *buffer, unsigned int buffer_size)
+{
+ struct dm_task *dmt;
+ struct dm_info dmi;
+ uint64_t start, length;
+ char *target_type, *key, *params;
+ int r = -EINVAL;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+ goto out;
+ if (!dm_task_set_name(dmt, name))
+ goto out;
+ if (!dm_task_run(dmt))
+ goto out;
+ if (!dm_task_get_info(dmt, &dmi))
+ goto out;
+ if (!dmi.exists)
+ goto out;
+
+ dm_get_next_target(dmt, NULL, &start, &length, &target_type, &params);
+ if (!target_type || strcmp(target_type, "crypt") != 0)
+ goto out;
+
+ (void)strsep(&params, " "); /* rcipher */
+ key = strsep(&params, " ");
+
+ if (buffer_size <= strlen(key))
+ goto out;
+
+ strncpy(buffer, key, buffer_size);
+ r = 0;
+out:
+ if (dmt)
+ dm_task_destroy(dmt);
+
+ return r;
+}
+
+int prepare_keyfile(const char *name, const char *passphrase, int size)
+{
+ int fd, r;
+
+ fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR);
+ if (fd != -1) {
+ r = write(fd, passphrase, size);
+ close(fd);
+ } else
+ r = 0;
+
+ return r == size ? 0 : 1;
+}
+
+// Decode key from its hex representation
+int crypt_decode_key(char *key, const char *hex, unsigned int size)
+{
+ char buffer[3];
+ char *endp;
+ unsigned int i;
+
+ buffer[2] = '\0';
+
+ for (i = 0; i < size; i++) {
+ buffer[0] = *hex++;
+ buffer[1] = *hex++;
+
+ key[i] = (unsigned char)strtoul(buffer, &endp, 16);
+
+ if (endp != &buffer[2])
+ return -1;
+ }
+
+ if (*hex != '\0')
+ return -1;
+
+ return 0;
+}
+
+void global_log_callback(int level, const char *msg, void *usrptr __attribute__((unused)))
+{
+ size_t len;
+
+ if (_debug) {
+ if (level == CRYPT_LOG_DEBUG)
+ fprintf(stdout, "# %s", msg);
+ else
+ fprintf(stdout, "%s", msg);
+ }
+
+ if (level <= CRYPT_LOG_DEBUG)
+ return;
+
+ len = strlen(global_log);
+
+ if (len + strlen(msg) > sizeof(global_log)) {
+ printf("Log buffer is too small, fix the test.\n");
+ return;
+ }
+
+ strncat(global_log, msg, sizeof(global_log) - len);
+ global_lines++;
+ if (level == CRYPT_LOG_ERROR) {
+ len = strlen(msg);
+ if (len > sizeof(last_error))
+ len = sizeof(last_error);
+ strncpy(last_error, msg, sizeof(last_error));
+ last_error[len-1] = '\0';
+ }
+}
+
+void reset_log(void)
+{
+ memset(global_log, 0, sizeof(global_log));
+ memset(last_error, 0, sizeof(last_error));
+ global_lines = 0;
+}
+
+int _system(const char *command, int warn)
+{
+ int r;
+ if (_debug)
+ printf("Running system: %s\n", command);
+ if ((r=system(command)) < 0 && warn)
+ printf("System command failed: %s", command);
+ return r;
+}
+
+static int _keyring_check(void)
+{
+#ifdef KERNEL_KEYRING
+ return syscall(__NR_request_key, "logon", "dummy", NULL, 0) == -1l && errno != ENOSYS;
+#else
+ return 0;
+#endif
+}
+
+static int t_dm_satisfies_version(unsigned target_maj, unsigned target_min, unsigned target_patch,
+ unsigned actual_maj, unsigned actual_min, unsigned actual_patch)
+{
+ if (actual_maj > target_maj)
+ return 1;
+ if (actual_maj == target_maj && actual_min > target_min)
+ return 1;
+ if (actual_maj == target_maj && actual_min == target_min && actual_patch >= target_patch)
+ return 1;
+ return 0;
+}
+
+static void t_dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
+ unsigned crypt_min, unsigned crypt_patch)
+{
+ unsigned dm_maj = 0, dm_min = 0, dm_patch = 0;
+
+ if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3) {
+ dm_maj = 0;
+ dm_min = 0;
+ dm_patch = 0;
+ }
+
+ if (t_dm_satisfies_version(1, 2, 0, crypt_maj, crypt_min, 0))
+ t_dm_crypt_flags |= T_DM_KEY_WIPE_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 10, 0, crypt_maj, crypt_min, 0))
+ t_dm_crypt_flags |= T_DM_LMK_SUPPORTED;
+
+ if (t_dm_satisfies_version(4, 20, 0, dm_maj, dm_min, 0))
+ t_dm_crypt_flags |= T_DM_SECURE_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 8, 0, crypt_maj, crypt_min, 0))
+ t_dm_crypt_flags |= T_DM_PLAIN64_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 11, 0, crypt_maj, crypt_min, 0))
+ t_dm_crypt_flags |= T_DM_DISCARDS_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 13, 0, crypt_maj, crypt_min, 0))
+ t_dm_crypt_flags |= T_DM_TCW_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 14, 0, crypt_maj, crypt_min, 0)) {
+ t_dm_crypt_flags |= T_DM_SAME_CPU_CRYPT_SUPPORTED;
+ t_dm_crypt_flags |= T_DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED;
+ }
+
+ if (t_dm_satisfies_version(1, 18, 1, crypt_maj, crypt_min, crypt_patch) && _keyring_check())
+ t_dm_crypt_flags |= T_DM_KERNEL_KEYRING_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 17, 0, crypt_maj, crypt_min, crypt_patch)) {
+ t_dm_crypt_flags |= T_DM_SECTOR_SIZE_SUPPORTED;
+ t_dm_crypt_flags |= T_DM_CAPI_STRING_SUPPORTED;
+ }
+
+ if (t_dm_satisfies_version(1, 19, 0, crypt_maj, crypt_min, crypt_patch))
+ t_dm_crypt_flags |= T_DM_BITLK_EBOIV_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 20, 0, crypt_maj, crypt_min, crypt_patch))
+ t_dm_crypt_flags |= T_DM_BITLK_ELEPHANT_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 22, 0, crypt_maj, crypt_min, crypt_patch))
+ t_dm_crypt_flags |= T_DM_CRYPT_NO_WORKQUEUE_SUPPORTED;
+}
+
+static void t_dm_set_verity_compat(const char *dm_version __attribute__((unused)),
+ unsigned verity_maj,
+ unsigned verity_min,
+ unsigned verity_patch __attribute__((unused)))
+{
+ if (verity_maj > 0)
+ t_dm_crypt_flags |= T_DM_VERITY_SUPPORTED;
+ else
+ return;
+ /*
+ * ignore_corruption, restart_on corruption is available since 1.2 (kernel 4.1)
+ * ignore_zero_blocks since 1.3 (kernel 4.5)
+ * (but some dm-verity targets 1.2 don't support it)
+ * FEC is added in 1.3 as well.
+ */
+ if (t_dm_satisfies_version(1, 3, 0, verity_maj, verity_min, 0)) {
+ t_dm_crypt_flags |= T_DM_VERITY_ON_CORRUPTION_SUPPORTED;
+ t_dm_crypt_flags |= T_DM_VERITY_FEC_SUPPORTED;
+ }
+
+ if (t_dm_satisfies_version(1, 5, 0, verity_maj, verity_min, verity_patch))
+ t_dm_crypt_flags |= T_DM_VERITY_SIGNATURE_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch))
+ t_dm_crypt_flags |= T_DM_VERITY_PANIC_CORRUPTION_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 9, 0, verity_maj, verity_min, verity_patch))
+ t_dm_crypt_flags |= T_DM_VERITY_TASKLETS_SUPPORTED;
+}
+
+static void t_dm_set_integrity_compat(const char *dm_version __attribute__((unused)),
+ unsigned integrity_maj __attribute__((unused)),
+ unsigned integrity_min __attribute__((unused)),
+ unsigned integrity_patch __attribute__((unused)))
+{
+ if (integrity_maj > 0)
+ t_dm_crypt_flags |= T_DM_INTEGRITY_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 2, 0, integrity_maj, integrity_min, integrity_patch))
+ t_dm_crypt_flags |= T_DM_INTEGRITY_RECALC_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 3, 0, integrity_maj, integrity_min, integrity_patch))
+ t_dm_crypt_flags |= T_DM_INTEGRITY_BITMAP_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch))
+ t_dm_crypt_flags |= T_DM_INTEGRITY_FIX_PADDING_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 6, 0, integrity_maj, integrity_min, integrity_patch))
+ t_dm_crypt_flags |= T_DM_INTEGRITY_DISCARDS_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 7, 0, integrity_maj, integrity_min, integrity_patch))
+ t_dm_crypt_flags |= T_DM_INTEGRITY_FIX_HMAC_SUPPORTED;
+
+ if (t_dm_satisfies_version(1, 8, 0, integrity_maj, integrity_min, integrity_patch))
+ t_dm_crypt_flags |= T_DM_INTEGRITY_RESET_RECALC_SUPPORTED;
+}
+
+int t_dm_check_versions(void)
+{
+ struct dm_task *dmt;
+ struct dm_versions *target, *last_target;
+ char dm_version[16];
+ int r = 1;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
+ goto out;
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version)))
+ goto out;
+
+ target = dm_task_get_versions(dmt);
+ do {
+ last_target = target;
+ if (!strcmp("crypt", target->name)) {
+ t_dm_set_crypt_compat(dm_version,
+ (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ } else if (!strcmp("verity", target->name)) {
+ t_dm_set_verity_compat(dm_version,
+ (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ } else if (!strcmp("integrity", target->name)) {
+ t_dm_set_integrity_compat(dm_version,
+ (unsigned)target->version[0],
+ (unsigned)target->version[1],
+ (unsigned)target->version[2]);
+ }
+ target = VOIDP_CAST(struct dm_versions *)((char *) target + target->next);
+ } while (last_target != target);
+
+ r = 0;
+out:
+ if (dmt)
+ dm_task_destroy(dmt);
+
+ return r;
+}
+
+int t_dm_crypt_keyring_support(void)
+{
+ return t_dm_crypt_flags & T_DM_KERNEL_KEYRING_SUPPORTED;
+}
+
+int t_dm_crypt_cpu_switch_support(void)
+{
+ return t_dm_crypt_flags & (T_DM_SAME_CPU_CRYPT_SUPPORTED |
+ T_DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED);
+}
+
+int t_dm_crypt_discard_support(void)
+{
+ return t_dm_crypt_flags & T_DM_DISCARDS_SUPPORTED;
+}
+
+int t_dm_integrity_resize_support(void)
+{
+ return t_dm_crypt_flags & T_DM_INTEGRITY_RESIZE_SUPPORTED;
+}
+
+int t_dm_integrity_recalculate_support(void)
+{
+ return t_dm_crypt_flags & T_DM_INTEGRITY_RECALC_SUPPORTED;
+}
+
+int t_dm_capi_string_supported(void)
+{
+ return t_dm_crypt_flags & T_DM_CAPI_STRING_SUPPORTED;
+}
+
+/* loop helpers */
+
+#define LOOP_DEV_MAJOR 7
+
+#ifndef LO_FLAGS_AUTOCLEAR
+#define LO_FLAGS_AUTOCLEAR 4
+#endif
+
+#ifndef LOOP_CTL_GET_FREE
+#define LOOP_CTL_GET_FREE 0x4C82
+#endif
+
+#ifndef LOOP_SET_CAPACITY
+#define LOOP_SET_CAPACITY 0x4C07
+#endif
+
+int loop_device(const char *loop)
+{
+ struct stat st;
+
+ if (!loop)
+ return 0;
+
+ if (stat(loop, &st) || !S_ISBLK(st.st_mode) ||
+ major(st.st_rdev) != LOOP_DEV_MAJOR)
+ return 0;
+
+ return 1;
+}
+
+static char *crypt_loop_get_device_old(void)
+{
+ char dev[64];
+ int i, loop_fd;
+ struct loop_info64 lo64 = {0};
+
+ for (i = 0; i < 256; i++) {
+ sprintf(dev, "/dev/loop%d", i);
+
+ loop_fd = open(dev, O_RDONLY);
+ if (loop_fd < 0)
+ return NULL;
+
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &lo64) &&
+ errno == ENXIO) {
+ close(loop_fd);
+ return strdup(dev);
+ }
+ close(loop_fd);
+ }
+
+ return NULL;
+}
+
+static char *crypt_loop_get_device(void)
+{
+ char dev[64];
+ int i, loop_fd;
+ struct stat st;
+
+ loop_fd = open("/dev/loop-control", O_RDONLY);
+ if (loop_fd < 0)
+ return crypt_loop_get_device_old();
+
+ i = ioctl(loop_fd, LOOP_CTL_GET_FREE);
+ if (i < 0) {
+ close(loop_fd);
+ return NULL;
+ }
+ close(loop_fd);
+
+ if (sprintf(dev, "/dev/loop%d", i) < 0)
+ return NULL;
+
+ if (stat(dev, &st) || !S_ISBLK(st.st_mode))
+ return NULL;
+
+ return strdup(dev);
+}
+
+int loop_attach(char **loop, const char *file, int offset,
+ int autoclear, int *readonly)
+{
+ struct loop_config config = {0};
+ char *lo_file_name;
+ int loop_fd = -1, file_fd = -1, r = 1;
+ int fallback = 0;
+
+ *loop = NULL;
+
+ file_fd = open(file, (*readonly ? O_RDONLY : O_RDWR) | O_EXCL);
+ if (file_fd < 0 && (errno == EROFS || errno == EACCES) && !*readonly) {
+ *readonly = 1;
+ file_fd = open(file, O_RDONLY | O_EXCL);
+ }
+ if (file_fd < 0)
+ goto out;
+
+ config.fd = file_fd;
+
+ lo_file_name = (char*)config.info.lo_file_name;
+ lo_file_name[LO_NAME_SIZE-1] = '\0';
+ strncpy(lo_file_name, file, LO_NAME_SIZE-1);
+ config.info.lo_offset = offset;
+ if (autoclear)
+ config.info.lo_flags |= LO_FLAGS_AUTOCLEAR;
+
+ while (loop_fd < 0) {
+ *loop = crypt_loop_get_device();
+ if (!*loop)
+ goto out;
+
+ loop_fd = open(*loop, *readonly ? O_RDONLY : O_RDWR);
+ if (loop_fd < 0)
+ goto out;
+ if (ioctl(loop_fd, LOOP_CONFIGURE, &config) < 0) {
+ if (errno == EINVAL || errno == ENOTTY) {
+ free(*loop);
+ *loop = NULL;
+
+ close(loop_fd);
+ loop_fd = -1;
+
+ /* kernel doesn't support LOOP_CONFIGURE */
+ fallback = 1;
+ break;
+ }
+ if (errno != EBUSY)
+ goto out;
+ free(*loop);
+ *loop = NULL;
+
+ close(loop_fd);
+ loop_fd = -1;
+ }
+ }
+
+ if (fallback)
+ {
+ while (loop_fd < 0) {
+ *loop = crypt_loop_get_device();
+ if (!*loop)
+ goto out;
+
+ loop_fd = open(*loop, *readonly ? O_RDONLY : O_RDWR);
+ if (loop_fd < 0)
+ goto out;
+ if (ioctl(loop_fd, LOOP_SET_FD, file_fd) < 0) {
+ if (errno != EBUSY)
+ goto out;
+ free(*loop);
+ *loop = NULL;
+
+ close(loop_fd);
+ loop_fd = -1;
+ }
+ }
+
+ if (ioctl(loop_fd, LOOP_SET_STATUS64, &config.info) < 0) {
+ (void)ioctl(loop_fd, LOOP_CLR_FD, 0);
+ goto out;
+ }
+ }
+
+ /* Verify that autoclear is really set */
+ if (autoclear) {
+ memset(&config.info, 0, sizeof(config.info));
+ if (ioctl(loop_fd, LOOP_GET_STATUS64, &config.info) < 0 ||
+ !(config.info.lo_flags & LO_FLAGS_AUTOCLEAR)) {
+ (void)ioctl(loop_fd, LOOP_CLR_FD, 0);
+ goto out;
+ }
+ }
+
+ r = 0;
+out:
+ if (r && loop_fd >= 0)
+ close(loop_fd);
+ if (file_fd >= 0)
+ close(file_fd);
+ if (r && *loop) {
+ free(*loop);
+ *loop = NULL;
+ }
+ return r ? -1 : loop_fd;
+}
+
+int loop_detach(const char *loop)
+{
+ int loop_fd = -1, r = 1;
+
+ loop_fd = open(loop, O_RDONLY);
+ if (loop_fd < 0)
+ return 1;
+
+ if (!ioctl(loop_fd, LOOP_CLR_FD, 0))
+ r = 0;
+
+ close(loop_fd);
+ return r;
+}
+
+int t_get_devno(const char *name, dev_t *devno)
+{
+ char path[PATH_MAX];
+ int r;
+ struct stat st;
+
+ r = snprintf(path, sizeof(path), DMDIR "%s", name);
+ if (r < 0 || (size_t)r >= sizeof(path))
+ return 1;
+
+ if (stat(path, &st) || !S_ISBLK(st.st_mode))
+ return 1;
+
+ *devno = st.st_rdev;
+
+ return 0;
+}
+
+static int _read_uint64(const char *sysfs_path, uint64_t *value)
+{
+ char tmp[64] = {0};
+ int fd, r;
+
+ if ((fd = open(sysfs_path, O_RDONLY)) < 0)
+ return 0;
+ r = read(fd, tmp, sizeof(tmp));
+ close(fd);
+
+ if (r <= 0)
+ return 0;
+
+ if (sscanf(tmp, "%" PRIu64, value) != 1)
+ return 0;
+
+ return 1;
+}
+
+static int _sysfs_get_uint64(int major, int minor, uint64_t *value, const char *attr)
+{
+ char path[PATH_MAX];
+
+ if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/%s",
+ major, minor, attr) < 0)
+ return 0;
+
+ return _read_uint64(path, value);
+}
+
+int t_device_size_by_devno(dev_t devno, uint64_t *retval)
+{
+ if (!_sysfs_get_uint64(major(devno), minor(devno), retval, "size"))
+ return 1;
+
+ *retval *= 512;
+ return 0;
+}
diff --git a/tests/unit-utils-crypt.c b/tests/unit-utils-crypt.c
new file mode 100644
index 0000000..4ab3c96
--- /dev/null
+++ b/tests/unit-utils-crypt.c
@@ -0,0 +1,259 @@
+/*
+ * cryptsetup crypto name and hex conversion helper test vectors
+ *
+ * Copyright (C) 2022-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils_crypt.h"
+#include "libcryptsetup.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+
+/*
+ * Cryptsetup/dm-crypt algorithm naming conversion test
+ */
+struct mode_test_vector {
+ const char *input;
+ const char *cipher;
+ const char *mode;
+ int keys;
+};
+static struct mode_test_vector mode_test_vectors[] = {
+ { "aes-xts-plain", "aes", "xts-plain", 1 },
+ { "aes-xts-plain64", "aes", "xts-plain64", 1 },
+ { "aes-cbc-plain", "aes", "cbc-plain", 1 },
+ { "aes-cbc-plain64", "aes", "cbc-plain64", 1 },
+ { "aes-cbc-essiv:sha256", "aes", "cbc-essiv:sha256", 1 },
+ { "aes", "aes", "cbc-plain", 1 },
+ { "twofish", "twofish", "cbc-plain", 1 },
+ { "cipher_null", "cipher_null", "ecb", 0 },
+ { "null", "cipher_null", "ecb", 0 },
+ { "xchacha12,aes-adiantum-plain64", "xchacha12,aes", "adiantum-plain64", 1 },
+ { "xchacha20,aes-adiantum-plain64", "xchacha20,aes", "adiantum-plain64", 1 },
+ { "aes:64-cbc-lmk", "aes:64", "cbc-lmk", 64 },
+ { "des3_ede-cbc-tcw", "des3_ede" ,"cbc-tcw", 1 },
+ { "aes-lrw-benbi", "aes","lrw-benbi", 1 },
+};
+
+static int test_parse_mode(void)
+{
+ char cipher[MAX_CIPHER_LEN], mode[MAX_CIPHER_LEN];
+ unsigned int i;
+ int keys;
+
+ printf("MODECONV:");
+ for (i = 0; i < ARRAY_SIZE(mode_test_vectors); i++) {
+ if (i && !(i % 8))
+ printf("\n");
+ keys = -1;
+ memset(cipher, 0, sizeof(cipher));
+ memset(mode, 0, sizeof(mode));
+ printf("[%s]", mode_test_vectors[i].input ?: "NULL");
+ if (crypt_parse_name_and_mode(mode_test_vectors[i].input, cipher, &keys, mode) < 0 ||
+ strcmp(mode_test_vectors[i].cipher, cipher) ||
+ strcmp(mode_test_vectors[i].mode, mode) ||
+ mode_test_vectors[i].keys != keys) {
+ printf("[FAILED (%s / %s / %i)]\n", cipher, mode, keys);
+ return EXIT_FAILURE;
+ }
+ }
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ * Cryptsetup/dm-crypt/dm-integrity algorithm naming conversion test
+ */
+struct integrity_test_vector {
+ bool int_mode; /* non-null if it is supported as integrity mode for LUKS2 */
+ const char *input;
+ const char *integrity;
+ int key_size;
+};
+static struct integrity_test_vector integrity_test_vectors[] = {
+ { true, "aead", "aead", 0 },
+ { true, "poly1305", "poly1305", 0 },
+ { true, "none", "none", 0 },
+ { false, "crc32", "crc32", 0 },
+ { true, "hmac-sha1", "hmac(sha1)", 20 },
+ { true, "hmac-sha256", "hmac(sha256)", 32 },
+ { true, "hmac-sha512", "hmac(sha512)", 64 },
+ { true, "cmac-aes", "cmac(aes)", 16 },
+ { false, "blake2b-256", "blake2b-256", 0 },
+};
+
+static int test_parse_integrity_mode(void)
+{
+ char integrity[MAX_CIPHER_LEN];
+ unsigned int i;
+ int key_size;
+
+ printf("INTEGRITYCONV:");
+ for (i = 0; i < ARRAY_SIZE(integrity_test_vectors); i++) {
+ memset(integrity, 0, sizeof(integrity));
+ printf("[%s,%i]", integrity_test_vectors[i].input ?: "NULL", integrity_test_vectors[i].key_size);
+ if (crypt_parse_hash_integrity_mode(integrity_test_vectors[i].input, integrity) < 0 ||
+ strcmp(integrity_test_vectors[i].integrity, integrity)) {
+ printf("[FAILED (%s)]\n", integrity);
+ return EXIT_FAILURE;
+ }
+ key_size = -1;
+ memset(integrity, 0, sizeof(integrity));
+ if (integrity_test_vectors[i].int_mode &&
+ (crypt_parse_integrity_mode(integrity_test_vectors[i].input, integrity, &key_size) < 0 ||
+ strcmp(integrity_test_vectors[i].integrity, integrity) ||
+ integrity_test_vectors[i].key_size != key_size)) {
+ printf("[FAILED (%s / %i)]\n", integrity, key_size);
+ return EXIT_FAILURE;
+ }
+ }
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+/*
+ * Cryptsetup null cipher bypass algorithm name
+ */
+struct null_test_vector {
+ const char *cipher;
+ bool ok;
+};
+static struct null_test_vector null_test_vectors[] = {
+ { "cipher_null-ecb", true },
+ { "cipher_null", true },
+ { "null", true },
+ { "cipher-null", false },
+ { "aes-ecb", false },
+ { NULL, false },
+};
+
+static int test_cipher_null(void)
+{
+ unsigned int i;
+
+ printf("NULLCONV:");
+ for (i = 0; i < ARRAY_SIZE(null_test_vectors); i++) {
+ printf("[%s]", null_test_vectors[i].cipher ?: "NULL");
+ if (crypt_is_cipher_null(null_test_vectors[i].cipher) !=
+ null_test_vectors[i].ok) {
+ printf("[FAILED]\n");
+ return EXIT_FAILURE;
+ }
+ }
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+struct hex_test_vector {
+ const char *hex;
+ const char *bytes;
+ ssize_t bytes_size;
+ bool ok;
+};
+static struct hex_test_vector hex_test_vectors[] = {
+ { "0000000000000000", "\x00\x00\x00\x00\x00\x00\x00\x00", 8, true },
+ { "abcdef0123456789", "\xab\xcd\xef\x01\x23\x45\x67\x89", 8, true },
+ { "aBCDef0123456789", "\xab\xcd\xef\x01\x23\x45\x67\x89", 8, true },
+ { "ff", "\xff", 1, true },
+ { "f", NULL , 1, false },
+ { "a-cde", NULL, 2, false },
+ { "FAKE", NULL, 2, false },
+ { "\x01\x02\xff", NULL, 3, false },
+ { NULL, NULL, 1, false },
+ { "fff", NULL, 2, false },
+ { "fg", NULL, 1, false },
+};
+
+/*
+ * Hexa conversion test (also should be constant time)
+ */
+static int test_hex_conversion(void)
+{
+ char *bytes, *hex;
+ ssize_t len;
+ unsigned int i;
+
+ printf("HEXCONV:");
+ for (i = 0; i < ARRAY_SIZE(hex_test_vectors); i++) {
+ bytes = NULL;
+ hex = NULL;
+ if (hex_test_vectors[i].hex && *hex_test_vectors[i].hex >= '0')
+ printf("[%s]", hex_test_vectors[i].hex);
+ else
+ printf("[INV:%i]", i);
+ len = crypt_hex_to_bytes(hex_test_vectors[i].hex, &bytes, 1);
+ if ((hex_test_vectors[i].ok && len != hex_test_vectors[i].bytes_size) ||
+ (!hex_test_vectors[i].ok && len >= 0)) {
+ printf("[FAILED]\n");
+ crypt_safe_free(bytes);
+ return EXIT_FAILURE;
+ }
+ crypt_safe_free(bytes);
+ hex = crypt_bytes_to_hex(hex_test_vectors[i].bytes_size, hex_test_vectors[i].bytes);
+ if ((hex_test_vectors[i].ok && strcasecmp(hex, hex_test_vectors[i].hex)) ||
+ (!hex_test_vectors[i].ok && hex)) {
+ printf("[FAILED]\n");
+ crypt_safe_free(hex);
+ return EXIT_FAILURE;
+ }
+ crypt_safe_free(hex);
+ }
+ printf("[OK]\n");
+
+ return EXIT_SUCCESS;
+}
+
+static void __attribute__((noreturn)) exit_test(const char *msg, int r)
+{
+ if (msg)
+ printf("%s\n", msg);
+ exit(r);
+}
+
+int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[])
+{
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+#ifndef NO_CRYPTSETUP_PATH
+ if (getenv("CRYPTSETUP_PATH")) {
+ printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
+ exit(77);
+ }
+#endif
+ if (test_parse_mode())
+ exit_test("Parse mode test failed.", EXIT_FAILURE);
+
+ if (test_parse_integrity_mode())
+ exit_test("Parse integrity mode test failed.", EXIT_FAILURE);
+
+ if (test_cipher_null())
+ exit_test("CIPHER null test failed.", EXIT_FAILURE);
+
+ if (test_hex_conversion())
+ exit_test("HEX conversion test failed.", EXIT_FAILURE);
+
+ exit_test(NULL, EXIT_SUCCESS);
+}
diff --git a/tests/unit-utils-io.c b/tests/unit-utils-io.c
new file mode 100644
index 0000000..3bfc762
--- /dev/null
+++ b/tests/unit-utils-io.c
@@ -0,0 +1,352 @@
+/*
+ * simple unit test for utils_io.c (blockwise low level functions)
+ *
+ * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "utils_io.h"
+
+enum fn_enum {
+ READ_BUFFER = 0,
+ WRITE_BUFFER,
+ READ_BLOCKWISE,
+ WRITE_BLOCKWISE,
+ READ_LSEEK_BLOCKWISE,
+ WRITE_LSEEK_BLOCKWISE
+} test_fn;
+
+char *test_file;
+size_t test_bsize;
+size_t test_alignment;
+size_t test_length;
+off_t test_offset; //FIXME: check for proper 64bit support (and test it!)
+size_t test_mem_alignment = 4096;
+
+static int test_read_buffer(void)
+{
+ void *buffer = NULL;
+ int fd = -1;
+ ssize_t ret = -EINVAL;
+
+ //printf("Entering test_read_buffer\n");
+
+ if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
+ fprintf(stderr, "Failed to allocate aligned buffer.\n");
+ goto out;
+ }
+
+ fd = open(test_file, O_RDONLY | O_DIRECT);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s.\n", test_file);
+ goto out;
+ }
+
+ ret = read_buffer(fd, buffer, test_length);
+ if (ret < 0)
+ goto out;
+
+ ret = (size_t) ret == test_length ? 0 : -EIO;
+out:
+ if (fd >= 0)
+ close(fd);
+ free(buffer);
+ return ret;
+}
+
+static int test_write_buffer(void)
+{
+ void *buffer = NULL;
+ int fd = -1;
+ ssize_t ret = -EINVAL;
+
+ //printf("Entering test_write_buffer\n");
+
+ if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
+ fprintf(stderr, "Failed to allocate aligned buffer.\n");
+ goto out;
+ }
+
+ fd = open(test_file, O_WRONLY | O_DIRECT);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s.\n", test_file);
+ goto out;
+ }
+
+ ret = write_buffer(fd, buffer, test_length);
+ if (ret < 0)
+ goto out;
+
+ ret = (size_t) ret == test_length ? 0 : -EIO;
+out:
+ if (fd >= 0)
+ close(fd);
+ free(buffer);
+ return ret;
+}
+
+static int test_read_blockwise(void)
+{
+ void *buffer = NULL;
+ int fd = -1;
+ ssize_t ret = -EINVAL;
+
+ //printf("Entering test_read_blockwise ");
+ //printf("test_bsize: %zu, test_length: %zu\n", test_bsize, test_length);
+
+ if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
+ fprintf(stderr, "Failed to allocate aligned buffer.\n");
+ goto out;
+ }
+
+ fd = open(test_file, O_RDONLY | O_DIRECT);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s.\n", test_file);
+ goto out;
+ }
+
+
+ ret = read_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length);
+ if (ret < 0)
+ goto out;
+
+ ret = (size_t) ret == test_length ? 0 : -EIO;
+out:
+ if (fd >= 0)
+ close(fd);
+ free(buffer);
+ return ret;
+}
+
+static int test_write_blockwise(void)
+{
+ void *buffer = NULL;
+ int fd = -1;
+ ssize_t ret = -EINVAL;
+
+ //printf("Entering test_write_blockwise\n");
+
+ if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
+ fprintf(stderr, "Failed to allocate aligned buffer.\n");
+ goto out;
+ }
+
+ fd = open(test_file, O_RDWR | O_DIRECT);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s.\n", test_file);
+ goto out;
+ }
+
+ ret = write_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length);
+ if (ret < 0)
+ goto out;
+
+ ret = (size_t) ret == test_length ? 0 : -EIO;
+out:
+ if (fd >= 0)
+ close(fd);
+ free(buffer);
+ return ret;
+}
+
+static int test_read_lseek_blockwise(void)
+{
+ void *buffer = NULL;
+ int fd = -1;
+ ssize_t ret = -EINVAL;
+
+ //printf("Entering test_read_lseek_blockwise\n");
+
+ if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
+ fprintf(stderr, "Failed to allocate aligned buffer.\n");
+ goto out;
+ }
+
+ fd = open(test_file, O_RDONLY | O_DIRECT);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s.\n", test_file);
+ goto out;
+ }
+
+ ret = read_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset);
+ if (ret < 0)
+ goto out;
+
+ ret = (size_t) ret == test_length ? 0 : -EIO;
+out:
+ if (fd >= 0)
+ close(fd);
+ free(buffer);
+ return ret;
+}
+
+static int test_write_lseek_blockwise(void)
+{
+ void *buffer = NULL;
+ int fd = -1;
+ ssize_t ret = -EINVAL;
+
+ //printf("Entering test_write_lseek_blockwise\n");
+
+ if (posix_memalign(&buffer, test_mem_alignment, test_length)) {
+ fprintf(stderr, "Failed to allocate aligned buffer.\n");
+ goto out;
+ }
+
+ fd = open(test_file, O_RDWR | O_DIRECT);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s.\n", test_file);
+ goto out;
+ }
+
+ ret = write_lseek_blockwise(fd, test_bsize, test_mem_alignment, buffer, test_length, test_offset);
+ if (ret < 0)
+ goto out;
+
+ ret = (size_t) ret == test_length ? 0 : -EIO;
+out:
+ if (fd >= 0)
+ close(fd);
+ free(buffer);
+ return ret;
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "Use:\tunit-utils-io file/device blockwise_fn length [bsize] [offset].\n");
+}
+
+static int parse_input_params(int argc, char **argv)
+{
+ struct stat st;
+ unsigned long offset;
+
+ if (argc < 4) {
+ usage();
+ return 1;
+ }
+
+ if (stat(argv[1], &st)) {
+ fprintf(stderr, "File/device %s is missing?\n", argv[1]);
+ return 1;
+ }
+ test_file = argv[1];
+ if (sscanf(argv[3], "%zu", &test_length) != 1)
+ return 1;
+ if (argc >= 5 && sscanf(argv[4], "%zu", &test_bsize) != 1)
+ return 1;
+ if (argc >= 6) {
+ if (sscanf(argv[5], "%ld", &offset) != 1)
+ return 1;
+ test_offset = offset;
+ }
+
+ if (!strcmp(argv[2], "read_buffer"))
+ test_fn = READ_BUFFER;
+ else if (!strcmp(argv[2], "write_buffer"))
+ test_fn = WRITE_BUFFER;
+ else if (!strcmp(argv[2], "read_blockwise")) {
+ if (argc < 5) {
+ usage();
+ return 1;
+ }
+ test_fn = READ_BLOCKWISE;
+ } else if (!strcmp(argv[2], "write_blockwise")) {
+ if (argc < 5) {
+ usage();
+ return 1;
+ }
+ test_fn = WRITE_BLOCKWISE;
+ } else if (!strcmp(argv[2], "read_lseek_blockwise")) {
+ if (argc < 6) {
+ usage();
+ return 1;
+ }
+ test_fn = READ_LSEEK_BLOCKWISE;
+ } else if (!strcmp(argv[2], "write_lseek_blockwise")) {
+ if (argc < 6) {
+ usage();
+ return 1;
+ }
+ test_fn = WRITE_LSEEK_BLOCKWISE;
+ } else {
+ usage();
+ return 1;
+ }
+
+ /* printf("function '%s': length %zu", argv[2], test_length);
+ if (argc >= 5)
+ printf(", bsize %zu", test_bsize);
+ if (argc >= 6)
+ printf(", offset %llu", test_offset);
+ printf("\n"); */
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ long ps;
+ int r = EXIT_FAILURE;
+
+#ifndef NO_CRYPTSETUP_PATH
+ if (getenv("CRYPTSETUP_PATH")) {
+ printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
+ exit(77);
+ }
+#endif
+ if (parse_input_params(argc, argv))
+ return r;
+
+ ps = sysconf(_SC_PAGESIZE);
+ if (ps > 0)
+ test_mem_alignment = (size_t)ps;
+
+ switch (test_fn) {
+ case READ_BUFFER:
+ r = test_read_buffer();
+ break;
+ case WRITE_BUFFER:
+ r = test_write_buffer();
+ break;
+ case READ_BLOCKWISE:
+ r = test_read_blockwise();
+ break;
+ case WRITE_BLOCKWISE:
+ r = test_write_blockwise();
+ break;
+ case READ_LSEEK_BLOCKWISE:
+ r = test_read_lseek_blockwise();
+ break;
+ case WRITE_LSEEK_BLOCKWISE:
+ r = test_write_lseek_blockwise();
+ break;
+ default :
+ fprintf(stderr, "Internal test error.\n");
+ return r;
+ }
+
+ return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/unit-wipe-test b/tests/unit-wipe-test
new file mode 100755
index 0000000..4d0a078
--- /dev/null
+++ b/tests/unit-wipe-test
@@ -0,0 +1,170 @@
+#!/bin/bash
+
+WIPE_UNIT=./unit-wipe
+FILE=./wipe_localfile
+FILE_RAND=./wipe_random_localfile
+MB_BYTES=$((1024*1024))
+DEVSIZEMB=8
+DEVSIZE=$((DEVSIZEMB*$MB_BYTES))
+
+HASH_EMPTY=2daeb1f36095b44b318410b3f4e8b5d989dcc7bb023d1426c492dab0a3053e74
+
+function cleanup() {
+ rm -f $FILE $FILE_RAND 2> /dev/null
+ sleep 1
+ rmmod scsi_debug >/dev/null 2>&1
+}
+
+function fail()
+{
+ if [ -n "$1" ] ; then echo "FAIL $1" ; else echo "FAIL" ; fi
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ cleanup
+ exit 100
+}
+
+function skip()
+{
+ echo "TEST SKIPPED: $1"
+ cleanup
+ exit 77
+}
+
+function add_device()
+{
+ rmmod scsi_debug >/dev/null 2>&1
+ if [ -d /sys/module/scsi_debug ] ; then
+ skip "Cannot use scsi_debug module (in use or compiled-in)."
+ fi
+ modprobe scsi_debug dev_size_mb=$DEVSIZEMB num_tgts=1 delay=0 >/dev/null 2>&1
+ if [ $? -ne 0 ] ; then
+ skip "This kernel seems to not support proper scsi_debug module."
+ fi
+ grep -q scsi_debug /sys/block/*/device/model || sleep 2
+ DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)
+ DEV="/dev/$DEV"
+ [ -b $DEV ] || fail "Cannot find $DEV."
+}
+
+function check_hash() # $1 dev, $2 hash
+{
+ local HASH=$(sha256sum $1 | cut -d' ' -f 1)
+ [ $HASH == "$2" ]
+}
+
+function init_hash_dd() # $1 dev, $dev orig
+{
+ dd if=/dev/urandom of=$2 bs=1M count=$DEVSIZEMB conv=notrunc 2> /dev/null
+ dd if=$2 of=$1 bs=1M conv=notrunc 2> /dev/null
+ HASH_0=$(sha256sum $1 | cut -d' ' -f 1)
+ # second MB wiped
+ dd if=/dev/zero of=$1 bs=1M seek=1 count=1 conv=notrunc 2> /dev/null
+ HASH_1=$(sha256sum $1 | cut -d' ' -f 1)
+ # 4,5,6 MB wiped
+ dd if=/dev/zero of=$1 bs=1M seek=4 count=3 conv=notrunc 2> /dev/null
+ HASH_2=$(sha256sum $1 | cut -d' ' -f 1)
+ dd if=$2 of=$1 bs=1M conv=notrunc 2> /dev/null
+}
+
+function add_file()
+{
+ dd if=/dev/zero of=$FILE bs=1M count=$DEVSIZEMB 2> /dev/null || fail
+ dd if=/dev/zero of=$FILE_RAND bs=1M count=$DEVSIZEMB 2> /dev/null || fail
+ check_hash $FILE $HASH_EMPTY || fail
+ check_hash $FILE_RAND $HASH_EMPTY || fail
+ dd if=$FILE of=/dev/null bs=4096 count=1 iflag=direct >/dev/null 2>&1 || FILE_NODIO=1
+}
+
+function test_wipe_full() # $1 dev, $2 block size, [$3 flags]
+{
+ # wipe random and back to zero
+ $WIPE_UNIT $1 random 0 $DEVSIZE $2 $3 || fail
+ check_hash $1 $HASH_EMPTY && fail "Failed random wipe"
+ $WIPE_UNIT $1 zero 0 $DEVSIZE $2 $3 || fail
+ check_hash $1 $HASH_EMPTY || fail "Failed zero wipe"
+}
+
+# wipe MB blocks, with zero, random and special and back to original
+function test_wipe_blocks() # $1 dev $2 block sizem [$3 flags]
+{
+ init_hash_dd $1 $FILE_RAND
+ check_hash $1 $HASH_0 || fail
+
+ $WIPE_UNIT $1 zero $((1*$MB_BYTES)) $((1*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_1 || fail
+ $WIPE_UNIT $1 random $((1*$MB_BYTES)) $((1*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_1 && fail
+ $WIPE_UNIT $1 special $((1*$MB_BYTES)) $((1*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_1 && fail
+ $WIPE_UNIT $1 zero $((1*$MB_BYTES)) $((1*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_1 || fail
+
+ $WIPE_UNIT $1 zero $((4*$MB_BYTES)) $((3*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_2 || fail
+ $WIPE_UNIT $1 random $((4*$MB_BYTES)) $((3*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_2 && fail
+ $WIPE_UNIT $1 special $((4*$MB_BYTES)) $((3*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_2 && fail
+ $WIPE_UNIT $1 zero $((4*$MB_BYTES)) $((3*$MB_BYTES)) $2 $3 || fail
+ check_hash $1 $HASH_2 || fail
+}
+
+test -x $WIPE_UNIT || skip "Run \"make `basename $WIPE_UNIT`\" first"
+
+cleanup
+add_file
+
+echo -n "[1] Wipe full file "
+for bs in 0 $MB_BYTES $((4*$MB_BYTES)); do
+ if [ -n "$FILE_NODIO" ]; then
+ echo -n [$bs/DIO N/A]
+ else
+ echo -n [$bs/DIO]
+ test_wipe_full $FILE $bs
+ fi
+ echo -n [$bs]
+ test_wipe_full $FILE $bs no-dio
+done
+echo "[OK]"
+
+echo -n "[2] Wipe blocks in file "
+for bs in 0 $MB_BYTES $((4*$MB_BYTES)); do
+ if [ -n "$FILE_NODIO" ]; then
+ echo -n [$bs/DIO N/A]
+ else
+ echo -n [$bs/DIO]
+ test_wipe_blocks $FILE $bs
+ fi
+ echo -n [$bs]
+ test_wipe_blocks $FILE $bs no-dio
+done
+echo "[OK]"
+
+[ $(id -u) -eq 0 ] || {
+ echo "WARNING: You must be root to run remaining tests."
+ cleanup
+ exit 0
+}
+
+add_device
+
+echo -n "[3] Wipe full block device "
+for bs in 0 $MB_BYTES $((4*$MB_BYTES)); do
+ echo -n [$bs/DIO]
+ test_wipe_full $DEV $bs
+ echo -n [$bs]
+ test_wipe_full $DEV $bs no-dio
+done
+echo "[OK]"
+
+echo -n "[4] Wipe blocks in block device "
+for bs in 0 $MB_BYTES $((4*$MB_BYTES)); do
+ echo -n [$bs/DIO]
+ test_wipe_blocks $DEV $bs
+ echo -n [$bs]
+ test_wipe_blocks $DEV $bs no-dio
+done
+echo "[OK]"
+
+cleanup
diff --git a/tests/unit-wipe.c b/tests/unit-wipe.c
new file mode 100644
index 0000000..c3019c7
--- /dev/null
+++ b/tests/unit-wipe.c
@@ -0,0 +1,138 @@
+/*
+ * unit test helper for crypt_wipe API call
+ *
+ * Copyright (C) 2022-2023 Milan Broz
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "libcryptsetup.h"
+
+const char *test_file;
+uint64_t test_offset, test_length, test_block;
+uint32_t flags;
+crypt_wipe_pattern pattern;
+
+static void usage(void)
+{
+ fprintf(stderr, "Use:\tunit-wipe file/device zero|random|special offset length bsize [no-dio].\n");
+}
+
+static bool parse_u64(const char *arg, uint64_t *u64)
+{
+ unsigned long long ull;
+ char *end;
+
+ ull = strtoull(arg, &end, 10);
+ if (*end || !*arg || errno == ERANGE)
+ return false;
+
+ if (ull % 512)
+ return false;
+
+ *u64 = ull;
+ return true;
+}
+
+static bool parse_input_params(int argc, char **argv)
+{
+ struct stat st;
+
+ if (argc < 6 || argc > 7) {
+ usage();
+ return false;
+ }
+
+ if (stat(argv[1], &st)) {
+ fprintf(stderr, "File/device %s is missing?\n", argv[1]);
+ return false;
+ }
+ test_file = argv[1];
+
+ if (!strcmp(argv[2], "random"))
+ pattern = CRYPT_WIPE_RANDOM;
+ else if (!strcmp(argv[2], "zero"))
+ pattern = CRYPT_WIPE_ZERO;
+ else if (!strcmp(argv[2], "special"))
+ pattern = CRYPT_WIPE_SPECIAL;
+ else {
+ fprintf(stderr, "Wrong pattern specification.\n");
+ return false;
+ }
+
+ if (!parse_u64(argv[3], &test_offset)) {
+ fprintf(stderr, "Wrong offset specification.\n");
+ return false;
+ }
+
+ if (!parse_u64(argv[4], &test_length)) {
+ fprintf(stderr, "Wrong length specification.\n");
+ return false;
+ }
+
+ if (!parse_u64(argv[5], &test_block)) {
+ fprintf(stderr, "Wrong block length specification.\n");
+ return false;
+ }
+
+ if (argc > 6) {
+ if (!strcmp(argv[6], "no-dio"))
+ flags = CRYPT_WIPE_NO_DIRECT_IO;
+ else {
+ fprintf(stderr, "Wrong flags specification.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ struct crypt_device *cd;
+ int r;
+
+#ifndef NO_CRYPTSETUP_PATH
+ if (getenv("CRYPTSETUP_PATH")) {
+ printf("Cannot run this test with CRYPTSETUP_PATH set.\n");
+ exit(77);
+ }
+#endif
+
+ if (!parse_input_params(argc, argv))
+ return EXIT_FAILURE;
+
+ r = crypt_init(&cd, NULL);
+ if (r < 0) {
+ fprintf(stderr, "Context init failure %i.\n", r);
+ return EXIT_FAILURE;
+ }
+
+ r = crypt_wipe(cd, test_file, pattern, test_offset, test_length,
+ test_block, flags, NULL, NULL);
+ crypt_free(cd);
+
+ if (r)
+ fprintf(stderr, "Failure %i\n", r);
+
+ return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/tests/valg-api.sh b/tests/valg-api.sh
new file mode 100755
index 0000000..4c6a600
--- /dev/null
+++ b/tests/valg-api.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+SUP="--suppressions=./cryptsetup-valg-supps"
+CHILD="--trace-children=no --child-silent-after-fork=yes"
+MALLOC="--malloc-fill=aa"
+FREE="--free-fill=21"
+STACK="--max-stackframe=300000"
+EXTRAS="--read-var-info=yes --show-reachable=yes"
+LOGFILE="--log-file=./valglog.$(date +%j:%H:%M:%S:%N)_${INFOSTRING}"
+LEAKCHECK="--leak-check=full --track-origins=yes"
+
+exec valgrind $SUP $GETSUP $CHILD $MALLOC $FREE $STACK $EXTRAS $LOGFILE $LEAKCHECK "$@"
diff --git a/tests/valg.sh b/tests/valg.sh
new file mode 100755
index 0000000..f3d4032
--- /dev/null
+++ b/tests/valg.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+SUP="--suppressions=./cryptsetup-valg-supps"
+CHILD="--trace-children=yes --child-silent-after-fork=yes"
+MALLOC="--malloc-fill=aa"
+FREE="--free-fill=21"
+STACK="--max-stackframe=2000000"
+EXTRAS="--read-var-info=yes --show-reachable=yes"
+LOGFILE="--log-file=./valglog.$(date +%j:%H:%M:%S:%N)_${INFOSTRING}"
+LEAKCHECK="--leak-check=full --track-origins=yes"
+
+exec valgrind $SUP $GETSUP $CHILD $MALLOC $FREE $STACK $EXTRAS $LOGFILE $LEAKCHECK "$@"
diff --git a/tests/valid_header_file.xz b/tests/valid_header_file.xz
new file mode 100644
index 0000000..4b443ae
--- /dev/null
+++ b/tests/valid_header_file.xz
Binary files differ
diff --git a/tests/verity-compat-test b/tests/verity-compat-test
new file mode 100755
index 0000000..8a28a12
--- /dev/null
+++ b/tests/verity-compat-test
@@ -0,0 +1,559 @@
+#!/bin/bash
+
+[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
+VERITYSETUP=$CRYPTSETUP_PATH/veritysetup
+VERITYSETUP_VALGRIND=../.libs/veritysetup
+VERITYSETUP_LIB_VALGRIND=../.libs
+
+DEV_NAME=verity3273
+DEV_NAME2=verity3273x
+DEV_OUT="$DEV_NAME.out"
+IMG=verity-data
+IMG_HASH=verity-hash
+IMG_TMP=tst-dev
+FEC_DEV=tst_fec123
+# If we need deterministic image creation
+DEV_SALT=9e7457222290f1bac0d42ad2de2d602a87bb871c22ab70ca040bad450578a436
+DEV_UUID=a60c98d2-ae9b-4865-bfcb-b4e3ace11033
+
+function remove_mapping()
+{
+ [ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove $DEV_NAME2 >/dev/null 2>&1
+ [ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME >/dev/null 2>&1
+ [ ! -z "$LOOPDEV1" ] && losetup -d $LOOPDEV1 >/dev/null 2>&1
+ rm -f $IMG $IMG.roothash $IMG_HASH $DEV_OUT $FEC_DEV $IMG_TMP >/dev/null 2>&1
+ LOOPDEV1=""
+ LOOPDEV2=""
+}
+
+function fail()
+{
+ [ -n "$1" ] && echo "$1"
+ echo "FAILED backtrace:"
+ while caller $frame; do ((frame++)); done
+ [ -f $DEV_OUT ] && cat $DEV_OUT
+ remove_mapping
+ exit 2
+}
+
+function skip()
+{
+ [ -n "$1" ] && echo "$1"
+ exit 77
+}
+
+function prepare() # $1 dev1_siz [$2 dev2_size]
+{
+ remove_mapping
+
+ dd if=/dev/zero of=$IMG bs=1k count=$1 >/dev/null 2>&1
+ LOOPDEV1=$(losetup -f 2>/dev/null)
+ [ -z "$LOOPDEV1" ] && fail "No free loop device"
+ losetup $LOOPDEV1 $IMG
+
+ [ -z "$2" ] && return
+ LOOPDEV2=$IMG_HASH
+}
+
+function wipe()
+{
+ dd if=/dev/zero of=$LOOPDEV1 bs=256k >/dev/null 2>&1
+ rm -f $IMG_HASH $DEV_OUT >/dev/null 2>&1
+}
+
+function check_exists()
+{
+ [ -b /dev/mapper/$DEV_NAME ] || fail
+}
+
+function check_version() # MAJ MIN
+{
+ VER_STR=$(dmsetup targets | grep verity | cut -f 3 -dv)
+ [ -z "$VER_STR" ] && fail "Failed to parse dm-verity version."
+
+ VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
+ VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
+
+ test $VER_MAJ -gt $1 && return 0
+ test $VER_MIN -ge $2 && return 0
+ return 1
+}
+
+function compare_out() # $1 what, $2 expected
+{
+ OPT=$(grep -v "^#" $DEV_OUT | grep -i "$1" | sed -e s/.*\:\ // )
+ [ -z "$OPT" ] && fail
+ [ $OPT != $2 ] && fail "$1 differs ($2)"
+}
+
+function check_root_hash_fail()
+{
+ echo -n "Root hash check "
+ ROOT_HASH=$($VERITYSETUP format $IMG $IMG_HASH --fec-device $FEC_DEV --fec-roots 2 -h sha256 | grep -e "Root hash" | cut -d: -f2 | tr -d "\t\n ")
+ ROOT_HASH_BAD=abcdef0000000000000000000000000000000000000000000000000000000000
+
+ $VERITYSETUP verify $IMG $IMG_HASH $ROOT_HASH || fail
+ $VERITYSETUP verify $IMG $IMG_HASH $ROOT_HASH_BAD >/dev/null 2>&1 && fail
+ $VERITYSETUP verify $IMG $IMG_HASH $ROOT_HASH_BAD --fec-device $FEC_DEV --fec-roots 2 >/dev/null 2>&1 && fail
+
+ $VERITYSETUP open $IMG $DEV_NAME $IMG_HASH $ROOT_HASH || fail
+ check_exists
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=4096 count=1 >/dev/null 2>&1
+ dmsetup status $DEV_NAME | grep "verity V" >/dev/null || fail
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
+
+ $VERITYSETUP open $IMG $DEV_NAME $IMG_HASH $ROOT_HASH_BAD >/dev/null 2>&1 || fail
+ check_exists
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=4096 count=1 >/dev/null 2>&1
+ dmsetup status $DEV_NAME | grep "verity C" >/dev/null || fail
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
+
+ echo "[OK]"
+}
+
+function check_root_hash() # $1 size, $2 hash, $3 salt, $4 version, $5 hash, [$6 offset]
+{
+ local FORMAT_PARAMS
+ local VERIFY_PARAMS
+ local ROOT_HASH
+
+ if [ -z "$LOOPDEV2" ] ; then
+ BLOCKS=$(($6 / $1))
+ DEV_PARAMS="$LOOPDEV1 $LOOPDEV1 \
+ --hash-offset $6 \
+ --data-blocks=$BLOCKS --debug"
+ else
+ DEV_PARAMS="$LOOPDEV1 $LOOPDEV2"
+ fi
+
+ for root_hash_as_file in yes no; do
+ for sb in yes no; do
+ FORMAT_PARAMS="--format=$4 --data-block-size=$1 --hash-block-size=$1 --hash=$5 --salt=$3"
+ if [ $sb == yes ] ; then
+ VERIFY_PARAMS=""
+ else
+ FORMAT_PARAMS="$FORMAT_PARAMS --no-superblock"
+ VERIFY_PARAMS=$FORMAT_PARAMS
+ fi
+ if [ $root_hash_as_file == yes ] ; then
+ echo -n $2 > $IMG.roothash
+ FORMAT_PARAMS="$FORMAT_PARAMS --root-hash-file=$IMG.roothash"
+ VERIFY_PARAMS="$VERIFY_PARAMS --root-hash-file=$IMG.roothash"
+ ROOT_HASH=""
+ else
+ ROOT_HASH="$2"
+ fi
+
+ for fail in data hash; do
+ wipe
+ echo -n "V$4(sb=$sb root_hash_as_file=$root_hash_as_file) $5 block size $1: "
+ $VERITYSETUP format $DEV_PARAMS $FORMAT_PARAMS >$DEV_OUT
+ if [ $? -ne 0 ] ; then
+ if [[ $1 =~ "sha2" ]] ; then
+ fail "Cannot format device."
+ fi
+ return
+ fi
+
+ echo -n "[root hash]"
+ compare_out "root hash" $2
+ compare_out "salt" "$3"
+
+ $VERITYSETUP verify $DEV_PARAMS $VERIFY_PARAMS $ROOT_HASH >>$DEV_OUT 2>&1 || fail
+ echo -n "[verify]"
+
+ $VERITYSETUP create $DEV_NAME $DEV_PARAMS $VERIFY_PARAMS $ROOT_HASH >>$DEV_OUT 2>&1 || fail
+ check_exists
+ echo -n "[activate]"
+
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=$1 2>/dev/null
+ dmsetup status $DEV_NAME | grep "verity V" >/dev/null || fail
+ echo -n "[in-kernel verify]"
+
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
+
+ case $fail in
+ data)
+ dd if=/dev/urandom of=$LOOPDEV1 bs=1 seek=3456 count=8 conv=notrunc 2>/dev/null
+ TXT="data_dev"
+ ;;
+ hash)
+ if [ -z "$LOOPDEV2" ] ; then
+ dd if=/dev/urandom of=$LOOPDEV1 bs=1 seek=$((8193 + $4)) count=8 conv=notrunc 2>/dev/null
+ else
+ dd if=/dev/urandom of=$LOOPDEV2 bs=1 seek=8193 count=8 conv=notrunc 2>/dev/null
+ fi
+ TXT="hash_dev"
+ ;;
+ esac
+
+ $VERITYSETUP verify $DEV_PARAMS $VERIFY_PARAMS $ROOT_HASH >>$DEV_OUT 2>&1 && \
+ fail "userspace check for $TXT corruption"
+ $VERITYSETUP create $DEV_NAME $DEV_PARAMS $VERIFY_PARAMS $ROOT_HASH >>$DEV_OUT 2>&1 || \
+ fail "activation"
+ dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=$1 2>/dev/null
+ dmsetup status $DEV_NAME | grep "verity V" >/dev/null && \
+ fail "in-kernel check for $TXT corruption"
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail "deactivation"
+ echo "[$TXT corruption]"
+ done
+ done
+ done
+}
+
+function corrupt_device() # $1 device, $2 device_size(in bytes), $3 #{corrupted_bytes}
+{
+ # Repeatable magic corruption :-)
+ CORRUPT=$3
+ RANDOM=43
+ while [ "$CORRUPT" -gt 0 ]; do
+ SEEK=$RANDOM
+ while [ $SEEK -ge $2 ] ; do SEEK=$RANDOM; done
+ echo -n -e "\x55" | dd of=$1 bs=1 count=1 seek=$SEEK conv=notrunc > /dev/null 2>&1
+ CORRUPT=$(($CORRUPT - 1))
+ done
+}
+
+# $1 data_device, $2 hash_device, $3 fec_device, $4 data/hash_block_size(in bytes),
+# $5 data_size(in blocks), $6 device_size(in blocks), $7 hash_offset(in bytes),
+# $8 fec_offset(in bytes), $9 fec_roots, ${10} corrupted_bytes, [${11} superblock(y/n), ${12} salt]
+function check_fec()
+{
+ INDEX=25
+ dd if=/dev/zero of=$1 bs=$4 count=$6 > /dev/null 2>&1
+
+ echo -n "Block_size: $4, Data_size: $(($4 * $5))B, FEC_roots: $9, Corrupted_bytes: ${10} "
+
+ PARAMS=" --data-block-size=$4 --hash-block-size=$4 "
+ if [ "$5" -ne "$6" ]; then
+ PARAMS="$PARAMS --data-blocks=$5"
+ fi
+
+ if [ "$7" -ne 0 ]; then
+ PARAMS="$PARAMS --hash-offset=$7"
+ fi
+
+ if [ "$8" -ne 0 ]; then
+ PARAMS="$PARAMS --fec-offset=$8"
+ fi
+
+ if [ "${11}" == "n" ]; then
+ INDEX=24
+ echo -n "[no-superblock]"
+ PARAMS="$PARAMS --no-superblock --salt=${12}"
+ elif [ -n "${12}" ]; then
+ PARAMS="$PARAMS --salt=${12}"
+ fi
+
+ if [[ "$1" == "$2" && "$1" == "$3" ]]; then
+ echo -n "[one_device_test]"
+ dd if=/dev/zero of=$IMG_TMP bs=$4 count=$5 > /dev/null 2>&1
+ HASH_ORIG=$(sha256sum $IMG_TMP | cut -d' ' -f 1)
+ else
+ HASH_ORIG=$(sha256sum $1 | cut -d' ' -f 1)
+ fi
+
+ ROOT_HASH=$($VERITYSETUP format $1 $2 --fec-device=$3 $PARAMS | grep -e "Root hash" | cut -d: -f2 | tr -d "\t\n ")
+
+ corrupt_device $1 $(($5 * $4)) ${10}
+
+ $VERITYSETUP create $DEV_NAME $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS > /dev/null 2>&1
+ if [ "$?" -ne "0" ] ; then
+ echo "[N/A, test skipped]"
+ return 3
+ fi
+
+ udevadm settle > /dev/null 2>&1
+
+ dd if=/dev/mapper/$DEV_NAME of=$IMG_TMP > /dev/null 2>&1
+ HASH_REPAIRED=$(sha256sum $IMG_TMP | cut -d' ' -f 1)
+
+ $VERITYSETUP close $DEV_NAME
+
+ if [ "$HASH_ORIG" != "$HASH_REPAIRED" ]; then
+ echo -n "[kernel correction failed]"
+ $VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && fail "Userspace verify should fail"
+ echo -n "[userspace verify failed]"
+ RET=1
+ else
+ echo -n "[repaired in kernel]"
+ $VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || fail "Userspace verify failed"
+ echo "[userspace verify][OK]"
+ RET=0
+ fi
+ rm $1 $2 $3 $IMG_TMP > /dev/null 2>&1
+ return $RET
+}
+
+function check_option() # $1 size, $2 hash, $3 salt, $4 version, $5 hash, $6 CLI option, $7 status option
+{
+ DEV_PARAMS="$LOOPDEV1 $LOOPDEV2"
+ FORMAT_PARAMS="--format=$4 --data-block-size=$1 --hash-block-size=$1 --hash=$5 --salt=$3"
+
+ echo -n "Option $6 "
+ $VERITYSETUP format $DEV_PARAMS $FORMAT_PARAMS >/dev/null 2>&1 || fail
+ $VERITYSETUP create $DEV_NAME $DEV_PARAMS $2 $6 >/dev/null 2>&1 || fail
+ check_exists
+ $VERITYSETUP status $DEV_NAME 2>/dev/null | grep flags | grep -q $7 || fail
+ dmsetup table $DEV_NAME 2>/dev/null | grep -q $7 || fail
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
+ echo "[OK]"
+}
+
+function valgrind_setup()
+{
+ command -v valgrind >/dev/null || fail "Cannot find valgrind."
+ [ ! -f $VERITYSETUP_VALGRIND ] && fail "Unable to get location of veritysetup executable."
+ export LD_LIBRARY_PATH="$VERITYSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
+}
+
+function valgrind_run()
+{
+ INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${VERITYSETUP_VALGRIND} "$@"
+}
+
+function checkOffsetBug() # $1 size, $2 hash-offset, $3 data-blocks
+{
+ echo -n "Size :: $1 B | Hash-offset :: $2 blocks | Data-blocks :: $3 "
+ dd if=/dev/zero of=$IMG bs=1 count=0 seek=$1 >/dev/null 2>&1
+ $VERITYSETUP --data-blocks=$3 --hash-offset=$2 format $IMG $IMG >/dev/null 2>&1 || fail "Test [hash-offset greater than 2G] failed"
+ echo "[OK]"
+ remove_mapping
+}
+
+function checkOverlapBug() # $1 size, $2 hash-offset, $3 data-blocks, $4 block_size, $5 fec_offset
+{
+ echo -n "Device-size :: $1 B | "
+ [ $# -ge 3 ] && echo -n "Data-blocks :: $3 blocks| "
+ [ $# -lt 3 ] && echo -n "Data-blocks :: whole device | "
+ [ $# -ge 4 ] && echo -n "Block-size :: $4 B | "
+ [ $# -lt 4 ] && echo -n "Block-size :: 4096 B | "
+ echo -n "Hash-offset :: $2 B | "
+
+ dd if=/dev/zero of=$IMG bs=1 count=0 seek=$1 >/dev/null 2>&1
+ if [ -z $3 ] ; then
+ # veritysetup must fail
+ $VERITYSETUP --hash-offset=$2 format $IMG $IMG >/dev/null 2>&1 && fail "Test [overlap with option \"--data-blocks\" not entered] failed"
+ else
+ $VERITYSETUP --data-block-size=$4 --hash-block-size=$4 --data-blocks=$3 --hash-offset=$2 format $IMG $IMG >/dev/null 2>&1
+ RET=$?
+ [ "$3" -gt "$(($2 / $4))" ] && [ "$RET" -eq "0" ] && fail "Test [overlap - hash-offset in data area] failed"
+ fi
+
+ if [ $# -eq 5 ] ; then
+ echo -n "FEC-offset :: $5 B | "
+ PARAMS="--data-block-size=$4 --hash-block-size=$4 --data-blocks=$3 --fec-device=$IMG --fec-offset=$5"
+
+ # test data-fec area overlap
+ $VERITYSETUP format $IMG $IMG_HASH $PARAMS >/dev/null 2>&1
+ RET=$?
+ [ "$(($3*$4))" -gt "$5" ] && [ "$RET" -eq "0" ] && fail "Test [data/fec area overlap] failed"
+
+ HASH_SIZE=$(stat --printf="%s" $IMG_HASH)
+
+ # test hash-fec area overlap
+ $VERITYSETUP format $IMG $IMG $PARAMS --hash-offset=$2 >/dev/null 2>&1
+ RET=$?
+ [ "$(($2 + $HASH_SIZE))" -gt "$5" ] && [ "$RET" -eq "0" ] && fail "Test [hash/fec area overlap] failed"
+ fi
+
+ echo "[OK]"
+ remove_mapping
+}
+
+# $1 size, $2 block size, $3 roots, $4 hash offset, $5 fec offset,
+# $6 one dev(1 - one device, 2 - one device for data and hash, one device for fec data, 3 - three separate devices),
+# $7 #{corrupted bytes}
+function checkUserSpaceRepair()
+{
+ BS=512
+ COUNT=50000
+ dd if=/dev/zero of=$IMG bs=$BS count=$COUNT >/dev/null 2>&1
+ PARAMS="--data-block-size=$2 --hash-block-size=$2 --fec-roots=$3"
+ [ "$1" -gt 0 ] && PARAMS="$PARAMS --data-blocks=$1" && BS=$2 && COUNT=$1
+
+ # different parameters for different number of devices
+ [ "$6" -eq 1 ] && HASH_DEV=$IMG && FEC=$IMG && PARAMS="$PARAMS --hash-offset=$4 --fec-offset=$5" && echo -n "[One device]"
+ [ "$6" -eq 2 ] && HASH_DEV=$IMG && FEC=$FEC_DEV && PARAMS="$PARAMS --hash-offset=$4" && echo -n "[Two separate data/hash and fec devices]"
+ [ "$6" -eq 3 ] && HASH_DEV=$IMG_HASH && FEC=$FEC_DEV && echo -n "[Three separate devices]"
+
+ echo -n "[nroots::$3]"
+
+ ROOT_HASH=$($VERITYSETUP format $IMG $HASH_DEV --fec-device $FEC $PARAMS --salt=$DEV_SALT --uuid=$DEV_UUID | grep -e "Root hash" | cut -d: -f2 | tr -d "\t\n ")
+
+ echo -n "[Errors can be corrected]"
+ corrupt_device $IMG $(($BS*$COUNT)) $7
+ $VERITYSETUP verify $IMG $HASH_DEV $ROOT_HASH --fec-device=$FEC $PARAMS >/dev/null 2>&1
+ RET=$?
+ [ "$RET" -ne 0 ] && fail "Device can be corrected, but it wasn't."
+ echo -n "[OK]"
+
+ echo -n "[Errors cannot be corrected]"
+ dd if=/dev/urandom of=$IMG bs=$BS count=$COUNT conv=notrunc >/dev/null 2>&1
+ $VERITYSETUP verify $IMG $HASH_DEV $ROOT_HASH --fec-device=$FEC $PARAMS >/dev/null 2>&1
+ RET=$?
+ [ "$RET" -eq 0 ] && fail "Device cannot be correct, but it didn't fail."
+ echo "[OK]"
+}
+
+function check_concurrent() # $1 hash
+{
+ DEV_PARAMS="$LOOPDEV1 $LOOPDEV2"
+
+ # First check that with two sequential opens, we are returning the expected -EEXIST
+ $VERITYSETUP format $DEV_PARAMS >/dev/null 2>&1 || fail
+ $VERITYSETUP create $DEV_NAME $DEV_PARAMS $1 >/dev/null 2>&1 || fail
+ check_exists
+ $VERITYSETUP create $DEV_NAME $DEV_PARAMS $1 2>&1 >/dev/null | grep -q "Device $DEV_NAME already exists" || fail
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
+
+ # Then do two concurrent opens, and check that libdevmapper did not return -EINVAL, which is
+ # not gracefully recoverable. Either could fail depending on scheduling, so just check that
+ # the libdevmapper error does not appear in either of the outputs.
+ cat /dev/null >$DEV_OUT
+ $VERITYSETUP create -v $DEV_NAME $DEV_PARAMS $1 >>$DEV_OUT 2>&1 &
+ $VERITYSETUP create -v $DEV_NAME $DEV_PARAMS $1 >>$DEV_OUT 2>&1 &
+ wait
+ grep -q "Command failed with code .* (wrong or missing parameters)" $DEV_OUT && fail
+ check_exists
+ rm $DEV_OUT
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
+
+ echo "[OK]"
+}
+
+export LANG=C
+[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
+[ ! -x "$VERITYSETUP" ] && skip "Cannot find $VERITYSETUP, test skipped."
+
+[ -n "$VALG" ] && valgrind_setup && VERITYSETUP=valgrind_run
+modprobe dm-verity >/dev/null 2>&1
+dmsetup targets | grep verity >/dev/null 2>&1 || skip "Cannot find dm-verity target, test skipped."
+
+# VERITYSETUP tests
+
+SALT=e48da609055204e89ae53b655ca2216dd983cf3cb829f34f63a297d106d53e2d
+
+echo "Verity tests [separate devices]"
+prepare 8192 1024
+check_root_hash_fail
+
+check_root_hash 512 9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174 $SALT 1 sha256
+check_root_hash 1024 54d92778750495d1f80832b486ebd007617d746271511bbf0e295e143da2b3df $SALT 1 sha256
+check_root_hash 4096 e522df0f97da4febb882ac40f30b37dc0b444bf6df418929463fa25280f09d5c $SALT 1 sha256
+# version 0
+check_root_hash 4096 cbbf4ebd004ef65e29b935bb635a39cf754d677f3fa10b0126da725bbdf10f7d $SALT 0 sha256
+# no salt
+check_root_hash 4096 ef29c902d87350f1da4bfa536e16cebc162a909bf89abe448b81ec500d4fb9bf - 1 sha256
+# sha1
+check_root_hash 1024 d0e9163ca8844aaa2e88fe5265a8c5d9ee494a99 $SALT 1 sha1
+check_root_hash 1024 73509e8e868be6b8ac939817a98a3d35121413b2 dadada 1 sha1
+
+echo "Verity tests [one device offset]"
+prepare $((8192 + 1024))
+check_root_hash 512 9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174 $SALT 1 sha256 8388608
+check_root_hash 1024 54d92778750495d1f80832b486ebd007617d746271511bbf0e295e143da2b3df $SALT 1 sha256 8388608
+check_root_hash 4096 e522df0f97da4febb882ac40f30b37dc0b444bf6df418929463fa25280f09d5c $SALT 1 sha256 8388608
+# version 0
+check_root_hash 4096 cbbf4ebd004ef65e29b935bb635a39cf754d677f3fa10b0126da725bbdf10f7d $SALT 0 sha256 8388608
+# no salt
+check_root_hash 4096 ef29c902d87350f1da4bfa536e16cebc162a909bf89abe448b81ec500d4fb9bf - 1 sha256 8388608
+# sha1
+check_root_hash 1024 d0e9163ca8844aaa2e88fe5265a8c5d9ee494a99 $SALT 1 sha1 8388608
+check_root_hash 1024 73509e8e868be6b8ac939817a98a3d35121413b2 dadada 1 sha1 8388608
+
+if check_version 1 3; then
+ echo "Verity data corruption options test."
+ SALT=e48da609055204e89ae53b655ca2216dd983cf3cb829f34f63a297d106d53e2d
+ HASH=9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174
+ prepare 8192 1024
+ check_option 512 $HASH $SALT 1 sha256 "--ignore-corruption" "ignore_corruption"
+ check_option 512 $HASH $SALT 1 sha256 "--restart-on-corruption" "restart_on_corruption"
+ check_option 512 $HASH $SALT 1 sha256 "--ignore-zero-blocks" "ignore_zero_blocks"
+ check_option 512 $HASH $SALT 1 sha256 "--ignore-corruption --ignore-zero-blocks" "ignore_corruption"
+ if check_version 1 4; then
+ check_option 512 $HASH $SALT 1 sha256 "--check-at-most-once" "check_at_most_once"
+ fi
+ if check_version 1 7; then
+ check_option 512 $HASH $SALT 1 sha256 "--panic-on-corruption" "panic_on_corruption"
+ fi
+
+ if check_version 1 9; then
+ echo "Verity data performance options test."
+ check_option 512 $HASH $SALT 1 sha256 "--use-tasklets" "try_verify_in_tasklet"
+ fi
+fi
+
+echo "Veritysetup [hash-offset bigger than 2G works] "
+checkOffsetBug 3000000000 2499997696 256
+checkOffsetBug 10000000000 8000000000 128
+
+echo "Veritysetup [overlap-detection] "
+checkOverlapBug 2097152 1433600
+checkOverlapBug 2097152 1433600 350 4096
+checkOverlapBug 2097152 1228800 350 4096 # data-hash overlap
+checkOverlapBug 2097152 0 350 4096 1228800 # data-fec overlap
+checkOverlapBug 10240000 256000 400 512 256512 # hash-fec overlap
+
+if check_version 1 3; then
+ echo "Veritysetup [FEC tests]"
+ for INDEX in {1..4}; do
+ # in the first iteration check if we can use FEC (it can be compiled-out)
+ (check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) )
+ RET=$?
+ [ "$RET" -eq "3" ] && break
+ [ "$RET" -eq "0" ] || fail "FEC repair failed"
+
+ (check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'n' $SALT) || fail "FEC repair failed"
+ (check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'y' $SALT) || fail "FEC repair failed"
+ (check_fec $IMG $IMG $IMG 4096 64 6250 4194304 8388608 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'n' $SALT) || fail "FEC repair failed"
+ (check_fec $IMG $IMG $IMG 4096 64 6250 4194304 8388608 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'y' $SALT) || fail "FEC repair failed"
+
+ (check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'n' $SALT) || fail "FEC repair failed"
+ (check_fec $IMG $IMG_HASH $FEC_DEV 4096 35 35 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
+ (check_fec $IMG $IMG_HASH $FEC_DEV 512 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
+ (check_fec $IMG $IMG_HASH $FEC_DEV 1024 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
+ # this test should fail
+ (check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200))) && fail "FEC repair must fail"
+ echo "[OK]"
+ done
+fi
+
+echo "Correction in userspace: "
+# checkUserSpaceRepair <#blocks> <block_size> <roots> <hash_offset> <fec_offset> <#devices> <#corrupted bytes>
+checkUserSpaceRepair -1 512 2 0 0 3 100
+checkUserSpaceRepair 400 512 2 256000 0 2 50
+checkUserSpaceRepair 500 512 2 2457600 4915200 1 1
+checkUserSpaceRepair -1 4096 2 0 0 3 10
+checkUserSpaceRepair 400 4096 2 2048000 0 2 1
+checkUserSpaceRepair 500 4096 2 2457600 4915200 1 2
+
+echo -n "Verity concurrent opening tests:"
+prepare 8192 1024
+check_concurrent 9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174
+
+echo -n "Deferred removal of device:"
+prepare 8192 1024
+$VERITYSETUP format $LOOPDEV1 $IMG_HASH --format=1 --data-block-size=512 --hash-block-size=512 --hash=sha256 --salt=$SALT >/dev/null 2>&1 || fail "Cannot format device."
+$VERITYSETUP open $LOOPDEV1 $DEV_NAME $DEV $IMG_HASH 9de18652fe74edfb9b805aaed72ae2aa48f94333f1ba5c452ac33b1c39325174 || fail "Cannot activate device."
+dmsetup create $DEV_NAME2 --table "0 8 linear /dev/mapper/$DEV_NAME 0"
+[ ! -b /dev/mapper/$DEV_NAME2 ] && fail
+$VERITYSETUP close $DEV_NAME >/dev/null 2>&1 && fail
+$VERITYSETUP status $DEV_NAME >/dev/null 2>&1 || fail
+$VERITYSETUP close --deferred $DEV_NAME >/dev/null 2>&1
+if [ $? -eq 0 ] ; then
+ dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" || fail
+ $VERITYSETUP close --cancel-deferred $DEV_NAME >/dev/null 2>&1
+ dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" >/dev/null 2>&1 && fail
+ $VERITYSETUP close --deferred $DEV_NAME >/dev/null 2>&1
+ dmsetup remove $DEV_NAME2 || fail
+ $VERITYSETUP status $DEV_NAME >/dev/null 2>&1 && fail
+ echo "[OK]"
+else
+ dmsetup remove $DEV_NAME2 >/dev/null 2>&1
+ $VERITYSETUP close $DEV_NAME >/dev/null 2>&1
+ echo "[N/A]"
+fi
+
+remove_mapping
+exit 0
diff --git a/tests/xfs_512_block_size.img.xz b/tests/xfs_512_block_size.img.xz
new file mode 100644
index 0000000..047c788
--- /dev/null
+++ b/tests/xfs_512_block_size.img.xz
Binary files differ
diff --git a/tokens/Makemodule.am b/tokens/Makemodule.am
new file mode 100644
index 0000000..4be7bc5
--- /dev/null
+++ b/tokens/Makemodule.am
@@ -0,0 +1,29 @@
+EXTRA_DIST += tokens/libcryptsetup-token.sym
+
+TOKENS_LDFLAGS = $(AM_LDFLAGS) -no-undefined -avoid-version \
+ -Wl,--version-script=$(top_srcdir)/tokens/libcryptsetup-token.sym
+
+tokendir = ${EXTERNAL_LUKS2_TOKENS_PATH}
+
+if SSHPLUGIN_TOKEN
+libcryptsetup_token_ssh_la_LDFLAGS = $(TOKENS_LDFLAGS)
+libcryptsetup_token_ssh_la_SOURCES = tokens/ssh/libcryptsetup-token-ssh.c \
+ tokens/ssh/ssh-utils.c \
+ tokens/ssh/ssh-utils.h
+libcryptsetup_token_ssh_la_LIBADD = libcryptsetup.la @LIBSSH_LIBS@ @JSON_C_LIBS@
+token_LTLIBRARIES = libcryptsetup-token-ssh.la
+
+cryptsetup_ssh_SOURCES = tokens/ssh/cryptsetup-ssh.c \
+ tokens/ssh/ssh-utils.c \
+ tokens/ssh/ssh-utils.h \
+ src/utils_tools.c \
+ src/utils_password.c \
+ lib/utils_io.c \
+ lib/utils_loop.c
+cryptsetup_ssh_LDADD = -lm libcryptsetup.la @LIBSSH_LIBS@ @JSON_C_LIBS@ @POPT_LIBS@ \
+ @PWQUALITY_LIBS@ @PASSWDQC_LIBS@ @ARGP_LIBS@
+
+cryptsetup_ssh_CFLAGS = $(AM_CFLAGS)
+
+sbin_PROGRAMS += cryptsetup-ssh
+endif
diff --git a/tokens/libcryptsetup-token.sym b/tokens/libcryptsetup-token.sym
new file mode 100644
index 0000000..17ec599
--- /dev/null
+++ b/tokens/libcryptsetup-token.sym
@@ -0,0 +1,9 @@
+CRYPTSETUP_TOKEN_1.0 {
+ global: cryptsetup_token_open;
+ cryptsetup_token_open_pin;
+ cryptsetup_token_buffer_free;
+ cryptsetup_token_validate;
+ cryptsetup_token_dump;
+ cryptsetup_token_version;
+ local: *;
+};
diff --git a/tokens/ssh/cryptsetup-ssh.c b/tokens/ssh/cryptsetup-ssh.c
new file mode 100644
index 0000000..7c0bf02
--- /dev/null
+++ b/tokens/ssh/cryptsetup-ssh.c
@@ -0,0 +1,420 @@
+/*
+ * Example of LUKS2 token storing third party metadata (EXPERIMENTAL EXAMPLE)
+ *
+ * Copyright (C) 2016-2023 Milan Broz
+ * Copyright (C) 2021-2023 Vojtech Trefny
+ *
+ * Use:
+ * - generate ssh example token
+ *
+ * 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 the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <argp.h>
+#include <json-c/json.h>
+#include <termios.h>
+#include <stdbool.h>
+#include "libcryptsetup.h"
+#include "ssh-utils.h"
+#include "../src/cryptsetup.h"
+
+#define TOKEN_NAME "ssh"
+
+#define l_err(cd, x...) crypt_logf(cd, CRYPT_LOG_ERROR, x)
+#define l_dbg(cd, x...) crypt_logf(cd, CRYPT_LOG_DEBUG, x)
+
+#define OPT_SSH_SERVER 1
+#define OPT_SSH_USER 2
+#define OPT_SSH_PATH 3
+#define OPT_KEY_PATH 4
+#define OPT_DEBUG 5
+#define OPT_DEBUG_JSON 6
+#define OPT_KEY_SLOT 7
+
+void tools_cleanup(void)
+{
+}
+
+
+static int token_add(
+ const char *device,
+ const char *server,
+ const char *user,
+ const char *path,
+ const char *keypath,
+ int keyslot)
+
+{
+ struct crypt_device *cd;
+ json_object *jobj = NULL;
+ json_object *jobj_keyslots = NULL;
+ const char *string_token;
+ int r, token;
+
+ r = crypt_init(&cd, device);
+ if (r)
+ return r;
+
+ r = crypt_load(cd, CRYPT_LUKS2, NULL);
+ if (r) {
+ l_err(cd, _("Device %s is not a valid LUKS device."), device);
+ goto out;
+ }
+
+ r = -EINVAL;
+ jobj = json_object_new_object();
+ if (!jobj)
+ goto out;
+
+ /* type is mandatory field in all tokens and must match handler name member */
+ json_object_object_add(jobj, "type", json_object_new_string(TOKEN_NAME));
+
+ jobj_keyslots = json_object_new_array();
+
+ /* mandatory array field (may be empty and assigned later */
+ json_object_object_add(jobj, "keyslots", jobj_keyslots);
+
+ /* custom metadata */
+ json_object_object_add(jobj, "ssh_server", json_object_new_string(server));
+ json_object_object_add(jobj, "ssh_user", json_object_new_string(user));
+ json_object_object_add(jobj, "ssh_path", json_object_new_string(path));
+ json_object_object_add(jobj, "ssh_keypath", json_object_new_string(keypath));
+
+ string_token = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN);
+ if (!string_token) {
+ r = -EINVAL;
+ goto out;
+ }
+
+ l_dbg(cd, "Token JSON: %s", string_token);
+
+ r = crypt_token_json_set(cd, CRYPT_ANY_TOKEN, string_token);
+ if (r < 0) {
+ l_err(cd, _("Failed to write ssh token json."));
+ goto out;
+ }
+
+ token = r;
+ r = crypt_token_assign_keyslot(cd, token, keyslot);
+ if (r != token) {
+ crypt_token_json_set(cd, token, NULL);
+ r = -EINVAL;
+ }
+out:
+ json_object_put(jobj);
+ crypt_free(cd);
+ return r;
+}
+
+const char *argp_program_version = "cryptsetup-ssh " PACKAGE_VERSION;
+
+static char doc[] = N_("Experimental cryptsetup plugin for unlocking LUKS2 devices with token connected " \
+ "to an SSH server\v" \
+ "This plugin currently allows only adding a token to an existing key slot.\n\n" \
+ "Specified SSH server must contain a key file on the specified path with " \
+ "a passphrase for an existing key slot on the device.\n" \
+ "Provided credentials will be used by cryptsetup to get the password when " \
+ "opening the device using the token.\n\n" \
+ "Note: The information provided when adding the token (SSH server address, user and paths) " \
+ "will be stored in the LUKS2 header in plaintext.");
+
+static char args_doc[] = N_("<action> <device>");
+
+static struct argp_option options[] = {
+ {0, 0, 0, 0, N_("Options for the 'add' action:")},
+ {"ssh-server", OPT_SSH_SERVER, "STRING", 0, N_("IP address/URL of the remote server for this token")},
+ {"ssh-user", OPT_SSH_USER, "STRING", 0, N_("Username used for the remote server")},
+ {"ssh-path", OPT_SSH_PATH, "STRING", 0, N_("Path to the key file on the remote server")},
+ {"ssh-keypath", OPT_KEY_PATH, "STRING", 0, N_("Path to the SSH key for connecting to the remote server")},
+ {"key-slot", OPT_KEY_SLOT, "NUM", 0, N_("Keyslot to assign the token to. If not specified, token will "\
+ "be assigned to the first keyslot matching provided passphrase.")},
+ {0, 0, 0, 0, N_("Generic options:")},
+ {"verbose", 'v', 0, 0, N_("Shows more detailed error messages")},
+ {"debug", OPT_DEBUG, 0, 0, N_("Show debug messages")},
+ {"debug-json", OPT_DEBUG_JSON, 0, 0, N_("Show debug messages including JSON metadata")},
+ { NULL, 0, 0, 0, NULL }
+};
+
+struct arguments {
+ char *device;
+ char *action;
+ char *ssh_server;
+ char *ssh_user;
+ char *ssh_path;
+ char *ssh_keypath;
+ int keyslot;
+ int verbose;
+ int debug;
+ int debug_json;
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state) {
+ struct arguments *arguments = state->input;
+
+ switch (key) {
+ case OPT_SSH_SERVER:
+ arguments->ssh_server = arg;
+ break;
+ case OPT_SSH_USER:
+ arguments->ssh_user = arg;
+ break;
+ case OPT_SSH_PATH:
+ arguments->ssh_path = arg;
+ break;
+ case OPT_KEY_PATH:
+ arguments->ssh_keypath = arg;
+ break;
+ case OPT_KEY_SLOT:
+ arguments->keyslot = atoi(arg);
+ break;
+ case 'v':
+ arguments->verbose = 1;
+ break;
+ case OPT_DEBUG:
+ arguments->debug = 1;
+ break;
+ case OPT_DEBUG_JSON:
+ arguments->debug = 1;
+ arguments->debug_json = 1;
+ break;
+ case ARGP_KEY_NO_ARGS:
+ argp_usage(state);
+ break;
+ case ARGP_KEY_ARG:
+ arguments->action = arg;
+ arguments->device = state->argv[state->next];
+ state->next = state->argc;
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static struct argp argp = { options, parse_opt, args_doc, doc };
+
+
+static void _log(int level, const char *msg, void *usrptr)
+{
+ struct arguments *arguments = (struct arguments *)usrptr;
+
+ switch (level) {
+ case CRYPT_LOG_NORMAL:
+ fprintf(stdout, "%s", msg);
+ break;
+ case CRYPT_LOG_VERBOSE:
+ if (arguments && arguments->verbose)
+ fprintf(stdout, "%s", msg);
+ break;
+ case CRYPT_LOG_ERROR:
+ fprintf(stderr, "%s", msg);
+ break;
+ case CRYPT_LOG_DEBUG_JSON:
+ if (arguments && arguments->debug_json)
+ fprintf(stdout, "# %s", msg);
+ break;
+ case CRYPT_LOG_DEBUG:
+ if (arguments && arguments->debug)
+ fprintf(stdout, "# %s", msg);
+ break;
+ }
+}
+
+static int get_keyslot_for_passphrase(struct arguments *arguments, const char *pin)
+{
+ int r = 0;
+ ssh_key pkey;
+ ssh_session ssh;
+ char *password = NULL;
+ size_t password_len = 0;
+ struct crypt_device *cd = NULL;
+ char *ssh_pass = NULL;
+ size_t key_size = 0;
+ char *prompt = NULL;
+
+ r = crypt_init(&cd, arguments->device);
+ if (r < 0)
+ return r;
+ crypt_set_log_callback(cd, &_log, arguments);
+
+ r = ssh_pki_import_privkey_file(arguments->ssh_keypath, pin, NULL, NULL, &pkey);
+ if (r != SSH_OK) {
+ if (r == SSH_EOF) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Failed to open and import private key:\n"));
+ crypt_free(cd);
+ return -EINVAL;
+ } else {
+ _log(CRYPT_LOG_ERROR, _("Failed to import private key (password protected?).\n"), NULL);
+ /* TRANSLATORS: SSH credentials prompt, e.g. "user@server's password: " */
+ r = asprintf(&prompt, _("%s@%s's password: "), arguments->ssh_user, arguments->ssh_server);
+ if (r < 0) {
+ crypt_safe_free(ssh_pass);
+ crypt_free(cd);
+ return -EINVAL;
+ }
+
+ r = tools_get_key(prompt, &ssh_pass, &key_size, 0, 0, NULL, 0, 0, 0, cd);
+ if (r < 0) {
+ free(prompt);
+ crypt_safe_free(ssh_pass);
+ crypt_free(cd);
+ return -EINVAL;
+ }
+
+ /* now try again with the password */
+ r = get_keyslot_for_passphrase(arguments, ssh_pass);
+
+ crypt_safe_free(ssh_pass);
+ crypt_free(cd);
+ free(prompt);
+
+ return r;
+ }
+ }
+
+ ssh = sshplugin_session_init(cd, arguments->ssh_server, arguments->ssh_user);
+ if (!ssh) {
+ ssh_key_free(pkey);
+ crypt_free(cd);
+ return -EINVAL;
+ }
+
+ r = sshplugin_public_key_auth(cd, ssh, pkey);
+ ssh_key_free(pkey);
+
+ if (r != SSH_AUTH_SUCCESS) {
+ crypt_free(cd);
+ return r;
+ }
+
+ r = sshplugin_download_password(cd, ssh, arguments->ssh_path, &password, &password_len);
+ if (r < 0) {
+ ssh_disconnect(ssh);
+ ssh_free(ssh);
+ crypt_free(cd);
+ return r;
+ }
+
+ ssh_disconnect(ssh);
+ ssh_free(ssh);
+
+ r = crypt_load(cd, CRYPT_LUKS2, NULL);
+ if (r < 0) {
+ crypt_safe_memzero(password, password_len);
+ free(password);
+ crypt_free(cd);
+ return r;
+ }
+
+ r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT, password, password_len, 0);
+ if (r < 0) {
+ crypt_safe_memzero(password, password_len);
+ free(password);
+ crypt_free(cd);
+ return r;
+ }
+
+ arguments->keyslot = r;
+
+ crypt_safe_memzero(password, password_len);
+ free(password);
+ crypt_free(cd);
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+ struct arguments arguments = { 0 };
+ arguments.keyslot = CRYPT_ANY_SLOT;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ ret = argp_parse (&argp, argc, argv, 0, 0, &arguments);
+ if (ret != 0) {
+ printf(_("Failed to parse arguments.\n"));
+ return EXIT_FAILURE;
+ }
+
+ crypt_set_log_callback(NULL, _log, &arguments);
+ if (arguments.debug)
+ crypt_set_debug_level(CRYPT_DEBUG_ALL);
+ if (arguments.debug_json)
+ crypt_set_debug_level(CRYPT_DEBUG_JSON);
+
+ if (arguments.action == NULL) {
+ printf(_("An action must be specified\n"));
+ return EXIT_FAILURE;
+ }
+
+ if (strcmp("add", arguments.action) == 0) {
+ if (!arguments.device) {
+ printf(_("Device must be specified for '%s' action.\n"), arguments.action);
+ return EXIT_FAILURE;
+ }
+
+ if (!arguments.ssh_server) {
+ printf(_("SSH server must be specified for '%s' action.\n"), arguments.action);
+ return EXIT_FAILURE;
+ }
+
+ if (!arguments.ssh_user) {
+ printf(_("SSH user must be specified for '%s' action.\n"), arguments.action);
+ return EXIT_FAILURE;
+ }
+
+ if (!arguments.ssh_path) {
+ printf(_("SSH path must be specified for '%s' action.\n"), arguments.action);
+ return EXIT_FAILURE;
+ }
+
+ if (!arguments.ssh_keypath) {
+ printf(_("SSH key path must be specified for '%s' action.\n"), arguments.action);
+ return EXIT_FAILURE;
+ }
+
+ if (arguments.keyslot == CRYPT_ANY_SLOT) {
+ ret = get_keyslot_for_passphrase(&arguments, NULL);
+ if (ret != 0) {
+ printf(_("Failed open %s using provided credentials.\n"), arguments.device);
+ return EXIT_FAILURE;
+ }
+ }
+
+ ret = token_add(arguments.device,
+ arguments.ssh_server,
+ arguments.ssh_user,
+ arguments.ssh_path,
+ arguments.ssh_keypath,
+ arguments.keyslot);
+ if (ret < 0)
+ return EXIT_FAILURE;
+ else
+ return EXIT_SUCCESS;
+ } else {
+ printf(_("Only 'add' action is currently supported by this plugin.\n"));
+ return EXIT_FAILURE;
+ }
+}
diff --git a/tokens/ssh/libcryptsetup-token-ssh.c b/tokens/ssh/libcryptsetup-token-ssh.c
new file mode 100644
index 0000000..639b25d
--- /dev/null
+++ b/tokens/ssh/libcryptsetup-token-ssh.c
@@ -0,0 +1,193 @@
+/*
+ * Example of LUKS2 ssh token handler (EXPERIMENTAL)
+ *
+ * Copyright (C) 2016-2023 Milan Broz
+ * Copyright (C) 2020-2023 Vojtech Trefny
+ *
+ * Use:
+ * - generate LUKS device
+ * - store passphrase used in previous step remotely (single line w/o \r\n)
+ * - add new token using this example
+ * - activate device by token
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <json-c/json.h>
+#include "libcryptsetup.h"
+#include "ssh-utils.h"
+
+#define TOKEN_NAME "ssh"
+#define TOKEN_VERSION_MAJOR "1"
+#define TOKEN_VERSION_MINOR "0"
+
+#define SERVER_ARG "plugin-ssh-server"
+#define USER_ARG "plugin-ssh-user"
+#define PATH_ARG "plugin-ssh-path"
+#define KEYPATH_ARG "plugin-ssh-keypath"
+
+#define l_dbg(cd, x...) crypt_logf(cd, CRYPT_LOG_DEBUG, x)
+
+
+const char *cryptsetup_token_version(void);
+int cryptsetup_token_open_pin(struct crypt_device *cd, int token, const char *pin,
+ size_t pin_size, char **password, size_t *password_len, void *usrptr);
+int cryptsetup_token_open(struct crypt_device *cd, int token,
+ char **password, size_t *password_len, void *usrptr);
+void cryptsetup_token_dump(struct crypt_device *cd, const char *json);
+int cryptsetup_token_validate(struct crypt_device *cd, const char *json);
+
+
+const char *cryptsetup_token_version(void)
+{
+ return TOKEN_VERSION_MAJOR "." TOKEN_VERSION_MINOR;
+}
+
+static json_object *get_token_jobj(struct crypt_device *cd, int token)
+{
+ const char *json_slot;
+
+ /* libcryptsetup API call */
+ if (crypt_token_json_get(cd, token, &json_slot))
+ return NULL;
+
+ return json_tokener_parse(json_slot);
+}
+
+int cryptsetup_token_open_pin(struct crypt_device *cd, int token, const char *pin,
+ size_t pin_size __attribute__((unused)), char **password, size_t *password_len,
+ void *usrptr __attribute__((unused)))
+{
+ int r;
+ json_object *jobj_server, *jobj_user, *jobj_path, *jobj_token, *jobj_keypath;
+ ssh_key pkey;
+ ssh_session ssh;
+
+ jobj_token = get_token_jobj(cd, token);
+ if (!jobj_token)
+ return -ENOMEM;
+
+ json_object_object_get_ex(jobj_token, "ssh_server", &jobj_server);
+ json_object_object_get_ex(jobj_token, "ssh_user", &jobj_user);
+ json_object_object_get_ex(jobj_token, "ssh_path", &jobj_path);
+ json_object_object_get_ex(jobj_token, "ssh_keypath",&jobj_keypath);
+
+ r = ssh_pki_import_privkey_file(json_object_get_string(jobj_keypath), pin, NULL, NULL, &pkey);
+ if (r != SSH_OK) {
+ json_object_put(jobj_token);
+ if (r == SSH_EOF) {
+ crypt_log(cd, CRYPT_LOG_ERROR, "Failed to open and import private key.\n");
+ return -EINVAL;
+ }
+ crypt_log(cd, CRYPT_LOG_ERROR, "Failed to import private key (password protected?).\n");
+ return -EAGAIN;
+ }
+
+ ssh = sshplugin_session_init(cd, json_object_get_string(jobj_server),
+ json_object_get_string(jobj_user));
+ if (!ssh) {
+ json_object_put(jobj_token);
+ ssh_key_free(pkey);
+ return -EINVAL;
+ }
+
+ r = sshplugin_public_key_auth(cd, ssh, pkey);
+ ssh_key_free(pkey);
+
+ if (r == SSH_AUTH_SUCCESS)
+ r = sshplugin_download_password(cd, ssh, json_object_get_string(jobj_path),
+ password, password_len);
+
+ ssh_disconnect(ssh);
+ ssh_free(ssh);
+ json_object_put(jobj_token);
+
+ return r ? -EINVAL : r;
+}
+
+int cryptsetup_token_open(struct crypt_device *cd, int token,
+ char **password, size_t *password_len, void *usrptr)
+{
+ return cryptsetup_token_open_pin(cd, token, NULL, 0, password, password_len, usrptr);
+}
+
+void cryptsetup_token_dump(struct crypt_device *cd, const char *json)
+{
+ json_object *jobj_token, *jobj_server, *jobj_user, *jobj_path, *jobj_keypath;
+ char buf[4096];
+
+ jobj_token = json_tokener_parse(json);
+ if (!jobj_token)
+ return;
+
+ json_object_object_get_ex(jobj_token, "ssh_server", &jobj_server);
+ json_object_object_get_ex(jobj_token, "ssh_user", &jobj_user);
+ json_object_object_get_ex(jobj_token, "ssh_path", &jobj_path);
+ json_object_object_get_ex(jobj_token, "ssh_keypath",&jobj_keypath);
+
+ if (snprintf(buf, sizeof(buf) - 1, "\tssh_server: %s\n\tssh_user: %s\n"
+ "\tssh_path: %s\n\tssh_key_path: %s\n",
+ json_object_get_string(jobj_server),
+ json_object_get_string(jobj_user),
+ json_object_get_string(jobj_path),
+ json_object_get_string(jobj_keypath)) > 0)
+ crypt_log(cd, CRYPT_LOG_NORMAL, buf);
+
+ json_object_put(jobj_token);
+}
+
+int cryptsetup_token_validate(struct crypt_device *cd, const char *json)
+{
+ enum json_tokener_error jerr;
+ json_object *jobj_token, *jobj;
+ int r = -EINVAL;
+
+ jobj_token = json_tokener_parse_verbose(json, &jerr);
+ if (!jobj_token)
+ return -EINVAL;
+
+ if (!json_object_object_get_ex(jobj_token, "ssh_server", &jobj) ||
+ !json_object_is_type(jobj, json_type_string)) {
+ l_dbg(cd, "ssh_server element is missing or not string.");
+ goto out;
+ }
+
+ if (!json_object_object_get_ex(jobj_token, "ssh_user", &jobj) ||
+ !json_object_is_type(jobj, json_type_string)) {
+ l_dbg(cd, "ssh_user element is missing or not string.");
+ goto out;
+ }
+
+ if (!json_object_object_get_ex(jobj_token, "ssh_path", &jobj) ||
+ !json_object_is_type(jobj, json_type_string)) {
+ l_dbg(cd, "ssh_path element is missing or not string.");
+ goto out;
+ }
+
+ if (!json_object_object_get_ex(jobj_token, "ssh_keypath", &jobj) ||
+ !json_object_is_type(jobj, json_type_string)) {
+ l_dbg(cd, "ssh_keypath element is missing or not string.");
+ goto out;
+ }
+
+ r = 0;
+out:
+ json_object_put(jobj_token);
+ return r;
+}
diff --git a/tokens/ssh/ssh-utils.c b/tokens/ssh/ssh-utils.c
new file mode 100644
index 0000000..564d858
--- /dev/null
+++ b/tokens/ssh/ssh-utils.c
@@ -0,0 +1,177 @@
+/*
+ * ssh plugin utilities
+ *
+ * Copyright (C) 2016-2023 Milan Broz
+ * Copyright (C) 2020-2023 Vojtech Trefny
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <libssh/libssh.h>
+#include <libssh/sftp.h>
+#include <fcntl.h>
+#include <libcryptsetup.h>
+#include "ssh-utils.h"
+#include "../lib/nls.h"
+
+#define KEYFILE_LENGTH_MAX 8192
+
+int sshplugin_download_password(struct crypt_device *cd, ssh_session ssh,
+ const char *path, char **password, size_t *password_len)
+{
+ char *pass = NULL;
+ size_t pass_len;
+ int r;
+ sftp_attributes sftp_attr = NULL;
+ sftp_session sftp = NULL;
+ sftp_file file = NULL;
+
+ sftp = sftp_new(ssh);
+ if (!sftp) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Cannot create sftp session: "));
+ r = SSH_FX_FAILURE;
+ goto out;
+ }
+
+ r = sftp_init(sftp);
+ if (r != SSH_OK) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Cannot init sftp session: "));
+ goto out;
+ }
+
+ file = sftp_open(sftp, path, O_RDONLY, 0);
+ if (!file) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Cannot open sftp session: "));
+ r = SSH_FX_FAILURE;
+ goto out;
+ }
+
+ sftp_attr = sftp_fstat(file);
+ if (!sftp_attr) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Cannot stat sftp file: "));
+ r = SSH_FX_FAILURE;
+ goto out;
+ }
+
+ pass_len = sftp_attr->size > KEYFILE_LENGTH_MAX ? KEYFILE_LENGTH_MAX : sftp_attr->size;
+ pass = malloc(pass_len);
+ if (!pass) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Not enough memory.\n"));
+ r = SSH_FX_FAILURE;
+ goto out;
+ }
+
+ r = sftp_read(file, pass, pass_len);
+ if (r < 0 || (size_t)r != pass_len) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Cannot read remote key: "));
+ r = SSH_FX_FAILURE;
+ goto out;
+ }
+
+ *password = pass;
+ *password_len = pass_len;
+
+ r = SSH_OK;
+out:
+ if (r != SSH_OK) {
+ crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
+ crypt_log(cd, CRYPT_LOG_ERROR, "\n");
+ free(pass);
+ }
+
+ if (sftp_attr)
+ sftp_attributes_free(sftp_attr);
+
+ if (file)
+ sftp_close(file);
+ if (sftp)
+ sftp_free(sftp);
+ return r == SSH_OK ? 0 : -EINVAL;
+}
+
+ssh_session sshplugin_session_init(struct crypt_device *cd, const char *host, const char *user)
+{
+ int r, port = 22;
+ ssh_session ssh = ssh_new();
+ if (!ssh)
+ return NULL;
+
+ ssh_options_set(ssh, SSH_OPTIONS_HOST, host);
+ ssh_options_set(ssh, SSH_OPTIONS_USER, user);
+ ssh_options_set(ssh, SSH_OPTIONS_PORT, &port);
+
+ crypt_log(cd, CRYPT_LOG_NORMAL, "SSH token initiating ssh session.\n");
+
+ r = ssh_connect(ssh);
+ if (r != SSH_OK) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Connection failed: "));
+ goto out;
+ }
+
+#if HAVE_DECL_SSH_SESSION_IS_KNOWN_SERVER
+ r = ssh_session_is_known_server(ssh);
+#else
+ r = ssh_is_server_known(ssh);
+#endif
+ if (r != SSH_SERVER_KNOWN_OK) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Server not known: "));
+ r = SSH_AUTH_ERROR;
+ goto out;
+ }
+
+ r = SSH_OK;
+
+ /* initialise list of authentication methods. yes, according to official libssh docs... */
+ ssh_userauth_none(ssh, NULL);
+out:
+ if (r != SSH_OK) {
+ crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
+ crypt_log(cd, CRYPT_LOG_ERROR, "\n");
+ ssh_disconnect(ssh);
+ ssh_free(ssh);
+ ssh = NULL;
+ }
+
+ return ssh;
+}
+
+int sshplugin_public_key_auth(struct crypt_device *cd, ssh_session ssh, const ssh_key pkey)
+{
+ int r;
+
+ crypt_log(cd, CRYPT_LOG_DEBUG, "Trying public key authentication method.\n");
+
+ if (!(ssh_userauth_list(ssh, NULL) & SSH_AUTH_METHOD_PUBLICKEY)) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Public key auth method not allowed on host.\n"));
+ return SSH_AUTH_ERROR;
+ }
+
+ r = ssh_userauth_try_publickey(ssh, NULL, pkey);
+ if (r == SSH_AUTH_SUCCESS) {
+ crypt_log(cd, CRYPT_LOG_DEBUG, "Public key method accepted.\n");
+ r = ssh_userauth_publickey(ssh, NULL, pkey);
+ }
+
+ if (r != SSH_AUTH_SUCCESS) {
+ crypt_log(cd, CRYPT_LOG_ERROR, _("Public key authentication error: "));
+ crypt_log(cd, CRYPT_LOG_ERROR, ssh_get_error(ssh));
+ crypt_log(cd, CRYPT_LOG_ERROR, "\n");
+ }
+
+ return r;
+}
diff --git a/tokens/ssh/ssh-utils.h b/tokens/ssh/ssh-utils.h
new file mode 100644
index 0000000..a491275
--- /dev/null
+++ b/tokens/ssh/ssh-utils.h
@@ -0,0 +1,29 @@
+/*
+ * ssh plugin utilities
+ *
+ * Copyright (C) 2016-2023 Milan Broz
+ * Copyright (C) 2020-2023 Vojtech Trefny
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <libssh/libssh.h>
+#include <libssh/sftp.h>
+#include <libcryptsetup.h>
+
+int sshplugin_download_password(struct crypt_device *cd, ssh_session ssh,
+ const char *path, char **password, size_t *password_len);
+ssh_session sshplugin_session_init(struct crypt_device *cd, const char *host, const char *user);
+int sshplugin_public_key_auth(struct crypt_device *cd, ssh_session ssh, const ssh_key pkey);