]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9920 crypto: use libsodium instead of OpenSSL
authorHoward Chu <hyc@openldap.org>
Mon, 14 Oct 2024 17:54:37 +0000 (18:54 +0100)
committerHoward Chu <hyc@openldap.org>
Mon, 14 Oct 2024 18:39:32 +0000 (19:39 +0100)
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.

libraries/liblmdb/Makefile
libraries/liblmdb/crypto.c

index 7411b309f819d37b90cf98ca657eea56e6006128..01d653660480f431ff94fdb0d3f342a160192e68 100644 (file)
@@ -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
index a1e635d61dfe7f4f95470465397fcb416acae7c1..14fc737c83b87cb70793d4fd38f038f9b41679a2 100644 (file)
@@ -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
  */
 #include <string.h>
 
-#include <openssl/engine.h>
+#include <sodium.h>
 
 #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;
 }