Skip to content
Snippets Groups Projects
Commit e3bf73c8 authored by Vladimir Davydov's avatar Vladimir Davydov Committed by Vladimir Davydov
Browse files

crypto: OpenSSL 3.0 support

Two things we need to do to fix build with OpenSSL 3.0:

1. Use EVP_MAC_* functions instead of HMAC_*
   https://www.openssl.org/docs/man3.0/man3/HMAC_CTX_new.html

2. Load the Legacy provider to enable legacy algorithms, such as MD4
   https://wiki.openssl.org/index.php/OpenSSL_3.0#Programming_in_OpenSSL_3.0

Closes #6477

NO_DOC=build fix
NO_TEST=build fix
NO_CHANGELOG=build fix
parent f9739160
No related branches found
No related tags found
No related merge requests found
......@@ -11,6 +11,14 @@
#include <openssl/ssl.h>
#include <stddef.h>
#include "say.h"
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
static OSSL_PROVIDER *legacy_provider = NULL;
static OSSL_PROVIDER *default_provider = NULL;
#endif
void
ssl_init_impl(void)
{
......@@ -22,11 +30,26 @@ ssl_init_impl(void)
OPENSSL_init_crypto(0, NULL);
OPENSSL_init_ssl(0, NULL);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/* Needed to enable legacy algorithms, such as MD4. */
legacy_provider = OSSL_PROVIDER_load(NULL, "legacy");
if (legacy_provider == NULL)
say_error("cannot load the Legacy OpenSSL provider");
default_provider = OSSL_PROVIDER_load(NULL, "default");
if (default_provider == NULL)
say_error("cannot load the Default OpenSSL provider");
#endif
}
void
ssl_free_impl(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (legacy_provider != NULL)
OSSL_PROVIDER_unload(legacy_provider);
if (default_provider != NULL)
OSSL_PROVIDER_unload(default_provider);
#endif
#ifdef OPENSSL_cleanup
OPENSSL_cleanup();
#endif
......
......@@ -343,7 +343,13 @@ crypto_EVP_MD_CTX_free(EVP_MD_CTX *ctx)
#endif
}
HMAC_CTX *
#if OPENSSL_VERSION_NUMBER < 0x30000000L
# define crypto_HMAC_CTX HMAC_CTX
#else
# define crypto_HMAC_CTX EVP_MAC_CTX
#endif
crypto_HMAC_CTX *
crypto_HMAC_CTX_new(void)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
......@@ -353,20 +359,29 @@ crypto_HMAC_CTX_new(void)
}
HMAC_CTX_init(ctx);
return ctx;
#else
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
return HMAC_CTX_new();
#else
static EVP_MAC *mac;
if (mac == NULL)
mac = EVP_MAC_fetch(NULL, "hmac", NULL);
if (mac == NULL)
return NULL;
return EVP_MAC_CTX_new(mac);
#endif
}
void
crypto_HMAC_CTX_free(HMAC_CTX *ctx)
crypto_HMAC_CTX_free(crypto_HMAC_CTX *ctx)
{
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
HMAC_cleanup(ctx); /* Remove key from memory */
OPENSSL_free(ctx);
#else
#elif OPENSSL_VERSION_NUMBER < 0x30000000L
HMAC_CTX_free(ctx);
#else
EVP_MAC_CTX_free(ctx);
#endif
}
......@@ -406,22 +421,46 @@ crypto_EVP_get_digestbyname(const char *name)
}
int
crypto_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md,
ENGINE *impl)
crypto_HMAC_Init_ex(crypto_HMAC_CTX *ctx, const void *key, int len,
const char *digest, const EVP_MD *md, ENGINE *impl)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
(void)digest;
return HMAC_Init_ex(ctx, key, len, md, impl);
#else
(void)md;
(void)impl;
OSSL_PARAM params[2];
params[0] = OSSL_PARAM_construct_utf8_string("digest",
(char *)digest, 0);
params[1] = OSSL_PARAM_construct_end();
return EVP_MAC_init(ctx, key, len, params);
#endif
}
int
crypto_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
crypto_HMAC_Update(crypto_HMAC_CTX *ctx, const unsigned char *data, size_t len)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
return HMAC_Update(ctx, data, len);
#else
return EVP_MAC_update(ctx, data, len);
#endif
}
int
crypto_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
crypto_HMAC_Final(crypto_HMAC_CTX *ctx, unsigned char *md, unsigned int *len,
unsigned int size)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
(void)size;
return HMAC_Final(ctx, md, len);
#else
size_t l;
int rc = EVP_MAC_final(ctx, md, &l, size);
*len = l;
return rc;
#endif
}
const char *
......
......@@ -28,10 +28,11 @@ ffi.cdef[[
HMAC_CTX *crypto_HMAC_CTX_new(void);
void crypto_HMAC_CTX_free(HMAC_CTX *ctx);
int crypto_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
const EVP_MD *md, ENGINE *impl);
const char *digest, const EVP_MD *md, ENGINE *impl);
int crypto_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data,
size_t len);
int crypto_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
int crypto_HMAC_Final(HMAC_CTX *ctx, unsigned char *md,
unsigned int *len, unsigned int size);
enum crypto_algo {
CRYPTO_ALGO_NONE,
......@@ -167,7 +168,7 @@ local function hmac_gc(ctx)
ffi.C.crypto_HMAC_CTX_free(ctx)
end
local function hmac_new(digest, key)
local function hmac_new(class, digest, key)
if key == nil then
return error('Key should be specified for HMAC operations')
end
......@@ -178,6 +179,7 @@ local function hmac_new(digest, key)
ffi.gc(ctx, hmac_gc)
local self = setmetatable({
ctx = ctx,
class = class,
digest = digest,
initialized = false,
}, hmac_mt)
......@@ -189,7 +191,8 @@ local function hmac_init(self, key)
if self.ctx == nil then
return error('HMAC context isn\'t usable')
end
if ffi.C.crypto_HMAC_Init_ex(self.ctx, key, key:len(), self.digest, nil) ~= 1 then
if ffi.C.crypto_HMAC_Init_ex(self.ctx, key, key:len(), self.class,
self.digest, nil) ~= 1 then
return error('Can\'t init HMAC: ' .. openssl_err_str())
end
self.initialized = true
......@@ -210,9 +213,10 @@ local function hmac_final(self)
end
self.initialized = false
local ibuf = cord_ibuf_take()
local buf = ibuf:alloc(64)
local buf_size = 64
local buf = ibuf:alloc(buf_size)
local ai = ffi.new('int[1]')
if ffi.C.crypto_HMAC_Final(self.ctx, buf, ai) ~= 1 then
if ffi.C.crypto_HMAC_Final(self.ctx, buf, ai, buf_size) ~= 1 then
cord_ibuf_put(ibuf)
return error('Can\'t finalize HMAC: ' .. openssl_err_str())
end
......@@ -349,13 +353,13 @@ digest_api = setmetatable(digest_api,
local hmac_api = {}
for class, digest in pairs(hmacs) do
hmac_api[class] = setmetatable({
new = function (key) return hmac_new(digest, key) end
new = function (key) return hmac_new(class, digest, key) end
}, {
__call = function (self, key, str)
if type(str) ~= 'string' then
error("Usage: hmac."..class.."(key, string)")
end
local ctx = hmac_new(digest, key)
local ctx = hmac_new(class, digest, key)
ctx:update(str)
local res = ctx:result()
ctx:free()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment