[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Build libssh against openssl 1.1.0


Hello libssh developers,
during last days we were porting various applications to openssl 1.1.0, which brought various API changes to simplify the transition to new version in future Fedora [1].

The most of the changes are not backward compatible and require special layer of compatibility (also included). I tested the patch with the new 1.1.0 and the old 1.0.2 (unfortunately I don't have any older) versions and the test suite passed in both cases.

What was not handled are deprecated methods DSA_generate_parameters and RAND_pseudo_bytes, that will be removed in the future releases, but it is not preventing from the usage.

[1] https://fedoraproject.org/wiki/Changes/OpenSSL110

Let me know, if the patch is acceptable, or there are things to improve.
Regards,

--
Jakub Jelen
Software Engineer
Security Technologies
Red Hat

From 8999422863565d5cf9bc231aea13e79419ae76c8 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@xxxxxxxxxx>
Date: Mon, 31 Oct 2016 17:39:28 +0100
Subject: [PATCH] Allow to build against OpenSSL 1.1.0

Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx>
---
 include/libssh/crypto.h |   2 +-
 src/CMakeLists.txt      |   1 +
 src/libcrypto-compat.c  | 322 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/libcrypto-compat.h  |  43 +++++++
 src/libcrypto.c         |  51 ++++----
 src/pki_crypto.c        | 250 +++++++++++++++++++++----------------
 6 files changed, 543 insertions(+), 126 deletions(-)
 create mode 100644 src/libcrypto-compat.c
 create mode 100644 src/libcrypto-compat.h

diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index e370c74..18bc944 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -126,7 +126,7 @@ struct ssh_cipher_struct {
     struct ssh_3des_key_schedule *des3_key;
     struct ssh_aes_key_schedule *aes_key;
     const EVP_CIPHER *cipher;
-    EVP_CIPHER_CTX ctx;
+    EVP_CIPHER_CTX *ctx;
 #endif
     unsigned int keysize; /* bytes of key used. != keylen */
     /* sets the new key for immediate use */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a3e08a6..2517267 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -126,6 +126,7 @@ set(libssh_SRCS
   known_hosts.c
   legacy.c
   libcrypto.c
+  libcrypto-compat.c
   log.c
   match.c
   messages.c
diff --git a/src/libcrypto-compat.c b/src/libcrypto-compat.c
new file mode 100644
index 0000000..65d94a6
--- /dev/null
+++ b/src/libcrypto-compat.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+#include <string.h>
+#include <openssl/engine.h>
+#include "libcrypto-compat.h"
+
+static void *OPENSSL_zalloc(size_t num)
+{
+    void *ret = OPENSSL_malloc(num);
+
+    if (ret != NULL)
+        memset(ret, 0, num);
+    return ret;
+}
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+    /* If the fields n and e in r are NULL, the corresponding input
+     * parameters MUST be non-NULL for n and e.  d may be
+     * left NULL (in case only the public key is used).
+     */
+    if ((r->n == NULL && n == NULL)
+        || (r->e == NULL && e == NULL))
+        return 0;
+
+    if (n != NULL) {
+        BN_free(r->n);
+        r->n = n;
+    }
+    if (e != NULL) {
+        BN_free(r->e);
+        r->e = e;
+    }
+    if (d != NULL) {
+        BN_free(r->d);
+        r->d = d;
+    }
+
+    return 1;
+}
+
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+    /* If the fields p and q in r are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((r->p == NULL && p == NULL)
+        || (r->q == NULL && q == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(r->p);
+        r->p = p;
+    }
+    if (q != NULL) {
+        BN_free(r->q);
+        r->q = q;
+    }
+
+    return 1;
+}
+
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+    /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((r->dmp1 == NULL && dmp1 == NULL)
+        || (r->dmq1 == NULL && dmq1 == NULL)
+        || (r->iqmp == NULL && iqmp == NULL))
+        return 0;
+
+    if (dmp1 != NULL) {
+        BN_free(r->dmp1);
+        r->dmp1 = dmp1;
+    }
+    if (dmq1 != NULL) {
+        BN_free(r->dmq1);
+        r->dmq1 = dmq1;
+    }
+    if (iqmp != NULL) {
+        BN_free(r->iqmp);
+        r->iqmp = iqmp;
+    }
+
+    return 1;
+}
+
+void RSA_get0_key(const RSA *r,
+                  const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+    if (n != NULL)
+        *n = r->n;
+    if (e != NULL)
+        *e = r->e;
+    if (d != NULL)
+        *d = r->d;
+}
+
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+    if (p != NULL)
+        *p = r->p;
+    if (q != NULL)
+        *q = r->q;
+}
+
+void RSA_get0_crt_params(const RSA *r,
+                         const BIGNUM **dmp1, const BIGNUM **dmq1,
+                         const BIGNUM **iqmp)
+{
+    if (dmp1 != NULL)
+        *dmp1 = r->dmp1;
+    if (dmq1 != NULL)
+        *dmq1 = r->dmq1;
+    if (iqmp != NULL)
+        *iqmp = r->iqmp;
+}
+
+void DSA_get0_pqg(const DSA *d,
+                  const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+    if (p != NULL)
+        *p = d->p;
+    if (q != NULL)
+        *q = d->q;
+    if (g != NULL)
+        *g = d->g;
+}
+
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    /* If the fields p, q and g in d are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((d->p == NULL && p == NULL)
+        || (d->q == NULL && q == NULL)
+        || (d->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(d->p);
+        d->p = p;
+    }
+    if (q != NULL) {
+        BN_free(d->q);
+        d->q = q;
+    }
+    if (g != NULL) {
+        BN_free(d->g);
+        d->g = g;
+    }
+
+    return 1;
+}
+
+void DSA_get0_key(const DSA *d,
+                  const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+    if (pub_key != NULL)
+        *pub_key = d->pub_key;
+    if (priv_key != NULL)
+        *priv_key = d->priv_key;
+}
+
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    /* If the field pub_key in d is NULL, the corresponding input
+     * parameters MUST be non-NULL.  The priv_key field may
+     * be left NULL.
+     */
+    if (d->pub_key == NULL && pub_key == NULL)
+        return 0;
+
+    if (pub_key != NULL) {
+        BN_free(d->pub_key);
+        d->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(d->priv_key);
+        d->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
+}
+
+static void OPENSSL_clear_free(void *str, size_t num)
+{
+    if (str == NULL)
+        return;
+    if (num)
+        OPENSSL_cleanse(str, num);
+    OPENSSL_free(str);
+}
+
+/* This call frees resources associated with the context */
+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+    if (ctx == NULL)
+        return 1;
+
+    /*
+     * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
+     * sometimes only copies of the context are ever finalised.
+     */
+    if (ctx->digest && ctx->digest->cleanup
+        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
+        ctx->digest->cleanup(ctx);
+    if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
+        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
+        OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
+    }
+    EVP_PKEY_CTX_free(ctx->pctx);
+#ifndef OPENSSL_NO_ENGINE
+    ENGINE_finish(ctx->engine);
+#endif
+    OPENSSL_cleanse(ctx, sizeof(*ctx));
+
+    return 1;
+}
+
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+    EVP_MD_CTX_reset(ctx);
+    OPENSSL_free(ctx);
+}
+
+HMAC_CTX *HMAC_CTX_new(void)
+{
+    HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
+
+    if (ctx != NULL) {
+        if (!HMAC_CTX_reset(ctx)) {
+            HMAC_CTX_free(ctx);
+            return NULL;
+        }
+    }
+    return ctx;
+}
+
+static void hmac_ctx_cleanup(HMAC_CTX *ctx)
+{
+    EVP_MD_CTX_reset(&ctx->i_ctx);
+    EVP_MD_CTX_reset(&ctx->o_ctx);
+    EVP_MD_CTX_reset(&ctx->md_ctx);
+    ctx->md = NULL;
+    ctx->key_length = 0;
+    OPENSSL_cleanse(ctx->key, sizeof(ctx->key));
+}
+
+void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+    if (ctx != NULL) {
+        hmac_ctx_cleanup(ctx);
+        EVP_MD_CTX_free(&ctx->i_ctx);
+        EVP_MD_CTX_free(&ctx->o_ctx);
+        EVP_MD_CTX_free(&ctx->md_ctx);
+        OPENSSL_free(ctx);
+    }
+}
+
+int HMAC_CTX_reset(HMAC_CTX *ctx)
+{
+    HMAC_CTX_init(ctx);
+    return 1;
+}
+#else
+typedef int iso_c_forbids_an_empty_source_file;
+#endif /* OPENSSL_VERSION_NUMBER */
diff --git a/src/libcrypto-compat.h b/src/libcrypto-compat.h
new file mode 100644
index 0000000..7364d4c
--- /dev/null
+++ b/src/libcrypto-compat.h
@@ -0,0 +1,43 @@
+#ifndef LIBCRYPTO_COMPAT_H
+#define LIBCRYPTO_COMPAT_H
+
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/ecdsa.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
+void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
+void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
+
+void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
+
+HMAC_CTX *HMAC_CTX_new(void);
+int HMAC_CTX_reset(HMAC_CTX *ctx);
+void HMAC_CTX_free(HMAC_CTX *ctx);
+
+#endif /* OPENSSL_VERSION_NUMBER */
+
+#endif /* LIBCRYPTO_COMPAT_H */
+
diff --git a/src/libcrypto.c b/src/libcrypto.c
index ac95010..e0c8a9e 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -43,6 +43,7 @@
 #include <openssl/hmac.h>
 #include <openssl/opensslv.h>
 #include <openssl/rand.h>
