Blame SOURCES/cyrus-sasl-2.1.27-cumulative-digestmd5.patch

8b8af0
diff -uPr cyrus-sasl-2.1.27/plugins/digestmd5.c cyrus-sasl-2.1.27.digestmd5/plugins/digestmd5.c
8b8af0
--- cyrus-sasl-2.1.27/plugins/digestmd5.c	2021-09-30 17:13:06.573093526 -0400
8b8af0
+++ cyrus-sasl-2.1.27.digestmd5/plugins/digestmd5.c	2021-09-30 17:26:31.818378442 -0400
8b8af0
@@ -80,6 +80,12 @@
8b8af0
 # endif
8b8af0
 #endif /* WITH_DES */
8b8af0
 
8b8af0
+/* legacy provider with openssl 3.0 */
8b8af0
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
8b8af0
+#  include <openssl/provider.h>
8b8af0
+#  include <openssl/crypto.h>
8b8af0
+#endif
8b8af0
+
8b8af0
 #ifdef WIN32
8b8af0
 # include <winsock2.h>
8b8af0
 #else /* Unix */
8b8af0
@@ -170,6 +176,12 @@
8b8af0
 
8b8af0
 typedef struct cipher_context cipher_context_t;
8b8af0
 
8b8af0
+typedef struct crypto_context {
8b8af0
+    void *libctx;
8b8af0
+    cipher_context_t *enc_ctx;
8b8af0
+    cipher_context_t *dec_ctx;
8b8af0
+} crypto_context_t;
8b8af0
+
8b8af0
 /* cached auth info used for fast reauth */
8b8af0
 typedef struct reauth_entry {
8b8af0
     char *authid;
8b8af0
@@ -254,12 +266,12 @@
8b8af0
     decode_context_t decode_context;
8b8af0
 
8b8af0
     /* if privacy mode is used use these functions for encode and decode */
8b8af0
+    char *cipher_name;
8b8af0
     cipher_function_t *cipher_enc;
8b8af0
     cipher_function_t *cipher_dec;
8b8af0
     cipher_init_t *cipher_init;
8b8af0
     cipher_free_t *cipher_free;
8b8af0
-    struct cipher_context *cipher_enc_context;
8b8af0
-    struct cipher_context *cipher_dec_context;
8b8af0
+    crypto_context_t crypto;
8b8af0
 } context_t;
8b8af0
 
8b8af0
 struct digest_cipher {
8b8af0
@@ -888,7 +900,7 @@
8b8af0
 		    char *output,
8b8af0
 		    unsigned *outputlen)
8b8af0
 {
8b8af0
-    des_context_t *c = (des_context_t *) text->cipher_dec_context;
8b8af0
+    des_context_t *c = (des_context_t *) text->crypto.dec_ctx;
8b8af0
     int padding, p;
8b8af0
     
8b8af0
     des_ede2_cbc_encrypt((void *) input,
8b8af0
@@ -925,7 +937,7 @@
8b8af0
 		    char *output,
8b8af0
 		    unsigned *outputlen)
8b8af0
 {
8b8af0
-    des_context_t *c = (des_context_t *) text->cipher_enc_context;
8b8af0
+    des_context_t *c = (des_context_t *) text->crypto.enc_ctx;
8b8af0
     int len;
8b8af0
     int paddinglen;
8b8af0
     
8b8af0
@@ -973,7 +985,7 @@
8b8af0
 	return SASL_FAIL;
8b8af0
     memcpy(c->ivec, ((char *) enckey) + 8, 8);
8b8af0
 
8b8af0
-    text->cipher_enc_context = (cipher_context_t *) c;
8b8af0
+    text->crypto.enc_ctx = (cipher_context_t *) c;
8b8af0
 
8b8af0
     /* setup dec context */
8b8af0
     c++;
8b8af0
@@ -987,7 +999,7 @@
8b8af0
     
8b8af0
     memcpy(c->ivec, ((char *) deckey) + 8, 8);
8b8af0
 
8b8af0
-    text->cipher_dec_context = (cipher_context_t *) c;
8b8af0
+    text->crypto.dec_ctx = (cipher_context_t *) c;
8b8af0
     
8b8af0
     return SASL_OK;
8b8af0
 }
8b8af0
@@ -1006,7 +1018,7 @@
8b8af0
 		   char *output,
8b8af0
 		   unsigned *outputlen)
8b8af0
 {
8b8af0
-    des_context_t *c = (des_context_t *) text->cipher_dec_context;
8b8af0
+    des_context_t *c = (des_context_t *) text->crypto.dec_ctx;
8b8af0
     int p, padding = 0;
8b8af0
     
8b8af0
     des_cbc_encrypt((void *) input,
8b8af0
@@ -1046,7 +1058,7 @@
8b8af0
 		   char *output,
8b8af0
 		   unsigned *outputlen)
8b8af0
 {
8b8af0
-    des_context_t *c = (des_context_t *) text->cipher_enc_context;
8b8af0
+    des_context_t *c = (des_context_t *) text->crypto.enc_ctx;
8b8af0
     int len;
8b8af0
     int paddinglen;
8b8af0
   
8b8af0
@@ -1093,7 +1105,7 @@
8b8af0
 
8b8af0
     memcpy(c->ivec, ((char *) enckey) + 8, 8);
8b8af0
     
8b8af0
-    text->cipher_enc_context = (cipher_context_t *) c;
8b8af0
+    text->crypto.enc_ctx = (cipher_context_t *) c;
8b8af0
 
8b8af0
     /* setup dec context */
8b8af0
     c++;
8b8af0
@@ -1102,60 +1114,139 @@
8b8af0
 
8b8af0
     memcpy(c->ivec, ((char *) deckey) + 8, 8);
8b8af0
     
8b8af0
-    text->cipher_dec_context = (cipher_context_t *) c;
8b8af0
+    text->crypto.dec_ctx = (cipher_context_t *) c;
8b8af0
 
8b8af0
     return SASL_OK;
8b8af0
 }
8b8af0
 
8b8af0
 static void free_des(context_t *text)
8b8af0
 {
8b8af0
-    /* free des contextss. only cipher_enc_context needs to be free'd,
8b8af0
-       since cipher_dec_context was allocated at the same time. */
8b8af0
-    if (text->cipher_enc_context) text->utils->free(text->cipher_enc_context);
8b8af0
+    /* free des contextss. only enc_ctx needs to be free'd,
8b8af0
+       since dec_cxt was allocated at the same time. */
8b8af0
+    if (text->crypto.enc_ctx) {
8b8af0
+        text->utils->free(text->crypto.enc_ctx);
8b8af0
+    }
8b8af0
 }
8b8af0
 
8b8af0
 #endif /* WITH_DES */
8b8af0
 
8b8af0
 #ifdef WITH_RC4
8b8af0
-#ifdef HAVE_OPENSSL
8b8af0
 #include <openssl/evp.h>
8b8af0
 
8b8af0
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
8b8af0
+typedef struct ossl3_library_context {
8b8af0
+    OSSL_LIB_CTX *libctx;
8b8af0
+    OSSL_PROVIDER *legacy_provider;
8b8af0
+    OSSL_PROVIDER *default_provider;
8b8af0
+} ossl3_context_t;
8b8af0
+
8b8af0
+static int init_ossl3_ctx(context_t *text)
8b8af0
+{
8b8af0
+    ossl3_context_t *ctx = text->utils->malloc(sizeof(ossl3_context_t));
8b8af0
+    if (!ctx) return SASL_NOMEM;
8b8af0
+
8b8af0
+    ctx->libctx = OSSL_LIB_CTX_new();
8b8af0
+    if (!ctx->libctx) {
8b8af0
+        text->utils->free(ctx);
8b8af0
+        return SASL_FAIL;
8b8af0
+    }
8b8af0
+
8b8af0
+    /* Load both legacy and default provider as both may be needed */
8b8af0
+    /* if they fail keep going and an error will be raised when we try to
8b8af0
+     * fetch the cipher later */
8b8af0
+    ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
8b8af0
+    ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
8b8af0
+    text->crypto.libctx = (void *)ctx;
8b8af0
+
8b8af0
+    return SASL_OK;
8b8af0
+}
8b8af0
+
8b8af0
+static void free_ossl3_ctx(context_t *text)
8b8af0
+{
8b8af0
+    ossl3_context_t *ctx;
8b8af0
+
8b8af0
+    if (!text->crypto.libctx) return;
8b8af0
+
8b8af0
+    ctx = (ossl3_context_t *)text->crypto.libctx;
8b8af0
+
8b8af0
+    if (ctx->legacy_provider) OSSL_PROVIDER_unload(ctx->legacy_provider);
8b8af0
+    if (ctx->default_provider) OSSL_PROVIDER_unload(ctx->default_provider);
8b8af0
+    if (ctx->libctx) OSSL_LIB_CTX_free(ctx->libctx);
8b8af0
+
8b8af0
+    text->utils->free(ctx);
8b8af0
+    text->crypto.libctx = NULL;
8b8af0
+}
8b8af0
+#endif
8b8af0
+
8b8af0
 static void free_rc4(context_t *text)
8b8af0
 {
8b8af0
-    if (text->cipher_enc_context) {
8b8af0
-        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_enc_context);
8b8af0
-        text->cipher_enc_context = NULL;
8b8af0
-    }
8b8af0
-    if (text->cipher_dec_context) {
8b8af0
-        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_dec_context);
8b8af0
-        text->cipher_dec_context = NULL;
8b8af0
+    if (text->crypto.enc_ctx) {
8b8af0
+        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->crypto.enc_ctx);
8b8af0
+        text->crypto.enc_ctx = NULL;
8b8af0
+    }
8b8af0
+    if (text->crypto.dec_ctx) {
8b8af0
+        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->crypto.dec_ctx);
8b8af0
+        text->crypto.dec_ctx = NULL;
8b8af0
     }
