New upstream version 2.6.1
This commit is contained in:
parent
afbb21d063
commit
fa551524b1
|
@ -4,9 +4,10 @@ set -ex
|
|||
|
||||
PACKAGES=(
|
||||
git make autoconf automake autopoint pkg-config libtool libtool-bin
|
||||
gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev
|
||||
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:?}"
|
||||
|
|
|
@ -2,9 +2,10 @@ name: Build test
|
|||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'main'
|
||||
- 'wip-luks2'
|
||||
- 'v2.3.x'
|
||||
- 'v2.4.x'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ Makefile.in.in
|
|||
*.lo
|
||||
*.la
|
||||
*.o
|
||||
*.so
|
||||
*.8
|
||||
**/*.dirstamp
|
||||
.deps/
|
||||
.libs/
|
||||
|
@ -54,3 +56,6 @@ 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*
|
||||
|
|
120
.gitlab-ci.yml
120
.gitlab-ci.yml
|
@ -1,113 +1,23 @@
|
|||
stages:
|
||||
- test
|
||||
|
||||
.debian-prep:
|
||||
before_script:
|
||||
- sudo apt-get -y update --fix-missing
|
||||
- >
|
||||
sudo apt-get -y install -y -qq git gcc make
|
||||
autoconf automake autopoint pkg-config libtool libtool-bin gettext
|
||||
libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-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
|
||||
- sudo apt-get -y build-dep cryptsetup
|
||||
- sudo -E git clean -xdf
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-libargon2
|
||||
|
||||
.dnf-openssl-backend:
|
||||
before_script:
|
||||
- >
|
||||
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
|
||||
- sudo -E git clean -xdf
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-fips --enable-pwquality --enable-libargon2 --with-crypto_backend=openssl
|
||||
|
||||
# Merge request: Build and run only non-root tests
|
||||
test-mergerq-job-debian-noroot:
|
||||
extends:
|
||||
- .debian-prep
|
||||
tags:
|
||||
- libvirt
|
||||
- debian10
|
||||
stage: test
|
||||
interruptible: true
|
||||
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
|
||||
- make check
|
||||
|
||||
# For main branch commit, run all tests as root
|
||||
test-main-commit-job-debian:
|
||||
extends:
|
||||
- .debian-prep
|
||||
tags:
|
||||
- libvirt
|
||||
- debian10
|
||||
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
|
||||
- sudo -E make clean
|
||||
|
||||
test-main-commit-job-dnf:
|
||||
extends:
|
||||
- .dnf-openssl-backend
|
||||
tags:
|
||||
- libvirt
|
||||
- fedora-rawhide
|
||||
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
|
||||
|
||||
test-mergerq-job-dnf:
|
||||
extends:
|
||||
- .dnf-openssl-backend
|
||||
tags:
|
||||
- libvirt
|
||||
- fedora-rawhide
|
||||
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
|
||||
.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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -4,9 +4,10 @@ set -ex
|
|||
|
||||
PACKAGES=(
|
||||
git make autoconf automake autopoint pkg-config libtool libtool-bin
|
||||
gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev
|
||||
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:?}"
|
||||
|
@ -42,7 +43,7 @@ apt-get -y build-dep cryptsetup
|
|||
|
||||
echo "====================== VERSIONS ==================="
|
||||
if [[ $COMPILER == "clang" ]]; then
|
||||
scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} --help
|
||||
echo "Using scan-build${COMPILER_VERSION:+-$COMPILER_VERSION}"
|
||||
fi
|
||||
|
||||
${COMPILER}-$COMPILER_VERSION -v
|
||||
|
|
|
@ -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/
|
|
@ -15,8 +15,10 @@ CLANG="clang${COMPILER_VERSION:+-$COMPILER_VERSION}"
|
|||
#PEDANTIC="-pedantic -std=gnu99 -Wno-variadic-macros"
|
||||
#CONVERSION="-Wconversion"
|
||||
|
||||
EXTRA="-Wextra \
|
||||
EXTRA="\
|
||||
-Wextra \
|
||||
-Wsign-compare \
|
||||
-Wcast-align
|
||||
-Werror-implicit-function-declaration \
|
||||
-Wpointer-arith \
|
||||
-Wwrite-strings \
|
||||
|
@ -27,7 +29,6 @@ EXTRA="-Wextra \
|
|||
-Wold-style-definition \
|
||||
-Wno-missing-field-initializers \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-attributes \
|
||||
-Wno-long-long"
|
||||
|
||||
exec $CLANG $PEDANTIC $CONVERSION \
|
||||
|
@ -43,13 +44,6 @@ exec $CLANG $PEDANTIC $CONVERSION \
|
|||
-Wnested-externs \
|
||||
-Wcomment \
|
||||
-Winline \
|
||||
-Wcast-align \
|
||||
-Wcast-qual \
|
||||
-Wredundant-decls $EXTRA \
|
||||
"$@" 2>&1 | {
|
||||
if [[ $USE_FILTER -eq 1 ]]; then
|
||||
.gitlab/ci/warnings_filter.py
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
"$@"
|
||||
|
|
|
@ -3,23 +3,25 @@ test-clang-compilation:
|
|||
- .gitlab-shared-clang
|
||||
script:
|
||||
- export CFLAGS="-Wall -Werror"
|
||||
- ./configure --enable-pwquality --enable-libargon2
|
||||
- ./configure
|
||||
- make -j
|
||||
- make -j check-programs
|
||||
|
||||
# Clang doesn't support json output, so we cannot use the warnings filter
|
||||
# test-clang-Wall-script:
|
||||
# extends:
|
||||
# - .gitlab-shared-clang
|
||||
# script:
|
||||
# - export CFLAGS="-g -O0"
|
||||
# - export CC=".gitlab/ci/clang-Wall"
|
||||
# - ./configure --enable-pwquality --enable-libargon2
|
||||
# - make -j CFLAGS="-g -O0 -Werror"
|
||||
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" --enable-internal-sse-argon2 --enable-pwquality --enable-libargon2
|
||||
- scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} -V ./configure CFLAGS="-g -O0"
|
||||
- make clean
|
||||
- scan-build${COMPILER_VERSION:+-$COMPILER_VERSION} -maxloop 10 make -j
|
||||
- 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
|
||||
|
|
|
@ -3,22 +3,25 @@ test-gcc-compilation:
|
|||
- .gitlab-shared-gcc
|
||||
script:
|
||||
- export CFLAGS="-Wall -Werror"
|
||||
- ./configure --enable-pwquality --enable-libargon2
|
||||
- ./configure
|
||||
- make -j
|
||||
- make -j check-programs
|
||||
|
||||
test-gcc-Wall-script:
|
||||
extends:
|
||||
- .gitlab-shared-gcc
|
||||
script:
|
||||
- export CFLAGS="-g -O0"
|
||||
- export CC=".gitlab/ci/gcc-Wall"
|
||||
- USE_FILTER=0 ./configure --enable-pwquality --enable-libargon2
|
||||
- USE_FILTER=1 make -j CFLAGS="-g -O0 -fdiagnostics-format=json"
|
||||
- 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 --enable-pwquality --enable-libargon2
|
||||
- ./configure
|
||||
- make -j
|
||||
- make -j check-programs
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -16,6 +16,8 @@ GCC="gcc${COMPILER_VERSION:+-$COMPILER_VERSION}"
|
|||
#CONVERSION="-Wconversion"
|
||||
# -Wpacked \
|
||||
|
||||
# This does more than expected for gcc (mixed code with declarations)
|
||||
# -Wdeclaration-after-statement \
|
||||
|
||||
EXTRA="-Wextra \
|
||||
-Wsign-compare \
|
||||
|
@ -27,14 +29,14 @@ EXTRA="-Wextra \
|
|||
-Wstrict-aliasing=3 \
|
||||
-Winit-self \
|
||||
-Wunsafe-loop-optimizations \
|
||||
-Wdeclaration-after-statement \
|
||||
-Wold-style-definition \
|
||||
-Wno-missing-field-initializers \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-attributes \
|
||||
-Wno-long-long \
|
||||
-Wmaybe-uninitialized \
|
||||
-Wvla"
|
||||
-Wvla \
|
||||
-Wformat-overflow \
|
||||
-Wformat-truncation"
|
||||
|
||||
exec $GCC $PEDANTIC $CONVERSION \
|
||||
-Wall $Wuninitialized \
|
||||
|
@ -49,13 +51,7 @@ exec $GCC $PEDANTIC $CONVERSION \
|
|||
-Wnested-externs \
|
||||
-Wcomment \
|
||||
-Winline \
|
||||
-Wcast-align \
|
||||
-Wcast-align=strict \
|
||||
-Wcast-qual \
|
||||
-Wredundant-decls $EXTRA \
|
||||
"$@" 2>&1 | {
|
||||
if [[ $USE_FILTER -eq 1 ]]; then
|
||||
.gitlab/ci/warnings_filter.py
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
"$@"
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
stage: test
|
||||
interruptible: true
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
|
||||
- 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}"
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,31 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import json
|
||||
import linecache
|
||||
|
||||
if __name__ == "__main__":
|
||||
json_string = sys.stdin.read()
|
||||
if json_string in [None, ""]:
|
||||
sys.exit(0)
|
||||
|
||||
parsed = json.loads(json_string)
|
||||
#print(json.dumps(parsed, indent=4, sort_keys=True))
|
||||
|
||||
r = 0
|
||||
|
||||
for o in parsed:
|
||||
kind = o["kind"]
|
||||
|
||||
start = o["locations"][0]["caret"]
|
||||
l = linecache.getline(start["file"], int(start["line"]))
|
||||
|
||||
ignored = "json_object_object_foreach" in l
|
||||
|
||||
print(f"{o['kind']} {'ignored' if ignored else 'FOUND'} in {start['file']}:{start['line']}:{start['column']} {o['message']}")
|
||||
print(f"line contains:\n\t{l}", end="")
|
||||
|
||||
if not ignored:
|
||||
r = 1
|
||||
|
||||
sys.exit(r)
|
|
@ -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"
|
860
FAQ → FAQ.md
860
FAQ → FAQ.md
File diff suppressed because it is too large
Load Diff
23
Makefile.am
23
Makefile.am
|
@ -1,5 +1,5 @@
|
|||
EXTRA_DIST = README.md COPYING.LGPL FAQ docs misc autogen.sh
|
||||
SUBDIRS = po tests
|
||||
EXTRA_DIST = README.md COPYING.LGPL FAQ.md docs misc autogen.sh
|
||||
SUBDIRS = po tests tests/fuzz
|
||||
CLEANFILES =
|
||||
DISTCLEAN_TARGETS =
|
||||
|
||||
|
@ -14,9 +14,15 @@ AM_CPPFLAGS = \
|
|||
-DVERSION=\""$(VERSION)"\" \
|
||||
-DEXTERNAL_LUKS2_TOKENS_PATH=\"${EXTERNAL_LUKS2_TOKENS_PATH}\"
|
||||
AM_CFLAGS = -Wall
|
||||
AM_CXXFLAGS = -Wall
|
||||
AM_LDFLAGS =
|
||||
|
||||
LDADD = $(LTLIBINTL) -lm
|
||||
if ENABLE_FUZZ_TARGETS
|
||||
AM_CFLAGS += -fsanitize=fuzzer-no-link
|
||||
AM_CXXFLAGS += -fsanitize=fuzzer-no-link
|
||||
endif
|
||||
|
||||
LDADD = $(LTLIBINTL)
|
||||
|
||||
tmpfilesddir = @DEFAULT_TMPFILESDIR@
|
||||
|
||||
|
@ -27,6 +33,7 @@ sbin_PROGRAMS =
|
|||
man8_MANS =
|
||||
tmpfilesd_DATA =
|
||||
pkgconfig_DATA =
|
||||
dist_noinst_DATA =
|
||||
|
||||
include man/Makemodule.am
|
||||
|
||||
|
@ -46,7 +53,7 @@ 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-external-tokens --enable-ssh-token --enable-asciidoc
|
||||
|
||||
distclean-local:
|
||||
-find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f
|
||||
|
@ -60,3 +67,11 @@ install-data-local:
|
|||
|
||||
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
|
||||
|
|
163
README.md
163
README.md
|
@ -2,106 +2,147 @@
|
|||
|
||||
What the ...?
|
||||
=============
|
||||
**Cryptsetup** is a utility used to conveniently set up disk encryption based
|
||||
on the [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
|
||||
**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 include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**,
|
||||
**TrueCrypt** (including **VeraCrypt** extension) and **BitLocker** formats.
|
||||
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
|
||||
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module
|
||||
and **integritysetup** to setup
|
||||
[DMIntegrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity) block integrity kernel module.
|
||||
|
||||
[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 hard 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.
|
||||
**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.
|
||||
|
||||
### Specifications
|
||||
### Specification and documentation
|
||||
|
||||
Last version of the LUKS2 format specification is
|
||||
[available here](https://gitlab.com/cryptsetup/LUKS2-docs).
|
||||
|
||||
Last version of the LUKS1 format specification is
|
||||
[available here](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
|
||||
|
||||
Why LUKS?
|
||||
---------
|
||||
* compatibility via standardization,
|
||||
* secure against low entropy attacks,
|
||||
* support for multiple keys,
|
||||
* effective passphrase revocation,
|
||||
* free.
|
||||
|
||||
[Project home page](https://gitlab.com/cryptsetup/cryptsetup/).
|
||||
-----------------
|
||||
|
||||
[Frequently asked questions (FAQ)](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
|
||||
--------------------------------
|
||||
* 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/).
|
||||
All release tarballs and release notes are hosted on
|
||||
[kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
|
||||
|
||||
**The latest stable cryptsetup version is 2.4.3**
|
||||
* [cryptsetup-2.4.3.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.3.tar.xz)
|
||||
* Signature [cryptsetup-2.4.3.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.3.tar.sign)
|
||||
**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.4.3 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/v2.4.3-ReleaseNotes).
|
||||
* [Cryptsetup 2.6.1 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.6/v2.6.1-ReleaseNotes).
|
||||
|
||||
Previous versions
|
||||
* [Version 2.3.7](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.7.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.7.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.7-ReleaseNotes).
|
||||
* [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 docs
|
||||
-------------------
|
||||
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).
|
||||
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.
|
||||
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/).
|
||||
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).
|
||||
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.
|
||||
For available compile options, check ``configure --help`` for more info. If you are using a git snapshot, you need to generate a configure script with ``autogen.sh`` script.
|
||||
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 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 you also need to install `sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass`
|
||||
**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.
|
||||
|
||||
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.
|
||||
|
||||
* [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions)
|
||||
* LUKS Specifications
|
||||
* [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
|
||||
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 dm-crypt mailing list, [dm-crypt@saout.de](mailto:dm-crypt@saout.de). To subscribe send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
|
||||
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 archives using the following resources:
|
||||
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.
|
||||
|
||||
* [list archive](https://www.saout.de/pipermail/dm-crypt/)
|
||||
* [web interface on lore.kernel.org](https://lore.kernel.org/dm-crypt/)
|
||||
* [marc.info](https://marc.info/?l=dm-crypt).
|
||||
The former dm-crypt [list archive](https://lore.kernel.org/dm-crypt/) is also available.
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -74,7 +74,7 @@ autopoint --force $AP_OPTS
|
|||
libtoolize --force --copy
|
||||
aclocal -I m4 $AL_OPTS
|
||||
autoheader $AH_OPTS
|
||||
automake --add-missing --copy --gnu $AM_OPTS
|
||||
automake --force-missing --add-missing --copy --gnu $AM_OPTS
|
||||
autoconf $AC_OPTS
|
||||
|
||||
echo
|
||||
|
|
82
configure.ac
82
configure.ac
|
@ -1,9 +1,9 @@
|
|||
AC_PREREQ([2.67])
|
||||
AC_INIT([cryptsetup],[2.4.3])
|
||||
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=19:0:7
|
||||
LIBCRYPTSETUP_VERSION_INFO=21:0:9
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
AC_CONFIG_SRCDIR(src/cryptsetup.c)
|
||||
|
@ -28,13 +28,13 @@ 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
|
||||
AM_ICONV
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
|
||||
|
@ -53,12 +53,33 @@ 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 sys/ioctl.h sys/mman.h \
|
||||
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])],
|
||||
[[
|
||||
|
@ -130,6 +151,7 @@ if test "x$enable_external_tokens" = "xyes"; then
|
|||
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]),
|
||||
|
@ -193,6 +215,17 @@ if test "x$enable_pwquality" = "xyes"; then
|
|||
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],
|
||||
|
@ -362,11 +395,6 @@ AC_ARG_ENABLE([veritysetup],
|
|||
[], [enable_veritysetup=yes])
|
||||
AM_CONDITIONAL(VERITYSETUP, test "x$enable_veritysetup" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE([cryptsetup-reencrypt],
|
||||
AS_HELP_STRING([--disable-cryptsetup-reencrypt], [disable cryptsetup-reencrypt tool]),
|
||||
[], [enable_cryptsetup_reencrypt=yes])
|
||||
AM_CONDITIONAL(REENCRYPT, test "x$enable_cryptsetup_reencrypt" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE([integritysetup],
|
||||
AS_HELP_STRING([--disable-integritysetup], [disable integritysetup support]),
|
||||
[], [enable_integritysetup=yes])
|
||||
|
@ -419,7 +447,7 @@ if test "x$enable_ssh_token" = "xyes"; then
|
|||
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_usage],[argp])
|
||||
AC_SEARCH_LIBS([argp_parse],[argp])
|
||||
AC_SUBST(ARGP_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
fi
|
||||
|
@ -560,6 +588,23 @@ if test "x$enable_static_cryptsetup" = "xyes"; then
|
|||
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])
|
||||
|
@ -585,6 +630,22 @@ 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)]))
|
||||
|
@ -707,5 +768,6 @@ lib/libcryptsetup.pc
|
|||
po/Makefile.in
|
||||
scripts/cryptsetup.conf
|
||||
tests/Makefile
|
||||
tests/fuzz/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
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 to specify --align-payload only for luksFormat.
|
||||
* Allow one to specify --align-payload only for luksFormat.
|
||||
|
||||
2012-03-16 Milan Broz <mbroz@redhat.com>
|
||||
* Unify password verification option.
|
||||
|
@ -228,7 +228,7 @@
|
|||
* 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 to activate by internally cached volume key
|
||||
* 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.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* libcryptsetup API log example
|
||||
*
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
* 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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* libcryptsetup API - using LUKS device example
|
||||
*
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
* 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
|
||||
|
|
Binary file not shown.
|
@ -85,7 +85,7 @@ Libcryptsetup API additions:
|
|||
|
||||
* Fix optional password callback handling.
|
||||
|
||||
* Allow to activate by internally cached volume key immediately after
|
||||
* Allow one to activate by internally cached volume key immediately after
|
||||
crypt_format() without active slot (for temporary devices with
|
||||
on-disk metadata)
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ Changes since version 1.4.1
|
|||
* Fix header check to support old (cryptsetup 1.0.0) header alignment.
|
||||
(Regression in 1.4.0)
|
||||
|
||||
* Allow to specify --align-payload only for luksFormat.
|
||||
* Allow one to specify --align-payload only for luksFormat.
|
||||
|
||||
* Add --master-key-file option to luksOpen (open using volume key).
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ Changes since version 1.4.2
|
|||
Device-mapper now retry removal if device is busy.
|
||||
|
||||
* Allow "private" activation (skip some udev global rules) flag.
|
||||
Cryptsetup library API now allows to specify CRYPT_ACTIVATE_PRIVATE,
|
||||
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.)
|
||||
|
|
|
@ -4,7 +4,7 @@ Cryptsetup 1.6.0 Release Notes
|
|||
Changes since version 1.6.0-rc1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Change LUKS default cipher to to use XTS encryption mode,
|
||||
* 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.
|
||||
|
@ -209,7 +209,7 @@ Important changes
|
|||
|
||||
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 is is usable for basic comparison.
|
||||
different results. But it is usable for basic comparison.
|
||||
(Note for example AES-NI decryption optimization effect in example above.)
|
||||
|
||||
Features
|
||||
|
|
|
@ -8,7 +8,7 @@ Changes since version 1.6.1
|
|||
* Fix cipher specification string parsing (found by gcc -fsanitize=address option).
|
||||
|
||||
* Try to map TCRYPT system encryption through partition
|
||||
(allows to activate mapping when other partition on the same device is mounted).
|
||||
(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.)
|
||||
|
|
|
@ -25,7 +25,7 @@ Changes since version 1.6.3
|
|||
|
||||
Please refer to cryptsetup FAQ for detail how to fix this situation.
|
||||
|
||||
* Allow to use --disable-gcrypt-pbkdf2 during configuration
|
||||
* 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
|
||||
|
|
|
@ -38,7 +38,7 @@ Changes since version 1.6.4
|
|||
The command "cryptsetup status" will print basic info, even if you
|
||||
do not provide detached header argument.
|
||||
|
||||
* Allow to specify ECB mode in cryptsetup benchmark.
|
||||
* 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
|
||||
|
|
|
@ -35,14 +35,14 @@ Changes since version 1.6.6
|
|||
* Support permanent device decryption for cryptsetup-reencrypt.
|
||||
To remove LUKS encryption from a device, you can now use --decrypt option.
|
||||
|
||||
* Allow to use --header option in all LUKS commands.
|
||||
* 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
|
||||
to open devices with direct-io but fails on all IO operations later.
|
||||
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.
|
||||
|
|
|
@ -30,7 +30,7 @@ Changes since version 1.6.7
|
|||
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 to use empty password through stdin pipe.
|
||||
* Cryptsetup now allows one to use empty password through stdin pipe.
|
||||
(Intended only for testing in scripts.)
|
||||
|
||||
Cryptsetup API NOTE:
|
||||
|
|
|
@ -3,7 +3,7 @@ Cryptsetup 1.7.4 Release Notes
|
|||
|
||||
Changes since version 1.7.3
|
||||
|
||||
* Allow to specify LUKS1 hash algorithm in Python luksFormat wrapper.
|
||||
* Allow one to specify LUKS1 hash algorithm in Python luksFormat wrapper.
|
||||
|
||||
* Use LUKS1 compiled-in defaults also in Python wrapper.
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ Important features
|
|||
|
||||
Integritysetup is intended to be used for settings that require
|
||||
non-cryptographic data integrity protection with no data encryption.
|
||||
Fo setting integrity protected encrypted devices, see disk authenticated
|
||||
For setting integrity protected encrypted devices, see disk authenticated
|
||||
encryption below.
|
||||
|
||||
Note that after formatting the checksums need to be initialized;
|
||||
|
@ -583,7 +583,7 @@ Unfinished things & TODO for next releases
|
|||
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 collison probability is not negligible).
|
||||
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.
|
||||
|
|
|
@ -30,7 +30,7 @@ Changes since version 2.0.1
|
|||
|
||||
* 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
|
||||
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
|
||||
|
|
|
@ -28,7 +28,7 @@ Changes since version 2.0.2
|
|||
|
||||
* New API extensions for unbound keyslots (LUKS2 only)
|
||||
crypt_keyslot_get_key_size() and crypt_volume_key_get()
|
||||
These functions allow to get key and key size for unbound keyslots.
|
||||
These functions allow one to get key and key size for unbound keyslots.
|
||||
|
||||
* New enum value CRYPT_SLOT_UNBOUND for keyslot status (LUKS2 only).
|
||||
|
||||
|
|
|
@ -170,21 +170,21 @@ These new calls are now exported, for details see libcryptsetup.h:
|
|||
|
||||
* crypt_get_metadata_size
|
||||
* crypt_set_metadata_size
|
||||
allows to set/get area sizes in LUKS header
|
||||
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 to get compiled-in PBKDF parameters.
|
||||
allows one to get compiled-in PBKDF parameters.
|
||||
|
||||
* crypt_keyslot_set_encryption
|
||||
* crypt_keyslot_get_encryption
|
||||
allows to set/get per-keyslot encryption algorithm for LUKS2.
|
||||
allows one to set/get per-keyslot encryption algorithm for LUKS2.
|
||||
|
||||
* crypt_keyslot_get_pbkdf
|
||||
allows to get PBKDF parameters per-keyslot.
|
||||
allows one to get PBKDF parameters per-keyslot.
|
||||
|
||||
and these new defines:
|
||||
* CRYPT_LOG_DEBUG_JSON (message type for JSON debug)
|
||||
|
|
|
@ -9,7 +9,7 @@ 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
|
||||
to access this proprietary disk encryption.
|
||||
one to access this proprietary disk encryption.
|
||||
|
||||
Changes since version 2.2.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -18,7 +18,7 @@ Changes since version 2.3.1
|
|||
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 to store arbitrary keys).
|
||||
area on disk (LUKS2 allows one to store arbitrary keys).
|
||||
|
||||
* Rephrase some error messages and remove redundant end-of-lines.
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ Changes since version 2.3.3
|
|||
|
||||
If users want to use blake2b/blake2s, the kernel algorithm name includes
|
||||
a dash (like "blake2s-256").
|
||||
Theses algorithms can now be used for integritysetup devices.
|
||||
These algorithms can now be used for integritysetup devices.
|
||||
|
||||
* Fix crypto backend to properly handle ECB mode.
|
||||
|
||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -33,7 +33,6 @@ libcryptsetup_la_LIBADD = \
|
|||
@JSON_C_LIBS@ \
|
||||
@BLKID_LIBS@ \
|
||||
@DL_LIBS@ \
|
||||
$(LTLIBICONV) \
|
||||
$(LTLIBINTL) \
|
||||
libcrypto_backend.la \
|
||||
libutils_io.la
|
||||
|
@ -54,8 +53,6 @@ libcryptsetup_la_SOURCES = \
|
|||
lib/utils_loop.h \
|
||||
lib/utils_devpath.c \
|
||||
lib/utils_wipe.c \
|
||||
lib/utils_fips.c \
|
||||
lib/utils_fips.h \
|
||||
lib/utils_device.c \
|
||||
lib/utils_keyring.c \
|
||||
lib/utils_keyring.h \
|
||||
|
@ -70,14 +67,14 @@ libcryptsetup_la_SOURCES = \
|
|||
lib/volumekey.c \
|
||||
lib/random.c \
|
||||
lib/crypt_plain.c \
|
||||
lib/base64.h \
|
||||
lib/base64.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 \
|
||||
|
@ -109,4 +106,6 @@ libcryptsetup_la_SOURCES = \
|
|||
lib/utils_blkid.c \
|
||||
lib/utils_blkid.h \
|
||||
lib/bitlk/bitlk.h \
|
||||
lib/bitlk/bitlk.c
|
||||
lib/bitlk/bitlk.c \
|
||||
lib/fvault2/fvault2.h \
|
||||
lib/fvault2/fvault2.c
|
||||
|
|
605
lib/base64.c
605
lib/base64.c
|
@ -1,605 +0,0 @@
|
|||
/* base64.c -- Encode binary data using printable characters.
|
||||
Copyright (C) 1999-2001, 2004-2006, 2009-2019 Free Software Foundation, Inc.
|
||||
|
||||
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, 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, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Simon Josefsson. Partially adapted from GNU MailUtils
|
||||
* (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
|
||||
* from Paul Eggert, Bruno Haible, and Stepan Kasal.
|
||||
*
|
||||
* See also RFC 4648 <https://www.ietf.org/rfc/rfc4648.txt>.
|
||||
*
|
||||
* Be careful with error checking. Here is how you would typically
|
||||
* use these functions:
|
||||
*
|
||||
* bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
|
||||
* if (!ok)
|
||||
* FAIL: input was not valid base64
|
||||
* if (out == NULL)
|
||||
* FAIL: memory allocation error
|
||||
* OK: data in OUT/OUTLEN
|
||||
*
|
||||
* size_t outlen = base64_encode_alloc (in, inlen, &out);
|
||||
* if (out == NULL && outlen == 0 && inlen != 0)
|
||||
* FAIL: input too long
|
||||
* if (out == NULL)
|
||||
* FAIL: memory allocation error
|
||||
* OK: data in OUT/OUTLEN.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Get prototype. */
|
||||
#include "base64.h"
|
||||
|
||||
/* Get malloc. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Get UCHAR_MAX. */
|
||||
#include <limits.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* C89 compliant way to cast 'char' to 'unsigned char'. */
|
||||
static unsigned char
|
||||
to_uchar (char ch)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
static const char b64c[64] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/* Base64 encode IN array of size INLEN into OUT array. OUT needs
|
||||
to be of length >= BASE64_LENGTH(INLEN), and INLEN needs to be
|
||||
a multiple of 3. */
|
||||
static void
|
||||
base64_encode_fast (const char *restrict in, size_t inlen, char *restrict out)
|
||||
{
|
||||
while (inlen)
|
||||
{
|
||||
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
|
||||
*out++ = b64c[((to_uchar (in[0]) << 4) + (to_uchar (in[1]) >> 4)) & 0x3f];
|
||||
*out++ = b64c[((to_uchar (in[1]) << 2) + (to_uchar (in[2]) >> 6)) & 0x3f];
|
||||
*out++ = b64c[to_uchar (in[2]) & 0x3f];
|
||||
|
||||
inlen -= 3;
|
||||
in += 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
|
||||
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
|
||||
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
|
||||
terminate the output buffer. */
|
||||
void
|
||||
base64_encode (const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t outlen)
|
||||
{
|
||||
/* Note this outlen constraint can be enforced at compile time.
|
||||
I.E. that the output buffer is exactly large enough to hold
|
||||
the encoded inlen bytes. The inlen constraints (of corresponding
|
||||
to outlen, and being a multiple of 3) can change at runtime
|
||||
at the end of input. However the common case when reading
|
||||
large inputs is to have both constraints satisfied, so we depend
|
||||
on both in base_encode_fast(). */
|
||||
if (outlen % 4 == 0 && inlen == outlen / 4 * 3)
|
||||
{
|
||||
base64_encode_fast (in, inlen, out);
|
||||
return;
|
||||
}
|
||||
|
||||
while (inlen && outlen)
|
||||
{
|
||||
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
|
||||
if (!--outlen)
|
||||
break;
|
||||
*out++ = b64c[((to_uchar (in[0]) << 4)
|
||||
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
|
||||
& 0x3f];
|
||||
if (!--outlen)
|
||||
break;
|
||||
*out++ =
|
||||
(inlen
|
||||
? b64c[((to_uchar (in[1]) << 2)
|
||||
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
|
||||
& 0x3f]
|
||||
: '=');
|
||||
if (!--outlen)
|
||||
break;
|
||||
*out++ = inlen ? b64c[to_uchar (in[2]) & 0x3f] : '=';
|
||||
if (!--outlen)
|
||||
break;
|
||||
if (inlen)
|
||||
inlen--;
|
||||
if (inlen)
|
||||
in += 3;
|
||||
}
|
||||
|
||||
if (outlen)
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
/* Allocate a buffer and store zero terminated base64 encoded data
|
||||
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
|
||||
the length of the encoded data, excluding the terminating zero. On
|
||||
return, the OUT variable will hold a pointer to newly allocated
|
||||
memory that must be deallocated by the caller. If output string
|
||||
length would overflow, 0 is returned and OUT is set to NULL. If
|
||||
memory allocation failed, OUT is set to NULL, and the return value
|
||||
indicates length of the requested memory block, i.e.,
|
||||
BASE64_LENGTH(inlen) + 1. */
|
||||
size_t
|
||||
base64_encode_alloc (const char *in, size_t inlen, char **out)
|
||||
{
|
||||
size_t outlen = 1 + BASE64_LENGTH (inlen);
|
||||
|
||||
/* Check for overflow in outlen computation.
|
||||
*
|
||||
* If there is no overflow, outlen >= inlen.
|
||||
*
|
||||
* If the operation (inlen + 2) overflows then it yields at most +1, so
|
||||
* outlen is 0.
|
||||
*
|
||||
* If the multiplication overflows, we lose at least half of the
|
||||
* correct value, so the result is < ((inlen + 2) / 3) * 2, which is
|
||||
* less than (inlen + 2) * 0.66667, which is less than inlen as soon as
|
||||
* (inlen > 4).
|
||||
*/
|
||||
if (inlen > outlen)
|
||||
{
|
||||
*out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out = malloc (outlen);
|
||||
if (!*out)
|
||||
return outlen;
|
||||
|
||||
base64_encode (in, inlen, *out, outlen);
|
||||
|
||||
return outlen - 1;
|
||||
}
|
||||
|
||||
/* With this approach this file works independent of the charset used
|
||||
(think EBCDIC). However, it does assume that the characters in the
|
||||
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
|
||||
1003.1-2001 require that char and unsigned char are 8-bit
|
||||
quantities, though, taking care of that problem. But this may be a
|
||||
potential problem on non-POSIX C99 platforms.
|
||||
|
||||
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
|
||||
as the formal parameter rather than "x". */
|
||||
#define B64(_) \
|
||||
((_) == 'A' ? 0 \
|
||||
: (_) == 'B' ? 1 \
|
||||
: (_) == 'C' ? 2 \
|
||||
: (_) == 'D' ? 3 \
|
||||
: (_) == 'E' ? 4 \
|
||||
: (_) == 'F' ? 5 \
|
||||
: (_) == 'G' ? 6 \
|
||||
: (_) == 'H' ? 7 \
|
||||
: (_) == 'I' ? 8 \
|
||||
: (_) == 'J' ? 9 \
|
||||
: (_) == 'K' ? 10 \
|
||||
: (_) == 'L' ? 11 \
|
||||
: (_) == 'M' ? 12 \
|
||||
: (_) == 'N' ? 13 \
|
||||
: (_) == 'O' ? 14 \
|
||||
: (_) == 'P' ? 15 \
|
||||
: (_) == 'Q' ? 16 \
|
||||
: (_) == 'R' ? 17 \
|
||||
: (_) == 'S' ? 18 \
|
||||
: (_) == 'T' ? 19 \
|
||||
: (_) == 'U' ? 20 \
|
||||
: (_) == 'V' ? 21 \
|
||||
: (_) == 'W' ? 22 \
|
||||
: (_) == 'X' ? 23 \
|
||||
: (_) == 'Y' ? 24 \
|
||||
: (_) == 'Z' ? 25 \
|
||||
: (_) == 'a' ? 26 \
|
||||
: (_) == 'b' ? 27 \
|
||||
: (_) == 'c' ? 28 \
|
||||
: (_) == 'd' ? 29 \
|
||||
: (_) == 'e' ? 30 \
|
||||
: (_) == 'f' ? 31 \
|
||||
: (_) == 'g' ? 32 \
|
||||
: (_) == 'h' ? 33 \
|
||||
: (_) == 'i' ? 34 \
|
||||
: (_) == 'j' ? 35 \
|
||||
: (_) == 'k' ? 36 \
|
||||
: (_) == 'l' ? 37 \
|
||||
: (_) == 'm' ? 38 \
|
||||
: (_) == 'n' ? 39 \
|
||||
: (_) == 'o' ? 40 \
|
||||
: (_) == 'p' ? 41 \
|
||||
: (_) == 'q' ? 42 \
|
||||
: (_) == 'r' ? 43 \
|
||||
: (_) == 's' ? 44 \
|
||||
: (_) == 't' ? 45 \
|
||||
: (_) == 'u' ? 46 \
|
||||
: (_) == 'v' ? 47 \
|
||||
: (_) == 'w' ? 48 \
|
||||
: (_) == 'x' ? 49 \
|
||||
: (_) == 'y' ? 50 \
|
||||
: (_) == 'z' ? 51 \
|
||||
: (_) == '0' ? 52 \
|
||||
: (_) == '1' ? 53 \
|
||||
: (_) == '2' ? 54 \
|
||||
: (_) == '3' ? 55 \
|
||||
: (_) == '4' ? 56 \
|
||||
: (_) == '5' ? 57 \
|
||||
: (_) == '6' ? 58 \
|
||||
: (_) == '7' ? 59 \
|
||||
: (_) == '8' ? 60 \
|
||||
: (_) == '9' ? 61 \
|
||||
: (_) == '+' ? 62 \
|
||||
: (_) == '/' ? 63 \
|
||||
: -1)
|
||||
|
||||
static const signed char b64[0x100] = {
|
||||
B64 (0), B64 (1), B64 (2), B64 (3),
|
||||
B64 (4), B64 (5), B64 (6), B64 (7),
|
||||
B64 (8), B64 (9), B64 (10), B64 (11),
|
||||
B64 (12), B64 (13), B64 (14), B64 (15),
|
||||
B64 (16), B64 (17), B64 (18), B64 (19),
|
||||
B64 (20), B64 (21), B64 (22), B64 (23),
|
||||
B64 (24), B64 (25), B64 (26), B64 (27),
|
||||
B64 (28), B64 (29), B64 (30), B64 (31),
|
||||
B64 (32), B64 (33), B64 (34), B64 (35),
|
||||
B64 (36), B64 (37), B64 (38), B64 (39),
|
||||
B64 (40), B64 (41), B64 (42), B64 (43),
|
||||
B64 (44), B64 (45), B64 (46), B64 (47),
|
||||
B64 (48), B64 (49), B64 (50), B64 (51),
|
||||
B64 (52), B64 (53), B64 (54), B64 (55),
|
||||
B64 (56), B64 (57), B64 (58), B64 (59),
|
||||
B64 (60), B64 (61), B64 (62), B64 (63),
|
||||
B64 (64), B64 (65), B64 (66), B64 (67),
|
||||
B64 (68), B64 (69), B64 (70), B64 (71),
|
||||
B64 (72), B64 (73), B64 (74), B64 (75),
|
||||
B64 (76), B64 (77), B64 (78), B64 (79),
|
||||
B64 (80), B64 (81), B64 (82), B64 (83),
|
||||
B64 (84), B64 (85), B64 (86), B64 (87),
|
||||
B64 (88), B64 (89), B64 (90), B64 (91),
|
||||
B64 (92), B64 (93), B64 (94), B64 (95),
|
||||
B64 (96), B64 (97), B64 (98), B64 (99),
|
||||
B64 (100), B64 (101), B64 (102), B64 (103),
|
||||
B64 (104), B64 (105), B64 (106), B64 (107),
|
||||
B64 (108), B64 (109), B64 (110), B64 (111),
|
||||
B64 (112), B64 (113), B64 (114), B64 (115),
|
||||
B64 (116), B64 (117), B64 (118), B64 (119),
|
||||
B64 (120), B64 (121), B64 (122), B64 (123),
|
||||
B64 (124), B64 (125), B64 (126), B64 (127),
|
||||
B64 (128), B64 (129), B64 (130), B64 (131),
|
||||
B64 (132), B64 (133), B64 (134), B64 (135),
|
||||
B64 (136), B64 (137), B64 (138), B64 (139),
|
||||
B64 (140), B64 (141), B64 (142), B64 (143),
|
||||
B64 (144), B64 (145), B64 (146), B64 (147),
|
||||
B64 (148), B64 (149), B64 (150), B64 (151),
|
||||
B64 (152), B64 (153), B64 (154), B64 (155),
|
||||
B64 (156), B64 (157), B64 (158), B64 (159),
|
||||
B64 (160), B64 (161), B64 (162), B64 (163),
|
||||
B64 (164), B64 (165), B64 (166), B64 (167),
|
||||
B64 (168), B64 (169), B64 (170), B64 (171),
|
||||
B64 (172), B64 (173), B64 (174), B64 (175),
|
||||
B64 (176), B64 (177), B64 (178), B64 (179),
|
||||
B64 (180), B64 (181), B64 (182), B64 (183),
|
||||
B64 (184), B64 (185), B64 (186), B64 (187),
|
||||
B64 (188), B64 (189), B64 (190), B64 (191),
|
||||
B64 (192), B64 (193), B64 (194), B64 (195),
|
||||
B64 (196), B64 (197), B64 (198), B64 (199),
|
||||
B64 (200), B64 (201), B64 (202), B64 (203),
|
||||
B64 (204), B64 (205), B64 (206), B64 (207),
|
||||
B64 (208), B64 (209), B64 (210), B64 (211),
|
||||
B64 (212), B64 (213), B64 (214), B64 (215),
|
||||
B64 (216), B64 (217), B64 (218), B64 (219),
|
||||
B64 (220), B64 (221), B64 (222), B64 (223),
|
||||
B64 (224), B64 (225), B64 (226), B64 (227),
|
||||
B64 (228), B64 (229), B64 (230), B64 (231),
|
||||
B64 (232), B64 (233), B64 (234), B64 (235),
|
||||
B64 (236), B64 (237), B64 (238), B64 (239),
|
||||
B64 (240), B64 (241), B64 (242), B64 (243),
|
||||
B64 (244), B64 (245), B64 (246), B64 (247),
|
||||
B64 (248), B64 (249), B64 (250), B64 (251),
|
||||
B64 (252), B64 (253), B64 (254), B64 (255)
|
||||
};
|
||||
|
||||
#if UCHAR_MAX == 255
|
||||
# define uchar_in_range(c) true
|
||||
#else
|
||||
# define uchar_in_range(c) ((c) <= 255)
|
||||
#endif
|
||||
|
||||
/* Return true if CH is a character from the Base64 alphabet, and
|
||||
false otherwise. Note that '=' is padding and not considered to be
|
||||
part of the alphabet. */
|
||||
bool
|
||||
isbase64 (char ch)
|
||||
{
|
||||
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
|
||||
}
|
||||
|
||||
/* Initialize decode-context buffer, CTX. */
|
||||
void
|
||||
base64_decode_ctx_init (struct base64_decode_context *ctx)
|
||||
{
|
||||
ctx->i = 0;
|
||||
}
|
||||
|
||||
/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
|
||||
none of those four is a newline, then return *IN. Otherwise, copy up to
|
||||
4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
|
||||
index CTX->i and setting CTX->i to reflect the number of bytes copied,
|
||||
and return CTX->buf. In either case, advance *IN to point to the byte
|
||||
after the last one processed, and set *N_NON_NEWLINE to the number of
|
||||
verified non-newline bytes accessible through the returned pointer. */
|
||||
static const char *
|
||||
get_4 (struct base64_decode_context *ctx,
|
||||
char const *restrict *in, char const *restrict in_end,
|
||||
size_t *n_non_newline)
|
||||
{
|
||||
if (ctx->i == 4)
|
||||
ctx->i = 0;
|
||||
|
||||
if (ctx->i == 0)
|
||||
{
|
||||
char const *t = *in;
|
||||
if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
|
||||
{
|
||||
/* This is the common case: no newline. */
|
||||
*in += 4;
|
||||
*n_non_newline = 4;
|
||||
return (const char *) t;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* Copy non-newline bytes into BUF. */
|
||||
char const *p = *in;
|
||||
while (p < in_end)
|
||||
{
|
||||
char c = *p++;
|
||||
if (c != '\n')
|
||||
{
|
||||
ctx->buf[ctx->i++] = c;
|
||||
if (ctx->i == 4)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*in = p;
|
||||
*n_non_newline = ctx->i;
|
||||
return ctx->buf;
|
||||
}
|
||||
}
|
||||
|
||||
#define return_false \
|
||||
do \
|
||||
{ \
|
||||
*outp = out; \
|
||||
return false; \
|
||||
} \
|
||||
while (false)
|
||||
|
||||
/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
|
||||
into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
|
||||
decoding is successful, false otherwise. If *OUTLEN is too small,
|
||||
as many bytes as possible are written to *OUT. On return, advance
|
||||
*OUT to point to the byte after the last one written, and decrement
|
||||
*OUTLEN to reflect the number of bytes remaining in *OUT. */
|
||||
static bool
|
||||
decode_4 (char const *restrict in, size_t inlen,
|
||||
char *restrict *outp, size_t *outleft)
|
||||
{
|
||||
char *out = *outp;
|
||||
if (inlen < 2)
|
||||
return false;
|
||||
|
||||
if (!isbase64 (in[0]) || !isbase64 (in[1]))
|
||||
return false;
|
||||
|
||||
if (*outleft)
|
||||
{
|
||||
*out++ = ((b64[to_uchar (in[0])] << 2)
|
||||
| (b64[to_uchar (in[1])] >> 4));
|
||||
--*outleft;
|
||||
}
|
||||
|
||||
if (inlen == 2)
|
||||
return_false;
|
||||
|
||||
if (in[2] == '=')
|
||||
{
|
||||
if (inlen != 4)
|
||||
return_false;
|
||||
|
||||
if (in[3] != '=')
|
||||
return_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isbase64 (in[2]))
|
||||
return_false;
|
||||
|
||||
if (*outleft)
|
||||
{
|
||||
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
|
||||
| (b64[to_uchar (in[2])] >> 2));
|
||||
--*outleft;
|
||||
}
|
||||
|
||||
if (inlen == 3)
|
||||
return_false;
|
||||
|
||||
if (in[3] == '=')
|
||||
{
|
||||
if (inlen != 4)
|
||||
return_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isbase64 (in[3]))
|
||||
return_false;
|
||||
|
||||
if (*outleft)
|
||||
{
|
||||
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
|
||||
| b64[to_uchar (in[3])]);
|
||||
--*outleft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*outp = out;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Decode base64-encoded input array IN of length INLEN to output array
|
||||
OUT that can hold *OUTLEN bytes. The input data may be interspersed
|
||||
with newlines. Return true if decoding was successful, i.e. if the
|
||||
input was valid base64 data, false otherwise. If *OUTLEN is too
|
||||
small, as many bytes as possible will be written to OUT. On return,
|
||||
*OUTLEN holds the length of decoded bytes in OUT. Note that as soon
|
||||
as any non-alphabet, non-newline character is encountered, decoding
|
||||
is stopped and false is returned. If INLEN is zero, then process
|
||||
only whatever data is stored in CTX.
|
||||
|
||||
Initially, CTX must have been initialized via base64_decode_ctx_init.
|
||||
Subsequent calls to this function must reuse whatever state is recorded
|
||||
in that buffer. It is necessary for when a quadruple of base64 input
|
||||
bytes spans two input buffers.
|
||||
|
||||
If CTX is NULL then newlines are treated as garbage and the input
|
||||
buffer is processed as a unit. */
|
||||
|
||||
bool
|
||||
base64_decode_ctx (struct base64_decode_context *ctx,
|
||||
const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t *outlen)
|
||||
{
|
||||
size_t outleft = *outlen;
|
||||
bool ignore_newlines = ctx != NULL;
|
||||
bool flush_ctx = false;
|
||||
unsigned int ctx_i = 0;
|
||||
|
||||
if (ignore_newlines)
|
||||
{
|
||||
ctx_i = ctx->i;
|
||||
flush_ctx = inlen == 0;
|
||||
}
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t outleft_save = outleft;
|
||||
if (ctx_i == 0 && !flush_ctx)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
/* Save a copy of outleft, in case we need to re-parse this
|
||||
block of four bytes. */
|
||||
outleft_save = outleft;
|
||||
if (!decode_4 (in, inlen, &out, &outleft))
|
||||
break;
|
||||
|
||||
in += 4;
|
||||
inlen -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (inlen == 0 && !flush_ctx)
|
||||
break;
|
||||
|
||||
/* Handle the common case of 72-byte wrapped lines.
|
||||
This also handles any other multiple-of-4-byte wrapping. */
|
||||
if (inlen && *in == '\n' && ignore_newlines)
|
||||
{
|
||||
++in;
|
||||
--inlen;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Restore OUT and OUTLEFT. */
|
||||
out -= outleft_save - outleft;
|
||||
outleft = outleft_save;
|
||||
|
||||
{
|
||||
char const *in_end = in + inlen;
|
||||
char const *non_nl;
|
||||
|
||||
if (ignore_newlines)
|
||||
non_nl = get_4 (ctx, &in, in_end, &inlen);
|
||||
else
|
||||
non_nl = in; /* Might have nl in this case. */
|
||||
|
||||
/* If the input is empty or consists solely of newlines (0 non-newlines),
|
||||
then we're done. Likewise if there are fewer than 4 bytes when not
|
||||
flushing context and not treating newlines as garbage. */
|
||||
if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
|
||||
{
|
||||
inlen = 0;
|
||||
break;
|
||||
}
|
||||
if (!decode_4 (non_nl, inlen, &out, &outleft))
|
||||
break;
|
||||
|
||||
inlen = in_end - in;
|
||||
}
|
||||
}
|
||||
|
||||
*outlen -= outleft;
|
||||
|
||||
return inlen == 0;
|
||||
}
|
||||
|
||||
/* Allocate an output buffer in *OUT, and decode the base64 encoded
|
||||
data stored in IN of size INLEN to the *OUT buffer. On return, the
|
||||
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
|
||||
if the caller is not interested in the decoded length. *OUT may be
|
||||
NULL to indicate an out of memory error, in which case *OUTLEN
|
||||
contains the size of the memory block needed. The function returns
|
||||
true on successful decoding and memory allocation errors. (Use the
|
||||
*OUT and *OUTLEN parameters to differentiate between successful
|
||||
decoding and memory error.) The function returns false if the
|
||||
input was invalid, in which case *OUT is NULL and *OUTLEN is
|
||||
undefined. */
|
||||
bool
|
||||
base64_decode_alloc_ctx (struct base64_decode_context *ctx,
|
||||
const char *in, size_t inlen, char **out,
|
||||
size_t *outlen)
|
||||
{
|
||||
/* This may allocate a few bytes too many, depending on input,
|
||||
but it's not worth the extra CPU time to compute the exact size.
|
||||
The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
|
||||
input ends with "=" and minus another 1 if the input ends with "==".
|
||||
Dividing before multiplying avoids the possibility of overflow. */
|
||||
size_t needlen = 3 * (inlen / 4) + 3;
|
||||
|
||||
*out = malloc (needlen);
|
||||
if (!*out)
|
||||
return true;
|
||||
|
||||
if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
|
||||
{
|
||||
free (*out);
|
||||
*out = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outlen)
|
||||
*outlen = needlen;
|
||||
|
||||
return true;
|
||||
}
|
68
lib/base64.h
68
lib/base64.h
|
@ -1,68 +0,0 @@
|
|||
/* base64.h -- Encode binary data using printable characters.
|
||||
Copyright (C) 2004-2006, 2009-2019 Free Software Foundation, Inc.
|
||||
Written by Simon Josefsson.
|
||||
|
||||
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, 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, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef BASE64_H
|
||||
# define BASE64_H
|
||||
|
||||
/* Get size_t. */
|
||||
# include <stddef.h>
|
||||
|
||||
/* Get bool. */
|
||||
# include <stdbool.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/* This uses that the expression (n+(k-1))/k means the smallest
|
||||
integer >= n/k, i.e., the ceiling of n/k. */
|
||||
# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
|
||||
|
||||
struct base64_decode_context
|
||||
{
|
||||
unsigned int i;
|
||||
char buf[4];
|
||||
};
|
||||
|
||||
extern bool isbase64 (char ch) __attribute__ ((__const__));
|
||||
|
||||
extern void base64_encode (const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t outlen);
|
||||
|
||||
extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
|
||||
|
||||
extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
|
||||
|
||||
extern bool base64_decode_ctx (struct base64_decode_context *ctx,
|
||||
const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t *outlen);
|
||||
|
||||
extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
|
||||
const char *in, size_t inlen,
|
||||
char **out, size_t *outlen);
|
||||
|
||||
#define base64_decode(in, inlen, out, outlen) \
|
||||
base64_decode_ctx (NULL, in, inlen, out, outlen)
|
||||
|
||||
#define base64_decode_alloc(in, inlen, out, outlen) \
|
||||
base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* BASE64_H */
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* BITLK (BitLocker-compatible) volume handling
|
||||
*
|
||||
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2019-2021 Milan Broz
|
||||
* Copyright (C) 2019-2021 Vojtech Trefny
|
||||
* 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
|
||||
|
@ -24,7 +24,6 @@
|
|||
#include <string.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <time.h>
|
||||
#include <iconv.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "bitlk.h"
|
||||
|
@ -234,86 +233,11 @@ static const char* get_bitlk_type_string(BITLKEncryptionType type)
|
|||
}
|
||||
}
|
||||
|
||||
/* TODO -- move to some utils file */
|
||||
static void hexprint(struct crypt_device *cd, const char *d, int n, const char *sep)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < n; i++)
|
||||
log_std(cd, "%02hhx%s", (const char)d[i], sep);
|
||||
}
|
||||
|
||||
static uint64_t filetime_to_unixtime(uint64_t time)
|
||||
{
|
||||
return (time - EPOCH_AS_FILETIME) / HUNDREDS_OF_NANOSECONDS;
|
||||
}
|
||||
|
||||
static int convert_to_utf8(struct crypt_device *cd, uint8_t *input, size_t inlen, char **out)
|
||||
{
|
||||
char *outbuf = NULL;
|
||||
iconv_t ic;
|
||||
size_t ic_inlen = inlen;
|
||||
size_t ic_outlen = inlen;
|
||||
char *ic_outbuf = NULL;
|
||||
size_t r = 0;
|
||||
|
||||
outbuf = malloc(inlen);
|
||||
if (outbuf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(outbuf, 0, inlen);
|
||||
ic_outbuf = outbuf;
|
||||
|
||||
ic = iconv_open("UTF-8", "UTF-16LE");
|
||||
r = iconv(ic, (char **) &input, &ic_inlen, &ic_outbuf, &ic_outlen);
|
||||
iconv_close(ic);
|
||||
|
||||
if (r == 0)
|
||||
*out = strdup(outbuf);
|
||||
else {
|
||||
*out = NULL;
|
||||
log_dbg(cd, "Failed to convert volume description: %s", strerror(errno));
|
||||
r = 0;
|
||||
}
|
||||
|
||||
free(outbuf);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int passphrase_to_utf16(struct crypt_device *cd, char *input, size_t inlen, char **out)
|
||||
{
|
||||
char *outbuf = NULL;
|
||||
iconv_t ic;
|
||||
size_t ic_inlen = inlen;
|
||||
size_t ic_outlen = inlen * 2;
|
||||
char *ic_outbuf = NULL;
|
||||
size_t r = 0;
|
||||
|
||||
if (inlen == 0)
|
||||
return r;
|
||||
|
||||
outbuf = crypt_safe_alloc(inlen * 2);
|
||||
if (outbuf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(outbuf, 0, inlen * 2);
|
||||
ic_outbuf = outbuf;
|
||||
|
||||
ic = iconv_open("UTF-16LE", "UTF-8");
|
||||
r = iconv(ic, &input, &ic_inlen, &ic_outbuf, &ic_outlen);
|
||||
iconv_close(ic);
|
||||
|
||||
if (r == 0) {
|
||||
*out = outbuf;
|
||||
} else {
|
||||
*out = NULL;
|
||||
crypt_safe_free(outbuf);
|
||||
log_dbg(cd, "Failed to convert passphrase: %s", strerror(errno));
|
||||
r = -errno;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -324,19 +248,23 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
|
|||
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 > 2) {
|
||||
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,
|
||||
|
@ -355,20 +283,24 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
|
|||
}
|
||||
|
||||
/* stretch key with salt, skip 4 B (encryption method of the stretch key) */
|
||||
if (key_entry_value == BITLK_ENTRY_VALUE_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,
|
||||
sizeof((*vmk)->salt));
|
||||
BITLK_SALT_SIZE);
|
||||
/* AES-CCM encrypted key */
|
||||
else if (key_entry_value == BITLK_ENTRY_VALUE_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,
|
||||
sizeof((*vmk)->nonce));
|
||||
BITLK_NONCE_SIZE);
|
||||
/* MAC tag */
|
||||
memcpy((*vmk)->mac_tag,
|
||||
data + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE,
|
||||
sizeof((*vmk)->mac_tag));
|
||||
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;
|
||||
|
@ -393,9 +325,16 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
|
|||
} else if (key_entry_value == BITLK_ENTRY_VALUE_RECOVERY_TIME) {
|
||||
;
|
||||
} else if (key_entry_value == BITLK_ENTRY_VALUE_STRING) {
|
||||
if (convert_to_utf8(cd, data + start + BITLK_ENTRY_HEADER_LEN, key_entry_size - BITLK_ENTRY_HEADER_LEN, &string) < 0) {
|
||||
log_err(cd, _("Invalid string found when parsing Volume Master Key."));
|
||||
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) {
|
||||
|
@ -475,6 +414,7 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
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};
|
||||
|
@ -483,9 +423,9 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
int i = 0;
|
||||
int r = 0;
|
||||
int start = 0;
|
||||
int end = 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;
|
||||
|
@ -499,8 +439,8 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
/* 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_err(cd, _("Failed to read BITLK signature from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
log_dbg(cd, "Failed to read BITLK signature from %s.", device_path(device));
|
||||
r = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -511,7 +451,7 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
params->togo = true;
|
||||
fve_offset = BITLK_HEADER_METADATA_OFFSET_TOGO;
|
||||
} else {
|
||||
log_err(cd, _("Invalid or unknown signature for BITLK device."));
|
||||
log_dbg(cd, "Invalid or unknown signature for BITLK device.");
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -581,8 +521,8 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
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);
|
||||
fve_metadata_size = le32_to_cpu(fve.metadata_size);
|
||||
|
||||
switch (le16_to_cpu(fve.encryption)) {
|
||||
/* AES-CBC with Elephant difuser */
|
||||
|
@ -637,40 +577,56 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
|
||||
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_metadata_size - BITLK_FVE_METADATA_HEADER_LEN);
|
||||
fve_entries = malloc(fve_entries_size);
|
||||
if (!fve_entries) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memset(fve_entries, 0, (fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN));
|
||||
memset(fve_entries, 0, fve_entries_size);
|
||||
|
||||
log_dbg(cd, "Reading BITLK FVE metadata entries of size %" PRIu32 " on device %s, offset %" PRIu64 ".",
|
||||
fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN, device_path(device),
|
||||
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN);
|
||||
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_metadata_size - BITLK_FVE_METADATA_HEADER_LEN,
|
||||
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN) != (ssize_t)(fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN)) {
|
||||
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;
|
||||
}
|
||||
|
||||
end = fve_metadata_size - BITLK_FVE_METADATA_HEADER_LEN;
|
||||
while (end - start > 2) {
|
||||
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,
|
||||
|
@ -707,7 +663,11 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
vmk_p = vmk;
|
||||
vmk = vmk->next;
|
||||
/* FVEK */
|
||||
} else if (entry_type == BITLK_ENTRY_TYPE_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;
|
||||
|
@ -715,11 +675,11 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
}
|
||||
memcpy(params->fvek->nonce,
|
||||
fve_entries + start + BITLK_ENTRY_HEADER_LEN,
|
||||
sizeof(params->fvek->nonce));
|
||||
BITLK_NONCE_SIZE);
|
||||
/* MAC tag */
|
||||
memcpy(params->fvek->mac_tag,
|
||||
fve_entries + start + BITLK_ENTRY_HEADER_LEN + BITLK_NONCE_SIZE,
|
||||
sizeof(params->fvek->mac_tag));
|
||||
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;
|
||||
|
@ -731,20 +691,35 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||
/* 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) {
|
||||
r = convert_to_utf8(cd, fve_entries + start + BITLK_ENTRY_HEADER_LEN,
|
||||
entry_size - BITLK_ENTRY_HEADER_LEN,
|
||||
&(params->description));
|
||||
if (r < 0) {
|
||||
BITLK_bitlk_vmk_free(vmk);
|
||||
} 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;
|
||||
|
@ -767,6 +742,7 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
|
|||
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);
|
||||
|
@ -785,7 +761,7 @@ int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_meta
|
|||
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");
|
||||
hexprint(cd, (const char *) vmk_p->salt, 16, "");
|
||||
crypt_log_hex(cd, (const char *) vmk_p->salt, 16, "", 0, NULL);
|
||||
log_std(cd, "\n");
|
||||
|
||||
vk_p = vmk_p->vk;
|
||||
|
@ -835,13 +811,13 @@ static int get_recovery_key(struct crypt_device *cd,
|
|||
- 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;
|
||||
}
|
||||
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] != '-')
|
||||
|
@ -884,13 +860,16 @@ static int parse_external_key_entry(struct crypt_device *cd,
|
|||
struct bitlk_guid guid;
|
||||
char guid_buf[UUID_STR_LEN] = {0};
|
||||
|
||||
while (end - start > 2) {
|
||||
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,
|
||||
|
@ -905,6 +884,8 @@ static int parse_external_key_entry(struct crypt_device *cd,
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -916,6 +897,8 @@ static int parse_external_key_entry(struct crypt_device *cd,
|
|||
;
|
||||
/* 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) {
|
||||
|
@ -949,7 +932,7 @@ static int get_startup_key(struct crypt_device *cd,
|
|||
uint16_t key_entry_type = 0;
|
||||
uint16_t key_entry_value = 0;
|
||||
|
||||
if (passwordLen < BITLK_BEK_FILE_HEADER_LEN)
|
||||
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);
|
||||
|
@ -961,13 +944,14 @@ static int get_startup_key(struct crypt_device *cd,
|
|||
else
|
||||
return -EPERM;
|
||||
|
||||
if (bek_header.metadata_version != 1) {
|
||||
log_err(cd, _("Unsupported BEK metadata version %" PRIu32), bek_header.metadata_version);
|
||||
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 (bek_header.metadata_size != passwordLen) {
|
||||
log_err(cd, _("Unexpected BEK metadata size %" PRIu32 " does not match BEK file length"), bek_header.metadata_size);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1008,7 +992,7 @@ static int bitlk_kdf(struct crypt_device *cd,
|
|||
struct bitlk_kdf_data kdf = {};
|
||||
struct crypt_hash *hd = NULL;
|
||||
int len = 0;
|
||||
char *utf16Password = NULL;
|
||||
char16_t *utf16Password = NULL;
|
||||
int i = 0;
|
||||
int r = 0;
|
||||
|
||||
|
@ -1025,11 +1009,16 @@ static int bitlk_kdf(struct crypt_device *cd,
|
|||
|
||||
if (!recovery) {
|
||||
/* passphrase: convert to UTF-16 first, then sha256(sha256(pw)) */
|
||||
r = passphrase_to_utf16(cd, CONST_CAST(char*)password, passwordLen, &utf16Password);
|
||||
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, utf16Password, passwordLen * 2);
|
||||
crypt_hash_write(hd, (char*)utf16Password, passwordLen * 2);
|
||||
r = crypt_hash_final(hd, kdf.initial_sha256, len);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
@ -1258,7 +1247,7 @@ static int _activate(struct crypt_device *cd,
|
|||
uint64_t next_start = 0;
|
||||
uint64_t next_end = 0;
|
||||
uint64_t last_segment = 0;
|
||||
uint32_t dmt_flags;
|
||||
uint32_t dmt_flags = 0;
|
||||
|
||||
r = _activate_check(cd, params);
|
||||
if (r)
|
||||
|
@ -1269,6 +1258,11 @@ static int _activate(struct crypt_device *cd,
|
|||
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;
|
||||
|
@ -1399,6 +1393,14 @@ static int _activate(struct crypt_device *cd,
|
|||
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);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* BITLK (BitLocker-compatible) header definition
|
||||
*
|
||||
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2019-2021 Milan Broz
|
||||
* Copyright (C) 2019-2021 Vojtech Trefny
|
||||
* 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
|
||||
|
@ -99,6 +99,7 @@ struct bitlk_fvek {
|
|||
|
||||
struct bitlk_metadata {
|
||||
uint16_t sector_size;
|
||||
uint64_t volume_size;
|
||||
bool togo;
|
||||
bool state;
|
||||
BITLKEncryptionType type;
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* cryptsetup plain device helper functions
|
||||
*
|
||||
* Copyright (C) 2004 Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -9,6 +9,8 @@ libcrypto_backend_la_SOURCES = \
|
|||
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
|
||||
|
|
|
@ -279,7 +279,6 @@ static void *fill_segment_thr(void *thread_data)
|
|||
{
|
||||
argon2_thread_data *my_data = thread_data;
|
||||
fill_segment(my_data->instance_ptr, my_data->pos);
|
||||
argon2_thread_exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,12 +46,4 @@ int argon2_thread_join(argon2_thread_handle_t handle) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void argon2_thread_exit(void) {
|
||||
#if defined(_WIN32)
|
||||
_endthreadex(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ARGON2_NO_THREADS */
|
||||
|
|
|
@ -58,10 +58,5 @@ int argon2_thread_create(argon2_thread_handle_t *handle,
|
|||
*/
|
||||
int argon2_thread_join(argon2_thread_handle_t handle);
|
||||
|
||||
/* Terminate the current thread. Must be run inside a thread created by
|
||||
* argon2_thread_create.
|
||||
*/
|
||||
void argon2_thread_exit(void);
|
||||
|
||||
#endif /* ARGON2_NO_THREADS */
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Argon2 PBKDF2 library wrapper
|
||||
*
|
||||
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2016-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Cipher performance check
|
||||
*
|
||||
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2018-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Linux kernel cipher generic utilities
|
||||
*
|
||||
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2018-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -97,12 +97,71 @@ static const uint32_t crc32_tab[] = {
|
|||
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.
|
||||
*/
|
||||
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
|
||||
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;
|
||||
|
@ -112,3 +171,13 @@ uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -21,10 +21,17 @@
|
|||
#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;
|
||||
|
@ -34,7 +41,8 @@ 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_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);
|
||||
|
@ -82,6 +90,15 @@ int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
|||
|
||||
/* 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);
|
||||
|
@ -135,4 +152,10 @@ static inline void crypt_backend_memzero(void *s, size_t n)
|
|||
#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 */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -58,4 +58,18 @@ int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_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 */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Linux kernel userspace API crypto backend implementation (skcipher)
|
||||
*
|
||||
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* GCRYPT crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -22,7 +22,6 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <gcrypt.h>
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
|
@ -550,3 +549,25 @@ out:
|
|||
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 */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Linux kernel userspace API crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -416,3 +416,13 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_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;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Nettle crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
#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
|
||||
|
@ -446,3 +447,14 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_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;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* NSS crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -395,3 +395,13 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_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;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* OPENSSL crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -30,6 +30,8 @@
|
|||
|
||||
#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>
|
||||
|
@ -230,7 +232,11 @@ void crypt_backend_destroy(void)
|
|||
|
||||
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)
|
||||
|
@ -573,6 +579,10 @@ static int openssl_pbkdf2(const char *password, size_t password_length,
|
|||
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
|
||||
|
@ -789,9 +799,6 @@ int crypt_bitlk_decrypt_key(const void *key, size_t key_length __attribute__((un
|
|||
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL) != 1)
|
||||
goto out;
|
||||
|
||||
//EVP_CIPHER_CTX_key_length(ctx)
|
||||
//EVP_CIPHER_CTX_iv_length(ctx)
|
||||
|
||||
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)
|
||||
|
@ -809,3 +816,34 @@ out:
|
|||
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 */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Generic wrapper for storage encryption modes and Initial Vectors
|
||||
* (reimplementation of some functions from Linux dm-crypt kernel)
|
||||
*
|
||||
* Copyright (C) 2014-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -151,7 +151,8 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
|
|||
|
||||
static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
|
||||
{
|
||||
uint64_t val;
|
||||
uint64_t val, *u64_iv;
|
||||
uint32_t *u32_iv;
|
||||
|
||||
switch (ctx->type) {
|
||||
case IV_NONE:
|
||||
|
@ -161,19 +162,24 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
|
|||
break;
|
||||
case IV_PLAIN:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
|
||||
u32_iv = (void *)ctx->iv;
|
||||
*u32_iv = cpu_to_le32(sector & 0xffffffff);
|
||||
break;
|
||||
case IV_PLAIN64:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
|
||||
u64_iv = (void *)ctx->iv;
|
||||
*u64_iv = cpu_to_le64(sector);
|
||||
break;
|
||||
case IV_PLAIN64BE:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(sector);
|
||||
/* 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);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
|
||||
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;
|
||||
|
@ -184,7 +190,8 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
|
|||
break;
|
||||
case IV_EBOIV:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
|
||||
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;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* Copyright (C) 2004 Free Software Foundation
|
||||
*
|
||||
* cryptsetup related changes
|
||||
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PBKDF performance check
|
||||
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Integrity volume handling
|
||||
*
|
||||
* Copyright (C) 2016-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -27,6 +27,17 @@
|
|||
#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)
|
||||
|
@ -38,11 +49,13 @@ static int INTEGRITY_read_superblock(struct crypt_device *cd,
|
|||
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)) ||
|
||||
sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
|
||||
log_std(cd, "No integrity superblock detected on %s.\n",
|
||||
device_path(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);
|
||||
|
@ -63,7 +76,7 @@ int INTEGRITY_read_sb(struct crypt_device *cd,
|
|||
struct superblock sb;
|
||||
int r;
|
||||
|
||||
r = INTEGRITY_read_superblock(cd, crypt_metadata_device(cd), 0, &sb);
|
||||
r = INTEGRITY_read_superblock(cd, INTEGRITY_metadata_device(cd), 0, &sb);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -120,7 +133,7 @@ int INTEGRITY_data_sectors(struct crypt_device *cd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int INTEGRITY_key_size(struct crypt_device *cd __attribute__((unused)), const char *integrity)
|
||||
int INTEGRITY_key_size(const char *integrity)
|
||||
{
|
||||
if (!integrity)
|
||||
return 0;
|
||||
|
@ -154,6 +167,9 @@ int INTEGRITY_hash_tag_size(const char *integrity)
|
|||
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);
|
||||
|
@ -163,8 +179,7 @@ int INTEGRITY_hash_tag_size(const char *integrity)
|
|||
return r < 0 ? 0 : r;
|
||||
}
|
||||
|
||||
int INTEGRITY_tag_size(struct crypt_device *cd __attribute__((unused)),
|
||||
const char *integrity,
|
||||
int INTEGRITY_tag_size(const char *integrity,
|
||||
const char *cipher,
|
||||
const char *cipher_mode)
|
||||
{
|
||||
|
@ -228,13 +243,13 @@ int INTEGRITY_create_dmd_device(struct crypt_device *cd,
|
|||
if (sb_flags & SB_FLAG_RECALCULATING)
|
||||
dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
|
||||
|
||||
r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
|
||||
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,
|
||||
crypt_metadata_device(cd), crypt_data_device(cd),
|
||||
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);
|
||||
|
@ -256,18 +271,8 @@ int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
|
|||
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 = device_block_adjust(cd, tgt->data_device, DEV_EXCL,
|
||||
tgt->u.integrity.offset, NULL, &dmd->flags);
|
||||
if (r)
|
||||
return r;
|
||||
r = create_or_reload_device(cd, name, type, dmd);
|
||||
|
||||
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);
|
||||
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;
|
||||
|
@ -299,14 +304,33 @@ int INTEGRITY_activate(struct crypt_device *cd,
|
|||
struct volume_key *journal_mac_key,
|
||||
uint32_t flags, uint32_t sb_flags)
|
||||
{
|
||||
struct crypt_dm_active_device dmd = {};
|
||||
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
|
||||
journal_mac_key, &dmd, flags, sb_flags);
|
||||
struct crypt_dm_active_device dmdq = {}, dmd = {};
|
||||
int r;
|
||||
|
||||
if (r < 0)
|
||||
return 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_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags);
|
||||
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;
|
||||
}
|
||||
|
@ -338,7 +362,7 @@ int INTEGRITY_format(struct crypt_device *cd,
|
|||
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, crypt_metadata_device(cd),
|
||||
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);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Integrity header definition
|
||||
*
|
||||
* Copyright (C) 2016-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -66,9 +66,8 @@ int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offs
|
|||
int INTEGRITY_data_sectors(struct crypt_device *cd,
|
||||
struct device *device, uint64_t offset,
|
||||
uint64_t *data_sectors);
|
||||
int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity);
|
||||
int INTEGRITY_tag_size(struct crypt_device *cd,
|
||||
const char *integrity,
|
||||
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);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Copyright (C) 2004 Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -31,6 +31,7 @@
|
|||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nls.h"
|
||||
#include "bitops.h"
|
||||
|
@ -38,7 +39,6 @@
|
|||
#include "utils_crypt.h"
|
||||
#include "utils_loop.h"
|
||||
#include "utils_dm.h"
|
||||
#include "utils_fips.h"
|
||||
#include "utils_keyring.h"
|
||||
#include "utils_io.h"
|
||||
#include "crypto_backend/crypto_backend.h"
|
||||
|
@ -178,8 +178,7 @@ int init_crypto(struct crypt_device *ctx);
|
|||
|
||||
int crypt_get_debug_level(void);
|
||||
|
||||
int crypt_memlock_inc(struct crypt_device *ctx);
|
||||
int crypt_memlock_dec(struct crypt_device *ctx);
|
||||
void crypt_process_priority(struct crypt_device *cd, int *priority, bool raise);
|
||||
|
||||
int crypt_metadata_locking_enabled(void);
|
||||
|
||||
|
|
|
@ -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>";
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Copyright (C) 2004 Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -46,6 +46,7 @@ extern "C" {
|
|||
*/
|
||||
|
||||
struct crypt_device; /* crypt device handle */
|
||||
struct crypt_keyslot_context;
|
||||
|
||||
/**
|
||||
* Initialize crypt device handle and check if the provided device exists.
|
||||
|
@ -271,9 +272,9 @@ struct crypt_pbkdf_type {
|
|||
};
|
||||
|
||||
/** Iteration time set by crypt_set_iteration_time(), for compatibility only. */
|
||||
#define CRYPT_PBKDF_ITER_TIME_SET (1 << 0)
|
||||
#define CRYPT_PBKDF_ITER_TIME_SET (UINT32_C(1) << 0)
|
||||
/** Never run benchmarks, use pre-set value or defaults. */
|
||||
#define CRYPT_PBKDF_NO_BENCHMARK (1 << 1)
|
||||
#define CRYPT_PBKDF_NO_BENCHMARK (UINT32_C(1) << 1)
|
||||
|
||||
/** PBKDF2 according to RFC2898, LUKS1 legacy */
|
||||
#define CRYPT_KDF_PBKDF2 "pbkdf2"
|
||||
|
@ -344,6 +345,7 @@ void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_m
|
|||
|
||||
/**
|
||||
* 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
|
||||
|
@ -353,7 +355,7 @@ void crypt_set_iteration_time(struct crypt_device *cd, uint64_t iteration_time_m
|
|||
* @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);
|
||||
int crypt_memory_lock(struct crypt_device *cd, int lock) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* Set global lock protection for on-disk metadata (file-based locking).
|
||||
|
@ -427,6 +429,8 @@ int crypt_get_metadata_size(struct crypt_device *cd,
|
|||
#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
|
||||
|
@ -513,13 +517,13 @@ struct crypt_params_verity {
|
|||
};
|
||||
|
||||
/** No on-disk header (only hashes) */
|
||||
#define CRYPT_VERITY_NO_HEADER (1 << 0)
|
||||
#define CRYPT_VERITY_NO_HEADER (UINT32_C(1) << 0)
|
||||
/** Verity hash in userspace before activation */
|
||||
#define CRYPT_VERITY_CHECK_HASH (1 << 1)
|
||||
#define CRYPT_VERITY_CHECK_HASH (UINT32_C(1) << 1)
|
||||
/** Create hash - format hash device */
|
||||
#define CRYPT_VERITY_CREATE_HASH (1 << 2)
|
||||
#define CRYPT_VERITY_CREATE_HASH (UINT32_C(1) << 2)
|
||||
/** Root hash signature required for activation */
|
||||
#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (1 << 3)
|
||||
#define CRYPT_VERITY_ROOT_HASH_SIGNATURE (UINT32_C(1) << 3)
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -542,18 +546,18 @@ struct crypt_params_tcrypt {
|
|||
};
|
||||
|
||||
/** Include legacy modes when scanning for header */
|
||||
#define CRYPT_TCRYPT_LEGACY_MODES (1 << 0)
|
||||
#define CRYPT_TCRYPT_LEGACY_MODES (UINT32_C(1) << 0)
|
||||
/** Try to load hidden header (describing hidden device) */
|
||||
#define CRYPT_TCRYPT_HIDDEN_HEADER (1 << 1)
|
||||
#define CRYPT_TCRYPT_HIDDEN_HEADER (UINT32_C(1) << 1)
|
||||
/** Try to load backup header */
|
||||
#define CRYPT_TCRYPT_BACKUP_HEADER (1 << 2)
|
||||
#define CRYPT_TCRYPT_BACKUP_HEADER (UINT32_C(1) << 2)
|
||||
/** Device contains encrypted system (with boot loader) */
|
||||
#define CRYPT_TCRYPT_SYSTEM_HEADER (1 << 3)
|
||||
#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 (1 << 4)
|
||||
#define CRYPT_TCRYPT_VERA_MODES (UINT32_C(1) << 4)
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -662,11 +666,11 @@ void crypt_set_compatibility(struct crypt_device *cd, uint32_t 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 (1 << 0)
|
||||
#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 (1 << 1)
|
||||
#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 (1 << 2)
|
||||
#define CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC (UINT32_C(1) << 2)
|
||||
|
||||
/**
|
||||
* Convert to new type for already existing device.
|
||||
|
@ -718,6 +722,24 @@ 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
|
||||
|
@ -749,7 +771,8 @@ int crypt_volume_key_keyring(struct crypt_device *cd, int enable);
|
|||
* @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 in current version load works only for LUKS and VERITY device type.
|
||||
* @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,
|
||||
|
@ -881,6 +904,43 @@ 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);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -1005,13 +1065,13 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
|
|||
size_t passphrase_size);
|
||||
|
||||
/** create keyslot with volume key not associated with current dm-crypt segment */
|
||||
#define CRYPT_VOLUME_KEY_NO_SEGMENT (1 << 0)
|
||||
#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 (1 << 1)
|
||||
#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 (1 << 2)
|
||||
#define CRYPT_VOLUME_KEY_DIGEST_REUSE (UINT32_C(1) << 2)
|
||||
|
||||
/**
|
||||
* Add key slot using provided key.
|
||||
|
@ -1050,6 +1110,187 @@ int crypt_keyslot_add_by_key(struct crypt_device *cd,
|
|||
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.
|
||||
*
|
||||
|
@ -1073,59 +1314,61 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
|
|||
*/
|
||||
|
||||
/** device is read only */
|
||||
#define CRYPT_ACTIVATE_READONLY (1 << 0)
|
||||
#define CRYPT_ACTIVATE_READONLY (UINT32_C(1) << 0)
|
||||
/** only reported for device without uuid */
|
||||
#define CRYPT_ACTIVATE_NO_UUID (1 << 1)
|
||||
#define CRYPT_ACTIVATE_NO_UUID (UINT32_C(1) << 1)
|
||||
/** activate even if cannot grant exclusive access (DANGEROUS) */
|
||||
#define CRYPT_ACTIVATE_SHARED (1 << 2)
|
||||
#define CRYPT_ACTIVATE_SHARED (UINT32_C(1) << 2)
|
||||
/** enable discards aka TRIM */
|
||||
#define CRYPT_ACTIVATE_ALLOW_DISCARDS (1 << 3)
|
||||
#define CRYPT_ACTIVATE_ALLOW_DISCARDS (UINT32_C(1) << 3)
|
||||
/** skip global udev rules in activation ("private device"), input only */
|
||||
#define CRYPT_ACTIVATE_PRIVATE (1 << 4)
|
||||
#define CRYPT_ACTIVATE_PRIVATE (UINT32_C(1) << 4)
|
||||
/** corruption detected (verity), output only */
|
||||
#define CRYPT_ACTIVATE_CORRUPTED (1 << 5)
|
||||
#define CRYPT_ACTIVATE_CORRUPTED (UINT32_C(1) << 5)
|
||||
/** use same_cpu_crypt option for dm-crypt */
|
||||
#define CRYPT_ACTIVATE_SAME_CPU_CRYPT (1 << 6)
|
||||
#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 (1 << 7)
|
||||
#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 (1 << 8)
|
||||
#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 (1 << 9)
|
||||
#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 (1 << 10)
|
||||
#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 (1 << 11)
|
||||
#define CRYPT_ACTIVATE_KEYRING_KEY (UINT32_C(1) << 11)
|
||||
/** dm-integrity: direct writes, do not use journal */
|
||||
#define CRYPT_ACTIVATE_NO_JOURNAL (1 << 12)
|
||||
#define CRYPT_ACTIVATE_NO_JOURNAL (UINT32_C(1) << 12)
|
||||
/** dm-integrity: recovery mode - no journal, no integrity checks */
|
||||
#define CRYPT_ACTIVATE_RECOVERY (1 << 13)
|
||||
#define CRYPT_ACTIVATE_RECOVERY (UINT32_C(1) << 13)
|
||||
/** ignore persistently stored flags */
|
||||
#define CRYPT_ACTIVATE_IGNORE_PERSISTENT (1 << 14)
|
||||
#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 (1 << 15)
|
||||
#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 (1 << 16)
|
||||
#define CRYPT_ACTIVATE_ALLOW_UNBOUND_KEY (UINT32_C(1) << 16)
|
||||
/** dm-integrity: activate automatic recalculation */
|
||||
#define CRYPT_ACTIVATE_RECALCULATE (1 << 17)
|
||||
#define CRYPT_ACTIVATE_RECALCULATE (UINT32_C(1) << 17)
|
||||
/** reactivate existing and update flags, input only */
|
||||
#define CRYPT_ACTIVATE_REFRESH (1 << 18)
|
||||
#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 (1 << 19)
|
||||
#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 (1 << 20)
|
||||
#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 (1 << 21)
|
||||
#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 (1 << 22)
|
||||
#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 (1 << 23)
|
||||
#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 (1 << 24)
|
||||
#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 (1 << 25)
|
||||
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (UINT32_C(1) << 25)
|
||||
/** dm-integrity: reset automatic recalculation */
|
||||
#define CRYPT_ACTIVATE_RECALCULATE_RESET (1 << 26)
|
||||
#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
|
||||
|
@ -1174,11 +1417,11 @@ uint64_t crypt_get_active_integrity_failures(struct crypt_device *cd,
|
|||
* LUKS2 header requirements
|
||||
*/
|
||||
/** Unfinished offline reencryption */
|
||||
#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (1 << 0)
|
||||
#define CRYPT_REQUIREMENT_OFFLINE_REENCRYPT (UINT32_C(1) << 0)
|
||||
/** Online reencryption in-progress */
|
||||
#define CRYPT_REQUIREMENT_ONLINE_REENCRYPT (1 << 1)
|
||||
#define CRYPT_REQUIREMENT_ONLINE_REENCRYPT (UINT32_C(1) << 1)
|
||||
/** unknown requirement in header (output only) */
|
||||
#define CRYPT_REQUIREMENT_UNKNOWN (1 << 31)
|
||||
#define CRYPT_REQUIREMENT_UNKNOWN (UINT32_C(1) << 31)
|
||||
|
||||
/**
|
||||
* Persistent flags type
|
||||
|
@ -1308,8 +1551,8 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
|
|||
* @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 and because master
|
||||
* key from decrypted header is used instead.
|
||||
* @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,
|
||||
|
@ -1365,11 +1608,11 @@ int crypt_activate_by_keyring(struct crypt_device *cd,
|
|||
uint32_t flags);
|
||||
|
||||
/** lazy deactivation - remove once last user releases it */
|
||||
#define CRYPT_DEACTIVATE_DEFERRED (1 << 0)
|
||||
#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 (1 << 1)
|
||||
#define CRYPT_DEACTIVATE_FORCE (UINT32_C(1) << 1)
|
||||
/** if set, remove lazy deactivation */
|
||||
#define CRYPT_DEACTIVATE_DEFERRED_CANCEL (1 << 2)
|
||||
#define CRYPT_DEACTIVATE_DEFERRED_CANCEL (UINT32_C(1) << 2)
|
||||
|
||||
/**
|
||||
* Deactivate crypt device. This function tries to remove active device-mapper
|
||||
|
@ -1415,6 +1658,9 @@ int crypt_deactivate(struct crypt_device *cd, const char *name);
|
|||
* @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,
|
||||
|
@ -1423,6 +1669,41 @@ int crypt_volume_key_get(struct crypt_device *cd,
|
|||
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.
|
||||
*
|
||||
|
@ -1431,6 +1712,10 @@ int crypt_volume_key_get(struct crypt_device *cd,
|
|||
* @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,
|
||||
|
@ -1923,7 +2208,7 @@ int crypt_keyfile_read(struct crypt_device *cd,
|
|||
uint32_t flags);
|
||||
|
||||
/** Read key only to the first end of line (\\n). */
|
||||
#define CRYPT_KEYFILE_STOP_EOL (1 << 0)
|
||||
#define CRYPT_KEYFILE_STOP_EOL (UINT32_C(1) << 0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -1937,7 +2222,7 @@ int crypt_keyfile_read(struct crypt_device *cd,
|
|||
typedef enum {
|
||||
CRYPT_WIPE_ZERO, /**< Fill with zeroes */
|
||||
CRYPT_WIPE_RANDOM, /**< Use RNG to fill data */
|
||||
CRYPT_WIPE_ENCRYPTED_ZERO, /**< Add encryption and fill with zeroes as plaintext */
|
||||
CRYPT_WIPE_ENCRYPTED_ZERO, /**< Obsolete, same as CRYPT_WIPE_RANDOM */
|
||||
CRYPT_WIPE_SPECIAL, /**< Compatibility only, do not use (Gutmann method) */
|
||||
} crypt_wipe_pattern;
|
||||
|
||||
|
@ -1973,7 +2258,7 @@ int crypt_wipe(struct crypt_device *cd,
|
|||
);
|
||||
|
||||
/** Use direct-io */
|
||||
#define CRYPT_WIPE_NO_DIRECT_IO (1 << 0)
|
||||
#define CRYPT_WIPE_NO_DIRECT_IO (UINT32_C(1) << 0)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -2390,15 +2675,16 @@ int crypt_activate_by_token_pin(struct crypt_device *cd,
|
|||
*/
|
||||
|
||||
/** Initialize reencryption metadata but do not run reencryption yet. (in) */
|
||||
#define CRYPT_REENCRYPT_INITIALIZE_ONLY (1 << 0)
|
||||
/** Move the first segment, used only with data shift. (in/out) */
|
||||
#define CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT (1 << 1)
|
||||
#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 (1 << 2)
|
||||
#define CRYPT_REENCRYPT_RESUME_ONLY (UINT32_C(1) << 2)
|
||||
/** Run reencryption recovery only. (in) */
|
||||
#define CRYPT_REENCRYPT_RECOVERY (1 << 3)
|
||||
#define CRYPT_REENCRYPT_RECOVERY (UINT32_C(1) << 3)
|
||||
/** Reencryption requires metadata protection. (in/out) */
|
||||
#define CRYPT_REENCRYPT_REPAIR_NEEDED (1 << 4)
|
||||
#define CRYPT_REENCRYPT_REPAIR_NEEDED (UINT32_C(1) << 4)
|
||||
|
||||
/**
|
||||
* Reencryption direction
|
||||
|
@ -2423,10 +2709,15 @@ typedef enum {
|
|||
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" or "shift" (only "shift" is immutable after 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 "shift" mode, must be non-zero, immutable after first init. */
|
||||
uint64_t max_hotzone_size; /**< Exact hotzone size for "none" mode. Maximum hotzone size for "checksum" and "journal" modes. */
|
||||
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. */
|
||||
|
|
|
@ -8,3 +8,4 @@ Description: cryptsetup library
|
|||
Version: @LIBCRYPTSETUP_VERSION@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lcryptsetup
|
||||
Requires.private: @PKGMODULES@
|
||||
|
|
|
@ -144,3 +144,24 @@ CRYPTSETUP_2.4 {
|
|||
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;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Definitions of common constant and generic macros fo libcryptsetup
|
||||
* Definitions of common constant and generic macros of libcryptsetup
|
||||
*
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -25,6 +25,9 @@
|
|||
/* 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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Helpers for defining versioned symbols
|
||||
*
|
||||
* Copyright (C) 2021 Red Hat, Inc. All rights reserved.
|
||||
* 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
|
||||
|
@ -31,7 +31,7 @@
|
|||
* 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 oll other compatible
|
||||
* - the latest version is marked with _NEW variant and all other compatible
|
||||
* symbols should be marked with _OLD variant
|
||||
*
|
||||
* Examples:
|
||||
|
@ -67,16 +67,14 @@
|
|||
* under CRYPT_SYMBOL_EXPORT_OLD(int, crypt_func_X, ...) macro
|
||||
*/
|
||||
|
||||
#ifdef __has_attribute
|
||||
# if __has_attribute(symver)
|
||||
# define _CRYPT_SYMVER(_local_sym, _public_sym, _ver_str, _maj, _min) \
|
||||
__attribute__((__symver__(#_public_sym _ver_str #_maj "." #_min)))
|
||||
# endif
|
||||
#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__)
|
||||
#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);
|
||||
__asm__(".symver " #_local_sym "," #_public_sym _ver_str #_maj "." #_min);
|
||||
#endif
|
||||
|
||||
#define _CRYPT_FUNC(_public_sym, _prefix_str, _maj, _min, _ret, ...) \
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* Copyright (C) 2004 Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -31,7 +31,6 @@
|
|||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
# include <sys/sysmacros.h> /* for major, minor */
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include "internal.h"
|
||||
|
||||
#define DM_CRYPT_TARGET "crypt"
|
||||
|
@ -47,6 +46,7 @@ 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;
|
||||
|
@ -204,6 +204,9 @@ static void _dm_set_verity_compat(struct crypt_device *cd,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -241,6 +244,20 @@ static void _dm_set_integrity_compat(struct crypt_device *cd,
|
|||
_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)
|
||||
{
|
||||
|
@ -278,11 +295,12 @@ static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_typ
|
|||
unsigned dm_maj, dm_min, dm_patch;
|
||||
int r = 0;
|
||||
|
||||
if ((target_type == DM_CRYPT && _dm_crypt_checked) ||
|
||||
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_LINEAR) || (target_type == DM_ZERO) ||
|
||||
(_dm_crypt_checked && _dm_verity_checked && _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 */
|
||||
|
@ -331,8 +349,12 @@ static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_typ
|
|||
_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 = (struct dm_versions *)((char *) target + target->next);
|
||||
target = VOIDP_CAST(struct dm_versions *)((char *) target + target->next);
|
||||
} while (last_target != target);
|
||||
|
||||
r = 1;
|
||||
|
@ -355,13 +377,14 @@ int dm_flags(struct crypt_device *cd, dm_target_type target, uint32_t *flags)
|
|||
*flags = _dm_flags;
|
||||
|
||||
if (target == DM_UNKNOWN &&
|
||||
_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked)
|
||||
_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked)
|
||||
return 0;
|
||||
|
||||
if ((target == DM_CRYPT && _dm_crypt_checked) ||
|
||||
if ((target == DM_CRYPT && _dm_crypt_checked) ||
|
||||
(target == DM_VERITY && _dm_verity_checked) ||
|
||||
(target == DM_INTEGRITY && _dm_integrity_checked) ||
|
||||
(target == DM_LINEAR) || (target == DM_ZERO)) /* nothing to check */
|
||||
(target == DM_ZERO && _dm_zero_checked) ||
|
||||
(target == DM_LINEAR)) /* nothing to check */
|
||||
return 0;
|
||||
|
||||
return -ENODEV;
|
||||
|
@ -444,14 +467,6 @@ char *dm_device_name(const char *path)
|
|||
return dm_device_path(NULL, major(st.st_rdev), minor(st.st_rdev));
|
||||
}
|
||||
|
||||
static void hex_key(char *hexkey, size_t key_size, const char *key)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < key_size; i++)
|
||||
sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
|
||||
}
|
||||
|
||||
static size_t int_log10(uint64_t x)
|
||||
{
|
||||
uint64_t r = 0;
|
||||
|
@ -460,27 +475,22 @@ static size_t int_log10(uint64_t x)
|
|||
return r;
|
||||
}
|
||||
|
||||
#define CLEN 64 /* 2*MAX_CIPHER_LEN */
|
||||
#define CLENS "63" /* for sscanf length + '\0' */
|
||||
#define CAPIL 144 /* should be enough to fit whole capi string */
|
||||
#define CAPIS "143" /* for sscanf of crypto API string + 16 + \0 */
|
||||
|
||||
static int cipher_c2dm(const char *org_c, const char *org_i, unsigned tag_size,
|
||||
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[CLEN], mode[CLEN], iv[CLEN+1], tmp[CLEN];
|
||||
char capi[CAPIL];
|
||||
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, "%" CLENS "[^-]-%" CLENS "s", cipher, tmp);
|
||||
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, "%" CLENS "[^-]-%" CLENS "s", mode, iv);
|
||||
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);
|
||||
|
@ -527,75 +537,6 @@ static int cipher_c2dm(const char *org_c, const char *org_i, unsigned tag_size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cipher_dm2c(char **org_c, char **org_i, const char *c_dm, const char *i_dm)
|
||||
{
|
||||
char cipher[CLEN], mode[CLEN], iv[CLEN], auth[CLEN];
|
||||
char tmp[CAPIL], dmcrypt_tmp[CAPIL*2], capi[CAPIL+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;
|
||||
*org_i = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* modes with capi: prefix */
|
||||
i = sscanf(c_dm, "capi:%" CAPIS "[^-]-%" CLENS "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(%" CAPIS "s", capi) == 1) {
|
||||
if (!(*org_i = strdup("aead")))
|
||||
return -ENOMEM;
|
||||
} else if (sscanf(tmp, "rfc7539(%" CAPIS "[^,],%" CLENS "s", capi, auth) == 2) {
|
||||
if (!(*org_i = strdup(auth)))
|
||||
return -ENOMEM;
|
||||
} else if (sscanf(tmp, "authenc(%" CLENS "[^,],%" CAPIS "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, "%" CLENS "[^(](%" CLENS "[^)])", 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -613,7 +554,7 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
|
|||
if (!tgt)
|
||||
return NULL;
|
||||
|
||||
r = cipher_c2dm(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size,
|
||||
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;
|
||||
|
@ -655,24 +596,20 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
|
|||
null_cipher = 1;
|
||||
|
||||
if (null_cipher)
|
||||
hexkey = crypt_safe_alloc(2);
|
||||
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);
|
||||
} else
|
||||
hexkey = crypt_safe_alloc(tgt->u.crypt.vk->keylength * 2 + 1);
|
||||
|
||||
if (!hexkey)
|
||||
goto out;
|
||||
|
||||
if (null_cipher)
|
||||
strncpy(hexkey, "-", 2);
|
||||
else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
|
||||
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
|
||||
hex_key(hexkey, tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key);
|
||||
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)) +
|
||||
|
@ -725,6 +662,8 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
|
|||
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);
|
||||
|
@ -755,30 +694,26 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
|
|||
} else
|
||||
*verity_verify_args = '\0';
|
||||
|
||||
if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 */
|
||||
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s", num_options,
|
||||
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_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_safe_alloc(tgt->u.verity.root_hash_size * 2 + 1);
|
||||
hexroot = crypt_bytes_to_hex(tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
|
||||
if (!hexroot)
|
||||
goto out;
|
||||
hex_key(hexroot, tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
|
||||
|
||||
hexsalt = crypt_safe_alloc(vp->salt_size ? vp->salt_size * 2 + 1 : 2);
|
||||
hexsalt = crypt_bytes_to_hex(vp->salt_size, vp->salt);
|
||||
if (!hexsalt)
|
||||
goto out;
|
||||
if (vp->salt_size)
|
||||
hex_key(hexsalt, vp->salt_size, vp->salt);
|
||||
else
|
||||
strncpy(hexsalt, "-", 2);
|
||||
|
||||
max_size = strlen(hexroot) + strlen(hexsalt) +
|
||||
strlen(device_block_path(tgt->data_device)) +
|
||||
|
@ -843,10 +778,9 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
|
|||
num_options++;
|
||||
|
||||
if (tgt->u.integrity.vk) {
|
||||
hexkey = crypt_safe_alloc(tgt->u.integrity.vk->keylength * 2 + 1);
|
||||
hexkey = crypt_bytes_to_hex(tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
|
||||
if (!hexkey)
|
||||
goto out;
|
||||
hex_key(hexkey, tgt->u.integrity.vk->keylength, tgt->u.integrity.vk->key);
|
||||
} else
|
||||
hexkey = NULL;
|
||||
|
||||
|
@ -861,11 +795,10 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
|
|||
num_options++;
|
||||
|
||||
if (tgt->u.integrity.journal_integrity_key) {
|
||||
hexkey = crypt_safe_alloc(tgt->u.integrity.journal_integrity_key->keylength * 2 + 1);
|
||||
hexkey = crypt_bytes_to_hex( tgt->u.integrity.journal_integrity_key->keylength,
|
||||
tgt->u.integrity.journal_integrity_key->key);
|
||||
if (!hexkey)
|
||||
goto out;
|
||||
hex_key(hexkey, tgt->u.integrity.journal_integrity_key->keylength,
|
||||
tgt->u.integrity.journal_integrity_key->key);
|
||||
} else
|
||||
hexkey = NULL;
|
||||
|
||||
|
@ -880,11 +813,10 @@ static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags
|
|||
num_options++;
|
||||
|
||||
if (tgt->u.integrity.journal_crypt_key) {
|
||||
hexkey = crypt_safe_alloc(tgt->u.integrity.journal_crypt_key->keylength * 2 + 1);
|
||||
hexkey = crypt_bytes_to_hex(tgt->u.integrity.journal_crypt_key->keylength,
|
||||
tgt->u.integrity.journal_crypt_key->key);
|
||||
if (!hexkey)
|
||||
goto out;
|
||||
hex_key(hexkey, tgt->u.integrity.journal_crypt_key->keylength,
|
||||
tgt->u.integrity.journal_crypt_key->key);
|
||||
} else
|
||||
hexkey = NULL;
|
||||
|
||||
|
@ -980,7 +912,7 @@ out:
|
|||
return params_out;
|
||||
}
|
||||
|
||||
static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags __attribute__((unused)))
|
||||
static char *get_dm_linear_params(const struct dm_target *tgt)
|
||||
{
|
||||
char *params;
|
||||
int r;
|
||||
|
@ -1001,7 +933,7 @@ static char *get_dm_linear_params(const struct dm_target *tgt, uint32_t flags __
|
|||
return params;
|
||||
}
|
||||
|
||||
static char *get_dm_zero_params(const struct dm_target *tgt __attribute__((unused)), uint32_t flags __attribute__((unused)))
|
||||
static char *get_dm_zero_params(void)
|
||||
{
|
||||
char *params = crypt_safe_alloc(1);
|
||||
if (!params)
|
||||
|
@ -1263,8 +1195,7 @@ int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char
|
|||
return r;
|
||||
|
||||
r_udev = r;
|
||||
if (r_udev <= 0)
|
||||
r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
|
||||
r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
|
||||
|
||||
return r == -ENOENT ? r_udev : r;
|
||||
}
|
||||
|
@ -1328,9 +1259,9 @@ static int _create_dm_targets_params(struct crypt_dm_active_device *dmd)
|
|||
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, dmd->flags);
|
||||
tgt->params = get_dm_linear_params(tgt);
|
||||
else if (tgt->type == DM_ZERO)
|
||||
tgt->params = get_dm_zero_params(tgt, dmd->flags);
|
||||
tgt->params = get_dm_zero_params();
|
||||
else {
|
||||
r = -ENOTSUP;
|
||||
goto err;
|
||||
|
@ -1576,6 +1507,9 @@ static void _dm_target_free_query_path(struct crypt_device *cd, struct dm_target
|
|||
|
||||
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);
|
||||
|
||||
|
@ -1667,16 +1601,94 @@ int dm_create_device(struct crypt_device *cd, const char *name,
|
|||
return -ENOTSUP;
|
||||
|
||||
r = _dm_create_device(cd, name, type, dmd);
|
||||
|
||||
if (r < 0 && dm_flags(cd, dmd->segment.type, &dmt_flags))
|
||||
if (!r || r == -EEXIST)
|
||||
goto out;
|
||||
|
||||
if (r && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
|
||||
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).
|
||||
|
@ -1685,54 +1697,6 @@ int dm_create_device(struct crypt_device *cd, const char *name,
|
|||
crypt_is_cipher_null(dmd->segment.u.crypt.cipher))
|
||||
log_dbg(cd, "Activated dm-crypt device with cipher_null. Device is not encrypted.");
|
||||
|
||||
if (r == -EINVAL &&
|
||||
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."));
|
||||
|
||||
if (r == -EINVAL &&
|
||||
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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
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."));
|
||||
}
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
|
||||
if (r == -EINVAL && 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."));
|
||||
out:
|
||||
dm_exit_context();
|
||||
return r;
|
||||
}
|
||||
|
@ -2027,9 +1991,7 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags,
|
|||
|
||||
/* cipher */
|
||||
if (get_flags & DM_ACTIVE_CRYPT_CIPHER) {
|
||||
r = cipher_dm2c(CONST_CAST(char**)&cipher,
|
||||
CONST_CAST(char**)&integrity,
|
||||
rcipher, rintegrity);
|
||||
r = crypt_capi_to_cipher(&cipher, &integrity, rcipher, rintegrity);
|
||||
if (r < 0)
|
||||
goto err;
|
||||
}
|
||||
|
@ -2262,6 +2224,8 @@ static int _dm_target_query_verity(struct crypt_device *cd,
|
|||
*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(¶ms, " ");
|
||||
str2 = crypt_lookup_dev(str);
|
||||
|
@ -2370,6 +2334,8 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
|
|||
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;
|
||||
|
@ -2499,6 +2465,28 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
|
|||
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, ":");
|
||||
|
@ -2509,6 +2497,28 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
|
|||
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")) {
|
||||
|
@ -2544,6 +2554,10 @@ static int _dm_target_query_integrity(struct crypt_device *cd,
|
|||
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);
|
||||
|
@ -2552,6 +2566,8 @@ err:
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -2595,7 +2611,7 @@ err:
|
|||
return r;
|
||||
}
|
||||
|
||||
static int _dm_target_query_error(struct crypt_device *cd __attribute__((unused)), struct dm_target *tgt)
|
||||
static int _dm_target_query_error(struct dm_target *tgt)
|
||||
{
|
||||
tgt->type = DM_ERROR;
|
||||
tgt->direction = TARGET_QUERY;
|
||||
|
@ -2603,7 +2619,7 @@ static int _dm_target_query_error(struct crypt_device *cd __attribute__((unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _dm_target_query_zero(struct crypt_device *cd __attribute__((unused)), struct dm_target *tgt)
|
||||
static int _dm_target_query_zero(struct dm_target *tgt)
|
||||
{
|
||||
tgt->type = DM_ZERO;
|
||||
tgt->direction = TARGET_QUERY;
|
||||
|
@ -2631,9 +2647,9 @@ static int dm_target_query(struct crypt_device *cd, struct dm_target *tgt, const
|
|||
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(cd, tgt);
|
||||
r = _dm_target_query_error(tgt);
|
||||
else if (!strcmp(target_type, DM_ZERO_TARGET))
|
||||
r = _dm_target_query_zero(cd, tgt);
|
||||
r = _dm_target_query_zero(tgt);
|
||||
|
||||
if (!r) {
|
||||
tgt->offset = *start;
|
||||
|
@ -2681,7 +2697,7 @@ static int _dm_query_device(struct crypt_device *cd, const char *name,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Never allow to return empty key */
|
||||
/* 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;
|
||||
|
@ -2763,7 +2779,8 @@ int dm_query_device(struct crypt_device *cd, const char *name,
|
|||
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)
|
||||
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;
|
||||
|
@ -2809,7 +2826,8 @@ static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_
|
|||
#endif
|
||||
}
|
||||
|
||||
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix, char **names, size_t names_length)
|
||||
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;
|
||||
|
@ -2948,7 +2966,7 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
|
|||
{
|
||||
uint32_t dmt_flags;
|
||||
int msg_size;
|
||||
char *msg = NULL;
|
||||
char *msg = NULL, *key = NULL;
|
||||
int r = -ENOTSUP;
|
||||
|
||||
if (dm_init_context(cd, DM_CRYPT) || dm_flags(cd, DM_CRYPT, &dmt_flags))
|
||||
|
@ -2970,14 +2988,21 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
|
|||
goto out;
|
||||
}
|
||||
|
||||
strcpy(msg, "key set ");
|
||||
if (!vk->keylength)
|
||||
snprintf(msg + 8, msg_size - 8, "-");
|
||||
else if (vk->key_description)
|
||||
snprintf(msg + 8, msg_size - 8, ":%zu:logon:%s", vk->keylength, vk->key_description);
|
||||
else
|
||||
hex_key(&msg[8], vk->keylength, vk->key);
|
||||
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;
|
||||
|
@ -2986,6 +3011,7 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
|
|||
r = 0;
|
||||
out:
|
||||
crypt_safe_free(msg);
|
||||
crypt_safe_free(key);
|
||||
dm_exit_context();
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* loop-AES compatible volume handling
|
||||
*
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* loop-AES compatible volume handling
|
||||
*
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* AFsplitter - Anti forensic information splitter
|
||||
*
|
||||
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* AFsplitter diffuses information over a large stripe of data,
|
||||
* therefore supporting secure data destruction.
|
||||
|
@ -131,7 +131,7 @@ out:
|
|||
return r;
|
||||
}
|
||||
|
||||
int AF_merge(struct crypt_device *ctx __attribute__((unused)), const char *src, char *dst,
|
||||
int AF_merge(const char *src, char *dst,
|
||||
size_t blocksize, unsigned int blocknumbers, const char *hash)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -142,7 +142,7 @@ int AF_merge(struct crypt_device *ctx __attribute__((unused)), const char *src,
|
|||
if (!bufblock)
|
||||
return -ENOMEM;
|
||||
|
||||
for(i = 0; i < blocknumbers - 1; i++) {
|
||||
for (i = 0; i < blocknumbers - 1; i++) {
|
||||
XORblock(src + blocksize * i, bufblock, bufblock, blocksize);
|
||||
r = diffuse(bufblock, bufblock, blocksize, hash);
|
||||
if (r < 0)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* AFsplitter - Anti forensic information splitter
|
||||
*
|
||||
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* AFsplitter diffuses information over a large stripe of data,
|
||||
* therefore supporting secure data destruction.
|
||||
|
@ -44,7 +44,7 @@ struct volume_key;
|
|||
|
||||
int AF_split(struct crypt_device *ctx, const char *src, char *dst,
|
||||
size_t blocksize, unsigned int blocknumbers, const char *hash);
|
||||
int AF_merge(struct crypt_device *ctx, const char *src, char *dst, size_t blocksize,
|
||||
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);
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* LUKS - Linux Unified Key Setup
|
||||
*
|
||||
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
* 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
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* LUKS - Linux Unified Key Setup
|
||||
*
|
||||
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2013-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -28,8 +28,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "luks.h"
|
||||
#include "af.h"
|
||||
|
@ -232,11 +232,12 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
|
|||
hdr_size = LUKS_device_sectors(&hdr) << SECTOR_SHIFT;
|
||||
buffer_size = size_round_up(hdr_size, crypt_getpagesize());
|
||||
|
||||
buffer = crypt_safe_alloc(buffer_size);
|
||||
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);
|
||||
|
@ -280,7 +281,8 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
|
|||
r = 0;
|
||||
out:
|
||||
crypt_safe_memzero(&hdr, sizeof(hdr));
|
||||
crypt_safe_free(buffer);
|
||||
crypt_safe_memzero(buffer, buffer_size);
|
||||
free(buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -308,7 +310,7 @@ int LUKS_hdr_restore(
|
|||
goto out;
|
||||
}
|
||||
|
||||
buffer = crypt_safe_alloc(buffer_size);
|
||||
buffer = malloc(buffer_size);
|
||||
if (!buffer) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -379,7 +381,8 @@ int LUKS_hdr_restore(
|
|||
r = LUKS_read_phdr(hdr, 1, 0, ctx);
|
||||
out:
|
||||
device_sync(ctx, device);
|
||||
crypt_safe_free(buffer);
|
||||
crypt_safe_memzero(buffer, buffer_size);
|
||||
free(buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -399,7 +402,7 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
|
|||
/*
|
||||
* 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 neccessary.
|
||||
* 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."));
|
||||
|
@ -817,7 +820,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
|
|||
return r;
|
||||
}
|
||||
|
||||
/* Compute master key digest */
|
||||
/* Compute volume key digest */
|
||||
pbkdf = crypt_get_pbkdf(ctx);
|
||||
r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength);
|
||||
if (r < 0)
|
||||
|
@ -922,11 +925,15 @@ int LUKS_set_key(unsigned int keyIndex,
|
|||
hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
|
||||
derived_key->key, hdr->keyBytes,
|
||||
hdr->keyblock[keyIndex].passwordIterations, 0, 0);
|
||||
if (r < 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 masterkey stored in vk->key is split to AfKey
|
||||
* 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;
|
||||
|
@ -982,7 +989,7 @@ int LUKS_verify_volume_key(const struct luks_phdr *hdr,
|
|||
hdr->mkDigestIterations, 0, 0) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (memcmp(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE))
|
||||
if (crypt_backend_memeq(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE))
|
||||
return -EPERM;
|
||||
|
||||
return 0;
|
||||
|
@ -1044,7 +1051,7 @@ static int LUKS_open_key(unsigned int keyIndex,
|
|||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = AF_merge(ctx, AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
|
||||
r = AF_merge(AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -1227,6 +1234,10 @@ int LUKS_wipe_header_areas(struct luks_phdr *hdr,
|
|||
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;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* LUKS - Linux Unified Key Setup
|
||||
*
|
||||
* Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
* Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
|
||||
* 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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* LUKS - Linux Unified Key Setup v2
|
||||
*
|
||||
* Copyright (C) 2015-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2015-2021 Milan Broz
|
||||
* 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
|
||||
|
@ -62,8 +62,16 @@
|
|||
/* 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 */
|
||||
|
@ -113,6 +121,7 @@ struct luks2_hdr {
|
|||
uint8_t salt2[LUKS2_SALT_L];
|
||||
char uuid[LUKS2_UUID_L];
|
||||
void *jobj;
|
||||
void *jobj_rollback;
|
||||
};
|
||||
|
||||
struct luks2_keyslot_params {
|
||||
|
@ -159,6 +168,7 @@ int LUKS2_hdr_version_unlocked(struct crypt_device *cd,
|
|||
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);
|
||||
|
||||
|
@ -217,9 +227,7 @@ int LUKS2_keyslot_wipe(struct crypt_device *cd,
|
|||
int keyslot,
|
||||
int wipe_area_only);
|
||||
|
||||
crypt_keyslot_priority LUKS2_keyslot_priority_get(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
int keyslot);
|
||||
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,
|
||||
|
@ -235,8 +243,7 @@ int LUKS2_keyslot_swap(struct crypt_device *cd,
|
|||
/*
|
||||
* Generic LUKS2 token
|
||||
*/
|
||||
int LUKS2_token_json_get(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
int LUKS2_token_json_get(struct luks2_hdr *hdr,
|
||||
int token,
|
||||
const char **json);
|
||||
|
||||
|
@ -247,8 +254,7 @@ int LUKS2_token_assign(struct crypt_device *cd,
|
|||
int assign,
|
||||
int commit);
|
||||
|
||||
int LUKS2_token_is_assigned(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
int LUKS2_token_is_assigned(struct luks2_hdr *hdr,
|
||||
int keyslot,
|
||||
int token);
|
||||
|
||||
|
@ -279,14 +285,33 @@ int LUKS2_token_open_and_activate(struct crypt_device *cd,
|
|||
uint32_t flags,
|
||||
void *usrptr);
|
||||
|
||||
int LUKS2_token_keyring_get(struct crypt_device *cd,
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -372,7 +397,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
|
|||
|
||||
uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr);
|
||||
int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic);
|
||||
int LUKS2_get_sector_size(struct luks2_hdr *hdr);
|
||||
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,
|
||||
|
@ -400,8 +425,11 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
|
|||
*/
|
||||
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, uint32_t *version);
|
||||
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);
|
||||
|
||||
|
@ -410,7 +438,7 @@ int LUKS2_key_description_by_segment(struct crypt_device *cd,
|
|||
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 luks2_hdr *hdr, struct volume_key *vk, int digest);
|
||||
struct volume_key *vk, int digest);
|
||||
|
||||
int LUKS2_luks1_to_luks2(struct crypt_device *cd,
|
||||
struct luks_phdr *hdr1,
|
||||
|
@ -427,7 +455,6 @@ int LUKS2_reencrypt_locked_recovery_by_passphrase(struct crypt_device *cd,
|
|||
int keyslot_new,
|
||||
const char *passphrase,
|
||||
size_t passphrase_size,
|
||||
uint32_t flags,
|
||||
struct volume_key **vks);
|
||||
|
||||
void LUKS2_reencrypt_free(struct crypt_device *cd,
|
||||
|
@ -459,4 +486,12 @@ 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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue