Compare commits

..

16 Commits

Author SHA1 Message Date
Milan Broz
36809e1fa2 ci: Try to build fuzzers without Docker image 2025-11-30 20:08:56 +01:00
Kristina Hanicova
f1ba606c28 ci: Add debian unstable (sid) 2025-11-28 20:46:56 +01:00
Ondrej Kozina
5d69c34f59 Reinstate pbkdf serialization flag in device activation.
crypt_activate_by_keyslot_context never respected pbkdf serialation
flag (CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF).

In fact it worked only when device was activated via passphrase or via
passphrase file. It was never respected when device was activated
by a token for example.

When the internal code was fully switched to activation via keyslot
context the legacy code for passphrase based activation was dropped
and we lost track of serialization flag completely.

This fixes all of the issues so now the serialization flag will be
respected also with tokens (and all other activation methods unlocking
LUKS2 keyslot with memory hard pbkdf).

Fixes: 58385d68d8 (Allow activation via keyslot context)
Fixes: #968.
2025-11-27 14:51:44 +01:00
Ondrej Kozina
e1cbd4ecba tests: add simple verification test for --serialize-memory-hard-pbkdf 2025-11-27 14:51:32 +01:00
Kfir Kahanov
9ea9af1bcd tests: Add Bitlocker images for clearkey 2025-11-21 22:07:01 +02:00
Kfir Kahanov
4fe1601d9c bitlocker: Open bitlocker devices with clearkey
Always trying to open with clearkey when available
2025-11-21 22:07:01 +02:00
Kfir Kahanov
72173b2777 bitlocker: Handle getting NULL passwords 2025-11-21 22:07:01 +02:00
Kfir Kahanov
f304132b2b bitlocker: Support clearkey
Clearkey does not mean partially encrypted, and may be on fully
encrypted volumes.
2025-11-21 22:07:01 +02:00
Milan Broz
0779c8ceed Explicitly mention units (bytes) for volume key in header. 2025-11-21 16:34:47 +01:00
Milan Broz
153aed3d16 Fix key-size descriptions
For compatibility reasons, cryptsetup uses key size in BITS
while integritysetup in BYTES.

The help is confusing here, this patch fixes it.

Thanks Daniel Tang for notification.
2025-11-21 16:34:47 +01:00
Milan Broz
8a3e16fa25 tests: Avoid verity concurrent test failure on device node check
This regularly crashes on Alpine Linux that use some strange
configuration.
Udev settle seems to help, despite it should be noop on recent systems...
2025-11-21 14:29:38 +01:00
Milan Broz
8da66c3066 verity: Support status info about FEC repaired events
Kernel 6.19 will support additional info on dm-verity status
line that contains number of FEC successful repair events.

This patch adds support to libcryptsetup and veritysetup status command.

Ref. https://lore.kernel.org/dm-devel/074e1ecc-6690-1c22-0dba-454e191e1b6f@redhat.com/T/#m1af31c9c4263fe2b1fb58dee2fd7f0bdf045c463
2025-11-20 17:18:37 +01:00
Milan Broz
11a4fc6790 tests: use utility to detect FIPS mode
Also try to use crypto lib/kernel check where appropriate.

This can be useful for local testing (non-FIPS kernel) byt
should not break real FIPS systems.
2025-11-19 22:09:27 +01:00
Milan Broz
e4c498d15b Remove fips argument from crypt_backend_init()
It is really not needed, as it is detected automagically.
2025-11-19 22:09:27 +01:00
Milan Broz
e609c47916 tests: Add fips mode detection to crypt check tool 2025-11-19 22:09:27 +01:00
Milan Broz
ccc0c69cd7 Add fips_mode check for kernel.
Akso add a separate function so we can detect that kernel and crypto
lib is in different FIPS state (only for testing).
2025-11-19 22:09:27 +01:00
37 changed files with 429 additions and 220 deletions

View File

