From 37e233307a79a9250962dcf77b7c7e27a02a1a35 Mon Sep 17 00:00:00 2001
From: Khem Raj <raj.khem@gmail.com>
Date: Fri, 1 Feb 2019 22:44:10 -0800
Subject: [PATCH] Adapt to OpenSSL 1.1.1

From: Guido Falsi <mad@madpilot.net>
https://sources.debian.org/src/pam-ssh-agent-auth/0.10.3-3/debian/patches/openssl-1.1.1-1.patch/

Upstream-Status: Pending
Signed-off-by: Khem Raj <raj.khem@gmail.com>
---
 authfd.c    |  50 ++++++++++++++++++++
 bufbn.c     |   4 ++
 cipher.h    |   6 ++-
 kex.h       |   9 +++-
 key.c       | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 ssh-dss.c   |  51 ++++++++++++++++----
 ssh-ecdsa.c |  40 ++++++++++++----
 ssh-rsa.c   |  22 +++++++--
 8 files changed, 287 insertions(+), 28 deletions(-)

diff --git a/authfd.c b/authfd.c
index 212e06b..f91514d 100644
--- a/authfd.c
+++ b/authfd.c
@@ -367,6 +367,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
 	case 1:
 		key = pamsshagentauth_key_new(KEY_RSA1);
 		bits = pamsshagentauth_buffer_get_int(&auth->identities);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		pamsshagentauth_buffer_get_bignum(&auth->identities, key->rsa->e);
 		pamsshagentauth_buffer_get_bignum(&auth->identities, key->rsa->n);
 		*comment = pamsshagentauth_buffer_get_string(&auth->identities, NULL);
@@ -374,6 +375,15 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
 		if (keybits < 0 || bits != (u_int)keybits)
 			pamsshagentauth_logit("Warning: identity keysize mismatch: actual %d, announced %u",
 			    BN_num_bits(key->rsa->n), bits);
+#else
+		pamsshagentauth_buffer_get_bignum(&auth->identities, RSA_get0_e(key->rsa));
+		pamsshagentauth_buffer_get_bignum(&auth->identities, RSA_get0_n(key->rsa));
+		*comment = pamsshagentauth_buffer_get_string(&auth->identities, NULL);
+		keybits = BN_num_bits(RSA_get0_n(key->rsa));
+		if (keybits < 0 || bits != (u_int)keybits)
+			pamsshagentauth_logit("Warning: identity keysize mismatch: actual %d, announced %u",
+			    BN_num_bits(RSA_get0_n(key->rsa)), bits);
+#endif
 		break;
 	case 2:
 		blob = pamsshagentauth_buffer_get_string(&auth->identities, &blen);
@@ -417,9 +427,15 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
 	}
 	pamsshagentauth_buffer_init(&buffer);
 	pamsshagentauth_buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	pamsshagentauth_buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
 	pamsshagentauth_buffer_put_bignum(&buffer, key->rsa->e);
 	pamsshagentauth_buffer_put_bignum(&buffer, key->rsa->n);
+#else
+	pamsshagentauth_buffer_put_int(&buffer, BN_num_bits(RSA_get0_n(key->rsa)));
+	pamsshagentauth_buffer_put_bignum(&buffer, RSA_get0_e(key->rsa));
+	pamsshagentauth_buffer_put_bignum(&buffer, RSA_get0_n(key->rsa));
+#endif
 	pamsshagentauth_buffer_put_bignum(&buffer, challenge);
 	pamsshagentauth_buffer_append(&buffer, session_id, 16);
 	pamsshagentauth_buffer_put_int(&buffer, response_type);
@@ -496,6 +512,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
 static void
 ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
 {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	pamsshagentauth_buffer_put_int(b, BN_num_bits(key->n));
 	pamsshagentauth_buffer_put_bignum(b, key->n);
 	pamsshagentauth_buffer_put_bignum(b, key->e);
@@ -504,6 +521,16 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
 	pamsshagentauth_buffer_put_bignum(b, key->iqmp);	/* ssh key->u */
 	pamsshagentauth_buffer_put_bignum(b, key->q);	/* ssh key->p, SSL key->q */
 	pamsshagentauth_buffer_put_bignum(b, key->p);	/* ssh key->q, SSL key->p */
+#else
+	pamsshagentauth_buffer_put_int(b, BN_num_bits(RSA_get0_n(key)));
+	pamsshagentauth_buffer_put_bignum(b, RSA_get0_n(key));
+	pamsshagentauth_buffer_put_bignum(b, RSA_get0_e(key));
+	pamsshagentauth_buffer_put_bignum(b, RSA_get0_d(key));
+	/* To keep within the protocol: p < q for ssh. in SSL p > q */
+	pamsshagentauth_buffer_put_bignum(b, RSA_get0_iqmp(key));	/* ssh key->u */
+	pamsshagentauth_buffer_put_bignum(b, RSA_get0_q(key));	/* ssh key->p, SSL key->q */
+	pamsshagentauth_buffer_put_bignum(b, RSA_get0_p(key));	/* ssh key->q, SSL key->p */
+#endif
 	pamsshagentauth_buffer_put_cstring(b, comment);
 }
 
