Simo Sorce 9ce724b
From 8aa9ae816ddf66921b4a8a0f422517e6f2e55ac6 Mon Sep 17 00:00:00 2001
Simo Sorce 9ce724b
From: Simo Sorce <simo@redhat.com>
Simo Sorce 9ce724b
Date: Wed, 27 Mar 2019 14:29:08 -0400
Simo Sorce 9ce724b
Subject: [PATCH] Use Openssl RC4 when available
Simo Sorce 9ce724b
Simo Sorce 9ce724b
Signed-off-by: Simo Sorce <simo@redhat.com>
Simo Sorce 9ce724b
---
Simo Sorce 9ce724b
 configure.ac        |   5 +--
Simo Sorce 9ce724b
 plugins/digestmd5.c | 107 +++++++++++++++++++++++++++++++++++++++++++-
Simo Sorce 9ce724b
 2 files changed, 108 insertions(+), 4 deletions(-)
Simo Sorce 9ce724b
Simo Sorce 9ce724b
diff --git a/configure.ac b/configure.ac
Simo Sorce 9ce724b
index 388f5d02..cfdee4a2 100644
Simo Sorce 9ce724b
--- a/configure.ac
Simo Sorce 9ce724b
+++ b/configure.ac
Simo Sorce 9ce724b
@@ -1103,13 +1103,12 @@ AC_ARG_WITH(configdir, [   --with-configdir=DIR    set the directory where confi
Simo Sorce 9ce724b
   configdir='${plugindir}:${sysconfdir}/sasl2')
Simo Sorce 9ce724b
 AC_SUBST(configdir)
Simo Sorce 9ce724b
 
Simo Sorce 9ce724b
-dnl look for rc4 libraries. we accept the CMU one or one from openSSL
Simo Sorce 9ce724b
-AC_ARG_WITH(rc4, [  --with-rc4              use internal rc4 routines [[yes]] ],
Simo Sorce 9ce724b
+AC_ARG_WITH(rc4, [  --with-rc4              use rc4 routines [[yes]] ],
Simo Sorce 9ce724b
 	with_rc4=$withval,
Simo Sorce 9ce724b
 	with_rc4=yes)
Simo Sorce 9ce724b
 
Simo Sorce 9ce724b
 if test "$with_rc4" != no; then
Simo Sorce 9ce724b
-    AC_DEFINE(WITH_RC4,[],[Use internal RC4 implementation?])
Simo Sorce 9ce724b
+    AC_DEFINE(WITH_RC4,[],[Use RC4])
Simo Sorce 9ce724b
 fi
Simo Sorce 9ce724b
 
Simo Sorce 9ce724b
 building_for_macosx=no
Simo Sorce 9ce724b
diff --git a/plugins/digestmd5.c b/plugins/digestmd5.c
Simo Sorce 9ce724b
index df35093d..c6b54317 100644
Simo Sorce 9ce724b
--- a/plugins/digestmd5.c
Simo Sorce 9ce724b
+++ b/plugins/digestmd5.c
Simo Sorce 9ce724b
@@ -1117,6 +1117,111 @@ static void free_des(context_t *text)
Simo Sorce 9ce724b
 #endif /* WITH_DES */
Simo Sorce 9ce724b
 
Simo Sorce 9ce724b
 #ifdef WITH_RC4
Simo Sorce 9ce724b
+#ifdef HAVE_OPENSSL
Simo Sorce 9ce724b
+#include <openssl/evp.h>
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+static void free_rc4(context_t *text)
Simo Sorce 9ce724b
+{
Simo Sorce 9ce724b
+    if (text->cipher_enc_context) {
Simo Sorce 9ce724b
+        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_enc_context);
Simo Sorce 9ce724b
+        text->cipher_enc_context = NULL;
Simo Sorce 9ce724b
+    }
Simo Sorce 9ce724b
+    if (text->cipher_dec_context) {
Simo Sorce 9ce724b
+        EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *)text->cipher_dec_context);
Simo Sorce 9ce724b
+        text->cipher_dec_context = NULL;
Simo Sorce 9ce724b
+    }
Simo Sorce 9ce724b
+}
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+static int init_rc4(context_t *text,
Simo Sorce 9ce724b
+		    unsigned char enckey[16],
Simo Sorce 9ce724b
+		    unsigned char deckey[16])
Simo Sorce 9ce724b
+{
Simo Sorce 9ce724b
+    EVP_CIPHER_CTX *ctx;
Simo Sorce 9ce724b
+    int rc;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    ctx = EVP_CIPHER_CTX_new();
Simo Sorce 9ce724b
+    if (ctx == NULL) return SASL_NOMEM;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    rc = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, enckey, NULL);
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    text->cipher_enc_context = (void *)ctx;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    ctx = EVP_CIPHER_CTX_new();
Simo Sorce 9ce724b
+    if (ctx == NULL) return SASL_NOMEM;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    rc = EVP_DecryptInit_ex(ctx, EVP_rc4(), NULL, deckey, NULL);
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    text->cipher_dec_context = (void *)ctx;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    return SASL_OK;
Simo Sorce 9ce724b
+}
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+static int dec_rc4(context_t *text,
Simo Sorce 9ce724b
+		   const char *input,
Simo Sorce 9ce724b
+		   unsigned inputlen,
Simo Sorce 9ce724b
+		   unsigned char digest[16] __attribute__((unused)),
Simo Sorce 9ce724b
+		   char *output,
Simo Sorce 9ce724b
+		   unsigned *outputlen)
Simo Sorce 9ce724b
+{
Simo Sorce 9ce724b
+    int len;
Simo Sorce 9ce724b
+    int rc;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    /* decrypt the text part & HMAC */
Simo Sorce 9ce724b
+    rc = EVP_DecryptUpdate((EVP_CIPHER_CTX *)text->cipher_dec_context,
Simo Sorce 9ce724b
+                           (unsigned char *)output, &len,
Simo Sorce 9ce724b
+                           (const unsigned char *)input, inputlen);
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    *outputlen = len;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    rc = EVP_DecryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_dec_context,
Simo Sorce 9ce724b
+                             (unsigned char *)output + len, &len;;
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    *outputlen += len;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    /* subtract the HMAC to get the text length */
Simo Sorce 9ce724b
+    *outputlen -= 10;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    return SASL_OK;
Simo Sorce 9ce724b
+}
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+static int enc_rc4(context_t *text,
Simo Sorce 9ce724b
+		   const char *input,
Simo Sorce 9ce724b
+		   unsigned inputlen,
Simo Sorce 9ce724b
+		   unsigned char digest[16],
Simo Sorce 9ce724b
+		   char *output,
Simo Sorce 9ce724b
+		   unsigned *outputlen)
Simo Sorce 9ce724b
+{
Simo Sorce 9ce724b
+    int len;
Simo Sorce 9ce724b
+    int rc;
Simo Sorce 9ce724b
+    /* encrypt the text part */
Simo Sorce 9ce724b
+    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
Simo Sorce 9ce724b
+                           (unsigned char *)output, &len,
Simo Sorce 9ce724b
+                           (const unsigned char *)input, inputlen);
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    *outputlen = len;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    /* encrypt the `MAC part */
Simo Sorce 9ce724b
+    rc = EVP_EncryptUpdate((EVP_CIPHER_CTX *)text->cipher_enc_context,
Simo Sorce 9ce724b
+                           (unsigned char *)output + *outputlen, &len,
Simo Sorce 9ce724b
+                           digest, 10);
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    *outputlen += len;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    rc = EVP_EncryptFinal_ex((EVP_CIPHER_CTX *)text->cipher_enc_context,
Simo Sorce 9ce724b
+                             (unsigned char *)output + *outputlen, &len;;
Simo Sorce 9ce724b
+    if (rc != 1) return SASL_FAIL;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    *outputlen += len;
Simo Sorce 9ce724b
+
Simo Sorce 9ce724b
+    return SASL_OK;
Simo Sorce 9ce724b
+}
Simo Sorce 9ce724b
+#else
Simo Sorce 9ce724b
 /* quick generic implementation of RC4 */
Simo Sorce 9ce724b
 struct rc4_context_s {
Simo Sorce 9ce724b
     unsigned char sbox[256];
Simo Sorce 9ce724b
@@ -1296,7 +1401,7 @@ static int enc_rc4(context_t *text,
Simo Sorce 9ce724b
     
Simo Sorce 9ce724b
     return SASL_OK;
Simo Sorce 9ce724b
 }
Simo Sorce 9ce724b
-
Simo Sorce 9ce724b
+#endif /* HAVE_OPENSSL */
Simo Sorce 9ce724b
 #endif /* WITH_RC4 */
Simo Sorce 9ce724b
 
Simo Sorce 9ce724b
 struct digest_cipher available_ciphers[] =