From ebe9dcf842988e8e76dde9cbcd18a182c9acd289 Mon Sep 17 00:00:00 2001
From: Jonathan Helmus <jjhelmus@gmail.com>
Date: Tue, 30 Oct 2018 11:05:43 -0500
Subject: [PATCH 5/6] openssl 1.1.1 support

adapted from FreeBSD patches

xref: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=225891
---
 Makefile.am           |   5 +
 crypto-compat.c       | 446 +++++++++++++++++++++++++++++++++++++++++++++++
 crypto-compat.h       |  73 ++++++++
 lib/Makefile.am       |   4 +-
 plugins/Makefile.am   |  13 +-
 plugins/ntlm.c        |  40 ++++-
 plugins/otp.c         | 107 ++++++++----
 plugins/passdss.c     | 290 ++++++++++++++++++-------------
 plugins/srp.c         | 465 ++++++++++++++++++++++++++------------------------
 saslauthd/Makefile.am |   6 +-
 saslauthd/lak.c       |   3 +
 11 files changed, 1060 insertions(+), 392 deletions(-)
 create mode 100644 crypto-compat.c
 create mode 100644 crypto-compat.h

diff --git a/Makefile.am b/Makefile.am
index 2e78217..313ddca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -71,6 +71,11 @@ EXTRA_DIST=config cmulocal win32 mac dlcompat-20010505 NTMakefile INSTALL.TXT \
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = libsasl2.pc
 
+noinst_LTLIBRARIES = libcrypto_compat.la
+
+libcrypto_compat_la_SOURCES = crypto-compat.c crypto-compat.h
+libcrypto_compat_la_LDFLAGS = -version-info $(crypto_compat_version) -no-undefined
+
 dist-hook:
 	@find $(distdir) -exec chmod o+w {} ';'
 	@find $(distdir) -name CVS -print | xargs -t rm -rf
diff --git a/crypto-compat.c b/crypto-compat.c
new file mode 100644
index 0000000..f4717b6
--- /dev/null
+++ b/crypto-compat.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "crypto-compat.h"
+
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER < 0x10100000L)
+
+#include <string.h>
+#include <openssl/engine.h>
+
+static void *OPENSSL_zalloc(size_t num)
+{
+    void *ret = OPENSSL_malloc(num);
+
+    if (ret != NULL)
+        memset(ret, 0, num);
+    return ret;
+}
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+    /* If the fields n and e in r are NULL, the corresponding input
+     * parameters MUST be non-NULL for n and e.  d may be
+     * left NULL (in case only the public key is used).
+     */
+    if ((r->n == NULL && n == NULL)
+        || (r->e == NULL && e == NULL))
+        return 0;
+
+    if (n != NULL) {
+        BN_free(r->n);
+        r->n = n;
+    }
+    if (e != NULL) {
+        BN_free(r->e);
+        r->e = e;
+    }
+    if (d != NULL) {
+        BN_free(r->d);
+        r->d = d;
+    }
+
+    return 1;
+}
+
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+    /* If the fields p and q in r are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((r->p == NULL && p == NULL)
+        || (r->q == NULL && q == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(r->p);
+        r->p = p;
+    }
+    if (q != NULL) {
+        BN_free(r->q);
+        r->q = q;
+    }
+
+    return 1;
+}
+
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+    /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((r->dmp1 == NULL && dmp1 == NULL)
+        || (r->dmq1 == NULL && dmq1 == NULL)
+        || (r->iqmp == NULL && iqmp == NULL))
+        return 0;
+
+    if (dmp1 != NULL) {
+        BN_free(r->dmp1);
+        r->dmp1 = dmp1;
+    }
+    if (dmq1 != NULL) {
+        BN_free(r->dmq1);
+        r->dmq1 = dmq1;
+    }
+    if (iqmp != NULL) {
+        BN_free(r->iqmp);
+        r->iqmp = iqmp;
+    }
+
+    return 1;
+}
+
+void RSA_get0_key(const RSA *r,
+                  const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+    if (n != NULL)
+        *n = r->n;
+    if (e != NULL)
+        *e = r->e;
+    if (d != NULL)
+        *d = r->d;
+}
+
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+    if (p != NULL)
+        *p = r->p;
+    if (q != NULL)
+        *q = r->q;
+}
+
+void RSA_get0_crt_params(const RSA *r,
+                         const BIGNUM **dmp1, const BIGNUM **dmq1,
+                         const BIGNUM **iqmp)
+{
+    if (dmp1 != NULL)
+        *dmp1 = r->dmp1;
+    if (dmq1 != NULL)
+        *dmq1 = r->dmq1;
+    if (iqmp != NULL)
+        *iqmp = r->iqmp;
+}
+
+void DSA_get0_pqg(const DSA *d,
+                  const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+    if (p != NULL)
+        *p = d->p;
+    if (q != NULL)
+        *q = d->q;
+    if (g != NULL)
+        *g = d->g;
+}
+
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    /* If the fields p, q and g in d are NULL, the corresponding input
+     * parameters MUST be non-NULL.
+     */
+    if ((d->p == NULL && p == NULL)
+        || (d->q == NULL && q == NULL)
+        || (d->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(d->p);
+        d->p = p;
+    }
+    if (q != NULL) {
+        BN_free(d->q);
+        d->q = q;
+    }
+    if (g != NULL) {
+        BN_free(d->g);
+        d->g = g;
+    }
+
+    return 1;
+}
+
+void DSA_get0_key(const DSA *d,
+                  const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+    if (pub_key != NULL)
+        *pub_key = d->pub_key;
+    if (priv_key != NULL)
+        *priv_key = d->priv_key;
+}
+
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    /* If the field pub_key in d is NULL, the corresponding input
+     * parameters MUST be non-NULL.  The priv_key field may
+     * be left NULL.
+     */
+    if (d->pub_key == NULL && pub_key == NULL)
+        return 0;
+
+    if (pub_key != NULL) {
+        BN_free(d->pub_key);
+        d->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(d->priv_key);
+        d->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+    if (pr != NULL)
+        *pr = sig->r;
+    if (ps != NULL)
+        *ps = sig->s;
+}
+
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+    if (r == NULL || s == NULL)
+        return 0;
+    BN_clear_free(sig->r);
+    BN_clear_free(sig->s);
+    sig->r = r;
+    sig->s = s;
+    return 1;
+}
+
+void DH_get0_pqg(const DH *dh,
+                 const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
+{
+    if (p != NULL)
+        *p = dh->p;
+    if (q != NULL)
+        *q = dh->q;
+    if (g != NULL)
+        *g = dh->g;
+}
+
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+    /* If the fields p and g in d are NULL, the corresponding input
+     * parameters MUST be non-NULL.  q may remain NULL.
+     */
+    if ((dh->p == NULL && p == NULL)
+        || (dh->g == NULL && g == NULL))
+        return 0;
+
+    if (p != NULL) {
+        BN_free(dh->p);
+        dh->p = p;
+    }
+    if (q != NULL) {
+        BN_free(dh->q);
+        dh->q = q;
+    }
+    if (g != NULL) {
+        BN_free(dh->g);
+        dh->g = g;
+    }
+
+    if (q != NULL) {
+        dh->length = BN_num_bits(q);
+    }
+
+    return 1;
+}
+
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+    if (pub_key != NULL)
+        *pub_key = dh->pub_key;
+    if (priv_key != NULL)
+        *priv_key = dh->priv_key;
+}
+
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+    /* If the field pub_key in dh is NULL, the corresponding input
+     * parameters MUST be non-NULL.  The priv_key field may
+     * be left NULL.
+     */
+    if (dh->pub_key == NULL && pub_key == NULL)
+        return 0;
+
+    if (pub_key != NULL) {
+        BN_free(dh->pub_key);
+        dh->pub_key = pub_key;
+    }
+    if (priv_key != NULL) {
+        BN_free(dh->priv_key);
+        dh->priv_key = priv_key;
+    }
+
+    return 1;
+}
+
+int DH_set_length(DH *dh, long length)
+{
+    dh->length = length;
+    return 1;
+}
+
+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx)
+{
+    return ctx->iv;
+}
+
+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx)
+{
+    return ctx->iv;
+}
+
+EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
+}
+
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+    EVP_MD_CTX_cleanup(ctx);
+    OPENSSL_free(ctx);
+}
+
+EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void)
+{
+    return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX));
+}
+
+void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
+{
+    OPENSSL_free(ctx);
+}
+
+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)
+{
+    RSA_METHOD *ret;
+
+    ret = OPENSSL_malloc(sizeof(RSA_METHOD));
+
+    if (ret != NULL) {
+        memcpy(ret, meth, sizeof(*meth));
+        ret->name = OPENSSL_strdup(meth->name);
+        if (ret->name == NULL) {
+            OPENSSL_free(ret);
+            return NULL;
+        }
+    }
+
+    return ret;
+}
+
+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
+{
+    char *tmpname;
+
+    tmpname = OPENSSL_strdup(name);
+    if (tmpname == NULL) {
+        return 0;
+    }
+
+    OPENSSL_free((char *)meth->name);
+    meth->name = tmpname;
+
+    return 1;
+}
+
+int RSA_meth_set_priv_enc(RSA_METHOD *meth,
+                          int (*priv_enc) (int flen, const unsigned char *from,
+                                           unsigned char *to, RSA *rsa,
+                                           int padding))
+{
+    meth->rsa_priv_enc = priv_enc;
+    return 1;
+}
+
+int RSA_meth_set_priv_dec(RSA_METHOD *meth,
+                          int (*priv_dec) (int flen, const unsigned char *from,
+                                           unsigned char *to, RSA *rsa,
+                                           int padding))
+{
+    meth->rsa_priv_dec = priv_dec;
+    return 1;
+}
+
+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa))
+{
+    meth->finish = finish;
+    return 1;
+}
+
+void RSA_meth_free(RSA_METHOD *meth)
+{
+    if (meth != NULL) {
+        OPENSSL_free((char *)meth->name);
+        OPENSSL_free(meth);
+    }
+}
+
+int RSA_bits(const RSA *r)
+{
+    return (BN_num_bits(r->n));
+}
+
+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
+{
+    if (pkey->type != EVP_PKEY_RSA) {
+        return NULL;
+    }
+    return pkey->pkey.rsa;
+}
+
+HMAC_CTX *HMAC_CTX_new(void)
+{
+    HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
+    if (ctx != NULL) {
+        if (!HMAC_CTX_reset(ctx)) {
+            HMAC_CTX_free(ctx);
+            return NULL;
+        }
+    }
+    return ctx;
+}
+
+void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+    if (ctx != NULL) {
+        HMAC_CTX_cleanup(ctx);
+        OPENSSL_free(ctx);
+    }
+}
+
+int HMAC_CTX_reset(HMAC_CTX *ctx)
+{
+    HMAC_CTX_init(ctx);
+    return 1;
+}
+
+
+#endif /* HAVE_OPENSSL && OPENSSL_VERSION_NUMBER */
diff --git a/crypto-compat.h b/crypto-compat.h
new file mode 100644
index 0000000..73424ad
--- /dev/null
+++ b/crypto-compat.h
@@ -0,0 +1,73 @@
+#ifndef LIBCRYPTO_COMPAT_H
+#define LIBCRYPTO_COMPAT_H
+
+#include <config.h>
+
+#ifdef HAVE_OPENSSL
+
+#include <openssl/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/ecdsa.h>
+#include <openssl/dh.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+
+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
+void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);
+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);
+void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);
+
+void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
+
+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
+
+void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+int DH_set_length(DH *dh, long length);
+
+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
+EVP_MD_CTX *EVP_MD_CTX_new(void);
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
+EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void);
+void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx);
+#define EVP_CIPHER_impl_ctx_size(e) e->ctx_size
+#define EVP_CIPHER_CTX_get_cipher_data(ctx) ctx->cipher_data
+
+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);
+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);
+#define RSA_meth_get_finish(meth) meth->finish
+int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
+int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));
+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa));
+void RSA_meth_free(RSA_METHOD *meth);
+
+int RSA_bits(const RSA *r);
+
+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
+
+HMAC_CTX *HMAC_CTX_new(void);
+void HMAC_CTX_free(HMAC_CTX *ctx);
+int HMAC_CTX_reset(HMAC_CTX *ctx);
+
+
+#endif /* OPENSSL_VERSION_NUMBER */
+
+#endif /* HAVE_OPENSSL */
+
+#endif /* LIBCRYPTO_COMPAT_H */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index fcc99b6..6c24bc0 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -65,8 +65,8 @@ lib_LTLIBRARIES = libsasl2.la
 
 libsasl2_la_SOURCES = $(common_sources) $(common_headers)
 libsasl2_la_LDFLAGS = -version-info $(sasl_version)
