On 2016-11-02, Aki Tuomi <aki.tuomi@dovecot.fi> wrote:
If the standard way works, I am happy to include the original patch I sent, amended so that it checks for presence of LIBRESSL_VERSION_NUMBER. If they keep this promise, then we should have no worries about things breaking up.
Diff below is what I've added to OpenBSD ports. The libressl API is not cast in stone, there's a possibility some functions from newer OpenSSL might be added - in fact we already have some like TLS_method. 0x20000000L was specifically chosen to not match up with anything OpenSSL had used because they aren't directly comparable. In general I think the best approach would be for feature checks, e.g. in autoconf. (I wish there was some common m4 file shared between projects that people could use for this..) In the absence of this, it seems a better idea to check at the places where #ifdefs are done rather than override OPENSSL_VERSION_NUMBER locally. I don't think carrying patches like this separately is all that good an idea - people may well compile things on their own and not know about the problem. If the build fails that's not so bad, but the silent miscompile we see here is pretty nasty. --- src/lib-dcrypt/dcrypt-openssl.c.orig Wed Nov 2 12:11:31 2016 +++ src/lib-dcrypt/dcrypt-openssl.c Wed Nov 2 12:22:26 2016 @@ -67,7 +67,7 @@ 2<tab>key algo oid<tab>1<tab>symmetric algo name<tab>salt<tab>hash algo<tab>rounds<tab>E(RSA = i2d_PrivateKey, EC=Private Point)<tab>key id **/ -#if OPENSSL_VERSION_NUMBER < 0x10100000L +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) #define EVP_PKEY_get0_EC_KEY(x) x->pkey.ec #define EVP_PKEY_get0_RSA(x) x->pkey.rsa #define OBJ_length(o) ((o)->length) @@ -90,7 +90,7 @@ struct dcrypt_context_symmetric { struct dcrypt_context_hmac { pool_t pool; const EVP_MD *md; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) HMAC_CTX *ctx; #else HMAC_CTX ctx; @@ -427,7 +427,7 @@ static void dcrypt_openssl_ctx_hmac_destroy(struct dcrypt_context_hmac **ctx) { pool_t pool = (*ctx)->pool; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) if ((*ctx)->ctx) HMAC_CTX_free((*ctx)->ctx); #else HMAC_cleanup(&((*ctx)->ctx)); @@ -470,7 +470,7 @@ bool dcrypt_openssl_ctx_hmac_init(struct dcrypt_contex { int ec; i_assert(ctx->md != NULL); -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ctx->ctx = HMAC_CTX_new(); if (ctx->ctx == NULL) return dcrypt_openssl_error(error_r); ec = HMAC_Init_ex(ctx->ctx, ctx->key, ctx->klen, ctx->md, NULL); @@ -484,7 +484,7 @@ static bool dcrypt_openssl_ctx_hmac_update(struct dcrypt_context_hmac *ctx, const unsigned char *data, size_t data_len, const char **error_r) { int ec; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ec = HMAC_Update(ctx->ctx, data, data_len); #else ec = HMAC_Update(&(ctx->ctx), data, data_len); @@ -498,7 +498,7 @@ bool dcrypt_openssl_ctx_hmac_final(struct dcrypt_conte int ec; unsigned char buf[HMAC_MAX_MD_CBLOCK]; unsigned int outl; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ec = HMAC_Final(ctx->ctx, buf, &outl); HMAC_CTX_free(ctx->ctx); ctx->ctx = NULL; @@ -2133,7 +2133,7 @@ bool dcrypt_openssl_public_key_id_evp(EVP_PKEY *key, c long len = BIO_get_mem_data(b, &ptr); unsigned int hlen = sizeof(buf); /* then hash it */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) EVP_MD_CTX *ctx = EVP_MD_CTX_new(); #else EVP_MD_CTX *ctx = EVP_MD_CTX_create(); @@ -2147,7 +2147,7 @@ bool dcrypt_openssl_public_key_id_evp(EVP_PKEY *key, c buffer_append(result, buf, hlen); res = TRUE; } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) EVP_MD_CTX_free(ctx); #else EVP_MD_CTX_destroy(ctx); --- src/lib-ssl-iostream/dovecot-openssl-common.c.orig Wed Nov 2 12:11:31 2016 +++ src/lib-ssl-iostream/dovecot-openssl-common.c Wed Nov 2 12:21:04 2016 @@ -10,7 +10,7 @@ static int openssl_init_refcount = 0; static ENGINE *dovecot_openssl_engine; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) static void *dovecot_openssl_malloc(size_t size, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED) #else static void *dovecot_openssl_malloc(size_t size) @@ -26,7 +26,7 @@ static void *dovecot_openssl_malloc(size_t size) return mem; } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) static void *dovecot_openssl_realloc(void *ptr, size_t size, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED) #else static void *dovecot_openssl_realloc(void *ptr, size_t size) @@ -40,7 +40,7 @@ static void *dovecot_openssl_realloc(void *ptr, size_t return mem; } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) static void dovecot_openssl_free(void *ptr, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED) #else static void dovecot_openssl_free(void *ptr) @@ -97,7 +97,7 @@ bool dovecot_openssl_common_global_unref(void) CRYPTO_cleanup_all_ex_data(); #if OPENSSL_VERSION_NUMBER < 0x10000000L ERR_remove_state(0); -#elif OPENSSL_VERSION_NUMBER < 0x10100000L +#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) ERR_remove_thread_state(NULL); #endif ERR_free_strings();