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. Aki On 02.11.2016 14:24, Michael A. Peters wrote:> Indeed, which is why I use it. > > But it also is in the minority which is why I find it acceptable for > FLOSS projects like dovecot to elect to only un-officially support > LibreSSL via a community maintained patch. > > One of the reasons why OpenSSL was forked is because they were trying > to support so many platforms that it made the code a real mess. Don't > want the same to happen to another project because of it. > > Especially with places like github that make it easy for members of > the community to create and maintain such a patch, it may be the best > option if the project itself doesn't have someone who can officially > maintain LibreSSL support. > > On 11/02/2016 05:08 AM, Ruga wrote: >> libressl is a leaner and safer openssl >> >> Sent from ProtonMail Mobile >> >> >> On Wed, Nov 2, 2016 at 12:39 PM, Michael A. Peters >> <'mpeters at domblogger.net'> wrote: >> IMHO it would be acceptable to have a LibreSSL patch that is maintained >> by the people who want it. >> >> It's free software, and that kind of is the point of Open Source. >> >> On 11/02/2016 04:36 AM, Michael A. Peters wrote: >>> They have stated they are going to remain API compatible with 1.0.1h >>> (or >>> g, forget which they forked) - their new stuff is outside of libcrypto. >>> >>> On 11/02/2016 04:25 AM, Aki Tuomi wrote: >>>> It does work today, I am just bit worried that it will keep on >>>> breaking >>>> with libressl as they evolve their API. I would personally like to >>>> avoid >>>> more ifdef hell if possible... >>>> >>>> Aki >>>> >>>> >>>> On 02.11.2016 13:22, Michael A. Peters wrote: >>>>> Standard way to fix it (on the LibreSSL page) is to check for >>>>> LIBRESSL_VERSION_NUMBER - e.g. the patch attached which I think >>>>> catches them all where needed. Note the word think. >>>>> >>>>> It certainly appears to be working anyway with it. >>>>> >>>>> On 11/02/2016 04:07 AM, Aki Tuomi wrote: >>>>>> After doing some testing by myself, I noticed that libressl, for >>>>>> some >>>>>> unknown reason, defines >>>>>> >>>>>> #define OPENSSL_VERSION_NUMBER 0x20000000L >>>>>> >>>>>> No idea why they decided to advertise that they are OpenSSL >>>>>> v2.0.0. A >>>>>> local fix, if you need one, is to use >>>>>> >>>>>> #if OPENSSL_VERSION_NUMBER == 0x20000000L >>>>>> #define OPENSSL_VERSION_NUMBER 0x1000100L >>>>>> #endif >>>>>> >>>>>> in dcrypt-openssl.c after includes. >>>>>> >>>>>> Aki >>>>>> >>>>>> >>>>>> On 02.11.2016 12:39, Aki Tuomi wrote: >>>>>>> Hi! >>>>>>> >>>>>>> Those are used if >>>>>>> >>>>>>> #if OPENSSL_VERSION_NUMBER >= 0x10100000L >>>>>>> >>>>>>> So (your) libressl is providing this define. We compile our code >>>>>>> using >>>>>>> GCC and CLANG regularly, with OpenSSL v1.0.x which is the currently >>>>>>> officially supported one. >>>>>>> >>>>>>> Aki >>>>>>> >>>>>>> >>>>>>> On 02.11.2016 12:34, Ruga wrote: >>>>>>>> dovecot 2.2.26.0 uses the following functions, which are not >>>>>>>> available on libressl 2.4.3: >>>>>>>> >>>>>>>> HMAC_CTX_new >>>>>>>> HMAC_CTX_free >>>>>>>> EVP_PKEY_get0_EC_KEY >>>>>>>> EVP_PKEY_get0_RSA >>>>>>>> OBJ_length >>>>>>>> EVP_MD_CTX_new >>>>>>>> EVP_MD_CTX_free >>>>>>>> >>>>>>>> The result of calling a non-existent function is a runtime error, >>>>>>>> and we do not want that on production servers. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> There are additional problems. I recommend compiling with >>>>>>>> clang-llvm >>>>>>>> 3.9.0 >>>>>>>> to see them all. >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -------- Original Message -------- >>>>>>>> Subject: Re: v2.2.26.0 released >>>>>>>> Local Time: 1 November 2016 7:30 PM >>>>>>>> UTC Time: 1 November 2016 18:30 >>>>>>>> From: aki.tuomi at dovecot.fi >>>>>>>> To: Dovecot Mailing List <dovecot at dovecot.org>, Ruga >>>>>>>> <ruga at protonmail.com> >>>>>>>> >>>>>>>> OpenSSL v1.0.1 is enough. >>>>>>>> >>>>>>>> Aki >>>>>>>> >>>>>>>>> On November 1, 2016 at 7:46 PM Ruga <ruga at protonmail.com> wrote: >>>>>>>>> >>>>>>>>> >>>>>>>>> Hello, >>>>>>>>> >>>>>>>>> We cannot upgrade from 2.2.24, because we use libressl and the >>>>>>>>> newer >>>>>>>>> dovecot versions demand openssl v1.1. >>>>>>>>> >>>>>>>>> Please add the new library requirement to the INSTALL file. >>>>>>>>> >>>>>>>>> All the best. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -------- Original Message -------- >>>>>>>>> Subject: v2.2.26.0 released >>>>>>>>> Local Time: 28 October 2016 6:51 PM >>>>>>>>> UTC Time: 28 October 2016 16:51 >>>>>>>>> From: tss at iki.fi >>>>>>>>> To: dovecot-news at dovecot.org, Dovecot Mailing List >>>>>>>>> <dovecot at dovecot.org> >>>>>>>>> >>>>>>>>> http://dovecot.org/releases/2.2/dovecot-2.2.26.0.tar.gz >>>>>>>>> http://dovecot.org/releases/2.2/dovecot-2.2.26.0.tar.gz.sig >>>>>>>>> >>>>>>>>> v2.2.26 had a couple of nasty bugs left in it, so here's a fixup >>>>>>>>> release. The version number is also a little bit weird, but >>>>>>>>> had to >>>>>>>>> be done this way (although 2.2.26.0.1 could have been another >>>>>>>>> possibility). >>>>>>>>> >>>>>>>>> - Fixed some compiling issues. >>>>>>>>> - auth: Fixed assert-crash when using NTLM or SKEY mechanisms and >>>>>>>>> multiple passdbs. >>>>>>>>> - auth: Fixed crash when exporting to auth-worker passdb extra >>>>>>>>> fields >>>>>>>>> that had empty values. >>>>>>>>> - dsync: Fixed assert-crash in dsync_brain_sync_mailbox_deinit >>>> >
On 2016-11-02, Aki Tuomi <aki.tuomi at 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();
On 02.11.2016 19:54, Stuart Henderson wrote:> On 2016-11-02, Aki Tuomi <aki.tuomi at 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. > > >Thank you for the patch. My personal opinion is that it is also bit nasty to pretend to support some API/ABI but provide false version numbers. https://wiki.openssl.org/index.php/1.1_API_Changes, this is what OpenSSL recommends to use for handling backwards compability with older versions. As you can see, it uses < test. Now you are claiming to be v2.0.0, which means that there is no reasonable way to use OPENSSL_VERSION to determine whether some particular feature is there or not. Yes, we could test each function separately, but that would kinda beat the point of having a VERSION header in the first place, and also adds up for the ifdef hell by forcing us to check for each and every openssl function that has changed since 1.0.0 and use that particular ifdef. It would've been, again in my opinion, to keep the VERSION in libressl to match with the API you are providing instead of choosing some abstract value that can will mess up with everyone's code. If you add features to your API from OpenSSL, you can update the version number to match with the API you provide. Just my 0.02?. Aki