+#include "libcrypto-compat.h"
 
 #ifdef HAVE_OPENSSL_AES_H
 #define HAS_AES
@@ -135,18 +136,19 @@ static const EVP_MD *nid_to_evpmd(int nid)
 void evp(int nid, unsigned char *digest, int len, unsigned char *hash, unsigned int *hlen)
 {
     const EVP_MD *evp_md = nid_to_evpmd(nid);
-    EVP_MD_CTX md;
+    EVP_MD_CTX *md = EVP_MD_CTX_new();
 
-    EVP_DigestInit(&md, evp_md);
-    EVP_DigestUpdate(&md, digest, len);
-    EVP_DigestFinal(&md, hash, hlen);
+    EVP_DigestInit(md, evp_md);
+    EVP_DigestUpdate(md, digest, len);
+    EVP_DigestFinal(md, hash, hlen);
+    EVP_MD_CTX_free(md);
 }
 
 EVPCTX evp_init(int nid)
 {
     const EVP_MD *evp_md = nid_to_evpmd(nid);
 
-    EVPCTX ctx = malloc(sizeof(EVP_MD_CTX));
+    EVPCTX ctx = EVP_MD_CTX_new();
     if (ctx == NULL) {
         return NULL;
     }
@@ -378,32 +380,33 @@ void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
 HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
   HMACCTX ctx = NULL;
 
-  ctx = malloc(sizeof(*ctx));
+  ctx = HMAC_CTX_new();
   if (ctx == NULL) {
     return NULL;
   }
 
 #ifndef OLD_CRYPTO
-  HMAC_CTX_init(ctx); // openssl 0.9.7 requires it.
+  HMAC_CTX_reset(ctx); // openssl 0.9.7 requires it.
 #endif
 
   switch(type) {
     case SSH_HMAC_SHA1:
-      HMAC_Init(ctx, key, len, EVP_sha1());
+      HMAC_Init_ex(ctx, key, len, EVP_sha1(), NULL);
       break;
     case SSH_HMAC_SHA256:
-      HMAC_Init(ctx, key, len, EVP_sha256());
+      HMAC_Init_ex(ctx, key, len, EVP_sha256(), NULL);
       break;
     case SSH_HMAC_SHA384:
-      HMAC_Init(ctx, key, len, EVP_sha384());
+      HMAC_Init_ex(ctx, key, len, EVP_sha384(), NULL);
       break;
     case SSH_HMAC_SHA512:
-      HMAC_Init(ctx, key, len, EVP_sha512());
+      HMAC_Init_ex(ctx, key, len, EVP_sha512(), NULL);
       break;
     case SSH_HMAC_MD5:
-      HMAC_Init(ctx, key, len, EVP_md5());
+      HMAC_Init_ex(ctx, key, len, EVP_md5(), NULL);
       break;
     default:
+      HMAC_CTX_free(ctx);
       SAFE_FREE(ctx);
       ctx = NULL;
   }
@@ -419,7 +422,7 @@ void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) {
   HMAC_Final(ctx,hashmacbuf,len);
 
 #ifndef OLD_CRYPTO
-  HMAC_CTX_cleanup(ctx);
+  HMAC_CTX_reset(ctx);
 #else
   HMAC_cleanup(ctx);
 #endif
@@ -478,14 +481,14 @@ static int evp_cipher_set_encrypt_key(struct ssh_cipher_struct *cipher,
     int rc;
 
     evp_cipher_init(cipher);
-    EVP_CIPHER_CTX_init(&cipher->ctx);
+    EVP_CIPHER_CTX_init(cipher->ctx);
 
-    rc = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, key, IV);
+    rc = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
     if (rc != 1){
         SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptInit_ex failed");
         return SSH_ERROR;
     }
-    EVP_CIPHER_CTX_set_padding(&cipher->ctx, 0);
+    EVP_CIPHER_CTX_set_padding(cipher->ctx, 0);
 
     return SSH_OK;
 }
