diff -rupN cyrus-sasl-2.1.26/plugins/srp.c cyrus-sasl-2.1.26-new/plugins/srp.c
--- cyrus-sasl-2.1.26/plugins/srp.c	2012-10-12 07:05:48.000000000 -0700
+++ cyrus-sasl-2.1.26-new/plugins/srp.c	2017-11-21 17:01:53.628237347 -0800
@@ -1,10 +1,9 @@
 /* SRP SASL plugin
  * Ken Murchison
  * Tim Martin  3/17/00
- * $Id: srp.c,v 1.59 2010/11/30 11:41:47 mel Exp $
  */
 /* 
- * Copyright (c) 1998-2003 Carnegie Mellon University.  All rights reserved.
+ * Copyright (c) 1998-2016 Carnegie Mellon University.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -22,12 +21,13 @@
  *    endorse or promote products derived from this software without
  *    prior written permission. For permission or any other legal
  *    details, please contact  
- *      Office of Technology Transfer
  *      Carnegie Mellon University
- *      5000 Forbes Avenue
- *      Pittsburgh, PA  15213-3890
- *      (412) 268-4387, fax: (412) 268-7395
- *      tech-transfer@andrew.cmu.edu
+ *      Center for Technology Transfer and Enterprise Creation
+ *      4615 Forbes Avenue
+ *      Suite 302
+ *      Pittsburgh, PA  15213
+ *      (412) 268-7393, fax: (412) 268-7395
+ *      innovation@andrew.cmu.edu
  *
  * 4. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
@@ -101,8 +101,6 @@ typedef unsigned short uint32;
 
 /*****************************  Common Section  *****************************/
 
-static const char plugin_id[] = "$Id: srp.c,v 1.59 2010/11/30 11:41:47 mel Exp $";
-
 /* Size limit of cipher block size */
 #define SRP_MAXBLOCKSIZE 16
 /* Size limit of SRP buffer */
@@ -216,22 +214,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 +240,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 +257,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;
@@ -279,6 +277,52 @@ typedef struct context {
     
 } context_t;
 
+static void *OPENSSL_zalloc(size_t num)
+{
+    void *ret = OPENSSL_malloc(num);
+
+    if (ret != NULL)
+        memset(ret, 0, num);
+    return ret;
+}
+
+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;
+}
+
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+        EVP_MD_CTX_cleanup(ctx);
+            OPENSSL_free(ctx);
+}
+
+EVP_MD_CTX *EVP_MD_CTX_new(void)
+{
+    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
+}
+
 static int srp_encode(void *context,
 		      const struct iovec *invec,
 		      unsigned numiov,
@@ -317,12 +361,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 +381,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 +394,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 +434,8 @@ static int srp_decode_packet(void *conte
 
     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 +452,23 @@ static int srp_decode_packet(void *conte
 	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 +477,17 @@ static int srp_decode_packet(void *conte
     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 +520,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 +551,12 @@ static int BigIntCmpWord(BIGNUM *a, BN_U
 /*
  * 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 +671,8 @@ static int MakeBuffer(const sasl_utils_t
 	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 +743,7 @@ static int UnBuffer(const sasl_utils_t *
     va_list ap;
     char *p;
     int r = SASL_OK, noalloc;
-    BIGNUM *mpi;
+    BIGNUM **mpi;
     char **os, **str;
     uint32 *u;
     unsigned short ns;
@@ -757,9 +805,12 @@ static int UnBuffer(const sasl_utils_t *
 		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 +934,17 @@ static int UnBuffer(const sasl_utils_t *
 /*
  * 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 +962,7 @@ static int MakeHash(const EVP_MD *md, un
 		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 +999,52 @@ static int MakeHash(const EVP_MD *md, un
 
 	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 +1067,10 @@ static int CalculateM1(context_t *text,
 }
 
 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 +1444,8 @@ static int SetMDA(srp_options_t *opts, c
  * 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 +1490,10 @@ static int LayerInit(srp_options_t *opts
 
 	/* 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 +1517,13 @@ static int LayerInit(srp_options_t *opts
 	/* 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);
-
-	EVP_CIPHER_CTX_init(&text->cipher_dec_ctx);
-	EVP_DecryptInit(&text->cipher_dec_ctx, text->cipher, text->K, dec_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);
+
+        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 +1532,13 @@ static int LayerInit(srp_options_t *opts
 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 +1553,13 @@ static void srp_common_mech_dispose(void
     
     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 +1597,16 @@ srp_common_mech_free(void *global_contex
  *
  * 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 +1614,10 @@ static int generate_N_and_g(BIGNUM *N, B
 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 +1635,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 +1677,13 @@ static int CalculateB(context_t *text  _
 	
 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 +1691,47 @@ static int ServerCalculateK(context_t *t
     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 +1739,7 @@ static int ParseUserSecret(const sasl_ut
      *
      *  { 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 +1980,8 @@ static int srp_server_mech_step1(context
 	    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 +1999,7 @@ static int srp_server_mech_step1(context
     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 +2027,8 @@ static int srp_server_mech_step1(context
      */
     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 +2057,15 @@ static int srp_server_mech_step2(context
 			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 +2087,7 @@ static int srp_server_mech_step2(context
     }
     
     /* 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 +2118,8 @@ static int srp_server_mech_step2(context
     }
 
     /* 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 +2127,8 @@ static int srp_server_mech_step2(context
     }
     
     /* 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 +2155,7 @@ static int srp_server_mech_step2(context
     }
     
     /* 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 +2165,7 @@ static int srp_server_mech_step2(context
     }
     
     /* 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 +2290,20 @@ static int srp_setpass(void *glob_contex
     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 +2324,8 @@ static int srp_setpass(void *glob_contex
 	}
 
 	/* 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 +2357,16 @@ static int srp_setpass(void *glob_contex
 	    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 +2380,7 @@ static int srp_setpass(void *glob_contex
 	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 +2536,7 @@ static int check_N_and_g(const sasl_util
 }
 
 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 +2544,11 @@ static int CalculateA(context_t *text  _
     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 +2556,29 @@ static int CalculateA(context_t *text  _
 }
 	
 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);
+    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 +2590,43 @@ static int ClientCalculateK(context_t *t
     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 +2764,7 @@ static int srp_client_mech_new(void *glo
     }
     
     memset(text, 0, sizeof(context_t));
-    
+
     text->state = 1;
     text->utils = params->utils;
 
@@ -2866,7 +2921,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 +2929,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 +2968,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 +2979,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 +2988,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 +2999,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 +3012,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 +3040,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 +3067,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);
@@ -3182,3 +3237,4 @@ int srp_client_plug_init(const sasl_util
     
     return SASL_OK;
 }
+