Hi,

as I wrote earlier, Sebastian Andrzej Siewior, one of the OpenSSL
maintainers of Debian, kindly submitted patches to support building with
OpenSSL 1.1.

I have now tested them in an installation with about 50 clients using
transport encryption without apparent problems.

The debian packages in the experimental branch already contain these
patches and they install cleanly on a Debian 9 system if someone is
interested in testing the result.

Please find the patches attached for review.

I'll reopen bug #2247 to keep track.

Regards,

Carsten

>From 2da5f9b134943f62fb7c22e6d5e64599b43011cc Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
Date: Wed, 8 Nov 2017 14:37:31 +0100
Subject: [PATCH 1/5] crypto: remove support for ancient openssl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

OpenSSL 1.0.2 is still supported. Everything earlier is not so the old
code for compat can be thrown away, especially the 0.9.8 support.

TLSv1_method() should not be used and SSLv23_method() should be
preferred because the latter supports TLS1.0…1.2 while the former _only_
tries TLS1.0.

Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
---
 src/lib/crypto.c | 22 ----------------------
 src/lib/tls.c    | 14 +-------------
 2 files changed, 1 insertion(+), 35 deletions(-)

diff --git a/src/lib/crypto.c b/src/lib/crypto.c
index 9f309d58e473..b4403eb45618 100644
--- a/src/lib/crypto.c
+++ b/src/lib/crypto.c
@@ -307,12 +307,7 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
    const X509V3_EXT_METHOD *method;
    ASN1_OCTET_STRING *keyid;
    int i;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
    const unsigned char *ext_value_data;
-#else
-   unsigned char *ext_value_data;
-#endif
-
 
    /* Find the index to the subjectKeyIdentifier extension */
    i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
@@ -331,7 +326,6 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
 
    ext_value_data = ext->value->data;
 
-#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
    if (method->it) {
       /* New style ASN1 */
 
@@ -345,10 +339,6 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
       keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ext->value->length);
    }
 
-#else
-   keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ext->value->length);
-#endif
-
    return keyid;
 }
 
