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