diff options
Diffstat (limited to 'lib/crypto_backend/crypto_openssl.c')
-rw-r--r-- | lib/crypto_backend/crypto_openssl.c | 90 |
1 files changed, 80 insertions, 10 deletions
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, ¶llel), + 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 */ |