@@ -783,11 +773,7 @@ crypto_error_t crypto_sign_verify(SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST
    SignerInfo *si;
    int ok, i;
    unsigned int sigLen;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
    const unsigned char *sigData;
-#else
-   unsigned char *sigData;
-#endif
 
    signers = sig->sigData->signerInfo;
 
@@ -934,11 +920,7 @@ int crypto_sign_encode(SIGNATURE *sig, uint8_t *dest, uint32_t *length)
 SIGNATURE *crypto_sign_decode(JCR *jcr, const uint8_t *sigData, uint32_t length)
 {
    SIGNATURE *sig;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
    const unsigned char *p = (const unsigned char *) sigData;
-#else
-   unsigned char *p = (unsigned char *)sigData;
-#endif
 
    sig = (SIGNATURE *)malloc(sizeof(SIGNATURE));
    if (!sig) {
@@ -1156,11 +1138,7 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist
    X509_KEYPAIR *keypair;
    STACK_OF(RecipientInfo) *recipients;
    crypto_error_t retval = CRYPTO_ERROR_NONE;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
    const unsigned char *p = (const unsigned char *)data;
-#else
-   unsigned char *p = (unsigned char *)data;
-#endif
 
    /* bacula-fd.conf doesn't contains any key */
    if (!keypairs) {
diff --git a/src/lib/tls.c b/src/lib/tls.c
index f444a276a5e2..992265b38ad2 100644
--- a/src/lib/tls.c
+++ b/src/lib/tls.c
@@ -118,13 +118,10 @@ TLS_CONTEXT *new_tls_context(const char *ca_certfile, const char *ca_certdir,
    /* Allows SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols */
    ctx->openssl = SSL_CTX_new(TLS_method());
 
-#elif (OPENSSL_VERSION_NUMBER >= 0x10000000L)
+#else
    /* Allows most all protocols */
    ctx->openssl = SSL_CTX_new(SSLv23_method());
 
-#else
-   /* Older method only understands TLSv1 */
-   ctx->openssl = SSL_CTX_new(TLSv1_method());
 #endif
 
    /* Use SSL_OP_ALL to turn on all "rather harmless" workarounds that
@@ -337,11 +334,7 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
             STACK_OF(CONF_VALUE) *val;
             CONF_VALUE *nval;
             void *extstr = NULL;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800FL)
             const unsigned char *ext_value_data;
-#else
-            unsigned char *ext_value_data;
-#endif
 
             /* Get x509 extension method structure */
             if (!(method = X509V3_EXT_get(ext))) {
@@ -350,7 +343,6 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
 
             ext_value_data = ext->value->data;
 
-#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
             if (method->it) {
                /* New style ASN1 */
 
@@ -364,10 +356,6 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
                extstr = method->d2i(NULL, &ext_value_data, ext->value->length);
             }
 
-#else
-            extstr = method->d2i(NULL, &ext_value_data, ext->value->length);
-#endif
-
             /* Iterate through to find the dNSName field(s) */
             val = method->i2v(method, extstr, NULL);
 
-- 
2.15.0

>From bdcf77673aeac0cb1de81f4148c23328cae0f4f7 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
Date: Wed, 8 Nov 2017 14:40:12 +0100
Subject: [PATCH 2/5] crypto: Add a tiny OpenSSL compat level

This header file provides a few OpenSSL 1.1 functions which are not
available in OpenSSL 1.0.2 and earlier. The body of the function
implements the pre-1.1 version of the function provided in 1.1.

Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
---
 src/lib/crypto.c         |  2 ++
 src/lib/openssl-compat.h | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/lib/tls.c            |  2 ++
 3 files changed, 47 insertions(+)
 create mode 100644 src/lib/openssl-compat.h

diff --git a/src/lib/crypto.c b/src/lib/crypto.c
index b4403eb45618..c172efb2b5d9 100644
--- a/src/lib/crypto.c
+++ b/src/lib/crypto.c
@@ -131,6 +131,8 @@
 #ifdef HAVE_CRYPTO /* Is encryption enabled? */
 #ifdef HAVE_OPENSSL /* How about OpenSSL? */
 
+#include "openssl-compat.h"
+
 /* ASN.1 Declarations */
 #define BACULA_ASN1_VERSION 0
 
diff --git a/src/lib/openssl-compat.h b/src/lib/openssl-compat.h
new file mode 100644
index 000000000000..2effcb6bc9bb
--- /dev/null
+++ b/src/lib/openssl-compat.h
@@ -0,0 +1,43 @@
+#ifndef __OPENSSL_COPMAT__H__
+#define __OPENSSL_COPMAT__H__
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+static int EVP_PKEY_up_ref(EVP_PKEY *pkey)
+{
+	CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+	return 0;
+}
+
+static void EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
+{
+	EVP_CIPHER_CTX_init(ctx);
+}
+
+static void EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+	EVP_MD_CTX_init(ctx);
+}
+
+static EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+	EVP_MD_CTX *ctx;
+
+	ctx = (EVP_MD_CTX *)OPENSSL_malloc(sizeof(EVP_MD_CTX));
+	if (ctx)
+		memset(ctx, 0, sizeof(EVP_MD_CTX));
+	return ctx;
+}
+
+static void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+	EVP_MD_CTX_reset(ctx);
+	OPENSSL_free(ctx);
+}
+
+static const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1)
+{
+	return asn1->data;
+}
+#endif
+
+#endif
diff --git a/src/lib/tls.c b/src/lib/tls.c
index 992265b38ad2..c71a4ad525fe 100644
--- a/src/lib/tls.c
+++ b/src/lib/tls.c
@@ -45,6 +45,8 @@
 
 #ifdef HAVE_OPENSSL /* How about OpenSSL? */
 
+#include "openssl-compat.h"
+
 /* No anonymous ciphers, no <128 bit ciphers, no export ciphers, no MD5 ciphers */
 #define TLS_DEFAULT_CIPHERS "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
 
-- 
2.15.0

>From e8186c36805dcec1c9f4333a294288200a3ab9f1 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
Date: Wed, 8 Nov 2017 14:42:22 +0100
Subject: [PATCH 3/5] crypto: Use DEFINE_STACK_OF()

OpenSSL 1.1 makes it possible to use DEFINE_STACK_OF() instead of
IMPLEMENT_STACK_OF() + mkstack.pl's output.

Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
---
 src/lib/crypto.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/lib/crypto.c b/src/lib/crypto.c
index c172efb2b5d9..4b9f0f2a2f3a 100644
--- a/src/lib/crypto.c
+++ b/src/lib/crypto.c
@@ -194,9 +194,11 @@ IMPLEMENT_ASN1_FUNCTIONS(SignerInfo)
 IMPLEMENT_ASN1_FUNCTIONS(RecipientInfo)
 IMPLEMENT_ASN1_FUNCTIONS(SignatureData)
 IMPLEMENT_ASN1_FUNCTIONS(CryptoData)
-IMPLEMENT_STACK_OF(SignerInfo)
-IMPLEMENT_STACK_OF(RecipientInfo)
 
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
+DEFINE_STACK_OF(SignerInfo);
+DEFINE_STACK_OF(RecipientInfo);
+#else
 /*
  * SignerInfo and RecipientInfo stack macros, generated by OpenSSL's util/mkstack.pl.
  */
@@ -260,6 +262,7 @@ IMPLEMENT_STACK_OF(RecipientInfo)
 #define ASN1_seq_unpack_RecipientInfo(buf, len, d2i_func, free_func) \
         SKM_ASN1_seq_unpack(RecipientInfo, (buf), (len), (d2i_func), (free_func))
 /* End of util/mkstack.pl block */
+#endif
 
 /* X509 Public/Private Key Pair Structure */
 struct X509_Keypair {
-- 
2.15.0

>From 44a8f9083ac6e5ecc9ea199074695b425ab2b050 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
Date: Wed, 8 Nov 2017 21:01:45 +0100
Subject: [PATCH 4/5] crypto: convert EVP_MD_CTX + EVP_CIPHER_CTX to OpenSSL
 1.1

Those digest structs became opaque and now they need to be allocated
and for access we need to use accessor functions.

Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
---
 src/lib/crypto.c | 51 +++++++++++++++++++++++++++++----------------------
 1 file changed, 29 insertions(+), 22 deletions(-)

diff --git a/src/lib/crypto.c b/src/lib/crypto.c
index 4b9f0f2a2f3a..1dae063697c7 100644
--- a/src/lib/crypto.c
+++ b/src/lib/crypto.c
@@ -275,7 +275,7 @@ struct X509_Keypair {
 struct Digest {
    crypto_digest_t type;
    JCR *jcr;
-   EVP_MD_CTX ctx;
+   EVP_MD_CTX *ctx;
 };
 
 /* Message Signature Structure */
@@ -293,7 +293,7 @@ struct Crypto_Session {
 
 /* Symmetric Cipher Context */
 struct Cipher_Context {
-   EVP_CIPHER_CTX ctx;
+   EVP_CIPHER_CTX *ctx;
 };
 
 /* PEM Password Dispatch Context */
@@ -590,7 +590,10 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
    Dmsg1(150, "crypto_digest_new jcr=%p\n", jcr);
 
    /* Initialize the OpenSSL message digest context */
-   EVP_MD_CTX_init(&digest->ctx);
+   digest->ctx = EVP_MD_CTX_new();
+   if (!digest->ctx)
+	   goto err;
+   EVP_MD_CTX_reset(digest->ctx);
 
    /* Determine the correct OpenSSL message digest type */
    switch (type) {
@@ -614,7 +617,7 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
    }
 
    /* Initialize the backing OpenSSL context */
-   if (EVP_DigestInit_ex(&digest->ctx, md, NULL) == 0) {
+   if (EVP_DigestInit_ex(digest->ctx, md, NULL) == 0) {
       goto err;
    }
 
@@ -635,7 +638,7 @@ DIGEST *crypto_digest_new(JCR *jcr, crypto_digest_t type)
  */
 bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length)
 {
-   if (EVP_DigestUpdate(&digest->ctx, data, length) == 0) {
+   if (EVP_DigestUpdate(digest->ctx, data, length) == 0) {
       Dmsg0(150, "digest update failed\n");
       openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest update failed"));
       return false;
@@ -653,7 +656,7 @@ bool crypto_digest_update(DIGEST *digest, const uint8_t *data, uint32_t length)
  */
 bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length)
 {
-   if (!EVP_DigestFinal(&digest->ctx, dest, (unsigned int *)length)) {
+   if (!EVP_DigestFinal(digest->ctx, dest, (unsigned int *)length)) {
       Dmsg0(150, "digest finalize failed\n");
       openssl_post_errors(digest->jcr, M_ERROR, _("OpenSSL digest finalize failed"));
       return false;
@@ -667,7 +670,7 @@ bool crypto_digest_finalize(DIGEST *digest, uint8_t *dest, uint32_t *length)
  */
 void crypto_digest_free(DIGEST *digest)
 {
-  EVP_MD_CTX_cleanup(&digest->ctx);
+  EVP_MD_CTX_free(digest->ctx);
   free(digest);
 }
 
@@ -790,7 +793,7 @@ crypto_error_t crypto_sign_verify(SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST
          sigLen = M_ASN1_STRING_length(si->signature);
          sigData = M_ASN1_STRING_data(si->signature);
 
-         ok = EVP_VerifyFinal(&digest->ctx, sigData, sigLen, keypair->pubkey);
+         ok = EVP_VerifyFinal(digest->ctx, sigData, sigLen, keypair->pubkey);
          if (ok >= 1) {
             return CRYPTO_ERROR_NONE;
          } else if (ok == 0) {
@@ -858,12 +861,12 @@ int crypto_sign_add_signer(SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair
    /* Set our signature algorithm. We currently require RSA */
    assert(EVP_PKEY_type(keypair->pubkey->type) == EVP_PKEY_RSA);
    /* This is slightly evil. Reach into the MD structure and grab the key type */
-   si->signatureAlgorithm = OBJ_nid2obj(digest->ctx.digest->pkey_type);
+   si->signatureAlgorithm = OBJ_nid2obj(EVP_MD_pkey_type(EVP_MD_CTX_md(digest->ctx)));
 
    /* Finalize/Sign our Digest */
    len = EVP_PKEY_size(keypair->privkey);
    buf = (unsigned char *) malloc(len);
-   if (!EVP_SignFinal(&digest->ctx, buf, &len, keypair->privkey)) {
+   if (!EVP_SignFinal(digest->ctx, buf, &len, keypair->privkey)) {
       openssl_post_errors(M_ERROR, _("Signature creation failed"));
       goto err;
    }
@@ -1249,6 +1252,12 @@ CIPHER_CONTEXT *crypto_cipher_new(CRYPTO_SESSION *cs, bool encrypt, uint32_t *bl
    const EVP_CIPHER *ec;
 
    cipher_ctx = (CIPHER_CONTEXT *)malloc(sizeof(CIPHER_CONTEXT));
+   if (!cipher_ctx)
+	   return NULL;
+
+   cipher_ctx->ctx = EVP_CIPHER_CTX_new();
+   if (cipher_ctx->ctx)
+	   goto err;
 
    /*
     * Acquire a cipher instance for the given ASN.1 cipher NID
@@ -1261,40 +1270,40 @@ CIPHER_CONTEXT *crypto_cipher_new(CRYPTO_SESSION *cs, bool encrypt, uint32_t *bl
    }
 
    /* Initialize the OpenSSL cipher context */
-   EVP_CIPHER_CTX_init(&cipher_ctx->ctx);
+   EVP_CIPHER_CTX_reset(cipher_ctx->ctx);
    if (encrypt) {
       /* Initialize for encryption */
-      if (!EVP_CipherInit_ex(&cipher_ctx->ctx, ec, NULL, NULL, NULL, 1)) {
+      if (!EVP_CipherInit_ex(cipher_ctx->ctx, ec, NULL, NULL, NULL, 1)) {
          openssl_post_errors(M_ERROR, _("OpenSSL cipher context initialization failed"));
          goto err;
       }
    } else {
       /* Initialize for decryption */
-      if (!EVP_CipherInit_ex(&cipher_ctx->ctx, ec, NULL, NULL, NULL, 0)) {
+      if (!EVP_CipherInit_ex(cipher_ctx->ctx, ec, NULL, NULL, NULL, 0)) {
          openssl_post_errors(M_ERROR, _("OpenSSL cipher context initialization failed"));
          goto err;
       }
    }
 
    /* Set the key size */
-   if (!EVP_CIPHER_CTX_set_key_length(&cipher_ctx->ctx, cs->session_key_len)) {
+   if (!EVP_CIPHER_CTX_set_key_length(cipher_ctx->ctx, cs->session_key_len)) {
       openssl_post_errors(M_ERROR, _("Encryption session provided an invalid symmetric key"));
       goto err;
    }
 
    /* Validate the IV length */
-   if (EVP_CIPHER_iv_length(ec) != M_ASN1_STRING_length(cs->cryptoData->iv)) {
+   if (EVP_CIPHER_iv_length(ec) != ASN1_STRING_length(cs->cryptoData->iv)) {
       openssl_post_errors(M_ERROR, _("Encryption session provided an invalid IV"));
       goto err;
    }
 
    /* Add the key and IV to the cipher context */
-   if (!EVP_CipherInit_ex(&cipher_ctx->ctx, NULL, NULL, cs->session_key, M_ASN1_STRING_data(cs->cryptoData->iv), -1)) {
+   if (!EVP_CipherInit_ex(cipher_ctx->ctx, NULL, NULL, cs->session_key, ASN1_STRING_get0_data(cs->cryptoData->iv), -1)) {
       openssl_post_errors(M_ERROR, _("OpenSSL cipher context key/IV initialization failed"));
       goto err;
    }
 
-   *blocksize = EVP_CIPHER_CTX_block_size(&cipher_ctx->ctx);
+   *blocksize = EVP_CIPHER_CTX_block_size(cipher_ctx->ctx);
    return cipher_ctx;
 
 err:
@@ -1310,7 +1319,7 @@ CIPHER_CONTEXT *crypto_cipher_new(CRYPTO_SESSION *cs, bool encrypt, uint32_t *bl
  */
 bool crypto_cipher_update(CIPHER_CONTEXT *cipher_ctx, const uint8_t *data, uint32_t length, const uint8_t *dest, uint32_t *written)
 {
-   if (!EVP_CipherUpdate(&cipher_ctx->ctx, (unsigned char *)dest, (int *)written, (const unsigned char *)data, length)) {
+   if (!EVP_CipherUpdate(cipher_ctx->ctx, (unsigned char *)dest, (int *)written, (const unsigned char *)data, length)) {
       /* This really shouldn't fail */
       return false;
    } else {
@@ -1328,7 +1337,7 @@ bool crypto_cipher_update(CIPHER_CONTEXT *cipher_ctx, const uint8_t *data, uint3
  */
 bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, uint8_t *dest, uint32_t *written)
 {
-   if (!EVP_CipherFinal_ex(&cipher_ctx->ctx, (unsigned char *)dest, (int *) written)) {
+   if (!EVP_CipherFinal_ex(cipher_ctx->ctx, (unsigned char *)dest, (int *) written)) {
       /* This really shouldn't fail */
       return false;
    } else {
@@ -1342,12 +1351,10 @@ bool crypto_cipher_finalize (CIPHER_CONTEXT *cipher_ctx, uint8_t *dest, uint32_t
  */
 void crypto_cipher_free (CIPHER_CONTEXT *cipher_ctx)
 {
-   EVP_CIPHER_CTX_cleanup(&cipher_ctx->ctx);
+   EVP_CIPHER_CTX_free(cipher_ctx->ctx);
    free (cipher_ctx);
 }
 
-
-
 #else /* HAVE_OPENSSL */
 # error No encryption library available
 #endif /* HAVE_OPENSSL */
-- 
2.15.0

>From 8e5336b18826a9057912d55f5aafb3d1e392d195 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
Date: Wed, 8 Nov 2017 21:08:10 +0100
Subject: [PATCH 5/5] crypto_: convert EVP_PKEY access and remainings bits for
 OpenSSL 1.1

EVP_PKEY became opaque and can not be dereferences in OpenSSL 1.1 and
accessor functions need to be used. This is also true for X509_EXTENSION
relevant access.

Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
---
 src/lib/crypto.c | 72 +++++++++++++++++++++++++++++++-------------------------
 src/lib/tls.c    |  8 ++++---
 2 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/src/lib/crypto.c b/src/lib/crypto.c
index 1dae063697c7..3657c06aa8b0 100644
--- a/src/lib/crypto.c
+++ b/src/lib/crypto.c
@@ -304,7 +304,7 @@ typedef struct PEM_CB_Context {
 
 /*
  * Extract subjectKeyIdentifier from x509 certificate.
- * Returns: On success, an ASN1_OCTET_STRING that must be freed via M_ASN1_OCTET_STRING_free().
+ * Returns: On success, an ASN1_OCTET_STRING that must be freed via ASN1_OCTET_STRING_free().
  *          NULL on failure.
  */
 static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
@@ -312,6 +312,7 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
    const X509V3_EXT_METHOD *method;
    ASN1_OCTET_STRING *keyid;
    int i;
+   const ASN1_STRING *asn1_ext_val;
    const unsigned char *ext_value_data;
 
    /* Find the index to the subjectKeyIdentifier extension */
@@ -329,19 +330,20 @@ static ASN1_OCTET_STRING *openssl_cert_keyid(X509 *cert) {
       return NULL;
    }
 
-   ext_value_data = ext->value->data;
+   asn1_ext_val = X509_EXTENSION_get_data(ext);
+   ext_value_data = ASN1_STRING_get0_data(asn1_ext_val);
 
    if (method->it) {
       /* New style ASN1 */
 
       /* Decode ASN1 item in data */
-      keyid = (ASN1_OCTET_STRING *) ASN1_item_d2i(NULL, &ext_value_data, ext->value->length,
+      keyid = (ASN1_OCTET_STRING *) ASN1_item_d2i(NULL, &ext_value_data, ASN1_STRING_length(asn1_ext_val),
                                                   ASN1_ITEM_ptr(method->it));
    } else {
       /* Old style ASN1 */
 
       /* Decode ASN1 item in data */
-      keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ext->value->length);
+      keyid = (ASN1_OCTET_STRING *) method->d2i(NULL, &ext_value_data, ASN1_STRING_length(asn1_ext_val));
    }
 
    return keyid;
@@ -376,6 +378,7 @@ X509_KEYPAIR *crypto_keypair_new(void)
 X509_KEYPAIR *crypto_keypair_dup(X509_KEYPAIR *keypair)
 {
    X509_KEYPAIR *newpair;
+   int ret;
 
    newpair = crypto_keypair_new();
 
@@ -386,27 +389,32 @@ X509_KEYPAIR *crypto_keypair_dup(X509_KEYPAIR *keypair)
 
    /* Increment the public key ref count */
    if (keypair->pubkey) {
-      CRYPTO_add(&(keypair->pubkey->references), 1, CRYPTO_LOCK_EVP_PKEY);
+      ret = EVP_PKEY_up_ref(keypair->pubkey);
+      if (ret == 0)
+	      goto out_free_new;
       newpair->pubkey = keypair->pubkey;
    }
 
    /* Increment the private key ref count */
    if (keypair->privkey) {
-      CRYPTO_add(&(keypair->privkey->references), 1, CRYPTO_LOCK_EVP_PKEY);
+      ret = EVP_PKEY_up_ref(keypair->privkey);
+      if (ret == 0)
+	      goto out_free_new;
       newpair->privkey = keypair->privkey;
    }
 
    /* Duplicate the keyid */
    if (keypair->keyid) {
-      newpair->keyid = M_ASN1_OCTET_STRING_dup(keypair->keyid);
-      if (!newpair->keyid) {
-         /* Allocation failed */
-         crypto_keypair_free(newpair);
-         return NULL;
-      }
+      newpair->keyid = ASN1_OCTET_STRING_dup(keypair->keyid);
+      if (!newpair->keyid)
+	      goto out_free_new;
    }
 
    return newpair;
+
+out_free_new:
+   crypto_keypair_free(newpair);
+   return NULL;
 }
 
 
@@ -447,9 +455,9 @@ int crypto_keypair_load_cert(X509_KEYPAIR *keypair, const char *file)
    }
 
    /* Validate the public key type (only RSA is supported) */
-   if (EVP_PKEY_type(keypair->pubkey->type) != EVP_PKEY_RSA) {
+   if (EVP_PKEY_base_id(keypair->pubkey) != EVP_PKEY_RSA) {
        Jmsg1(NULL, M_ERROR, 0,
-             _("Unsupported key type provided: %d\n"), EVP_PKEY_type(keypair->pubkey->type));
+             _("Unsupported key type provided: %d\n"), EVP_PKEY_id(keypair->pubkey));
        goto err;
    }
 
@@ -569,7 +577,7 @@ void crypto_keypair_free(X509_KEYPAIR *keypair)
       EVP_PKEY_free(keypair->privkey);
    }
    if (keypair->keyid) {
-      M_ASN1_OCTET_STRING_free(keypair->keyid);
+      ASN1_OCTET_STRING_free(keypair->keyid);
    }
    free(keypair);
 }
@@ -722,7 +730,7 @@ crypto_error_t crypto_sign_get_digest(SIGNATURE *sig, X509_KEYPAIR *keypair,
 
    for (i = 0; i < sk_SignerInfo_num(signers); i++) {
       si = sk_SignerInfo_value(signers, i);
-      if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) {
+      if (ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) {
          /* Get the digest algorithm and allocate a digest context */
          Dmsg1(150, "crypto_sign_get_digest jcr=%p\n", sig->jcr);
          switch (OBJ_obj2nid(si->digestAlgorithm)) {
@@ -788,10 +796,10 @@ crypto_error_t crypto_sign_verify(SIGNATURE *sig, X509_KEYPAIR *keypair, DIGEST
    /* Find the signer */
    for (i = 0; i < sk_SignerInfo_num(signers); i++) {
       si = sk_SignerInfo_value(signers, i);
-      if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) {
+      if (ASN1_OCTET_STRING_cmp(keypair->keyid, si->subjectKeyIdentifier) == 0) {
          /* Extract the signature data */
-         sigLen = M_ASN1_STRING_length(si->signature);
-         sigData = M_ASN1_STRING_data(si->signature);
+         sigLen = ASN1_STRING_length(si->signature);
+         sigData = ASN1_STRING_get0_data(si->signature);
 
          ok = EVP_VerifyFinal(digest->ctx, sigData, sigLen, keypair->pubkey);
          if (ok >= 1) {
@@ -855,11 +863,11 @@ int crypto_sign_add_signer(SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair
    }
 
    /* Drop the string allocated by OpenSSL, and add our subjectKeyIdentifier */
-   M_ASN1_OCTET_STRING_free(si->subjectKeyIdentifier);
-   si->subjectKeyIdentifier = M_ASN1_OCTET_STRING_dup(keypair->keyid);
+   ASN1_OCTET_STRING_free(si->subjectKeyIdentifier);
+   si->subjectKeyIdentifier = ASN1_OCTET_STRING_dup(keypair->keyid);
 
    /* Set our signature algorithm. We currently require RSA */
-   assert(EVP_PKEY_type(keypair->pubkey->type) == EVP_PKEY_RSA);
+   assert(EVP_PKEY_base_id(keypair->pubkey) == EVP_PKEY_RSA);
    /* This is slightly evil. Reach into the MD structure and grab the key type */
    si->signatureAlgorithm = OBJ_nid2obj(EVP_MD_pkey_type(EVP_MD_CTX_md(digest->ctx)));
 
@@ -872,7 +880,7 @@ int crypto_sign_add_signer(SIGNATURE *sig, DIGEST *digest, X509_KEYPAIR *keypair
    }
 
    /* Add the signature to the SignerInfo structure */
-   if (!M_ASN1_OCTET_STRING_set(si->signature, buf, len)) {
+   if (!ASN1_OCTET_STRING_set(si->signature, buf, len)) {
       /* Allocation failed in OpenSSL */
       goto err;
    }
@@ -1045,7 +1053,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
       }
 
       /* Store it in our ASN.1 structure */
-      if (!M_ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) {
+      if (!ASN1_OCTET_STRING_set(cs->cryptoData->iv, iv, iv_len)) {
          /* Allocation failed in OpenSSL */
          crypto_session_free(cs);
          free(iv);
@@ -1074,11 +1082,11 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
       ASN1_INTEGER_set(ri->version, BACULA_ASN1_VERSION);
 
       /* Drop the string allocated by OpenSSL, and add our subjectKeyIdentifier */
-      M_ASN1_OCTET_STRING_free(ri->subjectKeyIdentifier);
-      ri->subjectKeyIdentifier = M_ASN1_OCTET_STRING_dup(keypair->keyid);
+      ASN1_OCTET_STRING_free(ri->subjectKeyIdentifier);
+      ri->subjectKeyIdentifier = ASN1_OCTET_STRING_dup(keypair->keyid);
 
       /* Set our key encryption algorithm. We currently require RSA */
-      assert(keypair->pubkey && EVP_PKEY_type(keypair->pubkey->type) == EVP_PKEY_RSA);
+      assert(keypair->pubkey && EVP_PKEY_base_id(keypair->pubkey) == EVP_PKEY_RSA);
       ri->keyEncryptionAlgorithm = OBJ_nid2obj(NID_rsaEncryption);
 
       /* Encrypt the session key */
@@ -1093,7 +1101,7 @@ CRYPTO_SESSION *crypto_session_new (crypto_cipher_t cipher, alist *pubkeys)
       }
 
       /* Store it in our ASN.1 structure */
-      if (!M_ASN1_OCTET_STRING_set(ri->encryptedKey, ekey, ekey_len)) {
+      if (!ASN1_OCTET_STRING_set(ri->encryptedKey, ekey, ekey_len)) {
          /* Allocation failed in OpenSSL */
          RecipientInfo_free(ri);
          crypto_session_free(cs);
@@ -1187,11 +1195,11 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist
          ri = sk_RecipientInfo_value(recipients, i);
 
          /* Match against the subjectKeyIdentifier */
-         if (M_ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) {
+         if (ASN1_OCTET_STRING_cmp(keypair->keyid, ri->subjectKeyIdentifier) == 0) {
             /* Match found, extract symmetric encryption session data */
 
             /* RSA is required. */
-            assert(EVP_PKEY_type(keypair->privkey->type) == EVP_PKEY_RSA);
+            assert(EVP_PKEY_base_id(keypair->privkey) == EVP_PKEY_RSA);
 
             /* If we recieve a RecipientInfo structure that does not use
              * RSA, return an error */
@@ -1203,8 +1211,8 @@ crypto_error_t crypto_session_decode(const uint8_t *data, uint32_t length, alist
             /* Decrypt the session key */
             /* Allocate sufficient space for the largest possible decrypted data */
             cs->session_key = (unsigned char *)malloc(EVP_PKEY_size(keypair->privkey));
-            cs->session_key_len = EVP_PKEY_decrypt(cs->session_key, M_ASN1_STRING_data(ri->encryptedKey),
-                                  M_ASN1_STRING_length(ri->encryptedKey), keypair->privkey);
+            cs->session_key_len = EVP_PKEY_decrypt(cs->session_key, ASN1_STRING_get0_data(ri->encryptedKey),
+                                  ASN1_STRING_length(ri->encryptedKey), keypair->privkey);
 
             if (cs->session_key_len <= 0) {
                openssl_post_errors(M_ERROR, _("Failure decrypting the session key"));
diff --git a/src/lib/tls.c b/src/lib/tls.c
index c71a4ad525fe..01d3f94e8113 100644
--- a/src/lib/tls.c
+++ b/src/lib/tls.c
@@ -337,25 +337,27 @@ bool tls_postconnect_verify_host(JCR *jcr, TLS_CONNECTION *tls, const char *host
             CONF_VALUE *nval;
             void *extstr = NULL;
             const unsigned char *ext_value_data;
+            const ASN1_STRING *asn1_ext_val;
 
             /* Get x509 extension method structure */
             if (!(method = X509V3_EXT_get(ext))) {
                break;
             }
 
-            ext_value_data = ext->value->data;
+            asn1_ext_val = X509_EXTENSION_get_data(ext);
+            ext_value_data = ASN1_STRING_get0_data(asn1_ext_val);
 
             if (method->it) {
                /* New style ASN1 */
 
                /* Decode ASN1 item in data */
-               extstr = ASN1_item_d2i(NULL, &ext_value_data, ext->value->length,
+               extstr = ASN1_item_d2i(NULL, &ext_value_data, ASN1_STRING_length(asn1_ext_val),
                                       ASN1_ITEM_ptr(method->it));
             } else {
                /* Old style ASN1 */
 
                /* Decode ASN1 item in data */
-               extstr = method->d2i(NULL, &ext_value_data, ext->value->length);
+               extstr = method->d2i(NULL, &ext_value_data, ASN1_STRING_length(asn1_ext_val));
             }
 
             /* Iterate through to find the dNSName field(s) */
-- 
2.15.0

>From b24350f437064af4564d7b07263eb88b2de82a44 Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
Date: Thu, 9 Nov 2017 21:55:20 +0100
Subject: [PATCH] crypto: remove most of OpenSSL initcallbacks for 1.1

In OpenSSL 1.1 the thread model atomically initialized the library so
there is no need to invoke the init calls, like it was needed for 1.0.2
and earlier. The may be needed for non-standard inits like no-error
strings or so (not the case here). So the ifdef avoids them.

Also, in 1.1 there is no need to teach OpenSSL how to do locking and so
on. Infect, those functions are null-macros as for 1.0.2 compat. So
another ifdef avoids them, too.

I made four function static and removed them the header file since they
don't seem to be used outside of that openssl.c file.

This leaves us the 1.1 init part down to openssl_seed_prng(). I would
actually suggest to get rid of it. OpenSSL is able to gather some
entropy if needed. I don't think reading 2x 1024KiB from system's
entropy on each invocation of the program is wise. But I leave it to
the maintainer to make a decision, I just point it out.

Signed-off-by: Sebastian Andrzej Siewior <sebast...@breakpoint.cc>
---
 src/lib/openssl.c | 35 +++++++++++++++++++----------------
 src/lib/openssl.h |  4 ----
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/src/lib/openssl.c b/src/lib/openssl.c
index 64b0e96009a7..23ac946cfaee 100644
--- a/src/lib/openssl.c
+++ b/src/lib/openssl.c
@@ -41,15 +41,6 @@
 
 /* Are we initialized? */
 static int crypto_initialized = false;
-
-/* Array of mutexes for use with OpenSSL static locking */
-static pthread_mutex_t *mutexes;
-
-/* OpenSSL dynamic locking structure */
-struct CRYPTO_dynlock_value {
-   pthread_mutex_t mutex;
-};
-
 /*
  * ***FIXME*** this is a sort of dummy to avoid having to
  *   change all the existing code to pass either a jcr or
@@ -61,7 +52,6 @@ void openssl_post_errors(int code, const char *errstring)
    openssl_post_errors(NULL, code, errstring);
 }
 
-
 /*
  * Post all per-thread openssl errors
  */
@@ -79,6 +69,15 @@ void openssl_post_errors(JCR *jcr, int code, const char *errstring)
    }
 }
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
+/* Array of mutexes for use with OpenSSL static locking */
+static pthread_mutex_t *mutexes;
+
+/* OpenSSL dynamic locking structure */
+struct CRYPTO_dynlock_value {
+   pthread_mutex_t mutex;
+};
+
 /*
  * Return an OpenSSL thread ID
  *  Returns: thread ID
@@ -151,12 +150,11 @@ static void openssl_update_static_mutex (int mode, int i, const char *file, int
  *  Returns: 0 on success
  *           errno on failure
  */
-int openssl_init_threads (void)
+static int openssl_init_threads (void)
 {
    int i, numlocks;
    int stat;
 
-
    /* Set thread ID callback */
    CRYPTO_set_id_callback(get_openssl_thread_id);
 
@@ -185,7 +183,7 @@ int openssl_init_threads (void)
 /*
  * Clean up OpenSSL threading support
  */
-void openssl_cleanup_threads(void)
+static void openssl_cleanup_threads(void)
 {
    int i, numlocks;
    int stat;
@@ -216,13 +214,14 @@ void openssl_cleanup_threads(void)
    CRYPTO_set_dynlock_destroy_callback(NULL);
 }
 
+#endif
 
 /*
  * Seed OpenSSL PRNG
  *  Returns: 1 on success
  *           0 on failure
  */
-int openssl_seed_prng (void)
+static int openssl_seed_prng (void)
 {
    const char *names[]  = { "/dev/urandom", "/dev/random", NULL };
    int i;
@@ -247,7 +246,7 @@ int openssl_seed_prng (void)
  *  Returns: 1 on success
  *           0 on failure
  */
-int openssl_save_prng (void)
+static int openssl_save_prng (void)
 {
    // ***FIXME***
    // Implement PRNG state save
@@ -262,8 +261,9 @@ int openssl_save_prng (void)
  */
 int init_crypto (void)
 {
-   int stat;
+   int stat = 0;
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
    if ((stat = openssl_init_threads()) != 0) {
       berrno be;
       Jmsg1(NULL, M_ABORT, 0,
@@ -278,6 +278,7 @@ int init_crypto (void)
 
    /* Register OpenSSL ciphers and digests */
    OpenSSL_add_all_algorithms();
+#endif
 
    if (!openssl_seed_prng()) {
       Jmsg0(NULL, M_ERROR_TERM, 0, _("Failed to seed OpenSSL PRNG\n"));
@@ -309,6 +310,7 @@ int cleanup_crypto (void)
       Jmsg0(NULL, M_ERROR, 0, _("Failed to save OpenSSL PRNG\n"));
    }
 
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
    openssl_cleanup_threads();
 
    /* Free libssl and libcrypto error strings */
@@ -319,6 +321,7 @@ int cleanup_crypto (void)
 
    /* Free memory used by PRNG */
    RAND_cleanup();
+#endif
 
    crypto_initialized = false;
 
diff --git a/src/lib/openssl.h b/src/lib/openssl.h
index 597517a4fd68..9374a581c735 100644
--- a/src/lib/openssl.h
+++ b/src/lib/openssl.h
@@ -39,10 +39,6 @@
 #ifdef HAVE_OPENSSL
 void             openssl_post_errors     (int code, const char *errstring);
 void             openssl_post_errors     (JCR *jcr, int code, const char *errstring);
-int              openssl_init_threads    (void);
-void             openssl_cleanup_threads (void);
-int              openssl_seed_prng       (void);
-int              openssl_save_prng       (void);
 #endif /* HAVE_OPENSSL */
 
 #endif /* __OPENSSL_H_ */
-- 
2.15.0.rc0

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Bacula-devel mailing list
Bacula-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-devel

Reply via email to