8b8af0
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
8b8af0
+    free_ossl3_ctx(text);
8b8af0
+#endif
8b8af0
 }
8b8af0
 
8b8af0
 static int init_rc4(context_t *text,
8b8af0
 		    unsigned char enckey[16],
8b8af0
 		    unsigned char deckey[16])
8b8af0
 {
8b8af0
+    const EVP_CIPHER *cipher;
8b8af0
     EVP_CIPHER_CTX *ctx;
8b8af0
     int rc;
8b8af0
 
8b8af0
-    ctx = EVP_CIPHER_CTX_new();
8b8af0
-    if (ctx == NULL) return SASL_NOMEM;
8b8af0
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
8b8af0
+    ossl3_context_t *ossl3_ctx;
8b8af0
 
8b8af0
-    rc = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, enckey, NULL);
8b8af0
-    if (rc != 1) return SASL_FAIL;
8b8af0
+    rc = init_ossl3_ctx(text);
8b8af0
+    if (rc != SASL_OK) return rc;
8b8af0
+
8b8af0
+    ossl3_ctx = (ossl3_context_t *)text->crypto.libctx;
8b8af0
+    cipher = EVP_CIPHER_fetch(ossl3_ctx->libctx, "RC4", "");
8b8af0
+#else
8b8af0
+    cipher = EVP_rc4();
8b8af0
+#endif
8b8af0
 
8b8af0
-    text->cipher_enc_context = (void *)ctx;
8b8af0
 
8b8af0
     ctx = EVP_CIPHER_CTX_new();
8b8af0
-    if (ctx == NULL) return SASL_NOMEM;
8b8af0
+    if (ctx == NULL) {
8b8af0
+        rc = SASL_NOMEM;
8b8af0
+        goto done;
8b8af0
+    }
8b8af0
 
8b8af0
-    rc = EVP_DecryptInit_ex(ctx, EVP_rc4(), NULL, deckey, NULL);
8b8af0
-    if (rc != 1) return SASL_FAIL;
8b8af0
+    rc = EVP_EncryptInit_ex(ctx, cipher, NULL, enckey, NULL);
8b8af0
+    if (rc != 1) {
8b8af0
+        rc = SASL_FAIL;
8b8af0
+        goto done;
8b8af0
+    }
8b8af0
+    text->crypto.enc_ctx = (void *)ctx;
8b8af0
 
8b8af0
-    text->cipher_dec_context = (void *)ctx;
8b8af0
+    ctx = EVP_CIPHER_CTX_new();
8b8af0
+    if (ctx == NULL) {
8b8af0
+        rc = SASL_NOMEM;
8b8af0
+        goto done;
8b8af0
+    }
8b8af0
 
8b8af0
-    return SASL_OK;
8b8af0
+    rc = EVP_DecryptInit_ex(ctx, cipher, NULL, deckey, NULL);
8b8af0
+    if (rc != 1) {
8b8af0
+        rc = SASL_FAIL;
8b8af0
+        goto done;
8b8af0
+    }
8b8af0
+    text->crypto.dec_ctx = (void *)ctx;
8b8af0
+
8b8af0
+    rc = SASL_OK;
8b8af0
+
8b8af0
+done:
8b8af0
+    if (rc != SASL_OK) {
8b8af0
+        free_rc4(text);
8b8af0
+    }
8b8af0
+    return rc;
8b8af0
 }