-libsasl2_la_DEPENDENCIES = $(LTLIBOBJS)
-libsasl2_la_LIBADD = $(LTLIBOBJS) $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR)
+libsasl2_la_DEPENDENCIES = $(LTLIBOBJS) $(CRYPTO_COMPAT_OBJS)
+libsasl2_la_LIBADD = $(LTLIBOBJS) $(SASL_DL_LIB) $(LIB_SOCKET) $(LIB_DOOR) $(CRYPTO_COMPAT_OBJS)
 
 install-exec-hook:
 
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index d570de1..09f064f 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -53,6 +53,7 @@ INCLUDES=-I$(top_srcdir)/include -I$(top_srcdir)/lib -I$(top_srcdir)/sasldb -I$(
 AM_LDFLAGS = -module -export-dynamic -rpath $(plugindir) -version-info $(plugin_version)
 
 COMPAT_OBJS = @LTGETADDRINFOOBJS@ @LTGETNAMEINFOOBJS@ @LTSNPRINTFOBJS@
+CRYPTO_COMPAT_OBJS = $(top_builddir)/common/libcrypto_compat.la
 
 EXTRA_DIST = makeinit.sh NTMakefile
 noinst_SCRIPTS = makeinit.sh
@@ -106,20 +107,20 @@ liblogin_la_DEPENDENCIES = $(COMPAT_OBJS)
 liblogin_la_LIBADD = $(PLAIN_LIBS) $(COMPAT_OBJS)
 
 libsrp_la_SOURCES = srp.c srp_init.c $(common_sources)
-libsrp_la_DEPENDENCIES = $(COMPAT_OBJS)
-libsrp_la_LIBADD = $(SRP_LIBS) $(COMPAT_OBJS)
+libsrp_la_DEPENDENCIES = $(COMPAT_OBJS) $(CRYPTO_COMPAT_OBJS)
+libsrp_la_LIBADD = $(SRP_LIBS) $(COMPAT_OBJS) $(CRYPTO_COMPAT_OBJS)
 
 libotp_la_SOURCES = otp.c otp_init.c otp.h $(common_sources)
 libotp_la_DEPENDENCIES = $(COMPAT_OBJS)
 libotp_la_LIBADD = $(OTP_LIBS) $(COMPAT_OBJS)
 
 libntlm_la_SOURCES = ntlm.c ntlm_init.c $(common_sources)
-libntlm_la_DEPENDENCIES = $(COMPAT_OBJS)
-libntlm_la_LIBADD = $(NTLM_LIBS) $(COMPAT_OBJS)
+libntlm_la_DEPENDENCIES = $(COMPAT_OBJS) $(CRYPTO_COMPAT_OBJS)
+libntlm_la_LIBADD = $(NTLM_LIBS) $(COMPAT_OBJS) $(CRYPTO_COMPAT_OBJS)
 
 libpassdss_la_SOURCES = passdss.c passdss_init.c $(common_sources)
-libpassdss_la_DEPENDENCIES = $(COMPAT_OBJS)
-libpassdss_la_LIBADD = $(PASSDSS_LIBS) $(COMPAT_OBJS)
+libpassdss_la_DEPENDENCIES = $(COMPAT_OBJS) $(CRYPTO_COMPAT_OBJS)
+libpassdss_la_LIBADD = $(PASSDSS_LIBS) $(COMPAT_OBJS) $(CRYPTO_COMPAT_OBJS)
 
 # Auxprop Plugins
 libsasldb_la_SOURCES = sasldb.c sasldb_init.c $(common_sources)
diff --git a/plugins/ntlm.c b/plugins/ntlm.c
index 79ea47c..5c25879 100644
--- a/plugins/ntlm.c
+++ b/plugins/ntlm.c
@@ -417,6 +417,29 @@ static unsigned char *P24(unsigned char *P24, unsigned char *P21,
     return P24;
 }
 
+static HMAC_CTX *_plug_HMAC_CTX_new(const sasl_utils_t *utils)
+{
+    utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_new()");
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+    return HMAC_CTX_new();
+#else
+    return utils->malloc(sizeof(EVP_MD_CTX));
+#endif    
+}
+
+static void _plug_HMAC_CTX_free(HMAC_CTX *ctx, const sasl_utils_t *utils)
+{
+    utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_free()");
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+    HMAC_CTX_free(ctx);
+#else
+    HMAC_cleanup(ctx);
+    utils->free(ctx);
+#endif    
+}
+
 static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd,
 			 const char *authid, const char *target,
 			 const unsigned char *challenge,
@@ -424,7 +447,7 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd,
 			 const sasl_utils_t *utils,
 			 char **buf, unsigned *buflen, int *result)
 {
-    HMAC_CTX ctx;
+    HMAC_CTX *ctx = NULL;
     unsigned char hash[EVP_MAX_MD_SIZE];
     char *upper;
     unsigned int len;
@@ -435,6 +458,10 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd,
 	SETERROR(utils, "cannot allocate NTLMv2 hash");
 	*result = SASL_NOMEM;
     }
+    else if ((ctx = _plug_HMAC_CTX_new(utils)) == NULL) {
+        SETERROR(utils, "cannot allocate HMAC CTX");
+        *result = SASL_NOMEM;
+    }
     else {
 	/* NTLMv2hash = HMAC-MD5(NTLMhash, unicode(ucase(authid + domain))) */
 	P16_nt(hash, passwd, utils, buf, buflen, result);
@@ -449,17 +476,18 @@ static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd,
 	HMAC(EVP_md5(), hash, MD4_DIGEST_LENGTH, *buf, 2 * len, hash, &len);
 
 	/* V2 = HMAC-MD5(NTLMv2hash, challenge + blob) + blob */
-	HMAC_Init(&ctx, hash, len, EVP_md5());
-	HMAC_Update(&ctx, challenge, NTLM_NONCE_LENGTH);
-	HMAC_Update(&ctx, blob, bloblen);
-	HMAC_Final(&ctx, V2, &len);
-	HMAC_cleanup(&ctx);
+	HMAC_Init_ex(ctx, hash, len, EVP_md5(), NULL);
+	HMAC_Update(ctx, challenge, NTLM_NONCE_LENGTH);
+	HMAC_Update(ctx, blob, bloblen);
+	HMAC_Final(ctx, V2, &len);
 
 	/* the blob is concatenated outside of this function */
 
 	*result = SASL_OK;
     }
 
+    if (ctx) _plug_HMAC_CTX_free(ctx, utils);
+
     return V2;
 }
 
diff --git a/plugins/otp.c b/plugins/otp.c
index dd73065..6d84bed 100644
--- a/plugins/otp.c
+++ b/plugins/otp.c
@@ -96,6 +96,28 @@ static algorithm_option_t algorithm_options[] = {
     {NULL,	0,	NULL}
 };
 
+static EVP_MD_CTX *_plug_EVP_MD_CTX_new(const sasl_utils_t *utils)
+{
+    utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_new()");
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+    return EVP_MD_CTX_new();
+#else
+    return utils->malloc(sizeof(EVP_MD_CTX));
+#endif    
+}
+
+static void _plug_EVP_MD_CTX_free(EVP_MD_CTX *ctx, const sasl_utils_t *utils)
+{
+    utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_free()");
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+    EVP_MD_CTX_free(ctx);
+#else
+    utils->free(ctx);
+#endif    
+}
+
 /* Convert the binary data into ASCII hex */
 void bin2hex(unsigned char *bin, int binlen, char *hex)
 {
@@ -116,17 +138,16 @@ void bin2hex(unsigned char *bin, int binlen, char *hex)
  * swabbing bytes if necessary.
  */
 static void otp_hash(const EVP_MD *md, char *in, size_t inlen,
-		     unsigned char *out, int swab)
+		     unsigned char *out, int swab, EVP_MD_CTX *mdctx)
 {
-    EVP_MD_CTX mdctx;
     char hash[EVP_MAX_MD_SIZE];
     unsigned int i;
     int j;
     unsigned hashlen;
     
-    EVP_DigestInit(&mdctx, md);
-    EVP_DigestUpdate(&mdctx, in, inlen);
-    EVP_DigestFinal(&mdctx, hash, &hashlen);
+    EVP_DigestInit(mdctx, md);
+    EVP_DigestUpdate(mdctx, in, inlen);
+    EVP_DigestFinal(mdctx, hash, &hashlen);
     
     /* Fold the result into 64 bits */
     for (i = OTP_HASH_SIZE; i < hashlen; i++) {
@@ -149,31 +170,42 @@ static int generate_otp(const sasl_utils_t *utils,
 			char *secret, char *otp)
 {
     const EVP_MD *md;
-    char *key;
+    EVP_MD_CTX *mdctx = NULL;
+    char *key = NULL;
+    int r = SASL_OK;
     
     if (!(md = EVP_get_digestbyname(alg->evp_name))) {
 	utils->seterror(utils->conn, 0,
 			"OTP algorithm %s is not available", alg->evp_name);
 	return SASL_FAIL;
     }
-    
+
+    if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) {
+	SETERROR(utils, "cannot allocate MD CTX");
+	r = SASL_NOMEM;
+        goto done;
+    }    
+
     if ((key = utils->malloc(strlen(seed) + strlen(secret) + 1)) == NULL) {
 	SETERROR(utils, "cannot allocate OTP key");
-	return SASL_NOMEM;
+        r = SASL_NOMEM;
+        goto done;
     }
     
     /* initial step */
     strcpy(key, seed);
     strcat(key, secret);
-    otp_hash(md, key, strlen(key), otp, alg->swab);
+    otp_hash(md, key, strlen(key), otp, alg->swab, mdctx);
     
     /* computation step */
     while (seq-- > 0)
-	otp_hash(md, otp, OTP_HASH_SIZE, otp, alg->swab);
-    
-    utils->free(key);
+	otp_hash(md, otp, OTP_HASH_SIZE, otp, alg->swab, mdctx);
+
+ done:
+    if (key) utils->free(key);
+    if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils);
     
-    return SASL_OK;
+    return r;
 }
 
 static int parse_challenge(const sasl_utils_t *utils,
@@ -693,7 +725,8 @@ static int strptrcasecmp(const void *arg1, const void *arg2)
 
 /* Convert the 6 words into binary data */
 static int word2bin(const sasl_utils_t *utils,
-		    char *words, unsigned char *bin, const EVP_MD *md)
+		    char *words, unsigned char *bin, const EVP_MD *md,
+                    EVP_MD_CTX *mdctx)
 {
     int i, j;
     char *c, *word, buf[OTP_RESPONSE_MAX+1];
@@ -752,13 +785,12 @@ static int word2bin(const sasl_utils_t *utils,
 	
 	/* alternate dictionary */
 	if (alt_dict) {
-	    EVP_MD_CTX mdctx;
 	    char hash[EVP_MAX_MD_SIZE];
 	    int hashlen;
 	    
-	    EVP_DigestInit(&mdctx, md);
-	    EVP_DigestUpdate(&mdctx, word, strlen(word));
-	    EVP_DigestFinal(&mdctx, hash, &hashlen);
+	    EVP_DigestInit(mdctx, md);
+	    EVP_DigestUpdate(mdctx, word, strlen(word));
+	    EVP_DigestFinal(mdctx, hash, &hashlen);
 	    
 	    /* use lowest 11 bits */
 	    x = ((hash[hashlen-2] & 0x7) << 8) | hash[hashlen-1];
@@ -802,6 +834,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 			   char *response)
 {
     const EVP_MD *md;
+    EVP_MD_CTX *mdctx = NULL;
     char *c;
     int do_init = 0;
     unsigned char cur_otp[OTP_HASH_SIZE], prev_otp[OTP_HASH_SIZE];
@@ -815,6 +848,11 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 	return SASL_FAIL;
     }
     
+    if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) {
+	SETERROR(utils, "cannot allocate MD CTX");
+	return SASL_NOMEM;
+    }
+    
     /* eat leading whitespace */
     c = response;
     while (isspace((int) *c)) c++;
@@ -824,7 +862,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 	    r = hex2bin(c+strlen(OTP_HEX_TYPE), cur_otp, OTP_HASH_SIZE);
 	}
 	else if (!strncasecmp(c, OTP_WORD_TYPE, strlen(OTP_WORD_TYPE))) {
-	    r = word2bin(utils, c+strlen(OTP_WORD_TYPE), cur_otp, md);
+	    r = word2bin(utils, c+strlen(OTP_WORD_TYPE), cur_otp, md, mdctx);
 	}
 	else if (!strncasecmp(c, OTP_INIT_HEX_TYPE,
 			      strlen(OTP_INIT_HEX_TYPE))) {
@@ -834,7 +872,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 	else if (!strncasecmp(c, OTP_INIT_WORD_TYPE,
 			      strlen(OTP_INIT_WORD_TYPE))) {
 	    do_init = 1;
-	    r = word2bin(utils, c+strlen(OTP_INIT_WORD_TYPE), cur_otp, md);
+	    r = word2bin(utils, c+strlen(OTP_INIT_WORD_TYPE), cur_otp, md, mdctx);
 	}
 	else {
 	    SETERROR(utils, "unknown OTP extended response type");
@@ -843,14 +881,15 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
     }
     else {
 	/* standard response, try word first, and then hex */
-	r = word2bin(utils, c, cur_otp, md);
+	r = word2bin(utils, c, cur_otp, md, mdctx);
 	if (r != SASL_OK)
 	    r = hex2bin(c, cur_otp, OTP_HASH_SIZE);
     }
     
     if (r == SASL_OK) {
 	/* do one more hash (previous otp) and compare to stored otp */
-	otp_hash(md, cur_otp, OTP_HASH_SIZE, prev_otp, text->alg->swab);
+	otp_hash(md, cur_otp, OTP_HASH_SIZE, 
+		prev_otp, text->alg->swab, mdctx);
 	
 	if (!memcmp(prev_otp, text->otp, OTP_HASH_SIZE)) {
 	    /* update the secret with this seq/otp */
@@ -879,23 +918,28 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 		*new_resp++ = '\0';
 	}
 	
-	if (!(new_chal && new_resp))
-	    return SASL_BADAUTH;
+	if (!(new_chal && new_resp)) {
+	    r = SASL_BADAUTH;
+            goto done;
+        }
 	
 	if ((r = parse_challenge(utils, new_chal, &alg, &seq, seed, 1))
 	    != SASL_OK) {
-	    return r;
+            goto done;
 	}
 	
-	if (seq < 1 || !strcasecmp(seed, text->seed))
-	    return SASL_BADAUTH;
+	if (seq < 1 || !strcasecmp(seed, text->seed)) {
+	    r = SASL_BADAUTH;
+            goto done;
+        }
 	
 	/* find the MDA */
 	if (!(md = EVP_get_digestbyname(alg->evp_name))) {
 	    utils->seterror(utils->conn, 0,
 			    "OTP algorithm %s is not available",
 			    alg->evp_name);
-	    return SASL_BADAUTH;
+	    r = SASL_BADAUTH;
+            goto done;
 	}
 	
 	if (!strncasecmp(c, OTP_INIT_HEX_TYPE, strlen(OTP_INIT_HEX_TYPE))) {
@@ -903,7 +947,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 	}
 	else if (!strncasecmp(c, OTP_INIT_WORD_TYPE,
 			      strlen(OTP_INIT_WORD_TYPE))) {
-	    r = word2bin(utils, new_resp, new_otp, md);
+	    r = word2bin(utils, new_resp, new_otp, md, mdctx);
 	}
 	
 	if (r == SASL_OK) {
@@ -914,7 +958,10 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
 	    memcpy(text->otp, new_otp, OTP_HASH_SIZE);
 	}
     }
-    
+
+  done:
+    if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils);
+
     return r;
 }
 