@@ -1,46 +1,25 @@
cifuzz:
variables:
OSS_FUZZ_PROJECT_NAME: cryptsetup
CFL_PLATFORM: gitlab
CIFUZZ_DEBUG: "True"
FUZZ_SECONDS: 300 # 5 minutes per fuzzer
ARCHITECTURE: "x86_64"
DRY_RUN: "False"
LOW_DISK_SPACE: "True"
BAD_BUILD_CHECK: "True"
LANGUAGE: "c"
DOCKER_HOST: "tcp://docker:2375"
DOCKER_IN_DOCKER: "true"
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
image:
name: gcr.io/oss-fuzz-base/cifuzz-base
entrypoint: [""]
services:
- docker:dind
image: ubuntu:noble
tags:
- gitlab-org-docker
stage: test
parallel:
matrix:
- SANITIZER: [address, undefined, memory]
interruptible: true
rules:
# Default code change.
# - if: $CI_PIPELINE_SOURCE == "merge_request_event"
# variables:
# MODE: "code-change"
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
when: never
- if: $BUILD_AND_RUN_FUZZERS != null
before_script:
# Get gitlab's container id.
- export CFL_CONTAINER_ID=`cut -c9- < /proc/1/cpuset`
- apt-get -y update
- >
apt-get -y install -y -qq git clang 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
flex bison cmake ninja-build
parallel:
matrix:
# memory does not work for now
- SANITIZER: [address, undefined]
script:
# Will build and run the fuzzers.
# We use a hack to override CI_JOB_ID, because otherwise a bad path is used
# in GitLab CI environment
- CI_JOB_ID="$CI_PROJECT_NAMESPACE/$CI_PROJECT_TITLE" python3 "/opt/oss-fuzz/infra/cifuzz/cifuzz_combined_entrypoint.py"
artifacts:
# Upload artifacts when a crash makes the job fail.
when: always
paths:
- artifacts/
- cd tests/fuzz
- ./oss-fuzz-build.sh
- ls -l out

View File

@@ -17,6 +17,48 @@
- ./configure --enable-libargon2 --enable-asciidoc
test-mergerq-job-debian:
extends:
- .debian-prep
tags:
- libvirt
- cryptsetup-debian-unstable
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-unstable
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-debian:
extends:
- .debian-prep
tags:
- libvirt
- cryptsetup-debian-unstable
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-unstable
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
test-mergerq-job-debian12:
extends:
- .debian-prep
tags:
@@ -37,7 +79,7 @@ test-mergerq-job-debian:
- make -j -C tests check-programs
- sudo -E make check
test-main-commit-job-debian:
test-main-commit-job-debian12:
extends:
- .debian-prep
tags:
@@ -60,6 +102,50 @@ test-main-commit-job-debian:
# meson tests
test-mergerq-job-debian-meson:
extends:
- .debian-prep
tags:
- libvirt
- cryptsetup-debian-unstable
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-unstable
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-debian-meson:
extends:
- .debian-prep
tags:
- libvirt
- cryptsetup-debian-unstable
stage: test
interruptible: true
variables:
DISTRO: cryptsetup-debian-unstable
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
test-mergerq-job-debian12-meson:
extends:
- .debian-prep
tags:
@@ -81,7 +167,7 @@ test-mergerq-job-debian-meson:
- ninja -C build
- cd build && sudo -E meson test --verbose --print-errorlogs
test-main-commit-job-debian-meson:
test-main-commit-job-debian12-meson:
extends:
- .debian-prep
tags:

View File

@@ -264,10 +264,11 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
bool supported = false;
int r = 0;
/* only passphrase or recovery passphrase vmks are supported (can be used to activate) */
/* only passphrase, recovery passphrase, startup key and clearkey vmks are supported (can be used to activate) */
supported = (*vmk)->protection == BITLK_PROTECTION_PASSPHRASE ||
(*vmk)->protection == BITLK_PROTECTION_RECOVERY_PASSPHRASE ||
(*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY;
(*vmk)->protection == BITLK_PROTECTION_STARTUP_KEY ||
(*vmk)->protection == BITLK_PROTECTION_CLEAR_KEY;
while ((end - start) >= (ssize_t)(sizeof(key_entry_size) + sizeof(key_entry_type) + sizeof(key_entry_value))) {
/* size of this entry */
@@ -324,17 +325,13 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
crypt_volume_key_add_next(&((*vmk)->vk), vk);
/* clear key for a partially decrypted volume */
} else if (key_entry_value == BITLK_ENTRY_VALUE_KEY) {
/* We currently don't want to support opening a partially decrypted
* device so we don't need to store this key.
*
* key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + 4);
* key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + 4;
* vk = crypt_alloc_volume_key(key_size, key);
* if (vk == NULL)
* return -ENOMEM;
* crypt_volume_key_add_next(&((*vmk)->vk), vk);
*/
log_dbg(cd, "Skipping clear key metadata entry.");
/* For clearkey protection, we need to store this key */
key_size = key_entry_size - (BITLK_ENTRY_HEADER_LEN + 4);
key = (const char *) data + start + BITLK_ENTRY_HEADER_LEN + 4;
vk = crypt_alloc_volume_key(key_size, key);
if (vk == NULL)
return -ENOMEM;
crypt_volume_key_add_next(&((*vmk)->vk), vk);
/* unknown timestamps in recovery protected VMK */
} else if (key_entry_value == BITLK_ENTRY_VALUE_RECOVERY_TIME) {
;
@@ -1135,6 +1132,9 @@ static int bitlk_kdf(const char *password,
int i = 0;
int r = 0;
if (!password)
return -EINVAL;
memcpy(kdf.salt, salt, 16);
r = crypt_hash_init(&hd, BITLK_KDF_HASH);
@@ -1249,6 +1249,41 @@ out:
return r;
}
static int get_clear_key(struct crypt_device *cd, const struct bitlk_vmk *vmk, struct volume_key **vmk_dec_key)
{
struct volume_key *nested_key = vmk->vk;
if (!nested_key) {
log_dbg(cd, "Clearkey VMK structure incomplete - missing nested key");
return -ENOTSUP;
}
struct volume_key *encrypted_vmk = crypt_volume_key_next(nested_key);
if (!encrypted_vmk) {
log_dbg(cd, "Clearkey VMK structure incomplete - missing encrypted VMK");
return -ENOTSUP;
}
/**
* For clearkey protection, we need to decrypt the encrypted VMK using the nested key
* and return the decrypted VMK as vmk_dec_key
*/
struct volume_key *decrypted_vmk = NULL;
int r = decrypt_key(cd, &decrypted_vmk, encrypted_vmk, nested_key,
vmk->mac_tag, BITLK_VMK_MAC_TAG_SIZE,
vmk->nonce, BITLK_NONCE_SIZE, false);
if (r == 0 && decrypted_vmk) {
log_dbg(cd, "Successfully decrypted VMK using nested key");
*vmk_dec_key = decrypted_vmk;
return 0;
} else {
log_dbg(cd, "Failed to decrypt VMK using nested key (error: %d)", r);
return r;
}
}
int BITLK_get_volume_key(struct crypt_device *cd,
const char *password,
size_t passwordLen,
@@ -1264,6 +1299,7 @@ int BITLK_get_volume_key(struct crypt_device *cd,
next_vmk = params->vmks;
while (next_vmk) {
bool is_decrypted = false;
if (next_vmk->protection == BITLK_PROTECTION_PASSPHRASE) {
r = bitlk_kdf(password, passwordLen, false, next_vmk->salt, &vmk_dec_key);
if (r) {
@@ -1298,8 +1334,18 @@ int BITLK_get_volume_key(struct crypt_device *cd,
continue;
}
log_dbg(cd, "Trying to use external key found in provided password.");
} else if (next_vmk->protection == BITLK_PROTECTION_CLEAR_KEY) {
r = get_clear_key(cd, next_vmk, &vmk_dec_key);
if (r) {
/* something wrong happened, but we still want to check other key slots */
next_vmk = next_vmk->next;
continue;
}
is_decrypted = true;
open_vmk_key = vmk_dec_key;
log_dbg(cd, "Extracted VMK using clearkey.");
} else {
/* only passphrase, recovery passphrase and startup key VMKs supported right now */
/* only passphrase, recovery passphrase, startup key and clearkey VMKs supported right now */
log_dbg(cd, "Skipping %s", get_vmk_protection_string(next_vmk->protection));
next_vmk = next_vmk->next;
if (r == 0)
@@ -1308,19 +1354,21 @@ int BITLK_get_volume_key(struct crypt_device *cd,
continue;
}
log_dbg(cd, "Trying to decrypt %s.", get_vmk_protection_string(next_vmk->protection));
r = decrypt_key(cd, &open_vmk_key, next_vmk->vk, vmk_dec_key,
next_vmk->mac_tag, BITLK_VMK_MAC_TAG_SIZE,
next_vmk->nonce, BITLK_NONCE_SIZE, false);
if (!is_decrypted) {
r = decrypt_key(cd, &open_vmk_key, next_vmk->vk, vmk_dec_key,
next_vmk->mac_tag, BITLK_VMK_MAC_TAG_SIZE,
next_vmk->nonce, BITLK_NONCE_SIZE, false);
crypt_free_volume_key(vmk_dec_key);
}
if (r < 0) {
log_dbg(cd, "Failed to decrypt VMK using provided passphrase.");
crypt_free_volume_key(vmk_dec_key);
if (r == -ENOTSUP)
return r;
next_vmk = next_vmk->next;
continue;
}
crypt_free_volume_key(vmk_dec_key);
log_dbg(cd, "Trying to decrypt validation metadata using VMK.");
r = crypt_bitlk_decrypt_key(crypt_volume_key_get_key(open_vmk_key),
@@ -1379,8 +1427,6 @@ int BITLK_get_volume_key(struct crypt_device *cd,
static int _activate_check(struct crypt_device *cd,
const struct bitlk_metadata *params)
{
const struct bitlk_vmk *next_vmk = NULL;
if (!params->state) {
log_err(cd, _("This BITLK device is in an unsupported state and cannot be activated."));
return -ENOTSUP;
@@ -1391,15 +1437,6 @@ static int _activate_check(struct crypt_device *cd,
return -ENOTSUP;
}
next_vmk = params->vmks;
while (next_vmk) {
if (next_vmk->protection == BITLK_PROTECTION_CLEAR_KEY) {
log_err(cd, _("Activation of BITLK device with clear key protection is not supported."));
return -ENOTSUP;
}
next_vmk = next_vmk->next;
}
return 0;
}

View File

@@ -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');
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -980,7 +980,7 @@ int crypt_resume_by_keyfile(struct crypt_device *cd,
* @param cd crypt device handle
* @param name name of device to resume
* @param volume_key provided volume key
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
*
* @return @e 0 on success or negative errno value otherwise.
*/
@@ -1152,7 +1152,7 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
* @param cd crypt device handle
* @param keyslot requested keyslot or CRYPT_ANY_SLOT
* @param volume_key provided volume key or @e NULL if used after crypt_format
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
* @param passphrase passphrase for new keyslot
* @param passphrase_size size of passphrase
*
@@ -1182,7 +1182,7 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
* @param cd crypt device handle
* @param keyslot requested keyslot or CRYPT_ANY_SLOT
* @param volume_key provided volume key or @e NULL (see note below)
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
* @param passphrase passphrase for new keyslot
* @param passphrase_size size of passphrase
* @param flags key flags to set
@@ -1289,7 +1289,7 @@ int crypt_keyslot_context_init_by_token(struct crypt_device *cd,
*
* @param volume_key provided volume key or @e NULL if used after crypt_format
* or with CRYPT_VOLUME_KEY_NO_SEGMENT flag
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_KEY
*
* @return zero on success or negative errno otherwise.
@@ -1305,9 +1305,9 @@ int crypt_keyslot_context_init_by_volume_key(struct crypt_device *cd,
* @param cd crypt device handle initialized to device context
*
* @param volume_key provided volume key
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
* @param signature buffer with signature for the key
* @param signature_size bsize of signature buffer
* @param signature_size size of signature buffer
* @param kc returns crypt keyslot context handle type CRYPT_KC_TYPE_SIGNED_KEY
*
* @return zero on success or negative errno otherwise.
@@ -1753,7 +1753,7 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
* @param cd crypt device handle
* @param name name of device to create, if @e NULL only check volume key
* @param volume_key provided volume key (or @e NULL to use internal)
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
* @param flags activation flags
*
* @return @e 0 on success or negative errno value otherwise.
@@ -1782,9 +1782,9 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
* @param cd crypt device handle
* @param name name of device to create
* @param volume_key provided volume key
* @param volume_key_size size of volume_key
* @param volume_key_size size of volume_key in bytes
* @param signature buffer with signature for the key
* @param signature_size bsize of signature buffer
* @param signature_size size of signature buffer
* @param flags activation flags
*
* @return @e 0 on success or negative errno value otherwise.
@@ -1865,7 +1865,7 @@ int crypt_deactivate(struct crypt_device *cd, const char *name);
* @param keyslot use this keyslot or @e CRYPT_ANY_SLOT
* @param volume_key buffer for volume key
* @param volume_key_size on input, size of buffer @e volume_key,
* on output size of @e volume_key
* on output size of @e volume_key in bytes
* @param passphrase passphrase used to unlock volume key
* @param passphrase_size size of @e passphrase
*
@@ -1892,7 +1892,7 @@ int crypt_volume_key_get(struct crypt_device *cd,
* @param keyslot use this keyslot or @e CRYPT_ANY_SLOT
* @param volume_key buffer for volume key
* @param volume_key_size on input, size of buffer @e volume_key,
* on output size of @e volume_key
* on output size of @e volume_key in bytes
* @param kc keyslot context used to unlock volume key
*
* @return unlocked key slot number or negative errno otherwise.
@@ -1925,7 +1925,7 @@ int crypt_volume_key_get_by_keyslot_context(struct crypt_device *cd,
*
* @param cd crypt device handle
* @param volume_key provided volume key
* @param volume_key_size size of @e volume_key
* @param volume_key_size size of @e volume_key in bytes
*
* @return @e 0 on success or negative errno value otherwise.
*
@@ -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.
*
@@ -2172,7 +2184,7 @@ int crypt_benchmark(struct crypt_device *cd,
* @param password_size size of password
* @param salt salt for benchmark
* @param salt_size size of salt
* @param volume_key_size output volume key size
* @param volume_key_size output volume key size in bytes
* @param progress callback function
* @param usrptr provided identification in callback
*
@@ -2409,8 +2421,8 @@ void crypt_set_debug_level(int level);
* @param cd crypt device handle
* @param keyfile keyfile to read
* @param key buffer for key
* @param key_size_read size of read key
* @param keyfile_offset key offset in keyfile
* @param key_size_read size of read key in bytes
* @param keyfile_offset key offset in bytes in keyfile
* @param key_size exact key length to read from file or 0
* @param flags keyfile read flags
*

View File

@@ -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;

View File

@@ -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;

View File

@@ -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."));
@@ -5450,6 +5450,9 @@ int crypt_activate_by_keyslot_context(struct crypt_device *cd,
return _activate_loopaes(cd, name, passphrase, passphrase_size, flags);
}
if (flags & CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF)
cd->memory_hard_pbkdf_lock_enabled = true;
/* acquire the volume key(s) */
r = -EINVAL;
if (isLUKS1(cd->type)) {
@@ -5921,7 +5924,7 @@ int crypt_volume_key_get_by_keyslot_context(struct crypt_device *cd,
struct volume_key *vk = NULL;
if (!cd || !volume_key || !volume_key_size ||
(!kc && !isLUKS(cd->type) && !isTCRYPT(cd->type) && !isVERITY(cd->type)))
(!kc && !isLUKS(cd->type) && !isTCRYPT(cd->type) && !isVERITY(cd->type) && !isBITLK(cd->type)))
return -EINVAL;
if (isLUKS2(cd->type) && keyslot != CRYPT_ANY_SLOT)
@@ -5981,6 +5984,8 @@ int crypt_volume_key_get_by_keyslot_context(struct crypt_device *cd,
} else if (isBITLK(cd->type)) {
if (kc && kc->get_bitlk_volume_key)
r = kc->get_bitlk_volume_key(cd, kc, &cd->u.bitlk.params, &vk);
else if (!kc)
r = BITLK_get_volume_key(cd, NULL, 0, &cd->u.bitlk.params, &vk);
if (r < 0)
log_err(cd, _("Cannot retrieve volume key for BITLK device."));
} else if (isFVAULT2(cd->type)) {
@@ -6790,6 +6795,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)
{

View File

@@ -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,

View File

@@ -367,8 +367,9 @@ This option is available since the Linux kernel version 6.11.
endif::[]
ifdef::ACTION_LUKSFORMAT[]
*--integrity-key-size* _bytes_::
*--integrity-key-size* _bits_::
The size of the data integrity key.
The argument has to be a multiple of 8.
Configurable only for HMAC integrity.
The default integrity key size is set to the same as the hash output length.
endif::[]

View File

@@ -509,6 +509,10 @@ static int action_open_bitlk(void)
r = crypt_activate_by_volume_key(cd, activated_name,
key, keysize, activate_flags);
} else {
r = crypt_activate_by_passphrase(cd, activated_name, CRYPT_ANY_SLOT, NULL, 0, activate_flags);
if (r != -EPERM)
goto out;
tries = set_tries_tty(false);
do {
r = tools_get_key(NULL, &password, &passwordLen,
@@ -617,14 +621,19 @@ static int bitlkDump_with_volume_key(struct crypt_device *cd)
if (!vk)
return -ENOMEM;
r = tools_get_key(NULL, &password, &passwordLen,
ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
ARG_UINT32(OPT_TIMEOUT_ID), 0, 0, cd);
if (r < 0)
goto out;
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size,
password, passwordLen);
password, passwordLen);
if (r < 0) {
r = tools_get_key(NULL, &password, &passwordLen,
ARG_UINT64(OPT_KEYFILE_OFFSET_ID), ARG_UINT32(OPT_KEYFILE_SIZE_ID), ARG_STR(OPT_KEY_FILE_ID),
ARG_UINT32(OPT_TIMEOUT_ID), 0, 0, cd);
if (r < 0)
goto out;
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, vk, &vk_size,
password, passwordLen);
}
tools_passphrase_msg(r);
check_signal(&r);
if (r < 0)

View File

@@ -38,7 +38,7 @@ ARG(OPT_INTEGRITY_INLINE, '\0', POPT_ARG_NONE, N_("Use inline integrity mode (HW
ARG(OPT_INTEGRITY_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the integrity key from a file"), NULL, CRYPT_ARG_STRING, {}, {})
ARG(OPT_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the data integrity key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the data integrity key"), N_("bytes"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_INTEGRITY_LEGACY_PADDING, '\0', POPT_ARG_NONE, N_("Use inefficient legacy padding (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, {})
@@ -60,7 +60,7 @@ ARG(OPT_JOURNAL_COMMIT_TIME, '\0', POPT_ARG_STRING, N_("Journal commit time"), N
ARG(OPT_JOURNAL_INTEGRITY, '\0', POPT_ARG_STRING, N_("Journal integrity algorithm"), NULL, CRYPT_ARG_STRING, {}, {})
ARG(OPT_JOURNAL_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the journal integrity key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_JOURNAL_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the journal integrity key"), N_("bytes"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_JOURNAL_INTEGRITY_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the journal integrity key from a file"), NULL, CRYPT_ARG_STRING, {}, {})
@@ -68,7 +68,7 @@ ARG(OPT_JOURNAL_CRYPT, '\0', POPT_ARG_STRING, N_("Journal encryption algorithm")
ARG(OPT_JOURNAL_CRYPT_KEY_FILE, '\0', POPT_ARG_STRING, N_("Read the journal encryption key from a file"), NULL, CRYPT_ARG_STRING,{}, {})
ARG(OPT_JOURNAL_CRYPT_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the journal encryption key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_JOURNAL_CRYPT_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the journal encryption key"), N_("bytes"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_JOURNAL_SIZE, 'j', POPT_ARG_STRING, N_("Journal size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_JOURNAL_SIZE_ACTIONS)

View File

@@ -1914,6 +1914,7 @@ static int reencrypt_luks2_init(struct crypt_device *cd, const char *data_device
new_key_size = ARG_UINT32(OPT_NEW_KEY_SIZE_ID);
if (new_key_size || new_cipher)
/* This will convert new key size to bytes from bits */
new_key_size = get_adjusted_key_size(cipher, mode, new_key_size,
DEFAULT_LUKS1_KEYBITS, 0);
else

View File

@@ -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);

View File

@@ -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"
@@ -51,16 +54,4 @@ dmsetup version
echo "Device mapper targets:"
dmsetup targets
echo "---------------------------"
pwd
lsblk
lsblk -S
lsblk -N
lsblk -D
lsblk -t
nvme list
mount
time $CRYPTSETUP_PATH/cryptsetup benchmark
echo "---------------------------"
exit 0

View File

@@ -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() {

View File

@@ -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));

View File

@@ -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);

View File

@@ -49,6 +49,9 @@ load_vars()
if echo "$1" | grep -q -e "two-recovery"; then
# 2 extra variables for image with 2 recovery passphrases
num_vars=10
elif echo "$1" | grep -q -e "clearkey"; then
# 1 extra variable for image with clearkey
num_vars=9
else
num_vars=8
fi
@@ -67,7 +70,7 @@ check_dump()
# volume size
dump_size=$(echo "$dump" | grep "Volume size:" | cut -d: -f2 | tr -d "\t\n ")
[ "$dump_size" = "104857600[bytes]" -o "$dump_size" = "134217728[bytes]" -o "$dump_size" = "105906176[bytes]" ] || fail " volume size check from dump failed."
[ "$dump_size" = "104857600[bytes]" -o "$dump_size" = "134217728[bytes]" -o "$dump_size" = "105906176[bytes]" ] || fail " volume size check from dump failed."
# description
dump_desc=$(echo "$dump" | grep Description: | cut -d: -f2 | tr -d "\t\n ")
@@ -95,6 +98,11 @@ check_dump()
# second recovery passphrase protected VMK GUID
dump_rp2_vmk=$(echo "$dump" | grep "VMK protected with recovery passphrase" -B 1 | tail -2 | head -1 | cut -d: -f2 | tr -d "\t ")
[ ! -z "$RP2_VMK_GUID" -a "$dump_rp2_vmk" = "$RP2_VMK_GUID" ] || fail " second recovery passphrase protected VMK GUID check from dump failed."
elif echo "$file" | grep -q -e "clearkey"; then
# clearkey protected VMK GUID
dump_clearkey_guid=$(echo "$dump" | grep "VMK protected with clear key" -B 1 | tail -2 | head -1 | cut -d: -f2 | tr -d "\t ")
[ ! -z "$CLEARKEY_VMK_GUID" -a "$dump_clearkey_guid" = "$CLEARKEY_VMK_GUID" ] || fail " clear key protected VMK GUID check from dump failed."
return
else
# password protected VMK GUID
dump_pw_vmk=$(echo "$dump" | grep "VMK protected with passphrase" -B 1 | head -1 | cut -d: -f2 | tr -d "\t ")
@@ -157,7 +165,7 @@ for file in $(ls $TST_DIR/bitlk-*) ; do
ret=$?
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc-elephant" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "clearkey" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "partially-encrypted" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "eow" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "-4k.img" ) && echo " [N/A]" && continue
[ $ret -eq 0 ] || fail " failed to open $file ($ret)"
@@ -184,7 +192,7 @@ for file in $(ls $TST_DIR/bitlk-*) ; do
ret=$?
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "aes-cbc-elephant" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "clearkey" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "partially-encrypted" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "eow" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$file" | grep -q -e "-4k.img" ) && echo " [N/A]" && continue
[ $ret -eq 0 ] || fail " failed to open $file using volume key ($ret)"
@@ -236,8 +244,27 @@ for file in $(ls $TST_DIR/bitlk-*) ; do
[ "$uuid" = "$UUID" ] || fail " UUID check failed."
[ "$sha256sum" = "$SHA256SUM" ] || fail " SHA256 sum check failed."
echo " [OK]"
fi
# clear key
if echo "$file" | grep -q -e "clearkey"; then
echo -n " $file"
echo $CRYPTSETUP bitlkOpen -r $file --test-passphrase >/dev/null 2>&1
ret=$?
[ $ret -eq 1 ] && echo " [N/A]" && continue
$CRYPTSETUP bitlkOpen -r $file $MAP >/dev/null 2>&1
ret=$?
[ $ret -eq 0 ] || fail " failed to open $file ($ret)"
$CRYPTSETUP status $MAP >/dev/null || fail
$CRYPTSETUP status /dev/mapper/$MAP >/dev/null || fail
uuid=$(blkid -p -o value -s UUID /dev/mapper/$MAP)
sha256sum=$(sha256sum /dev/mapper/$MAP | cut -d" " -f1)
$CRYPTSETUP remove $MAP || fail
[ "$uuid" = "$UUID" ] || fail " UUID check failed."
[ "$sha256sum" = "$SHA256SUM" ] || fail " SHA256 sum check failed."
echo " [OK]"
fi
done
remove_mapping

Binary file not shown.

View File

@@ -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()

View File

@@ -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()

View File

@@ -45,10 +45,17 @@ KEY_FILE1=test-key-file1
FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
# 32 MiB + 1KiB to bypass minimal memory check (hardocoded)
FAST_PBKDF_ARGON_OPT="--pbkdf argon2id --pbkdf-force-iterations 4 --pbkdf-memory 32769 --pbkdf-parallel 1"
# TODO: this is configurable
LUKS2_LOCKING_DIR=/run/cryptsetup
# hardcoded value
MEMORY_HARD_LOCK_FILE=LN_memory-hard-access
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 +95,7 @@ trap _sigchld CHLD
fips_mode()
{
[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
./crypto-check fips_mode
}
can_fail_fips()
@@ -1699,5 +1706,14 @@ echo $PWD1 | $CRYPTSETUP luksFormat -q $FAST_PBKDF_OPT --type luks2 $LOOPDEV ||
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DM_BAD_NAME 2>/dev/null && fail
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV $DM_LONG_NAME 2>/dev/null && fail
if ! fips_mode -a -d $LUKS2_LOCKING_DIR; then
touch $LUKS2_LOCKING_DIR/$MEMORY_HARD_LOCK_FILE
prepare "[52] Test pbkdf serialization flag." wipe
echo $PWD1 | $CRYPTSETUP luksFormat -q $FAST_PBKDF_ARGON_OPT --type luks2 $LOOPDEV || fail
test -f $LUKS2_LOCKING_DIR/$MEMORY_HARD_LOCK_FILE || fail "The locking file disappeared unexpectedly"
echo $PWD1 | $CRYPTSETUP open --serialize-memory-hard-pbkdf --test-passphrase $LOOPDEV || fail
test -f $LUKS2_LOCKING_DIR/$MEMORY_HARD_LOCK_FILE && fail "The --serialize-memory-hard-pbkdf option did not remove the locking file (did not use the file)."
fi
remove_mapping
exit 0

View File

@@ -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;
@@ -67,7 +49,7 @@ static int check_hash(const char *hash)
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]\n");
if (destroy_backend)
crypt_backend_destroy();
exit(EXIT_FAILURE);
@@ -80,13 +62,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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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() {

View File

@@ -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()

View File

@@ -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;
}
/*

View File

@@ -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
@@ -443,6 +458,8 @@ check_concurrent() # $1 hash
wait
grep -q "Command failed with code .* (wrong or missing parameters)" $DEV_OUT && fail
grep -q "Command failed with code .* (wrong device or file specified)." $DEV_OUT && fail
# Some distros have strange udev rules, settle here seems to be necessary
udevadm settle >/dev/null 2>&1
check_exists
rm $DEV_OUT
$VERITYSETUP close $DEV_NAME >/dev/null 2>&1 || fail
@@ -531,10 +548,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 +563,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