8b8af0
 
8b8af0
 static int dec_rc4(context_t *text,
8b8af0
@@ -1169,14 +1260,14 @@
8b8af0
     int rc;
8b8af0
 
8b8af0
     /* decrypt the text part & HMAC */
8b8af0
-    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->cipher_dec_context,
8b8af0
+    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->crypto.dec_ctx,
8b8af0
                            (unsigned char *)output, &len,
8b8af0
                            (const unsigned char *)input, inputlen);
8b8af0
     if (rc != 1) return SASL_FAIL;
8b8af0
 
8b8af0
     *outputlen = len;
8b8af0
 
8b8af0
-    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_dec_context,
8b8af0
+    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->crypto.dec_ctx,
8b8af0
                              (unsigned char *)output + len, &len;;
8b8af0
     if (rc != 1) return SASL_FAIL;
8b8af0
 
8b8af0
@@ -1198,7 +1289,7 @@
8b8af0
     int len;
8b8af0
     int rc;
8b8af0
     /* encrypt the text part */
8b8af0
-    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
8b8af0
+    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
8b8af0
                            (unsigned char *)output, &len,
8b8af0
                            (const unsigned char *)input, inputlen);
8b8af0
     if (rc != 1) return SASL_FAIL;
8b8af0
@@ -1206,14 +1297,14 @@
8b8af0
     *outputlen = len;
8b8af0
 
8b8af0
     /* encrypt the `MAC part */
8b8af0
-    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
8b8af0
+    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
8b8af0
                            (unsigned char *)output + *outputlen, &len,
8b8af0
                            digest, 10);
8b8af0
     if (rc != 1) return SASL_FAIL;
8b8af0
 
8b8af0
     *outputlen += len;
8b8af0
 
8b8af0
-    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_enc_context,
8b8af0
+    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->crypto.enc_ctx,
8b8af0
                              (unsigned char *)output + *outputlen, &len;;
8b8af0
     if (rc != 1) return SASL_FAIL;
8b8af0
 
8b8af0
@@ -1221,188 +1312,11 @@
8b8af0
 
8b8af0
     return SASL_OK;
8b8af0
 }