@@ -495,14 +498,14 @@ static int evp_cipher_set_decrypt_key(struct ssh_cipher_struct *cipher,
     int rc;
 
     evp_cipher_init(cipher);
-    EVP_CIPHER_CTX_init(&cipher->ctx);
+    EVP_CIPHER_CTX_init(cipher->ctx);
 
-    rc = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, key, IV);
+    rc = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, key, IV);
     if (rc != 1){
         SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptInit_ex failed");
         return SSH_ERROR;
     }
-    EVP_CIPHER_CTX_set_padding(&cipher->ctx, 0);
+    EVP_CIPHER_CTX_set_padding(cipher->ctx, 0);
 
     return SSH_OK;
 }
@@ -515,7 +518,7 @@ static void evp_cipher_encrypt(struct ssh_cipher_struct *cipher,
     int outlen = 0;
     int rc = 0;
 
-    rc = EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, len);
+    rc = EVP_EncryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, len);
     if (rc != 1){
         SSH_LOG(SSH_LOG_WARNING, "EVP_EncryptUpdate failed");
         return;
@@ -533,7 +536,7 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
     int outlen = 0;
     int rc = 0;
 
-    rc = EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, len);
+    rc = EVP_DecryptUpdate(cipher->ctx, (unsigned char *)out, &outlen, (unsigned char *)in, len);
     if (rc != 1){
         SSH_LOG(SSH_LOG_WARNING, "EVP_DecryptUpdate failed");
         return;
@@ -545,7 +548,7 @@ static void evp_cipher_decrypt(struct ssh_cipher_struct *cipher,
 }
 
 static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) {
-    EVP_CIPHER_CTX_cleanup(&cipher->ctx);
+    EVP_CIPHER_CTX_cleanup(cipher->ctx);
 }
 
 #ifndef HAVE_OPENSSL_EVP_AES_CTR