diff --git a/plugins/passdss.c b/plugins/passdss.c
index 4304f48..da37618 100644
--- a/plugins/passdss.c
+++ b/plugins/passdss.c
@@ -71,6 +71,9 @@
 #include <openssl/sha.h>
 #include <openssl/dsa.h>
 
+/* for legacy libcrypto support */
+#include "crypto-compat.h"
+
 #include <sasl.h>
 #define MD5_H  /* suppress internal MD5 */
 #include <saslplug.h>
@@ -110,23 +113,23 @@ typedef struct context {
     const sasl_utils_t *utils;
     
     /* per-step mem management */
-    char *out_buf;
+    unsigned char *out_buf;
     unsigned out_buf_len;
 
     /* security layer foo */
     unsigned char secmask;	/* bitmask of enabled security layers */
     unsigned char padding[EVP_MAX_BLOCK_LENGTH];  /* block of NULs */
 
-    HMAC_CTX hmac_send_ctx;
-    HMAC_CTX hmac_recv_ctx;
+    HMAC_CTX *hmac_send_ctx;
+    HMAC_CTX *hmac_recv_ctx;
 
     unsigned char send_integrity_key[4 + EVP_MAX_MD_SIZE]; /* +4 for pktnum */
     unsigned char recv_integrity_key[4 + EVP_MAX_MD_SIZE]; /* +4 for pktnum */
     unsigned char *cs_integrity_key;  /* ptr to bare key in send/recv key */
     unsigned char *sc_integrity_key;  /* ptr to bare key in send/recv key */
 
-    EVP_CIPHER_CTX cipher_enc_ctx;
-    EVP_CIPHER_CTX cipher_dec_ctx;
+    EVP_CIPHER_CTX *cipher_enc_ctx;
+    EVP_CIPHER_CTX *cipher_dec_ctx;
     unsigned blk_siz;
     
     unsigned char cs_encryption_iv[EVP_MAX_MD_SIZE];
@@ -139,7 +142,7 @@ typedef struct context {
     uint32_t pktnum_in;
     
     /* for encoding/decoding mem management */
-    char           *encode_buf, *decode_buf, *decode_pkt_buf;
+    unsigned char  *encode_buf, *decode_buf, *decode_pkt_buf;
     unsigned       encode_buf_len, decode_buf_len, decode_pkt_buf_len;
     
     /* layers buffering */
@@ -171,7 +174,7 @@ static int passdss_encode(void *context,
 	inputlen += invec[i].iov_len;
 
     /* allocate a buffer for the output */
-    ret = _plug_buf_alloc(text->utils, &text->encode_buf,
+    ret = _plug_buf_alloc(text->utils, (char **) &text->encode_buf,
 			  &text->encode_buf_len,
 			  4 +				/* length */
 			  inputlen +			/* content */
@@ -186,19 +189,19 @@ static int passdss_encode(void *context,
     memcpy(text->send_integrity_key, &tmpnum, 4);
 
     /* key the HMAC */
-    HMAC_Init_ex(&text->hmac_send_ctx, text->send_integrity_key,
+    HMAC_Init_ex(text->hmac_send_ctx, text->send_integrity_key,
 		 4+SHA_DIGEST_LENGTH, EVP_sha1(), NULL);
 
     /* operate on each iovec */
     for (i = 0; i < numiov; i++) {
 	/* hash the content */
-	HMAC_Update(&text->hmac_send_ctx, invec[i].iov_base, invec[i].iov_len);
+	HMAC_Update(text->hmac_send_ctx, invec[i].iov_base, invec[i].iov_len);
 
 	if (text->secmask & PRIVACY_LAYER_FLAG) {
-	    unsigned enclen;
+	    int enclen;
 
 	    /* encrypt the data into the output buffer */
-	    EVP_EncryptUpdate(&text->cipher_enc_ctx,
+	    EVP_EncryptUpdate(text->cipher_enc_ctx,
 			      text->encode_buf + *outputlen, &enclen,
 			      invec[i].iov_base, invec[i].iov_len);
 	    *outputlen += enclen;
@@ -212,14 +215,14 @@ static int passdss_encode(void *context,
     }
 
     /* calculate the HMAC */
-    HMAC_Final(&text->hmac_send_ctx, hmac, &hmaclen);
+    HMAC_Final(text->hmac_send_ctx, hmac, &hmaclen);
 
     if (text->secmask & PRIVACY_LAYER_FLAG) {
-	unsigned enclen;
+	int enclen;
 	unsigned char padlen;
 
 	/* encrypt the HMAC into the output buffer */
-	EVP_EncryptUpdate(&text->cipher_enc_ctx,
+	EVP_EncryptUpdate(text->cipher_enc_ctx,
 			  text->encode_buf + *outputlen, &enclen,
 			  hmac, hmaclen);
 	*outputlen += enclen;
@@ -227,17 +230,17 @@ static int passdss_encode(void *context,
 	/* pad output buffer to multiple of blk_siz
 	   with padlen-1 as last octet */
 	padlen = text->blk_siz - ((inputlen + hmaclen) % text->blk_siz) - 1;
-	EVP_EncryptUpdate(&text->cipher_enc_ctx,
+	EVP_EncryptUpdate(text->cipher_enc_ctx,
 			  text->encode_buf + *outputlen, &enclen,
 			  text->padding, padlen);
 	*outputlen += enclen;
-	EVP_EncryptUpdate(&text->cipher_enc_ctx,
+	EVP_EncryptUpdate(text->cipher_enc_ctx,
 			  text->encode_buf + *outputlen, &enclen,
 			  &padlen, 1);
 	*outputlen += enclen;
 
 	/* encrypt the last block of data into the output buffer */
-	EVP_EncryptFinal_ex(&text->cipher_enc_ctx,
+	EVP_EncryptFinal_ex(text->cipher_enc_ctx,
 			    text->encode_buf + *outputlen, &enclen);
 	*outputlen += enclen;
     }
@@ -252,7 +255,7 @@ static int passdss_encode(void *context,
     tmpnum = htonl(tmpnum);
     memcpy(text->encode_buf, &tmpnum, 4);
 
-    *output = text->encode_buf;
+    *output = (char *) text->encode_buf;
     
     return SASL_OK;
 }
@@ -271,25 +274,25 @@ static int passdss_decode_packet(void *context,
     int ret;
 
     if (text->secmask & PRIVACY_LAYER_FLAG) {
-	unsigned declen, padlen;
+	int declen, padlen;
 
 	/* allocate a buffer for the output */
-	ret = _plug_buf_alloc(text->utils, &(text->decode_pkt_buf),
+	ret = _plug_buf_alloc(text->utils, (char **) &(text->decode_pkt_buf),
 			      &(text->decode_pkt_buf_len), inputlen);
 	if (ret != SASL_OK) return ret;
 
 	/* decrypt the data into the output buffer */
-	ret = EVP_DecryptUpdate(&text->cipher_dec_ctx,
+	ret = EVP_DecryptUpdate(text->cipher_dec_ctx,
 				text->decode_pkt_buf, &declen,
-				(char *) input, inputlen);
+				(unsigned char *) input, inputlen);
 	if (ret)
-	    EVP_DecryptFinal_ex(&text->cipher_dec_ctx,  /* should be no output */
+	    EVP_DecryptFinal_ex(text->cipher_dec_ctx,  /* should be no output */
 				text->decode_pkt_buf + declen, &declen);
 	if (!ret) {
 	    SETERROR(text->utils, "Error decrypting input");
 	    return SASL_BADPROT;
 	}
-	input = text->decode_pkt_buf;
+	input = (char *) text->decode_pkt_buf;
 
 	/* trim padding */
 	padlen = text->decode_pkt_buf[inputlen - 1] + 1;
@@ -305,7 +308,7 @@ static int passdss_decode_packet(void *context,
 
     /* calculate the HMAC */
     HMAC(EVP_sha1(), text->recv_integrity_key, 4+SHA_DIGEST_LENGTH,
-	 input, inputlen, hmac, &hmaclen);
+	 (unsigned char *) input, inputlen, hmac, &hmaclen);
 
     /* verify HMAC */
     if (memcmp(hmac, input+inputlen, hmaclen)) {
@@ -326,12 +329,12 @@ static int passdss_decode(void *context,
 {
     context_t *text = (context_t *) context;
     int ret;
-    
+
     ret = _plug_decode(&text->decode_context, input, inputlen,
-		       &text->decode_buf, &text->decode_buf_len, outputlen,
-		       passdss_decode_packet, text);
+		       (char **) &text->decode_buf, &text->decode_buf_len,
+                       outputlen, passdss_decode_packet, text);
     
-    *output = text->decode_buf;
+    *output = (const char *) text->decode_buf;
     
     return ret;
 }
@@ -342,7 +345,8 @@ static int passdss_decode(void *context,
 /*
  * Create/append to a PASSDSS buffer from the data specified by the fmt string.
  */
-static int MakeBuffer(const sasl_utils_t *utils, char **buf, unsigned offset,
+static int MakeBuffer(const sasl_utils_t *utils,
+                      unsigned char **buf, unsigned offset,
 		      unsigned *buflen, unsigned *outlen, const char *fmt, ...)
 {
     va_list ap;
@@ -425,10 +429,10 @@ static int MakeBuffer(const sasl_utils_t *utils, char **buf, unsigned offset,
     }
     va_end(ap);
 
-    r = _plug_buf_alloc(utils, buf, buflen, alloclen);
+    r = _plug_buf_alloc(utils, (char **) buf, buflen, alloclen);
     if (r != SASL_OK) return r;
 
-    out = *buf + offset;
+    out = (char *) *buf + offset;
 
     /* second pass to fill buffer */
     va_start(ap, fmt);
@@ -463,7 +467,7 @@ static int MakeBuffer(const sasl_utils_t *utils, char **buf, unsigned offset,
 	case 'm':
 	    /* MPI */
 	    mpi = va_arg(ap, BIGNUM *);
-	    len = BN_bn2bin(mpi, out+4);
+	    len = BN_bn2bin(mpi, (unsigned char *) out+4);
 	    nl = htonl(len);
 	    memcpy(out, &nl, 4);	/* add 4 byte len (network order) */
 	    out += len + 4;
@@ -515,7 +519,7 @@ static int MakeBuffer(const sasl_utils_t *utils, char **buf, unsigned offset,
   done:
     va_end(ap);
 
-    *outlen = out - *buf;
+    *outlen = out - (char *) *buf;
 
     return r;
 }
@@ -600,8 +604,8 @@ static int UnBuffer(const sasl_utils_t *utils, const char *buf,
 	    
 	    if (mpi) {
 		if (!*mpi) *mpi = BN_new();
-		BN_init(*mpi);
-		BN_bin2bn(buf, len, *mpi);
+		BN_clear(*mpi);
+		BN_bin2bn((unsigned char *) buf, len, *mpi);
 	    }
 	    break;
 
@@ -716,16 +720,16 @@ static int UnBuffer(const sasl_utils_t *utils, const char *buf,
 }
 
 #define DOHASH(out, in1, len1, in2, len2, in3, len3)	\
-    EVP_DigestInit(&mdctx, EVP_sha1());			\
-    EVP_DigestUpdate(&mdctx, in1, len1);		\
-    EVP_DigestUpdate(&mdctx, in2, len2);		\
-    EVP_DigestUpdate(&mdctx, in3, len3);		\
-    EVP_DigestFinal(&mdctx, out, NULL)
-
-void CalcLayerParams(context_t *text, char *K, unsigned Klen,
-		     char *hash, unsigned hashlen)
+    EVP_DigestInit(mdctx, EVP_sha1());			\
+    EVP_DigestUpdate(mdctx, in1, len1);			\
+    EVP_DigestUpdate(mdctx, in2, len2);			\
+    EVP_DigestUpdate(mdctx, in3, len3);			\
+    EVP_DigestFinal(mdctx, out, NULL)
+
+void CalcLayerParams(context_t *text, unsigned char *K, unsigned Klen,
+		     unsigned char *hash, unsigned hashlen)
 {
-    EVP_MD_CTX mdctx;
+    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
 
     DOHASH(text->cs_encryption_iv, K, Klen, "A", 1, hash, hashlen);
     DOHASH(text->sc_encryption_iv, K, Klen, "B", 1, hash, hashlen);
@@ -737,6 +741,8 @@ void CalcLayerParams(context_t *text, char *K, unsigned Klen,
 	   text->sc_encryption_key, hashlen);
     DOHASH(text->cs_integrity_key, K, Klen, "E", 1, hash, hashlen);
     DOHASH(text->sc_integrity_key, K, Klen, "F", 1, hash, hashlen);
+
+    EVP_MD_CTX_free(mdctx);
 }
 
 /*
@@ -755,11 +761,11 @@ static void passdss_common_mech_dispose(void *conn_context,
 
     if (text->dh)		DH_free(text->dh);
 
-    HMAC_CTX_cleanup(&text->hmac_send_ctx);
-    HMAC_CTX_cleanup(&text->hmac_recv_ctx);
+    HMAC_CTX_free(text->hmac_send_ctx);
+    HMAC_CTX_free(text->hmac_recv_ctx);
 
-    EVP_CIPHER_CTX_cleanup(&text->cipher_enc_ctx);
-    EVP_CIPHER_CTX_cleanup(&text->cipher_dec_ctx);
+    EVP_CIPHER_CTX_free(text->cipher_enc_ctx);
+    EVP_CIPHER_CTX_free(text->cipher_dec_ctx);
     
     _plug_decode_free(&text->decode_context);
 
@@ -809,15 +815,17 @@ passdss_server_mech_step1(context_t *text,
 			  unsigned *serveroutlen,
 			  sasl_out_params_t *oparams __attribute__((unused)))
 {
-    BIGNUM *X = NULL;
+    BIGNUM *X = NULL, *dh_p = NULL, *dh_g = NULL;
     DSA *dsa = NULL;
+    const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key, *dh_pub_key;
     unsigned char *K = NULL;
     unsigned Klen, hashlen;
     int need, musthave;
-    EVP_MD_CTX mdctx;
+    EVP_MD_CTX *mdctx;
     unsigned char hash[EVP_MAX_MD_SIZE];
     DSA_SIG *sig = NULL;
-    int result;
+    const BIGNUM *sig_r, *sig_s;
+    int r = 0, result;
     
     /* Expect:
      *
@@ -835,8 +843,18 @@ passdss_server_mech_step1(context_t *text,
     }
 
     /* Fetch DSA (XXX create one for now) */
-    dsa = DSA_generate_parameters(1024, NULL, 0, NULL, NULL, NULL, NULL);
+    dsa = DSA_new();
     if (!dsa) {
+	params->utils->log(NULL,
+                           SASL_LOG_ERR, "Error creating DSA\n");
+	result = SASL_FAIL;
+	goto cleanup;
+    }
+
+    r = DSA_generate_parameters_ex(dsa, 1024, NULL, 0, NULL, NULL, NULL);
+    if (!r) {
+	params->utils->log(NULL,
+                           SASL_LOG_ERR, "Error generating DSA parameters\n");
 	result = SASL_FAIL;
 	goto cleanup;
     }
@@ -844,8 +862,9 @@ passdss_server_mech_step1(context_t *text,
 
     /* Create Diffie-Hellman parameters */
     text->dh = DH_new();
-    BN_hex2bn(&text->dh->p, N);
-    BN_hex2bn(&text->dh->g, g);
+    BN_hex2bn(&dh_p, N);
+    BN_hex2bn(&dh_g, g);
+    DH_set0_pqg(text->dh, dh_p, NULL, dh_g);
     DH_generate_key(text->dh);
 
     /* Alloc space for shared secret K as mpint */
@@ -897,10 +916,13 @@ passdss_server_mech_step1(context_t *text,
      */
 
     /* Items (4) - (7) */
+    DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g);
+    DSA_get0_key(dsa, &dsa_pub_key, NULL);
+    DH_get0_key(text->dh, &dh_pub_key, NULL);
     result = MakeBuffer(text->utils, &text->out_buf, 0, &text->out_buf_len,
 			serveroutlen, "%5a%s%m%m%m%m%m%1o%3u",
-			"ssh-dss", dsa->p, dsa->q, dsa->g, dsa->pub_key,
-			text->dh->pub_key, &text->secmask,
+			"ssh-dss", dsa_p, dsa_q, dsa_g, dsa_pub_key,
+			dh_pub_key, &text->secmask,
 			(params->props.maxbufsize > 0xFFFFFF) ? 0xFFFFFF :
 			params->props.maxbufsize);
     if (result) {
@@ -909,26 +931,29 @@ passdss_server_mech_step1(context_t *text,
     }
 
     /* Hash (1) - (7) and K */
-    EVP_DigestInit(&mdctx, EVP_sha1());
+    mdctx = EVP_MD_CTX_new();
+    EVP_DigestInit(mdctx, EVP_sha1());
     /* (1) - (3) */
-    EVP_DigestUpdate(&mdctx, clientin, clientinlen);
+    EVP_DigestUpdate(mdctx, clientin, clientinlen);
     /* (4) - (7) */
-    EVP_DigestUpdate(&mdctx, text->out_buf, *serveroutlen);
+    EVP_DigestUpdate(mdctx, text->out_buf, *serveroutlen);
     /* K */
-    EVP_DigestUpdate(&mdctx, K, Klen);
-    EVP_DigestFinal(&mdctx, hash, &hashlen);
+    EVP_DigestUpdate(mdctx, K, Klen);
+    EVP_DigestFinal(mdctx, hash, &hashlen);
+    EVP_MD_CTX_free(mdctx);
 
     /* Calculate security layer params */
     CalcLayerParams(text, K, Klen, hash, hashlen);
 
     /* Start cli-hmac */
-    HMAC_CTX_init(&text->hmac_recv_ctx);
-    HMAC_Init_ex(&text->hmac_recv_ctx, text->cs_integrity_key,
+    text->hmac_recv_ctx = HMAC_CTX_new();
+    HMAC_CTX_reset(text->hmac_recv_ctx);
+    HMAC_Init_ex(text->hmac_recv_ctx, text->cs_integrity_key,
 		 SHA_DIGEST_LENGTH, EVP_sha1(), NULL);
     /* (1) - (3) */
-    HMAC_Update(&text->hmac_recv_ctx, clientin, clientinlen);
+    HMAC_Update(text->hmac_recv_ctx, (unsigned char *) clientin, clientinlen);
     /* (4) - (7) */
-    HMAC_Update(&text->hmac_recv_ctx, text->out_buf, *serveroutlen);
+    HMAC_Update(text->hmac_recv_ctx, text->out_buf, *serveroutlen);
 
     /* Sign the hash */
     sig = DSA_do_sign(hash, hashlen, dsa);
@@ -940,14 +965,15 @@ passdss_server_mech_step1(context_t *text,
     }
 
     /* Item (8) */
+    DSA_SIG_get0(sig, &sig_r, &sig_s);
     result = MakeBuffer(text->utils, &text->out_buf, *serveroutlen,
 			&text->out_buf_len, serveroutlen,
-			"%3a%s%m%m", "ssh-dss", sig->r, sig->s);
+			"%3a%s%m%m", "ssh-dss", sig_r, sig_s);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR, "Error making output buffer\n");
 	goto cleanup;
     }
-    *serverout = text->out_buf;
+    *serverout = (char *) text->out_buf;
 
     text->state = 2;
     result = SASL_CONTINUE;
@@ -971,10 +997,10 @@ passdss_server_mech_step2(context_t *text,
 			  sasl_out_params_t *oparams)
 {
     char *password = NULL;
-    unsigned declen, hmaclen;
+    unsigned hmaclen;
     unsigned char *csecmask, *cli_hmac, hmac[EVP_MAX_MD_SIZE];
     uint32_t cbufsiz;
-    int r, result = SASL_OK;
+    int declen, r, result = SASL_OK;
     
     /* Expect (3DES encrypted):
      *
@@ -985,7 +1011,7 @@ passdss_server_mech_step2(context_t *text,
      */
 
     /* Alloc space for the decrypted input */
-    result = _plug_buf_alloc(text->utils, &text->decode_pkt_buf,
+    result = _plug_buf_alloc(text->utils, (char **) &text->decode_pkt_buf,
 			     &text->decode_pkt_buf_len, clientinlen);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR,
@@ -994,25 +1020,28 @@ passdss_server_mech_step2(context_t *text,
     }
 
     /* Initialize decrypt cipher */
-    EVP_CIPHER_CTX_init(&text->cipher_dec_ctx);
-    EVP_DecryptInit_ex(&text->cipher_dec_ctx, EVP_des_ede3_cbc(), NULL,
+    text->cipher_dec_ctx = EVP_CIPHER_CTX_new();
+    EVP_CIPHER_CTX_init(text->cipher_dec_ctx);
+    EVP_DecryptInit_ex(text->cipher_dec_ctx, EVP_des_ede3_cbc(), NULL,
 		       text->cs_encryption_key, text->cs_encryption_iv);
-    EVP_CIPHER_CTX_set_padding(&text->cipher_dec_ctx, 0);
-    text->blk_siz = EVP_CIPHER_CTX_block_size(&text->cipher_dec_ctx);
+    EVP_CIPHER_CTX_set_padding(text->cipher_dec_ctx, 0);
+    text->blk_siz = EVP_CIPHER_CTX_block_size(text->cipher_dec_ctx);
 
     /* Decrypt the blob */
-    r = EVP_DecryptUpdate(&text->cipher_dec_ctx, text->decode_pkt_buf, &declen,
-			  clientin, clientinlen);
+    r = EVP_DecryptUpdate(text->cipher_dec_ctx,
+                          text->decode_pkt_buf, &declen,
+			  (unsigned char *) clientin, clientinlen);
     if (r)
-	r = EVP_DecryptFinal_ex(&text->cipher_dec_ctx,  /* should be no output */
-				text->decode_pkt_buf + declen, &declen);
+	r = EVP_DecryptFinal_ex(text->cipher_dec_ctx,  /* should be no output */
+				text->decode_pkt_buf + declen,
+                                &declen);
     if (!r) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error decrypting input in step 2");
 	result = SASL_BADPROT;
 	goto cleanup;
     }
-    clientin = text->decode_pkt_buf;
+    clientin = (char *) text->decode_pkt_buf;
 
     result = UnBuffer(params->utils, clientin, clientinlen,
 		      "%-1o%3u%s%-*o%*p", &csecmask, &cbufsiz, &password,
@@ -1026,8 +1055,8 @@ passdss_server_mech_step2(context_t *text,
     /* Finish cli-hmac */
     /* (1) - (7) hashed in step 1 */
     /* 1st 4 bytes of (9) */
-    HMAC_Update(&text->hmac_recv_ctx, clientin, 4);
-    HMAC_Final(&text->hmac_recv_ctx, hmac, &hmaclen);
+    HMAC_Update(text->hmac_recv_ctx, (unsigned char *) clientin, 4);
+    HMAC_Final(text->hmac_recv_ctx, hmac, &hmaclen);
 
     /* Verify cli-hmac */
     if (memcmp(cli_hmac, hmac, hmaclen)) {
@@ -1089,16 +1118,18 @@ passdss_server_mech_step2(context_t *text,
 	oparams->decode = &passdss_decode;
 	oparams->maxoutbuf = cbufsiz - 4 - SHA_DIGEST_LENGTH; /* -len -HMAC */
 
-	HMAC_CTX_init(&text->hmac_send_ctx);
+        text->hmac_send_ctx = HMAC_CTX_new();
+	HMAC_CTX_reset(text->hmac_send_ctx);
 
 	if (oparams->mech_ssf > 1) {
 	    oparams->maxoutbuf -= text->blk_siz-1; /* padding */
 
 	    /* Initialize encrypt cipher */
-	    EVP_CIPHER_CTX_init(&text->cipher_enc_ctx);
-	    EVP_EncryptInit_ex(&text->cipher_enc_ctx, EVP_des_ede3_cbc(), NULL,
+            text->cipher_enc_ctx = EVP_CIPHER_CTX_new();
+	    EVP_CIPHER_CTX_init(text->cipher_enc_ctx);
+	    EVP_EncryptInit_ex(text->cipher_enc_ctx, EVP_des_ede3_cbc(), NULL,
 			       text->sc_encryption_key, text->sc_encryption_iv);
-	    EVP_CIPHER_CTX_set_padding(&text->cipher_enc_ctx, 0);
+	    EVP_CIPHER_CTX_set_padding(text->cipher_enc_ctx, 0);
 	}
 
 	_plug_decode_init(&text->decode_context, text->utils,
@@ -1247,6 +1278,8 @@ passdss_client_mech_step1(context_t *text,
     int auth_result = SASL_OK;
     int pass_result = SASL_OK;
     int result;
+    BIGNUM *dh_p = NULL, *dh_g = NULL;
+    const BIGNUM *dh_pub_key;
 
     /* Expect: absolutely nothing */
     if (serverinlen > 0) {
@@ -1334,8 +1367,9 @@ passdss_client_mech_step1(context_t *text,
 
     /* create Diffie-Hellman parameters */
     text->dh = DH_new();
-    BN_hex2bn(&text->dh->p, N);
-    BN_hex2bn(&text->dh->g, g);
+    BN_hex2bn(&dh_p, N);
+    BN_hex2bn(&dh_g, g);
+    DH_set0_pqg(text->dh, dh_p, NULL, dh_g);
     DH_generate_key(text->dh);
 
 
@@ -1346,15 +1380,16 @@ passdss_client_mech_step1(context_t *text,
      * (3) mpint  X 		; Diffie-Hellman parameter X
      */
     
+    DH_get0_key(text->dh, &dh_pub_key, NULL);
     result = MakeBuffer(text->utils, &text->out_buf, 0, &text->out_buf_len,
 			clientoutlen, "%s%s%m",
 			(user && *user) ? (char *) oparams->user : "",
-			(char *) oparams->authid, text->dh->pub_key);
+			(char *) oparams->authid, dh_pub_key);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR, "Error making output buffer\n");
 	goto cleanup;
     }
-    *clientout = text->out_buf;
+    *clientout = (char *) text->out_buf;
     
     text->state = 2;
     result = SASL_CONTINUE;
@@ -1376,15 +1411,16 @@ passdss_client_mech_step2(context_t *text,
 {
     DSA *dsa = DSA_new();
     DSA_SIG *sig = DSA_SIG_new();
-    BIGNUM *Y = NULL;
+    BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL;
+    BIGNUM *Y = NULL, *sig_r = NULL, *sig_s = NULL;
     uint32_t siglen;
     unsigned char *K = NULL;
-    unsigned Klen, hashlen, enclen;
+    unsigned Klen, hashlen;
     unsigned char *ssecmask;
     uint32_t sbufsiz;
-    EVP_MD_CTX mdctx;
+    EVP_MD_CTX *mdctx;
     unsigned char hash[EVP_MAX_MD_SIZE];
-    int need, musthave;
+    int enclen, need, musthave;
     int result, r;
     
     /* Expect:
@@ -1406,14 +1442,18 @@ passdss_client_mech_step2(context_t *text,
 
     result = UnBuffer(params->utils, serverin, serverinlen,
 		      "%u%3p\7ssh-dss%m%m%m%m%m%-1o%3u%u%3p\7ssh-dss%m%m",
-		      NULL, &dsa->p, &dsa->q, &dsa->g, &dsa->pub_key,
-		      &Y, &ssecmask, &sbufsiz, &siglen, &sig->r, &sig->s);
+		      NULL, &dsa_p, &dsa_q, &dsa_g, &dsa_pub_key,
+		      &Y, &ssecmask, &sbufsiz, &siglen, &sig_r, &sig_s);
     if (result) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error UnBuffering input in step 2");
 	goto cleanup;
     }
 
+    DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
+    DSA_set0_key(dsa, dsa_pub_key, NULL);
+    DSA_SIG_set0(sig, sig_r, sig_s);
+
     /* XXX  Validate server DSA public key */
 
     /* Alloc space for shared secret K as mpint */
@@ -1432,14 +1472,16 @@ passdss_client_mech_step2(context_t *text,
     Klen += 4;
 
     /* Hash (1) - (7) and K */
-    EVP_DigestInit(&mdctx, EVP_sha1());
+    mdctx = EVP_MD_CTX_new();
+    EVP_DigestInit(mdctx, EVP_sha1());
     /* (1) - (3) (output from step 1 still in buffer) */
-    EVP_DigestUpdate(&mdctx, text->out_buf, text->out_buf_len);
+    EVP_DigestUpdate(mdctx, text->out_buf, text->out_buf_len);
     /* (4) - (7) */
-    EVP_DigestUpdate(&mdctx, serverin, serverinlen - siglen - 4);
+    EVP_DigestUpdate(mdctx, serverin, serverinlen - siglen - 4);
     /* K */
-    EVP_DigestUpdate(&mdctx, K, Klen);
-    EVP_DigestFinal(&mdctx, hash, &hashlen);
+    EVP_DigestUpdate(mdctx, K, Klen);
+    EVP_DigestFinal(mdctx, hash, &hashlen);
+    EVP_MD_CTX_free(mdctx);
 
     /* Verify signature on the hash */
     result = DSA_do_verify(hash, hashlen, sig, dsa);
@@ -1455,11 +1497,12 @@ passdss_client_mech_step2(context_t *text,
     CalcLayerParams(text, K, Klen, hash, hashlen);
 
     /* Initialize encrypt cipher */
-    EVP_CIPHER_CTX_init(&text->cipher_enc_ctx);
-    EVP_EncryptInit_ex(&text->cipher_enc_ctx, EVP_des_ede3_cbc(), NULL,
+    text->cipher_enc_ctx = EVP_CIPHER_CTX_new();
+    EVP_CIPHER_CTX_init(text->cipher_enc_ctx);
+    EVP_EncryptInit_ex(text->cipher_enc_ctx, EVP_des_ede3_cbc(), NULL,
 		       text->cs_encryption_key, text->cs_encryption_iv);
-    EVP_CIPHER_CTX_set_padding(&text->cipher_enc_ctx, 0);
-    text->blk_siz = EVP_CIPHER_CTX_block_size(&text->cipher_enc_ctx);
+    EVP_CIPHER_CTX_set_padding(text->cipher_enc_ctx, 0);
+    text->blk_siz = EVP_CIPHER_CTX_block_size(text->cipher_enc_ctx);
 
     /* pick a layer */
     if (params->props.maxbufsize < 32) {
@@ -1490,13 +1533,15 @@ passdss_client_mech_step2(context_t *text,
     }
 
     /* Start cli-hmac */
-    HMAC_CTX_init(&text->hmac_send_ctx);
-    HMAC_Init_ex(&text->hmac_send_ctx, text->cs_integrity_key,
+    text->hmac_send_ctx = HMAC_CTX_new();
+    HMAC_CTX_reset(text->hmac_send_ctx);
+    HMAC_Init_ex(text->hmac_send_ctx, text->cs_integrity_key,
 		 SHA_DIGEST_LENGTH, EVP_sha1(), NULL);
     /* (1) - (3) (output from step 1 still in buffer) */
-    HMAC_Update(&text->hmac_send_ctx, text->out_buf, text->out_buf_len);
+    HMAC_Update(text->hmac_send_ctx, text->out_buf, text->out_buf_len);
     /* (4) - (7) */
-    HMAC_Update(&text->hmac_send_ctx, serverin, serverinlen - siglen - 4);
+    HMAC_Update(text->hmac_send_ctx,
+                (unsigned char *) serverin, serverinlen - siglen - 4);
 
 
     /* Send out (3DES encrypted):
@@ -1520,8 +1565,8 @@ passdss_client_mech_step2(context_t *text,
 
     /* Finish cli-hmac */
     /* 1st 4 bytes of (9) */
-    HMAC_Update(&text->hmac_send_ctx, text->out_buf, 4);
-    HMAC_Final(&text->hmac_send_ctx, hash, &hashlen);
+    HMAC_Update(text->hmac_send_ctx, text->out_buf, 4);
+    HMAC_Final(text->hmac_send_ctx, hash, &hashlen);
 
     /* Add HMAC and pad to fill no more than current block */
     result = MakeBuffer(text->utils, &text->out_buf, *clientoutlen,
@@ -1533,7 +1578,7 @@ passdss_client_mech_step2(context_t *text,
     }
 
     /* Alloc space for the encrypted output */
-    result = _plug_buf_alloc(text->utils, &text->encode_buf,
+    result = _plug_buf_alloc(text->utils, (char **) &text->encode_buf,
 			     &text->encode_buf_len, *clientoutlen);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR,
@@ -1542,19 +1587,20 @@ passdss_client_mech_step2(context_t *text,
     }
 
     /* Encrypt (9) (here we calculate the exact number of full blocks) */
-    r = EVP_EncryptUpdate(&text->cipher_enc_ctx, text->encode_buf,
-			  clientoutlen, text->out_buf,
+    r = EVP_EncryptUpdate(text->cipher_enc_ctx,
+                          text->encode_buf, (int *) clientoutlen, text->out_buf,
 			  text->blk_siz * (*clientoutlen / text->blk_siz));
     if (r)
-	r = EVP_EncryptFinal_ex(&text->cipher_enc_ctx,  /* should be no output */
-				text->encode_buf + *clientoutlen, &enclen);
+	r = EVP_EncryptFinal_ex(text->cipher_enc_ctx,  /* should be no output */
+				text->encode_buf + *clientoutlen,
+                                &enclen);
     if (!r) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error encrypting output in step 2");
 	result = SASL_FAIL;
 	goto cleanup;
     }
-    *clientout = text->encode_buf;
+    *clientout = (char *) text->encode_buf;
 
     /* Set oparams */
     oparams->doneflag = 1;
@@ -1565,16 +1611,18 @@ passdss_client_mech_step2(context_t *text,
 	oparams->decode = &passdss_decode;
 	oparams->maxoutbuf = sbufsiz - 4 - SHA_DIGEST_LENGTH; /* -len -HMAC */
 
-	HMAC_CTX_init(&text->hmac_recv_ctx);
+        text->hmac_recv_ctx = HMAC_CTX_new();
+	HMAC_CTX_reset(text->hmac_recv_ctx);
 
 	if (oparams->mech_ssf > 1) {
 	    oparams->maxoutbuf -= text->blk_siz-1; /* padding */
 
 	    /* Initialize decrypt cipher */
-	    EVP_CIPHER_CTX_init(&text->cipher_dec_ctx);
-	    EVP_DecryptInit_ex(&text->cipher_dec_ctx, EVP_des_ede3_cbc(), NULL,
+            text->cipher_dec_ctx = EVP_CIPHER_CTX_new();
+	    EVP_CIPHER_CTX_init(text->cipher_dec_ctx);
+	    EVP_DecryptInit_ex(text->cipher_dec_ctx, EVP_des_ede3_cbc(), NULL,
 			       text->sc_encryption_key, text->sc_encryption_iv);
-	    EVP_CIPHER_CTX_set_padding(&text->cipher_dec_ctx, 0);
+	    EVP_CIPHER_CTX_set_padding(text->cipher_dec_ctx, 0);
 	}
 
 	_plug_decode_init(&text->decode_context, text->utils,
diff --git a/plugins/srp.c b/plugins/srp.c
index a07561c..7ea1000 100644
--- a/plugins/srp.c
+++ b/plugins/srp.c
@@ -89,6 +89,9 @@ typedef unsigned short uint32;
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
 
+/* for legacy libcrypto support */
+#include "crypto-compat.h"
+
 #include <sasl.h>
 #define MD5_H  /* suppress internal MD5 */
 #include <saslplug.h>
@@ -216,22 +219,22 @@ typedef struct srp_options_s {
 typedef struct context {
     int state;
     
-    BIGNUM N;			/* safe prime modulus */
-    BIGNUM g;			/* generator */
+    BIGNUM *N;			/* safe prime modulus */
+    BIGNUM *g;			/* generator */
     
-    BIGNUM v;			/* password verifier */
+    BIGNUM *v;			/* password verifier */
     
-    BIGNUM b;			/* server private key */
-    BIGNUM B;			/* server public key */
+    BIGNUM *b;			/* server private key */
+    BIGNUM *B;			/* server public key */
     
-    BIGNUM a;			/* client private key */
-    BIGNUM A;			/* client public key */
+    BIGNUM *a;			/* client private key */
+    BIGNUM *A;			/* client public key */
     
-    char K[EVP_MAX_MD_SIZE];	/* shared context key */
-    int Klen;
+    unsigned char K[EVP_MAX_MD_SIZE];	/* shared context key */
+    unsigned int Klen;
     
-    char M1[EVP_MAX_MD_SIZE];	/* client evidence */
-    int M1len;
+    unsigned char M1[EVP_MAX_MD_SIZE];	/* client evidence */
+    unsigned int M1len;
     
     char *authid;		/* authentication id (server) */
     char *userid;		/* authorization id (server) */
@@ -242,7 +245,7 @@ typedef struct context {
     char *server_options;
     
     srp_options_t client_opts;	/* cache between client steps */
-    char cIV[SRP_MAXBLOCKSIZE];	/* cache between client steps */
+    unsigned char cIV[SRP_MAXBLOCKSIZE];	/* cache between client steps */
     
     char *salt;			/* password salt */
     int saltlen;
@@ -259,12 +262,12 @@ typedef struct context {
     /* Layer foo */
     unsigned layer;		/* bitmask of enabled layers */
     const EVP_MD *hmac_md;	/* HMAC for integrity */
-    HMAC_CTX hmac_send_ctx;
-    HMAC_CTX hmac_recv_ctx;
+    HMAC_CTX *hmac_send_ctx;
+    HMAC_CTX *hmac_recv_ctx;
 
     const EVP_CIPHER *cipher;	/* cipher for confidentiality */
-    EVP_CIPHER_CTX cipher_enc_ctx;
-    EVP_CIPHER_CTX cipher_dec_ctx;
+    EVP_CIPHER_CTX *cipher_enc_ctx;
+    EVP_CIPHER_CTX *cipher_dec_ctx;
     
     /* replay detection sequence numbers */
     int seqnum_out;
@@ -317,12 +320,12 @@ static int srp_encode(void *context,
 	inputlen = invec[i].iov_len;
     
 	if (text->layer & BIT_CONFIDENTIALITY) {
-	    unsigned enclen;
+	    int enclen;
 
 	    /* encrypt the data into the output buffer */
-	    EVP_EncryptUpdate(&text->cipher_enc_ctx,
-			      text->encode_buf + *outputlen, &enclen,
-			      input, inputlen);
+	    EVP_EncryptUpdate(text->cipher_enc_ctx,
+			      (unsigned char *) text->encode_buf + *outputlen,
+                              &enclen, (unsigned char *) input, inputlen);
 	    *outputlen += enclen;
 
 	    /* switch the input to the encrypted data */
@@ -337,11 +340,12 @@ static int srp_encode(void *context,
     }
     
     if (text->layer & BIT_CONFIDENTIALITY) {
-	unsigned enclen;
+	int enclen;
 
 	/* encrypt the last block of data into the output buffer */
-	EVP_EncryptFinal(&text->cipher_enc_ctx,
-			 text->encode_buf + *outputlen, &enclen);
+	EVP_EncryptFinal(text->cipher_enc_ctx,
+			 (unsigned char *) text->encode_buf + *outputlen,
+                         &enclen);
 	*outputlen += enclen;
     }
 
@@ -349,18 +353,20 @@ static int srp_encode(void *context,
 	unsigned hashlen;
 
 	/* hash the content */
-	HMAC_Update(&text->hmac_send_ctx, text->encode_buf+4, *outputlen-4);
+	HMAC_Update(text->hmac_send_ctx,
+                    (unsigned char *) text->encode_buf+4, *outputlen-4);
 	
 	if (text->layer & BIT_REPLAY_DETECTION) {
 	    /* hash the sequence number */
 	    tmpnum = htonl(text->seqnum_out);
-	    HMAC_Update(&text->hmac_send_ctx, (char *) &tmpnum, 4);
+	    HMAC_Update(text->hmac_send_ctx, (unsigned char *) &tmpnum, 4);
 	    
 	    text->seqnum_out++;
 	}
 
 	/* append the HMAC into the output buffer */
-	HMAC_Final(&text->hmac_send_ctx, text->encode_buf + *outputlen,
+	HMAC_Final(text->hmac_send_ctx,
+                   (unsigned char *) text->encode_buf + *outputlen,
 		   &hashlen);
 	*outputlen += hashlen;
     }
@@ -387,8 +393,8 @@ static int srp_decode_packet(void *context,
 
     if (text->layer & BIT_INTEGRITY) {
 	const char *hash;
-	char myhash[EVP_MAX_MD_SIZE];
-	unsigned hashlen, myhashlen, i;
+	unsigned char myhash[EVP_MAX_MD_SIZE];
+	unsigned hashlen;
 	unsigned long tmpnum;
 
 	hashlen = EVP_MD_size(text->hmac_md);
@@ -405,25 +411,23 @@ static int srp_decode_packet(void *context,
 	hash = input + inputlen;
 
 	/* create our own hash from the input */
-	HMAC_Update(&text->hmac_recv_ctx, input, inputlen);
+	HMAC_Update(text->hmac_recv_ctx, (unsigned char *) input, inputlen);
 	    
 	if (text->layer & BIT_REPLAY_DETECTION) {
 	    /* hash the sequence number */
 	    tmpnum = htonl(text->seqnum_in);
-	    HMAC_Update(&text->hmac_recv_ctx, (char *) &tmpnum, 4);
+	    HMAC_Update(text->hmac_recv_ctx, (unsigned char *) &tmpnum, 4);
 		
 	    text->seqnum_in++;
 	}
 	    
-	HMAC_Final(&text->hmac_recv_ctx, myhash, &myhashlen);
+	HMAC_Final(text->hmac_recv_ctx, myhash, &hashlen);
 
 	/* compare hashes */
-	for (i = 0; i < hashlen; i++) {
-	    if ((myhashlen != hashlen) || (myhash[i] != hash[i])) {
-		SETERROR(text->utils, "Hash is incorrect\n");
-		return SASL_BADMAC;
-	    }
-	}
+        if (memcmp(hash, myhash, hashlen)) {
+            SETERROR(text->utils, "Hash is incorrect\n");
+            return SASL_BADMAC;
+        }
     }
 	
     ret = _plug_buf_alloc(text->utils, &(text->decode_pkt_buf),
@@ -432,16 +436,17 @@ static int srp_decode_packet(void *context,
     if (ret != SASL_OK) return ret;
 	
     if (text->layer & BIT_CONFIDENTIALITY) {
-	unsigned declen;
+	int declen;
 
 	/* decrypt the data into the output buffer */
-	EVP_DecryptUpdate(&text->cipher_dec_ctx,
-			  text->decode_pkt_buf, &declen,
-			  (char *) input, inputlen);
+	EVP_DecryptUpdate(text->cipher_dec_ctx,
+			  (unsigned char *) text->decode_pkt_buf, &declen,
+			  (unsigned char *) input, inputlen);
 	*outputlen = declen;
 	    
-	EVP_DecryptFinal(&text->cipher_dec_ctx,
-			 text->decode_pkt_buf + declen, &declen);
+	EVP_DecryptFinal(text->cipher_dec_ctx,
+			 (unsigned char *) text->decode_pkt_buf + declen,
+                         &declen);
 	*outputlen += declen;
     } else {
 	/* copy the raw input to the output */
@@ -474,7 +479,8 @@ static int srp_decode(void *context,
 /*
  * Convert a big integer to it's byte representation
  */
-static int BigIntToBytes(BIGNUM *num, char *out, int maxoutlen, int *outlen)
+static int BigIntToBytes(BIGNUM *num, unsigned char *out, int maxoutlen,
+                         unsigned int *outlen)
 {
     int len;
     
@@ -504,12 +510,12 @@ static int BigIntCmpWord(BIGNUM *a, BN_ULONG w)
 /*
  * Generate a random big integer.
  */
-static void GetRandBigInt(BIGNUM *out)
+static void GetRandBigInt(BIGNUM **out)
 {
-    BN_init(out);
+    *out = BN_new();
     
     /* xxx likely should use sasl random funcs */
-    BN_rand(out, SRP_MAXBLOCKSIZE*8, 0, 0);
+    BN_rand(*out, SRP_MAXBLOCKSIZE*8, 0, 0);
 }
 
 #define MAX_BUFFER_LEN 2147483643
@@ -624,7 +630,8 @@ static int MakeBuffer(const sasl_utils_t *utils, char **buf, unsigned *buflen,
 	case 'm':
 	    /* MPI */
 	    mpi = va_arg(ap, BIGNUM *);
-	    r = BigIntToBytes(mpi, out+2, BN_num_bytes(mpi), &len);
+	    r = BigIntToBytes(mpi, (unsigned char *) out+2,
+                              BN_num_bytes(mpi), (unsigned *) &len);
 	    if (r) goto done;
 	    ns = htons(len);
 	    memcpy(out, &ns, 2);	/* add 2 byte len (network order) */
@@ -695,7 +702,7 @@ static int UnBuffer(const sasl_utils_t *utils, const char *buf,
     va_list ap;
     char *p;
     int r = SASL_OK, noalloc;
-    BIGNUM *mpi;
+    BIGNUM **mpi;
     char **os, **str;
     uint32 *u;
     unsigned short ns;
@@ -757,9 +764,12 @@ static int UnBuffer(const sasl_utils_t *utils, const char *buf,
 		goto done;
 	    }
 	    
-	    mpi = va_arg(ap, BIGNUM *);
-	    BN_init(mpi);
-	    BN_bin2bn(buf, len, mpi);
+	    mpi = va_arg(ap, BIGNUM **);
+            if (mpi) {
+                if (!*mpi) *mpi = BN_new();
+                else BN_clear(*mpi);
+                BN_bin2bn((unsigned char *) buf, len, *mpi);
+            }
 	    break;
 
 	case 'o':
@@ -883,16 +893,17 @@ static int UnBuffer(const sasl_utils_t *utils, const char *buf,
 /*
  * Apply the hash function to the data specifed by the fmt string.
  */
-static int MakeHash(const EVP_MD *md, unsigned char hash[], int *hashlen,
+static int MakeHash(const EVP_MD *md,
+                    unsigned char hash[], unsigned int *hashlen,
 		    const char *fmt, ...)
 {
     va_list ap;
     char *p, buf[4096], *in;
-    int inlen;
-    EVP_MD_CTX mdctx;
+    unsigned int inlen;
+    EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
     int r = 0, hflag;
 
-    EVP_DigestInit(&mdctx, md);
+    EVP_DigestInit(mdctx, md);
 
     va_start(ap, fmt);
     for (p = (char *) fmt; *p; p++) {
@@ -910,7 +921,7 @@ static int MakeHash(const EVP_MD *md, unsigned char hash[], int *hashlen,
 		BIGNUM *mval = va_arg(ap, BIGNUM *);
 
 		in = buf;
-		r = BigIntToBytes(mval, buf, sizeof(buf)-1, &inlen);
+		r = BigIntToBytes(mval, (unsigned char *) buf, sizeof(buf)-1, &inlen);
 		if (r) goto done;
 		break;
 	    }
@@ -947,47 +958,52 @@ static int MakeHash(const EVP_MD *md, unsigned char hash[], int *hashlen,
 
 	if (hflag) {
 	    /* hash data separately before adding to current hash */
-	    EVP_MD_CTX tmpctx;
+	    EVP_MD_CTX *tmpctx = EVP_MD_CTX_new();
 
-	    EVP_DigestInit(&tmpctx, md);
-	    EVP_DigestUpdate(&tmpctx, in, inlen);
-	    EVP_DigestFinal(&tmpctx, buf, &inlen);
+	    EVP_DigestInit(tmpctx, md);
+	    EVP_DigestUpdate(tmpctx, in, inlen);
+	    EVP_DigestFinal(tmpctx, (unsigned char *) buf, &inlen);
+            EVP_MD_CTX_free(tmpctx);
 	    in = buf;
 	}
 
-	EVP_DigestUpdate(&mdctx, in, inlen);
+	EVP_DigestUpdate(mdctx, in, inlen);
     }
   done:
     va_end(ap);
 
-    EVP_DigestFinal(&mdctx, hash, hashlen);
+    EVP_DigestFinal(mdctx, hash, hashlen);
+    EVP_MD_CTX_free(mdctx);
 
     return r;
 }
 
 static int CalculateX(context_t *text, const char *salt, int saltlen, 
-		      const char *user, const char *pass, int passlen, 
-		      BIGNUM *x)
+		      const char *user, const unsigned char *pass, int passlen, 
+		      BIGNUM **x)
 {
-    char hash[EVP_MAX_MD_SIZE];
-    int hashlen;
+    unsigned char hash[EVP_MAX_MD_SIZE];
+    unsigned int hashlen;
     
     /* x = H(salt | H(user | ':' | pass)) */
     MakeHash(text->md, hash, &hashlen, "%s:%o", user, passlen, pass);
     MakeHash(text->md, hash, &hashlen, "%o%o", saltlen, salt, hashlen, hash);
     
-    BN_init(x);
-    BN_bin2bn(hash, hashlen, x);
+    *x = BN_new();
+    BN_bin2bn(hash, hashlen, *x);
     
     return SASL_OK;
 }
 
 static int CalculateM1(context_t *text, BIGNUM *N, BIGNUM *g,
 		       char *U, char *salt, int saltlen,
-		       BIGNUM *A, BIGNUM *B, char *K, int Klen,
-		       char *I, char *L, char *M1, int *M1len)
+		       BIGNUM *A, BIGNUM *B,
+                       unsigned char *K, unsigned int Klen,
+		       char *I, char *L,
+                       unsigned char *M1, unsigned int *M1len)
 {
-    int r, i, len;
+    int r;
+    unsigned int i, len;
     unsigned char Nhash[EVP_MAX_MD_SIZE];
     unsigned char ghash[EVP_MAX_MD_SIZE];
     unsigned char Ng[EVP_MAX_MD_SIZE];
@@ -1010,9 +1026,10 @@ static int CalculateM1(context_t *text, BIGNUM *N, BIGNUM *g,
 }
 
 static int CalculateM2(context_t *text, BIGNUM *A,
-		       char *M1, int M1len, char *K, int Klen,
+		       unsigned char *M1, unsigned int M1len,
+                       unsigned char *K, unsigned int Klen,
 		       char *I, char *o, char *sid, uint32 ttl,
-		       char *M2, int *M2len)
+		       unsigned char *M2, unsigned int *M2len)
 {
     int r;
     
@@ -1386,7 +1403,8 @@ static int SetMDA(srp_options_t *opts, context_t *text)
  * Setup the selected security layer.
  */
 static int LayerInit(srp_options_t *opts, context_t *text,
-		     sasl_out_params_t *oparams, char *enc_IV, char *dec_IV,
+		     sasl_out_params_t *oparams,
+                     unsigned char *enc_IV, unsigned char *dec_IV,
 		     unsigned maxbufsize)
 {
     layer_option_t *opt;
@@ -1431,8 +1449,10 @@ static int LayerInit(srp_options_t *opts, context_t *text,
 
 	/* Initialize the HMACs */
 	text->hmac_md = EVP_get_digestbyname(opt->evp_name);
-	HMAC_Init(&text->hmac_send_ctx, text->K, text->Klen, text->hmac_md);
-	HMAC_Init(&text->hmac_recv_ctx, text->K, text->Klen, text->hmac_md);
+        text->hmac_send_ctx = HMAC_CTX_new();
+	HMAC_Init_ex(text->hmac_send_ctx, text->K, text->Klen, text->hmac_md, NULL);
+        text->hmac_recv_ctx = HMAC_CTX_new();
+	HMAC_Init_ex(text->hmac_recv_ctx, text->K, text->Klen, text->hmac_md, NULL);
 	
 	/* account for HMAC */
 	oparams->maxoutbuf -= EVP_MD_size(text->hmac_md);
@@ -1456,11 +1476,13 @@ static int LayerInit(srp_options_t *opts, context_t *text,
 	/* Initialize the ciphers */
 	text->cipher = EVP_get_cipherbyname(opt->evp_name);
 
-	EVP_CIPHER_CTX_init(&text->cipher_enc_ctx);
-	EVP_EncryptInit(&text->cipher_enc_ctx, text->cipher, text->K, enc_IV);
+        text->cipher_enc_ctx = EVP_CIPHER_CTX_new();
+	EVP_CIPHER_CTX_init(text->cipher_enc_ctx);
+	EVP_EncryptInit(text->cipher_enc_ctx, text->cipher, text->K, enc_IV);
 
-	EVP_CIPHER_CTX_init(&text->cipher_dec_ctx);
-	EVP_DecryptInit(&text->cipher_dec_ctx, text->cipher, text->K, dec_IV);
+        text->cipher_dec_ctx = EVP_CIPHER_CTX_new();
+	EVP_CIPHER_CTX_init(text->cipher_dec_ctx);
+	EVP_DecryptInit(text->cipher_dec_ctx, text->cipher, text->K, dec_IV);
     }
     
     return SASL_OK;
@@ -1469,13 +1491,13 @@ static int LayerInit(srp_options_t *opts, context_t *text,
 static void LayerCleanup(context_t *text)
 {
     if (text->layer & BIT_INTEGRITY) {
-	HMAC_cleanup(&text->hmac_send_ctx);
-	HMAC_cleanup(&text->hmac_recv_ctx);
+	HMAC_CTX_free(text->hmac_send_ctx);
+	HMAC_CTX_free(text->hmac_recv_ctx);
     }
 
     if (text->layer & BIT_CONFIDENTIALITY) {
-	EVP_CIPHER_CTX_cleanup(&text->cipher_enc_ctx);
-	EVP_CIPHER_CTX_cleanup(&text->cipher_dec_ctx);
+	EVP_CIPHER_CTX_free(text->cipher_enc_ctx);
+	EVP_CIPHER_CTX_free(text->cipher_dec_ctx);
     }
 }
     
@@ -1490,13 +1512,13 @@ static void srp_common_mech_dispose(void *conn_context,
     
     if (!text) return;
     
-    BN_clear_free(&text->N);
-    BN_clear_free(&text->g);
-    BN_clear_free(&text->v);
-    BN_clear_free(&text->b);
-    BN_clear_free(&text->B);
-    BN_clear_free(&text->a);
-    BN_clear_free(&text->A);
+    BN_clear_free(text->N);
+    BN_clear_free(text->g);
+    BN_clear_free(text->v);
+    BN_clear_free(text->b);
+    BN_clear_free(text->B);
+    BN_clear_free(text->a);
+    BN_clear_free(text->A);
     
     if (text->authid)		utils->free(text->authid);
     if (text->userid)		utils->free(text->userid);
@@ -1534,16 +1556,16 @@ srp_common_mech_free(void *global_context __attribute__((unused)),
  *
  * All arithmetic is done modulo N
  */
-static int generate_N_and_g(BIGNUM *N, BIGNUM *g)
+static int generate_N_and_g(BIGNUM **N, BIGNUM **g)
 {
     int result;
-    
-    BN_init(N);
-    result = BN_hex2bn(&N, Ng_tab[NUM_Ng-1].N);
+
+    *N = BN_new();
+    result = BN_hex2bn(N, Ng_tab[NUM_Ng-1].N);
     if (!result) return SASL_FAIL;
     
-    BN_init(g);
-    BN_set_word(g, Ng_tab[NUM_Ng-1].g);
+    *g = BN_new();
+    BN_set_word(*g, Ng_tab[NUM_Ng-1].g);
     
     return SASL_OK;
 }
@@ -1551,10 +1573,10 @@ static int generate_N_and_g(BIGNUM *N, BIGNUM *g)
 static int CalculateV(context_t *text,
 		      BIGNUM *N, BIGNUM *g,
 		      const char *user,
-		      const char *pass, unsigned passlen,
-		      BIGNUM *v, char **salt, int *saltlen)
+		      const unsigned char *pass, unsigned passlen,
+		      BIGNUM **v, char **salt, int *saltlen)
 {
-    BIGNUM x;
+    BIGNUM *x = NULL;
     BN_CTX *ctx = BN_CTX_new();
     int r;
     
@@ -1572,40 +1594,41 @@ static int CalculateV(context_t *text,
     }
     
     /* v = g^x % N */
-    BN_init(v);
-    BN_mod_exp(v, g, &x, N, ctx);
+    *v = BN_new();
+    BN_mod_exp(*v, g, x, N, ctx);
     
     BN_CTX_free(ctx);
-    BN_clear_free(&x);
+    BN_clear_free(x);
     
     return r;   
 }
 
 static int CalculateB(context_t *text  __attribute__((unused)),
-		      BIGNUM *v, BIGNUM *N, BIGNUM *g, BIGNUM *b, BIGNUM *B)
+		      BIGNUM *v, BIGNUM *N, BIGNUM *g, BIGNUM **b, BIGNUM **B)
 {
-    BIGNUM v3;
+    BIGNUM *v3 = BN_new();
     BN_CTX *ctx = BN_CTX_new();
     
     /* Generate b */
     GetRandBigInt(b);
 	
     /* Per [SRP]: make sure b > log[g](N) -- g is always 2 */
-    BN_add_word(b, BN_num_bits(N));
+    BN_add_word(*b, BN_num_bits(N));
 	
     /* B = (3v + g^b) % N */
-    BN_init(&v3);
-    BN_set_word(&v3, 3);
-    BN_mod_mul(&v3, &v3, v, N, ctx);
-    BN_init(B);
-    BN_mod_exp(B, g, b, N, ctx);
+    BN_set_word(v3, 3);
+    BN_mod_mul(v3, v3, v, N, ctx);
+
+    *B = BN_new();
+    BN_mod_exp(*B, g, *b, N, ctx);
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
-    BN_mod_add(B, B, &v3, N, ctx);
+    BN_mod_add(*B, *B, v3, N, ctx);
 #else
-    BN_add(B, B, &v3);
-    BN_mod(B, B, N, ctx);
+    BN_add(*B, *B, v3);
+    BN_mod(*B, *B, N, ctx);
 #endif
 
+    BN_clear_free(v3);
     BN_CTX_free(ctx);
     
     return SASL_OK;
@@ -1613,13 +1636,13 @@ static int CalculateB(context_t *text  __attribute__((unused)),
 	
 static int ServerCalculateK(context_t *text, BIGNUM *v,
 			    BIGNUM *N, BIGNUM *A, BIGNUM *b, BIGNUM *B,
-			    char *K, int *Klen)
+			    unsigned char *K, unsigned int *Klen)
 {
     unsigned char hash[EVP_MAX_MD_SIZE];
-    int hashlen;
-    BIGNUM u;
-    BIGNUM base;
-    BIGNUM S;
+    unsigned int hashlen;
+    BIGNUM *u = BN_new();
+    BIGNUM *base = BN_new();
+    BIGNUM *S = BN_new();
     BN_CTX *ctx = BN_CTX_new();
     int r;
     
@@ -1627,50 +1650,47 @@ static int ServerCalculateK(context_t *text, BIGNUM *v,
     r = MakeHash(text->md, hash, &hashlen, "%m%m", A, B);
     if (r) return r;
 	
-    BN_init(&u);
-    BN_bin2bn(hash, hashlen, &u);
+    BN_bin2bn(hash, hashlen, u);
 	
     /* S = (Av^u) ^ b % N */
-    BN_init(&base);
-    BN_mod_exp(&base, v, &u, N, ctx);
-    BN_mod_mul(&base, &base, A, N, ctx);
+    BN_mod_exp(base, v, u, N, ctx);
+    BN_mod_mul(base, base, A, N, ctx);
     
-    BN_init(&S);
-    BN_mod_exp(&S, &base, b, N, ctx);
+    BN_mod_exp(S, base, b, N, ctx);
     
     /* per Tom Wu: make sure Av^u != 1 (mod N) */
-    if (BN_is_one(&base)) {
+    if (BN_is_one(base)) {
 	SETERROR(text->utils, "Unsafe SRP value for 'Av^u'\n");
 	r = SASL_BADPROT;
 	goto err;
     }
     
     /* per Tom Wu: make sure Av^u != -1 (mod N) */
-    BN_add_word(&base, 1);
-    if (BN_cmp(&S, N) == 0) {
+    BN_add_word(base, 1);
+    if (BN_cmp(S, N) == 0) {
 	SETERROR(text->utils, "Unsafe SRP value for 'Av^u'\n");
 	r = SASL_BADPROT;
 	goto err;
     }
     
     /* K = H(S) */
-    r = MakeHash(text->md, K, Klen, "%m", &S);
+    r = MakeHash(text->md, K, Klen, "%m", S);
     if (r) goto err;
     
     r = SASL_OK;
     
   err:
     BN_CTX_free(ctx);
-    BN_clear_free(&u);
-    BN_clear_free(&base);
-    BN_clear_free(&S);
+    BN_clear_free(u);
+    BN_clear_free(base);
+    BN_clear_free(S);
     
     return r;
 }
 
 static int ParseUserSecret(const sasl_utils_t *utils,
 			   char *secret, size_t seclen,
-			   char **mda, BIGNUM *v, char **salt, int *saltlen)
+			   char **mda, BIGNUM **v, char **salt, int *saltlen)
 {
     int r;
     
@@ -1678,7 +1698,7 @@ static int ParseUserSecret(const sasl_utils_t *utils,
      *
      *  { utf8(mda) mpi(v) os(salt) }  (base64 encoded)
      */
-    r = utils->decode64(secret, seclen, secret, seclen, &seclen);
+    r = utils->decode64(secret, seclen, secret, seclen, (unsigned *) &seclen);
 
     if (!r)
 	r = UnBuffer(utils, secret, seclen, "%s%m%o", mda, v, saltlen, salt);
@@ -1919,8 +1939,8 @@ static int srp_server_mech_step1(context_t *text,
 	    goto cleanup;
 	}
 	
-	result = CalculateV(text, &text->N, &text->g, text->authid,
-			    auxprop_values[1].values[0], len,
+	result = CalculateV(text, text->N, text->g, text->authid,
+			    (unsigned char *) auxprop_values[1].values[0], len,
 			    &text->v, &text->salt, &text->saltlen);
 	if (result) {
 	    params->utils->seterror(params->utils->conn, 0, 
@@ -1938,8 +1958,7 @@ static int srp_server_mech_step1(context_t *text,
     params->utils->prop_erase(params->propctx, password_request[1]);
     
     /* Calculate B */
-    result = CalculateB(text, &text->v, &text->N, &text->g,
-			&text->b, &text->B);
+    result = CalculateB(text, text->v, text->N, text->g, &text->b, &text->B);
     if (result) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error calculating B");
@@ -1967,8 +1986,8 @@ static int srp_server_mech_step1(context_t *text,
      */
     result = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len,
 			serveroutlen, "%c%m%m%o%m%s",
-			0x00, &text->N, &text->g, text->saltlen, text->salt,
-			&text->B, text->server_options);
+			0x00, text->N, text->g, text->saltlen, text->salt,
+			text->B, text->server_options);
     if (result) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error creating SRP buffer from data in step 1");
@@ -1997,15 +2016,15 @@ static int srp_server_mech_step2(context_t *text,
 			sasl_out_params_t *oparams)
 {
     int result;    
-    char *M1 = NULL, *cIV = NULL; /* don't free */
-    int M1len, cIVlen;
+    unsigned char *M1 = NULL, *cIV = NULL; /* don't free */
+    unsigned int M1len, cIVlen;
     srp_options_t client_opts;
-    char myM1[EVP_MAX_MD_SIZE];
-    int myM1len;
-    int i;
-    char M2[EVP_MAX_MD_SIZE];
-    int M2len;
-    char sIV[SRP_MAXBLOCKSIZE];
+    unsigned char myM1[EVP_MAX_MD_SIZE];
+    unsigned int myM1len;
+    unsigned int i;
+    unsigned char M2[EVP_MAX_MD_SIZE];
+    unsigned int M2len;
+    unsigned char sIV[SRP_MAXBLOCKSIZE];
     
     /* Expect:
      *
@@ -2027,7 +2046,7 @@ static int srp_server_mech_step2(context_t *text,
     }
     
     /* Per [SRP]: reject A <= 0 */
-    if (BigIntCmpWord(&text->A, 0) <= 0) {
+    if (BigIntCmpWord(text->A, 0) <= 0) {
 	SETERROR(params->utils, "Illegal value for 'A'\n");
 	result = SASL_BADPROT;
 	goto cleanup;
@@ -2058,8 +2077,8 @@ static int srp_server_mech_step2(context_t *text,
     }
 
     /* Calculate K */
-    result = ServerCalculateK(text, &text->v, &text->N, &text->A,
-			      &text->b, &text->B, text->K, &text->Klen);
+    result = ServerCalculateK(text, text->v, text->N, text->A,
+			      text->b, text->B, text->K, &text->Klen);
     if (result) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error calculating K");
@@ -2067,8 +2086,8 @@ static int srp_server_mech_step2(context_t *text,
     }
     
     /* See if M1 is correct */
-    result = CalculateM1(text, &text->N, &text->g, text->authid,
-			 text->salt, text->saltlen, &text->A, &text->B,
+    result = CalculateM1(text, text->N, text->g, text->authid,
+			 text->salt, text->saltlen, text->A, text->B,
 			 text->K, text->Klen, text->userid,
 			 text->server_options, myM1, &myM1len);
     if (result) {
@@ -2095,7 +2114,7 @@ static int srp_server_mech_step2(context_t *text,
     }
     
     /* calculate M2 to send */
-    result = CalculateM2(text, &text->A, M1, M1len, text->K, text->Klen,
+    result = CalculateM2(text, text->A, M1, M1len, text->K, text->Klen,
 			 text->userid, text->client_options, "", 0,
 			 M2, &M2len);
     if (result) {
@@ -2105,7 +2124,7 @@ static int srp_server_mech_step2(context_t *text,
     }
     
     /* Create sIV (server initial vector) */
-    text->utils->rand(text->utils->rpool, sIV, sizeof(sIV));
+    text->utils->rand(text->utils->rpool, (char *) sIV, sizeof(sIV));
     
     /*
      * Send out:
@@ -2230,20 +2249,20 @@ static int srp_setpass(void *glob_context __attribute__((unused)),
     r = _plug_make_fulluser(sparams->utils, &user, user_only, realm);
 
     if (r) {
-	goto end;
+	goto cleanup;
     }
 
     if ((flags & SASL_SET_DISABLE) || pass == NULL) {
 	sec = NULL;
     } else {
-	context_t *text;
-	BIGNUM N;
-	BIGNUM g;
-	BIGNUM v;
+	context_t *text = NULL;
+	BIGNUM *N = NULL;
+	BIGNUM *g = NULL;
+	BIGNUM *v = NULL;
 	char *salt;
 	int saltlen;
 	char *buffer = NULL;
-	int bufferlen, alloclen, encodelen;
+	unsigned int bufferlen, alloclen, encodelen;
 	
 	text = sparams->utils->malloc(sizeof(context_t));
 	if (text == NULL) {
@@ -2264,7 +2283,8 @@ static int srp_setpass(void *glob_context __attribute__((unused)),
 	}
 
 	/* user is a full username here */
-	r = CalculateV(text, &N, &g, user, pass, passlen, &v, &salt, &saltlen);
+	r = CalculateV(text, N, g, user,
+                       (unsigned char *) pass, passlen, &v, &salt, &saltlen);
 	if (r) {
 	    sparams->utils->seterror(sparams->utils->conn, 0, 
 				     "Error calculating v");
@@ -2296,16 +2316,16 @@ static int srp_setpass(void *glob_context __attribute__((unused)),
 	    r = SASL_NOMEM;
 	    goto end;
 	}
-	sparams->utils->encode64(buffer, bufferlen, sec->data, alloclen,
+	sparams->utils->encode64(buffer, bufferlen, (char *) sec->data, alloclen,
 				 &encodelen);
 	sec->len = encodelen;
 	
 	/* Clean everything up */
       end:
 	if (buffer) sparams->utils->free((void *) buffer);
-	BN_clear_free(&N);
-	BN_clear_free(&g);
-	BN_clear_free(&v);
+	BN_clear_free(N);
+	BN_clear_free(g);
+	BN_clear_free(v);
 	sparams->utils->free(text);
 	
 	if (r) return r;
@@ -2319,7 +2339,7 @@ static int srp_setpass(void *glob_context __attribute__((unused)),
 	r = sparams->utils->prop_request(propctx, store_request);
     if (!r)
 	r = sparams->utils->prop_set(propctx, "cmusaslsecretSRP",
-				     (sec ? sec->data : NULL),
+				     (char *) (sec ? sec->data : NULL),
 				     (sec ? sec->len : 0));
     if (!r)
 	r = sparams->utils->auxprop_store(sparams->utils->conn, propctx, user);
@@ -2475,7 +2495,7 @@ static int check_N_and_g(const sasl_utils_t *utils, BIGNUM *N, BIGNUM *g)
 }
 
 static int CalculateA(context_t *text  __attribute__((unused)),
-		      BIGNUM *N, BIGNUM *g, BIGNUM *a, BIGNUM *A)
+		      BIGNUM *N, BIGNUM *g, BIGNUM **a, BIGNUM **A)
 {
     BN_CTX *ctx = BN_CTX_new();
     
@@ -2483,11 +2503,11 @@ static int CalculateA(context_t *text  __attribute__((unused)),
     GetRandBigInt(a);
 	
     /* Per [SRP]: make sure a > log[g](N) -- g is always 2 */
-    BN_add_word(a, BN_num_bits(N));
+    BN_add_word(*a, BN_num_bits(N));
 	
     /* A = g^a % N */
-    BN_init(A);
-    BN_mod_exp(A, g, a, N, ctx);
+    *A = BN_new();
+    BN_mod_exp(*A, g, *a, N, ctx);
 
     BN_CTX_free(ctx);
     
@@ -2495,30 +2515,30 @@ static int CalculateA(context_t *text  __attribute__((unused)),
 }
 	
 static int ClientCalculateK(context_t *text, char *salt, int saltlen,
-			    char *user, char *pass, int passlen,
+			    char *user, unsigned char *pass, int passlen,
 			    BIGNUM *N, BIGNUM *g, BIGNUM *a, BIGNUM *A,
-			    BIGNUM *B, char *K, int *Klen)
+			    BIGNUM *B, unsigned char *K, unsigned int *Klen)
 {
     int r;
     unsigned char hash[EVP_MAX_MD_SIZE];
-    int hashlen;
-    BIGNUM x;
-    BIGNUM u;
-    BIGNUM aux;
-    BIGNUM gx;
-    BIGNUM gx3;
-    BIGNUM base;
-    BIGNUM S;
+    unsigned int hashlen;
+    BIGNUM *x = NULL;
+    BIGNUM *u = BN_new();
+    BIGNUM *aux = BN_new();
+    BIGNUM *gx = BN_new();
+    BIGNUM *gx3 = BN_new();
+    BIGNUM *base = BN_new();
+    BIGNUM *S = BN_new();
     BN_CTX *ctx = BN_CTX_new();
     
     /* u = H(A | B) */
     r = MakeHash(text->md, hash, &hashlen, "%m%m", A, B);
     if (r) goto err;
-    BN_init(&u);
-    BN_bin2bn(hash, hashlen, &u);
+    u = BN_new();
+    BN_bin2bn(hash, hashlen, u);
     
     /* per Tom Wu: make sure u != 0 */
-    if (BN_is_zero(&u)) {
+    if (BN_is_zero(u)) {
 	SETERROR(text->utils, "SRP: Illegal value for 'u'\n");
 	r = SASL_BADPROT;
 	goto err;
@@ -2530,48 +2550,43 @@ static int ClientCalculateK(context_t *text, char *salt, int saltlen,
     if (r) return r;
     
     /* a + ux */
-    BN_init(&aux);
-    BN_mul(&aux, &u, &x, ctx);
-    BN_add(&aux, &aux, a);
+    BN_mul(aux, u, x, ctx);
+    BN_add(aux, aux, a);
     
     /* gx3 = 3(g^x) % N */
-    BN_init(&gx);
-    BN_mod_exp(&gx, g, &x, N, ctx);
-    BN_init(&gx3);
-    BN_set_word(&gx3, 3);
-    BN_mod_mul(&gx3, &gx3, &gx, N, ctx);
+    BN_mod_exp(gx, g, x, N, ctx);
+    BN_set_word(gx3, 3);
+    BN_mod_mul(gx3, gx3, gx, N, ctx);
     
     /* base = (B - 3(g^x)) % N */
-    BN_init(&base);
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
-    BN_mod_sub(&base, B, &gx3, N, ctx);
+    BN_mod_sub(base, B, gx3, N, ctx);
 #else
-    BN_sub(&base, B, &gx3);
-    BN_mod(&base, &base, N, ctx);
-    if (BigIntCmpWord(&base, 0) < 0) {
-	BN_add(&base, &base, N);
+    BN_sub(base, B, gx3);
+    BN_mod(base, base, N, ctx);
+    if (BigIntCmpWord(base, 0) < 0) {
+	BN_add(base, base, N);
     }
 #endif
     
     /* S = base^aux % N */
-    BN_init(&S);
-    BN_mod_exp(&S, &base, &aux, N, ctx);
+    BN_mod_exp(S, base, aux, N, ctx);
     
     /* K = H(S) */
-    r = MakeHash(text->md, K, Klen, "%m", &S);
+    r = MakeHash(text->md, K, Klen, "%m", S);
     if (r) goto err;
     
     r = SASL_OK;
     
   err:
     BN_CTX_free(ctx);
-    BN_clear_free(&x);
-    BN_clear_free(&u);
-    BN_clear_free(&aux);
-    BN_clear_free(&gx);
-    BN_clear_free(&gx3);
-    BN_clear_free(&base);
-    BN_clear_free(&S);
+    BN_clear_free(x);
+    BN_clear_free(u);
+    BN_clear_free(aux);
+    BN_clear_free(gx);
+    BN_clear_free(gx3);
+    BN_clear_free(base);
+    BN_clear_free(S);
     
     return r;
 }
@@ -2709,7 +2724,7 @@ static int srp_client_mech_new(void *glob_context __attribute__((unused)),
     }
     
     memset(text, 0, sizeof(context_t));
-    
+
     text->state = 1;
     text->utils = params->utils;
 
@@ -2866,7 +2881,7 @@ srp_client_mech_step2(context_t *text,
     }
 
     /* Check N and g to see if they are one of the recommended pairs */
-    result = check_N_and_g(params->utils, &text->N, &text->g);
+    result = check_N_and_g(params->utils, text->N, text->g);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR,
 			   "Values of 'N' and 'g' are not recommended\n");
@@ -2874,7 +2889,7 @@ srp_client_mech_step2(context_t *text,
     }
     
     /* Per [SRP]: reject B <= 0, B >= N */
-    if (BigIntCmpWord(&text->B, 0) <= 0 || BN_cmp(&text->B, &text->N) >= 0) {
+    if (BigIntCmpWord(text->B, 0) <= 0 || BN_cmp(text->B, text->N) >= 0) {
 	SETERROR(params->utils, "Illegal value for 'B'\n");
 	result = SASL_BADPROT;
 	goto cleanup;
@@ -2913,7 +2928,7 @@ srp_client_mech_step2(context_t *text,
     }
 
     /* Calculate A */
-    result = CalculateA(text, &text->N, &text->g, &text->a, &text->A);
+    result = CalculateA(text, text->N, text->g, &text->a, &text->A);
     if (result) {
 	params->utils->seterror(params->utils->conn, 0, 
 				"Error calculating A");
@@ -2924,7 +2939,7 @@ srp_client_mech_step2(context_t *text,
     result = ClientCalculateK(text, text->salt, text->saltlen,
 			      (char *) oparams->authid, 
 			      text->password->data, text->password->len,
-			      &text->N, &text->g, &text->a, &text->A, &text->B,
+			      text->N, text->g, text->a, text->A, text->B,
 			      text->K, &text->Klen);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR,
@@ -2933,8 +2948,8 @@ srp_client_mech_step2(context_t *text,
     }
     
     /* Calculate M1 (client evidence) */
-    result = CalculateM1(text, &text->N, &text->g, (char *) oparams->authid,
-			 text->salt, text->saltlen, &text->A, &text->B,
+    result = CalculateM1(text, text->N, text->g, (char *) oparams->authid,
+			 text->salt, text->saltlen, text->A, text->B,
 			 text->K, text->Klen, (char *) oparams->user,
 			 text->server_options, text->M1, &text->M1len);
     if (result) {
@@ -2944,7 +2959,7 @@ srp_client_mech_step2(context_t *text,
     }
 
     /* Create cIV (client initial vector) */
-    text->utils->rand(text->utils->rpool, text->cIV, sizeof(text->cIV));
+    text->utils->rand(text->utils->rpool, (char *) text->cIV, sizeof(text->cIV));
     
     /* Send out:
      *
@@ -2957,7 +2972,7 @@ srp_client_mech_step2(context_t *text,
      */
     result = MakeBuffer(text->utils, &text->out_buf, &text->out_buf_len,
 			clientoutlen, "%m%o%s%o",
-			&text->A, text->M1len, text->M1, text->client_options,
+			text->A, text->M1len, text->M1, text->client_options,
 			sizeof(text->cIV), text->cIV);
     if (result) {
 	params->utils->log(NULL, SASL_LOG_ERR, "Error making output buffer\n");
@@ -2985,13 +3000,13 @@ srp_client_mech_step3(context_t *text,
 		      sasl_out_params_t *oparams)
 {
     int result;    
-    char *M2 = NULL, *sIV = NULL; /* don't free */
+    unsigned char *M2 = NULL, *sIV = NULL; /* don't free */
     char *sid = NULL;
-    int M2len, sIVlen;
+    unsigned int M2len, sIVlen;
     uint32 ttl;
-    int i;
-    char myM2[EVP_MAX_MD_SIZE];
-    int myM2len;
+    unsigned int i;
+    unsigned char myM2[EVP_MAX_MD_SIZE];
+    unsigned int myM2len;
     
     /* Expect:
      *
@@ -3012,7 +3027,7 @@ srp_client_mech_step3(context_t *text,
     }
 
     /* calculate our own M2 */
-    result = CalculateM2(text, &text->A, text->M1, text->M1len,
+    result = CalculateM2(text, text->A, text->M1, text->M1len,
 			 text->K, text->Klen, (char *) oparams->user,
 			 text->client_options, "", 0,
 			 myM2, &myM2len);
diff --git a/saslauthd/Makefile.am b/saslauthd/Makefile.am
index ce1e92b..b3a7dc3 100644
--- a/saslauthd/Makefile.am
+++ b/saslauthd/Makefile.am
@@ -2,6 +2,8 @@ AUTOMAKE_OPTIONS = 1.7
 sbin_PROGRAMS	= saslauthd testsaslauthd
 EXTRA_PROGRAMS  = saslcache
 
+CRYPTO_COMPAT_OBJS = $(top_builddir)/common/libcrypto_compat.la
+
 saslauthd_SOURCES = mechanisms.c globals.h \
 		    mechanisms.h auth_dce.c auth_dce.h auth_getpwent.c \
 		    auth_getpwent.h auth_krb5.c auth_krb5.h auth_krb4.c \
@@ -16,7 +18,7 @@ EXTRA_saslauthd_sources = getaddrinfo.c getnameinfo.c
 saslauthd_DEPENDENCIES = saslauthd-main.o @LTLIBOBJS@
 saslauthd_LDADD	= @SASL_KRB_LIB@ \
 		  @GSSAPIBASE_LIBS@ @GSSAPI_LIBS@ @LIB_CRYPT@ @LIB_SIA@ \
-		  @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ @LTLIBOBJS@
+		  @LIB_SOCKET@ @SASL_DB_LIB@ @LIB_PAM@ @LDAP_LIBS@ @LTLIBOBJS@ $(CRYPTO_COMPAT_OBJS)
 
 testsaslauthd_SOURCES = testsaslauthd.c utils.c
 testsaslauthd_LDADD = @LIB_SOCKET@
@@ -25,7 +27,7 @@ saslcache_SOURCES = saslcache.c
 
 EXTRA_DIST	= saslauthd.8 saslauthd.mdoc config include \
 		  getnameinfo.c getaddrinfo.c LDAP_SASLAUTHD
-INCLUDES	= -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/../include
+INCLUDES	= -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_srcdir)/../include -I$(top_builddir)/common
 DEFS            = @DEFS@ -DSASLAUTHD_CONF_FILE_DEFAULT=\"@sysconfdir@/saslauthd.conf\" -I. -I$(srcdir) -I..
 
 
diff --git a/saslauthd/lak.c b/saslauthd/lak.c
index 419a658..f366fc0 100644
--- a/saslauthd/lak.c
+++ b/saslauthd/lak.c
@@ -53,6 +53,9 @@
 #endif
 #include <openssl/evp.h>
 #include <openssl/des.h>
+
+/* for legacy libcrypto support */
+#include "crypto-compat.h"
 #endif
 
 #define LDAP_DEPRECATED 1
-- 
2.7.4

