diff --git a/lib/crypto_backend/cipher_generic.c b/lib/crypto_backend/cipher_generic.c index 9b6acfd5..0f80a904 100644 --- a/lib/crypto_backend/cipher_generic.c +++ b/lib/crypto_backend/cipher_generic.c @@ -26,53 +26,58 @@ struct cipher_alg { const char *name; + const char *mode; int blocksize; bool wrapped_key; }; /* FIXME: Getting block size should be dynamic from cipher backend. */ static const struct cipher_alg cipher_algs[] = { - { "cipher_null", 16, false }, - { "aes", 16, false }, - { "serpent", 16, false }, - { "twofish", 16, false }, - { "anubis", 16, false }, - { "blowfish", 8, false }, - { "camellia", 16, false }, - { "cast5", 8, false }, - { "cast6", 16, false }, - { "des", 8, false }, - { "des3_ede", 8, false }, - { "khazad", 8, false }, - { "seed", 16, false }, - { "tea", 8, false }, - { "xtea", 8, false }, - { "paes", 16, true }, /* protected AES, s390 wrapped key scheme */ - { NULL, 0, false } + { "cipher_null", NULL, 16, false }, + { "aes", NULL, 16, false }, + { "serpent", NULL, 16, false }, + { "twofish", NULL, 16, false }, + { "anubis", NULL, 16, false }, + { "blowfish", NULL, 8, false }, + { "camellia", NULL, 16, false }, + { "cast5", NULL, 8, false }, + { "cast6", NULL, 16, false }, + { "des", NULL, 8, false }, + { "des3_ede", NULL, 8, false }, + { "khazad", NULL, 8, false }, + { "seed", NULL, 16, false }, + { "tea", NULL, 8, false }, + { "xtea", NULL, 8, false }, + { "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */ + { "xchacha12,aes", "adiantum", 32, false }, + { "xchacha20,aes", "adiantum", 32, false }, + { NULL, NULL, 0, false } }; -static const struct cipher_alg *_get_alg(const char *name) +static const struct cipher_alg *_get_alg(const char *name, const char *mode) { int i = 0; while (name && cipher_algs[i].name) { if (!strcasecmp(name, cipher_algs[i].name)) - return &cipher_algs[i]; + if (!mode || !cipher_algs[i].mode || + !strncasecmp(mode, cipher_algs[i].mode, strlen(cipher_algs[i].mode))) + return &cipher_algs[i]; i++; } return NULL; } -int crypt_cipher_blocksize(const char *name) +int crypt_cipher_ivsize(const char *name, const char *mode) { - const struct cipher_alg *ca = _get_alg(name); + const struct cipher_alg *ca = _get_alg(name, mode); return ca ? ca->blocksize : -EINVAL; } -int crypt_cipher_wrapped_key(const char *name) +int crypt_cipher_wrapped_key(const char *name, const char *mode) { - const struct cipher_alg *ca = _get_alg(name); + const struct cipher_alg *ca = _get_alg(name, mode); return ca ? (int)ca->wrapped_key : 0; } diff --git a/lib/crypto_backend/crypto_backend.h b/lib/crypto_backend/crypto_backend.h index 862288a0..e0de050f 100644 --- a/lib/crypto_backend/crypto_backend.h +++ b/lib/crypto_backend/crypto_backend.h @@ -99,8 +99,8 @@ int argon2(const char *type, const char *password, size_t password_length, uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len); /* ciphers */ -int crypt_cipher_blocksize(const char *name); -int crypt_cipher_wrapped_key(const char *name); +int crypt_cipher_ivsize(const char *name, const char *mode); +int crypt_cipher_wrapped_key(const char *name, const char *mode); int crypt_cipher_init(struct crypt_cipher **ctx, const char *name, const char *mode, const void *key, size_t key_length); void crypt_cipher_destroy(struct crypt_cipher *ctx); diff --git a/lib/crypto_backend/crypto_storage.c b/lib/crypto_backend/crypto_storage.c index b3258479..be8abec7 100644 --- a/lib/crypto_backend/crypto_storage.c +++ b/lib/crypto_backend/crypto_storage.c @@ -60,7 +60,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx, { memset(ctx, 0, sizeof(*ctx)); - ctx->iv_size = crypt_cipher_blocksize(cipher_name); + ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name); if (ctx->iv_size < 8) return -ENOENT; diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c index bf015910..77cc3e51 100644 --- a/lib/luks2/luks2_keyslot.c +++ b/lib/luks2/luks2_keyslot.c @@ -114,17 +114,18 @@ int LUKS2_keyslot_active_count(struct luks2_hdr *hdr, int segment) int LUKS2_keyslot_cipher_incompatible(struct crypt_device *cd) { const char *cipher = crypt_get_cipher(cd); + const char *cipher_mode = crypt_get_cipher_mode(cd); /* Keyslot is already authenticated; we cannot use integrity tags here */ if (crypt_get_integrity_tag_size(cd) || !cipher) return 1; /* Wrapped key schemes cannot be used for keyslot encryption */ - if (crypt_cipher_wrapped_key(cipher)) + if (crypt_cipher_wrapped_key(cipher, cipher_mode)) return 1; /* Check if crypto backend can use the cipher */ - if (crypt_cipher_blocksize(cipher) < 0) + if (crypt_cipher_ivsize(cipher, cipher_mode) < 0) return 1; return 0; diff --git a/lib/luks2/luks2_luks1_convert.c b/lib/luks2/luks2_luks1_convert.c index 9d45d000..7a5ae150 100644 --- a/lib/luks2/luks2_luks1_convert.c +++ b/lib/luks2/luks2_luks1_convert.c @@ -674,7 +674,7 @@ int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct if (r < 0) return r; - if (crypt_cipher_wrapped_key(cipher)) { + if (crypt_cipher_wrapped_key(cipher, cipher_mode)) { log_err(cd, _("Cannot convert to LUKS1 format - device uses wrapped key cipher %s."), cipher); return -EINVAL; } diff --git a/lib/setup.c b/lib/setup.c index 2aa67838..328b2f2d 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -2368,7 +2368,7 @@ int crypt_suspend(struct crypt_device *cd, key_desc = crypt_get_device_key_description(name); /* we can't simply wipe wrapped keys */ - if (crypt_cipher_wrapped_key(crypt_get_cipher(cd))) + if (crypt_cipher_wrapped_key(crypt_get_cipher(cd), crypt_get_cipher_mode(cd))) r = dm_suspend_device(cd, name); else r = dm_suspend_and_wipe_key(cd, name); @@ -3420,7 +3420,8 @@ int crypt_volume_key_get(struct crypt_device *cd, return -EINVAL; /* wrapped keys or unbound keys may be exported */ - if (crypt_fips_mode() && !crypt_cipher_wrapped_key(crypt_get_cipher(cd))) { + if (crypt_fips_mode() && + !crypt_cipher_wrapped_key(crypt_get_cipher(cd), crypt_get_cipher_mode(cd))) { if (!isLUKS2(cd->type) || keyslot == CRYPT_ANY_SLOT || !LUKS2_keyslot_for_segment(&cd->u.luks2.hdr, keyslot, CRYPT_DEFAULT_SEGMENT)) { log_err(cd, _("Function not available in FIPS mode.")); diff --git a/tests/mode-test b/tests/mode-test index 3bf03974..6a946ef0 100755 --- a/tests/mode-test +++ b/tests/mode-test @@ -73,7 +73,7 @@ dmcrypt_check() # device outstring dmremove $1 } -dmcrypt_check_sum() # cipher device outstring +dmcrypt_check_sum() # cipher device { EXPSUM="c036cbb7553a909f8b8877d4461924307f27ecb66cff928eeeafd569c3887e29" # Fill device with zeroes and reopen it @@ -99,28 +99,35 @@ dmcrypt() { OUT=$2 [ -z "$OUT" ] && OUT=$1 - printf "%-25s" "$1" + printf "%-31s" "$1" - echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 "$DEV_NAME"_"$1" /dev/mapper/$DEV_NAME >/dev/null 2>&1 + echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 "$DEV_NAME"_tstdev /dev/mapper/$DEV_NAME >/dev/null 2>&1 if [ $? -eq 0 ] ; then echo -n -e "PLAIN:" - dmcrypt_check "$DEV_NAME"_"$1" $OUT + dmcrypt_check "$DEV_NAME"_tstdev $OUT else echo -n "[n/a]" fi - echo $PASSWORD | $CRYPTSETUP luksFormat -i 1 -c $1 -s 256 /dev/mapper/$DEV_NAME >/dev/null 2>&1 + echo $PASSWORD | $CRYPTSETUP luksFormat --type luks1 -i 1 -c $1 -s 256 /dev/mapper/$DEV_NAME >/dev/null 2>&1 if [ $? -eq 0 ] ; then - echo -n -e " LUKS:" - echo $PASSWORD | $CRYPTSETUP luksOpen /dev/mapper/$DEV_NAME "$DEV_NAME"_"$1" >/dev/null 2>&1 - dmcrypt_check "$DEV_NAME"_"$1" $OUT + echo -n -e " LUKS1:" + echo $PASSWORD | $CRYPTSETUP luksOpen /dev/mapper/$DEV_NAME "$DEV_NAME"_tstdev >/dev/null 2>&1 + dmcrypt_check "$DEV_NAME"_tstdev $OUT + fi + + echo $PASSWORD | $CRYPTSETUP luksFormat --type luks2 --pbkdf pbkdf2 -i 1 -c $1 -s 256 /dev/mapper/$DEV_NAME >/dev/null 2>&1 + if [ $? -eq 0 ] ; then + echo -n -e " LUKS2:" + echo $PASSWORD | $CRYPTSETUP luksOpen /dev/mapper/$DEV_NAME "$DEV_NAME"_tstdev >/dev/null 2>&1 + dmcrypt_check "$DEV_NAME"_tstdev $OUT fi # repeated device creation must return the same checksum - echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 "$DEV_NAME"_"$1" /dev/mapper/$DEV_NAME >/dev/null 2>&1 + echo $PASSWORD | $CRYPTSETUP create -h sha256 -c $1 -s 256 "$DEV_NAME"_tstdev /dev/mapper/$DEV_NAME >/dev/null 2>&1 if [ $? -eq 0 ] ; then echo -n -e " CHECKSUM:" - dmcrypt_check_sum "$1" "$DEV_NAME"_"$1" + dmcrypt_check_sum "$1" "$DEV_NAME"_tstdev fi echo } @@ -154,4 +161,7 @@ for cipher in $CIPHERS ; do done done +dmcrypt xchacha12,aes-adiantum-plain64 +dmcrypt xchacha20,aes-adiantum-plain64 + cleanup