@@ -587,7 +590,11 @@ static void aes_ctr_encrypt(struct ssh_cipher_struct *cipher, void *in, void *ou
    * Same for num, which is being used to store the current offset in blocksize in CTR
    * function.
    */
+# if OPENSSL_VERSION_NUMBER >= 0x10100000L
+  CRYPTO_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num, (block128_f)AES_encrypt);
+# else
   AES_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num);
+# endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
 }
 
 static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){
diff --git a/src/pki_crypto.c b/src/pki_crypto.c
index dabf54b..16cf3d6 100644
--- a/src/pki_crypto.c
+++ b/src/pki_crypto.c
@@ -31,6 +31,7 @@
 #include <openssl/dsa.h>
 #include <openssl/err.h>
 #include <openssl/rsa.h>
+#include "libcrypto-compat.h"
 
 #ifdef HAVE_OPENSSL_EC_H
 #include <openssl/ec.h>
@@ -230,7 +231,10 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
     }
 
     switch (key->type) {
-    case SSH_KEYTYPE_DSS:
+    case SSH_KEYTYPE_DSS: {
+        const BIGNUM *p = NULL, *q = NULL, *g = NULL,
+          *pub_key = NULL, *priv_key = NULL;
+        BIGNUM *np, *nq, *ng, *npub_key, *npriv_key;
         new->dsa = DSA_new();
         if (new->dsa == NULL) {
             goto fail;
@@ -243,36 +247,38 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
          * pub_key  = public key y = g^x
          * priv_key = private key x
          */
-        new->dsa->p = BN_dup(key->dsa->p);
-        if (new->dsa->p == NULL) {
+        DSA_get0_pqg(key->dsa, &p, &q, &g);
+        np = BN_dup(p);
+        nq = BN_dup(q);
+        ng = BN_dup(g);
+        if (np == NULL || nq == NULL || ng == NULL || /* need to set all of them */
+            DSA_set0_pqg(new->dsa, np, nq, ng) == 0) {
+            BN_free(np);
+            BN_free(nq);
+            BN_free(ng);
             goto fail;
         }
 
-        new->dsa->q = BN_dup(key->dsa->q);
-        if (new->dsa->q == NULL) {
-            goto fail;
-        }
-
-        new->dsa->g = BN_dup(key->dsa->g);
-        if (new->dsa->g == NULL) {
-            goto fail;
-        }
-
-        new->dsa->pub_key = BN_dup(key->dsa->pub_key);
-        if (new->dsa->pub_key == NULL) {
+        DSA_get0_key(key->dsa, &pub_key, &priv_key);
+        npub_key = BN_dup(pub_key);
+        if (npub_key == NULL || DSA_set0_key(new->dsa, npub_key, NULL) == 0) {
             goto fail;
         }
 
         if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
-            new->dsa->priv_key = BN_dup(key->dsa->priv_key);
-            if (new->dsa->priv_key == NULL) {
+            npriv_key = BN_dup(priv_key);
+            if (npriv_key == NULL ||
+              DSA_set0_key(new->dsa, NULL, npriv_key) == 0) {
                 goto fail;
             }
         }
 
         break;
+    }
     case SSH_KEYTYPE_RSA:
-    case SSH_KEYTYPE_RSA1:
+    case SSH_KEYTYPE_RSA1: {
+        const BIGNUM *n = NULL, *e = NULL, *d = NULL;
+        BIGNUM *nn, *ne, *nd;
         new->rsa = RSA_new();
         if (new->rsa == NULL) {
             goto fail;
@@ -288,62 +294,58 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
          * dmq1 = d mod (q-1)
          * iqmp = q^-1 mod p
          */
-        new->rsa->n = BN_dup(key->rsa->n);
-        if (new->rsa->n == NULL) {
-            goto fail;
-        }
-
-        new->rsa->e = BN_dup(key->rsa->e);
-        if (new->rsa->e == NULL) {
+        RSA_get0_key(key->rsa, &n, &e, &d);
+        nn = BN_dup(n);
+        ne = BN_dup(e);
+        if (nn == NULL || ne == NULL || /* need to set both n and e */
+            RSA_set0_key(new->rsa, nn, ne, NULL) == 0) {
+            BN_free(nn);
+            BN_free(ne);
             goto fail;
         }
 
         if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
-            new->rsa->d = BN_dup(key->rsa->d);
-            if (new->rsa->d == NULL) {
+            const BIGNUM *p = NULL, *q = NULL, *dmp1 = NULL,
+              *dmq1 = NULL, *iqmp = NULL;
+            BIGNUM *np, *nq, *ndmp1, *ndmq1, *niqmp;
+
+            nd = BN_dup(d);
+            if (nd == NULL || RSA_set0_key(new->rsa, NULL, NULL, nd) == 0) {
                 goto fail;
             }
 
             /* p, q, dmp1, dmq1 and iqmp may be NULL in private keys, but the
              * RSA operations are much faster when these values are available.
              */
-            if (key->rsa->p != NULL) {
-                new->rsa->p = BN_dup(key->rsa->p);
-                if (new->rsa->p == NULL) {
-                    goto fail;
-                }
-            }
-
-            if (key->rsa->q != NULL) {
-                new->rsa->q = BN_dup(key->rsa->q);
-                if (new->rsa->q == NULL) {
-                    goto fail;
-                }
-            }
-
-            if (key->rsa->dmp1 != NULL) {
-                new->rsa->dmp1 = BN_dup(key->rsa->dmp1);
-                if (new->rsa->dmp1 == NULL) {
+            RSA_get0_factors(key->rsa, &p, &q);
+            if (p != NULL && q != NULL) { /* need to set both of them */
+                np = BN_dup(p);
+                nq = BN_dup(q);
+                if (np == NULL || nq == NULL ||
+                    RSA_set0_factors(new->rsa, np, nq) == 0) {
+                    BN_free(np);
+                    BN_free(nq);
                     goto fail;
                 }
             }
 
-            if (key->rsa->dmq1 != NULL) {
-                new->rsa->dmq1 = BN_dup(key->rsa->dmq1);
-                if (new->rsa->dmq1 == NULL) {
-                    goto fail;
-                }
-            }
-
-            if (key->rsa->iqmp != NULL) {
-                new->rsa->iqmp = BN_dup(key->rsa->iqmp);
-                if (new->rsa->iqmp == NULL) {
+            RSA_get0_crt_params(key->rsa, &dmp1, &dmq1, &iqmp);
+            if (dmp1 != NULL || dmq1 != NULL || iqmp != NULL) {
+                ndmp1 = BN_dup(dmp1);
+                ndmq1 = BN_dup(dmq1);
+                niqmp = BN_dup(iqmp);
+                if (ndmp1 == NULL || ndmq1 == NULL || niqmp == NULL ||
+                  RSA_set0_crt_params(new->rsa, ndmp1, ndmq1, niqmp) == 0) {
+                    BN_free(ndmp1);
+                    BN_free(ndmq1);
+                    BN_free(niqmp);
                     goto fail;
                 }
             }
         }
 
         break;
+    }
     case SSH_KEYTYPE_ECDSA:
 #ifdef HAVE_OPENSSL_ECC
         new->ecdsa_nid = key->ecdsa_nid;
@@ -466,51 +468,64 @@ int pki_key_compare(const ssh_key k1,
                     enum ssh_keycmp_e what)
 {
     switch (k1->type) {
-        case SSH_KEYTYPE_DSS:
+        case SSH_KEYTYPE_DSS: {
+            const BIGNUM *p1, *p2, *q1, *q2, *g1, *g2,
+                *pub_key1, *pub_key2, *priv_key1, *priv_key2;
             if (DSA_size(k1->dsa) != DSA_size(k2->dsa)) {
                 return 1;
             }
-            if (bignum_cmp(k1->dsa->p, k2->dsa->p) != 0) {
+            DSA_get0_pqg(k1->dsa, &p1, &q1, &g1);
+            DSA_get0_pqg(k2->dsa, &p2, &q2, &g2);
+            if (bignum_cmp(p1, p2) != 0) {
                 return 1;
             }
-            if (bignum_cmp(k1->dsa->q, k2->dsa->q) != 0) {
+            if (bignum_cmp(q1, q2) != 0) {
                 return 1;
             }
-            if (bignum_cmp(k1->dsa->g, k2->dsa->g) != 0) {
+            if (bignum_cmp(g1, g2) != 0) {
                 return 1;
             }
-            if (bignum_cmp(k1->dsa->pub_key, k2->dsa->pub_key) != 0) {
+            DSA_get0_key(k1->dsa, &pub_key1, &priv_key1);
+            DSA_get0_key(k2->dsa, &pub_key2, &priv_key2);
+            if (bignum_cmp(pub_key1, pub_key2) != 0) {
                 return 1;
             }
 
             if (what == SSH_KEY_CMP_PRIVATE) {
-                if (bignum_cmp(k1->dsa->priv_key, k2->dsa->priv_key) != 0) {
+                if (bignum_cmp(priv_key1, priv_key2) != 0) {
                     return 1;
                 }
             }
             break;
+        }
         case SSH_KEYTYPE_RSA:
-        case SSH_KEYTYPE_RSA1:
+        case SSH_KEYTYPE_RSA1: {
+            const BIGNUM *e1, *e2, *n1, *n2, *p1, *p2, *q1, *q2;
             if (RSA_size(k1->rsa) != RSA_size(k2->rsa)) {
                 return 1;
             }
-            if (bignum_cmp(k1->rsa->e, k2->rsa->e) != 0) {
+            RSA_get0_key(k1->rsa, &n1, &e1, NULL);
+            RSA_get0_key(k2->rsa, &n2, &e2, NULL);
+            if (bignum_cmp(e1, e2) != 0) {
                 return 1;
             }
-            if (bignum_cmp(k1->rsa->n, k2->rsa->n) != 0) {
+            if (bignum_cmp(n1, n2) != 0) {
                 return 1;
             }
 
             if (what == SSH_KEY_CMP_PRIVATE) {
-                if (bignum_cmp(k1->rsa->p, k2->rsa->p) != 0) {
+                RSA_get0_factors(k1->rsa, &p1, &q1);
+                RSA_get0_factors(k2->rsa, &p2, &q2);
+                if (bignum_cmp(p1, p2) != 0) {
                     return 1;
                 }
 
-                if (bignum_cmp(k1->rsa->q, k2->rsa->q) != 0) {
+                if (bignum_cmp(q1, q2) != 0) {
                     return 1;
                 }
             }
             break;
+        }
         case SSH_KEYTYPE_ECDSA:
 #ifdef HAVE_OPENSSL_ECC
             {
@@ -826,19 +841,23 @@ int pki_pubkey_build_dss(ssh_key key,
                          ssh_string q,
                          ssh_string g,
                          ssh_string pubkey) {
+    BIGNUM *bp, *bq, *bg, *bpub_key;
+
     key->dsa = DSA_new();
     if (key->dsa == NULL) {
         return SSH_ERROR;
     }
 
-    key->dsa->p = ssh_make_string_bn(p);
-    key->dsa->q = ssh_make_string_bn(q);
-    key->dsa->g = ssh_make_string_bn(g);
-    key->dsa->pub_key = ssh_make_string_bn(pubkey);
-    if (key->dsa->p == NULL ||
-        key->dsa->q == NULL ||
-        key->dsa->g == NULL ||
-        key->dsa->pub_key == NULL) {
+    bp = ssh_make_string_bn(p);
+    bq = ssh_make_string_bn(q);
+    bg = ssh_make_string_bn(g);
+    bpub_key = ssh_make_string_bn(pubkey);
+    if (bp == NULL ||
+        bq == NULL ||
+        bg == NULL ||
+        bpub_key == NULL ||
+        DSA_set0_pqg(key->dsa, bp, bq, bg) == 0 ||
+        DSA_set0_key(key->dsa, bpub_key, NULL) == 0) {
         DSA_free(key->dsa);
         return SSH_ERROR;
     }
@@ -849,15 +868,18 @@ int pki_pubkey_build_dss(ssh_key key,
 int pki_pubkey_build_rsa(ssh_key key,
                          ssh_string e,
                          ssh_string n) {
+    BIGNUM *be, *bn;
+
     key->rsa = RSA_new();
     if (key->rsa == NULL) {
         return SSH_ERROR;
     }
 
-    key->rsa->e = ssh_make_string_bn(e);
-    key->rsa->n = ssh_make_string_bn(n);
-    if (key->rsa->e == NULL ||
-        key->rsa->n == NULL) {
+    be = ssh_make_string_bn(e);
+    bn = ssh_make_string_bn(n);
+    if (be == NULL ||
+        bn == NULL ||
+        RSA_set0_key(key->rsa, bn, be, NULL) == 0) {
         RSA_free(key->rsa);
         return SSH_ERROR;
     }
@@ -905,23 +927,26 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
     }
 
     switch (key->type) {
-        case SSH_KEYTYPE_DSS:
-            p = ssh_make_bignum_string(key->dsa->p);
+        case SSH_KEYTYPE_DSS: {
+            const BIGNUM *bp, *bq, *bg, *bpub_key;
+            DSA_get0_pqg(key->dsa, &bp, &bq, &bg);
+            p = ssh_make_bignum_string((BIGNUM *)bp);
             if (p == NULL) {
                 goto fail;
             }
 
-            q = ssh_make_bignum_string(key->dsa->q);
+            q = ssh_make_bignum_string((BIGNUM *)bq);
             if (q == NULL) {
                 goto fail;
             }
 
-            g = ssh_make_bignum_string(key->dsa->g);
+            g = ssh_make_bignum_string((BIGNUM *)bg);
             if (g == NULL) {
                 goto fail;
             }
 
-            n = ssh_make_bignum_string(key->dsa->pub_key);
+            DSA_get0_key(key->dsa, &bpub_key, NULL);
+            n = ssh_make_bignum_string((BIGNUM *)bpub_key);
             if (n == NULL) {
                 goto fail;
             }
@@ -953,14 +978,17 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
             n = NULL;
 
             break;
+        }
         case SSH_KEYTYPE_RSA:
-        case SSH_KEYTYPE_RSA1:
-            e = ssh_make_bignum_string(key->rsa->e);
+        case SSH_KEYTYPE_RSA1: {
+            const BIGNUM *be, *bn;
+            RSA_get0_key(key->rsa, &bn, &be, NULL);
+            e = ssh_make_bignum_string((BIGNUM *)be);
             if (e == NULL) {
                 goto fail;
             }
 
-            n = ssh_make_bignum_string(key->rsa->n);
+            n = ssh_make_bignum_string((BIGNUM *)bn);
             if (n == NULL) {
                 goto fail;
             }
@@ -980,6 +1008,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
             n = NULL;
 
             break;
+        }
         case SSH_KEYTYPE_ECDSA:
 #ifdef HAVE_OPENSSL_ECC
             rc = ssh_buffer_reinit(buffer);
@@ -1082,13 +1111,15 @@ int pki_export_pubkey_rsa1(const ssh_key key,
     char *e;
     char *n;
     int rsa_size = RSA_size(key->rsa);
+    const BIGNUM *be, *bn;
 
-    e = bignum_bn2dec(key->rsa->e);
+    RSA_get0_key(key->rsa, &bn, &be, NULL);
+    e = bignum_bn2dec(be);
     if (e == NULL) {
         return SSH_ERROR;
     }
 
-    n = bignum_bn2dec(key->rsa->n);
+    n = bignum_bn2dec(bn);
     if (n == NULL) {
         OPENSSL_free(e);
         return SSH_ERROR;
@@ -1153,6 +1184,7 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
 {
     char buffer[40] = { 0 };
     ssh_string sig_blob = NULL;
+    const BIGNUM *pr, *ps;
 
     ssh_string r;
     int r_len, r_offset_in, r_offset_out;
@@ -1160,12 +1192,13 @@ static ssh_string pki_dsa_signature_to_blob(const ssh_signature sig)
     ssh_string s;
     int s_len, s_offset_in, s_offset_out;
 
-    r = ssh_make_bignum_string(sig->dsa_sig->r);
+    DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
+    r = ssh_make_bignum_string((BIGNUM *)pr);
     if (r == NULL) {
         return NULL;
     }
 
-    s = ssh_make_bignum_string(sig->dsa_sig->s);
+    s = ssh_make_bignum_string((BIGNUM *)ps);
     if (s == NULL) {
         ssh_string_free(r);
         return NULL;
@@ -1218,13 +1251,15 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
             ssh_string s;
             ssh_buffer b;
             int rc;
+            const BIGNUM *pr, *ps;
 
             b = ssh_buffer_new();
             if (b == NULL) {
                 return NULL;
             }
 
-            r = ssh_make_bignum_string(sig->ecdsa_sig->r);
+            ECDSA_SIG_get0(sig->ecdsa_sig, &pr, &ps);
+            r = ssh_make_bignum_string((BIGNUM *)pr);
             if (r == NULL) {
                 ssh_buffer_free(b);
                 return NULL;
@@ -1236,7 +1271,7 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
                 return NULL;
             }
 
-            s = ssh_make_bignum_string(sig->ecdsa_sig->s);
+            s = ssh_make_bignum_string((BIGNUM *)ps);
             if (s == NULL) {
                 ssh_buffer_free(b);
                 return NULL;
@@ -1345,6 +1380,7 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
     ssh_string s;
     size_t len;
     int rc;
+    BIGNUM *pr = NULL, *ps = NULL;
 
     sig = ssh_signature_new();
     if (sig == NULL) {
@@ -1385,9 +1421,9 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
             }
             ssh_string_fill(r, ssh_string_data(sig_blob), 20);
 
-            sig->dsa_sig->r = ssh_make_string_bn(r);
+            pr = ssh_make_string_bn(r);
             ssh_string_free(r);
-            if (sig->dsa_sig->r == NULL) {
+            if (pr == NULL) {
                 ssh_signature_free(sig);
                 return NULL;
             }
@@ -1399,9 +1435,9 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
             }
             ssh_string_fill(s, (char *)ssh_string_data(sig_blob) + 20, 20);
 
-            sig->dsa_sig->s = ssh_make_string_bn(s);
+            ps = ssh_make_string_bn(s);
             ssh_string_free(s);
-            if (sig->dsa_sig->s == NULL) {
+            if (ps == NULL || DSA_SIG_set0(sig->dsa_sig, pr, ps) == 0) {
                 ssh_signature_free(sig);
                 return NULL;
             }
@@ -1449,10 +1485,10 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
                 ssh_print_hexa("r", ssh_string_data(r), ssh_string_len(r));
 #endif
 
-                ssh_make_string_bn_inplace(r, sig->ecdsa_sig->r);
+                ssh_make_string_bn_inplace(r, pr);
                 ssh_string_burn(r);
                 ssh_string_free(r);
-                if (sig->ecdsa_sig->r == NULL) {
+                if (pr == NULL) {
                     ssh_buffer_free(b);
                     ssh_signature_free(sig);
                     return NULL;
@@ -1470,10 +1506,10 @@ ssh_signature pki_signature_from_blob(const ssh_key pubkey,
                 ssh_print_hexa("s", ssh_string_data(s), ssh_string_len(s));
 #endif
 
-                ssh_make_string_bn_inplace(s, sig->ecdsa_sig->s);
+                ssh_make_string_bn_inplace(s, ps);
                 ssh_string_burn(s);
                 ssh_string_free(s);
-                if (sig->ecdsa_sig->s == NULL) {
+                if (ps == NULL || ECDSA_SIG_set0(sig->ecdsa_sig, pr, ps) == 0) {
                     ssh_signature_free(sig);
                     return NULL;
                 }
@@ -1601,8 +1637,12 @@ ssh_signature pki_do_sign(const ssh_key privkey,
             }
 
 #ifdef DEBUG_CRYPTO
-            ssh_print_bignum("r", sig->dsa_sig->r);
-            ssh_print_bignum("s", sig->dsa_sig->s);
+            {
+                const BIGNUM *pr, *ps;
+                DSA_SIG_get0(sig->dsa_sig, &pr, &ps);
+                ssh_print_bignum("r", pr);
+                ssh_print_bignum("s", ps);
+            }
 #endif
 
             break;
@@ -1624,8 +1664,12 @@ ssh_signature pki_do_sign(const ssh_key privkey,
             }
 
 # ifdef DEBUG_CRYPTO
-            ssh_print_bignum("r", sig->ecdsa_sig->r);
-            ssh_print_bignum("s", sig->ecdsa_sig->s);
+            {
+                const BIGNUM *pr, *ps;
+                ECDSA_SIG_get0(sig->dsa_sig, &pr, &ps);
+                ssh_print_bignum("r", pr);
+                ssh_print_bignum("s", ps);
+            }
 # endif /* DEBUG_CRYPTO */
 
             break;
-- 
2.7.4


Follow-Ups:
Re: Build libssh against openssl 1.1.0Aris Adamantiadis <aris@xxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org