8b8af0
-#else
8b8af0
-/* quick generic implementation of RC4 */
8b8af0
-struct rc4_context_s {
8b8af0
-    unsigned char sbox[256];
8b8af0
-    int i, j;
8b8af0
-};
8b8af0
-
8b8af0
-typedef struct rc4_context_s rc4_context_t;
8b8af0
-
8b8af0
-static void rc4_init(rc4_context_t *text,
8b8af0
-		     const unsigned char *key,
8b8af0
-		     unsigned keylen)
8b8af0
-{
8b8af0
-    int i, j;
8b8af0
-    
8b8af0
-    /* fill in linearly s0=0 s1=1... */
8b8af0
-    for (i=0;i<256;i++)
8b8af0
-	text->sbox[i]=i;
8b8af0
-    
8b8af0
-    j=0;
8b8af0
-    for (i = 0; i < 256; i++) {
8b8af0
-	unsigned char tmp;
8b8af0
-	/* j = (j + Si + Ki) mod 256 */
8b8af0
-	j = (j + text->sbox[i] + key[i % keylen]) % 256;
8b8af0
-	
8b8af0
-	/* swap Si and Sj */
8b8af0
-	tmp = text->sbox[i];
8b8af0
-	text->sbox[i] = text->sbox[j];
8b8af0
-	text->sbox[j] = tmp;
8b8af0
-    }
8b8af0
-    
8b8af0
-    /* counters initialized to 0 */
8b8af0
-    text->i = 0;
8b8af0
-    text->j = 0;
8b8af0
-}
8b8af0
-
8b8af0
-static void rc4_encrypt(rc4_context_t *text,
8b8af0
-			const char *input,
8b8af0
-			char *output,
8b8af0
-			unsigned len)
8b8af0
-{
8b8af0
-    int tmp;
8b8af0
-    int i = text->i;
8b8af0
-    int j = text->j;
8b8af0
-    int t;
8b8af0
-    int K;
8b8af0
-    const char *input_end = input + len;
8b8af0
-    
8b8af0
-    while (input < input_end) {
8b8af0
-	i = (i + 1) % 256;
8b8af0
-	
8b8af0
-	j = (j + text->sbox[i]) % 256;
8b8af0
-	
8b8af0
-	/* swap Si and Sj */
8b8af0
-	tmp = text->sbox[i];
8b8af0
-	text->sbox[i] = text->sbox[j];
8b8af0
-	text->sbox[j] = tmp;
8b8af0
-	
8b8af0
-	t = (text->sbox[i] + text->sbox[j]) % 256;
8b8af0
-	
8b8af0
-	K = text->sbox[t];
8b8af0
-	
8b8af0
-	/* byte K is Xor'ed with plaintext */
8b8af0
-	*output++ = *input++ ^ K;
8b8af0
-    }
8b8af0
-    
8b8af0
-    text->i = i;
8b8af0
-    text->j = j;
8b8af0
-}
8b8af0
-
8b8af0
-static void rc4_decrypt(rc4_context_t *text,
8b8af0
-			const char *input,
8b8af0
-			char *output,
8b8af0
-			unsigned len)
8b8af0
-{
8b8af0
-    int tmp;
8b8af0
-    int i = text->i;
8b8af0
-    int j = text->j;
8b8af0
-    int t;
8b8af0
-    int K;
8b8af0
-    const char *input_end = input + len;
8b8af0
-    
8b8af0
-    while (input < input_end) {
8b8af0
-	i = (i + 1) % 256;
8b8af0
-	
8b8af0
-	j = (j + text->sbox[i]) % 256;
8b8af0
-	
8b8af0
-	/* swap Si and Sj */
8b8af0
-	tmp = text->sbox[i];
8b8af0
-	text->sbox[i] = text->sbox[j];
8b8af0
-	text->sbox[j] = tmp;
8b8af0
-	
8b8af0
-	t = (text->sbox[i] + text->sbox[j]) % 256;
8b8af0
-	
8b8af0
-	K = text->sbox[t];
8b8af0
-	
8b8af0
-	/* byte K is Xor'ed with plaintext */
8b8af0
-	*output++ = *input++ ^ K;
8b8af0
-    }
8b8af0
-    
8b8af0
-    text->i = i;
8b8af0
-    text->j = j;
8b8af0
-}
8b8af0
-
8b8af0
-static void free_rc4(context_t *text)
8b8af0
-{
8b8af0
-    /* free rc4 context structures */
8b8af0
-
8b8af0
-    if(text->cipher_enc_context) text->utils->free(text->cipher_enc_context);
8b8af0
-    if(text->cipher_dec_context) text->utils->free(text->cipher_dec_context);
8b8af0
-}
8b8af0
-
8b8af0
-static int init_rc4(context_t *text, 
8b8af0
-		    unsigned char enckey[16],
8b8af0
-		    unsigned char deckey[16])
8b8af0
-{
8b8af0
-    /* allocate rc4 context structures */
8b8af0
-    text->cipher_enc_context=
8b8af0
-	(cipher_context_t *) text->utils->malloc(sizeof(rc4_context_t));
8b8af0
-    if (text->cipher_enc_context == NULL) return SASL_NOMEM;
8b8af0
-    
8b8af0
-    text->cipher_dec_context=
8b8af0
-	(cipher_context_t *) text->utils->malloc(sizeof(rc4_context_t));
8b8af0
-    if (text->cipher_dec_context == NULL) return SASL_NOMEM;
8b8af0
-    
8b8af0
-    /* initialize them */
8b8af0
-    rc4_init((rc4_context_t *) text->cipher_enc_context,
8b8af0
-             (const unsigned char *) enckey, 16);
8b8af0
-    rc4_init((rc4_context_t *) text->cipher_dec_context,
8b8af0
-             (const unsigned char *) deckey, 16);
8b8af0
-    
8b8af0
-    return SASL_OK;
8b8af0
-}
8b8af0
-
8b8af0
-static int dec_rc4(context_t *text,
8b8af0
-		   const char *input,
8b8af0
-		   unsigned inputlen,
8b8af0
-		   unsigned char digest[16] __attribute__((unused)),
8b8af0
-		   char *output,
8b8af0
-		   unsigned *outputlen)
8b8af0
-{
8b8af0
-    /* decrypt the text part & HMAC */
8b8af0
-    rc4_decrypt((rc4_context_t *) text->cipher_dec_context, 
8b8af0
-                input, output, inputlen);
8b8af0
-
8b8af0
-    /* no padding so we just subtract the HMAC to get the text length */
8b8af0
-    *outputlen = inputlen - 10;
8b8af0
-    
8b8af0
-    return SASL_OK;
8b8af0
-}
8b8af0
-
8b8af0
-static int enc_rc4(context_t *text,
8b8af0
-		   const char *input,
8b8af0
-		   unsigned inputlen,
8b8af0
-		   unsigned char digest[16],
8b8af0
-		   char *output,
8b8af0
-		   unsigned *outputlen)
8b8af0
-{
8b8af0
-    /* pad is zero */
8b8af0
-    *outputlen = inputlen+10;
8b8af0
-    
8b8af0
-    /* encrypt the text part */
8b8af0
-    rc4_encrypt((rc4_context_t *) text->cipher_enc_context,
8b8af0
-                input,
8b8af0
-                output,
8b8af0
-                inputlen);
8b8af0
-    
8b8af0
-    /* encrypt the HMAC part */
8b8af0
-    rc4_encrypt((rc4_context_t *) text->cipher_enc_context, 
8b8af0
-                (const char *) digest, 
8b8af0
-		(output)+inputlen, 10);
8b8af0
-    
8b8af0
-    return SASL_OK;
8b8af0
-}
8b8af0
-#endif /* HAVE_OPENSSL */
8b8af0
 #endif /* WITH_RC4 */
