summaryrefslogtreecommitdiffstats
path: root/lib/crypto_backend
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/crypto_backend/argon2/meson.build28
-rw-r--r--lib/crypto_backend/argon2_generic.c39
-rw-r--r--lib/crypto_backend/base64.c2
-rw-r--r--lib/crypto_backend/cipher_check.c4
-rw-r--r--lib/crypto_backend/cipher_generic.c5
-rw-r--r--lib/crypto_backend/crc32.c4
-rw-r--r--lib/crypto_backend/crypto_backend.h6
-rw-r--r--lib/crypto_backend/crypto_backend_internal.h4
-rw-r--r--lib/crypto_backend/crypto_cipher_kernel.c7
-rw-r--r--lib/crypto_backend/crypto_gcrypt.c150
-rw-r--r--lib/crypto_backend/crypto_kernel.c6
-rw-r--r--lib/crypto_backend/crypto_nettle.c4
-rw-r--r--lib/crypto_backend/crypto_nss.c4
-rw-r--r--lib/crypto_backend/crypto_openssl.c90
-rw-r--r--lib/crypto_backend/crypto_storage.c2
-rw-r--r--lib/crypto_backend/meson.build40
-rw-r--r--lib/crypto_backend/pbkdf2_generic.c4
-rw-r--r--lib/crypto_backend/pbkdf_check.c4
-rw-r--r--lib/crypto_backend/utf8.c2
19 files changed, 356 insertions, 49 deletions
diff --git a/lib/crypto_backend/argon2/meson.build b/lib/crypto_backend/argon2/meson.build
new file mode 100644
index 0000000..bb68516
--- /dev/null
+++ b/lib/crypto_backend/argon2/meson.build
@@ -0,0 +1,28 @@
+libargon2_sources = files(
+ 'blake2/blake2b.c',
+ 'argon2.c',
+ 'core.c',
+ 'encoding.c',
+ 'thread.c',
+)
+
+if use_internal_sse_argon2
+ libargon2_sources += files(
+ 'opt.c',
+ )
+else
+ libargon2_sources += files(
+ 'ref.c',
+ )
+endif
+
+libargon2 = static_library('argon2',
+ libargon2_sources,
+ override_options : ['c_std=c89', 'optimization=3'],
+ build_by_default : false,
+ include_directories: include_directories(
+ 'blake2',
+ ),
+ dependencies : [
+ threads,
+ ])
diff --git a/lib/crypto_backend/argon2_generic.c b/lib/crypto_backend/argon2_generic.c
index 0ce67da..eca575b 100644
--- a/lib/crypto_backend/argon2_generic.c
+++ b/lib/crypto_backend/argon2_generic.c
@@ -1,8 +1,8 @@
/*
* Argon2 PBKDF2 library wrapper
*
- * Copyright (C) 2016-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2016-2023 Milan Broz
+ * Copyright (C) 2016-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2016-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -29,14 +29,12 @@
#define CONST_CAST(x) (x)(uintptr_t)
+#if USE_INTERNAL_ARGON2 || HAVE_ARGON2_H
int argon2(const char *type, const char *password, size_t password_length,
const char *salt, size_t salt_length,
char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
-#if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H
- return -EINVAL;
-#else
argon2_type atype;
argon2_context context = {
.flags = ARGON2_DEFAULT_FLAGS,
@@ -54,6 +52,9 @@ int argon2(const char *type, const char *password, size_t password_length,
};
int r;
+ /* This code must not be run if crypt backend library natively supports Argon2 */
+ assert(!(crypt_backend_flags() & CRYPT_BACKEND_ARGON2));
+
if (!strcmp(type, "argon2i"))
atype = Argon2_i;
else if(!strcmp(type, "argon2id"))
@@ -75,5 +76,33 @@ int argon2(const char *type, const char *password, size_t password_length,
}
return r;
+}
+
+#else /* USE_INTERNAL_ARGON2 || HAVE_ARGON2_H */
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+int argon2(const char *type, const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ return -EINVAL;
+}
+
+#endif
+
+/* Additional string for crypt backend version */
+const char *crypt_argon2_version(void)
+{
+ const char *version = "";
+
+ if (crypt_backend_flags() & CRYPT_BACKEND_ARGON2)
+ return version;
+
+#if HAVE_ARGON2_H /* this has priority over internal argon2 */
+ version = " [external libargon2]";
+#elif USE_INTERNAL_ARGON2
+ version = " [cryptsetup libargon2]";
#endif
+ return version;
}
diff --git a/lib/crypto_backend/base64.c b/lib/crypto_backend/base64.c
index 42f70cb..92e558a 100644
--- a/lib/crypto_backend/base64.c
+++ b/lib/crypto_backend/base64.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Lennart Poettering
*
* cryptsetup related changes
- * Copyright (C) 2021-2023 Milan Broz
+ * Copyright (C) 2021-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/cipher_check.c b/lib/crypto_backend/cipher_check.c
index 98ec1a5..25200a4 100644
--- a/lib/crypto_backend/cipher_check.c
+++ b/lib/crypto_backend/cipher_check.c
@@ -1,8 +1,8 @@
/*
* Cipher performance check
*
- * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2018-2023 Milan Broz
+ * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/cipher_generic.c b/lib/crypto_backend/cipher_generic.c
index b3a4407..746cfcf 100644
--- a/lib/crypto_backend/cipher_generic.c
+++ b/lib/crypto_backend/cipher_generic.c
@@ -1,8 +1,8 @@
/*
* Linux kernel cipher generic utilities
*
- * Copyright (C) 2018-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2018-2023 Milan Broz
+ * Copyright (C) 2018-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2018-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -51,6 +51,7 @@ static const struct cipher_alg cipher_algs[] = {
{ "xchacha12,aes", "adiantum", 32, false },
{ "xchacha20,aes", "adiantum", 32, false },
{ "sm4", NULL, 16, false },
+ { "aria", NULL, 16, false },
{ NULL, NULL, 0, false }
};
diff --git a/lib/crypto_backend/crc32.c b/lib/crypto_backend/crc32.c
index 9009b02..7a12a8e 100644
--- a/lib/crypto_backend/crc32.c
+++ b/lib/crypto_backend/crc32.c
@@ -158,7 +158,7 @@ static const uint32_t crc32c_tab[] = {
* whatever they need.
*/
static uint32_t compute_crc32(
- const uint32_t *crc32_tab,
+ const uint32_t *crc32_table,
uint32_t seed,
const unsigned char *buf,
size_t len)
@@ -167,7 +167,7 @@ static uint32_t compute_crc32(
const unsigned char *p = buf;
while(len-- > 0)
- crc = crc32_tab[(crc ^ *p++) & 0xff] ^ (crc >> 8);
+ crc = crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return crc;
}
diff --git a/lib/crypto_backend/crypto_backend.h b/lib/crypto_backend/crypto_backend.h
index 88562e9..15ed745 100644
--- a/lib/crypto_backend/crypto_backend.h
+++ b/lib/crypto_backend/crypto_backend.h
@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
- * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2010-2023 Milan Broz
+ * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -43,9 +43,11 @@ void crypt_backend_destroy(void);
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
#define CRYPT_BACKEND_PBKDF2_INT (1 << 1) /* Iteration in PBKDF2 is signed int and can overflow */
+#define CRYPT_BACKEND_ARGON2 (1 << 2) /* Backend provides native Argon2 implementation */
uint32_t crypt_backend_flags(void);
const char *crypt_backend_version(void);
+const char *crypt_argon2_version(void);
/* HASH */
int crypt_hash_size(const char *name);
diff --git a/lib/crypto_backend/crypto_backend_internal.h b/lib/crypto_backend/crypto_backend_internal.h
index 9b1cc69..539f11a 100644
--- a/lib/crypto_backend/crypto_backend_internal.h
+++ b/lib/crypto_backend/crypto_backend_internal.h
@@ -1,8 +1,8 @@
/*
* crypto backend implementation
*
- * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2010-2023 Milan Broz
+ * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/crypto_cipher_kernel.c b/lib/crypto_backend/crypto_cipher_kernel.c
index 3460717..77b3643 100644
--- a/lib/crypto_backend/crypto_cipher_kernel.c
+++ b/lib/crypto_backend/crypto_cipher_kernel.c
@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation (skcipher)
*
- * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2012-2023 Milan Broz
+ * Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -109,6 +109,7 @@ int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
}
/* The in/out should be aligned to page boundary */
+/* coverity[ -taint_source : arg-3 ] */
static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
const char *in, size_t in_length,
char *out, size_t out_length,
@@ -312,6 +313,8 @@ int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
}
#else /* ENABLE_AF_ALG */
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
const char *mode, const void *key, size_t key_length)
{
diff --git a/lib/crypto_backend/crypto_gcrypt.c b/lib/crypto_backend/crypto_gcrypt.c
index e974aa8..8e3f14e 100644
--- a/lib/crypto_backend/crypto_gcrypt.c
+++ b/lib/crypto_backend/crypto_gcrypt.c
@@ -1,8 +1,8 @@
/*
* GCRYPT crypto backend implementation
*
- * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2010-2023 Milan Broz
+ * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <errno.h>
#include <gcrypt.h>
+#include <pthread.h>
#include "crypto_backend_internal.h"
static int crypto_backend_initialised = 0;
@@ -126,10 +127,11 @@ int crypt_backend_init(bool fips __attribute__((unused)))
crypto_backend_initialised = 1;
crypt_hash_test_whirlpool_bug();
- r = snprintf(version, sizeof(version), "gcrypt %s%s%s",
+ r = snprintf(version, sizeof(version), "gcrypt %s%s%s%s",
gcry_check_version(NULL),
crypto_backend_secmem ? "" : ", secmem disabled",
- crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "");
+ crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "",
+ crypt_backend_flags() & CRYPT_BACKEND_ARGON2 ? ", argon2" : "");
if (r < 0 || (size_t)r >= sizeof(version))
return -EINVAL;
@@ -151,7 +153,11 @@ const char *crypt_backend_version(void)
uint32_t crypt_backend_flags(void)
{
- return 0;
+ uint32_t flags = 0;
+#if HAVE_DECL_GCRY_KDF_ARGON2 && !USE_INTERNAL_ARGON2
+ flags |= CRYPT_BACKEND_ARGON2;
+#endif
+ return flags;
}
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
@@ -266,7 +272,6 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
void crypt_hash_destroy(struct crypt_hash *ctx)
{
gcry_md_close(ctx->hd);
- memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -341,7 +346,6 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
void crypt_hmac_destroy(struct crypt_hmac *ctx)
{
gcry_md_close(ctx->hd);
- memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -386,6 +390,130 @@ static int pbkdf2(const char *hash,
#endif /* USE_INTERNAL_PBKDF2 */
}
+#if HAVE_DECL_GCRY_KDF_ARGON2 && !USE_INTERNAL_ARGON2
+struct gcrypt_thread_job
+{
+ pthread_t thread;
+ struct job_thread_param {
+ gcry_kdf_job_fn_t job;
+ void *p;
+ } work;
+};
+
+struct gcrypt_threads
+{
+ pthread_attr_t attr;
+ unsigned int num_threads;
+ unsigned int max_threads;
+ struct gcrypt_thread_job *jobs_ctx;
+};
+
+static void *gcrypt_job_thread(void *p)
+{
+ struct job_thread_param *param = p;
+ param->job(param->p);
+ pthread_exit(NULL);
+}
+
+static int gcrypt_wait_all_jobs(void *ctx)
+{
+ unsigned int i;
+ struct gcrypt_threads *threads = ctx;
+
+ for (i = 0; i < threads->num_threads; i++) {
+ pthread_join(threads->jobs_ctx[i].thread, NULL);
+ threads->jobs_ctx[i].thread = 0;
+ }
+
+ threads->num_threads = 0;
+ return 0;
+}
+
+static int gcrypt_dispatch_job(void *ctx, gcry_kdf_job_fn_t job, void *p)
+{
+ struct gcrypt_threads *threads = ctx;
+
+ if (threads->num_threads >= threads->max_threads)
+ return -1;
+
+ threads->jobs_ctx[threads->num_threads].work.job = job;
+ threads->jobs_ctx[threads->num_threads].work.p = p;
+
+ if (pthread_create(&threads->jobs_ctx[threads->num_threads].thread, &threads->attr,
+ gcrypt_job_thread, &threads->jobs_ctx[threads->num_threads].work))
+ return -1;
+
+ threads->num_threads++;
+ return 0;
+}
+
+static int gcrypt_argon2(const char *type,
+ const char *password, size_t password_length,
+ const char *salt, size_t salt_length,
+ char *key, size_t key_length,
+ uint32_t iterations, uint32_t memory, uint32_t parallel)
+{
+ gcry_kdf_hd_t hd;
+ int atype, r = -EINVAL;
+ unsigned long param[4];
+ struct gcrypt_threads threads = {
+ .max_threads = parallel,
+ .num_threads = 0
+ };
+ const gcry_kdf_thread_ops_t ops = {
+ .jobs_context = &threads,
+ .dispatch_job = gcrypt_dispatch_job,
+ .wait_all_jobs = gcrypt_wait_all_jobs
+ };
+
+ if (!strcmp(type, "argon2i"))
+ atype = GCRY_KDF_ARGON2I;
+ else if (!strcmp(type, "argon2id"))
+ atype = GCRY_KDF_ARGON2ID;
+ else
+ return -EINVAL;
+
+ param[0] = key_length;
+ param[1] = iterations;
+ param[2] = memory;
+ param[3] = parallel;
+
+ if (gcry_kdf_open(&hd, GCRY_KDF_ARGON2, atype, param, 4,
+ password, password_length, salt, salt_length,
+ NULL, 0, NULL, 0)) {
+ free(threads.jobs_ctx);
+ return -EINVAL;
+ }
+
+ if (parallel == 1) {
+ /* Do not use threads here */
+ if (gcry_kdf_compute(hd, NULL))
+ goto out;
+ } else {
+ threads.jobs_ctx = calloc(threads.max_threads,
+ sizeof(struct gcrypt_thread_job));
+ if (!threads.jobs_ctx)
+ goto out;
+
+ if (pthread_attr_init(&threads.attr))
+ goto out;
+
+ if (gcry_kdf_compute(hd, &ops))
+ goto out;
+ }
+
+ if (gcry_kdf_final(hd, key_length, key))
+ goto out;
+ r = 0;
+out:
+ gcry_kdf_close(hd);
+ pthread_attr_destroy(&threads.attr);
+ free(threads.jobs_ctx);
+
+ return r;
+}
+#endif
+
/* PBKDF */
int crypt_pbkdf(const char *kdf, const char *hash,
const char *password, size_t password_length,
@@ -400,8 +528,13 @@ int crypt_pbkdf(const char *kdf, const char *hash,
return pbkdf2(hash, password, password_length, salt, salt_length,
key, key_length, iterations);
else if (!strncmp(kdf, "argon2", 6))
+#if HAVE_DECL_GCRY_KDF_ARGON2 && !USE_INTERNAL_ARGON2
+ return gcrypt_argon2(kdf, password, password_length, salt, salt_length,
+ key, key_length, iterations, memory, parallel);
+#else
return argon2(kdf, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
+#endif
return -EINVAL;
}
@@ -565,6 +698,9 @@ bool crypt_fips_mode(void)
if (fips_checked)
return fips_mode;
+ if (crypt_backend_init(false /* ignored */))
+ return false;
+
fips_mode = gcry_fips_mode_active();
fips_checked = true;
diff --git a/lib/crypto_backend/crypto_kernel.c b/lib/crypto_backend/crypto_kernel.c
index 8493c0a..be6051a 100644
--- a/lib/crypto_backend/crypto_kernel.c
+++ b/lib/crypto_backend/crypto_kernel.c
@@ -1,8 +1,8 @@
/*
* Linux kernel userspace API crypto backend implementation
*
- * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2010-2023 Milan Broz
+ * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -245,7 +245,6 @@ void crypt_hash_destroy(struct crypt_hash *ctx)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
- memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -324,7 +323,6 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
close(ctx->tfmfd);
if (ctx->opfd >= 0)
close(ctx->opfd);
- memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
diff --git a/lib/crypto_backend/crypto_nettle.c b/lib/crypto_backend/crypto_nettle.c
index 086e4fc..f08db74 100644
--- a/lib/crypto_backend/crypto_nettle.c
+++ b/lib/crypto_backend/crypto_nettle.c
@@ -1,8 +1,8 @@
/*
* Nettle crypto backend implementation
*
- * Copyright (C) 2011-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2011-2023 Milan Broz
+ * Copyright (C) 2011-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2011-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/crypto_nss.c b/lib/crypto_backend/crypto_nss.c
index c154812..6b390a4 100644
--- a/lib/crypto_backend/crypto_nss.c
+++ b/lib/crypto_backend/crypto_nss.c
@@ -1,8 +1,8 @@
/*
* NSS crypto backend implementation
*
- * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2010-2023 Milan Broz
+ * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/crypto_openssl.c b/lib/crypto_backend/crypto_openssl.c
index 607ec38..4e85384 100644
--- a/lib/crypto_backend/crypto_openssl.c
+++ b/lib/crypto_backend/crypto_openssl.c
@@ -1,8 +1,8 @@
/*
* OPENSSL crypto backend implementation
*
- * Copyright (C) 2010-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2010-2023 Milan Broz
+ * Copyright (C) 2010-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2010-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,9 +44,20 @@ static OSSL_PROVIDER *ossl_legacy = NULL;
static OSSL_PROVIDER *ossl_default = NULL;
static OSSL_LIB_CTX *ossl_ctx = NULL;
static char backend_version[256] = "OpenSSL";
+
+#define MAX_THREADS 8
+#if !HAVE_DECL_OSSL_GET_MAX_THREADS
+static int OSSL_set_max_threads(OSSL_LIB_CTX *ctx __attribute__((unused)),
+ uint64_t max_threads __attribute__((unused))) { return 0; }
+static uint64_t OSSL_get_max_threads(OSSL_LIB_CTX *ctx __attribute__((unused))) { return 0; }
+#else
+#include <openssl/thread.h>
+#endif
+
#endif
#define CONST_CAST(x) (x)(uintptr_t)
+#define UNUSED(x) (void)(x)
static int crypto_backend_initialised = 0;
@@ -162,6 +173,7 @@ static int openssl_backend_init(bool fips)
*/
#if OPENSSL_VERSION_MAJOR >= 3
int r;
+ bool ossl_threads = false;
/*
* In FIPS mode we keep default OpenSSL context & global config
@@ -181,16 +193,24 @@ static int openssl_backend_init(bool fips)
ossl_legacy = OSSL_PROVIDER_try_load(ossl_ctx, "legacy", 0);
}
- r = snprintf(backend_version, sizeof(backend_version), "%s %s%s%s",
+ if (OSSL_set_max_threads(ossl_ctx, MAX_THREADS) == 1 &&
+ OSSL_get_max_threads(ossl_ctx) == MAX_THREADS)
+ ossl_threads = true;
+
+ r = snprintf(backend_version, sizeof(backend_version), "%s %s%s%s%s%s",
OpenSSL_version(OPENSSL_VERSION),
ossl_default ? "[default]" : "",
ossl_legacy ? "[legacy]" : "",
- fips ? "[fips]" : "");
+ fips ? "[fips]" : "",
+ ossl_threads ? "[threads]" : "",
+ crypt_backend_flags() & CRYPT_BACKEND_ARGON2 ? "[argon2]" : "");
if (r < 0 || (size_t)r >= sizeof(backend_version)) {
openssl_backend_exit();
return -EINVAL;
}
+#else
+ UNUSED(fips);
#endif
return 0;
}
@@ -232,11 +252,14 @@ void crypt_backend_destroy(void)
uint32_t crypt_backend_flags(void)
{
-#if OPENSSL_VERSION_MAJOR >= 3
- return 0;
-#else
- return CRYPT_BACKEND_PBKDF2_INT;
+ uint32_t flags = 0;
+#if OPENSSL_VERSION_MAJOR < 3
+ flags |= CRYPT_BACKEND_PBKDF2_INT;
+#endif
+#if HAVE_DECL_OSSL_KDF_PARAM_ARGON2_VERSION
+ flags |= CRYPT_BACKEND_ARGON2;
#endif
+ return flags;
}
const char *crypt_backend_version(void)
@@ -281,6 +304,8 @@ static void hash_id_free(const EVP_MD *hash_id)
{
#if OPENSSL_VERSION_MAJOR >= 3
EVP_MD_free(CONST_CAST(EVP_MD*)hash_id);
+#else
+ UNUSED(hash_id);
#endif
}
@@ -297,6 +322,8 @@ static void cipher_type_free(const EVP_CIPHER *cipher_type)
{
#if OPENSSL_VERSION_MAJOR >= 3
EVP_CIPHER_free(CONST_CAST(EVP_CIPHER*)cipher_type);
+#else
+ UNUSED(cipher_type);
#endif
}
@@ -391,7 +418,6 @@ void crypt_hash_destroy(struct crypt_hash *ctx)
{
hash_id_free(ctx->hash_id);
EVP_MD_CTX_free(ctx->md);
- memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -527,7 +553,6 @@ void crypt_hmac_destroy(struct crypt_hmac *ctx)
hash_id_free(ctx->hash_id);
HMAC_CTX_free(ctx->md);
#endif
- memset(ctx, 0, sizeof(*ctx));
free(ctx);
}
@@ -593,8 +618,53 @@ static int openssl_argon2(const char *type, const char *password, size_t passwor
const char *salt, size_t salt_length, char *key, size_t key_length,
uint32_t iterations, uint32_t memory, uint32_t parallel)
{
+#if HAVE_DECL_OSSL_KDF_PARAM_ARGON2_VERSION
+ EVP_KDF_CTX *ctx;
+ EVP_KDF *argon2;
+ unsigned int threads = parallel;
+ int r;
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD,
+ CONST_CAST(void*)password, password_length),
+ OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT,
+ CONST_CAST(void*)salt, salt_length),
+ OSSL_PARAM_uint32(OSSL_KDF_PARAM_ITER, &iterations),
+ OSSL_PARAM_uint(OSSL_KDF_PARAM_THREADS, &threads),
+ OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &parallel),
+ OSSL_PARAM_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memory),
+ OSSL_PARAM_END
+ };
+
+ if (OSSL_get_max_threads(ossl_ctx) == 0)
+ threads = 1;
+
+ argon2 = EVP_KDF_fetch(ossl_ctx, type, NULL);
+ if (!argon2)
+ return -EINVAL;
+
+ ctx = EVP_KDF_CTX_new(argon2);
+ if (!ctx) {
+ EVP_KDF_free(argon2);
+ return -EINVAL;;
+ }
+
+ if (EVP_KDF_CTX_set_params(ctx, params) != 1) {
+ EVP_KDF_CTX_free(ctx);
+ EVP_KDF_free(argon2);
+ return -EINVAL;
+ }
+
+ r = EVP_KDF_derive(ctx, (unsigned char*)key, key_length, NULL /*params*/);
+
+ EVP_KDF_CTX_free(ctx);
+ EVP_KDF_free(argon2);
+
+ /* _derive() returns 0 or negative value on error, 1 on success */
+ return r == 1 ? 0 : -EINVAL;
+#else
return argon2(type, password, password_length, salt, salt_length,
key, key_length, iterations, memory, parallel);
+#endif
}
/* PBKDF */
diff --git a/lib/crypto_backend/crypto_storage.c b/lib/crypto_backend/crypto_storage.c
index 13479dd..6c8f991 100644
--- a/lib/crypto_backend/crypto_storage.c
+++ b/lib/crypto_backend/crypto_storage.c
@@ -2,7 +2,7 @@
* Generic wrapper for storage encryption modes and Initial Vectors
* (reimplementation of some functions from Linux dm-crypt kernel)
*
- * Copyright (C) 2014-2023 Milan Broz
+ * Copyright (C) 2014-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/meson.build b/lib/crypto_backend/meson.build
new file mode 100644
index 0000000..d6c31fd
--- /dev/null
+++ b/lib/crypto_backend/meson.build
@@ -0,0 +1,40 @@
+if use_internal_argon2
+ subdir('argon2')
+endif
+
+libcrypto_backend_dependencies = [
+ crypto_backend_library,
+ clock_gettime,
+]
+libcrypto_backend_link_with = []
+
+libcrypto_backend_sources = files(
+ 'argon2_generic.c',
+ 'base64.c',
+ 'cipher_check.c',
+ 'cipher_generic.c',
+ 'crc32.c',
+ 'crypto_cipher_kernel.c',
+ 'crypto_storage.c',
+ 'pbkdf_check.c',
+ 'utf8.c',
+)
+
+crypto_backend = get_option('crypto-backend')
+libcrypto_backend_sources += files('crypto_@0@.c'.format(crypto_backend))
+
+if use_internal_pbkdf2
+ libcrypto_backend_sources += files('pbkdf2_generic.c')
+endif
+
+if use_internal_argon2 and get_option('argon-implementation') == 'internal'
+ libcrypto_backend_link_with += libargon2
+elif get_option('argon-implementation') == 'libargon2'
+ libcrypto_backend_dependencies += libargon2_external
+endif
+
+libcrypto_backend = static_library('crypto_backend',
+ libcrypto_backend_sources,
+ include_directories: includes_lib,
+ dependencies: libcrypto_backend_dependencies,
+ link_with: libcrypto_backend_link_with)
diff --git a/lib/crypto_backend/pbkdf2_generic.c b/lib/crypto_backend/pbkdf2_generic.c
index 9e87e19..f7fe5bc 100644
--- a/lib/crypto_backend/pbkdf2_generic.c
+++ b/lib/crypto_backend/pbkdf2_generic.c
@@ -4,8 +4,8 @@
* Copyright (C) 2004 Free Software Foundation
*
* cryptsetup related changes
- * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2012-2023 Milan Broz
+ * Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2024 Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/crypto_backend/pbkdf_check.c b/lib/crypto_backend/pbkdf_check.c
index 53a2da9..54d6a34 100644
--- a/lib/crypto_backend/pbkdf_check.c
+++ b/lib/crypto_backend/pbkdf_check.c
@@ -1,7 +1,7 @@
/*
* PBKDF performance check
- * Copyright (C) 2012-2023 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2012-2023 Milan Broz
+ * Copyright (C) 2012-2024 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2012-2024 Milan Broz
* Copyright (C) 2016-2020 Ondrej Mosnacek
*
* This file is free software; you can redistribute it and/or
diff --git a/lib/crypto_backend/utf8.c b/lib/crypto_backend/utf8.c
index 24e0d8d..c13e953 100644
--- a/lib/crypto_backend/utf8.c
+++ b/lib/crypto_backend/utf8.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Lennart Poettering
*
* cryptsetup related changes
- * Copyright (C) 2021-2023 Vojtech Trefny
+ * Copyright (C) 2021-2024 Vojtech Trefny
* Parts of the original systemd implementation are based on the GLIB utf8
* validation functions.