@@ -513,19 +540,36 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
 	pamsshagentauth_buffer_put_cstring(b, key_ssh_name(key));
 	switch (key->type) {
 	case KEY_RSA:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		pamsshagentauth_buffer_put_bignum2(b, key->rsa->n);
 		pamsshagentauth_buffer_put_bignum2(b, key->rsa->e);
 		pamsshagentauth_buffer_put_bignum2(b, key->rsa->d);
 		pamsshagentauth_buffer_put_bignum2(b, key->rsa->iqmp);
 		pamsshagentauth_buffer_put_bignum2(b, key->rsa->p);
 		pamsshagentauth_buffer_put_bignum2(b, key->rsa->q);
+#else
+		pamsshagentauth_buffer_put_bignum2(b, RSA_get0_n(key->rsa));
+		pamsshagentauth_buffer_put_bignum2(b, RSA_get0_e(key->rsa));
+		pamsshagentauth_buffer_put_bignum2(b, RSA_get0_d(key->rsa));
+		pamsshagentauth_buffer_put_bignum2(b, RSA_get0_iqmp(key->rsa));
+		pamsshagentauth_buffer_put_bignum2(b, RSA_get0_p(key->rsa));
+		pamsshagentauth_buffer_put_bignum2(b, RSA_get0_q(key->rsa));
+#endif
 		break;
 	case KEY_DSA:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		pamsshagentauth_buffer_put_bignum2(b, key->dsa->p);
 		pamsshagentauth_buffer_put_bignum2(b, key->dsa->q);
 		pamsshagentauth_buffer_put_bignum2(b, key->dsa->g);
 		pamsshagentauth_buffer_put_bignum2(b, key->dsa->pub_key);
 		pamsshagentauth_buffer_put_bignum2(b, key->dsa->priv_key);
+#else
+		pamsshagentauth_buffer_put_bignum2(b, DSA_get0_p(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(b, DSA_get0_q(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(b, DSA_get0_g(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(b, DSA_get0_pub_key(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(b, DSA_get0_priv_key(key->dsa));
+#endif
 		break;
 	}
 	pamsshagentauth_buffer_put_cstring(b, comment);
@@ -605,9 +649,15 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
 
 	if (key->type == KEY_RSA1) {
 		pamsshagentauth_buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		pamsshagentauth_buffer_put_int(&msg, BN_num_bits(key->rsa->n));
 		pamsshagentauth_buffer_put_bignum(&msg, key->rsa->e);
 		pamsshagentauth_buffer_put_bignum(&msg, key->rsa->n);
+#else
+		pamsshagentauth_buffer_put_int(&msg, BN_num_bits(RSA_get0_n(key->rsa)));
+		pamsshagentauth_buffer_put_bignum(&msg, RSA_get0_e(key->rsa));
+		pamsshagentauth_buffer_put_bignum(&msg, RSA_get0_n(key->rsa));
+#endif
 	} else if (key->type == KEY_DSA || key->type == KEY_RSA) {
 		pamsshagentauth_key_to_blob(key, &blob, &blen);
 		pamsshagentauth_buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
diff --git a/bufbn.c b/bufbn.c
index 6a49c73..4ecedc1 100644
--- a/bufbn.c
+++ b/bufbn.c
@@ -151,7 +151,11 @@ pamsshagentauth_buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
 		pamsshagentauth_buffer_put_int(buffer, 0);
 		return 0;
 	}
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	if (value->neg) {
+#else
+	if (BN_is_negative(value)) {
+#endif
 		pamsshagentauth_logerror("buffer_put_bignum2_ret: negative numbers not supported");
 		return (-1);
 	}
diff --git a/cipher.h b/cipher.h
index 49bbc16..64f59ca 100644
--- a/cipher.h
+++ b/cipher.h
@@ -59,15 +59,18 @@
 #define CIPHER_DECRYPT		0
 
 typedef struct Cipher Cipher;
-typedef struct CipherContext CipherContext;
+// typedef struct CipherContext CipherContext;
 
 struct Cipher;
+/*
 struct CipherContext {
 	int	plaintext;
 	EVP_CIPHER_CTX evp;
 	Cipher *cipher;
 };
+*/
 
+/*
 u_int	 cipher_mask_ssh1(int);
 Cipher	*cipher_by_name(const char *);
 Cipher	*cipher_by_number(int);
@@ -88,4 +91,5 @@ void	 cipher_set_keyiv(CipherContext *, u_char *);
 int	 cipher_get_keyiv_len(const CipherContext *);
 int	 cipher_get_keycontext(const CipherContext *, u_char *);
 void	 cipher_set_keycontext(CipherContext *, u_char *);
+*/
 #endif				/* CIPHER_H */
diff --git a/kex.h b/kex.h
index 8e29c90..81ca57d 100644
--- a/kex.h
+++ b/kex.h
@@ -70,7 +70,7 @@ enum kex_exchange {
 #define KEX_INIT_SENT	0x0001
 
 typedef struct Kex Kex;
-typedef struct Mac Mac;
+// typedef struct Mac Mac;
 typedef struct Comp Comp;
 typedef struct Enc Enc;
 typedef struct Newkeys Newkeys;
@@ -84,6 +84,7 @@ struct Enc {
 	u_char	*key;
 	u_char	*iv;
 };
+/*
 struct Mac {
 	char	*name;
 	int	enabled;
@@ -95,11 +96,13 @@ struct Mac {
 	HMAC_CTX	evp_ctx;
 	struct umac_ctx *umac_ctx;
 };
+*/
 struct Comp {
 	int	type;
 	int	enabled;
 	char	*name;
 };
+/*
 struct Newkeys {
 	Enc	enc;
 	Mac	mac;
@@ -126,7 +129,9 @@ struct Kex {
 	int	(*host_key_index)(Key *);
 	void	(*kex[KEX_MAX])(Kex *);
 };
+*/
 
+/*
 Kex	*kex_setup(char *[PROPOSAL_MAX]);
 void	 kex_finish(Kex *);
 
@@ -152,6 +157,8 @@ kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *,
 void
 derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]);
 
+*/
+
 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
 void	dump_digest(char *, u_char *, int);
 #endif
diff --git a/key.c b/key.c
index 107a442..aedbbb5 100644
--- a/key.c
+++ b/key.c
@@ -77,15 +77,21 @@ pamsshagentauth_key_new(int type)
 	case KEY_RSA:
 		if ((rsa = RSA_new()) == NULL)
 			pamsshagentauth_fatal("key_new: RSA_new failed");
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((rsa->n = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new: BN_new failed");
 		if ((rsa->e = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new: BN_new failed");
+#else
+		if (RSA_set0_key(rsa, BN_new(), BN_new(), NULL) != 1)
+			pamsshagentauth_fatal("key_new: RSA_set0_key failed");
+#endif
 		k->rsa = rsa;
 		break;
 	case KEY_DSA:
 		if ((dsa = DSA_new()) == NULL)
 			pamsshagentauth_fatal("key_new: DSA_new failed");
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((dsa->p = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new: BN_new failed");
 		if ((dsa->q = BN_new()) == NULL)
@@ -94,6 +100,12 @@ pamsshagentauth_key_new(int type)
 			pamsshagentauth_fatal("key_new: BN_new failed");
 		if ((dsa->pub_key = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new: BN_new failed");
+#else
+		if (DSA_set0_pqg(dsa, BN_new(), BN_new(), BN_new()) != 1)
+			pamsshagentauth_fatal("key_new: DSA_set0_pqg failed");
+		if (DSA_set0_key(dsa, BN_new(), NULL) != 1)
+			pamsshagentauth_fatal("key_new: DSA_set0_key failed");
+#endif
 		k->dsa = dsa;
 		break;
 	case KEY_ECDSA:
@@ -118,6 +130,7 @@ pamsshagentauth_key_new_private(int type)
 	switch (k->type) {
 	case KEY_RSA1:
 	case KEY_RSA:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((k->rsa->d = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new_private: BN_new failed");
 		if ((k->rsa->iqmp = BN_new()) == NULL)
@@ -130,14 +143,30 @@ pamsshagentauth_key_new_private(int type)
 			pamsshagentauth_fatal("key_new_private: BN_new failed");
 		if ((k->rsa->dmp1 = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new_private: BN_new failed");
+#else
+		if (RSA_set0_key(k->rsa, NULL, NULL, BN_new()) != 1)
+			pamsshagentauth_fatal("key_new: RSA_set0_key failed");
+		if (RSA_set0_crt_params(k->rsa, BN_new(), BN_new(), BN_new()) != 1)
+			pamsshagentauth_fatal("key_new: RSA_set0_crt_params failed");
+		if (RSA_set0_factors(k->rsa, BN_new(), BN_new()) != 1)
+			pamsshagentauth_fatal("key_new: RSA_set0_factors failed");
+#endif
 		break;
 	case KEY_DSA:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((k->dsa->priv_key = BN_new()) == NULL)
 			pamsshagentauth_fatal("key_new_private: BN_new failed");
+#else
+		if (DSA_set0_key(k->dsa, NULL, BN_new()) != 1)
+			pamsshagentauth_fatal("key_new_private: DSA_set0_key failed");
+#endif
 		break;
 	case KEY_ECDSA:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if (EC_KEY_set_private_key(k->ecdsa, BN_new()) != 1)
 			pamsshagentauth_fatal("key_new_private: EC_KEY_set_private_key failed");
+#else
+#endif
 		break;
 	case KEY_ED25519:
 		RAND_bytes(k->ed25519->sk, sizeof(k->ed25519->sk));
@@ -195,14 +224,26 @@ pamsshagentauth_key_equal(const Key *a, const Key *b)
 	case KEY_RSA1:
 	case KEY_RSA:
 		return a->rsa != NULL && b->rsa != NULL &&
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		    BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
 		    BN_cmp(a->rsa->n, b->rsa->n) == 0;
+#else
+		    BN_cmp(RSA_get0_e(a->rsa), RSA_get0_e(b->rsa)) == 0 &&
+		    BN_cmp(RSA_get0_n(a->rsa), RSA_get0_n(b->rsa)) == 0;
+#endif
 	case KEY_DSA:
 		return a->dsa != NULL && b->dsa != NULL &&
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		    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;
+#else
+		    BN_cmp(DSA_get0_p(a->dsa), DSA_get0_p(b->dsa)) == 0 &&
+		    BN_cmp(DSA_get0_q(a->dsa), DSA_get0_q(b->dsa)) == 0 &&
+		    BN_cmp(DSA_get0_g(a->dsa), DSA_get0_g(b->dsa)) == 0 &&
+		    BN_cmp(DSA_get0_pub_key(a->dsa), DSA_get0_pub_key(b->dsa)) == 0;
+#endif
 	case KEY_ECDSA:
 		return a->ecdsa != NULL && b->ecdsa != NULL &&
 			EC_KEY_check_key(a->ecdsa) == 1 &&
@@ -231,7 +272,7 @@ pamsshagentauth_key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
     u_int *dgst_raw_length)
 {
 	const EVP_MD *md = NULL;
-	EVP_MD_CTX ctx;
+	EVP_MD_CTX *ctx;
 	u_char *blob = NULL;
 	u_char *retval = NULL;
 	u_int len = 0;
@@ -252,12 +293,21 @@ pamsshagentauth_key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
 	}
 	switch (k->type) {
 	case KEY_RSA1:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		nlen = BN_num_bytes(k->rsa->n);
 		elen = BN_num_bytes(k->rsa->e);
 		len = nlen + elen;
 		blob = pamsshagentauth_xmalloc(len);
 		BN_bn2bin(k->rsa->n, blob);
 		BN_bn2bin(k->rsa->e, blob + nlen);
+#else
+		nlen = BN_num_bytes(RSA_get0_n(k->rsa));
+		elen = BN_num_bytes(RSA_get0_e(k->rsa));
+		len = nlen + elen;
+		blob = pamsshagentauth_xmalloc(len);
+		BN_bn2bin(RSA_get0_n(k->rsa), blob);
+		BN_bn2bin(RSA_get0_e(k->rsa), blob + nlen);
+#endif
 		break;
 	case KEY_DSA:
 	case KEY_ECDSA:
@@ -273,11 +323,14 @@ pamsshagentauth_key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
 	}
 	if (blob != NULL) {
 		retval = pamsshagentauth_xmalloc(EVP_MAX_MD_SIZE);
-		EVP_DigestInit(&ctx, md);
-		EVP_DigestUpdate(&ctx, blob, len);
-		EVP_DigestFinal(&ctx, retval, dgst_raw_length);
+		/* XXX Errors from EVP_* functions are not hadled */
+		ctx = EVP_MD_CTX_create();
+		EVP_DigestInit(ctx, md);
+		EVP_DigestUpdate(ctx, blob, len);
+		EVP_DigestFinal(ctx, retval, dgst_raw_length);
 		memset(blob, 0, len);
 		pamsshagentauth_xfree(blob);
+		EVP_MD_CTX_destroy(ctx);
 	} else {
 		pamsshagentauth_fatal("key_fingerprint_raw: blob is null");
 	}
@@ -457,10 +510,17 @@ pamsshagentauth_key_read(Key *ret, char **cpp)
 			return -1;
 		*cpp = cp;
 		/* Get public exponent, public modulus. */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if (!read_bignum(cpp, ret->rsa->e))
 			return -1;
 		if (!read_bignum(cpp, ret->rsa->n))
 			return -1;
+#else
+		if (!read_bignum(cpp, RSA_get0_e(ret->rsa)))
+			return -1;
+		if (!read_bignum(cpp, RSA_get0_n(ret->rsa)))
+			return -1;
+#endif
 		success = 1;
 		break;
 	case KEY_UNSPEC:
@@ -583,10 +643,17 @@ pamsshagentauth_key_write(const Key *key, FILE *f)
 
 	if (key->type == KEY_RSA1 && key->rsa != NULL) {
 		/* size of modulus 'n' */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		bits = BN_num_bits(key->rsa->n);
 		fprintf(f, "%u", bits);
 		if (write_bignum(f, key->rsa->e) &&
 		    write_bignum(f, key->rsa->n)) {
+#else
+		bits = BN_num_bits(RSA_get0_n(key->rsa));
+		fprintf(f, "%u", bits);
+		if (write_bignum(f, RSA_get0_e(key->rsa)) &&
+		    write_bignum(f, RSA_get0_n(key->rsa))) {
+#endif
 			success = 1;
 		} else {
 			pamsshagentauth_logerror("key_write: failed for RSA key");
@@ -675,10 +742,17 @@ pamsshagentauth_key_size(const Key *k)
 {
 	switch (k->type) {
 	case KEY_RSA1:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	case KEY_RSA:
 		return BN_num_bits(k->rsa->n);
 	case KEY_DSA:
 		return BN_num_bits(k->dsa->p);
+#else
+	case KEY_RSA:
+		return BN_num_bits(RSA_get0_n(k->rsa));
+	case KEY_DSA:
+		return BN_num_bits(DSA_get0_p(k->dsa));
+#endif
 	case KEY_ECDSA:
 	{
 		int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(k->ecdsa));
@@ -769,17 +843,29 @@ pamsshagentauth_key_from_private(const Key *k)
 	switch (k->type) {
 	case KEY_DSA:
 		n = pamsshagentauth_key_new(k->type);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		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))
+#else
+		if ((BN_copy(DSA_get0_p(n->dsa), DSA_get0_p(k->dsa)) == NULL) ||
+		    (BN_copy(DSA_get0_q(n->dsa), DSA_get0_q(k->dsa)) == NULL) ||
+		    (BN_copy(DSA_get0_g(n->dsa), DSA_get0_g(k->dsa)) == NULL) ||
+		    (BN_copy(DSA_get0_pub_key(n->dsa), DSA_get0_pub_key(k->dsa)) == NULL))
+#endif
 			pamsshagentauth_fatal("key_from_private: BN_copy failed");
 		break;
 	case KEY_RSA:
 	case KEY_RSA1:
 		n = pamsshagentauth_key_new(k->type);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
 		    (BN_copy(n->rsa->e, k->rsa->e) == NULL))
+#else
+		if ((BN_copy(RSA_get0_n(n->rsa), RSA_get0_n(k->rsa)) == NULL) ||
+		    (BN_copy(RSA_get0_e(n->rsa), RSA_get0_e(k->rsa)) == NULL))
+#endif
 			pamsshagentauth_fatal("key_from_private: BN_copy failed");
 		break;
 	case KEY_ECDSA:
@@ -881,8 +967,13 @@ pamsshagentauth_key_from_blob(const u_char *blob, u_int blen)
 	switch (type) {
 	case KEY_RSA:
 		key = pamsshagentauth_key_new(type);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if (pamsshagentauth_buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
 		    pamsshagentauth_buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
+#else
+		if (pamsshagentauth_buffer_get_bignum2_ret(&b, RSA_get0_e(key->rsa)) == -1 ||
+		    pamsshagentauth_buffer_get_bignum2_ret(&b, RSA_get0_n(key->rsa)) == -1) {
+#endif
 			pamsshagentauth_logerror("key_from_blob: can't read rsa key");
 			pamsshagentauth_key_free(key);
 			key = NULL;
@@ -894,10 +985,17 @@ pamsshagentauth_key_from_blob(const u_char *blob, u_int blen)
 		break;
 	case KEY_DSA:
 		key = pamsshagentauth_key_new(type);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if (pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
 		    pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
 		    pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
 		    pamsshagentauth_buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
+#else
+		if (pamsshagentauth_buffer_get_bignum2_ret(&b, DSA_get0_p(key->dsa)) == -1 ||
+		    pamsshagentauth_buffer_get_bignum2_ret(&b, DSA_get0_q(key->dsa)) == -1 ||
+		    pamsshagentauth_buffer_get_bignum2_ret(&b, DSA_get0_g(key->dsa)) == -1 ||
+		    pamsshagentauth_buffer_get_bignum2_ret(&b, DSA_get0_pub_key(key->dsa)) == -1) {
+#endif
 			pamsshagentauth_logerror("key_from_blob: can't read dsa key");
 			pamsshagentauth_key_free(key);
 			key = NULL;
@@ -1015,6 +1113,7 @@ pamsshagentauth_key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
 	}
 	pamsshagentauth_buffer_init(&b);
 	switch (key->type) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	case KEY_DSA:
 		pamsshagentauth_buffer_put_cstring(&b, key_ssh_name(key));
 		pamsshagentauth_buffer_put_bignum2(&b, key->dsa->p);
@@ -1027,6 +1126,20 @@ pamsshagentauth_key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
 		pamsshagentauth_buffer_put_bignum2(&b, key->rsa->e);
 		pamsshagentauth_buffer_put_bignum2(&b, key->rsa->n);
 		break;
+#else
+	case KEY_DSA:
+		pamsshagentauth_buffer_put_cstring(&b, key_ssh_name(key));
+		pamsshagentauth_buffer_put_bignum2(&b, DSA_get0_p(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(&b, DSA_get0_q(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(&b, DSA_get0_g(key->dsa));
+		pamsshagentauth_buffer_put_bignum2(&b, DSA_get0_pub_key(key->dsa));
+		break;
+	case KEY_RSA:
+		pamsshagentauth_buffer_put_cstring(&b, key_ssh_name(key));
+		pamsshagentauth_buffer_put_bignum2(&b, RSA_get0_e(key->rsa));
+		pamsshagentauth_buffer_put_bignum2(&b, RSA_get0_n(key->rsa));
+		break;
+#endif
 	case KEY_ECDSA:
 	{
 		size_t l = 0;
@@ -1138,14 +1251,20 @@ pamsshagentauth_key_demote(const Key *k)
 	case KEY_RSA:
 		if ((pk->rsa = RSA_new()) == NULL)
 			pamsshagentauth_fatal("key_demote: RSA_new failed");
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
 			pamsshagentauth_fatal("key_demote: BN_dup failed");
 		if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
 			pamsshagentauth_fatal("key_demote: BN_dup failed");
+#else
+		if (RSA_set0_key(pk->rsa, BN_dup(RSA_get0_n(k->rsa)), BN_dup(RSA_get0_e(k->rsa)), NULL) != 1)
+			pamsshagentauth_fatal("key_demote: RSA_set0_key failed");
+#endif
 		break;
 	case KEY_DSA:
 		if ((pk->dsa = DSA_new()) == NULL)
 			pamsshagentauth_fatal("key_demote: DSA_new failed");
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
 			pamsshagentauth_fatal("key_demote: BN_dup failed");
 		if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
@@ -1154,6 +1273,12 @@ pamsshagentauth_key_demote(const Key *k)
 			pamsshagentauth_fatal("key_demote: BN_dup failed");
 		if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
 			pamsshagentauth_fatal("key_demote: BN_dup failed");
+#else
+		if (DSA_set0_pqg(pk->dsa, BN_dup(DSA_get0_p(k->dsa)), BN_dup(DSA_get0_q(k->dsa)), BN_dup(DSA_get0_g(k->dsa))) != 1)
+			pamsshagentauth_fatal("key_demote: DSA_set0_pqg failed");
+		if (DSA_set0_key(pk->dsa, BN_dup(DSA_get0_pub_key(k->dsa)), NULL) != 1)
+			pamsshagentauth_fatal("key_demote: DSA_set0_key failed");
+#endif
 		break;
 	case KEY_ECDSA:
 		pamsshagentauth_fatal("key_demote: implement me");
diff --git a/ssh-dss.c b/ssh-dss.c
index 9fdaa5d..1051ae2 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -48,37 +48,53 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
 {
 	DSA_SIG *sig;
 	const EVP_MD *evp_md = EVP_sha1();
-	EVP_MD_CTX md;
+	EVP_MD_CTX *md;
 	u_char digest[EVP_MAX_MD_SIZE], sigblob[SIGBLOB_LEN];
 	u_int rlen, slen, len, dlen;
 	Buffer b;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	const BIGNUM *r, *s;
+#endif
 
 	if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
 		pamsshagentauth_logerror("ssh_dss_sign: no DSA key");
 		return -1;
 	}
-	EVP_DigestInit(&md, evp_md);
-	EVP_DigestUpdate(&md, data, datalen);
-	EVP_DigestFinal(&md, digest, &dlen);
+	md = EVP_MD_CTX_create();
+	EVP_DigestInit(md, evp_md);
+	EVP_DigestUpdate(md, data, datalen);
+	EVP_DigestFinal(md, digest, &dlen);
 
 	sig = DSA_do_sign(digest, dlen, key->dsa);
 	memset(digest, 'd', sizeof(digest));
+	EVP_MD_CTX_destroy(md);
 
 	if (sig == NULL) {
 		pamsshagentauth_logerror("ssh_dss_sign: sign failed");
 		return -1;
 	}
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	rlen = BN_num_bytes(sig->r);
 	slen = BN_num_bytes(sig->s);
+#else
+	DSA_SIG_get0((const DSA_SIG *)sig, (const BIGNUM **)r, (const BIGNUM **)s);
+	rlen = BN_num_bytes(r);
+	slen = BN_num_bytes(s);
+#endif
 	if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
 		pamsshagentauth_logerror("bad sig size %u %u", rlen, slen);
 		DSA_SIG_free(sig);
 		return -1;
 	}
 	memset(sigblob, 0, SIGBLOB_LEN);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
 	BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
+#else
+	BN_bn2bin(r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
+	BN_bn2bin(s, sigblob+ SIGBLOB_LEN - slen);
+#endif
 	DSA_SIG_free(sig);
 
 	if (datafellows & SSH_BUG_SIGBLOB) {
@@ -110,11 +126,14 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
 {
 	DSA_SIG *sig;
 	const EVP_MD *evp_md = EVP_sha1();
-	EVP_MD_CTX md;
+	EVP_MD_CTX *md;
 	u_char digest[EVP_MAX_MD_SIZE], *sigblob;
 	u_int len, dlen;
 	int rlen, ret;
 	Buffer b;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	BIGNUM *r, *s;
+#endif
 
 	if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
 		pamsshagentauth_logerror("ssh_dss_verify: no DSA key");
@@ -157,6 +176,7 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
 	/* parse signature */
 	if ((sig = DSA_SIG_new()) == NULL)
 		pamsshagentauth_fatal("ssh_dss_verify: DSA_SIG_new failed");
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	if ((sig->r = BN_new()) == NULL)
 		pamsshagentauth_fatal("ssh_dss_verify: BN_new failed");
 	if ((sig->s = BN_new()) == NULL)
@@ -164,18 +184,33 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
 	if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) ||
 	    (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL))
 		pamsshagentauth_fatal("ssh_dss_verify: BN_bin2bn failed");
+#else
+	if ((r = BN_new()) == NULL)
+		pamsshagentauth_fatal("ssh_dss_verify: BN_new failed");
+	if ((s = BN_new()) == NULL)
+		pamsshagentauth_fatal("ssh_dss_verify: BN_new failed");
+	if (DSA_SIG_set0(sig, r, s) != 1)
+		pamsshagentauth_fatal("ssh_dss_verify: DSA_SIG_set0 failed");
+	if ((BN_bin2bn(sigblob, INTBLOB_LEN, r) == NULL) ||
+	    (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, s) == NULL))
+		pamsshagentauth_fatal("ssh_dss_verify: BN_bin2bn failed");
+	if (DSA_SIG_set0(sig, r, s) != 1)
+		pamsshagentauth_fatal("ssh_dss_verify: DSA_SIG_set0 failed");
+#endif
 
 	/* clean up */
 	memset(sigblob, 0, len);
 	pamsshagentauth_xfree(sigblob);
 
 	/* sha1 the data */
-	EVP_DigestInit(&md, evp_md);
-	EVP_DigestUpdate(&md, data, datalen);
-	EVP_DigestFinal(&md, digest, &dlen);
+	md = EVP_MD_CTX_create();
+	EVP_DigestInit(md, evp_md);
+	EVP_DigestUpdate(md, data, datalen);
+	EVP_DigestFinal(md, digest, &dlen);
 
 	ret = DSA_do_verify(digest, dlen, sig, key->dsa);
 	memset(digest, 'd', sizeof(digest));
+	EVP_MD_CTX_destroy(md);
 
 	DSA_SIG_free(sig);
 
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index efa0f3d..c213959 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -41,22 +41,27 @@ ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
 {
     ECDSA_SIG *sig;
     const EVP_MD *evp_md = evp_from_key(key);
-    EVP_MD_CTX md;
+    EVP_MD_CTX *md;
     u_char digest[EVP_MAX_MD_SIZE];
     u_int len, dlen;
     Buffer b, bb;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	BIGNUM *r, *s;
+#endif
 
     if (key == NULL || key->type != KEY_ECDSA || key->ecdsa == NULL) {
         pamsshagentauth_logerror("ssh_ecdsa_sign: no ECDSA key");
         return -1;
     }
 
-    EVP_DigestInit(&md, evp_md);
-    EVP_DigestUpdate(&md, data, datalen);
-    EVP_DigestFinal(&md, digest, &dlen);
+    md = EVP_MD_CTX_create();
+    EVP_DigestInit(md, evp_md);
+    EVP_DigestUpdate(md, data, datalen);
+    EVP_DigestFinal(md, digest, &dlen);
 
     sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
     memset(digest, 'd', sizeof(digest));
+    EVP_MD_CTX_destroy(md);
 
     if (sig == NULL) {
         pamsshagentauth_logerror("ssh_ecdsa_sign: sign failed");
@@ -64,8 +69,14 @@ ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
     }
 
     pamsshagentauth_buffer_init(&bb);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
     if (pamsshagentauth_buffer_get_bignum2_ret(&bb, sig->r) == -1 ||
         pamsshagentauth_buffer_get_bignum2_ret(&bb, sig->s) == -1) {
+#else
+    DSA_SIG_get0(sig, &r, &s);
+    if (pamsshagentauth_buffer_get_bignum2_ret(&bb, r) == -1 ||
+        pamsshagentauth_buffer_get_bignum2_ret(&bb, s) == -1) {
+#endif
         pamsshagentauth_logerror("couldn't serialize signature");
         ECDSA_SIG_free(sig);
         return -1;
@@ -94,11 +105,14 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
 {
     ECDSA_SIG *sig;
     const EVP_MD *evp_md = evp_from_key(key);
-    EVP_MD_CTX md;
+    EVP_MD_CTX *md;
     u_char digest[EVP_MAX_MD_SIZE], *sigblob;
     u_int len, dlen;
     int rlen, ret;
     Buffer b;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+	BIGNUM *r, *s;
+#endif
 
     if (key == NULL || key->type != KEY_ECDSA || key->ecdsa == NULL) {
         pamsshagentauth_logerror("ssh_ecdsa_sign: no ECDSA key");
@@ -127,8 +141,14 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
 
     pamsshagentauth_buffer_init(&b);
     pamsshagentauth_buffer_append(&b, sigblob, len);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
     if ((pamsshagentauth_buffer_get_bignum2_ret(&b, sig->r) == -1) ||
         (pamsshagentauth_buffer_get_bignum2_ret(&b, sig->s) == -1))
+#else
+    DSA_SIG_get0(sig, &r, &s);
+    if ((pamsshagentauth_buffer_get_bignum2_ret(&b, r) == -1) ||
+        (pamsshagentauth_buffer_get_bignum2_ret(&b, s) == -1))
+#endif
         pamsshagentauth_fatal("ssh_ecdsa_verify:"
             "pamsshagentauth_buffer_get_bignum2_ret failed");
 
@@ -137,16 +157,18 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
     pamsshagentauth_xfree(sigblob);
 
     /* sha256 the data */
-    EVP_DigestInit(&md, evp_md);
-    EVP_DigestUpdate(&md, data, datalen);
-    EVP_DigestFinal(&md, digest, &dlen);
+    md = EVP_MD_CTX_create();
+    EVP_DigestInit(md, evp_md);
+    EVP_DigestUpdate(md, data, datalen);
+    EVP_DigestFinal(md, digest, &dlen);
 
     ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
     memset(digest, 'd', sizeof(digest));
+    EVP_MD_CTX_destroy(md);
 
     ECDSA_SIG_free(sig);
 
     pamsshagentauth_verbose("ssh_ecdsa_verify: signature %s",
         ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
     return ret;
-}
\ No newline at end of file
+}
diff --git a/ssh-rsa.c b/ssh-rsa.c
index d05844b..9d74eb6 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -40,7 +40,7 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
     const u_char *data, u_int datalen)
 {
 	const EVP_MD *evp_md;
-	EVP_MD_CTX md;
+	EVP_MD_CTX *md;
 	u_char digest[EVP_MAX_MD_SIZE], *sig;
 	u_int slen, dlen, len;
 	int ok, nid;
@@ -55,6 +55,7 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
 		pamsshagentauth_logerror("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid);
 		return -1;
 	}
+	md = EVP_MD_CTX_create();
 	EVP_DigestInit(&md, evp_md);
 	EVP_DigestUpdate(&md, data, datalen);
 	EVP_DigestFinal(&md, digest, &dlen);
@@ -64,6 +65,7 @@ ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
 
 	ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
 	memset(digest, 'd', sizeof(digest));
+	EVP_MD_CTX_destroy(md);
 
 	if (ok != 1) {
 		int ecode = ERR_get_error();
@@ -107,7 +109,7 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
 {
 	Buffer b;
 	const EVP_MD *evp_md;
-	EVP_MD_CTX md;
+	EVP_MD_CTX *md;
 	char *ktype;
 	u_char digest[EVP_MAX_MD_SIZE], *sigblob;
 	u_int len, dlen, modlen;
@@ -117,9 +119,17 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
 		pamsshagentauth_logerror("ssh_rsa_verify: no RSA key");
 		return -1;
 	}
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 	if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+#else
+	if (BN_num_bits(RSA_get0_n(key->rsa)) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+#endif
 		pamsshagentauth_logerror("ssh_rsa_verify: RSA modulus too small: %d < minimum %d bits",
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 		    BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
+#else
+		    BN_num_bits(RSA_get0_n(key->rsa)), SSH_RSA_MINIMUM_MODULUS_SIZE);
+#endif
 		return -1;
 	}
 	pamsshagentauth_buffer_init(&b);
@@ -161,12 +171,14 @@ ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
 		pamsshagentauth_xfree(sigblob);
 		return -1;
 	}
-	EVP_DigestInit(&md, evp_md);
-	EVP_DigestUpdate(&md, data, datalen);
-	EVP_DigestFinal(&md, digest, &dlen);
+	md = EVP_MD_CTX_create();
+	EVP_DigestInit(md, evp_md);
+	EVP_DigestUpdate(md, data, datalen);
+	EVP_DigestFinal(md, digest, &dlen);
 
 	ret = openssh_RSA_verify(nid, digest, dlen, sigblob, len, key->rsa);
 	memset(digest, 'd', sizeof(digest));
+	EVP_MD_CTX_destroy(md);
 	memset(sigblob, 's', len);
 	pamsshagentauth_xfree(sigblob);
 	pamsshagentauth_verbose("ssh_rsa_verify: signature %scorrect", (ret==0) ? "in" : "");