8b8af0
 
8b8af0
 struct digest_cipher available_ciphers[] =
8b8af0
 {
8b8af0
 #ifdef WITH_RC4
8b8af0
-    { "rc4-40", 40, 5, 0x01, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
8b8af0
-    { "rc4-56", 56, 7, 0x02, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
8b8af0
     { "rc4", 128, 16, 0x04, &enc_rc4, &dec_rc4, &init_rc4, &free_rc4 },
8b8af0
 #endif
8b8af0
 #ifdef WITH_DES
8b8af0
@@ -2815,6 +2729,7 @@
8b8af0
 	}
8b8af0
 	
8b8af0
 	if (cptr->name) {
8b8af0
+	    text->cipher_name = cptr->name;
8b8af0
 	    text->cipher_enc = cptr->cipher_enc;
8b8af0
 	    text->cipher_dec = cptr->cipher_dec;
8b8af0
 	    text->cipher_init = cptr->cipher_init;
8b8af0
@@ -2958,7 +2873,10 @@
8b8af0
 	if (text->cipher_init) {
8b8af0
 	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
8b8af0
 		sparams->utils->seterror(sparams->utils->conn, 0,
8b8af0
-					 "couldn't init cipher");
8b8af0
+					 "couldn't init cipher '%s'",
8b8af0
+                                         text->cipher_name);
8b8af0
+                result = SASL_FAIL;
8b8af0
+                goto FreeAllMem;
8b8af0
 	    }
8b8af0
 	}
8b8af0
     }
8b8af0
@@ -3509,6 +3427,7 @@
8b8af0
 	oparams->mech_ssf = ctext->cipher->ssf;
8b8af0
 
8b8af0
 	nbits = ctext->cipher->n;
8b8af0
+	text->cipher_name = ctext->cipher->name;
8b8af0
 	text->cipher_enc = ctext->cipher->cipher_enc;
8b8af0
 	text->cipher_dec = ctext->cipher->cipher_dec;
8b8af0
 	text->cipher_free = ctext->cipher->cipher_free;
8b8af0
@@ -3733,7 +3652,13 @@
8b8af0
 	
8b8af0
 	/* initialize cipher if need be */
8b8af0
 	if (text->cipher_init) {
8b8af0
-	    text->cipher_init(text, enckey, deckey);
8b8af0
+	    if (text->cipher_init(text, enckey, deckey) != SASL_OK) {
8b8af0
+	        params->utils->seterror(params->utils->conn, 0,
8b8af0
+		         "internal error: failed to init cipher '%s'",
8b8af0
+                         text->cipher_name);
8b8af0
+                result = SASL_FAIL;
8b8af0
+                goto FreeAllocatedMem;
8b8af0
+            }
8b8af0
 	}
8b8af0
     }
8b8af0