Fix crypt_cipher_check_kernel to work with length-preserving modes too.

The check is currently used only with AEAD, but whould work also
with common block ciphers and modes.
This commit is contained in:
Milan Broz
2024-07-09 21:23:57 +02:00
committed by Daniel Zaťovič
parent 5e04a82e53
commit ce38d82025
2 changed files with 78 additions and 11 deletions

View File

@@ -200,8 +200,8 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
const char *integrity, size_t key_length)
{
struct crypt_cipher_kernel c;
char mode_name[64], tmp_salg_name[180], *real_mode = NULL, *cipher_iv = NULL, *key;
const char *salg_type;
char mode_name[64], tmp_salg_name[180], *cipher_iv = NULL, *key;
const char *salg_type, *real_mode;
bool aead;
int r;
struct sockaddr_alg sa = {
@@ -209,6 +209,7 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
};
aead = integrity && strcmp(integrity, "none");
real_mode = NULL;
/* Remove IV if present */
if (mode) {
@@ -229,14 +230,22 @@ int crypt_cipher_check_kernel(const char *name, const char *mode,
memset(tmp_salg_name, 0, sizeof(tmp_salg_name));
/* FIXME: this is duplicating a part of devmapper backend */
if (aead && !strcmp(integrity, "poly1305"))
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc7539(%s,%s)", name, integrity);
else if (!real_mode)
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name);
else if (aead && !strcmp(real_mode, "ccm"))
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc4309(%s(%s))", real_mode, name);
else
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
if (aead) {
/* In AEAD, mode parameter can be just IV like "random" */
if (!strcmp(integrity, "poly1305"))
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc7539(%s,%s)", name, integrity);
else if (!real_mode)
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name);
else if (!strcmp(real_mode, "ccm"))
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc4309(%s(%s))", real_mode, name);
else
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
} else {
if (!mode)
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name);
else
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode ?: mode_name, name);
}
if (r < 0 || (size_t)r >= sizeof(tmp_salg_name))
return -EINVAL;

View File

@@ -18,6 +18,8 @@
# 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;
@@ -1508,6 +1510,57 @@ static int memcmp_test(void)
return EXIT_SUCCESS;
}
#ifdef ENABLE_AF_ALG
struct capi_test_vector {
const char *name;
const char *mode;
const char *integrity;
size_t key_length;
bool fips;
};
static struct capi_test_vector capi_test_vectors[] = {
{ "aes", "xts", NULL, 64, true },
{ "aes", "xts-plain64", NULL, 32, true },
{ "aes", "xts-plain64", NULL, 64, true },
{ "aes", "xts-plain64", "none", 64, true },
{ "aes", "gcm-random", "aead", 16, true },
{ "aes", "gcm-random", "aead", 32, true },
{ "aes", "ccm-random", "aead", 19, false },
{ "aes", "ccm-random", "aead", 35, false },
{ "chacha20", "random", "poly1305", 32, false },
{ "aegis128", "random", "aead", 16, false },
};
#endif
static int kernel_capi_check_test(void)
{
#ifdef ENABLE_AF_ALG
unsigned int i;
int r;
for (i = 0; i < ARRAY_SIZE(capi_test_vectors); i++) {
printf("CAPI %s/%s/%s/%zu ", capi_test_vectors[i].name,
capi_test_vectors[i].mode,
capi_test_vectors[i].integrity ?: "NULL",
capi_test_vectors[i].key_length);
r = crypt_cipher_check_kernel(capi_test_vectors[i].name,
capi_test_vectors[i].mode,
capi_test_vectors[i].integrity,
capi_test_vectors[i].key_length);
if (!r)
printf("[OK]\n");
else if (r == -ENOENT || r == -ENOTSUP ||
(fips_active && !capi_test_vectors[i].fips))
printf("[N/A]\n");
else
return EXIT_FAILURE;
}
#endif
return EXIT_SUCCESS;
}
static void __attribute__((noreturn)) exit_test(const char *msg, int r)
{
if (msg)
@@ -1527,7 +1580,9 @@ int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[]
}
#endif
if (crypt_backend_init(fips_mode()))
fips_active = fips_mode();
if (crypt_backend_init(fips_active))
exit_test("Crypto backend init error.", EXIT_FAILURE);
printf("Test vectors using %s crypto backend.\n", crypt_backend_version());
@@ -1556,6 +1611,9 @@ int main(__attribute__ ((unused)) int argc, __attribute__ ((unused))char *argv[]
if (utf8_16_test())
exit_test("UTF8/16 test failed.", EXIT_FAILURE);
if (kernel_capi_check_test())
exit_test("Kernel CAPI test failed.", EXIT_FAILURE);
if (default_alg_test()) {
if (fips_mode())
printf("\nDefault compiled-in algorithms test ignored (FIPS mode on).\n");