All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Seiderer <ps.report@gmx.net>
To: buildroot@busybox.net
Subject: [Buildroot] [RFC v2 2/3] openssh: add patch to fix openssl-1.1.0h compile
Date: Thu,  3 May 2018 23:24:35 +0200	[thread overview]
Message-ID: <20180503212436.2521-2-ps.report@gmx.net> (raw)
In-Reply-To: <20180503212436.2521-1-ps.report@gmx.net>

Signed-off-by: Peter Seiderer <ps.report@gmx.net>
---
Changes v1 -> v2:
  - no changes
---
 ...penSSH-7.7p1-to-compile-with-OpenSSL-1.1..patch | 2003 ++++++++++++++++++++
 1 file changed, 2003 insertions(+)
 create mode 100644 package/openssh/0003-Patch-for-OpenSSH-7.7p1-to-compile-with-OpenSSL-1.1..patch

diff --git a/package/openssh/0003-Patch-for-OpenSSH-7.7p1-to-compile-with-OpenSSL-1.1..patch b/package/openssh/0003-Patch-for-OpenSSH-7.7p1-to-compile-with-OpenSSL-1.1..patch
new file mode 100644
index 0000000000..fa56168347
--- /dev/null
+++ b/package/openssh/0003-Patch-for-OpenSSH-7.7p1-to-compile-with-OpenSSL-1.1..patch
@@ -0,0 +1,2003 @@
+From 3dc11277f4d8164258bdf60bd87f3d5edf586d87 Mon Sep 17 00:00:00 2001
+From: Peter Seiderer <ps.report@gmx.net>
+Date: Tue, 17 Apr 2018 20:19:24 +0200
+Subject: [PATCH] Patch for OpenSSH-7.7p1 to compile with OpenSSL-1.1.0
+
+See [1] for more info and original source, concrete patch taken
+from [2].
+
+[1] http://vega.pgw.jp/~kabe/vsd/patch/openssh-7.7p1-openssl-1.1.0.patch.html
+[2] https://git.archlinux.org/svntogit/packages.git/plain/trunk/openssl-1.1.0.patch?h=packages/openssh
+
+Signed-off-by: Peter Seiderer <ps.report@gmx.net>
+---
+ auth-pam.c                             |   4 +
+ cipher.c                               |  18 +-
+ cipher.h                               |  11 +
+ dh.c                                   |  62 ++--
+ dh.h                                   |   2 +-
+ digest-openssl.c                       |  19 +-
+ kexdhc.c                               |  20 +-
+ kexdhs.c                               |  18 +-
+ kexgexc.c                              |  26 +-
+ kexgexs.c                              |  32 +-
+ monitor.c                              |   6 +-
+ openbsd-compat/openssl-compat.c        |   1 -
+ regress/unittests/sshkey/test_file.c   |  22 +-
+ regress/unittests/sshkey/test_sshkey.c |  82 +++--
+ ssh-dss.c                              |  27 +-
+ ssh-ecdsa.c                            |  29 +-
+ ssh-keygen.c                           |  84 ++++-
+ ssh-pkcs11-client.c                    |  11 +-
+ ssh-pkcs11.c                           |  47 ++-
+ ssh-rsa.c                              |  30 +-
+ sshkey.c                               | 562 +++++++++++++++++++++++++++------
+ 21 files changed, 877 insertions(+), 236 deletions(-)
+
+diff --git a/auth-pam.c b/auth-pam.c
+index bd0c1b8..60ede8f 100644
+--- a/auth-pam.c
++++ b/auth-pam.c
+@@ -128,6 +128,10 @@ extern u_int utmp_len;
+ typedef pthread_t sp_pthread_t;
+ #else
+ typedef pid_t sp_pthread_t;
++# define pthread_create(a, b, c, d)    _ssh_compat_pthread_create(a, b, c, d)
++# define pthread_exit(a)               _ssh_compat_pthread_exit(a)
++# define pthread_cancel(a)             _ssh_compat_pthread_cancel(a)
++# define pthread_join(a, b)            _ssh_compat_pthread_join(a, b)
+ #endif
+ 
+ struct pam_ctxt {
+diff --git a/cipher.c b/cipher.c
+index 5787636..c337331 100644
+--- a/cipher.c
++++ b/cipher.c
+@@ -297,7 +297,10 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
+ 			goto out;
+ 		}
+ 	}
+-	if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
++	/* in OpenSSL 1.1.0, EVP_CipherInit clears all previous setups;
++	   use EVP_CipherInit_ex for augmenting */
++	if (EVP_CipherInit_ex(cc->evp, NULL, NULL, (u_char *)key, NULL, -1) == 0)
++	{
+ 		ret = SSH_ERR_LIBCRYPTO_ERROR;
+ 		goto out;
+ 	}
+@@ -483,7 +486,7 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
+ 		   len, iv))
+ 		       return SSH_ERR_LIBCRYPTO_ERROR;
+ 	} else
+-		memcpy(iv, cc->evp->iv, len);
++		memcpy(iv, EVP_CIPHER_CTX_iv(cc->evp), len);
+ #endif
+ 	return 0;
+ }
+@@ -517,14 +520,19 @@ cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
+ 		    EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
+ 			return SSH_ERR_LIBCRYPTO_ERROR;
+ 	} else
+-		memcpy(cc->evp->iv, iv, evplen);
++		memcpy(EVP_CIPHER_CTX_iv(cc->evp), iv, evplen);
+ #endif
+ 	return 0;
+ }
+ 
+ #ifdef WITH_OPENSSL
+-#define EVP_X_STATE(evp)	(evp)->cipher_data
+-#define EVP_X_STATE_LEN(evp)	(evp)->cipher->ctx_size
++# if OPENSSL_VERSION_NUMBER >= 0x10100000UL
++#define EVP_X_STATE(evp)	EVP_CIPHER_CTX_get_cipher_data(evp)
++#define EVP_X_STATE_LEN(evp)	EVP_CIPHER_impl_ctx_size(EVP_CIPHER_CTX_cipher(evp))
++# else
++#define EVP_X_STATE(evp)	(evp).cipher_data
++#define EVP_X_STATE_LEN(evp)	(evp).cipher->ctx_size
++# endif
+ #endif
+ 
+ int
+diff --git a/cipher.h b/cipher.h
+index dc7ecf1..268f60a 100644
+--- a/cipher.h
++++ b/cipher.h
+@@ -46,7 +46,18 @@
+ #define CIPHER_DECRYPT		0
+ 
+ struct sshcipher;
++#if 0
++struct sshcipher_ctx {
++	int	plaintext;
++	int	encrypt;
++	EVP_CIPHER_CTX *evp;
++	struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
++	struct aesctr_ctx ac_ctx; /* XXX union with evp? */
++	const struct sshcipher *cipher;
++};
++#else
+ struct sshcipher_ctx;
++#endif
+ 
+ const struct sshcipher *cipher_by_name(const char *);
+ const char *cipher_warning_message(const struct sshcipher_ctx *);
+diff --git a/dh.c b/dh.c
+index 46afba0..d3ae531 100644
+--- a/dh.c
++++ b/dh.c
+@@ -211,14 +211,15 @@ choose_dh(int min, int wantbits, int max)
+ /* diffie-hellman-groupN-sha1 */
+ 
+ int
+-dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
++dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
+ {
+ 	int i;
+ 	int n = BN_num_bits(dh_pub);
+ 	int bits_set = 0;
+ 	BIGNUM *tmp;
++	const BIGNUM *p;
+ 
+-	if (dh_pub->neg) {
++	if (BN_is_negative(dh_pub)) {
+ 		logit("invalid public DH value: negative");
+ 		return 0;
+ 	}
+@@ -231,7 +232,8 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
+ 		error("%s: BN_new failed", __func__);
+ 		return 0;
+ 	}
+-	if (!BN_sub(tmp, dh->p, BN_value_one()) ||
++	DH_get0_pqg(dh, &p, NULL, NULL);
++	if (!BN_sub(tmp, p, BN_value_one()) ||
+ 	    BN_cmp(dh_pub, tmp) != -1) {		/* pub_exp > p-2 */
+ 		BN_clear_free(tmp);
+ 		logit("invalid public DH value: >= p-1");
+@@ -242,14 +244,14 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub)
+ 	for (i = 0; i <= n; i++)
+ 		if (BN_is_bit_set(dh_pub, i))
+ 			bits_set++;
+-	debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p));
++	debug2("bits set: %d/%d", bits_set, BN_num_bits(p));
+ 
+ 	/*
+ 	 * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial
+ 	 */
+ 	if (bits_set < 4) {
+ 		logit("invalid public DH value (%d/%d)",
+-		   bits_set, BN_num_bits(dh->p));
++		   bits_set, BN_num_bits(p));
+ 		return 0;
+ 	}
+ 	return 1;
+@@ -259,9 +261,13 @@ int
+ dh_gen_key(DH *dh, int need)
+ {
+ 	int pbits;
++	const BIGNUM *p, *pub_key;
++	BIGNUM *priv_key;
+ 
+-	if (need < 0 || dh->p == NULL ||
+-	    (pbits = BN_num_bits(dh->p)) <= 0 ||
++	DH_get0_pqg(dh, &p, NULL, NULL);
++
++	if (need < 0 || p == NULL ||
++	    (pbits = BN_num_bits(p)) <= 0 ||
+ 	    need > INT_MAX / 2 || 2 * need > pbits)
+ 		return SSH_ERR_INVALID_ARGUMENT;
+ 	if (need < 256)
+@@ -270,10 +276,13 @@ dh_gen_key(DH *dh, int need)
+ 	 * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
+ 	 * so double requested need here.
+ 	 */
+-	dh->length = MINIMUM(need * 2, pbits - 1);
+-	if (DH_generate_key(dh) == 0 ||
+-	    !dh_pub_is_valid(dh, dh->pub_key)) {
+-		BN_clear_free(dh->priv_key);
++	DH_set_length(dh, MIN(need * 2, pbits - 1));
++	if (DH_generate_key(dh) == 0) {
++		return SSH_ERR_LIBCRYPTO_ERROR;
++	}
++	DH_get0_key(dh, &pub_key, &priv_key);
++	if (!dh_pub_is_valid(dh, pub_key)) {
++		BN_clear(priv_key);
+ 		return SSH_ERR_LIBCRYPTO_ERROR;
+ 	}
+ 	return 0;
+@@ -282,16 +291,27 @@ dh_gen_key(DH *dh, int need)
+ DH *
+ dh_new_group_asc(const char *gen, const char *modulus)
+ {
+-	DH *dh;
+-
+-	if ((dh = DH_new()) == NULL)
+-		return NULL;
+-	if (BN_hex2bn(&dh->p, modulus) == 0 ||
+-	    BN_hex2bn(&dh->g, gen) == 0) {
+-		DH_free(dh);
+-		return NULL;
++	DH *dh = NULL;
++	BIGNUM *p=NULL, *g=NULL;
++
++	if ((dh = DH_new()) == NULL ||
++	    (p = BN_new()) == NULL ||
++	    (g = BN_new()) == NULL)
++		goto null;
++	if (BN_hex2bn(&p, modulus) == 0 ||
++	    BN_hex2bn(&g, gen) == 0) {
++		goto null;
+ 	}
++	if (DH_set0_pqg(dh, p, NULL, g) == 0) {
++		goto null;
++	}
++	p = g = NULL;
+ 	return (dh);
++null:
++	BN_free(p);
++	BN_free(g);
++	DH_free(dh);
++	return NULL;
+ }
+ 
+ /*
+@@ -306,8 +326,8 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulus)
+ 
+ 	if ((dh = DH_new()) == NULL)
+ 		return NULL;
+-	dh->p = modulus;
+-	dh->g = gen;
++	if (DH_set0_pqg(dh, modulus, NULL, gen) == 0)
++		return NULL;
+ 
+ 	return (dh);
+ }
+diff --git a/dh.h b/dh.h
+index bcd485c..344b29e 100644
+--- a/dh.h
++++ b/dh.h
+@@ -42,7 +42,7 @@ DH	*dh_new_group18(void);
+ DH	*dh_new_group_fallback(int);
+ 
+ int	 dh_gen_key(DH *, int);
+-int	 dh_pub_is_valid(DH *, BIGNUM *);
++int	 dh_pub_is_valid(const DH *, const BIGNUM *);
+ 
+ u_int	 dh_estimate(int);
+ 
+diff --git a/digest-openssl.c b/digest-openssl.c
+index 2770999..c24cf34 100644
+--- a/digest-openssl.c
++++ b/digest-openssl.c
+@@ -43,7 +43,7 @@
+ 
+ struct ssh_digest_ctx {
+ 	int alg;
+-	EVP_MD_CTX mdctx;
++	EVP_MD_CTX *mdctx;
+ };
+ 
+ struct ssh_digest {
+@@ -106,20 +106,21 @@ ssh_digest_bytes(int alg)
+ size_t
+ ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
+ {
+-	return EVP_MD_CTX_block_size(&ctx->mdctx);
++	return EVP_MD_CTX_block_size(ctx->mdctx);
+ }
+ 
+ struct ssh_digest_ctx *
+ ssh_digest_start(int alg)
+ {
+ 	const struct ssh_digest *digest = ssh_digest_by_alg(alg);
+-	struct ssh_digest_ctx *ret;
++	struct ssh_digest_ctx *ret = NULL;
+ 
+ 	if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL))
+ 		return NULL;
+ 	ret->alg = alg;
+-	EVP_MD_CTX_init(&ret->mdctx);
+-	if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) {
++	if ((ret->mdctx = EVP_MD_CTX_new()) == NULL ||
++	    EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) {
++		EVP_MD_CTX_free(ret->mdctx);
+ 		free(ret);
+ 		return NULL;
+ 	}
+@@ -132,7 +133,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
+ 	if (from->alg != to->alg)
+ 		return SSH_ERR_INVALID_ARGUMENT;
+ 	/* we have bcopy-style order while openssl has memcpy-style */
+-	if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
++	if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx))
+ 		return SSH_ERR_LIBCRYPTO_ERROR;
+ 	return 0;
+ }
+@@ -140,7 +141,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
+ int
+ ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
+ {
+-	if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1)
++	if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1)
+ 		return SSH_ERR_LIBCRYPTO_ERROR;
+ 	return 0;
+ }
+@@ -161,7 +162,7 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
+ 		return SSH_ERR_INVALID_ARGUMENT;
+ 	if (dlen < digest->digest_len) /* No truncation allowed */
+ 		return SSH_ERR_INVALID_ARGUMENT;
+-	if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1)
++	if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1)
+ 		return SSH_ERR_LIBCRYPTO_ERROR;
+ 	if (l != digest->digest_len) /* sanity */
+ 		return SSH_ERR_INTERNAL_ERROR;
+@@ -172,7 +173,7 @@ void
+ ssh_digest_free(struct ssh_digest_ctx *ctx)
+ {
+ 	if (ctx != NULL) {
+-		EVP_MD_CTX_cleanup(&ctx->mdctx);
++		EVP_MD_CTX_free(ctx->mdctx);
+ 		explicit_bzero(ctx, sizeof(*ctx));
+ 		free(ctx);
+ 	}
+diff --git a/kexdhc.c b/kexdhc.c
+index 9a9f1ea..e5ea825 100644
+--- a/kexdhc.c
++++ b/kexdhc.c
+@@ -81,11 +81,16 @@ kexdh_client(struct ssh *ssh)
+ 		goto out;
+ 	}
+ 	debug("sending SSH2_MSG_KEXDH_INIT");
+-	if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 ||
+-	    (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 ||
+-	    (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||
++	{
++	const BIGNUM *pub_key;
++	if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
++		goto out;
++	DH_get0_key(kex->dh, &pub_key, NULL);
++	if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 ||
++	    (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
+ 	    (r = sshpkt_send(ssh)) != 0)
+ 		goto out;
++	}
+ #ifdef DEBUG_KEXDH
+ 	DHparams_print_fp(stderr, kex->dh);
+ 	fprintf(stderr, "pub= ");
+@@ -169,6 +174,9 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
+ 
+ 	/* calc and verify H */
+ 	hashlen = sizeof(hash);
++	{
++	const BIGNUM *pub_key;
++	DH_get0_key(kex->dh, &pub_key, NULL);
+ 	if ((r = kex_dh_hash(
+ 	    kex->hash_alg,
+ 	    kex->client_version_string,
+@@ -176,11 +184,13 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
+ 	    sshbuf_ptr(kex->my), sshbuf_len(kex->my),
+ 	    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
+ 	    server_host_key_blob, sbloblen,
+-	    kex->dh->pub_key,
++	    pub_key,
+ 	    dh_server_pub,
+ 	    shared_secret,
+-	    hash, &hashlen)) != 0)
++	    hash, &hashlen)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
+ 	    kex->hostkey_alg, ssh->compat)) != 0)
+diff --git a/kexdhs.c b/kexdhs.c
+index da8f4c4..d5b57b1 100644
+--- a/kexdhs.c
++++ b/kexdhs.c
+@@ -163,6 +163,9 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
+ 		goto out;
+ 	/* calc H */
+ 	hashlen = sizeof(hash);
++	{
++	const BIGNUM *pub_key;
++	DH_get0_key(kex->dh, &pub_key, NULL);
+ 	if ((r = kex_dh_hash(
+ 	    kex->hash_alg,
+ 	    kex->client_version_string,
+@@ -171,10 +174,12 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
+ 	    sshbuf_ptr(kex->my), sshbuf_len(kex->my),
+ 	    server_host_key_blob, sbloblen,
+ 	    dh_client_pub,
+-	    kex->dh->pub_key,
++	    pub_key,
+ 	    shared_secret,
+-	    hash, &hashlen)) != 0)
++	    hash, &hashlen)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	/* save session id := H */
+ 	if (kex->session_id == NULL) {
+@@ -195,12 +200,17 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
+ 	/* destroy_sensitive_data(); */
+ 
+ 	/* send server hostkey, DH pubkey 'f' and singed H */
++	{
++	const BIGNUM *pub_key;
++	DH_get0_key(kex->dh, &pub_key, NULL);
+ 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 ||
+ 	    (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
+-	    (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||	/* f */
++	    (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||	/* f */
+ 	    (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
+-	    (r = sshpkt_send(ssh)) != 0)
++	    (r = sshpkt_send(ssh)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+ 		r = kex_send_newkeys(ssh);
+diff --git a/kexgexc.c b/kexgexc.c
+index 762a9a3..c30d8c3 100644
+--- a/kexgexc.c
++++ b/kexgexc.c
+@@ -118,11 +118,17 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
+ 	p = g = NULL; /* belong to kex->dh now */
+ 
+ 	/* generate and send 'e', client DH public key */
+-	if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 ||
+-	    (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
+-	    (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||
+-	    (r = sshpkt_send(ssh)) != 0)
++	{
++	const BIGNUM *pub_key;
++	if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
++		goto out;
++	DH_get0_key(kex->dh, &pub_key, NULL);
++	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 ||
++	    (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
++	    (r = sshpkt_send(ssh)) != 0) {
+ 		goto out;
++	}
++	}
+ 	debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
+ #ifdef DEBUG_KEXDH
+ 	DHparams_print_fp(stderr, kex->dh);
+@@ -212,6 +218,10 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
+ 
+ 	/* calc and verify H */
+ 	hashlen = sizeof(hash);
++	{
++	const BIGNUM *p, *g, *pub_key;
++	DH_get0_pqg(kex->dh, &p, NULL, &g);
++	DH_get0_key(kex->dh, &pub_key, NULL);
+ 	if ((r = kexgex_hash(
+ 	    kex->hash_alg,
+ 	    kex->client_version_string,
+@@ -220,12 +230,14 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
+ 	    sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
+ 	    server_host_key_blob, sbloblen,
+ 	    kex->min, kex->nbits, kex->max,
+-	    kex->dh->p, kex->dh->g,
+-	    kex->dh->pub_key,
++	    p, g,
++	    pub_key,
+ 	    dh_server_pub,
+ 	    shared_secret,
+-	    hash, &hashlen)) != 0)
++	    hash, &hashlen)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	if ((r = sshkey_verify(server_host_key, signature, slen, hash,
+ 	    hashlen, kex->hostkey_alg, ssh->compat)) != 0)
+diff --git a/kexgexs.c b/kexgexs.c
+index d7b48ea..992a390 100644
+--- a/kexgexs.c
++++ b/kexgexs.c
+@@ -101,11 +101,16 @@ input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
+ 		goto out;
+ 	}
+ 	debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
++	{
++	const BIGNUM *p, *g;
++	DH_get0_pqg(kex->dh, &p, NULL, &g);
+ 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 ||
+-	    (r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 ||
+-	    (r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 ||
+-	    (r = sshpkt_send(ssh)) != 0)
++	    (r = sshpkt_put_bignum2(ssh, p)) != 0 ||
++	    (r = sshpkt_put_bignum2(ssh, g)) != 0 ||
++	    (r = sshpkt_send(ssh)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	/* Compute our exchange value in parallel with the client */
+ 	if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
+@@ -191,6 +196,10 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
+ 		goto out;
+ 	/* calc H */
+ 	hashlen = sizeof(hash);
++	{
++	const BIGNUM *p, *g, *pub_key;
++	DH_get0_pqg(kex->dh, &p, NULL, &g);
++	DH_get0_key(kex->dh, &pub_key, NULL);
+ 	if ((r = kexgex_hash(
+ 	    kex->hash_alg,
+ 	    kex->client_version_string,
+@@ -199,12 +208,14 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
+ 	    sshbuf_ptr(kex->my), sshbuf_len(kex->my),
+ 	    server_host_key_blob, sbloblen,
+ 	    kex->min, kex->nbits, kex->max,
+-	    kex->dh->p, kex->dh->g,
++	    p, g,
+ 	    dh_client_pub,
+-	    kex->dh->pub_key,
++	    pub_key,
+ 	    shared_secret,
+-	    hash, &hashlen)) != 0)
++	    hash, &hashlen)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	/* save session id := H */
+ 	if (kex->session_id == NULL) {
+@@ -225,12 +236,17 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
+ 	/* destroy_sensitive_data(); */
+ 
+ 	/* send server hostkey, DH pubkey 'f' and singed H */
++	{
++	const BIGNUM *pub_key;
++	DH_get0_key(kex->dh, &pub_key, NULL);
+ 	if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 ||
+ 	    (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 ||
+-	    (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 ||     /* f */
++	    (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||     /* f */
+ 	    (r = sshpkt_put_string(ssh, signature, slen)) != 0 ||
+-	    (r = sshpkt_send(ssh)) != 0)
++	    (r = sshpkt_send(ssh)) != 0) {
+ 		goto out;
++	}
++	}
+ 
+ 	if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0)
+ 		r = kex_send_newkeys(ssh);
+diff --git a/monitor.c b/monitor.c
+index c68e1b0..64d5475 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -595,10 +595,12 @@ mm_answer_moduli(int sock, Buffer *m)
+ 		buffer_put_char(m, 0);
+ 		return (0);
+ 	} else {
++		const BIGNUM *p, *g;
++		DH_get0_pqg(dh, &p, NULL, &g);
+ 		/* Send first bignum */
+ 		buffer_put_char(m, 1);
+-		buffer_put_bignum2(m, dh->p);
+-		buffer_put_bignum2(m, dh->g);
++		buffer_put_bignum2(m, p);
++		buffer_put_bignum2(m, g);
+ 
+ 		DH_free(dh);
+ 	}
+diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
+index 259fccb..02bf3e1 100644
+--- a/openbsd-compat/openssl-compat.c
++++ b/openbsd-compat/openssl-compat.c
+@@ -75,7 +75,6 @@ ssh_OpenSSL_add_all_algorithms(void)
+ 	/* Enable use of crypto hardware */
+ 	ENGINE_load_builtin_engines();
+ 	ENGINE_register_all_complete();
+-	OPENSSL_config(NULL);
+ }
+ #endif
+ 
+diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c
+index 99b7e21..d4d7934 100644
+--- a/regress/unittests/sshkey/test_file.c
++++ b/regress/unittests/sshkey/test_file.c
+@@ -60,9 +60,14 @@ sshkey_file_tests(void)
+ 	a = load_bignum("rsa_1.param.n");
+ 	b = load_bignum("rsa_1.param.p");
+ 	c = load_bignum("rsa_1.param.q");
+-	ASSERT_BIGNUM_EQ(k1->rsa->n, a);
+-	ASSERT_BIGNUM_EQ(k1->rsa->p, b);
+-	ASSERT_BIGNUM_EQ(k1->rsa->q, c);
++	{
++	const BIGNUM *n, *p, *q;
++	RSA_get0_key(k1->rsa, &n, NULL, NULL);
++	RSA_get0_factors(k1->rsa, &p, &q);
++	ASSERT_BIGNUM_EQ(n, a);
++	ASSERT_BIGNUM_EQ(p, b);
++	ASSERT_BIGNUM_EQ(q, c);
++	}
+ 	BN_free(a);
+ 	BN_free(b);
+ 	BN_free(c);
+@@ -151,9 +156,14 @@ sshkey_file_tests(void)
+ 	a = load_bignum("dsa_1.param.g");
+ 	b = load_bignum("dsa_1.param.priv");
+ 	c = load_bignum("dsa_1.param.pub");
+-	ASSERT_BIGNUM_EQ(k1->dsa->g, a);
+-	ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b);
+-	ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c);
++	{
++	const BIGNUM *g, *priv_key, *pub_key;
++	DSA_get0_pqg(k1->dsa, NULL, NULL, &g);
++	DSA_get0_key(k1->dsa, &pub_key, &priv_key);
++	ASSERT_BIGNUM_EQ(g, a);
++	ASSERT_BIGNUM_EQ(priv_key, b);
++	ASSERT_BIGNUM_EQ(pub_key, c);
++	}
+ 	BN_free(a);
+ 	BN_free(b);
+ 	BN_free(c);
+diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c
+index 1aa608f..6181d50 100644
+--- a/regress/unittests/sshkey/test_sshkey.c
++++ b/regress/unittests/sshkey/test_sshkey.c
+@@ -197,9 +197,14 @@ sshkey_tests(void)
+ 	k1 = sshkey_new(KEY_RSA);
+ 	ASSERT_PTR_NE(k1, NULL);
+ 	ASSERT_PTR_NE(k1->rsa, NULL);
+-	ASSERT_PTR_NE(k1->rsa->n, NULL);
+-	ASSERT_PTR_NE(k1->rsa->e, NULL);
+-	ASSERT_PTR_EQ(k1->rsa->p, NULL);
++	{
++	const BIGNUM *n, *e, *p;
++	RSA_get0_key(k1->rsa, &n, &e, NULL);
++	RSA_get0_factors(k1->rsa, &p, NULL);
++	ASSERT_PTR_NE(n, NULL);
++	ASSERT_PTR_NE(e, NULL);
++	ASSERT_PTR_EQ(p, NULL);
++	}
+ 	sshkey_free(k1);
+ 	TEST_DONE();
+ 
+@@ -207,8 +212,13 @@ sshkey_tests(void)
+ 	k1 = sshkey_new(KEY_DSA);
+ 	ASSERT_PTR_NE(k1, NULL);
+ 	ASSERT_PTR_NE(k1->dsa, NULL);
+-	ASSERT_PTR_NE(k1->dsa->g, NULL);
+-	ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
++	{
++	const BIGNUM *g, *priv_key;
++	DSA_get0_pqg(k1->dsa, NULL, NULL, &g);
++	DSA_get0_key(k1->dsa, NULL, &priv_key);
++	ASSERT_PTR_NE(g, NULL);
++	ASSERT_PTR_EQ(priv_key, NULL);
++	}
+ 	sshkey_free(k1);
+ 	TEST_DONE();
+ 
+@@ -234,9 +244,14 @@ sshkey_tests(void)
+ 	k1 = sshkey_new_private(KEY_RSA);
+ 	ASSERT_PTR_NE(k1, NULL);
+ 	ASSERT_PTR_NE(k1->rsa, NULL);
+-	ASSERT_PTR_NE(k1->rsa->n, NULL);
+-	ASSERT_PTR_NE(k1->rsa->e, NULL);
+-	ASSERT_PTR_NE(k1->rsa->p, NULL);
++	{
++	const BIGNUM *n, *e, *p;
++	RSA_get0_key(k1->rsa, &n, &e, NULL);
++	RSA_get0_factors(k1->rsa, &p, NULL);
++	ASSERT_PTR_NE(n, NULL);
++	ASSERT_PTR_NE(e, NULL);
++	ASSERT_PTR_NE(p, NULL);
++	}
+ 	ASSERT_INT_EQ(sshkey_add_private(k1), 0);
+ 	sshkey_free(k1);
+ 	TEST_DONE();
+@@ -245,8 +260,13 @@ sshkey_tests(void)
+ 	k1 = sshkey_new_private(KEY_DSA);
+ 	ASSERT_PTR_NE(k1, NULL);
+ 	ASSERT_PTR_NE(k1->dsa, NULL);
+-	ASSERT_PTR_NE(k1->dsa->g, NULL);
+-	ASSERT_PTR_NE(k1->dsa->priv_key, NULL);
++	{
++	const BIGNUM *g, *priv_key;
++	DSA_get0_pqg(k1->dsa, NULL, NULL, &g);
++	DSA_get0_key(k1->dsa, NULL, &priv_key);
++	ASSERT_PTR_NE(g, NULL);
++	ASSERT_PTR_NE(priv_key, NULL);
++	}
+ 	ASSERT_INT_EQ(sshkey_add_private(k1), 0);
+ 	sshkey_free(k1);
+ 	TEST_DONE();
+@@ -285,18 +305,28 @@ sshkey_tests(void)
+ 	ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0);
+ 	ASSERT_PTR_NE(kr, NULL);
+ 	ASSERT_PTR_NE(kr->rsa, NULL);
+-	ASSERT_PTR_NE(kr->rsa->n, NULL);
+-	ASSERT_PTR_NE(kr->rsa->e, NULL);
+-	ASSERT_PTR_NE(kr->rsa->p, NULL);
+-	ASSERT_INT_EQ(BN_num_bits(kr->rsa->n), 1024);
++	{
++	const BIGNUM *n, *e, *p;
++	RSA_get0_key(kr->rsa, &n, &e, NULL);
++	RSA_get0_factors(kr->rsa, &p, NULL);
++	ASSERT_PTR_NE(n, NULL);
++	ASSERT_PTR_NE(e, NULL);
++	ASSERT_PTR_NE(p, NULL);
++	ASSERT_INT_EQ(BN_num_bits(n), 1024);
++	}
+ 	TEST_DONE();
+ 
+ 	TEST_START("generate KEY_DSA");
+ 	ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0);
+ 	ASSERT_PTR_NE(kd, NULL);
+ 	ASSERT_PTR_NE(kd->dsa, NULL);
+-	ASSERT_PTR_NE(kd->dsa->g, NULL);
+-	ASSERT_PTR_NE(kd->dsa->priv_key, NULL);
++	{
++	const BIGNUM *g, *priv_key;
++	DSA_get0_pqg(kd->dsa, NULL, NULL, &g);
++	DSA_get0_key(kd->dsa, NULL, &priv_key);
++	ASSERT_PTR_NE(g, NULL);
++	ASSERT_PTR_NE(priv_key, NULL);
++	}
+ 	TEST_DONE();
+ 
+ #ifdef OPENSSL_HAS_ECC
+@@ -323,9 +353,14 @@ sshkey_tests(void)
+ 	ASSERT_PTR_NE(kr, k1);
+ 	ASSERT_INT_EQ(k1->type, KEY_RSA);
+ 	ASSERT_PTR_NE(k1->rsa, NULL);
+-	ASSERT_PTR_NE(k1->rsa->n, NULL);
+-	ASSERT_PTR_NE(k1->rsa->e, NULL);
+-	ASSERT_PTR_EQ(k1->rsa->p, NULL);
++	{
++	const BIGNUM *n, *e, *p;
++	RSA_get0_key(k1->rsa, &n, &e, NULL);
++	RSA_get0_factors(k1->rsa, &p, NULL);
++	ASSERT_PTR_NE(n, NULL);
++	ASSERT_PTR_NE(e, NULL);
++	ASSERT_PTR_EQ(p, NULL);
++	}
+ 	TEST_DONE();
+ 
+ 	TEST_START("equal KEY_RSA/demoted KEY_RSA");
+@@ -339,8 +374,13 @@ sshkey_tests(void)
+ 	ASSERT_PTR_NE(kd, k1);
+ 	ASSERT_INT_EQ(k1->type, KEY_DSA);
+ 	ASSERT_PTR_NE(k1->dsa, NULL);
+-	ASSERT_PTR_NE(k1->dsa->g, NULL);
+-	ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
++	{
++	const BIGNUM *g, *priv_key;
++	DSA_get0_pqg(k1->dsa, NULL, NULL, &g);
++	DSA_get0_key(k1->dsa, NULL, &priv_key);
++	ASSERT_PTR_NE(g, NULL);
++	ASSERT_PTR_EQ(priv_key, NULL);
++	}
+ 	TEST_DONE();
+ 
+ 	TEST_START("equal KEY_DSA/demoted KEY_DSA");
+diff --git a/ssh-dss.c b/ssh-dss.c
+index 9f832ee..f9e30a6 100644
+--- a/ssh-dss.c
++++ b/ssh-dss.c
+@@ -53,6 +53,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ 	DSA_SIG *sig = NULL;
+ 	u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
+ 	size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
++	const BIGNUM *r, *s;
+ 	struct sshbuf *b = NULL;
+ 	int ret = SSH_ERR_INVALID_ARGUMENT;
+ 
+@@ -76,15 +77,16 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ 		goto out;
+ 	}
+ 
+-	rlen = BN_num_bytes(sig->r);
+-	slen = BN_num_bytes(sig->s);
++	DSA_SIG_get0(sig, &r, &s);
++	rlen = BN_num_bytes(r);
++	slen = BN_num_bytes(s);
+ 	if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
+ 		ret = SSH_ERR_INTERNAL_ERROR;
+ 		goto out;
+ 	}
+ 	explicit_bzero(sigblob, SIGBLOB_LEN);
+-	BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
+-	BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen);
++	BN_bn2bin(r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
++	BN_bn2bin(s, sigblob + SIGBLOB_LEN - slen);
+ 
+ 	if ((b = sshbuf_new()) == NULL) {
+ 		ret = SSH_ERR_ALLOC_FAIL;
+@@ -154,17 +156,26 @@ ssh_dss_verify(const struct sshkey *key,
+ 	}
+ 
+ 	/* parse signature */
++	{
++	BIGNUM *r=NULL, *s=NULL;
+ 	if ((sig = DSA_SIG_new()) == NULL ||
+-	    (sig->r = BN_new()) == NULL ||
+-	    (sig->s = BN_new()) == NULL) {
++	    (r = BN_new()) == NULL ||
++	    (s = BN_new()) == NULL) {
+ 		ret = SSH_ERR_ALLOC_FAIL;
++		BN_free(r);
++		BN_free(s);
+ 		goto out;
+ 	}
+-	if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) ||
+-	    (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) {
++	if ((BN_bin2bn(sigblob, INTBLOB_LEN, r) == NULL) ||
++	    (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, s) == NULL)) {
+ 		ret = SSH_ERR_LIBCRYPTO_ERROR;
++		BN_free(r);
++		BN_free(s);
+ 		goto out;
+ 	}
++	DSA_SIG_set0(sig, r, s);
++	r = s = NULL;
++	}
+ 
+ 	/* sha1 the data */
+ 	if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
+diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
+index 3d3b78d..893129b 100644
+--- a/ssh-ecdsa.c
++++ b/ssh-ecdsa.c
+@@ -80,9 +80,14 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ 		ret = SSH_ERR_ALLOC_FAIL;
+ 		goto out;
+ 	}
+-	if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 ||
+-	    (ret = sshbuf_put_bignum2(bb, sig->s)) != 0)
++	{
++	const BIGNUM *r, *s;
++	ECDSA_SIG_get0(sig, &r, &s);
++	if ((ret = sshbuf_put_bignum2(bb, r)) != 0 ||
++	    (ret = sshbuf_put_bignum2(bb, s)) != 0) {
+ 		goto out;
++	}
++	}
+ 	if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
+ 	    (ret = sshbuf_put_stringb(b, bb)) != 0)
+ 		goto out;
+@@ -150,11 +155,27 @@ ssh_ecdsa_verify(const struct sshkey *key,
+ 		ret = SSH_ERR_ALLOC_FAIL;
+ 		goto out;
+ 	}
+-	if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 ||
+-	    sshbuf_get_bignum2(sigbuf, sig->s) != 0) {
++	{
++	BIGNUM *r=NULL, *s=NULL;
++	if ((r = BN_new()) == NULL ||
++	    (s = BN_new()) == NULL) {
++		ret = SSH_ERR_ALLOC_FAIL;
++		goto out_rs;
++	}
++	if (sshbuf_get_bignum2(sigbuf, r) != 0 ||
++	    sshbuf_get_bignum2(sigbuf, s) != 0) {
+ 		ret = SSH_ERR_INVALID_FORMAT;
++		goto out_rs;
++	}
++	if (ECDSA_SIG_set0(sig, r, s) == 0) {
++		ret = SSH_ERR_LIBCRYPTO_ERROR;
++out_rs:
++		BN_free(r);
++		BN_free(s);
+ 		goto out;
+ 	}
++	r = s = NULL;
++	}
+ 	if (sshbuf_len(sigbuf) != 0) {
+ 		ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ 		goto out;
+diff --git a/ssh-keygen.c b/ssh-keygen.c
+index 9aac64f..7b71ff9 100644
+--- a/ssh-keygen.c
++++ b/ssh-keygen.c
+@@ -493,11 +493,33 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
+ 
+ 	switch (key->type) {
+ 	case KEY_DSA:
+-		buffer_get_bignum_bits(b, key->dsa->p);
+-		buffer_get_bignum_bits(b, key->dsa->g);
+-		buffer_get_bignum_bits(b, key->dsa->q);
+-		buffer_get_bignum_bits(b, key->dsa->pub_key);
+-		buffer_get_bignum_bits(b, key->dsa->priv_key);
++		{
++		BIGNUM *p=NULL, *g=NULL, *q=NULL, *pub_key=NULL, *priv_key=NULL;
++		if ((p=BN_new()) == NULL ||
++		    (g=BN_new()) == NULL ||
++		    (q=BN_new()) == NULL ||
++		    (pub_key=BN_new()) == NULL ||
++		    (priv_key=BN_new()) == NULL) {
++			BN_free(p);
++			BN_free(g);
++			BN_free(q);
++			BN_free(pub_key);
++			BN_free(priv_key);
++			return NULL;
++		}
++		buffer_get_bignum_bits(b, p);
++		buffer_get_bignum_bits(b, g);
++		buffer_get_bignum_bits(b, q);
++		buffer_get_bignum_bits(b, pub_key);
++		buffer_get_bignum_bits(b, priv_key);
++		if (DSA_set0_pqg(key->dsa, p, q, g) == 0 ||
++		    DSA_set0_key(key->dsa, pub_key, priv_key) == 0) {
++			fatal("failed to set DSA key");
++			BN_free(p); BN_free(g); BN_free(q);
++			BN_free(pub_key); BN_free(priv_key);
++			return NULL;
++		}
++		}
+ 		break;
+ 	case KEY_RSA:
+ 		if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
+@@ -514,16 +536,52 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
+ 			e += e3;
+ 			debug("e %lx", e);
+ 		}
+-		if (!BN_set_word(key->rsa->e, e)) {
++		{
++		BIGNUM *rsa_e = NULL;
++		BIGNUM *d=NULL, *n=NULL, *iqmp=NULL, *q=NULL, *p=NULL;
++		BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy input to set in RSA_set0_crt_params */
++		rsa_e = BN_new();
++		if (!rsa_e || !BN_set_word(rsa_e, e)) {
++			if (rsa_e) BN_free(rsa_e);
+ 			sshbuf_free(b);
+ 			sshkey_free(key);
+ 			return NULL;
+ 		}
+-		buffer_get_bignum_bits(b, key->rsa->d);
+-		buffer_get_bignum_bits(b, key->rsa->n);
+-		buffer_get_bignum_bits(b, key->rsa->iqmp);
+-		buffer_get_bignum_bits(b, key->rsa->q);
+-		buffer_get_bignum_bits(b, key->rsa->p);
++		if ((d=BN_new()) == NULL ||
++		    (n=BN_new()) == NULL ||
++		    (iqmp=BN_new()) == NULL ||
++		    (q=BN_new()) == NULL ||
++		    (p=BN_new()) == NULL ||
++		    (dmp1=BN_new()) == NULL ||
++		    (dmq1=BN_new()) == NULL) {
++			BN_free(d); BN_free(n); BN_free(iqmp);
++			BN_free(q); BN_free(p);
++			BN_free(dmp1); BN_free(dmq1);
++			return NULL;
++		}
++		BN_clear(dmp1); BN_clear(dmq1);
++		buffer_get_bignum_bits(b, d);
++		buffer_get_bignum_bits(b, n);
++		buffer_get_bignum_bits(b, iqmp);
++		buffer_get_bignum_bits(b, q);
++		buffer_get_bignum_bits(b, p);
++		if (RSA_set0_key(key->rsa, n, rsa_e, d) == 0)
++			goto null;
++		n = d = NULL;
++		if (RSA_set0_factors(key->rsa, p, q) == 0)
++			goto null;
++		p = q = NULL;
++		/* dmp1, dmq1 should not be NULL for initial set0 */
++		if (RSA_set0_crt_params(key->rsa, dmp1, dmq1, iqmp) == 0) {
++ null:
++			fatal("Failed to set RSA parameters");
++			BN_free(d); BN_free(n); BN_free(iqmp);
++			BN_free(q); BN_free(p);
++			BN_free(dmp1); BN_free(dmq1);
++			return NULL;
++		}
++		dmp1 = dmq1 = iqmp = NULL;
++		}
+ 		if ((r = ssh_rsa_generate_additional_parameters(key)) != 0)
+ 			fatal("generate RSA parameters failed: %s", ssh_err(r));
+ 		break;
+@@ -633,7 +691,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
+ 		    identity_file);
+ 	}
+ 	fclose(fp);
+-	switch (EVP_PKEY_type(pubkey->type)) {
++	switch (EVP_PKEY_type(EVP_PKEY_id(pubkey))) {
+ 	case EVP_PKEY_RSA:
+ 		if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
+ 			fatal("sshkey_new failed");
+@@ -657,7 +715,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
+ #endif
+ 	default:
+ 		fatal("%s: unsupported pubkey type %d", __func__,
+-		    EVP_PKEY_type(pubkey->type));
++		    EVP_PKEY_type(EVP_PKEY_id(pubkey)));
+ 	}
+ 	EVP_PKEY_free(pubkey);
+ 	return;
+diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
+index fc75828..48f9cbb 100644
+--- a/ssh-pkcs11-client.c
++++ b/ssh-pkcs11-client.c
+@@ -144,12 +144,13 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
+ static int
+ wrap_key(RSA *rsa)
+ {
+-	static RSA_METHOD helper_rsa;
++	static RSA_METHOD *helper_rsa;
+ 
+-	memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa));
+-	helper_rsa.name = "ssh-pkcs11-helper";
+-	helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt;
+-	RSA_set_method(rsa, &helper_rsa);
++	if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
++		return (-1); /* XXX but caller isn't checking */
++	RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper");
++	RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt);
++	RSA_set_method(rsa, helper_rsa);
+ 	return (0);
+ }
+ 
+diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
+index 65a7b58..a2358b5 100644
+--- a/ssh-pkcs11.c
++++ b/ssh-pkcs11.c
+@@ -67,7 +67,7 @@ struct pkcs11_key {
+ 	struct pkcs11_provider	*provider;
+ 	CK_ULONG		slotidx;
+ 	int			(*orig_finish)(RSA *rsa);
+-	RSA_METHOD		rsa_method;
++	RSA_METHOD		*rsa_method;
+ 	char			*keyid;
+ 	int			keyid_len;
+ };
+@@ -326,13 +326,15 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
+ 		k11->keyid = xmalloc(k11->keyid_len);
+ 		memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
+ 	}
+-	k11->orig_finish = def->finish;
+-	memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method));
+-	k11->rsa_method.name = "pkcs11";
+-	k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt;
+-	k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt;
+-	k11->rsa_method.finish = pkcs11_rsa_finish;
+-	RSA_set_method(rsa, &k11->rsa_method);
++	k11->orig_finish = RSA_meth_get_finish(def);
++
++	if ((k11->rsa_method = RSA_meth_new("pkcs11", RSA_meth_get_flags(def))) == NULL)
++		return -1;
++	RSA_meth_set_priv_enc(k11->rsa_method, pkcs11_rsa_private_encrypt);
++	RSA_meth_set_priv_dec(k11->rsa_method, pkcs11_rsa_private_decrypt);
++	RSA_meth_set_finish(k11->rsa_method, pkcs11_rsa_finish);
++
++	RSA_set_method(rsa, k11->rsa_method);
+ 	RSA_set_app_data(rsa, k11);
+ 	return (0);
+ }
+@@ -512,10 +514,19 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
+ 			if ((rsa = RSA_new()) == NULL) {
+ 				error("RSA_new failed");
+ 			} else {
+-				rsa->n = BN_bin2bn(attribs[1].pValue,
+-				    attribs[1].ulValueLen, NULL);
+-				rsa->e = BN_bin2bn(attribs[2].pValue,
+-				    attribs[2].ulValueLen, NULL);
++				BIGNUM *n=NULL, *e=NULL;
++				n = BN_new();
++				e = BN_new();
++				if (n == NULL || e == NULL)
++					error("BN_new alloc failed");
++				if (BN_bin2bn(attribs[1].pValue,
++				      attribs[1].ulValueLen, n) == NULL ||
++				    BN_bin2bn(attribs[2].pValue,
++				      attribs[2].ulValueLen, e) == NULL)
++					error("BN_bin2bn failed");
++				if (RSA_set0_key(rsa, n, e, NULL) == 0)
++					error("RSA_set0_key failed");
++				n = e = NULL;
+ 			}
+ 		} else {
+ 			cp = attribs[2].pValue;
+@@ -525,16 +536,19 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
+ 			    == NULL) {
+ 				error("d2i_X509 failed");
+ 			} else if ((evp = X509_get_pubkey(x509)) == NULL ||
+-			    evp->type != EVP_PKEY_RSA ||
+-			    evp->pkey.rsa == NULL) {
++			    EVP_PKEY_id(evp) != EVP_PKEY_RSA ||
++			    EVP_PKEY_get0_RSA(evp) == NULL) {
+ 				debug("X509_get_pubkey failed or no rsa");
+-			} else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa))
++			} else if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp)))
+ 			    == NULL) {
+ 				error("RSAPublicKey_dup");
+ 			}
+ 			X509_free(x509);
+ 		}
+-		if (rsa && rsa->n && rsa->e &&
++		{
++		const BIGNUM *n, *e;
++		RSA_get0_key(rsa, &n, &e, NULL);
++		if (rsa && n && e &&
+ 		    pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
+ 			if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ 				fatal("sshkey_new failed");
+@@ -554,6 +568,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
+ 		} else if (rsa) {
+ 			RSA_free(rsa);
+ 		}
++		}
+ 		for (i = 0; i < 3; i++)
+ 			free(attribs[i].pValue);
+ 	}
+diff --git a/ssh-rsa.c b/ssh-rsa.c
+index 49e71c8..b7c2206 100644
+--- a/ssh-rsa.c
++++ b/ssh-rsa.c
+@@ -84,7 +84,6 @@ ssh_rsa_generate_additional_parameters(struct sshkey *key)
+ {
+ 	BIGNUM *aux = NULL;
+ 	BN_CTX *ctx = NULL;
+-	BIGNUM d;
+ 	int r;
+ 
+ 	if (key == NULL || key->rsa == NULL ||
+@@ -99,16 +98,27 @@ ssh_rsa_generate_additional_parameters(struct sshkey *key)
+ 	}
+ 	BN_set_flags(aux, BN_FLG_CONSTTIME);
+ 
+-	BN_init(&d);
+-	BN_with_flags(&d, key->rsa->d, BN_FLG_CONSTTIME);
+-
+-	if ((BN_sub(aux, key->rsa->q, BN_value_one()) == 0) ||
+-	    (BN_mod(key->rsa->dmq1, &d, aux, ctx) == 0) ||
+-	    (BN_sub(aux, key->rsa->p, BN_value_one()) == 0) ||
+-	    (BN_mod(key->rsa->dmp1, &d, aux, ctx) == 0)) {
++	{
++	const BIGNUM *q, *d, *p;
++	BIGNUM *dmq1=NULL, *dmp1=NULL;
++	if ((dmq1 = BN_new()) == NULL ||
++	    (dmp1 = BN_new()) == NULL ) {
++		r = SSH_ERR_ALLOC_FAIL;
++		goto out;
++	}
++	RSA_get0_key(key->rsa, NULL, NULL, &d);
++	RSA_get0_factors(key->rsa, &p, &q);
++	if ((BN_sub(aux, q, BN_value_one()) == 0) ||
++	    (BN_mod(dmq1, d, aux, ctx) == 0) ||
++	    (BN_sub(aux, p, BN_value_one()) == 0) ||
++	    (BN_mod(dmp1, d, aux, ctx) == 0) ||
++	    RSA_set0_crt_params(key->rsa, dmp1, dmq1, NULL) == 0) {
+ 		r = SSH_ERR_LIBCRYPTO_ERROR;
++		BN_clear_free(dmp1);
++		BN_clear_free(dmq1);
+ 		goto out;
+ 	}
++	}
+ 	r = 0;
+  out:
+ 	BN_clear_free(aux);
+@@ -139,7 +149,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ 	if (key == NULL || key->rsa == NULL || hash_alg == -1 ||
+ 	    sshkey_type_plain(key->type) != KEY_RSA)
+ 		return SSH_ERR_INVALID_ARGUMENT;
+-	if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
++	if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ 		return SSH_ERR_KEY_LENGTH;
+ 	slen = RSA_size(key->rsa);
+ 	if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
+@@ -211,7 +221,7 @@ ssh_rsa_verify(const struct sshkey *key,
+ 	    sshkey_type_plain(key->type) != KEY_RSA ||
+ 	    sig == NULL || siglen == 0)
+ 		return SSH_ERR_INVALID_ARGUMENT;
+-	if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
++	if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
+ 		return SSH_ERR_KEY_LENGTH;
+ 
+ 	if ((b = sshbuf_from(sig, siglen)) == NULL)
+diff --git a/sshkey.c b/sshkey.c
+index 7712fba..1f65301 100644
+--- a/sshkey.c
++++ b/sshkey.c
+@@ -274,10 +274,18 @@ sshkey_size(const struct sshkey *k)
+ #ifdef WITH_OPENSSL
+ 	case KEY_RSA:
+ 	case KEY_RSA_CERT:
+-		return BN_num_bits(k->rsa->n);
++#if OPENSSL_VERSION_NUMBER >= 0x10100000UL
++		return RSA_bits(k->rsa);
++#else
++		return RSA_bits(key->rsa);
++#endif
+ 	case KEY_DSA:
+ 	case KEY_DSA_CERT:
++#if OPENSSL_VERSION_NUMBER >= 0x10100000UL
++		return DSA_bits(k->dsa);
++#else
+ 		return BN_num_bits(k->dsa->p);
++#endif
+ 	case KEY_ECDSA:
+ 	case KEY_ECDSA_CERT:
+ 		return sshkey_curve_nid_to_bits(k->ecdsa_nid);
+@@ -482,26 +490,53 @@ sshkey_new(int type)
+ #ifdef WITH_OPENSSL
+ 	case KEY_RSA:
+ 	case KEY_RSA_CERT:
++		{
++		BIGNUM *n=NULL, *e=NULL; /* just allocate */
+ 		if ((rsa = RSA_new()) == NULL ||
+-		    (rsa->n = BN_new()) == NULL ||
+-		    (rsa->e = BN_new()) == NULL) {
++		    (n = BN_new()) == NULL ||
++		    (e = BN_new()) == NULL) {
++			BN_free(n);
++			BN_free(e);
+ 			RSA_free(rsa);
+ 			free(k);
+ 			return NULL;
+ 		}
++		BN_clear(n); BN_clear(e);
++		if (RSA_set0_key(rsa, n, e, NULL) == 0)
++			return NULL;
++		n = e = NULL;
++		}
+ 		k->rsa = rsa;
+ 		break;
+ 	case KEY_DSA:
+ 	case KEY_DSA_CERT:
++		{
++		BIGNUM *p=NULL, *q=NULL, *g=NULL, *pubkey=NULL; /* just allocate */
+ 		if ((dsa = DSA_new()) == NULL ||
+-		    (dsa->p = BN_new()) == NULL ||
+-		    (dsa->q = BN_new()) == NULL ||
+-		    (dsa->g = BN_new()) == NULL ||
+-		    (dsa->pub_key = BN_new()) == NULL) {
++		    (p = BN_new()) == NULL ||
++		    (q = BN_new()) == NULL ||
++		    (g = BN_new()) == NULL ||
++		    (pubkey = BN_new()) == NULL) {
++			BN_free(p);
++			BN_free(q);
++			BN_free(g);
++			BN_free(pubkey);
+ 			DSA_free(dsa);
+ 			free(k);
+ 			return NULL;
+ 		}
++		if (DSA_set0_pqg(dsa, p, q, g) == 0) {
++			BN_free(p); BN_free(q); BN_free(g);
++			BN_free(pubkey);
++			return NULL;
++		}
++		p = q = g = NULL;
++		if (DSA_set0_key(dsa, pubkey, NULL) == 0) {
++			BN_free(pubkey);
++			return NULL;
++		}
++		pubkey = NULL;
++		}
+ 		k->dsa = dsa;
+ 		break;
+ 	case KEY_ECDSA:
+@@ -539,6 +574,51 @@ sshkey_add_private(struct sshkey *k)
+ #ifdef WITH_OPENSSL
+ 	case KEY_RSA:
+ 	case KEY_RSA_CERT:
++#if OPENSSL_VERSION_NUMBER >= 0x10100000UL
++		/* Allocate BIGNUM. This is a mess.
++		   For OpenSSL 1.1.x API these shouldn't be mandatory,
++		   but some regression tests for non-NULL pointer of
++		   the data. */
++#define new_or_dup(bn, nbn) \
++		if (bn == NULL) { \
++			if ((nbn = BN_new()) == NULL) \
++				return SSH_ERR_ALLOC_FAIL; \
++		} else { \
++			/* otherwise use-after-free will occur */ \
++			if ((nbn = BN_dup(bn)) == NULL) \
++				return SSH_ERR_ALLOC_FAIL; \
++		}
++		{
++		const BIGNUM *d, *iqmp, *q, *p, *dmq1, *dmp1; /* allocate if NULL */
++		BIGNUM *nd, *niqmp, *nq, *np, *ndmq1, *ndmp1;
++
++		RSA_get0_key(k->rsa, NULL, NULL, &d);
++		RSA_get0_factors(k->rsa, &p, &q);
++		RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp);
++
++		new_or_dup(d, nd);
++		new_or_dup(iqmp, niqmp);
++		new_or_dup(q, nq);
++		new_or_dup(p, np);
++		new_or_dup(dmq1, ndmq1);
++		new_or_dup(dmp1, ndmp1);
++
++		if (RSA_set0_key(k->rsa, NULL, NULL, nd) == 0)
++			goto error1;
++		nd = NULL;
++		if (RSA_set0_factors(k->rsa, np, nq) == 0)
++			goto error1;
++		np = nq = NULL;
++		if (RSA_set0_crt_params(k->rsa, ndmp1, ndmq1, niqmp) == 0) {
++error1:
++			BN_free(nd);
++			BN_free(np); BN_free(nq);
++			BN_free(ndmp1); BN_free(ndmq1); BN_free(niqmp);
++			return SSH_ERR_LIBCRYPTO_ERROR;
++		}
++		ndmp1 = ndmq1 = niqmp = NULL;
++		}
++#else
+ #define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
+ 		if (bn_maybe_alloc_failed(k->rsa->d) ||
+ 		    bn_maybe_alloc_failed(k->rsa->iqmp) ||
+@@ -547,13 +627,28 @@ sshkey_add_private(struct sshkey *k)
+ 		    bn_maybe_alloc_failed(k->rsa->dmq1) ||
+ 		    bn_maybe_alloc_failed(k->rsa->dmp1))
+ 			return SSH_ERR_ALLOC_FAIL;
++#endif
+ 		break;
+ 	case KEY_DSA:
+ 	case KEY_DSA_CERT:
++#if OPENSSL_VERSION_NUMBER >= 0x10100000UL
++		{
++		const BIGNUM *priv_key;
++		BIGNUM *npriv_key;
++		DSA_get0_key(k->dsa, NULL, &priv_key);
++		new_or_dup(priv_key, npriv_key);
++		if (DSA_set0_key(k->dsa, NULL, npriv_key) == 0) {
++			BN_free(npriv_key);
++			return SSH_ERR_LIBCRYPTO_ERROR;
++		}
++		}
++#else
+ 		if (bn_maybe_alloc_failed(k->dsa->priv_key))
+ 			return SSH_ERR_ALLOC_FAIL;
++#endif
+ 		break;
+ #undef bn_maybe_alloc_failed
++#undef new_or_dup
+ 	case KEY_ECDSA:
+ 	case KEY_ECDSA_CERT:
+ 		/* Cannot do anything until we know the group */
+@@ -677,16 +772,34 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
+ #ifdef WITH_OPENSSL
+ 	case KEY_RSA_CERT:
+ 	case KEY_RSA:
+-		return a->rsa != NULL && b->rsa != NULL &&
+-		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
+-		    BN_cmp(a->rsa->n, b->rsa->n) == 0;
++		{
++		const BIGNUM *a_e, *b_e, *a_n, *b_n;
++		const BIGNUM *a_d, *b_d;
++		if (a->rsa == NULL) return 0;
++		if (b->rsa == NULL) return 0;
++		RSA_get0_key(a->rsa, &a_n, &a_e, &a_d);
++		RSA_get0_key(b->rsa, &b_n, &b_e, &b_d);
++		return 
++		    BN_cmp(a_e, b_e) == 0 &&
++		    BN_cmp(a_n, b_n) == 0;
++		}
+ 	case KEY_DSA_CERT:
+ 	case KEY_DSA:
+-		return a->dsa != NULL && b->dsa != NULL &&
+-		    BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
+-		    BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
+-		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
+-		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
++		{
++		const BIGNUM *a_p, *a_q, *a_g, *a_pub_key;
++		const BIGNUM *b_p, *b_q, *b_g, *b_pub_key;
++		if (a->dsa == NULL) return 0;
++		if (b->dsa == NULL) return 0;
++		DSA_get0_pqg(a->dsa, &a_p, &a_q, &a_g);
++		DSA_get0_pqg(b->dsa, &b_p, &b_q, &b_g);
++		DSA_get0_key(a->dsa, &a_pub_key, NULL);
++		DSA_get0_key(b->dsa, &b_pub_key, NULL);
++		return 
++		    BN_cmp(a_p, b_p) == 0 &&
++		    BN_cmp(a_q, b_q) == 0 &&
++		    BN_cmp(a_g, b_g) == 0 &&
++		    BN_cmp(a_pub_key, b_pub_key) == 0;
++		}
+ # ifdef OPENSSL_HAS_ECC
+ 	case KEY_ECDSA_CERT:
+ 	case KEY_ECDSA:
+@@ -775,12 +888,17 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
+ 	case KEY_DSA:
+ 		if (key->dsa == NULL)
+ 			return SSH_ERR_INVALID_ARGUMENT;
++		{
++		const BIGNUM *p, *q, *g, *pub_key;
++		DSA_get0_pqg(key->dsa, &p, &q, &g);
++		DSA_get0_key(key->dsa, &pub_key, NULL);
+ 		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
++		    (ret = sshbuf_put_bignum2(b, p)) != 0 ||
++		    (ret = sshbuf_put_bignum2(b, q)) != 0 ||
++		    (ret = sshbuf_put_bignum2(b, g)) != 0 ||
++		    (ret = sshbuf_put_bignum2(b, pub_key)) != 0)
+ 			return ret;
++		}
+ 		break;
+ # ifdef OPENSSL_HAS_ECC
+ 	case KEY_ECDSA:
+@@ -796,10 +914,14 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain,
+ 	case KEY_RSA:
+ 		if (key->rsa == NULL)
+ 			return SSH_ERR_INVALID_ARGUMENT;
++		{
++		const BIGNUM *e, *n;
++		RSA_get0_key(key->rsa, &n, &e, NULL);
+ 		if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
++		    (ret = sshbuf_put_bignum2(b, e)) != 0 ||
++		    (ret = sshbuf_put_bignum2(b, n)) != 0)
+ 			return ret;
++		}
+ 		break;
+ #endif /* WITH_OPENSSL */
+ 	case KEY_ED25519:
+@@ -1740,13 +1862,32 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
+ 	case KEY_DSA_CERT:
+ 		if ((n = sshkey_new(k->type)) == NULL)
+ 			return SSH_ERR_ALLOC_FAIL;
+-		if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
+-		    (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
+-		    (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
+-		    (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
++		{
++		const BIGNUM *p, *q, *g, *pub_key, *priv_key;
++		BIGNUM *cp=NULL, *cq=NULL, *cg=NULL, *cpub_key=NULL;
++		DSA_get0_pqg(k->dsa, &p, &q, &g);
++		DSA_get0_key(k->dsa, &pub_key, &priv_key);
++		if ((cp = BN_dup(p)) == NULL ||
++		    (cq = BN_dup(q)) == NULL ||
++		    (cg = BN_dup(g)) == NULL ||
++		    (cpub_key = BN_dup(pub_key)) == NULL) {
++			BN_free(cp); BN_free(cq); BN_free(cg);
++			BN_free(cpub_key);
+ 			sshkey_free(n);
+ 			return SSH_ERR_ALLOC_FAIL;
+ 		}
++		if (DSA_set0_pqg(n->dsa, cp, cq, cg) == 0)
++			goto error1;
++		cp = cq = cg = NULL;
++		if (DSA_set0_key(n->dsa, cpub_key, NULL) == 0) {
++error1:
++			BN_free(cp); BN_free(cq); BN_free(cg);
++			BN_free(cpub_key);
++			sshkey_free(n);
++			return SSH_ERR_LIBCRYPTO_ERROR;
++		}
++		cpub_key = NULL;
++		}
+ 		break;
+ # ifdef OPENSSL_HAS_ECC
+ 	case KEY_ECDSA:
+@@ -1770,11 +1911,23 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
+ 	case KEY_RSA_CERT:
+ 		if ((n = sshkey_new(k->type)) == NULL)
+ 			return SSH_ERR_ALLOC_FAIL;
+-		if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
+-		    (BN_copy(n->rsa->e, k->rsa->e) == NULL)) {
++		{
++		const BIGNUM *nn, *e, *d;
++		BIGNUM *cn=NULL, *ce=NULL;
++		RSA_get0_key(k->rsa, &nn, &e, &d);
++		if ((cn = BN_dup(nn)) == NULL ||
++		    (ce = BN_dup(e)) == NULL ) {
++			BN_free(cn); BN_free(ce);
+ 			sshkey_free(n);
+ 			return SSH_ERR_ALLOC_FAIL;
+ 		}
++		if (RSA_set0_key(n->rsa, cn, ce, NULL) == 0) {
++			BN_free(cn); BN_free(ce);
++			sshkey_free(n);
++			return SSH_ERR_LIBCRYPTO_ERROR;
++		}
++		cn = ce = NULL;
++		}
+ 		break;
+ #endif /* WITH_OPENSSL */
+ 	case KEY_ED25519:
+@@ -1995,12 +2148,27 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
+ 			ret = SSH_ERR_ALLOC_FAIL;
+ 			goto out;
+ 		}
+-		if (sshbuf_get_bignum2(b, key->rsa->e) != 0 ||
+-		    sshbuf_get_bignum2(b, key->rsa->n) != 0) {
++		{
++		BIGNUM *e=NULL, *n=NULL;
++		if ((e = BN_new()) == NULL ||
++		    (n = BN_new()) == NULL ) {
++			ret = SSH_ERR_ALLOC_FAIL;
++			BN_free(e); BN_free(n);
++			goto out;
++		}
++		if (sshbuf_get_bignum2(b, e) != 0 ||
++		    sshbuf_get_bignum2(b, n) != 0) {
+ 			ret = SSH_ERR_INVALID_FORMAT;
++			BN_free(e); BN_free(n);
+ 			goto out;
+ 		}
+-		if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
++		if (RSA_set0_key(key->rsa, n, e, NULL) == 0) {
++			BN_free(e); BN_free(n);
++			return SSH_ERR_LIBCRYPTO_ERROR;
++		}
++		n = e = NULL;
++		}
++		if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ 			ret = SSH_ERR_KEY_LENGTH;
+ 			goto out;
+ 		}
+@@ -2020,13 +2188,36 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
+ 			ret = SSH_ERR_ALLOC_FAIL;
+ 			goto out;
+ 		}
+-		if (sshbuf_get_bignum2(b, key->dsa->p) != 0 ||
+-		    sshbuf_get_bignum2(b, key->dsa->q) != 0 ||
+-		    sshbuf_get_bignum2(b, key->dsa->g) != 0 ||
+-		    sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) {
++		{
++		BIGNUM *p=NULL, *q=NULL, *g=NULL, *pub_key=NULL;
++		if ((p = BN_new()) == NULL ||
++		    (q = BN_new()) == NULL ||
++		    (g = BN_new()) == NULL ||
++		    (pub_key = BN_new()) == NULL) {
++			ret = SSH_ERR_ALLOC_FAIL;
++			goto error1;
++		}
++		if (sshbuf_get_bignum2(b, p) != 0 ||
++		    sshbuf_get_bignum2(b, q) != 0 ||
++		    sshbuf_get_bignum2(b, g) != 0 ||
++		    sshbuf_get_bignum2(b, pub_key) != 0) {
+ 			ret = SSH_ERR_INVALID_FORMAT;
++			goto error1;
++		}
++		if (DSA_set0_pqg(key->dsa, p, q, g) == 0) {
++			ret = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error1;
++		}
++		p = q = g = NULL;
++		if (DSA_set0_key(key->dsa, pub_key, NULL) == 0) {
++			ret = SSH_ERR_LIBCRYPTO_ERROR;
++error1:
++			BN_free(p); BN_free(q); BN_free(g);
++			BN_free(pub_key);
+ 			goto out;
+ 		}
++		pub_key = NULL;
++		}
+ #ifdef DEBUG_PK
+ 		DSA_print_fp(stderr, key->dsa, 8);
+ #endif
+@@ -2327,26 +2518,63 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
+ 			goto fail;
+ 		/* FALLTHROUGH */
+ 	case KEY_RSA:
+-		if ((pk->rsa = RSA_new()) == NULL ||
+-		    (pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
+-		    (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) {
++		if ((pk->rsa = RSA_new()) == NULL ){
++			ret = SSH_ERR_ALLOC_FAIL;
++			goto fail;
++			}
++		{
++		const BIGNUM *ke, *kn;
++		BIGNUM *pke=NULL, *pkn=NULL;
++		RSA_get0_key(k->rsa, &kn, &ke, NULL);
++		 if ((pke = BN_dup(ke)) == NULL ||
++		     (pkn = BN_dup(kn)) == NULL) {
+ 			ret = SSH_ERR_ALLOC_FAIL;
++			BN_free(pke); BN_free(pkn);
+ 			goto fail;
+ 			}
++		if (RSA_set0_key(pk->rsa, pkn, pke, NULL) == 0) {
++			ret = SSH_ERR_LIBCRYPTO_ERROR;
++			BN_free(pke); BN_free(pkn);
++			goto fail;
++		}
++		pkn = pke = NULL;
++		}
+ 		break;
+ 	case KEY_DSA_CERT:
+ 		if ((ret = sshkey_cert_copy(k, pk)) != 0)
+ 			goto fail;
+ 		/* FALLTHROUGH */
+ 	case KEY_DSA:
+-		if ((pk->dsa = DSA_new()) == NULL ||
+-		    (pk->dsa->p = BN_dup(k->dsa->p)) == NULL ||
+-		    (pk->dsa->q = BN_dup(k->dsa->q)) == NULL ||
+-		    (pk->dsa->g = BN_dup(k->dsa->g)) == NULL ||
+-		    (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) {
++		if ((pk->dsa = DSA_new()) == NULL ) {
++			ret = SSH_ERR_ALLOC_FAIL;
++			goto fail;
++		}
++		{
++		const BIGNUM *kp, *kq, *kg, *kpub_key;
++		BIGNUM *pkp=NULL, *pkq=NULL, *pkg=NULL, *pkpub_key=NULL;
++		DSA_get0_pqg(k->dsa, &kp, &kq, &kg);
++		DSA_get0_key(k->dsa, &kpub_key, NULL);
++		if ((pkp = BN_dup(kp)) == NULL ||
++		    (pkq = BN_dup(kq)) == NULL ||
++		    (pkg = BN_dup(kg)) == NULL ||
++		    (pkpub_key = BN_dup(kpub_key)) == NULL) {
+ 			ret = SSH_ERR_ALLOC_FAIL;
++			goto error1;
++		}
++		if (DSA_set0_pqg(pk->dsa, pkp, pkq, pkg) == 0) {
++			ret = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error1;
++		}
++		pkp = pkq = pkg = NULL;
++		if (DSA_set0_key(pk->dsa, pkpub_key, NULL) == 0) {
++			ret = SSH_ERR_LIBCRYPTO_ERROR;
++error1:
++			BN_free(pkp); BN_free(pkq); BN_free(pkg);
++			BN_free(pkpub_key);
+ 			goto fail;
+ 		}
++		pkpub_key = NULL;
++		}
+ 		break;
+ 	case KEY_ECDSA_CERT:
+ 		if ((ret = sshkey_cert_copy(k, pk)) != 0)
+@@ -2496,11 +2724,17 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
+ 	switch (k->type) {
+ #ifdef WITH_OPENSSL
+ 	case KEY_DSA_CERT:
+-		if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0)
++		{
++		const BIGNUM *p, *q, *g, *pub_key;
++		DSA_get0_pqg(k->dsa, &p, &q, &g);
++		DSA_get0_key(k->dsa, &pub_key, NULL);
++		if ((ret = sshbuf_put_bignum2(cert, p)) != 0 ||
++		    (ret = sshbuf_put_bignum2(cert, q)) != 0 ||
++		    (ret = sshbuf_put_bignum2(cert, g)) != 0 ||
++		    (ret = sshbuf_put_bignum2(cert, pub_key)) != 0) {
+ 			goto out;
++		}
++		}
+ 		break;
+ # ifdef OPENSSL_HAS_ECC
+ 	case KEY_ECDSA_CERT:
+@@ -2513,9 +2747,15 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
+ 		break;
+ # endif /* OPENSSL_HAS_ECC */
+ 	case KEY_RSA_CERT:
+-		if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 ||
+-		    (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
++		{
++		const BIGNUM *e, *n;
++		RSA_get0_key(k->rsa, &n, &e, NULL);
++		if (n == NULL || e == NULL ||
++		    (ret = sshbuf_put_bignum2(cert, e)) != 0 ||
++		    (ret = sshbuf_put_bignum2(cert, n)) != 0) {
+ 			goto out;
++		}
++		}
+ 		break;
+ #endif /* WITH_OPENSSL */
+ 	case KEY_ED25519_CERT:
+@@ -2702,42 +2942,67 @@ sshkey_private_serialize_opt(const struct sshkey *key, struct sshbuf *b,
+ 	switch (key->type) {
+ #ifdef WITH_OPENSSL
+ 	case KEY_RSA:
+-		if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
++		{
++		const BIGNUM *n, *e, *d, *iqmp, *p, *q;
++		RSA_get0_key(key->rsa, &n, &e, &d);
++		RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);
++		RSA_get0_factors(key->rsa, &p, &q);
++		if ((r = sshbuf_put_bignum2(b, n)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, e)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, d)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, iqmp)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, p)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, q)) != 0) {
+ 			goto out;
++		}
++		}
+ 		break;
+ 	case KEY_RSA_CERT:
+ 		if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
+ 			r = SSH_ERR_INVALID_ARGUMENT;
+ 			goto out;
+ 		}
++		{
++		const BIGNUM *d, *iqmp, *p, *q;
++		RSA_get0_key(key->rsa, NULL, NULL, &d);
++		RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp);
++		RSA_get0_factors(key->rsa, &p, &q);
+ 		if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
++		    (r = sshbuf_put_bignum2(b, d)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, iqmp)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, p)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, q)) != 0) {
+ 			goto out;
++		}
++		}
+ 		break;
+ 	case KEY_DSA:
+-		if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
++		{
++		const BIGNUM *p, *q, *g, *pub_key, *priv_key;
++		DSA_get0_pqg(key->dsa, &p, &q, &g);
++		DSA_get0_key(key->dsa, &pub_key, &priv_key);
++		if ((r = sshbuf_put_bignum2(b, p)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, q)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, g)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, pub_key)) != 0 ||
++		    (r = sshbuf_put_bignum2(b, priv_key)) != 0) {
+ 			goto out;
++		}
++		}
+ 		break;
+ 	case KEY_DSA_CERT:
+ 		if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
+ 			r = SSH_ERR_INVALID_ARGUMENT;
+ 			goto out;
+ 		}
++		{
++		const BIGNUM *priv_key;
++		DSA_get0_key(key->dsa, NULL, &priv_key);
+ 		if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
+-		    (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
++		    (r = sshbuf_put_bignum2(b, priv_key)) != 0) {
+ 			goto out;
++		}
++		}
+ 		break;
+ # ifdef OPENSSL_HAS_ECC
+ 	case KEY_ECDSA:
+@@ -2851,18 +3116,61 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
+ 			r = SSH_ERR_ALLOC_FAIL;
+ 			goto out;
+ 		}
+-		if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
++		{
++		BIGNUM *p=NULL, *q=NULL, *g=NULL, *pub_key=NULL, *priv_key=NULL;
++		if ((p = BN_new()) == NULL ||
++		    (q = BN_new()) == NULL ||
++		    (g = BN_new()) == NULL ||
++		    (pub_key = BN_new()) == NULL ||
++		    (priv_key = BN_new()) == NULL) {
++			r = SSH_ERR_ALLOC_FAIL;
++			goto error1;
++		}
++		if (p == NULL || q == NULL || g == NULL ||
++		    pub_key == NULL || priv_key == NULL ||
++		    (r = sshbuf_get_bignum2(buf, p)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, q)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, g)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, pub_key)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, priv_key)) != 0) {
++			goto error1;
++		}
++		if (DSA_set0_pqg(k->dsa, p, q, g) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error1;
++		}
++		p = q = g = NULL;
++		if (DSA_set0_key(k->dsa, pub_key, priv_key) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++error1:
++			BN_free(p); BN_free(q); BN_free(g);
++			BN_free(pub_key); BN_free(priv_key);
+ 			goto out;
++		}
++		pub_key = priv_key = NULL;
++		}
+ 		break;
+ 	case KEY_DSA_CERT:
+-		if ((r = sshkey_froms(buf, &k)) != 0 ||
++		{
++		BIGNUM *priv_key=NULL;
++		if ((priv_key = BN_new()) == NULL) {
++			r = SSH_ERR_ALLOC_FAIL;
++			goto out;
++		}
++		if (priv_key == NULL ||
++		    (r = sshkey_froms(buf, &k)) != 0 ||
+ 		    (r = sshkey_add_private(k)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
++		    (r = sshbuf_get_bignum2(buf, priv_key)) != 0) {
++			BN_free(priv_key);
+ 			goto out;
++		}
++		if (DSA_set0_key(k->dsa, NULL, priv_key) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++			BN_free(priv_key);
++			goto out;
++		}
++		priv_key = NULL;
++		}
+ 		break;
+ # ifdef OPENSSL_HAS_ECC
+ 	case KEY_ECDSA:
+@@ -2921,29 +3229,104 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
+ 			r = SSH_ERR_ALLOC_FAIL;
+ 			goto out;
+ 		}
+-		if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
+-		    (r = ssh_rsa_generate_additional_parameters(k)) != 0)
++		{
++		BIGNUM *n=NULL, *e=NULL, *d=NULL, *iqmp=NULL, *p=NULL, *q=NULL;
++		BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy for RSA_set0_crt_params */
++		if ((n = BN_new()) == NULL ||
++		    (e = BN_new()) == NULL ||
++		    (d = BN_new()) == NULL ||
++		    (iqmp = BN_new()) == NULL ||
++		    (p = BN_new()) == NULL ||
++		    (q = BN_new()) == NULL ||
++		    (dmp1 = BN_new()) == NULL ||
++		    (dmq1 = BN_new()) == NULL) {
++			r = SSH_ERR_ALLOC_FAIL;
++			goto error2;
++		}
++		BN_clear(dmp1); BN_clear(dmq1);
++		if ((r = sshbuf_get_bignum2(buf, n)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, e)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, d)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, iqmp)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, p)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, q)) != 0) {
++			goto error2;
++		}
++		if (RSA_set0_key(k->rsa, n, e, d) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error2;
++		}
++		n = e = d = NULL;
++		/* dmp1,dmpq1 should be non NULL to set iqmp value */
++		if (RSA_set0_crt_params(k->rsa, dmp1, dmq1, iqmp) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error2;
++		}
++		dmp1 = dmq1 = iqmp = NULL;
++		if (RSA_set0_factors(k->rsa, p, q) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++ error2:
++			BN_free(n); BN_free(e); BN_free(d);
++			BN_free(iqmp);
++			BN_free(p); BN_free(q);
++			BN_free(dmp1); BN_free(dmq1);
++			goto out;
++		}
++		p = q = NULL;
++		if ((r = ssh_rsa_generate_additional_parameters(k)) != 0) {
+ 			goto out;
+-		if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
++		}
++		}
++		if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ 			r = SSH_ERR_KEY_LENGTH;
+ 			goto out;
+ 		}
+ 		break;
+ 	case KEY_RSA_CERT:
++		{
++		BIGNUM *d=NULL, *iqmp=NULL, *p=NULL, *q=NULL;
++		BIGNUM *dmp1=NULL, *dmq1=NULL; /* dummy for RSA_set0_crt_params */
++		if ((d = BN_new()) == NULL ||
++		    (iqmp = BN_new()) == NULL ||
++		    (p = BN_new()) == NULL ||
++		    (q = BN_new()) == NULL ||
++		    (dmp1 = BN_new()) == NULL ||
++		    (dmq1 = BN_new()) == NULL) {
++			r = SSH_ERR_ALLOC_FAIL;
++			goto error3;
++		}
++		BN_clear(dmp1); BN_clear(dmq1);
+ 		if ((r = sshkey_froms(buf, &k)) != 0 ||
+ 		    (r = sshkey_add_private(k)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
+-		    (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
+-		    (r = ssh_rsa_generate_additional_parameters(k)) != 0)
++		    (r = sshbuf_get_bignum2(buf, d)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, iqmp)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, p)) != 0 ||
++		    (r = sshbuf_get_bignum2(buf, q)) != 0) {
++			goto error3;
++		}
++		if (RSA_set0_key(k->rsa, NULL, NULL, d) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error3;
++		}
++		/* dmp1,dmpq1 should be non NULL to set value */
++		if (RSA_set0_crt_params(k->rsa, dmp1, dmq1, iqmp) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++			goto error3;
++		}
++		dmp1 = dmq1 = iqmp = NULL;
++		if (RSA_set0_factors(k->rsa, p, q) == 0) {
++			r = SSH_ERR_LIBCRYPTO_ERROR;
++ error3:
++			BN_free(d); BN_free(iqmp);
++			BN_free(p); BN_free(q);
++			BN_free(dmp1); BN_free(dmq1);
+ 			goto out;
+-		if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
++		}
++		p = q = NULL;
++		if ((r = ssh_rsa_generate_additional_parameters(k)) != 0)
++			goto out;
++		}
++		if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ 			r = SSH_ERR_KEY_LENGTH;
+ 			goto out;
+ 		}
+@@ -3707,7 +4090,6 @@ translate_libcrypto_error(unsigned long pem_err)
+ 		switch (pem_reason) {
+ 		case EVP_R_BAD_DECRYPT:
+ 			return SSH_ERR_KEY_WRONG_PASSPHRASE;
+-		case EVP_R_BN_DECODE_ERROR:
+ 		case EVP_R_DECODE_ERROR:
+ #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
+ 		case EVP_R_PRIVATE_KEY_DECODE_ERROR:
+@@ -3772,7 +4154,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
+ 		r = convert_libcrypto_error();
+ 		goto out;
+ 	}
+-	if (pk->type == EVP_PKEY_RSA &&
++	if (EVP_PKEY_id(pk) == EVP_PKEY_RSA &&
+ 	    (type == KEY_UNSPEC || type == KEY_RSA)) {
+ 		if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
+ 			r = SSH_ERR_ALLOC_FAIL;
+@@ -3787,11 +4169,11 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
+ 			r = SSH_ERR_LIBCRYPTO_ERROR;
+ 			goto out;
+ 		}
+-		if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
++		if (RSA_bits(prv->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ 			r = SSH_ERR_KEY_LENGTH;
+ 			goto out;
+ 		}
+-	} else if (pk->type == EVP_PKEY_DSA &&
++	} else if (EVP_PKEY_id(pk) == EVP_PKEY_DSA &&
+ 	    (type == KEY_UNSPEC || type == KEY_DSA)) {
+ 		if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
+ 			r = SSH_ERR_ALLOC_FAIL;
+@@ -3803,7 +4185,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
+ 		DSA_print_fp(stderr, prv->dsa, 8);
+ #endif
+ #ifdef OPENSSL_HAS_ECC
+-	} else if (pk->type == EVP_PKEY_EC &&
++	} else if (EVP_PKEY_id(pk) == EVP_PKEY_EC &&
+ 	    (type == KEY_UNSPEC || type == KEY_ECDSA)) {
+ 		if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
+ 			r = SSH_ERR_ALLOC_FAIL;
+-- 
+2.16.3
+
-- 
2.16.3

  reply	other threads:[~2018-05-03 21:24 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-03 21:24 [Buildroot] [RFC v2 1/3] libopenssl: bump version to 1.1.0h Peter Seiderer
2018-05-03 21:24 ` Peter Seiderer [this message]
2018-05-03 21:24 ` [Buildroot] [RFC v2 3/3] freeswitch: bump to git master 8f10ae54a18a19fc6ed938e4f662bd218ba54b5e Peter Seiderer
2018-05-03 21:48   ` Peter Seiderer
2018-05-06 17:17     ` [Buildroot] [RFC v2 3/3] freeswitch: bump to git master8f10ae54a18a19fc6ed938e4f662bd218ba54b5e Bernd Kuhls

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180503212436.2521-2-ps.report@gmx.net \
    --to=ps.report@gmx.net \
    --cc=buildroot@busybox.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.