mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 00:10:04 +01:00
Compare commits
35 Commits
v2.8.1
...
tcrypt-arg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b3eb37046 | ||
|
|
e9bd43a8fa | ||
|
|
8311a8a903 | ||
|
|
8da66c3066 | ||
|
|
11a4fc6790 | ||
|
|
e4c498d15b | ||
|
|
e609c47916 | ||
|
|
ccc0c69cd7 | ||
|
|
7fba92260a | ||
|
|
76ea8f13cf | ||
|
|
bbc053682a | ||
|
|
c9fd8b5ed4 | ||
|
|
fbd295259c | ||
|
|
5490d28aa4 | ||
|
|
296eb39c60 | ||
|
|
917b6836a9 | ||
|
|
b36d4be8fa | ||
|
|
0a8e7da7ae | ||
|
|
83a7310ca2 | ||
|
|
441802773f | ||
|
|
cc66b1fa52 | ||
|
|
a0d5d2bf5e | ||
|
|
61dbb69319 | ||
|
|
32b33541a8 | ||
|
|
346db2e42a | ||
|
|
0d07e80077 | ||
|
|
dc2251b88d | ||
|
|
a8e8e39007 | ||
|
|
bcef385346 | ||
|
|
9810c6fb2f | ||
|
|
4d98add260 | ||
|
|
0eaaa4553e | ||
|
|
3a8feb8be7 | ||
|
|
2b9523a1ef | ||
|
|
68d4749d8a |
@@ -10,7 +10,6 @@ include:
|
||||
- local: .gitlab/ci/debian.yml
|
||||
- local: .gitlab/ci/fedora.yml
|
||||
- local: .gitlab/ci/fedora-opal.yml
|
||||
- local: .gitlab/ci/rhel.yml
|
||||
- local: .gitlab/ci/centos.yml
|
||||
# - local: .gitlab/ci/annocheck.yml
|
||||
- local: .gitlab/ci/csmock.yml
|
||||
@@ -22,4 +21,3 @@ include:
|
||||
- local: .gitlab/ci/alpinelinux.yml
|
||||
- local: .gitlab/ci/debian-i686.yml
|
||||
- local: .gitlab/ci/cifuzz.yml
|
||||
- local: .gitlab/ci/ubuntu.yml
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
- >
|
||||
sudo apk add
|
||||
lvm2-dev openssl-dev popt-dev util-linux-dev json-c-dev
|
||||
argon2-dev device-mapper which sharutils gettext gettext-dev automake
|
||||
argon2-dev device-mapper which sharutils gettext-dev argp-standalone automake
|
||||
autoconf libtool build-base keyutils tar jq expect git asciidoctor
|
||||
# Be sure we have updated basic tools and system
|
||||
- sudo apk upgrade gcc binutils build-base musl
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
.centos-openssl-backend:
|
||||
variables:
|
||||
DISTRO: cryptsetup-centos-stream-9
|
||||
extends:
|
||||
- .fail_if_coredump_generated
|
||||
before_script:
|
||||
@@ -29,6 +27,7 @@ test-main-commit-centos-stream9:
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-centos-stream-9
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_TEST: "1"
|
||||
rules:
|
||||
@@ -51,6 +50,53 @@ test-mergerq-centos-stream9:
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-centos-stream-9
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_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-centos-stream10:
|
||||
extends:
|
||||
- .centos-openssl-backend
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-centos-stream-10
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-centos-stream-10
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_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-stream10:
|
||||
extends:
|
||||
- .centos-openssl-backend
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-centos-stream-10
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-centos-stream-10
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_TEST: "1"
|
||||
rules:
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
.rhel-openssl-backend:
|
||||
extends:
|
||||
- .fail_if_coredump_generated
|
||||
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
|
||||
- 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
|
||||
- cryptsetup-rhel-8
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-rhel-8
|
||||
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
|
||||
- cryptsetup-rhel-9
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-rhel-9
|
||||
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-rhel10:
|
||||
extends:
|
||||
- .rhel-openssl-backend
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-rhel-10
|
||||
stage: test
|
||||
interruptible: true
|
||||
allow_failure: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-rhel-10
|
||||
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
|
||||
- cryptsetup-rhel-8-fips
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-rhel-8-fips
|
||||
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:
|
||||
- grep -q fips=1 /proc/cmdline || 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
|
||||
- cryptsetup-rhel-9-fips
|
||||
stage: test
|
||||
interruptible: true
|
||||
allow_failure: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-rhel-9-fips
|
||||
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:
|
||||
- grep -q fips=1 /proc/cmdline || exit 1
|
||||
- make -j
|
||||
- make -j -C tests check-programs
|
||||
- sudo -E make check
|
||||
|
||||
test-main-commit-rhel10-fips:
|
||||
extends:
|
||||
- .rhel-openssl-backend
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-rhel-10-fips
|
||||
stage: test
|
||||
interruptible: true
|
||||
allow_failure: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-rhel-10-fips
|
||||
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:
|
||||
- grep -q fips=1 /proc/cmdline || exit 1
|
||||
- make -j
|
||||
- make -j -C tests check-programs
|
||||
- sudo -E make check
|
||||
@@ -1,106 +0,0 @@
|
||||
.ubuntu-prep:
|
||||
extends:
|
||||
- .fail_if_coredump_generated
|
||||
before_script:
|
||||
- sudo apt-get -y update
|
||||
- >
|
||||
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-dev libpwquality-dev sharutils dmsetup jq xxd expect
|
||||
keyutils netcat-openbsd passwd openssh-client sshpass asciidoctor
|
||||
swtpm meson ninja-build python3-jinja2 gperf libcap-dev libtss2-dev
|
||||
libmount-dev swtpm-tools tpm2-tools
|
||||
# scsi_debug, gost crypto
|
||||
- sudo apt-get -y install dkms linux-headers-$(uname -r) linux-modules-extra-$(uname -r) gost-crypto-dkms
|
||||
- sudo apt-get -y build-dep cryptsetup
|
||||
- sudo -E git clean -xdf
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-libargon2 --enable-asciidoc
|
||||
|
||||
test-mergerq-job-ubuntu:
|
||||
extends:
|
||||
- .ubuntu-prep
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-ubuntu-2404
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-ubuntu-2404
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_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-ubuntu:
|
||||
extends:
|
||||
- .ubuntu-prep
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-ubuntu-2404
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-ubuntu-2404
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_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
|
||||
|
||||
# meson tests
|
||||
test-mergerq-job-ubuntu-meson:
|
||||
extends:
|
||||
- .ubuntu-prep
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-ubuntu-2404
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-ubuntu-2404
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_TEST: "1"
|
||||
rules:
|
||||
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
script:
|
||||
- sudo apt-get -y install -y -qq meson ninja-build
|
||||
- meson setup build
|
||||
- ninja -C build
|
||||
- cd build && sudo -E meson test --verbose --print-errorlogs
|
||||
|
||||
test-main-commit-job-ubuntu-meson:
|
||||
extends:
|
||||
- .ubuntu-prep
|
||||
tags:
|
||||
- libvirt
|
||||
- cryptsetup-ubuntu-2404
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
DISTRO: cryptsetup-ubuntu-2404
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
RUN_KEYRING_TRUSTED_TEST: "1"
|
||||
rules:
|
||||
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH =~ /v2\..\.x$/
|
||||
script:
|
||||
- sudo apt-get -y install -y -qq meson ninja-build
|
||||
- meson setup build
|
||||
- ninja -C build
|
||||
- cd build && sudo -E meson test --verbose --print-errorlogs
|
||||
23
configure.ac
23
configure.ac
@@ -1,5 +1,5 @@
|
||||
AC_PREREQ([2.67])
|
||||
AC_INIT([cryptsetup],[2.8.1])
|
||||
AC_INIT([cryptsetup],[2.9.0-git])
|
||||
|
||||
dnl library version from <major>.<minor>.<release>[-<suffix>]
|
||||
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
|
||||
@@ -680,6 +680,27 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
])
|
||||
CFLAGS=$saved_CFLAGS
|
||||
|
||||
dnl Force compiler to use zero_call_used_regs("used") to check for the function attribute support.
|
||||
dnl Otherwise the compiler may falsely advertise it with __has_attribute operator, even though
|
||||
dnl it does not implement it on some archs.
|
||||
AC_MSG_CHECKING([for zero_call_used_regs(user)])
|
||||
saved_CFLAGS=$CFLAGS
|
||||
CFLAGS="-O0 -Werror"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
void _test_function(void);
|
||||
__attribute__((zero_call_used_regs("used"))) void _test_function(void) {
|
||||
volatile int *i; volatile int j = 0; if (j) *i = 0;
|
||||
}
|
||||
]],
|
||||
[[ _test_function() ]]
|
||||
)],[
|
||||
AC_DEFINE([HAVE_ATTRIBUTE_ZEROCALLUSEDREGS], 1, [Define to 1 to use __attribute__((zero_call_used_regs("used")))])
|
||||
AC_MSG_RESULT([yes])
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
CFLAGS=$saved_CFLAGS
|
||||
|
||||
AC_MSG_CHECKING([for systemd tmpfiles config directory])
|
||||
if test "x$prefix" != "xNONE"; then
|
||||
saved_PKG_CONFIG=$PKG_CONFIG
|
||||
|
||||
@@ -111,6 +111,7 @@ struct bitlk_superblock {
|
||||
struct bitlk_fve_metadata {
|
||||
/* FVE metadata block header */
|
||||
uint8_t signature[8];
|
||||
/* size of this block (in 16-byte units) */
|
||||
uint16_t fve_size;
|
||||
uint16_t fve_version;
|
||||
uint16_t curr_state;
|
||||
@@ -132,6 +133,32 @@ struct bitlk_fve_metadata {
|
||||
uint64_t creation_time;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct bitlk_validation_hash {
|
||||
uint16_t size;
|
||||
uint16_t role;
|
||||
uint16_t type;
|
||||
uint16_t flags;
|
||||
/* likely a hash type code, anything other than 0x2005 isn't supported */
|
||||
uint16_t hash_type;
|
||||
uint16_t unknown1;
|
||||
/* SHA-256 */
|
||||
uint8_t hash[32];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct bitlk_fve_metadata_validation {
|
||||
/* FVE metadata validation block header */
|
||||
uint16_t validation_size;
|
||||
uint16_t validation_version;
|
||||
uint32_t fve_crc32;
|
||||
/* this is a single nested structure's header defined here for simplicity */
|
||||
uint16_t nested_struct_size;
|
||||
uint16_t nested_struct_role;
|
||||
uint16_t nested_struct_type;
|
||||
uint16_t nested_struct_flags;
|
||||
/* datum containing a similar nested structure (encrypted using VMK) with hash (SHA256) */
|
||||
uint8_t nested_struct_data[BITLK_VALIDATION_VMK_DATA_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct bitlk_entry_header_block {
|
||||
uint64_t offset;
|
||||
uint64_t size;
|
||||
@@ -361,6 +388,54 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool check_fve_metadata(struct bitlk_fve_metadata *fve)
|
||||
{
|
||||
if (memcmp(fve->signature, BITLK_SIGNATURE, sizeof(fve->signature)) || le16_to_cpu(fve->fve_version) != 2 ||
|
||||
(fve->fve_size << 4) > BITLK_FVE_METADATA_SIZE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool check_fve_metadata_validation(struct bitlk_fve_metadata_validation *validation)
|
||||
{
|
||||
/* only check if there is room for CRC-32, the actual size must be larger */
|
||||
if (le16_to_cpu(validation->validation_size) < 8 || le16_to_cpu(validation->validation_version > 2))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_fve_metadata_validation(struct bitlk_metadata *params, struct bitlk_fve_metadata_validation *validation)
|
||||
{
|
||||
/* extra checks for a nested structure (MAC) and BITLK FVE metadata */
|
||||
|
||||
if (le16_to_cpu(validation->validation_size) < sizeof(struct bitlk_fve_metadata_validation))
|
||||
return false;
|
||||
|
||||
if (le16_to_cpu(validation->nested_struct_size != BITLK_VALIDATION_VMK_HEADER_SIZE + BITLK_VALIDATION_VMK_DATA_SIZE) ||
|
||||
le16_to_cpu(validation->nested_struct_role) != 0 ||
|
||||
le16_to_cpu(validation->nested_struct_type) != 5)
|
||||
return false;
|
||||
|
||||
/* nonce */
|
||||
memcpy(params->validation->nonce,
|
||||
validation->nested_struct_data,
|
||||
BITLK_NONCE_SIZE);
|
||||
|
||||
/* MAC tag */
|
||||
memcpy(params->validation->mac_tag,
|
||||
validation->nested_struct_data + BITLK_NONCE_SIZE,
|
||||
BITLK_VMK_MAC_TAG_SIZE);
|
||||
|
||||
/* AES-CCM encrypted datum with SHA256 hash */
|
||||
memcpy(params->validation->enc_datum,
|
||||
validation->nested_struct_data + BITLK_NONCE_SIZE + BITLK_VMK_MAC_TAG_SIZE,
|
||||
BITLK_VALIDATION_VMK_DATA_SIZE - BITLK_NONCE_SIZE - BITLK_VMK_MAC_TAG_SIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek)
|
||||
{
|
||||
if (!fvek)
|
||||
@@ -391,6 +466,7 @@ void BITLK_bitlk_metadata_free(struct bitlk_metadata *metadata)
|
||||
|
||||
free(metadata->guid);
|
||||
free(metadata->description);
|
||||
free(metadata->validation);
|
||||
BITLK_bitlk_vmk_free(metadata->vmks);
|
||||
BITLK_bitlk_fvek_free(metadata->fvek);
|
||||
}
|
||||
@@ -402,20 +478,25 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
||||
struct bitlk_signature sig = {};
|
||||
struct bitlk_superblock sb = {};
|
||||
struct bitlk_fve_metadata fve = {};
|
||||
struct bitlk_fve_metadata_validation validation = {};
|
||||
struct bitlk_entry_vmk entry_vmk = {};
|
||||
uint8_t *fve_entries = NULL;
|
||||
uint8_t *fve_validated_block = NULL;
|
||||
size_t fve_entries_size = 0;
|
||||
uint32_t fve_metadata_size = 0;
|
||||
uint32_t fve_size_real = 0;
|
||||
int fve_offset = 0;
|
||||
char guid_buf[UUID_STR_LEN] = {0};
|
||||
uint16_t entry_size = 0;
|
||||
uint16_t entry_type = 0;
|
||||
int i = 0;
|
||||
int r = 0;
|
||||
int valid_fve_metadata_idx = -1;
|
||||
int start = 0;
|
||||
size_t key_size = 0;
|
||||
const char *key = NULL;
|
||||
char *description = NULL;
|
||||
struct crypt_hash *hash;
|
||||
|
||||
struct bitlk_vmk *vmk = NULL;
|
||||
struct bitlk_vmk *vmk_p = params->vmks;
|
||||
@@ -490,15 +571,80 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
||||
for (i = 0; i < 3; i++)
|
||||
params->metadata_offset[i] = le64_to_cpu(sb.fve_offset[i]);
|
||||
|
||||
log_dbg(cd, "Reading BITLK FVE metadata of size %zu on device %s, offset %" PRIu64 ".",
|
||||
sizeof(fve), device_path(device), params->metadata_offset[0]);
|
||||
fve_validated_block = malloc(BITLK_FVE_METADATA_SIZE);
|
||||
if (fve_validated_block == NULL) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* read FVE metadata from the first metadata area */
|
||||
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||
device_alignment(device), &fve, sizeof(fve), params->metadata_offset[0]) != sizeof(fve) ||
|
||||
memcmp(fve.signature, BITLK_SIGNATURE, sizeof(fve.signature)) ||
|
||||
le16_to_cpu(fve.fve_version) != 2) {
|
||||
log_err(cd, _("Failed to read BITLK FVE metadata from %s."), device_path(device));
|
||||
for (i = 0; i < 3; i++) {
|
||||
/* iterate over FVE metadata copies and pick the valid one */
|
||||
log_dbg(cd, "Reading BITLK FVE metadata copy #%d of size %zu on device %s, offset %" PRIu64 ".",
|
||||
i, sizeof(fve), device_path(device), params->metadata_offset[i]);
|
||||
|
||||
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||
device_alignment(device), &fve, sizeof(fve), params->metadata_offset[i]) != sizeof(fve) ||
|
||||
!check_fve_metadata(&fve) ||
|
||||
(fve_size_real = le16_to_cpu(fve.fve_size) << 4, read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||
device_alignment(device), &validation, sizeof(validation), params->metadata_offset[i] + fve_size_real) != sizeof(validation)) ||
|
||||
!check_fve_metadata_validation(&validation) ||
|
||||
/* double-fetch is here, but we aren't validating MAC */
|
||||
read_lseek_blockwise(devfd, device_block_size(cd, device), device_alignment(device), fve_validated_block, fve_size_real,
|
||||
params->metadata_offset[i]) != fve_size_real ||
|
||||
(crypt_crc32(~0, fve_validated_block, fve_size_real) ^ ~0) != le32_to_cpu(validation.fve_crc32)) {
|
||||
/* found an invalid FVE metadata copy, log and skip */
|
||||
log_dbg(cd, _("Failed to read or validate BITLK FVE metadata copy #%d from %s."), i, device_path(device));
|
||||
} else {
|
||||
/* found a valid FVE metadata copy, use it */
|
||||
valid_fve_metadata_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_fve_metadata_idx < 0) {
|
||||
/* all FVE metadata copies are invalid, fail */
|
||||
log_err(cd, _("Failed to read and validate BITLK FVE metadata from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* check that a valid FVE metadata block is in its expected location */
|
||||
if (params->metadata_offset[valid_fve_metadata_idx] != le64_to_cpu(fve.fve_offset[valid_fve_metadata_idx])) {
|
||||
log_err(cd, _("Failed to validate the location of BITLK FVE metadata from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* update offsets from a valid FVE metadata copy */
|
||||
for (i = 0; i < 3; i++)
|
||||
params->metadata_offset[i] = le64_to_cpu(fve.fve_offset[i]);
|
||||
|
||||
/* check that the FVE metadata hasn't changed between reads, because we are preparing for the MAC check */
|
||||
if (memcmp(&fve, fve_validated_block, sizeof(fve)) != 0) {
|
||||
log_err(cd, _("BITLK FVE metadata changed between reads from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
crypt_backend_memzero(¶ms->sha256_fve, 32);
|
||||
if (crypt_hash_init(&hash, "sha256")) {
|
||||
log_err(cd, _("Failed to hash BITLK FVE metadata read from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
crypt_hash_write(hash, (const char *)fve_validated_block, fve_size_real);
|
||||
crypt_hash_final(hash, (char *)¶ms->sha256_fve, 32);
|
||||
crypt_hash_destroy(hash);
|
||||
|
||||
/* do some extended checks against FVE metadata, but not including MAC verification */
|
||||
params->validation = malloc(sizeof(struct bitlk_validation));
|
||||
if (!params->validation) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!parse_fve_metadata_validation(params, &validation)) {
|
||||
log_err(cd, _("Failed to parse BITLK FVE validation metadata from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@@ -583,17 +729,18 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
||||
}
|
||||
memset(fve_entries, 0, fve_entries_size);
|
||||
|
||||
log_dbg(cd, "Reading BITLK FVE metadata entries of size %zu on device %s, offset %" PRIu64 ".",
|
||||
fve_entries_size, device_path(device), params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN);
|
||||
log_dbg(cd, "Getting BITLK FVE metadata entries of size %zu on device %s, offset %" PRIu64 ".",
|
||||
fve_entries_size, device_path(device), params->metadata_offset[valid_fve_metadata_idx] + BITLK_FVE_METADATA_HEADERS_LEN);
|
||||
|
||||
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||
device_alignment(device), fve_entries, fve_entries_size,
|
||||
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADERS_LEN) != (ssize_t)fve_entries_size) {
|
||||
log_err(cd, _("Failed to read BITLK metadata entries from %s."), device_path(device));
|
||||
if (BITLK_FVE_METADATA_HEADERS_LEN + fve_entries_size > fve_size_real) {
|
||||
log_err(cd, _("Failed to check BITLK metadata entries previously read from %s."), device_path(device));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* fetch these entries from validated buffer to avoid double-fetch */
|
||||
memcpy(fve_entries, fve_validated_block + BITLK_FVE_METADATA_HEADERS_LEN, fve_entries_size);
|
||||
|
||||
while ((fve_entries_size - start) >= (sizeof(entry_size) + sizeof(entry_type))) {
|
||||
|
||||
/* size of this entry */
|
||||
@@ -716,6 +863,8 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
||||
}
|
||||
out:
|
||||
free(fve_entries);
|
||||
free(fve_validated_block);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1110,6 +1259,7 @@ int BITLK_get_volume_key(struct crypt_device *cd,
|
||||
struct volume_key *open_vmk_key = NULL;
|
||||
struct volume_key *vmk_dec_key = NULL;
|
||||
struct volume_key *recovery_key = NULL;
|
||||
struct bitlk_validation_hash dec_hash = {};
|
||||
const struct bitlk_vmk *next_vmk = NULL;
|
||||
|
||||
next_vmk = params->vmks;
|
||||
@@ -1172,6 +1322,36 @@ int BITLK_get_volume_key(struct crypt_device *cd,
|
||||
}
|
||||
crypt_free_volume_key(vmk_dec_key);
|
||||
|
||||
log_dbg(cd, "Trying to decrypt validation metadata using VMK.");
|
||||
r = crypt_bitlk_decrypt_key(crypt_volume_key_get_key(open_vmk_key),
|
||||
crypt_volume_key_length(open_vmk_key),
|
||||
(const char*)params->validation->enc_datum,
|
||||
(char *)&dec_hash,
|
||||
BITLK_VALIDATION_VMK_DATA_SIZE - BITLK_NONCE_SIZE - BITLK_VMK_MAC_TAG_SIZE,
|
||||
(const char*)params->validation->nonce, BITLK_NONCE_SIZE,
|
||||
(const char*)params->validation->mac_tag, BITLK_VMK_MAC_TAG_SIZE);
|
||||
if (r < 0) {
|
||||
log_dbg(cd, "Failed to decrypt validation metadata using VMK.");
|
||||
crypt_free_volume_key(open_vmk_key);
|
||||
if (r == -ENOTSUP)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
/* now, do the MAC validation */
|
||||
if (le16_to_cpu(dec_hash.role) != 0 ||le16_to_cpu(dec_hash.type) != 1 ||
|
||||
(le16_to_cpu(dec_hash.hash_type) != 0x2005)) {
|
||||
log_dbg(cd, "Failed to parse decrypted validation metadata.");
|
||||
crypt_free_volume_key(open_vmk_key);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (memcmp(dec_hash.hash, params->sha256_fve, sizeof(dec_hash.hash)) != 0) {
|
||||
log_dbg(cd, "Failed MAC validation of BITLK FVE metadata.");
|
||||
crypt_free_volume_key(open_vmk_key);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = decrypt_key(cd, open_fvek_key, params->fvek->vk, open_vmk_key,
|
||||
params->fvek->mac_tag, BITLK_VMK_MAC_TAG_SIZE,
|
||||
params->fvek->nonce, BITLK_NONCE_SIZE, true);
|
||||
|
||||
@@ -21,6 +21,8 @@ struct volume_key;
|
||||
#define BITLK_NONCE_SIZE 12
|
||||
#define BITLK_SALT_SIZE 16
|
||||
#define BITLK_VMK_MAC_TAG_SIZE 16
|
||||
#define BITLK_VALIDATION_VMK_HEADER_SIZE 8
|
||||
#define BITLK_VALIDATION_VMK_DATA_SIZE 72
|
||||
|
||||
#define BITLK_STATE_NORMAL 0x0004
|
||||
|
||||
@@ -85,6 +87,13 @@ struct bitlk_fvek {
|
||||
struct volume_key *vk;
|
||||
};
|
||||
|
||||
struct bitlk_validation {
|
||||
uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
|
||||
uint8_t nonce[BITLK_NONCE_SIZE];
|
||||
/* technically, this is not "VMK", but some sources call it this way */
|
||||
uint8_t enc_datum[BITLK_VALIDATION_VMK_DATA_SIZE];
|
||||
};
|
||||
|
||||
struct bitlk_metadata {
|
||||
uint16_t sector_size;
|
||||
uint64_t volume_size;
|
||||
@@ -101,8 +110,10 @@ struct bitlk_metadata {
|
||||
uint32_t metadata_version;
|
||||
uint64_t volume_header_offset;
|
||||
uint64_t volume_header_size;
|
||||
const char *sha256_fve[32];
|
||||
struct bitlk_vmk *vmks;
|
||||
struct bitlk_fvek *fvek;
|
||||
struct bitlk_validation *validation;
|
||||
};
|
||||
|
||||
int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
struct cipher_alg {
|
||||
@@ -77,3 +79,21 @@ int crypt_cipher_wrapped_key(const char *name, const char *mode)
|
||||
|
||||
return ca ? (int)ca->wrapped_key : 0;
|
||||
}
|
||||
|
||||
bool crypt_fips_mode_kernel(void)
|
||||
{
|
||||
int fd;
|
||||
char buf = 0;
|
||||
|
||||
fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
if (read(fd, &buf, 1) != 1)
|
||||
buf = '0';
|
||||
|
||||
close(fd);
|
||||
|
||||
return (buf == '1');
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ struct crypt_hmac;
|
||||
struct crypt_cipher;
|
||||
struct crypt_storage;
|
||||
|
||||
int crypt_backend_init(bool fips);
|
||||
int crypt_backend_init(void);
|
||||
void crypt_backend_destroy(void);
|
||||
|
||||
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
|
||||
@@ -148,6 +148,9 @@ int crypt_backend_memeq(const void *m1, const void *m2, size_t n);
|
||||
/* crypto backend running in FIPS mode */
|
||||
bool crypt_fips_mode(void);
|
||||
|
||||
/* kernel running in FIPS mode */
|
||||
bool crypt_fips_mode_kernel(void);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -80,7 +80,7 @@ static void crypt_hash_test_whirlpool_bug(void)
|
||||
crypto_backend_whirlpool_bug = 1;
|
||||
}
|
||||
|
||||
int crypt_backend_init(bool fips __attribute__((unused)))
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -684,7 +684,7 @@ bool crypt_fips_mode(void)
|
||||
if (fips_checked)
|
||||
return fips_mode;
|
||||
|
||||
if (crypt_backend_init(false /* ignored */))
|
||||
if (crypt_backend_init())
|
||||
return false;
|
||||
|
||||
fips_mode = gcry_fips_mode_active();
|
||||
|
||||
@@ -103,7 +103,7 @@ static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *op
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_backend_init(bool fips __attribute__((unused)))
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
struct utsname uts;
|
||||
struct sockaddr_alg sa = {
|
||||
@@ -408,5 +408,5 @@ int crypt_backend_memeq(const void *m1, const void *m2, size_t n)
|
||||
|
||||
bool crypt_fips_mode(void)
|
||||
{
|
||||
return false;
|
||||
return crypt_fips_mode_kernel();
|
||||
}
|
||||
|
||||
@@ -69,16 +69,13 @@ static const mbedtls_md_info_t *crypt_get_hash(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_backend_init(bool fips)
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (g_initialized)
|
||||
return 0;
|
||||
|
||||
if (fips)
|
||||
return -ENOTSUP;
|
||||
|
||||
mbedtls_version_get_string_full(g_backend_version);
|
||||
|
||||
mbedtls_entropy_init(&g_entropy);
|
||||
|
||||
@@ -200,7 +200,7 @@ static struct hash_alg *_get_alg(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_backend_init(bool fips __attribute__((unused)))
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ static struct hash_alg *_get_alg(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_backend_init(bool fips __attribute__((unused)))
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
|
||||
@@ -205,12 +205,12 @@ static const char *openssl_backend_version(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
int crypt_backend_init(bool fips)
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
if (openssl_backend_init(fips))
|
||||
if (openssl_backend_init(crypt_fips_mode()))
|
||||
return -EINVAL;
|
||||
|
||||
crypto_backend_initialised = 1;
|
||||
|
||||
@@ -9,11 +9,9 @@
|
||||
|
||||
#define ATTR_NOINLINE __attribute__ ((noinline))
|
||||
#define ATTR_ZERO_REGS
|
||||
#if defined __has_attribute
|
||||
# if __has_attribute (zero_call_used_regs)
|
||||
#if HAVE_ATTRIBUTE_ZEROCALLUSEDREGS
|
||||
# undef ATTR_ZERO_REGS
|
||||
# define ATTR_ZERO_REGS __attribute__ ((zero_call_used_regs("used")))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Workaround for https://github.com/google/sanitizers/issues/1507 */
|
||||
|
||||
@@ -151,6 +151,12 @@ int INTEGRITY_key_size(const char *integrity, int required_key_size)
|
||||
ks = required_key_size ?: 32;
|
||||
else if (!strcmp(integrity, "hmac(sha512)"))
|
||||
ks = required_key_size ?: 64;
|
||||
else if (!strcmp(integrity, "phmac(sha1)"))
|
||||
ks = required_key_size ?: -EINVAL;
|
||||
else if (!strcmp(integrity, "phmac(sha256)"))
|
||||
ks = required_key_size ?: -EINVAL;
|
||||
else if (!strcmp(integrity, "phmac(sha512)"))
|
||||
ks = required_key_size ?: -EINVAL;
|
||||
else if (!strcmp(integrity, "poly1305"))
|
||||
ks = 0;
|
||||
else if (!strcmp(integrity, "none"))
|
||||
@@ -180,6 +186,8 @@ int INTEGRITY_hash_tag_size(const char *integrity)
|
||||
return 8;
|
||||
|
||||
r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
|
||||
if (r != 1)
|
||||
r = sscanf(integrity, "phmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
|
||||
if (r == 1)
|
||||
r = crypt_hash_size(hash);
|
||||
else
|
||||
@@ -222,6 +230,12 @@ int INTEGRITY_tag_size(const char *integrity,
|
||||
auth_tag_size = 32;
|
||||
else if (!strcmp(integrity, "hmac(sha512)"))
|
||||
auth_tag_size = 64;
|
||||
else if (!strcmp(integrity, "phmac(sha1)"))
|
||||
auth_tag_size = 20;
|
||||
else if (!strcmp(integrity, "phmac(sha256)"))
|
||||
auth_tag_size = 32;
|
||||
else if (!strcmp(integrity, "phmac(sha512)"))
|
||||
auth_tag_size = 64;
|
||||
else if (!strcmp(integrity, "poly1305")) {
|
||||
if (iv_tag_size)
|
||||
iv_tag_size = 12;
|
||||
|
||||
@@ -2117,6 +2117,18 @@ int crypt_header_is_detached(struct crypt_device *cd);
|
||||
int crypt_get_verity_info(struct crypt_device *cd,
|
||||
struct crypt_params_verity *vp);
|
||||
|
||||
/**
|
||||
* Get FEC repaired block count for VERITY device.
|
||||
*
|
||||
* @param cd crypt device handle
|
||||
* @param name verity device name
|
||||
* @param repaired FEC repaired blocks
|
||||
*
|
||||
* @return @e 0 on success or negative errno value otherwise.
|
||||
*/
|
||||
int crypt_get_verity_repaired(struct crypt_device *cd, const char *name,
|
||||
uint64_t *repaired);
|
||||
|
||||
/**
|
||||
* Get device parameters for INTEGRITY device.
|
||||
*
|
||||
|
||||
@@ -195,3 +195,8 @@ CRYPTSETUP_2.8 {
|
||||
crypt_get_old_volume_key_size;
|
||||
crypt_format_inline;
|
||||
} CRYPTSETUP_2.7;
|
||||
|
||||
CRYPTSETUP_2.9 {
|
||||
global:
|
||||
crypt_get_verity_repaired;
|
||||
} CRYPTSETUP_2.8;
|
||||
|
||||
@@ -1992,6 +1992,40 @@ int dm_status_verity_ok(struct crypt_device *cd, const char *name)
|
||||
return r;
|
||||
}
|
||||
|
||||
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired)
|
||||
{
|
||||
int r;
|
||||
struct dm_info dmi;
|
||||
char *status_line = NULL, *p;
|
||||
uint64_t val64;
|
||||
|
||||
if (dm_init_context(cd, DM_VERITY))
|
||||
return -ENOTSUP;
|
||||
|
||||
r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
|
||||
dm_exit_context();
|
||||
if (r < 0 || !status_line || !*status_line) {
|
||||
free(status_line);
|
||||
return r;
|
||||
}
|
||||
p = status_line + 1;
|
||||
while (*p == ' ')
|
||||
p++;
|
||||
|
||||
if (!*p || *p == '-' || sscanf(p, "%" PRIu64, &val64) != 1) {
|
||||
free(status_line);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
|
||||
|
||||
if (repaired)
|
||||
*repaired = val64;
|
||||
|
||||
free(status_line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count)
|
||||
{
|
||||
int r;
|
||||
|
||||
@@ -58,6 +58,12 @@ typedef enum OpalStatus {
|
||||
_OPAL_STATUS_MAX = 0x13,
|
||||
} OpalStatus;
|
||||
|
||||
/*
|
||||
* Also defined in TCG Core spec Section 5.1.5 but
|
||||
* do not inflate the opal_status_table below
|
||||
*/
|
||||
#define OPAL_STATUS_FAIL 0x3f
|
||||
|
||||
static const char* const opal_status_table[_OPAL_STATUS_MAX] = {
|
||||
[OPAL_STATUS_SUCCESS] = "success",
|
||||
[OPAL_STATUS_NOT_AUTHORIZED] = "not authorized",
|
||||
@@ -85,9 +91,9 @@ static const char *opal_status_to_string(int t)
|
||||
if (t < 0)
|
||||
return strerror(-t);
|
||||
|
||||
/* Fail, as defined by specification */
|
||||
if (t == 0x3f)
|
||||
return "unknown failure";
|
||||
/* This will be checked upon 'Reactivate' method */
|
||||
if (t == OPAL_STATUS_FAIL)
|
||||
return "FAIL status";
|
||||
|
||||
if (t >= _OPAL_STATUS_MAX)
|
||||
return "unknown error";
|
||||
@@ -236,6 +242,8 @@ static int opal_ioctl(struct crypt_device *cd, int fd, unsigned long rq, void *a
|
||||
|
||||
opal_ioctl_debug(cd, rq, args, false, 0);
|
||||
r = ioctl(fd, rq, args);
|
||||
if (r < 0)
|
||||
r = -errno;
|
||||
opal_ioctl_debug(cd, rq, args, true, r);
|
||||
|
||||
return r;
|
||||
@@ -396,6 +404,194 @@ static int opal_enabled(struct crypt_device *cd, struct device *dev)
|
||||
return opal_query_status(cd, dev, OPAL_FL_LOCKING_ENABLED);
|
||||
}
|
||||
|
||||
static int opal_activate_lsp(struct crypt_device *cd, int fd,
|
||||
const void *admin_key, size_t admin_key_len)
|
||||
{
|
||||
int r;
|
||||
struct opal_lr_act *activate = crypt_safe_alloc(sizeof(*activate));
|
||||
|
||||
if (!activate)
|
||||
return -ENOMEM;
|
||||
|
||||
*activate = (struct opal_lr_act) {
|
||||
.key = {
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
/* useless but due to kernel bug it requires (num_lrs > 0 && num_lrs <= 9) */
|
||||
.num_lrs = 1,
|
||||
};
|
||||
crypt_safe_memcpy(activate->key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_TAKE_OWNERSHIP, &activate->key);
|
||||
if (r < 0) {
|
||||
r = -ENOTSUP;
|
||||
log_dbg(cd, "OPAL not supported on this kernel version, refusing.");
|
||||
goto out;
|
||||
}
|
||||
if (r == OPAL_STATUS_NOT_AUTHORIZED) /* We'll try again with a different key. */ {
|
||||
r = -EPERM;
|
||||
log_dbg(cd, "Failed to take ownership of OPAL device '%s': permission denied",
|
||||
crypt_get_device_name(cd));
|
||||
goto out;
|
||||
}
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to take ownership of OPAL device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ACTIVATE_LSP, activate);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to activate OPAL device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
}
|
||||
out:
|
||||
crypt_safe_free(activate);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int opal_reuse_active_lsp(struct crypt_device *cd, int fd,
|
||||
uint32_t segment_number,
|
||||
const void *admin_key, size_t admin_key_len)
|
||||
{
|
||||
int r;
|
||||
struct opal_session_info *user_session = crypt_safe_alloc(sizeof(*user_session));
|
||||
|
||||
if (!user_session)
|
||||
return -ENOMEM;
|
||||
|
||||
*user_session = (struct opal_session_info) {
|
||||
.who = OPAL_ADMIN1, /* irrelevant in SUM */
|
||||
.opal_key = {
|
||||
.lr = segment_number,
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
};
|
||||
|
||||
/* If it is already enabled, wipe the locking range first */
|
||||
crypt_safe_memcpy(user_session->opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_SECURE_ERASE_LR, user_session);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to reset (secure erase) OPAL locking range %u on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
}
|
||||
out:
|
||||
crypt_safe_free(user_session);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int opal_setup_range(struct crypt_device *cd, int fd, uint32_t segment_number,
|
||||
uint64_t range_start_blocks, uint64_t range_length_blocks,
|
||||
const void *admin_key, size_t admin_key_len)
|
||||
{
|
||||
int r;
|
||||
struct opal_user_lr_setup *setup = crypt_safe_alloc(sizeof(*setup));
|
||||
|
||||
if (!setup)
|
||||
return -ENOMEM;
|
||||
|
||||
*setup = (struct opal_user_lr_setup) {
|
||||
.range_start = range_start_blocks,
|
||||
.range_length = range_length_blocks,
|
||||
/* Some drives do not enable Locking Ranges on setup. This have some
|
||||
* interesting consequences: Lock command called later below will pass,
|
||||
* but locking range will _not_ be locked at all.
|
||||
*/
|
||||
.RLE = 1,
|
||||
.WLE = 1,
|
||||
.session = {
|
||||
.who = OPAL_ADMIN1,
|
||||
.opal_key = {
|
||||
.key_len = admin_key_len,
|
||||
.lr = segment_number,
|
||||
},
|
||||
},
|
||||
};
|
||||
crypt_safe_memcpy(setup->session.opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_LR_SETUP, setup);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to setup locking range of length %llu at offset %llu on OPAL device '%s': %s",
|
||||
setup->range_length, setup->range_start, crypt_get_device_name(cd),
|
||||
opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
}
|
||||
out:
|
||||
crypt_safe_free(setup);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int opal_setup_user(struct crypt_device *cd, int fd, uint32_t segment_number,
|
||||
const void *admin_key, size_t admin_key_len)
|
||||
{
|
||||
int r;
|
||||
struct opal_lock_unlock *user_add_to_lr = crypt_safe_alloc(sizeof(*user_add_to_lr));
|
||||
|
||||
if (!user_add_to_lr)
|
||||
return -ENOMEM;
|
||||
|
||||
*user_add_to_lr = (struct opal_lock_unlock) {
|
||||
.session = {
|
||||
.who = segment_number + 1,
|
||||
.opal_key = {
|
||||
.lr = segment_number,
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
},
|
||||
.l_state = OPAL_RO,
|
||||
};
|
||||
|
||||
crypt_safe_memcpy(user_add_to_lr->session.opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ACTIVATE_USR, &user_add_to_lr->session);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to activate OPAL user on device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ADD_USR_TO_LR, user_add_to_lr);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to add OPAL user to locking range %u (RO) on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
user_add_to_lr->l_state = OPAL_RW;
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ADD_USR_TO_LR, user_add_to_lr);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to add OPAL user to locking range %u (RW) on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
}
|
||||
out:
|
||||
crypt_safe_free(user_add_to_lr);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* requires opal lock */
|
||||
int opal_setup_ranges(struct crypt_device *cd,
|
||||
struct device *dev,
|
||||
@@ -407,11 +603,8 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
const void *admin_key,
|
||||
size_t admin_key_len)
|
||||
{
|
||||
struct opal_lr_act *activate = NULL;
|
||||
struct opal_session_info *user_session = NULL;
|
||||
struct opal_lock_unlock *user_add_to_lr = NULL, *lock = NULL;
|
||||
struct opal_lock_unlock *lock = NULL;
|
||||
struct opal_new_pw *new_pw = NULL;
|
||||
struct opal_user_lr_setup *setup = NULL;
|
||||
int r, fd;
|
||||
|
||||
assert(cd);
|
||||
@@ -437,130 +630,16 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
return r;
|
||||
|
||||
/* If OPAL has never been enabled, we need to take ownership and do basic setup first */
|
||||
if (r == 0) {
|
||||
activate = crypt_safe_alloc(sizeof(struct opal_lr_act));
|
||||
if (!activate) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
*activate = (struct opal_lr_act) {
|
||||
.key = {
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
.num_lrs = 8,
|
||||
/* A max of 9 segments are supported, enable them all as there's no reason not to
|
||||
* (0 is whole-volume)
|
||||
*/
|
||||
.lr = { 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
};
|
||||
crypt_safe_memcpy(activate->key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_TAKE_OWNERSHIP, &activate->key);
|
||||
if (r < 0) {
|
||||
r = -ENOTSUP;
|
||||
log_dbg(cd, "OPAL not supported on this kernel version, refusing.");
|
||||
goto out;
|
||||
}
|
||||
if (r == OPAL_STATUS_NOT_AUTHORIZED) /* We'll try again with a different key. */ {
|
||||
r = -EPERM;
|
||||
log_dbg(cd, "Failed to take ownership of OPAL device '%s': permission denied",
|
||||
crypt_get_device_name(cd));
|
||||
goto out;
|
||||
}
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to take ownership of OPAL device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ACTIVATE_LSP, activate);
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to activate OPAL device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* If it is already enabled, wipe the locking range first */
|
||||
user_session = crypt_safe_alloc(sizeof(struct opal_session_info));
|
||||
if (!user_session) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
*user_session = (struct opal_session_info) {
|
||||
.who = OPAL_ADMIN1,
|
||||
.opal_key = {
|
||||
.lr = segment_number,
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
};
|
||||
crypt_safe_memcpy(user_session->opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_SECURE_ERASE_LR, user_session);
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to reset (secure erase) OPAL locking range %u on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
crypt_safe_free(user_session);
|
||||
|
||||
user_session = crypt_safe_alloc(sizeof(struct opal_session_info));
|
||||
if (!user_session) {
|
||||
r = -ENOMEM;
|
||||
if (r == 0)
|
||||
r = opal_activate_lsp(cd, fd, admin_key, admin_key_len);
|
||||
else
|
||||
r = opal_reuse_active_lsp(cd, fd, segment_number, admin_key, admin_key_len);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
*user_session = (struct opal_session_info) {
|
||||
.who = segment_number + 1,
|
||||
.opal_key = {
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
};
|
||||
crypt_safe_memcpy(user_session->opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ACTIVATE_USR, user_session);
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to activate OPAL user on device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
r = opal_setup_user(cd, fd, segment_number, admin_key, admin_key_len);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
user_add_to_lr = crypt_safe_alloc(sizeof(struct opal_lock_unlock));
|
||||
if (!user_add_to_lr) {
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
*user_add_to_lr = (struct opal_lock_unlock) {
|
||||
.session = {
|
||||
.who = segment_number + 1,
|
||||
.opal_key = {
|
||||
.lr = segment_number,
|
||||
.key_len = admin_key_len,
|
||||
},
|
||||
},
|
||||
.l_state = OPAL_RO,
|
||||
};
|
||||
crypt_safe_memcpy(user_add_to_lr->session.opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ADD_USR_TO_LR, user_add_to_lr);
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to add OPAL user to locking range %u (RO) on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
user_add_to_lr->l_state = OPAL_RW;
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_ADD_USR_TO_LR, user_add_to_lr);
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to add OPAL user to locking range %u (RW) on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_pw = crypt_safe_alloc(sizeof(struct opal_new_pw));
|
||||
if (!new_pw) {
|
||||
@@ -588,6 +667,8 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
crypt_safe_memcpy(new_pw->session.opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_SET_PW, new_pw);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to set OPAL user password on device '%s': (%d) %s",
|
||||
crypt_get_device_name(cd), r, opal_status_to_string(r));
|
||||
@@ -595,37 +676,10 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
setup = crypt_safe_alloc(sizeof(struct opal_user_lr_setup));
|
||||
if (!setup) {
|
||||
r = -ENOMEM;
|
||||
r = opal_setup_range(cd, fd, segment_number, range_start_blocks, range_length_blocks,
|
||||
admin_key, admin_key_len);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
*setup = (struct opal_user_lr_setup) {
|
||||
.range_start = range_start_blocks,
|
||||
.range_length = range_length_blocks,
|
||||
/* Some drives do not enable Locking Ranges on setup. This have some
|
||||
* interesting consequences: Lock command called later below will pass,
|
||||
* but locking range will _not_ be locked at all.
|
||||
*/
|
||||
.RLE = 1,
|
||||
.WLE = 1,
|
||||
.session = {
|
||||
.who = OPAL_ADMIN1,
|
||||
.opal_key = {
|
||||
.key_len = admin_key_len,
|
||||
.lr = segment_number,
|
||||
},
|
||||
},
|
||||
};
|
||||
crypt_safe_memcpy(setup->session.opal_key.key, admin_key, admin_key_len);
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_LR_SETUP, setup);
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to setup locking range of length %llu at offset %llu on OPAL device '%s': %s",
|
||||
setup->range_length, setup->range_start, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* After setup an OPAL device is unlocked, but the expectation with cryptsetup is that it needs
|
||||
* to be activated separately, so lock it immediately. */
|
||||
@@ -648,6 +702,8 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
crypt_volume_key_length(vk));
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_LOCK_UNLOCK, lock);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to lock OPAL device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
@@ -661,11 +717,7 @@ int opal_setup_ranges(struct crypt_device *cd,
|
||||
&(uint64_t) {range_length_blocks * opal_block_bytes / SECTOR_SIZE},
|
||||
&(bool) {true}, &(bool){true}, NULL, NULL);
|
||||
out:
|
||||
crypt_safe_free(activate);
|
||||
crypt_safe_free(user_session);
|
||||
crypt_safe_free(user_add_to_lr);
|
||||
crypt_safe_free(new_pw);
|
||||
crypt_safe_free(setup);
|
||||
crypt_safe_free(lock);
|
||||
|
||||
return r;
|
||||
@@ -737,6 +789,8 @@ static int opal_lock_unlock(struct crypt_device *cd,
|
||||
unlock.flags = OPAL_SAVE_FOR_LOCK;
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_SAVE, &unlock);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
if (!lock)
|
||||
log_std(cd, "Failed to prepare OPAL device '%s' for sleep resume, be aware before suspending: %s",
|
||||
@@ -790,7 +844,11 @@ int opal_factory_reset(struct crypt_device *cd,
|
||||
if (password_len > OPAL_KEY_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
fd = device_open(cd, dev, O_RDONLY);
|
||||
/*
|
||||
* Submit PSID reset on R/W file descriptor so it
|
||||
* triggers blkid rescan after we close it.
|
||||
*/
|
||||
fd = device_open(cd, dev, O_RDWR);
|
||||
if (fd < 0)
|
||||
return -EIO;
|
||||
|
||||
@@ -860,6 +918,8 @@ int opal_reset_segment(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_SECURE_ERASE_LR, user_session);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to reset (secure erase) OPAL locking range %u on device '%s': %s",
|
||||
segment_number, crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
@@ -883,6 +943,8 @@ int opal_reset_segment(struct crypt_device *cd,
|
||||
};
|
||||
|
||||
r = opal_ioctl(cd, fd, IOC_OPAL_LR_SETUP, setup);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
if (r != OPAL_STATUS_SUCCESS) {
|
||||
log_dbg(cd, "Failed to disable locking range on OPAL device '%s': %s",
|
||||
crypt_get_device_name(cd), opal_status_to_string(r));
|
||||
|
||||
@@ -15,7 +15,7 @@ static json_object *parse_json_len(struct crypt_device *cd, const char *json_are
|
||||
uint64_t max_length, int *json_len)
|
||||
{
|
||||
json_object *jobj;
|
||||
struct json_tokener *jtok;
|
||||
json_tokener *jtok;
|
||||
|
||||
/* INT32_MAX is internal (json-c) json_tokener_parse_ex() limit */
|
||||
if (!json_area || max_length > INT32_MAX)
|
||||
|
||||
@@ -203,7 +203,7 @@ int LUKS2_generate_hdr(
|
||||
uint32_t opal_segment_number,
|
||||
uint32_t opal_key_size)
|
||||
{
|
||||
struct json_object *jobj_segment, *jobj_keyslots, *jobj_segments, *jobj_config;
|
||||
json_object *jobj_segment, *jobj_keyslots, *jobj_segments, *jobj_config;
|
||||
uuid_t partitionUuid;
|
||||
int r, digest;
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ void JSON_DBG(struct crypt_device *cd, json_object *jobj, const char *desc)
|
||||
/*
|
||||
* JSON array helpers
|
||||
*/
|
||||
struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num)
|
||||
json_object *LUKS2_array_jobj(json_object *array, const char *num)
|
||||
{
|
||||
struct json_object *jobj1;
|
||||
json_object *jobj1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int) json_object_array_length(array); i++) {
|
||||
@@ -63,9 +63,9 @@ struct json_object *LUKS2_array_jobj(struct json_object *array, const char *num)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct json_object *LUKS2_array_remove(struct json_object *array, const char *num)
|
||||
json_object *LUKS2_array_remove(json_object *array, const char *num)
|
||||
{
|
||||
struct json_object *jobj1, *jobj_removing = NULL, *array_new;
|
||||
json_object *jobj1, *jobj_removing = NULL, *array_new;
|
||||
int i;
|
||||
|
||||
jobj_removing = LUKS2_array_jobj(array, num);
|
||||
@@ -1272,7 +1272,11 @@ int LUKS2_hdr_uuid(struct crypt_device *cd, struct luks2_hdr *hdr, const char *u
|
||||
int LUKS2_hdr_labels(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
const char *label, const char *subsystem, int commit)
|
||||
{
|
||||
//FIXME: check if the labels are the same and skip this.
|
||||
if ((label && strlen(label) >= LUKS2_LABEL_L) ||
|
||||
(subsystem && strlen(subsystem) >= LUKS2_LABEL_L)) {
|
||||
log_err(cd, _("Label is too long."));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(hdr->label, 0, LUKS2_LABEL_L);
|
||||
if (label)
|
||||
|
||||
@@ -45,11 +45,11 @@ out:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struct json_object **keyslot_object)
|
||||
static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, json_object **keyslot_object)
|
||||
{
|
||||
char *base64_str, cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L];
|
||||
size_t base64_len;
|
||||
struct json_object *keyslot_obj, *field, *jobj_kdf, *jobj_af, *jobj_area;
|
||||
json_object *keyslot_obj, *field, *jobj_kdf, *jobj_af, *jobj_area;
|
||||
uint64_t offset, area_size, length;
|
||||
int r;
|
||||
|
||||
@@ -136,10 +136,10 @@ err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_object **keyslots_object)
|
||||
static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, json_object **keyslots_object)
|
||||
{
|
||||
int keyslot, r;
|
||||
struct json_object *keyslot_obj, *field;
|
||||
json_object *keyslot_obj, *field;
|
||||
|
||||
keyslot_obj = json_object_new_object();
|
||||
if (!keyslot_obj)
|
||||
@@ -165,11 +165,11 @@ static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_objec
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_luks1_segment(const struct luks_phdr *hdr_v1, struct json_object **segment_object)
|
||||
static int json_luks1_segment(const struct luks_phdr *hdr_v1, json_object **segment_object)
|
||||
{
|
||||
const char *c;
|
||||
char cipher[LUKS_CIPHERNAME_L+LUKS_CIPHERMODE_L];
|
||||
struct json_object *segment_obj, *field;
|
||||
json_object *segment_obj, *field;
|
||||
uint64_t number;
|
||||
|
||||
segment_obj = json_object_new_object();
|
||||
@@ -239,10 +239,10 @@ static int json_luks1_segment(const struct luks_phdr *hdr_v1, struct json_object
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_luks1_segments(const struct luks_phdr *hdr_v1, struct json_object **segments_object)
|
||||
static int json_luks1_segments(const struct luks_phdr *hdr_v1, json_object **segments_object)
|
||||
{
|
||||
int r;
|
||||
struct json_object *segments_obj, *field;
|
||||
json_object *segments_obj, *field;
|
||||
|
||||
segments_obj = json_object_new_object();
|
||||
if (!segments_obj)
|
||||
@@ -264,12 +264,12 @@ static int json_luks1_segments(const struct luks_phdr *hdr_v1, struct json_objec
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_luks1_digest(const struct luks_phdr *hdr_v1, struct json_object **digest_object)
|
||||
static int json_luks1_digest(const struct luks_phdr *hdr_v1, json_object **digest_object)
|
||||
{
|
||||
char keyslot_str[16], *base64_str;
|
||||
int r, ks;
|
||||
size_t base64_len;
|
||||
struct json_object *digest_obj, *array, *field;
|
||||
json_object *digest_obj, *array, *field;
|
||||
|
||||
digest_obj = json_object_new_object();
|
||||
if (!digest_obj)
|
||||
@@ -380,10 +380,10 @@ static int json_luks1_digest(const struct luks_phdr *hdr_v1, struct json_object
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_luks1_digests(const struct luks_phdr *hdr_v1, struct json_object **digests_object)
|
||||
static int json_luks1_digests(const struct luks_phdr *hdr_v1, json_object **digests_object)
|
||||
{
|
||||
int r;
|
||||
struct json_object *digests_obj, *field;
|
||||
json_object *digests_obj, *field;
|
||||
|
||||
digests_obj = json_object_new_object();
|
||||
if (!digests_obj)
|
||||
@@ -400,10 +400,10 @@ static int json_luks1_digests(const struct luks_phdr *hdr_v1, struct json_object
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int json_luks1_object(struct luks_phdr *hdr_v1, struct json_object **luks1_object, uint64_t keyslots_size)
|
||||
static int json_luks1_object(struct luks_phdr *hdr_v1, json_object **luks1_object, uint64_t keyslots_size)
|
||||
{
|
||||
int r;
|
||||
struct json_object *luks1_obj, *field;
|
||||
json_object *luks1_obj, *field;
|
||||
uint64_t json_size;
|
||||
|
||||
luks1_obj = json_object_new_object();
|
||||
|
||||
@@ -34,7 +34,7 @@ struct luks2_reencrypt {
|
||||
|
||||
/* already running reencryption */
|
||||
json_object *jobj_segs_hot;
|
||||
struct json_object *jobj_segs_post;
|
||||
json_object *jobj_segs_post;
|
||||
|
||||
/* backup segments */
|
||||
json_object *jobj_segment_new;
|
||||
@@ -54,6 +54,8 @@ struct luks2_reencrypt {
|
||||
uint32_t wflags1;
|
||||
uint32_t wflags2;
|
||||
|
||||
struct device *hotzone_device;
|
||||
|
||||
struct crypt_lock_handle *reenc_lock;
|
||||
};
|
||||
#if USE_LUKS2_REENCRYPTION
|
||||
@@ -882,6 +884,8 @@ void LUKS2_reencrypt_free(struct crypt_device *cd, struct luks2_reencrypt *rh)
|
||||
rh->cw1 = NULL;
|
||||
crypt_storage_wrapper_destroy(rh->cw2);
|
||||
rh->cw2 = NULL;
|
||||
device_free(cd, rh->hotzone_device);
|
||||
rh->hotzone_device = NULL;
|
||||
|
||||
free(rh->device_name);
|
||||
free(rh->overlay_name);
|
||||
@@ -2142,34 +2146,22 @@ static int reencrypt_make_targets(struct crypt_device *cd,
|
||||
* 2) can't we derive hotzone device name from crypt context? (unlocked name, device uuid, etc?)
|
||||
*/
|
||||
static int reencrypt_load_overlay_device(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
const char *overlay, const char *hotzone, struct volume_key *vks, uint64_t size,
|
||||
const char *overlay, struct device *hotzone_device, struct volume_key *vks, uint64_t size,
|
||||
uint32_t flags)
|
||||
{
|
||||
char hz_path[PATH_MAX];
|
||||
int r;
|
||||
|
||||
struct device *hz_dev = NULL;
|
||||
struct crypt_dm_active_device dmd = {
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
log_dbg(cd, "Loading new table for overlay device %s.", overlay);
|
||||
|
||||
r = snprintf(hz_path, PATH_MAX, "%s/%s", dm_get_dir(), hotzone);
|
||||
if (r < 0 || r >= PATH_MAX) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = device_alloc(cd, &hz_dev, hz_path);
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = dm_targets_allocate(&dmd.segment, LUKS2_segments_count(hdr));
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
r = reencrypt_make_targets(cd, hdr, hz_dev, vks, &dmd.segment, size);
|
||||
r = reencrypt_make_targets(cd, hdr, hotzone_device, vks, &dmd.segment, size);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -2178,7 +2170,6 @@ static int reencrypt_load_overlay_device(struct crypt_device *cd, struct luks2_h
|
||||
/* what else on error here ? */
|
||||
out:
|
||||
dm_targets_free(cd, &dmd);
|
||||
device_free(cd, hz_dev);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -2305,9 +2296,13 @@ out:
|
||||
}
|
||||
|
||||
static int reencrypt_init_device_stack(struct crypt_device *cd,
|
||||
const struct luks2_reencrypt *rh)
|
||||
struct luks2_reencrypt *rh)
|
||||
{
|
||||
int r;
|
||||
char hz_path[PATH_MAX];
|
||||
|
||||
assert(rh);
|
||||
assert(!rh->hotzone_device);
|
||||
|
||||
/* Activate hotzone device 1:1 linear mapping to data_device */
|
||||
r = reencrypt_activate_hotzone_device(cd, rh->hotzone_name, rh->device_size, CRYPT_ACTIVATE_PRIVATE);
|
||||
@@ -2316,6 +2311,18 @@ static int reencrypt_init_device_stack(struct crypt_device *cd,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = snprintf(hz_path, PATH_MAX, "%s/%s", dm_get_dir(), rh->hotzone_name);
|
||||
if (r < 0 || r >= PATH_MAX) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = device_alloc(cd, &rh->hotzone_device, hz_path);
|
||||
if (r) {
|
||||
log_err(cd, _("Failed to allocate hotzone device %s."), rh->hotzone_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Activate overlay device with exactly same table as original 'name' mapping.
|
||||
* Note that within this step the 'name' device may already include a table
|
||||
@@ -2395,11 +2402,12 @@ static int reencrypt_refresh_overlay_devices(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
const char *overlay,
|
||||
const char *hotzone,
|
||||
struct device *hotzone_device,
|
||||
struct volume_key *vks,
|
||||
uint64_t device_size,
|
||||
uint32_t flags)
|
||||
{
|
||||
int r = reencrypt_load_overlay_device(cd, hdr, overlay, hotzone, vks, device_size, flags);
|
||||
int r = reencrypt_load_overlay_device(cd, hdr, overlay, hotzone_device, vks, device_size, flags);
|
||||
if (r) {
|
||||
log_err(cd, _("Failed to reload device %s."), overlay);
|
||||
return REENC_ERR;
|
||||
@@ -4083,7 +4091,8 @@ static reenc_status_t reencrypt_step(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
if (online) {
|
||||
r = reencrypt_refresh_overlay_devices(cd, hdr, rh->overlay_name, rh->hotzone_name, rh->vks, rh->device_size, rh->flags);
|
||||
r = reencrypt_refresh_overlay_devices(cd, hdr, rh->overlay_name, rh->hotzone_name,
|
||||
rh->hotzone_device, rh->vks, rh->device_size, rh->flags);
|
||||
/* Teardown overlay devices with dm-error. None bio shall pass! */
|
||||
if (r != REENC_OK)
|
||||
return r;
|
||||
|
||||
18
lib/setup.c
18
lib/setup.c
@@ -267,7 +267,7 @@ int init_crypto(struct crypt_device *ctx)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_backend_init(crypt_fips_mode());
|
||||
r = crypt_backend_init();
|
||||
if (r < 0)
|
||||
log_err(ctx, _("Cannot initialize crypto backend."));
|
||||
|
||||
@@ -3045,7 +3045,11 @@ int crypt_format_inline(struct crypt_device *cd,
|
||||
iparams->journal_integrity_key_size))
|
||||
return -EINVAL;
|
||||
|
||||
if (!device_is_nop_dif(idevice, &device_tag_size)) {
|
||||
r = device_is_nop_dif(idevice, &device_tag_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!r) {
|
||||
log_err(cd, _("Device %s does not provide inline integrity data fields."), mdata_device_path(cd));
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -6786,6 +6790,16 @@ int crypt_get_verity_info(struct crypt_device *cd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_get_verity_repaired(struct crypt_device *cd, const char *name,
|
||||
uint64_t *repaired)
|
||||
|
||||
{
|
||||
if (!cd || !isVERITY(cd->type) || !name || !repaired)
|
||||
return -EINVAL;
|
||||
|
||||
return dm_status_verity_repaired(cd, name, repaired);
|
||||
}
|
||||
|
||||
int crypt_get_integrity_info(struct crypt_device *cd,
|
||||
struct crypt_params_integrity *ip)
|
||||
{
|
||||
|
||||
@@ -22,25 +22,28 @@ static const struct {
|
||||
const char *name;
|
||||
const char *hash;
|
||||
unsigned int iterations;
|
||||
uint32_t parallel_cost;
|
||||
uint32_t memory_cost;
|
||||
uint32_t veracrypt_pim_const;
|
||||
uint32_t veracrypt_pim_mult;
|
||||
} tcrypt_kdf[] = {
|
||||
{ false, false, "pbkdf2", "ripemd160", 2000, 0, 0 },
|
||||
{ false, false, "pbkdf2", "ripemd160", 1000, 0, 0 },
|
||||
{ false, false, "pbkdf2", "sha512", 1000, 0, 0 },
|
||||
{ false, false, "pbkdf2", "whirlpool", 1000, 0, 0 },
|
||||
{ true, false, "pbkdf2", "sha1", 2000, 0, 0 },
|
||||
{ false, true, "pbkdf2", "sha512", 500000, 15000, 1000 },
|
||||
{ false, true, "pbkdf2", "whirlpool", 500000, 15000, 1000 },
|
||||
{ false, true, "pbkdf2", "sha256", 500000, 15000, 1000 }, // VeraCrypt 1.0f
|
||||
{ false, true, "pbkdf2", "sha256", 200000, 0, 2048 }, // boot only
|
||||
{ false, true, "pbkdf2", "blake2s-256", 500000, 15000, 1000 }, // VeraCrypt 1.26.2
|
||||
{ false, true, "pbkdf2", "blake2s-256", 200000, 0, 2048 }, // boot only
|
||||
{ false, true, "pbkdf2", "ripemd160", 655331, 15000, 1000 },
|
||||
{ false, true, "pbkdf2", "ripemd160", 327661, 0, 2048 }, // boot only
|
||||
{ false, true, "pbkdf2", "stribog512",500000, 15000, 1000 },
|
||||
// { false, true, "pbkdf2", "stribog512",200000, 0, 2048 }, // boot only
|
||||
{ false, false, NULL, NULL, 0, 0, 0 }
|
||||
{ false, false, "pbkdf2", "ripemd160", 2000, 0, 0, 0, 0 },
|
||||
{ false, false, "pbkdf2", "ripemd160", 1000, 0, 0, 0, 0 },
|
||||
{ false, false, "pbkdf2", "sha512", 1000, 0, 0, 0, 0 },
|
||||
{ false, false, "pbkdf2", "whirlpool", 1000, 0, 0, 0, 0 },
|
||||
{ true, false, "pbkdf2", "sha1", 2000, 0, 0, 0, 0 },
|
||||
{ false, true, "pbkdf2", "sha512", 500000, 0, 0, 15000, 1000 },
|
||||
{ false, true, "pbkdf2", "whirlpool", 500000, 0, 0, 15000, 1000 },
|
||||
{ false, true, "pbkdf2", "sha256", 500000, 0, 0, 15000, 1000 }, // VeraCrypt 1.0f
|
||||
{ false, true, "pbkdf2", "sha256", 200000, 0, 0, 0, 2048 }, // boot only
|
||||
{ false, true, "argon2id", NULL, 6, 1, 425984, 0, 0 }, // VeraCrypt 1.26.27
|
||||
{ false, true, "pbkdf2", "blake2s-256", 500000, 0, 0, 15000, 1000 }, // VeraCrypt 1.26.2
|
||||
{ false, true, "pbkdf2", "blake2s-256", 200000, 0, 0, 0, 2048 }, // boot only
|
||||
{ false, true, "pbkdf2", "ripemd160", 655331, 0, 0, 15000, 1000 },
|
||||
{ false, true, "pbkdf2", "ripemd160", 327661, 0, 0, 0, 2048 }, // boot only
|
||||
{ false, true, "pbkdf2", "stribog512", 500000, 0, 0, 15000, 1000 },
|
||||
// { false, true, "pbkdf2", "stribog512", 200000, 0, 0, 0, 2048 }, // boot only
|
||||
{ false, false, NULL, NULL, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
struct tcrypt_alg {
|
||||
@@ -239,7 +242,8 @@ static int TCRYPT_hdr_from_disk(struct crypt_device *cd,
|
||||
/* Set params */
|
||||
params->passphrase = NULL;
|
||||
params->passphrase_size = 0;
|
||||
params->hash_name = tcrypt_kdf[kdf_index].hash;
|
||||
/* For Argon2, overload hash_name */
|
||||
params->hash_name = tcrypt_kdf[kdf_index].hash ?: tcrypt_kdf[kdf_index].name;
|
||||
params->key_size = tcrypt_cipher[cipher_index].chain_key_size;
|
||||
params->cipher = tcrypt_cipher[cipher_index].long_name;
|
||||
params->mode = tcrypt_cipher[cipher_index].mode;
|
||||
@@ -522,7 +526,8 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
unsigned char pwd[VCRYPT_KEY_POOL_LEN] = {};
|
||||
size_t passphrase_size, max_passphrase_size;
|
||||
char *key;
|
||||
unsigned int i, skipped = 0, iterations;
|
||||
unsigned int i, skipped = 0;
|
||||
uint32_t iterations, memory;
|
||||
int r = -EPERM, keyfiles_pool_length;
|
||||
|
||||
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
|
||||
@@ -561,7 +566,9 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
pwd[i] += params->passphrase[i];
|
||||
|
||||
for (i = 0; tcrypt_kdf[i].name; i++) {
|
||||
if (params->hash_name && !strstr(tcrypt_kdf[i].hash, params->hash_name))
|
||||
if (params->hash_name && tcrypt_kdf[i].hash && !strstr(tcrypt_kdf[i].hash, params->hash_name))
|
||||
continue;
|
||||
if (params->hash_name && !tcrypt_kdf[i].hash && !strstr(tcrypt_kdf[i].name, params->hash_name))
|
||||
continue;
|
||||
if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
|
||||
continue;
|
||||
@@ -572,19 +579,36 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||
if (!tcrypt_kdf[i].veracrypt)
|
||||
continue;
|
||||
/* adjust iterations to given PIM cmdline parameter */
|
||||
iterations = tcrypt_kdf[i].veracrypt_pim_const +
|
||||
(tcrypt_kdf[i].veracrypt_pim_mult * params->veracrypt_pim);
|
||||
} else
|
||||
if (!strcmp(tcrypt_kdf[i].name, "argon2id")) {
|
||||
if (params->veracrypt_pim <= 31) {
|
||||
iterations = (params->veracrypt_pim - 1) / 3 + 3;
|
||||
memory = 1024 * (64 + (params->veracrypt_pim - 1) * 32);
|
||||
} else{
|
||||
iterations = params->veracrypt_pim - 18;
|
||||
memory = 1024 * 1024;
|
||||
}
|
||||
} else {
|
||||
iterations = tcrypt_kdf[i].veracrypt_pim_const +
|
||||
(tcrypt_kdf[i].veracrypt_pim_mult * params->veracrypt_pim);
|
||||
memory = 0;
|
||||
}
|
||||
} else {
|
||||
iterations = tcrypt_kdf[i].iterations;
|
||||
memory = tcrypt_kdf[i].memory_cost;
|
||||
}
|
||||
/* Derive header key */
|
||||
log_dbg(cd, "TCRYPT: trying KDF: %s-%s-%d%s.",
|
||||
tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations,
|
||||
params->veracrypt_pim && tcrypt_kdf[i].veracrypt ? "-PIM" : "");
|
||||
if (!strcmp(tcrypt_kdf[i].name, "argon2id"))
|
||||
log_dbg(cd, "TCRYPT: trying KDF: %s%s.", tcrypt_kdf[i].name,
|
||||
params->veracrypt_pim && tcrypt_kdf[i].veracrypt ? "-PIM" : "");
|
||||
else
|
||||
log_dbg(cd, "TCRYPT: trying KDF: %s-%s-%d%s.",
|
||||
tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations,
|
||||
params->veracrypt_pim && tcrypt_kdf[i].veracrypt ? "-PIM" : "");
|
||||
r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash,
|
||||
(char*)pwd, passphrase_size,
|
||||
hdr->salt, TCRYPT_HDR_SALT_LEN,
|
||||
key, TCRYPT_HDR_KEY_LEN,
|
||||
iterations, 0, 0);
|
||||
iterations, memory, tcrypt_kdf[i].parallel_cost);
|
||||
if (r < 0) {
|
||||
log_verbose(cd, _("PBKDF2 hash algorithm %s not available, skipping."),
|
||||
tcrypt_kdf[i].hash);
|
||||
@@ -1187,7 +1211,11 @@ int TCRYPT_dump(struct crypt_device *cd,
|
||||
log_std(cd, "Volume size:\t%" PRIu64 " [bytes]\n", hdr->d.volume_size);
|
||||
if (hdr->d.hidden_volume_size)
|
||||
log_std(cd, "Hidden size:\t%" PRIu64 " [bytes]\n", hdr->d.hidden_volume_size);
|
||||
log_std(cd, "PBKDF2 hash:\t%s\n", params->hash_name);
|
||||
if (strcmp(params->hash_name, "argon2id")) {
|
||||
log_std(cd, "PBKDF:\t\tPBKDF2\n");
|
||||
log_std(cd, "PBKDF2 hash:\t%s\n", params->hash_name);
|
||||
} else
|
||||
log_std(cd, "PBKDF:\t\tArgon2id\n");
|
||||
}
|
||||
log_std(cd, "Cipher chain:\t%s\n", params->cipher);
|
||||
log_std(cd, "Cipher mode:\t%s\n", params->mode);
|
||||
|
||||
@@ -119,6 +119,21 @@ int crypt_parse_integrity_mode(const char *s, char *integrity,
|
||||
} else if (!strcmp(s, "hmac-sha512")) {
|
||||
strncpy(integrity, "hmac(sha512)", MAX_CIPHER_LEN);
|
||||
ks = required_key_size ?: 64;
|
||||
} else if (!strcmp(s, "phmac-sha1")) {
|
||||
strncpy(integrity, "phmac(sha1)", MAX_CIPHER_LEN);
|
||||
ks = required_key_size;
|
||||
if (!required_key_size)
|
||||
r = -EINVAL;
|
||||
} else if (!strcmp(s, "phmac-sha256")) {
|
||||
strncpy(integrity, "phmac(sha256)", MAX_CIPHER_LEN);
|
||||
ks = required_key_size;
|
||||
if (!required_key_size)
|
||||
r = -EINVAL;
|
||||
} else if (!strcmp(s, "phmac-sha512")) {
|
||||
strncpy(integrity, "phmac(sha512)", MAX_CIPHER_LEN);
|
||||
ks = required_key_size;
|
||||
if (!required_key_size)
|
||||
r = -EINVAL;
|
||||
} else if (!strcmp(s, "cmac-aes")) {
|
||||
strncpy(integrity, "cmac(aes)", MAX_CIPHER_LEN);
|
||||
ks = 16;
|
||||
|
||||
@@ -1004,12 +1004,26 @@ int device_is_zoned(struct device *device)
|
||||
|
||||
int device_is_nop_dif(struct device *device, uint32_t *tag_size)
|
||||
{
|
||||
char *base_device_path;
|
||||
int r;
|
||||
struct stat st;
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
if (stat(device_path(device), &st) < 0)
|
||||
/*
|
||||
* For partition devices, check integrity profile on the base device.
|
||||
* Partition device nodes don't advertise integrity profile directly
|
||||
* via sysfs attributes.
|
||||
*/
|
||||
base_device_path = crypt_get_base_device(device_path(device));
|
||||
if (base_device_path) {
|
||||
r = stat(base_device_path, &st);
|
||||
free(base_device_path);
|
||||
} else
|
||||
r = stat(device_path(device), &st);
|
||||
|
||||
if (r < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
|
||||
@@ -205,6 +205,7 @@ int dm_status_device(struct crypt_device *cd, const char *name);
|
||||
int dm_status_suspended(struct crypt_device *cd, const char *name);
|
||||
int dm_status_verity_ok(struct crypt_device *cd, const char *name);
|
||||
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count);
|
||||
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired);
|
||||
int dm_query_device(struct crypt_device *cd, const char *name,
|
||||
uint64_t get_flags, struct crypt_dm_active_device *dmd);
|
||||
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,
|
||||
|
||||
@@ -327,24 +327,6 @@ ssize_t crypt_storage_wrapper_encrypt_write(struct crypt_storage_wrapper *cw,
|
||||
cw->data_offset + offset);
|
||||
}
|
||||
|
||||
ssize_t crypt_storage_wrapper_encrypt(struct crypt_storage_wrapper *cw,
|
||||
off_t offset, void *buffer, size_t buffer_length)
|
||||
{
|
||||
if (cw->type == NONE)
|
||||
return 0;
|
||||
|
||||
if (cw->type == DMCRYPT)
|
||||
return -ENOTSUP;
|
||||
|
||||
if (crypt_storage_encrypt(cw->u.cb.s,
|
||||
cw->u.cb.iv_start + (offset >> SECTOR_SHIFT),
|
||||
buffer_length,
|
||||
buffer))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_storage_wrapper_destroy(struct crypt_storage_wrapper *cw)
|
||||
{
|
||||
if (!cw)
|
||||
|
||||
@@ -53,8 +53,6 @@ ssize_t crypt_storage_wrapper_write(struct crypt_storage_wrapper *cw,
|
||||
off_t offset, void *buffer, size_t buffer_length);
|
||||
ssize_t crypt_storage_wrapper_encrypt_write(struct crypt_storage_wrapper *cw,
|
||||
off_t offset, void *buffer, size_t buffer_length);
|
||||
ssize_t crypt_storage_wrapper_encrypt(struct crypt_storage_wrapper *cw,
|
||||
off_t offset, void *buffer, size_t buffer_length);
|
||||
|
||||
int crypt_storage_wrapper_datasync(const struct crypt_storage_wrapper *cw);
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ The file with the integrity key.
|
||||
The size of the journal integrity key.
|
||||
Maximum is 4096 bytes.
|
||||
|
||||
*--journal-size*, *-j* _butes_::
|
||||
*--journal-size*, *-j* _bytes_::
|
||||
Size of the journal.
|
||||
|
||||
*--journal-watermark* _percent_::
|
||||
|
||||
17
meson.build
17
meson.build
@@ -2,7 +2,7 @@ project('cryptsetup',
|
||||
'c',
|
||||
default_options: [ 'prefix=/usr' ],
|
||||
meson_version: '>=0.64',
|
||||
version: '2.8.1')
|
||||
version: '2.9.0-git')
|
||||
|
||||
libcryptsetup_version = '12.11.0'
|
||||
|
||||
@@ -697,6 +697,21 @@ if cc.links(
|
||||
description: 'Define to 1 to use __attribute__((symver))')
|
||||
endif
|
||||
|
||||
# ==========================================================================
|
||||
# Check compiler support for zero_called_used_regs("used") function attribute
|
||||
if cc.links(
|
||||
'''void _test_fn(void);
|
||||
|
||||
__attribute__((zero_call_used_regs("used"))) void _test_fn(void) {
|
||||
volatile int *i; volatile int j = 0; if (j) *i = 0;
|
||||
}
|
||||
int main(void) { _test_fn(); return 0; }''',
|
||||
args: ['-O0', '-Werror' ],
|
||||
name: 'for zero_call_used_regs("used") attribute support')
|
||||
conf.set10('HAVE_ATTRIBUTE_ZEROCALLUSEDREGS', true,
|
||||
description: 'Define to 1 to use __attribute__((zero_call_used_regs("used")))')
|
||||
endif
|
||||
|
||||
# ==========================================================================
|
||||
|
||||
if get_option('dev-random')
|
||||
|
||||
@@ -246,4 +246,4 @@ ARG(OPT_WRITE_LOG, '\0', POPT_ARG_NONE, N_("Update log file after every block"),
|
||||
|
||||
ARG(OPT_DUMP_MASTER_KEY, '\0', POPT_ARG_NONE, N_("Alias for --dump-volume-key"), NULL, CRYPT_ARG_ALIAS, { .o.id = OPT_DUMP_VOLUME_KEY_ID}, {})
|
||||
|
||||
ARG(OPT_MASTER_KEY_FILE, '\0', POPT_ARG_STRING, N_("Alias for --dump-volume-key-file"), NULL, CRYPT_ARG_ALIAS, { .o.id = OPT_VOLUME_KEY_FILE_ID}, {})
|
||||
ARG(OPT_MASTER_KEY_FILE, '\0', POPT_ARG_STRING, N_("Alias for --volume-key-file"), NULL, CRYPT_ARG_ALIAS, { .o.id = OPT_VOLUME_KEY_FILE_ID}, {})
|
||||
|
||||
@@ -333,6 +333,7 @@ static int action_status(void)
|
||||
size_t root_hash_size;
|
||||
unsigned path = 0;
|
||||
int r = 0;
|
||||
uint64_t repaired;
|
||||
|
||||
/* perhaps a path, not a dm device name */
|
||||
if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
|
||||
@@ -415,6 +416,8 @@ static int action_status(void)
|
||||
log_std(" FEC offset: %" PRIu64 " [512-byte units] (%" PRIu64 " [bytes])\n",
|
||||
vp.fec_area_offset * vp.hash_block_size / SECTOR_SIZE, vp.fec_area_offset * vp.hash_block_size);
|
||||
log_std(" FEC roots: %u\n", vp.fec_roots);
|
||||
if (!crypt_get_verity_repaired(cd, action_argv[0], &repaired))
|
||||
log_std(" FEC repaired: %" PRIu64 " [events]\n", repaired);
|
||||
}
|
||||
|
||||
root_hash_size = crypt_get_volume_key_size(cd);
|
||||
|
||||
@@ -17,6 +17,9 @@ if [ "$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)" = "1" ] ; then
|
||||
echo "Kernel running in FIPS mode."
|
||||
fi
|
||||
|
||||
./crypto-check fips_mode && echo "Crypto backend running in FIPS mode."
|
||||
./crypto-check fips_mode_kernel && echo "Kernel running in FIPS mode."
|
||||
|
||||
if [ -f /etc/os-release ] ; then
|
||||
source /etc/os-release
|
||||
echo "$PRETTY_NAME ($NAME) $VERSION"
|
||||
|
||||
@@ -10,8 +10,6 @@ PWD1="93R4P4pIqAH8"
|
||||
PWD2="mymJeD8ivEhE"
|
||||
FAST_PBKDF="--pbkdf-force-iterations 1000"
|
||||
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
if [ -n "$CRYPTSETUP_TESTS_RUN_IN_MESON" ]; then
|
||||
CRYPTSETUP_VALGRIND=$CRYPTSETUP
|
||||
else
|
||||
@@ -22,7 +20,7 @@ fi
|
||||
|
||||
fips_mode()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -4059,6 +4059,7 @@ static void Luks2Refresh(void)
|
||||
static void Luks2Flags(void)
|
||||
{
|
||||
uint32_t flags = 42;
|
||||
const char *longlabel = "0123456789abcedf0123456789abcedf0123456789abcedf";
|
||||
|
||||
OK_(crypt_init(&cd, DEVICE_1));
|
||||
OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
|
||||
@@ -4089,6 +4090,9 @@ static void Luks2Flags(void)
|
||||
OK_(strcmp("", crypt_get_label(cd)));
|
||||
OK_(strcmp("", crypt_get_subsystem(cd)));
|
||||
|
||||
FAIL_(crypt_set_label(cd, longlabel, NULL), "long label");
|
||||
FAIL_(crypt_set_label(cd, NULL, longlabel), "long subsystem");
|
||||
|
||||
CRYPT_FREE(cd);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
#define LUKS_PHDR_SIZE_B 1024
|
||||
|
||||
static int _fips_mode = 0;
|
||||
static int _fips_mode_kernel = 0;
|
||||
|
||||
static char *DEVICE_1 = NULL;
|
||||
static char *DEVICE_2 = NULL;
|
||||
@@ -293,8 +294,9 @@ static int _setup(void)
|
||||
return 1;
|
||||
|
||||
_fips_mode = fips_mode();
|
||||
_fips_mode_kernel = fips_mode_kernel();
|
||||
if (_debug)
|
||||
printf("FIPS MODE: %d\n", _fips_mode);
|
||||
printf("FIPS MODE: LIB %d, KERNEL %d\n", _fips_mode, _fips_mode_kernel);
|
||||
|
||||
/* Use default log callback */
|
||||
crypt_set_log_callback(NULL, &global_log_callback, NULL);
|
||||
@@ -1833,7 +1835,7 @@ static void TcryptTest(void)
|
||||
CRYPT_FREE(cd);
|
||||
|
||||
// Following test uses non-FIPS algorithms in the cipher chain
|
||||
if(_fips_mode)
|
||||
if(_fips_mode || _fips_mode_kernel)
|
||||
return;
|
||||
|
||||
OK_(crypt_init(&cd, tcrypt_dev2));
|
||||
|
||||
@@ -31,6 +31,7 @@ int t_dm_capi_string_supported(void);
|
||||
int t_set_readahead(const char *device, unsigned value);
|
||||
|
||||
int fips_mode(void);
|
||||
int fips_mode_kernel(void);
|
||||
|
||||
int create_dmdevice_over_device(const char *dm_name, const char *device, uint64_t size, uint64_t offset);
|
||||
|
||||
|
||||
Binary file not shown.
@@ -50,7 +50,6 @@ KEY_MATERIAL5_EXT="S331776-395264"
|
||||
TEST_UUID="12345678-1234-1234-1234-123456789abc"
|
||||
|
||||
LOOPDEV=$(losetup -f 2>/dev/null)
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
remove_mapping()
|
||||
{
|
||||
@@ -83,7 +82,7 @@ trap _sigchld CHLD
|
||||
|
||||
fips_mode()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode
|
||||
}
|
||||
|
||||
can_fail_fips()
|
||||
|
||||
@@ -42,8 +42,6 @@ FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
|
||||
|
||||
TEST_UUID="12345678-1234-1234-1234-123456789abc"
|
||||
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
remove_mapping()
|
||||
{
|
||||
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove --retry $DEV_NAME2
|
||||
@@ -73,7 +71,7 @@ trap _sigchld CHLD
|
||||
|
||||
fips_mode()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode
|
||||
}
|
||||
|
||||
can_fail_fips()
|
||||
|
||||
@@ -48,7 +48,6 @@ FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
|
||||
TEST_UUID="12345678-1234-1234-1234-123456789abc"
|
||||
|
||||
LOOPDEV=$(losetup -f 2>/dev/null)
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
remove_mapping()
|
||||
{
|
||||
@@ -88,7 +87,7 @@ trap _sigchld CHLD
|
||||
|
||||
fips_mode()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode
|
||||
}
|
||||
|
||||
can_fail_fips()
|
||||
@@ -1278,6 +1277,8 @@ $CRYPTSETUP luksDump $LOOPDEV | grep "Label:" | grep -q "(no label)" || fail
|
||||
$CRYPTSETUP config $LOOPDEV --subsystem SatelliteThree --label TheLabel
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep "Subsystem:" | grep -q "SatelliteThree" || fail
|
||||
$CRYPTSETUP luksDump $LOOPDEV | grep "Label:" | grep -q "TheLabel" || fail
|
||||
$CRYPTSETUP config $LOOPDEV --label 0123456789abcdef0123456789abcdef0123456789abcdef 2>/dev/null && fail
|
||||
$CRYPTSETUP config $LOOPDEV --subsystem 0123456789abcdef0123456789abcdef0123456789abcdef 2>/dev/null && fail
|
||||
|
||||
prepare "[36] LUKS PBKDF setting" wipe
|
||||
echo $PWD1 | $CRYPTSETUP luksFormat --type luks2 --pbkdf bla $LOOPDEV >/dev/null 2>&1 && fail
|
||||
|
||||
@@ -12,24 +12,6 @@
|
||||
|
||||
#include "crypto_backend/crypto_backend.h"
|
||||
|
||||
static bool fips_mode(void)
|
||||
{
|
||||
int fd;
|
||||
char buf = 0;
|
||||
|
||||
fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
if (read(fd, &buf, 1) != 1)
|
||||
buf = '0';
|
||||
|
||||
close(fd);
|
||||
|
||||
return (buf == '1');
|
||||
}
|
||||
|
||||
static int check_cipher(const char *alg, const char *mode, unsigned long key_bits)
|
||||
{
|
||||
struct crypt_cipher *cipher;
|
||||
@@ -65,9 +47,36 @@ static int check_hash(const char *hash)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int check_pbkdf(const char *pbkdf)
|
||||
{
|
||||
const char *hash;
|
||||
uint32_t iterations, memory, parallel;
|
||||
char out[32];
|
||||
|
||||
if (!strcmp(pbkdf, "pbkdf2")) {
|
||||
hash = "sha256";
|
||||
iterations = 1000;
|
||||
memory = 0;
|
||||
parallel = 0;
|
||||
} else if (!strncmp(pbkdf, "argon2", 6)) {
|
||||
hash = NULL;
|
||||
iterations = 3;
|
||||
memory = 256;
|
||||
parallel = 1;
|
||||
} else
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!crypt_pbkdf(pbkdf, hash, "01234567890abcdef01234567890abcdef", 32,
|
||||
"11234567890abcdef11234567890abcdef", 32, out, sizeof(out),
|
||||
iterations, memory, parallel))
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn)) exit_help(bool destroy_backend)
|
||||
{
|
||||
printf("Use: crypto_check version | hash <alg> | cipher <alg> <mode> [key_bits]\n");
|
||||
printf("Use: crypto_check version | fips_mode | fips_mode_kernel | hash <alg> | cipher <alg> <mode> [key_bits] | pbkdf <alg>\n");
|
||||
if (destroy_backend)
|
||||
crypt_backend_destroy();
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -80,13 +89,21 @@ int main(int argc, char *argv[])
|
||||
if (argc < 2)
|
||||
exit_help(false);
|
||||
|
||||
if (crypt_backend_init(fips_mode())) {
|
||||
if (!strcmp(argv[1], "fips_mode"))
|
||||
return crypt_fips_mode() ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
|
||||
if (!strcmp(argv[1], "fips_mode_kernel"))
|
||||
return crypt_fips_mode_kernel() ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
|
||||
if (crypt_backend_init()) {
|
||||
printf("Crypto backend init error.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "version")) {
|
||||
printf("%s%s\n", crypt_backend_version(), fips_mode() ? " (FIPS mode)" : "" );
|
||||
printf("%s%s%s\n", crypt_backend_version(),
|
||||
crypt_fips_mode() ? " (FIPS mode)" : "",
|
||||
crypt_fips_mode_kernel() ? " (FIPS kernel)" : "");
|
||||
} else if (!strcmp(argv[1], "hash")) {
|
||||
if (argc != 3)
|
||||
exit_help(true);
|
||||
@@ -102,6 +119,10 @@ int main(int argc, char *argv[])
|
||||
exit_help(true);
|
||||
}
|
||||
r = check_cipher(argv[2], argv[3], ul);
|
||||
} else if (!strcmp(argv[1], "pbkdf")) {
|
||||
if (argc != 3)
|
||||
exit_help(true);
|
||||
r = check_pbkdf(argv[2]);
|
||||
}
|
||||
|
||||
crypt_backend_destroy();
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
#endif
|
||||
|
||||
static bool fips_active = false;
|
||||
|
||||
static void printhex(const char *s, const char *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
@@ -31,24 +29,6 @@ static void printhex(const char *s, const char *buf, size_t len)
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static bool fips_mode(void)
|
||||
{
|
||||
int fd;
|
||||
char buf = 0;
|
||||
|
||||
fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
if (read(fd, &buf, 1) != 1)
|
||||
buf = '0';
|
||||
|
||||
close(fd);
|
||||
|
||||
return (buf == '1');
|
||||
}
|
||||
|
||||
/*
|
||||
* KDF tests
|
||||
*/
|
||||
@@ -1043,7 +1023,7 @@ static int pbkdf_test_vectors(void)
|
||||
vec->salt, vec->salt_length,
|
||||
result, vec->output_length,
|
||||
vec->iterations, vec->memory, vec->parallelism) < 0) {
|
||||
if (vec->can_fail_fips && fips_mode()) {
|
||||
if (vec->can_fail_fips && crypt_fips_mode()) {
|
||||
printf("[API FAILED, IGNORED (FIPS mode)]\n");
|
||||
continue;
|
||||
}
|
||||
@@ -1552,7 +1532,7 @@ static int kernel_capi_check_test(void)
|
||||
if (!r)
|
||||
printf("[OK]\n");
|
||||
else if (r == -ENOENT || r == -ENOTSUP ||
|
||||
(fips_active && !capi_test_vectors[i].fips))
|
||||
(crypt_fips_mode_kernel() && !capi_test_vectors[i].fips))
|
||||
printf("[N/A]\n");
|
||||
else
|
||||
return EXIT_FAILURE;
|
||||
@@ -1580,9 +1560,7 @@ int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[]
|
||||
}
|
||||
#endif
|
||||
|
||||
fips_active = fips_mode();
|
||||
|
||||
if (crypt_backend_init(fips_active))
|
||||
if (crypt_backend_init())
|
||||
exit_test("Crypto backend init error.", EXIT_FAILURE);
|
||||
|
||||
printf("Test vectors using %s crypto backend.\n", crypt_backend_version());
|
||||
@@ -1615,7 +1593,7 @@ int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[]
|
||||
exit_test("Kernel CAPI test failed.", EXIT_FAILURE);
|
||||
|
||||
if (default_alg_test()) {
|
||||
if (fips_mode())
|
||||
if (crypt_fips_mode())
|
||||
printf("\nDefault compiled-in algorithms test ignored (FIPS mode on).\n");
|
||||
else
|
||||
exit_test("\nDefault compiled-in algorithms test failed.", EXIT_FAILURE);
|
||||
|
||||
@@ -33,8 +33,6 @@ else
|
||||
CRYPTSETUP_LIB_VALGRIND=../.libs
|
||||
fi
|
||||
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
remove_mapping()
|
||||
{
|
||||
[ -b /dev/mapper/$NAME ] && dmsetup remove --retry $NAME
|
||||
@@ -115,9 +113,9 @@ test_and_prepare_keyring() {
|
||||
load_key "$HEXKEY_16" user test_key "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
|
||||
}
|
||||
|
||||
fips_mode()
|
||||
fips_mode_kernel()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode_kernel
|
||||
}
|
||||
|
||||
add_device() {
|
||||
@@ -205,7 +203,7 @@ diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corrupti
|
||||
echo "OK"
|
||||
|
||||
#test serpent cipher, cbc mode, tcw IV
|
||||
fips_mode || {
|
||||
fips_mode_kernel || {
|
||||
echo -n "Testing $CIPHER_CBC_TCW..."
|
||||
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
|
||||
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
|
||||
|
||||
@@ -54,8 +54,6 @@ HAVE_KEYRING=0
|
||||
JSON_MSIZE=16384
|
||||
IMG_JSON=luks2-digest-1.json
|
||||
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
dm_crypt_features()
|
||||
{
|
||||
VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
|
||||
@@ -163,7 +161,7 @@ skip()
|
||||
|
||||
fips_mode()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode || ./crypto-check fips_mode_kernel
|
||||
}
|
||||
|
||||
add_scsi_device() {
|
||||
|
||||
@@ -30,11 +30,10 @@ LUKS1_DECRYPT="LUKS-$LUKS1_DECRYPT_UUID"
|
||||
|
||||
MNT_DIR=./mnt_luks
|
||||
START_DIR=$(pwd)
|
||||
FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)
|
||||
|
||||
fips_mode()
|
||||
{
|
||||
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
|
||||
./crypto-check fips_mode || ./crypto-check fips_mode_kernel
|
||||
}
|
||||
|
||||
del_scsi_device()
|
||||
|
||||
@@ -9,7 +9,7 @@ MAP=tctst
|
||||
PASSWORD="aaaaaaaaaaaa"
|
||||
PASSWORD_HIDDEN="bbbbbbbbbbbb"
|
||||
PASSWORD_72C="aaaaaaaaaaaabbbbbbbbbbbbccccccccccccddddddddddddeeeeeeeeeeeeffffffffffff"
|
||||
PIM=1234
|
||||
PASSWORD_PIM="cccccccccccccccccccc"
|
||||
LOOP_SYS=""
|
||||
PART_IMG=tctst-part-img
|
||||
|
||||
@@ -77,11 +77,40 @@ test_kdf() # hash img_hash
|
||||
fi
|
||||
}
|
||||
|
||||
get_HASH_CIPHER() # filename
|
||||
test_pbkdf() # pbkdf img_hash
|
||||
{
|
||||
$CRYPTOCHECK pbkdf $1
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "$1 [N/A]"
|
||||
IMGS=$(ls $TST_DIR/[tv]c* | grep "$2")
|
||||
[ -n "$IMGS" ] && rm $IMGS
|
||||
else
|
||||
echo "$1 [OK]"
|
||||
fi
|
||||
}
|
||||
|
||||
get_PARAMS() # filename
|
||||
{
|
||||
# speed up the test by limiting options for hash and (first) cipher
|
||||
HASH=$(echo $file | cut -d'-' -f3)
|
||||
CIPHER=$(echo $file | cut -d'-' -f5)
|
||||
|
||||
if [[ $file =~ vcpim.* ]] ; then
|
||||
PIM=$(echo $file | sed -r s/.*vcpim_1_\([[:digit:]]+\).*/\\1/)
|
||||
PIM_OPT="--veracrypt-pim $PIM"
|
||||
PWD=$PASSWORD_PIM
|
||||
else
|
||||
PIM=""
|
||||
PIM_OPT=""
|
||||
PWD=$PASSWORD
|
||||
fi
|
||||
|
||||
SYS_OPT=""
|
||||
if [[ $file =~ sys_.* ]] ; then
|
||||
SYS_OPT="--tcrypt-system"
|
||||
else
|
||||
SYS_OPT=""
|
||||
fi
|
||||
}
|
||||
|
||||
test_required()
|
||||
@@ -97,6 +126,8 @@ test_required()
|
||||
test_kdf whirlpool whirlpool
|
||||
test_kdf stribog512 stribog
|
||||
|
||||
test_pbkdf argon2id argon2id
|
||||
|
||||
echo "REQUIRED CIPHERS TEST"
|
||||
test_one aes cbc 256 cbc-aes
|
||||
test_one aes lrw 384 lrw-aes
|
||||
@@ -155,16 +186,12 @@ test_required
|
||||
echo "HEADER CHECK"
|
||||
for file in $(ls $TST_DIR/[tv]c_* $TST_DIR/vcpim_* $TST_DIR/sys_[tv]c_*) ; do
|
||||
echo -n " $file"
|
||||
PIM_OPT=""
|
||||
[[ $file =~ vcpim.* ]] && PIM_OPT="--veracrypt-pim $PIM"
|
||||
SYS_OPT=""
|
||||
[[ $file =~ sys_.* ]] && SYS_OPT="--tcrypt-system"
|
||||
get_HASH_CIPHER $file
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h $HASH -c $CIPHER $file >/dev/null || fail
|
||||
get_PARAMS $file
|
||||
echo $PWD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h $HASH -c $CIPHER $file >/dev/null || fail
|
||||
if [[ $file =~ .*-sha512-xts-aes$ ]] ; then
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h sha512 -c aes $file >/dev/null || fail
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h xxxx $file 2>/dev/null && fail
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h sha512 -c xxx $file 2>/dev/null && fail
|
||||
echo $PWD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h sha512 -c aes $file >/dev/null || fail
|
||||
echo $PWD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h xxxx $file 2>/dev/null && fail
|
||||
echo $PWD | $CRYPTSETUP tcryptDump $SYS_OPT $PIM_OPT -h sha512 -c xxx $file 2>/dev/null && fail
|
||||
fi
|
||||
echo " [OK]"
|
||||
done
|
||||
@@ -172,17 +199,15 @@ done
|
||||
echo "HEADER CHECK (TCRYPT only)"
|
||||
for file in $(ls $TST_DIR/vc_* $TST_DIR/vcpim_*) ; do
|
||||
echo -n " $file"
|
||||
PIM_OPT=""
|
||||
[[ $file =~ vcpim.* ]] && PIM_OPT="--veracrypt-pim $PIM"
|
||||
get_HASH_CIPHER $file
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptDump --disable-veracrypt $PIM_OPT -h $HASH -c $CIPHER $file >/dev/null 2>&1 && fail
|
||||
get_PARAMS $file
|
||||
echo $PWD | $CRYPTSETUP tcryptDump --disable-veracrypt $PIM_OPT -h $HASH -c $CIPHER $file >/dev/null 2>&1 && fail
|
||||
echo " [OK]"
|
||||
done
|
||||
|
||||
echo "HEADER CHECK (HIDDEN)"
|
||||
for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
|
||||
echo -n " $file (hidden)"
|
||||
get_HASH_CIPHER $file
|
||||
get_PARAMS $file
|
||||
echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptDump --tcrypt-hidden -h $HASH -c $CIPHER $file >/dev/null || fail
|
||||
echo " [OK]"
|
||||
done
|
||||
@@ -190,10 +215,10 @@ done
|
||||
echo "HEADER KEYFILES CHECK"
|
||||
for file in $(ls $TST_DIR/[tv]ck_*) ; do
|
||||
echo -n " $file"
|
||||
get_PARAMS $file
|
||||
PWD=$PASSWORD
|
||||
[[ $file =~ vck_1_nopw.* ]] && PWD=""
|
||||
[[ $file =~ vck_1_pw72.* ]] && PWD=$PASSWORD_72C
|
||||
get_HASH_CIPHER $file
|
||||
echo $PWD | $CRYPTSETUP tcryptDump -d $TST_DIR/keyfile1 -d $TST_DIR/keyfile2 -h $HASH -c $CIPHER $file >/dev/null || fail
|
||||
echo " [OK]"
|
||||
done
|
||||
@@ -207,10 +232,8 @@ fi
|
||||
echo "ACTIVATION FS UUID CHECK"
|
||||
for file in $(ls $TST_DIR/[tv]c_* $TST_DIR/vcpim_*) ; do
|
||||
echo -n " $file"
|
||||
PIM_OPT=""
|
||||
[[ $file =~ vcpim.* ]] && PIM_OPT="--veracrypt-pim $PIM"
|
||||
get_HASH_CIPHER $file
|
||||
out=$(echo $PASSWORD | $CRYPTSETUP tcryptOpen $PIM_OPT -r -h $HASH -c $CIPHER $file $MAP 2>&1)
|
||||
get_PARAMS $file
|
||||
out=$(echo $PWD | $CRYPTSETUP tcryptOpen $PIM_OPT -r -h $HASH -c $CIPHER $file $MAP 2>&1)
|
||||
ret=$?
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
|
||||
@@ -241,28 +264,28 @@ for file in $(ls $TST_DIR/sys_[tv]c_*) ; do
|
||||
LOOP_SYS=""
|
||||
continue
|
||||
fi
|
||||
get_HASH_CIPHER $file
|
||||
get_PARAMS $file
|
||||
# map through partition name
|
||||
echo -n " [PART]"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER $LOOP_PART $MAP || fail
|
||||
echo $PWD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER $LOOP_PART $MAP || fail
|
||||
check_uuid DEAD-BABE
|
||||
$CRYPTSETUP close $MAP || fail
|
||||
if [[ $file =~ _part ]]; then
|
||||
# map through image only (TCRYPT hdr contains partition offset and size)
|
||||
echo -n "[IMG]"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER $file $MAP 2>/dev/null || fail
|
||||
echo $PWD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER $file $MAP 2>/dev/null || fail
|
||||
check_uuid DEAD-BABE
|
||||
$CRYPTSETUP close $MAP || fail
|
||||
# map through full device (TCRYPT hdr contains partition offset and size)
|
||||
echo -n "[DRIVE]"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER $LOOP_SYS $MAP || fail
|
||||
echo $PWD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER $LOOP_SYS $MAP || fail
|
||||
check_uuid DEAD-BABE
|
||||
$CRYPTSETUP close $MAP || fail
|
||||
elif [[ $file =~ _full ]]; then
|
||||
# map through image + header in real partition (whole system)
|
||||
dd if=$LOOP_PART of=$PART_IMG bs=1M >/dev/null 2>&1
|
||||
echo -n "[PART+IMG]"
|
||||
echo $PASSWORD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER --header $LOOP_PART $PART_IMG $MAP || fail
|
||||
echo $PWD | $CRYPTSETUP tcryptOpen --tcrypt-system -r -h $HASH -c $CIPHER --header $LOOP_PART $PART_IMG $MAP || fail
|
||||
check_uuid DEAD-BABE
|
||||
$CRYPTSETUP close $MAP || fail
|
||||
rm $PART_IMG
|
||||
@@ -275,7 +298,7 @@ done
|
||||
echo "ACTIVATION FS UUID (HIDDEN) CHECK"
|
||||
for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
|
||||
echo -n " $file"
|
||||
get_HASH_CIPHER $file
|
||||
get_PARAMS $file
|
||||
out=$(echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptOpen -r -h $HASH -c $CIPHER $file $MAP --tcrypt-hidden 2>&1)
|
||||
ret=$?
|
||||
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
|
||||
|
||||
Binary file not shown.
@@ -32,10 +32,10 @@
|
||||
#ifndef LOOP_CONFIGURE
|
||||
#define LOOP_CONFIGURE 0x4C0A
|
||||
struct loop_config {
|
||||
__u32 fd;
|
||||
__u32 block_size;
|
||||
struct loop_info64 info;
|
||||
__u64 __reserved[8];
|
||||
__u32 fd;
|
||||
__u32 block_size;
|
||||
struct loop_info64 info;
|
||||
__u64 __reserved[8];
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -165,20 +165,12 @@ int t_set_readahead(const char *device, unsigned value)
|
||||
|
||||
int fips_mode(void)
|
||||
{
|
||||
int fd;
|
||||
char buf = 0;
|
||||
return _system("./crypto-check fips_mode", 1) == 0;
|
||||
}
|
||||
|
||||
fd = open("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
|
||||
if (read(fd, &buf, 1) != 1)
|
||||
buf = '0';
|
||||
|
||||
close(fd);
|
||||
|
||||
return (buf == '1');
|
||||
int fips_mode_kernel(void)
|
||||
{
|
||||
return _system("./crypto-check fips_mode_kernel", 1) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -897,7 +889,7 @@ int loop_detach(const char *loop)
|
||||
|
||||
loop_fd = open(loop, O_RDONLY);
|
||||
if (loop_fd < 0)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
if (!ioctl(loop_fd, LOOP_CLR_FD, 0))
|
||||
r = 0;
|
||||
@@ -926,32 +918,31 @@ int t_get_devno(const char *name, dev_t *devno)
|
||||
|
||||
static int _read_uint64(const char *sysfs_path, uint64_t *value)
|
||||
{
|
||||
char tmp[64] = {0};
|
||||
int fd, r;
|
||||
char tmp[64] = {0};
|
||||
int fd, r;
|
||||
|
||||
if ((fd = open(sysfs_path, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
r = read(fd, tmp, sizeof(tmp));
|
||||
close(fd);
|
||||
if ((fd = open(sysfs_path, O_RDONLY)) < 0)
|
||||
return 0;
|
||||
r = read(fd, tmp, sizeof(tmp));
|
||||
close(fd);
|
||||
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
|
||||
if (sscanf(tmp, "%" PRIu64, value) != 1)
|
||||
return 0;
|
||||
if (sscanf(tmp, "%" PRIu64, value) != 1)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _sysfs_get_uint64(int major, int minor, uint64_t *value, const char *attr)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/%s",
|
||||
major, minor, attr) < 0)
|
||||
return 0;
|
||||
if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/%s", major, minor, attr) < 0)
|
||||
return 0;
|
||||
|
||||
return _read_uint64(path, value);
|
||||
return _read_uint64(path, value);
|
||||
}
|
||||
|
||||
int t_device_size_by_devno(dev_t devno, uint64_t *retval)
|
||||
|
||||
@@ -241,6 +241,7 @@ corrupt_device() # $1 device, $2 device_size(in bytes), $3 #{corrupted_bytes}
|
||||
# $1 data_device, $2 hash_device, $3 fec_device, $4 data/hash_block_size(in bytes),
|
||||
# $5 data_size(in blocks), $6 device_size(in blocks), $7 hash_offset(in bytes),
|
||||
# $8 fec_offset(in bytes), $9 fec_roots, ${10} corrupted_bytes, [${11} superblock(y/n), ${12} salt]
|
||||
# NOTE: do not use fail() in this function, use RET code
|
||||
check_fec()
|
||||
{
|
||||
INDEX=25
|
||||
@@ -292,18 +293,32 @@ check_fec()
|
||||
dd if=/dev/mapper/$DEV_NAME of=$IMG_TMP > /dev/null 2>&1
|
||||
HASH_REPAIRED=$(sha256sum $IMG_TMP | cut -d' ' -f 1)
|
||||
|
||||
# If empty, status not supported
|
||||
REPAIRED=$(dmsetup status $DEV_NAME |sed -e s/.*verity\ \[VC\]\ *//)
|
||||
if [ -n "$REPAIRED" -a "$REPAIRED" != "-" ] ; then
|
||||
echo -n "[EC events: $REPAIRED]"
|
||||
else
|
||||
REPAIRED=""
|
||||
fi
|
||||
|
||||
$VERITYSETUP close $DEV_NAME
|
||||
|
||||
if [ "$HASH_ORIG" != "$HASH_REPAIRED" ]; then
|
||||
echo -n "[kernel correction failed]"
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && fail "Userspace verify should fail"
|
||||
echo -n "[userspace verify failed]"
|
||||
RET=1
|
||||
if [ -n "$REPAIRED" ]; then
|
||||
[ "$REPAIRED" -eq 0 ] || { RET=4; echo "FEC repaired events should be 0."; }
|
||||
fi
|
||||
echo -n "[kernel correction failed]"
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 && { RET=5; echo "Userspace verify should fail"; }
|
||||
echo -n "[userspace verify failed]"
|
||||
else
|
||||
echo -n "[repaired in kernel]"
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || fail "Userspace verify failed"
|
||||
echo "[userspace verify][OK]"
|
||||
RET=0
|
||||
echo -n "[repaired in kernel]"
|
||||
if [ -n "$REPAIRED" ]; then
|
||||
[ "$REPAIRED" -gt 0 ] || { RET=4; echo "FEC repaired events should be greater than 0."; }
|
||||
fi
|
||||
$VERITYSETUP verify $1 $2 $ROOT_HASH --fec-device=$3 $PARAMS >/dev/null 2>&1 || { RET=5; echo "Userspace verify failed"; }
|
||||
echo "[userspace verify][OK]"
|
||||
fi
|
||||
rm $1 $2 $3 $IMG_TMP > /dev/null 2>&1
|
||||
return $RET
|
||||
@@ -531,10 +546,10 @@ if check_version 1 3; then
|
||||
echo "Veritysetup [FEC tests]"
|
||||
for INDEX in {1..4}; do
|
||||
# in the first iteration check if we can use FEC (it can be compiled-out)
|
||||
(check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) )
|
||||
(check_fec $IMG $IMG $IMG 4096 30 150 163840 409600 $(($RANDOM % 23 + 2)) $(($INDEX * 4)))
|
||||
RET=$?
|
||||
[ "$RET" -eq "3" ] && break
|
||||
[ "$RET" -eq "0" ] || fail "FEC repair failed"
|
||||
[ "$RET" -eq 3 ] && break
|
||||
[ "$RET" -eq 0 ] || fail "FEC repair failed"
|
||||
|
||||
(check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'n' $SALT) || fail "FEC repair failed"
|
||||
(check_fec $IMG $IMG $IMG 512 500 50000 2457600 4915200 $(($RANDOM % 23 + 2)) $(($INDEX * 4)) 'y' $SALT) || fail "FEC repair failed"
|
||||
@@ -546,7 +561,9 @@ if check_version 1 3; then
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 512 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 1024 2000 2000 0 0 $(($RANDOM % 23 + 2)) $(($INDEX * 4))) || fail "FEC repair failed"
|
||||
# this test should fail
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200))) && fail "FEC repair must fail"
|
||||
(check_fec $IMG $IMG_HASH $FEC_DEV 4096 30 30 0 0 $(($RANDOM % 23 + 2)) $(($RANDOM % 200 + 200)))
|
||||
RET=$?
|
||||
[ "$RET" -eq 1 ] || fail "FEC repair must fail"
|
||||
echo "[OK]"
|
||||
done
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user