From: Howard Chu Date: Mon, 14 Oct 2024 17:54:37 +0000 (+0100) Subject: ITS#9920 crypto: use libsodium instead of OpenSSL X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e895f5fd36b9bbfbb865baafb4a859cb942bed4b;p=thirdparty%2Fopenldap.git ITS#9920 crypto: use libsodium instead of OpenSSL Note: even though the same algorithms were used, the data produced by this module doesn't work with the OpenSSL-based module and vice versa. --- diff --git a/libraries/liblmdb/Makefile b/libraries/liblmdb/Makefile index 7411b309f8..01d6536604 100644 --- a/libraries/liblmdb/Makefile +++ b/libraries/liblmdb/Makefile @@ -98,7 +98,7 @@ mtest_enc2: mtest_enc2.o module.o liblmdb.a crypto.lm mplay: mplay.o liblmdb.a crypto.lm: crypto.c - $(CC) -shared $(CFLAGS) -o $@ $^ -lcrypto + $(CC) -shared $(CFLAGS) -o $@ $^ -lsodium mdb.o: mdb.c lmdb.h midl.h $(CC) $(CFLAGS) $(CPPFLAGS) -c mdb.c diff --git a/libraries/liblmdb/crypto.c b/libraries/liblmdb/crypto.c index a1e635d61d..14fc737c83 100644 --- a/libraries/liblmdb/crypto.c +++ b/libraries/liblmdb/crypto.c @@ -1,6 +1,6 @@ /* crypto.c - LMDB encryption helper module */ /* - * Copyright 2020-2021 Howard Chu, Symas Corp. + * Copyright 2020-2024 Howard Chu, Symas Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,173 +12,66 @@ */ #include -#include +#include #include "lmdb.h" -MDB_crypto_hooks MDB_crypto; +#define KEYBYTES crypto_aead_chacha20poly1305_ietf_KEYBYTES +#define NONCEBYTES crypto_aead_chacha20poly1305_ietf_NPUBBYTES +#define MACBYTES crypto_aead_chacha20poly1305_ietf_ABYTES -static EVP_CIPHER *cipher; +MDB_crypto_hooks MDB_crypto; static int mcf_str2key(const char *passwd, MDB_val *key) { - unsigned int size; - EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); - EVP_DigestUpdate(mdctx, "Just a Constant", sizeof("Just a Constant")); - EVP_DigestUpdate(mdctx, passwd, strlen(passwd)); - EVP_DigestFinal_ex(mdctx, key->mv_data, &size); - EVP_MD_CTX_free(mdctx); + crypto_hash_sha256_state state; + + crypto_hash_sha256_init(&state); + crypto_hash_sha256_update(&state, (const unsigned char *)"Just a Constant", sizeof("Just a Constant")); + crypto_hash_sha256_update(&state, (const unsigned char *)passwd, strlen(passwd)); + crypto_hash_sha256_final(&state, key->mv_data); return 0; } -/* cheats - internal OpenSSL 1.1 structures - * These are copied from the OpenSSL source code. - * - * We use these to allow stack allocation of these structures - * and to prevent OpenSSL from malloc'ing and free'ing them, - * which would be too slow. - */ -typedef struct my_cipher_ctx_st { - const EVP_CIPHER *cipher; - ENGINE *engine; /* functional reference if 'cipher' is - * ENGINE-provided */ - int encrypt; /* encrypt or decrypt */ - int buf_len; /* number we have left */ - unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ - unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ - unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */ - int num; /* used by cfb/ofb/ctr mode */ - /* FIXME: Should this even exist? It appears unused */ - void *app_data; /* application stuff */ - int key_len; /* May change for variable length cipher */ -#if OPENSSL_VERSION_NUMBER >= 0x30006000 - int iv_len; /* IV length */ -#endif - unsigned long flags; /* Various flags */ - void *cipher_data; /* per EVP data */ - int final_used; - int block_mask; - unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ - -#if OPENSSL_VERSION_NUMBER >= 0x30000000 - /* - * Opaque ctx returned from a providers cipher algorithm implementation - * OSSL_FUNC_cipher_newctx() - */ - void *algctx; - EVP_CIPHER *fetched_cipher; -#endif -} MY_CIPHER_CTX; - -typedef struct evp_cipher_head { - int nid; - int block_size; - int key_len; - int iv_len; - unsigned long flags; -#if OPENSSL_VERSION_NUMBER >= 0x30000000 - int origin; -#endif - int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); -} evp_cipher_head; - -#define CHACHA_KEY_SIZE 32 -#define CHACHA_CTR_SIZE 16 -#define CHACHA_BLK_SIZE 64 -#define POLY1305_BLOCK_SIZE 16 +#define ENC(dst, src, mac, key, iv) \ + crypto_aead_chacha20poly1305_ietf_encrypt_detached(dst->mv_data, mac, &mlen, \ + src->mv_data, src->mv_size, NULL, 0, NULL, iv, key) -typedef struct { - union { - double align; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */ - unsigned int d[CHACHA_KEY_SIZE / 4]; - } key; - unsigned int counter[CHACHA_CTR_SIZE / 4]; - unsigned char buf[CHACHA_BLK_SIZE]; - unsigned int partial_len; -} MY_CHACHA_KEY; - -typedef struct { - MY_CHACHA_KEY key; - unsigned int nonce[12/4]; - unsigned char tag[POLY1305_BLOCK_SIZE]; - unsigned char tls_aad[POLY1305_BLOCK_SIZE]; - struct { uint64_t aad, text; } len; - int aad, mac_inited, tag_len, nonce_len; - size_t tls_payload_length; -} MY_CHACHA_AEAD_CTX; - -typedef struct { - double opaque[24]; - unsigned int nonce[4]; - unsigned char data[POLY1305_BLOCK_SIZE]; - size_t num; - struct { - void (*foo1)(); - void (*foo2)(); - } func; -} my_poly1305_ctx; - -typedef struct my_cipherdata { - MY_CHACHA_AEAD_CTX aead_ctx; - my_poly1305_ctx poly_ctx; -} my_cipherdata; +#define DEC(dst, src, mac, key, iv) \ + crypto_aead_chacha20poly1305_ietf_decrypt_detached(dst->mv_data, NULL, src->mv_data, \ + src->mv_size, mac, NULL, 0, iv, key) static int mcf_encfunc(const MDB_val *src, MDB_val *dst, const MDB_val *key, int encdec) { - unsigned char iv[12]; - int ivl, outl, rc; + unsigned char iv[NONCEBYTES]; mdb_size_t *ptr; - MY_CIPHER_CTX myctx = {0}; - EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)&myctx; - my_cipherdata cactx = {0}; - evp_cipher_head *eh = (evp_cipher_head *)cipher; + int ivl, rc; + unsigned long long mlen; + /* the nonce is only 12 bytes */ ptr = key[1].mv_data; ivl = ptr[0] & 0xffffffff; memcpy(iv, &ivl, 4); memcpy(iv+4, ptr+1, sizeof(mdb_size_t)); - EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encdec); - - /* we can't set cipher_data before calling CipherInit because - * that will just try to free it. So set it now, and then finish - * up the other two Init calls that we disabled before. - */ - myctx.cipher_data = &cactx; - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL); - eh->init(ctx, key[0].mv_data, iv, encdec); - EVP_CIPHER_CTX_set_padding(ctx, 0); - if (!encdec) { - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, key[2].mv_size, key[2].mv_data); + if (encdec) { + rc = ENC(dst, src, key[2].mv_data, key[0].mv_data, iv); + } else { + rc = DEC(dst, src, key[2].mv_data, key[0].mv_data, iv); } - rc = EVP_CipherUpdate(ctx, dst->mv_data, &outl, src->mv_data, src->mv_size); - if (rc) - rc = EVP_CipherFinal_ex(ctx, key[2].mv_data, &outl); - if (rc && encdec) { - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, key[2].mv_size, key[2].mv_data); - } - return rc == 0; + return rc; } static const MDB_crypto_funcs mcf_table = { mcf_str2key, mcf_encfunc, NULL, - CHACHA_KEY_SIZE, - POLY1305_BLOCK_SIZE, + KEYBYTES, + MACBYTES, 0 }; MDB_crypto_funcs *MDB_crypto() { - evp_cipher_head *eh; - cipher = (EVP_CIPHER *)EVP_chacha20_poly1305(); - - /* We must disable the implicit init calls */ - eh = (evp_cipher_head *)cipher; - eh->flags &= ~(EVP_CIPH_CTRL_INIT|EVP_CIPH_ALWAYS_CALL_INIT); - return (MDB_crypto_funcs *)&mcf_table; }