Compare commits

...

8 Commits

Author SHA1 Message Date
Milan Broz
8b3eb37046 tests: Add new trcypt images for Argon2 PBKDF.
Also modify test to use longer PIM password, as VeraCrypt
requires at least 20 character password with lower PIM values.
2025-11-20 19:07:47 +01:00
Milan Broz
e9bd43a8fa tests: Add PBKDF check for crypto helper.
This can be used in FIPS mode to skip Argon2 if not available.
2025-11-20 19:07:47 +01:00
Milan Broz
8311a8a903 tcrypt: Support Argon2id PBKDF introduced in VeraCrypt 1.26.27.
It uses Argon2id only, with maximal memory cost 1024 MiB.
Parallel cost is always 1.

Default parameters (no PIM) is 416 MiB, 6 iterations (same as PIM 12).

In PIM mode, iterations and memory costs are calculated according
to the specific formula. Memory cost is always limited as above.
2025-11-20 19:07:47 +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
31 changed files with 299 additions and 160 deletions

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

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

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."));
@@ -6790,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)
{

View File

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

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

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

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

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

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

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

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

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

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