]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Allow local md5 functions to be selected at runtime depending on OpenSSL's FIPS setting
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 8 Jan 2019 02:53:15 +0000 (10:53 +0800)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 8 Jan 2019 04:03:19 +0000 (12:03 +0800)
src/lib/util/hmac_md5.c
src/lib/util/md5.c
src/lib/util/md5.h
src/modules/rlm_cram/rlm_cram.c
src/modules/rlm_pap/rlm_pap.c
src/protocols/radius/base.c
src/protocols/radius/decode.c
src/protocols/radius/encode.c
src/tests/util/radius1_test.c
src/tests/util/radius_schedule_test.c

index d8a46eed10e370d49b87cbb2c4b7b3c7f52b1ccf..24bf1cc89e69328f3264166e2871484dbfc59731 100644 (file)
@@ -89,19 +89,19 @@ void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t in
 void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen,
                 uint8_t const *key, size_t key_len)
 {
-       FR_MD5_CTX ctx;
-       uint8_t k_ipad[65];    /* inner padding - key XORd with ipad */
-       uint8_t k_opad[65];    /* outer padding - key XORd with opad */
-       uint8_t tk[16];
+       fr_md5_ctx_t    *ctx;
+       uint8_t         k_ipad[65];    /* inner padding - key XORd with ipad */
+       uint8_t         k_opad[65];    /* outer padding - key XORd with opad */
+       uint8_t         tk[16];
        int i;
 
+       ctx = fr_md5_ctx_alloc(true);
+
        /* if key is longer than 64 bytes reset it to key=MD5(key) */
        if (key_len > 64) {
-               FR_MD5_CTX tctx;
-
-               fr_md5_init(&tctx);
-               fr_md5_update(&tctx, key, key_len);
-               fr_md5_final(tk, &tctx);
+               fr_md5_update(ctx, key, key_len);
+               fr_md5_final(tk, ctx);
+               fr_md5_ctx_reset(ctx);
 
                key = tk;
                key_len = 16;
@@ -120,10 +120,10 @@ void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t in
         */
 
        /* start out by storing key in pads */
-       memset( k_ipad, 0, sizeof(k_ipad));
-       memset( k_opad, 0, sizeof(k_opad));
-       memcpy( k_ipad, key, key_len);
-       memcpy( k_opad, key, key_len);
+       memset(k_ipad, 0, sizeof(k_ipad));
+       memset(k_opad, 0, sizeof(k_opad));
+       memcpy(k_ipad, key, key_len);
+       memcpy(k_opad, key, key_len);
 
        /* XOR key with ipad and opad values */
        for (i = 0; i < 64; i++) {
@@ -133,20 +133,20 @@ void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *in, size_t in
        /*
         * perform inner MD5
         */
-       fr_md5_init(&ctx);                 /* init ctx for 1st
-                                             * pass */
-       fr_md5_update(&ctx, k_ipad, 64);      /* start with inner pad */
-       fr_md5_update(&ctx, in, inlen); /* then in of datagram */
-       fr_md5_final(digest, &ctx);       /* finish up 1st pass */
+       fr_md5_update(ctx, k_ipad, 64);         /* start with inner pad */
+       fr_md5_update(ctx, in, inlen);          /* then in of datagram */
+       fr_md5_final(digest, ctx);              /* finish up 1st pass */
+
+
        /*
         * perform outer MD5
         */
-       fr_md5_init(&ctx);                 /* init ctx for 2nd
-                                             * pass */
-       fr_md5_update(&ctx, k_opad, 64);     /* start with outer pad */
-       fr_md5_update(&ctx, digest, 16);     /* then results of 1st
-                                             * hash */
-       fr_md5_final(digest, &ctx);       /* finish up 2nd pass */
+       fr_md5_ctx_reset(ctx);
+       fr_md5_update(ctx, k_opad, 64);         /* start with outer pad */
+       fr_md5_update(ctx, digest, 16);         /* then results of 1st hash */
+       fr_md5_final(digest, ctx);              /* finish up 2nd pass */
+
+       fr_md5_ctx_free(&ctx);
 }
 #endif /* HAVE_OPENSSL_EVP_H */
 
index 8b50ccc7d7537cb2dba39a439a5fa33d70887a2f..007299800a9c63dca3fb73afec4e0c6a63085536 100644 (file)
  */
 RCSID("$Id$")
 
+#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/strerror.h>
+#include <freeradius-devel/util/talloc.h>
+#include <freeradius-devel/util/thread_local.h>
+#include <talloc.h>
+
 /*
  *  FORCE MD5 TO USE OUR MD5 HEADER FILE!
  *  If we don't do this, it might pick up the systems broken MD5.
  */
 #include "md5.h"
 
-/** Calculate the MD5 hash of the contents of a buffer
+fr_thread_local_setup(fr_md5_ctx_t *, md5_ctx)
+
+/*
+ *     If we have OpenSSL's EVP API available, then build wrapper functions.
  *
- * @param[out] out Where to write the MD5 digest. Must be a minimum of MD5_DIGEST_LENGTH.
- * @param[in] in Data to hash.
- * @param[in] inlen Length of the data.
+ *     We always need to build the local MD5 functions as OpenSSL could
+ *     be operating in FIPS mode where MD5 digest functions are unavailable.
  */
-void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
+#ifdef HAVE_OPENSSL_EVP_H
+#  include <openssl/evp.h>
+#  include <openssl/crypto.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#  define EVP_MD_CTX_new EVP_MD_CTX_create
+#  define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#  define EVP_MD_CTX_reset EVP_MD_CTX_cleanup
+#endif
+
+static int have_openssl_md5 = -1;
+
+static void _md5_ctx_openssl_free_on_exit(void *arg)
+{
+       EVP_MD_CTX_free(arg);
+}
+
+/** @copydoc fr_md5_ctx_reset
+ *
+ */
+static void fr_md5_openssl_ctx_reset(fr_md5_ctx_t *ctx)
 {
-       FR_MD5_CTX ctx;
+       EVP_MD_CTX *md_ctx = ctx;
 
-       fr_md5_init(&ctx);
-       fr_md5_update(&ctx, in, inlen);
-       fr_md5_final(out, &ctx);
+       EVP_MD_CTX_reset(md_ctx);
+       EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL);
 }
 
-#ifndef HAVE_OPENSSL_EVP_H
+/** @copydoc fr_md5_ctx_copy
+ *
+ */
+static void fr_md5_openssl_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
+{
+       EVP_MD_CTX_copy_ex(dst, src);
+}
+
+/** @copydoc fr_md5_ctx_alloc
+ *
+ */
+static fr_md5_ctx_t *fr_md5_openssl_ctx_alloc(bool thread_local)
+{
+       EVP_MD_CTX *md_ctx;
+
+       /*
+        *      Use the thread local ctx to avoid heap allocations.
+        */
+       if (thread_local) {
+               if (unlikely(!md5_ctx)) {
+                       md_ctx = EVP_MD_CTX_new();
+                       if (unlikely(!md_ctx)) {
+                       oom:
+                               fr_strerror_printf("Out of memory");
+                               return NULL;
+                       }
+                       fr_thread_local_set_destructor(md5_ctx, _md5_ctx_openssl_free_on_exit, md_ctx);
+                       EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL);
+               } else {
+                       md_ctx = md5_ctx;
+               }
+       /*
+        *      If the MD5 ctx might be used across a yield point
+        *      shared should be set to false, and new contexts
+        *      should be allocated.
+        */
+       } else {
+               md_ctx = EVP_MD_CTX_new();
+               if (unlikely(!md_ctx)) goto oom;
+               EVP_DigestInit_ex(md_ctx, EVP_md5(), NULL);
+       }
+
+       return md_ctx;
+}
+
+/** @copydoc fr_md5_ctx_free
+ *
+ */
+static void fr_md5_openssl_ctx_free(fr_md5_ctx_t **ctx)
+{
+       if (md5_ctx && (md5_ctx == *ctx)) {
+               fr_md5_openssl_ctx_reset(*ctx);
+               *ctx = NULL;
+               return;
+       }
+
+       EVP_MD_CTX_free(*ctx);
+       *ctx = NULL;
+}
+
+/** @copydoc fr_md5_update
+ *
+ */
+static void fr_md5_openssl_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
+{
+       EVP_DigestUpdate(ctx, in, inlen);
+}
+
+/** @copydoc fr_md5_final
+ *
+ */
+static void fr_md5_openssl_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx)
+{
+       unsigned int len;
+
+       EVP_DigestFinal(ctx, out, &len);
+
+       if (!fr_cond_assert(len == MD5_DIGEST_LENGTH)) return;
+}
+#endif
+
+#  define MD5_BLOCK_LENGTH 64
+typedef struct {
+       uint32_t state[4];                      //!< State.
+       uint32_t count[2];                      //!< Number of bits, mod 2^64.
+       uint8_t buffer[MD5_BLOCK_LENGTH];       //!< Input buffer.
+} fr_md5_ctx_local_t;
+
+
 /*
  * This code implements the MD5 message-digest algorithm.
  * The algorithm is due to Ron Rivest. This code was
@@ -68,96 +183,6 @@ static const uint8_t PADDING[MD5_BLOCK_LENGTH] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-/** Initialise a new MD5 context
- *
- * Set bit count to 0 and buffer to mysterious initialization constants.
- *
- * @param[out] ctx to initialise.
- */
-void fr_md5_init(FR_MD5_CTX *ctx)
-{
-       ctx->count[0] = 0;
-       ctx->count[1] = 0;
-       ctx->state[0] = 0x67452301;
-       ctx->state[1] = 0xefcdab89;
-       ctx->state[2] = 0x98badcfe;
-       ctx->state[3] = 0x10325476;
-}
-
-/** Feed additional data into the MD5 hashing function
- *
- * @param[in,out] ctx to update.
- * @param[in] in Data to hash.
- * @param[in] inlen Length of the data.
- */
-void fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen)
-{
-       size_t have, need;
-
-       /* Check how many bytes we already have and how many more we need. */
-       have = (size_t)((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
-       need = MD5_BLOCK_LENGTH - have;
-
-       /* Update bitcount */
-/*     ctx->count += (uint64_t)inlen << 3;*/
-       if ((ctx->count[0] += ((uint32_t)inlen << 3)) < (uint32_t)inlen) {
-       /* Overflowed ctx->count[0] */
-               ctx->count[1]++;
-       }
-       ctx->count[1] += ((uint32_t)inlen >> 29);
-
-       if (inlen >= need) {
-               if (have != 0) {
-                       memcpy(ctx->buffer + have, in, need);
-                       fr_md5_transform(ctx->state, ctx->buffer);
-                       in += need;
-                       inlen -= need;
-                       have = 0;
-               }
-
-               /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
-               while (inlen >= MD5_BLOCK_LENGTH) {
-                       fr_md5_transform(ctx->state, in);
-                       in += MD5_BLOCK_LENGTH;
-                       inlen -= MD5_BLOCK_LENGTH;
-               }
-       }
-
-       /* Handle any remaining bytes of data. */
-       if (inlen != 0) memcpy(ctx->buffer + have, in, inlen);
-}
-
-/** Finalise the MD5 context and write out the hash
- *
- * Final wrapup - pad to 64-byte boundary with the bit pattern 1 0*
- * (64-bit count of bits processed, MSB-first).
- *
- * @param[out] out Where to write the MD5 digest. Minimum length of MD5_DIGEST_LENGTH.
- * @param[in,out] ctx to finalise.
- */
-void fr_md5_final(uint8_t out[static MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx)
-{
-       uint8_t count[8];
-       size_t padlen;
-       int i;
-
-       /* Convert count to 8 bytes in little endian order. */
-       PUT_64BIT_LE(count, ctx->count);
-
-       /* Pad out to 56 mod 64. */
-       padlen = MD5_BLOCK_LENGTH -
-           ((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
-       if (padlen < 1 + 8)
-               padlen += MD5_BLOCK_LENGTH;
-       fr_md5_update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
-       fr_md5_update(ctx, count, 8);
-
-       if (out != NULL) {
-               for (i = 0; i < 4; i++)
-                       PUT_32BIT_LE(out + i * 4, ctx->state[i]);
-       }
-       memset(ctx, 0, sizeof(*ctx));   /* in case it's sensitive */
-}
 
 /* The four core functions - F1 is optimized somewhat */
 #define F1(x, y, z) (z ^ (x & (y ^ z)))
@@ -177,7 +202,7 @@ void fr_md5_final(uint8_t out[static MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx)
  * @param[in] state 16 bytes of data to feed into the hashing function.
  * @param[in,out] block MD5 digest block to update.
  */
-void fr_md5_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH])
+static void fr_md5_local_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH])
 {
        uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
 
@@ -267,4 +292,206 @@ void fr_md5_transform(uint32_t state[static 4], uint8_t const block[static MD5_B
        state[2] += c;
        state[3] += d;
 }
+
+/** @copydoc fr_md5_ctx_reset
+ *
+ */
+static void fr_md5_local_ctx_reset(fr_md5_ctx_t *ctx)
+{
+       fr_md5_ctx_local_t      *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
+
+       ctx_local->count[0] = 0;
+       ctx_local->count[1] = 0;
+       ctx_local->state[0] = 0x67452301;
+       ctx_local->state[1] = 0xefcdab89;
+       ctx_local->state[2] = 0x98badcfe;
+       ctx_local->state[3] = 0x10325476;
+}
+
+/** @copydoc fr_md5_ctx_copy
+ *
+ */
+static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src)
+{
+       fr_md5_ctx_local_t const *ctx_local_src = talloc_get_type_abort_const(src, fr_md5_ctx_local_t);
+       fr_md5_ctx_local_t *ctx_local_dst = talloc_get_type_abort(dst, fr_md5_ctx_local_t);
+
+       memcpy(ctx_local_dst, ctx_local_src, sizeof(*ctx_local_dst));
+}
+
+static void _md5_ctx_local_free_on_exit(void *arg)
+{
+       talloc_free(arg);
+}
+
+/** @copydoc fr_md5_ctx_alloc
+ *
+ */
+static fr_md5_ctx_t *fr_md5_local_ctx_alloc(bool thread_local)
+{
+       fr_md5_ctx_local_t *ctx_local;
+
+#ifdef HAVE_OPENSSL_EVP_H
+       if (unlikely(have_openssl_md5 == -1)) {
+               /*
+                *      If we're not in FIPS mode, then swap out the
+                *      md5 functions, and call the OpenSSL init
+                *      function.
+                */
+               if (FIPS_mode() == 0) {
+                       have_openssl_md5 = 1;
+
+                       /*
+                        *      Swap out the functions pointers
+                        *      for the OpenSSL versions.
+                        */
+                       fr_md5_ctx_reset = fr_md5_openssl_ctx_reset;
+                       fr_md5_ctx_copy = fr_md5_openssl_ctx_copy;
+                       fr_md5_ctx_alloc = fr_md5_openssl_ctx_alloc;
+                       fr_md5_ctx_free = fr_md5_openssl_ctx_free;
+                       fr_md5_update = fr_md5_openssl_update;
+                       fr_md5_final = fr_md5_openssl_final;
+
+                       return fr_md5_ctx_alloc(thread_local);
+               }
+
+               have_openssl_md5 = 0;
+       }
 #endif
+
+       /*
+        *      Use the thread local ctx to avoid heap allocations.
+        */
+       if (thread_local) {
+               if (unlikely(!md5_ctx)) {
+                       ctx_local = talloc(NULL, fr_md5_ctx_local_t);
+                       if (unlikely(!ctx_local)) return NULL;
+                       fr_md5_local_ctx_reset(ctx_local);
+                       fr_thread_local_set_destructor(md5_ctx, _md5_ctx_local_free_on_exit, ctx_local);
+               } else {
+                       ctx_local = md5_ctx;
+               }
+       /*
+        *      If the MD5 ctx might be used across a yield point
+        *      shared should be set to false, and new contexts
+        *      should be allocated.
+        */
+       } else {
+               ctx_local = talloc(NULL, fr_md5_ctx_local_t);
+               if (unlikely(!ctx_local)) return NULL;
+               fr_md5_local_ctx_reset(ctx_local);
+       }
+
+       return ctx_local;
+}
+
+/** @copydoc fr_md5_ctx_free
+ *
+ */
+static void fr_md5_local_ctx_free(fr_md5_ctx_t **ctx)
+{
+       if (md5_ctx && (md5_ctx == *ctx)) {
+               fr_md5_local_ctx_reset(*ctx);
+               *ctx = NULL;
+               return; /* Don't free the thread_local ctx */
+       }
+
+       talloc_free(*ctx);
+       *ctx = NULL;
+}
+
+/** @copydoc fr_md5_update
+ *
+ */
+static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen)
+{
+       fr_md5_ctx_local_t      *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
+
+       size_t have, need;
+
+       /* Check how many bytes we already have and how many more we need. */
+       have = (size_t)((ctx_local->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
+       need = MD5_BLOCK_LENGTH - have;
+
+       /* Update bitcount */
+/*     ctx_local->count += (uint64_t)inlen << 3;*/
+       if ((ctx_local->count[0] += ((uint32_t)inlen << 3)) < (uint32_t)inlen) {
+       /* Overflowed ctx_local->count[0] */
+               ctx_local->count[1]++;
+       }
+       ctx_local->count[1] += ((uint32_t)inlen >> 29);
+
+       if (inlen >= need) {
+               if (have != 0) {
+                       memcpy(ctx_local->buffer + have, in, need);
+                       fr_md5_local_transform(ctx_local->state, ctx_local->buffer);
+                       in += need;
+                       inlen -= need;
+                       have = 0;
+               }
+
+               /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
+               while (inlen >= MD5_BLOCK_LENGTH) {
+                       fr_md5_local_transform(ctx_local->state, in);
+                       in += MD5_BLOCK_LENGTH;
+                       inlen -= MD5_BLOCK_LENGTH;
+               }
+       }
+
+       /* Handle any remaining bytes of data. */
+       if (inlen != 0) memcpy(ctx_local->buffer + have, in, inlen);
+}
+
+/** @copydoc fr_md5_final
+ *
+ */
+static void fr_md5_local_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx)
+{
+       fr_md5_ctx_local_t      *ctx_local = talloc_get_type_abort(ctx, fr_md5_ctx_local_t);
+       uint8_t                 count[8];
+       size_t                  padlen;
+       int                     i;
+
+       /* Convert count to 8 bytes in little endian order. */
+       PUT_64BIT_LE(count, ctx_local->count);
+
+       /* Pad out to 56 mod 64. */
+       padlen = MD5_BLOCK_LENGTH -
+           ((ctx_local->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
+       if (padlen < 1 + 8)
+               padlen += MD5_BLOCK_LENGTH;
+       fr_md5_update(ctx_local, PADDING, padlen - 8); /* padlen - 8 <= 64 */
+       fr_md5_update(ctx_local, count, 8);
+
+       if (out != NULL) {
+               for (i = 0; i < 4; i++)
+                       PUT_32BIT_LE(out + i * 4, ctx_local->state[i]);
+       }
+       memset(ctx_local, 0, sizeof(*ctx_local));       /* in case it's sensitive */
+}
+
+/*
+ *     Digest function pointers
+ */
+fr_md5_ctx_reset_t fr_md5_ctx_reset = fr_md5_local_ctx_reset;
+fr_md5_ctx_copy_t fr_md5_ctx_copy = fr_md5_local_ctx_copy;
+fr_md5_ctx_alloc_t fr_md5_ctx_alloc = fr_md5_local_ctx_alloc;
+fr_md5_ctx_free_t fr_md5_ctx_free = fr_md5_local_ctx_free;
+fr_md5_update_t fr_md5_update = fr_md5_local_update;
+fr_md5_final_t fr_md5_final = fr_md5_local_final;
+
+/** Calculate the MD5 hash of the contents of a buffer
+ *
+ * @param[out] out Where to write the MD5 digest. Must be a minimum of MD5_DIGEST_LENGTH.
+ * @param[in] in Data to hash.
+ * @param[in] inlen Length of the data.
+ */
+void fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen)
+{
+       fr_md5_ctx_t *ctx;
+
+       ctx = fr_md5_ctx_alloc(true);
+       fr_md5_update(ctx, in, inlen);
+       fr_md5_final(out, ctx);
+       fr_md5_ctx_free(&ctx);
+}
index 62ba1340a25ccab87f28b8657bc1bfddc638b8d0..46bdfeee8565bbdeb2f6f85671c9c97cc00248bc 100644 (file)
@@ -4,6 +4,7 @@
  * @note license is LGPL, but largely derived from a public domain source.
  *
  * @file src/lib/util/md5.h
+ * @brief Structures and declarations for md5.
  */
 RCSIDH(md5_h, "$Id$")
 
@@ -14,72 +15,78 @@ extern "C" {
 #include <freeradius-devel/build.h>
 #include <freeradius-devel/missing.h>
 
-#ifdef HAVE_INTTYPES_H
-#  include <inttypes.h>
-#endif
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
 
-#ifdef HAVE_SYS_TYPES_H
-#  include <sys/types.h>
+#ifndef MD5_DIGEST_LENGTH
+#  define MD5_DIGEST_LENGTH 16
 #endif
 
-#ifdef HAVE_STDINT_H
-#  include <stdint.h>
-#endif
+typedef void fr_md5_ctx_t;
 
-#  include <string.h>
+/* md5.c */
 
-#ifdef HAVE_OPENSSL_EVP_H
-#  include <openssl/evp.h>
-#endif
+/** Reset the ctx to allow reuse
+ *
+ * @param[in] ctx      To reuse.
+ */
+typedef                void (*fr_md5_ctx_reset_t)(fr_md5_ctx_t *ctx);
+extern         fr_md5_ctx_reset_t      fr_md5_ctx_reset;
 
-#ifndef MD5_DIGEST_LENGTH
-#  define MD5_DIGEST_LENGTH 16
-#endif
+/** Copy the contents of a ctx
+ *
+ * @param[in] dst      Where to copy the context to.
+ * @param[in] src      Where to copy the context from.
+ */
+typedef                void (*fr_md5_ctx_copy_t)(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src);
+extern         fr_md5_ctx_copy_t       fr_md5_ctx_copy;
 
-#ifndef HAVE_OPENSSL_EVP_H
-/*
- * The MD5 code used here and in md5.c was originally retrieved from:
- *   http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.h?rev=1.1
+/** Allocation function for MD5 digest context
  *
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest.  This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
+ * @param[in] shared   Whether we allocate a new context or use the thread local context.
+ * @return
+ *     - An MD5 ctx.
+ *     - NULL if out of memory.
+ */
+typedef                fr_md5_ctx_t *(*fr_md5_ctx_alloc_t)(bool shared);
+extern         fr_md5_ctx_alloc_t      fr_md5_ctx_alloc;
+
+/** Free function for MD5 digest ctx
  *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
+ * @param[in] ctx      MD5 ctx to free.  If the shared ctx is passed in
+ *                     then the ctx is reset but not freed.
  */
-#  define MD5_BLOCK_LENGTH 64
-typedef struct {
-       uint32_t state[4];                      //!< State.
-       uint32_t count[2];                      //!< Number of bits, mod 2^64.
-       uint8_t buffer[MD5_BLOCK_LENGTH];       //!< Input buffer.
-} FR_MD5_CTX;
+typedef                void (*fr_md5_ctx_free_t)(fr_md5_ctx_t **ctx);
+extern         fr_md5_ctx_free_t       fr_md5_ctx_free;
 
-void   fr_md5_init(FR_MD5_CTX *ctx);
-void   fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen);
-void   fr_md5_final(uint8_t out[static MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx);
-void   fr_md5_transform(uint32_t state[static 4], uint8_t const block[static MD5_BLOCK_LENGTH]);
-#  define fr_md5_copy(_out, _in)       memcpy(_out, _in, sizeof(*_out))
-#else  /* HAVE_OPENSSL_EVP_H */
-USES_APPLE_DEPRECATED_API
-#include <openssl/md5.h>
-#  define FR_MD5_CTX                   MD5_CTX
-#  define fr_md5_init                  MD5_Init
-#  define fr_md5_update                        MD5_Update
-#  define fr_md5_final                 MD5_Final
-#  define fr_md5_transform             MD5_Transform
-#  define fr_md5_copy(_out, _in)       memcpy(_out, _in, sizeof(*_out))
-#endif
+/** Ingest plaintext into the digest
+ *
+ * @param[in] ctx      To ingest data into.
+ * @param[in] in       Data to ingest.
+ * @param[in] inlen    Length of data to ingest.
+ */
+typedef                void (*fr_md5_update_t)(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen);
+extern         fr_md5_update_t         fr_md5_update;
 
-/* hmac.c */
-void   fr_hmac_md5(uint8_t digest[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen,
-                   uint8_t const *key, size_t key_len);
-/* md5.c */
-void   fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen);
+/** Finalise the ctx, producing the digest
+ *
+ * @param[out] out     The MD5 digest.
+ * @param[in] ctx      To finalise.
+ */
+typedef                void (*fr_md5_final_t)(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx);
+extern         fr_md5_final_t          fr_md5_final;
+
+/** Perform a single digest operation on a single input buffer
+ *
+ */
+void           fr_md5_calc(uint8_t out[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen);
 
+/* hmac.c */
+void           fr_hmac_md5(uint8_t digest[static MD5_DIGEST_LENGTH], uint8_t const *in, size_t inlen,
+                           uint8_t const *key, size_t key_len);
 #ifdef __cplusplus
 }
 #endif
index a3c5292cb35c4b842ad9090b90a81175995a26da..e71bb0fca83024c93a98fa55379d9f6d146adfae 100644 (file)
@@ -74,33 +74,37 @@ fr_dict_attr_autoload_t rlm_cram_dict_attr[] = {
 static void calc_apop_digest(uint8_t *buffer, uint8_t const *challenge,
                             size_t challen, char const *password)
 {
-       FR_MD5_CTX context;
+       fr_md5_ctx_t *md5_ctx;
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, challenge, challen);
-       fr_md5_update(&context, (uint8_t const *) password, strlen(password));
-       fr_md5_final(buffer, &context);
+       md5_ctx = fr_md5_ctx_alloc(true);
+       fr_md5_update(md5_ctx, challenge, challen);
+       fr_md5_update(md5_ctx, (uint8_t const *) password, strlen(password));
+       fr_md5_final(buffer, md5_ctx);
+       fr_md5_ctx_free(&md5_ctx);
 }
 
-
 static void calc_md5_digest(uint8_t *buffer, uint8_t const *challenge, size_t challen, char const *password)
 {
-       uint8_t buf[1024];
-       int i;
-       FR_MD5_CTX context;
+       uint8_t         buf[1024];
+       int             i;
+       fr_md5_ctx_t    *md5_ctx;
 
        memset(buf, 0, 1024);
        memset(buf, 0x36, 64);
-       for(i=0; i<64 && password[i]; i++) buf[i]^=password[i];
-       memcpy(buf+64, challenge, challen);
-       fr_md5_init(&context);
-       fr_md5_update(&context, buf, 64+challen);
+       for (i = 0; i < 64 && password[i]; i++) buf[i] ^= password[i];
+       memcpy(buf + 64, challenge, challen);
+
+       md5_ctx = fr_md5_ctx_alloc(true);
+
+       fr_md5_update(md5_ctx, buf, 64 + challen);
        memset(buf, 0x5c, 64);
-       for(i=0; i<64 && password[i]; i++) buf[i]^=password[i];
-       fr_md5_final(buf+64,&context);
-       fr_md5_init(&context);
-       fr_md5_update(&context,buf,64+16);
-       fr_md5_final(buffer,&context);
+       for (i = 0; i < 64 && password[i]; i++) buf[i] ^= password[i];
+       fr_md5_final(buf + 64, md5_ctx);
+
+       fr_md5_ctx_reset(md5_ctx);
+       fr_md5_update(md5_ctx, buf, 64 + 16);
+       fr_md5_final(buffer, md5_ctx);
+       fr_md5_ctx_free(&md5_ctx);
 }
 
 static void calc_md4_digest(uint8_t *buffer, uint8_t const *challenge, size_t challen, char const *password)
index c5c0b33f19acecbe3a08915ad482f68cb15ba05d..67c0edaef50612aaf1be0f51cd58af387c7d8bba 100644 (file)
@@ -682,7 +682,7 @@ static rlm_rcode_t CC_HINT(nonnull) pap_auth_md5(rlm_pap_t const *inst, REQUEST
 
 static rlm_rcode_t CC_HINT(nonnull) pap_auth_smd5(rlm_pap_t const *inst, REQUEST *request, VALUE_PAIR *vp)
 {
-       FR_MD5_CTX md5_context;
+       fr_md5_ctx_t *md5_ctx;
        uint8_t digest[128];
 
        RDEBUG("Comparing with \"known-good\" SMD5-Password");
@@ -693,10 +693,11 @@ static rlm_rcode_t CC_HINT(nonnull) pap_auth_smd5(rlm_pap_t const *inst, REQUEST
                return RLM_MODULE_INVALID;
        }
 
-       fr_md5_init(&md5_context);
-       fr_md5_update(&md5_context, request->password->vp_octets, request->password->vp_length);
-       fr_md5_update(&md5_context, vp->vp_octets + MD5_DIGEST_LENGTH, vp->vp_length - MD5_DIGEST_LENGTH);
-       fr_md5_final(digest, &md5_context);
+       md5_ctx = fr_md5_ctx_alloc(true);
+       fr_md5_update(md5_ctx, request->password->vp_octets, request->password->vp_length);
+       fr_md5_update(md5_ctx, vp->vp_octets + MD5_DIGEST_LENGTH, vp->vp_length - MD5_DIGEST_LENGTH);
+       fr_md5_final(digest, md5_ctx);
+       fr_md5_ctx_free(&md5_ctx);
 
        /*
         *      Compare only the MD5 hash results, not the salt.
index 2268ab5dfa3b53950a11758bd7c22df6f853bf08..03e2c7bcd8fc2a68e8e4da844bc5148ecdaf3d47 100644 (file)
@@ -234,13 +234,14 @@ size_t fr_radius_attr_len(VALUE_PAIR const *vp)
  */
 void fr_radius_ascend_secret(uint8_t *digest, uint8_t const *vector, char const *secret, uint8_t const *value)
 {
-       FR_MD5_CTX context;
-       int          i;
+       fr_md5_ctx_t    *md5_ctx;
+       int             i;
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
-       fr_md5_update(&context, (uint8_t const *) secret, talloc_array_length(secret) - 1);
-       fr_md5_final(digest, &context);
+       md5_ctx = fr_md5_ctx_alloc(true);
+       fr_md5_update(md5_ctx, vector, AUTH_VECTOR_LEN);
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, talloc_array_length(secret) - 1);
+       fr_md5_final(digest, md5_ctx);
+       fr_md5_ctx_free(&md5_ctx);
 
        for (i = 0; i < AUTH_VECTOR_LEN; i++ ) digest[i] ^= value[i];
 }
@@ -334,7 +335,6 @@ int fr_radius_sign(uint8_t *packet, uint8_t const *original,
 {
        uint8_t         *msg, *end;
        size_t          packet_len = (packet[2] << 8) | packet[3];
-       FR_MD5_CTX      context;
 
        /*
         *      No real limit on secret length, this is just
@@ -466,10 +466,15 @@ int fr_radius_sign(uint8_t *packet, uint8_t const *original,
        /*
         *      Request / Response Authenticator = MD5(packet + secret)
         */
-       fr_md5_init(&context);
-       fr_md5_update(&context, packet, packet_len);
-       fr_md5_update(&context, secret, secret_len);
-       fr_md5_final(packet + 4, &context);
+       {
+               fr_md5_ctx_t    *md5_ctx;
+
+               md5_ctx = fr_md5_ctx_alloc(true);
+               fr_md5_update(md5_ctx, packet, packet_len);
+               fr_md5_update(md5_ctx, secret, secret_len);
+               fr_md5_final(packet + 4, md5_ctx);
+               fr_md5_ctx_free(&md5_ctx);
+       }
 
        return 0;
 }
index 14383da7d936bbb414cae5e4e12df80fa55a8fa7..9efa0657cd296c3104e8c32760656341d7ed8d74 100644 (file)
@@ -59,7 +59,7 @@ static void memcpy_bounded(void * restrict dst, const void * restrict src, size_
 ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen,
                                         char const *secret, uint8_t const *vector, bool tunnel_password_zeros)
 {
-       FR_MD5_CTX      context, old;
+       fr_md5_ctx_t    *md5_ctx, *md5_ctx_old;
        uint8_t         digest[AUTH_VECTOR_LEN];
        int             secretlen;
        size_t          i, n, encrypted_len, embedded_len;
@@ -97,17 +97,19 @@ ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen,
         */
        secretlen = talloc_array_length(secret) - 1;
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, (uint8_t const *) secret, secretlen);
-       fr_md5_copy(&old, &context); /* save intermediate work */
+       md5_ctx = fr_md5_ctx_alloc(false);
+       md5_ctx_old = fr_md5_ctx_alloc(true);
+
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, secretlen);
+       fr_md5_ctx_copy(md5_ctx_old, md5_ctx); /* save intermediate work */
 
        /*
         *      Set up the initial key:
         *
         *       b(1) = MD5(secret + vector + salt)
         */
-       fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
-       fr_md5_update(&context, passwd, 2);
+       fr_md5_update(md5_ctx, vector, AUTH_VECTOR_LEN);
+       fr_md5_update(md5_ctx, passwd, 2);
 
        embedded_len = 0;
        for (n = 0; n < encrypted_len; n += AUTH_PASS_LEN) {
@@ -124,8 +126,8 @@ ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen,
                if (n == 0) {
                        base = 1;
 
-                       fr_md5_final(digest, &context);
-                       fr_md5_copy(&context, &old);
+                       fr_md5_final(digest, md5_ctx);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
 
                        /*
                         *      A quick check: decrypt the first octet
@@ -136,18 +138,20 @@ ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen,
                        if (embedded_len > encrypted_len) {
                                fr_strerror_printf("Tunnel Password is too long for the attribute "
                                                   "(shared secret is probably incorrect!)");
+                               fr_md5_ctx_free(&md5_ctx);
+                               fr_md5_ctx_free(&md5_ctx_old);
                                return -1;
                        }
 
-                       fr_md5_update(&context, passwd + 2, block_len);
+                       fr_md5_update(md5_ctx, passwd + 2, block_len);
 
                } else {
                        base = 0;
 
-                       fr_md5_final(digest, &context);
+                       fr_md5_final(digest, md5_ctx);
 
-                       fr_md5_copy(&context, &old);
-                       fr_md5_update(&context, passwd + n + 2, block_len);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
+                       fr_md5_update(md5_ctx, passwd + n + 2, block_len);
                }
 
                for (i = base; i < block_len; i++) {
@@ -155,6 +159,9 @@ ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen,
                }
        }
 
+       fr_md5_ctx_free(&md5_ctx);
+       fr_md5_ctx_free(&md5_ctx_old);
+
        /*
         *      Check trailing bytes
         */
@@ -179,7 +186,7 @@ ssize_t fr_radius_decode_tunnel_password(uint8_t *passwd, size_t *pwlen,
  */
 ssize_t fr_radius_decode_password(char *passwd, size_t pwlen, char const *secret, uint8_t const *vector)
 {
-       FR_MD5_CTX      context, old;
+       fr_md5_ctx_t    *md5_ctx, *md5_ctx_old;
        uint8_t         digest[AUTH_VECTOR_LEN];
        int             i;
        size_t          n, secretlen;
@@ -201,34 +208,39 @@ ssize_t fr_radius_decode_password(char *passwd, size_t pwlen, char const *secret
         */
        secretlen = talloc_array_length(secret) - 1;
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, (uint8_t const *) secret, secretlen);
-       fr_md5_copy(&old, &context);    /* save intermediate work */
+       md5_ctx = fr_md5_ctx_alloc(false);
+       md5_ctx_old = fr_md5_ctx_alloc(true);
+
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, secretlen);
+       fr_md5_ctx_copy(md5_ctx_old, md5_ctx);  /* save intermediate work */
 
        /*
         *      The inverse of the code above.
         */
        for (n = 0; n < pwlen; n += AUTH_PASS_LEN) {
                if (n == 0) {
-                       fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
-                       fr_md5_final(digest, &context);
+                       fr_md5_update(md5_ctx, vector, AUTH_VECTOR_LEN);
+                       fr_md5_final(digest, md5_ctx);
 
-                       fr_md5_copy(&context, &old);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
                        if (pwlen > AUTH_PASS_LEN) {
-                               fr_md5_update(&context, (uint8_t *) passwd, AUTH_PASS_LEN);
+                               fr_md5_update(md5_ctx, (uint8_t *) passwd, AUTH_PASS_LEN);
                        }
                } else {
-                       fr_md5_final(digest, &context);
+                       fr_md5_final(digest, md5_ctx);
 
-                       fr_md5_copy(&context, &old);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
                        if (pwlen > (n + AUTH_PASS_LEN)) {
-                               fr_md5_update(&context, (uint8_t *) passwd + n, AUTH_PASS_LEN);
+                               fr_md5_update(md5_ctx, (uint8_t *) passwd + n, AUTH_PASS_LEN);
                        }
                }
 
                for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
        }
 
+       fr_md5_ctx_free(&md5_ctx);
+       fr_md5_ctx_free(&md5_ctx_old);
+
  done:
        passwd[pwlen] = '\0';
        return strlen(passwd);
index ccfc3283e3dbaa18750686b40aaccebe3d991cbf..d61061ddf086e616e3260be8b29612e848fb5969 100644 (file)
@@ -219,7 +219,7 @@ int fr_radius_encode_tunnel_password(char *passwd, size_t *pwlen, char const *se
  */
 int fr_radius_encode_password(char *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
 {
-       FR_MD5_CTX      context, old;
+       fr_md5_ctx_t    *md5_ctx, *md5_ctx_old;
        uint8_t         digest[AUTH_VECTOR_LEN];
        int             i, n, secretlen;
        int             len;
@@ -250,9 +250,11 @@ int fr_radius_encode_password(char *passwd, size_t *pwlen, char const *secret, u
         */
        secretlen = talloc_array_length(secret) - 1;
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, (uint8_t const *) secret, secretlen);
-       fr_md5_copy(&old, &context); /* save intermediate work */
+       md5_ctx = fr_md5_ctx_alloc(false);
+       md5_ctx_old = fr_md5_ctx_alloc(true);
+
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, secretlen);
+       fr_md5_ctx_copy(md5_ctx_old, md5_ctx); /* save intermediate work */
 
        /*
         *      Encrypt it in place.  Don't bother checking
@@ -260,24 +262,27 @@ int fr_radius_encode_password(char *passwd, size_t *pwlen, char const *secret, u
         */
        for (n = 0; n < len; n += AUTH_PASS_LEN) {
                if (n == 0) {
-                       fr_md5_update(&context, vector, AUTH_PASS_LEN);
-                       fr_md5_final(digest, &context);
+                       fr_md5_update(md5_ctx, vector, AUTH_PASS_LEN);
+                       fr_md5_final(digest, md5_ctx);
                } else {
-                       fr_md5_copy(&context, &old);
-                       fr_md5_update(&context, (uint8_t *) passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
-                       fr_md5_final(digest, &context);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
+                       fr_md5_update(md5_ctx, (uint8_t *) passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
+                       fr_md5_final(digest, md5_ctx);
                }
 
                for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
        }
 
+       fr_md5_ctx_free(&md5_ctx);
+       fr_md5_ctx_free(&md5_ctx_old);
+
        return 0;
 }
 
 static void encode_password(uint8_t *out, ssize_t *outlen, uint8_t const *input, size_t inlen,
                            char const *secret, uint8_t const *vector)
 {
-       FR_MD5_CTX      context, old;
+       fr_md5_ctx_t    *md5_ctx, *md5_ctx_old;
        uint8_t         digest[AUTH_VECTOR_LEN];
        uint8_t         passwd[MAX_PASS_LEN];
        size_t          i, n;
@@ -300,25 +305,30 @@ static void encode_password(uint8_t *out, ssize_t *outlen, uint8_t const *input,
        }
        *outlen = len;
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, (uint8_t const *) secret, talloc_array_length(secret) - 1);
-       fr_md5_copy(&old, &context);
+       md5_ctx = fr_md5_ctx_alloc(false);
+       md5_ctx_old = fr_md5_ctx_alloc(true);
+
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, talloc_array_length(secret) - 1);
+       fr_md5_ctx_copy(md5_ctx_old, md5_ctx);
 
        /*
         *      Do first pass.
         */
-       fr_md5_update(&context, vector, AUTH_PASS_LEN);
+       fr_md5_update(md5_ctx, vector, AUTH_PASS_LEN);
 
        for (n = 0; n < len; n += AUTH_PASS_LEN) {
                if (n > 0) {
-                       fr_md5_copy(&context, &old);
-                       fr_md5_update(&context, passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
+                       fr_md5_update(md5_ctx, passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
                }
 
-               fr_md5_final(digest, &context);
+               fr_md5_final(digest, md5_ctx);
                for (i = 0; i < AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
        }
 
+       fr_md5_ctx_free(&md5_ctx);
+       fr_md5_ctx_free(&md5_ctx_old);
+
        memcpy(out, passwd, len);
 }
 
@@ -327,7 +337,7 @@ static void encode_tunnel_password(uint8_t *out, ssize_t *outlen,
                                   uint8_t const *input, size_t inlen, size_t freespace,
                                   char const *secret, uint8_t const *vector)
 {
-       FR_MD5_CTX      context, old;
+       fr_md5_ctx_t    *md5_ctx, *md5_ctx_old;
        uint8_t         digest[AUTH_VECTOR_LEN];
        size_t          i, n;
        size_t          encrypted_len;
@@ -386,21 +396,23 @@ static void encode_tunnel_password(uint8_t *out, ssize_t *outlen,
        out[1] = fr_rand();
        out[2] = inlen; /* length of the password string */
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, (uint8_t const *) secret, talloc_array_length(secret) - 1);
-       fr_md5_copy(&old, &context);
+       md5_ctx = fr_md5_ctx_alloc(false);
+       md5_ctx_old = fr_md5_ctx_alloc(true);
+
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, talloc_array_length(secret) - 1);
+       fr_md5_ctx_copy(md5_ctx_old, md5_ctx);
 
-       fr_md5_update(&context, vector, AUTH_VECTOR_LEN);
-       fr_md5_update(&context, &out[0], 2);
+       fr_md5_update(md5_ctx, vector, AUTH_VECTOR_LEN);
+       fr_md5_update(md5_ctx, &out[0], 2);
 
        for (n = 0; n < encrypted_len; n += AUTH_PASS_LEN) {
                size_t block_len;
 
                if (n > 0) {
-                       fr_md5_copy(&context, &old);
-                       fr_md5_update(&context, out + 2 + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
+                       fr_md5_ctx_copy(md5_ctx, md5_ctx_old);
+                       fr_md5_update(md5_ctx, out + 2 + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
                }
-               fr_md5_final(digest, &context);
+               fr_md5_final(digest, md5_ctx);
 
                if ((2 + n + AUTH_PASS_LEN) < freespace) {
                        block_len = AUTH_PASS_LEN;
@@ -410,6 +422,9 @@ static void encode_tunnel_password(uint8_t *out, ssize_t *outlen,
 
                for (i = 0; i < block_len; i++) out[i + 2 + n] ^= digest[i];
        }
+
+       fr_md5_ctx_free(&md5_ctx);
+       fr_md5_ctx_free(&md5_ctx_old);
 }
 
 static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen,
index 0f958590ddb9c63ae68b62a9d0823f91f456a626..c4a2dd670cabd9563ea935e59247a206156536be 100644 (file)
@@ -114,7 +114,7 @@ static int test_decode(UNUSED void const *instance, REQUEST *request, uint8_t *c
 
 static ssize_t test_encode(UNUSED void const *instance, REQUEST *request, uint8_t *buffer, size_t buffer_len)
 {
-       FR_MD5_CTX context;
+       fr_md5_ctx_t    *md5_ctx;
        fr_radius_packet_ctx_t const *pc = talloc_get_type_abort_const(request->async->listen->app_instance,
                                                                       fr_radius_packet_ctx_t);
 
@@ -128,10 +128,11 @@ static ssize_t test_encode(UNUSED void const *instance, REQUEST *request, uint8_
 
        memcpy(buffer + 4, pc->vector, 16);
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, buffer, 20);
-       fr_md5_update(&context, (uint8_t const *) secret, strlen(secret));
-       fr_md5_final(buffer + 4, &context);
+       md5_ctx = fr_md5_ctx_alloc(true);
+       fr_md5_update(md5_ctx, buffer, 20);
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, strlen(secret));
+       fr_md5_final(buffer + 4, md5_ctx);
+       fr_md5_ctx_free(&md5_ctx);
 
        return 20;
 }
index 487ded661439e93fca8939181a89946cf15acc47..aeae6c9a26a147125e7fe42854711faf18e2c3f1 100644 (file)
@@ -83,7 +83,7 @@ static int test_decode(void const *instance, REQUEST *request, uint8_t *const da
 
 static ssize_t test_encode(void const *instance, REQUEST *request, uint8_t *buffer, size_t buffer_len)
 {
-       FR_MD5_CTX context;
+       fr_md5_ctx_t    *md5_ctx;
        fr_listen_test_t const *pc = instance;
 
        MPRINT1("\t\tENCODE >>> request %"PRIu64"- data %p %p room %zd\n", request->number, pc, buffer, buffer_len);
@@ -95,10 +95,11 @@ static ssize_t test_encode(void const *instance, REQUEST *request, uint8_t *buff
 
        memcpy(buffer + 4, tpc.vector, 16);
 
-       fr_md5_init(&context);
-       fr_md5_update(&context, buffer, 20);
-       fr_md5_update(&context, (uint8_t const *) secret, strlen(secret));
-       fr_md5_final(buffer + 4, &context);
+       md5_ctx = fr_md5_ctx_alloc(true);
+       fr_md5_update(md5_ctx, buffer, 20);
+       fr_md5_update(md5_ctx, (uint8_t const *) secret, strlen(secret));
+       fr_md5_final(buffer + 4, md5_ctx);
+       fr_md5_ctx_free(&md5_ctx);
 
        return 20;
 }