fr_md4_ctx_t *md_ctx;
} fr_md4_free_list_t;
static _Thread_local fr_md4_free_list_t *md4_array;
+
+static void fr_md4_local_ctx_reset(fr_md4_ctx_t *ctx);
+static void fr_md4_local_ctx_copy(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src);
+#ifdef HAVE_OPENSSL_EVP_H
+static fr_md4_ctx_t *fr_md4_local_ctx_init(void);
+#else
+static fr_md4_ctx_t *fr_md4_local_ctx_alloc(void);
+#endif
+static void fr_md4_local_ctx_free(fr_md4_ctx_t **ctx);
+static void fr_md4_local_update(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen);
+static void fr_md4_local_final(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx);
+
+static fr_md4_funcs_t md4_local_funcs = {
+ .reset = fr_md4_local_ctx_reset,
+ .copy = fr_md4_local_ctx_copy,
+#ifdef HAVE_OPENSSL_EVP_H
+ .alloc = fr_md4_local_ctx_init,
+#else
+ .alloc = fr_md4_local_ctx_alloc,
+#endif
+ .free = fr_md4_local_ctx_free,
+ .update = fr_md4_local_update,
+ .final = fr_md4_local_final
+};
+fr_md4_funcs_t const *fr_md4_funcs = &md4_local_funcs;
+
/*
* If we have OpenSSL's EVP API available, then build wrapper functions.
*
# include <openssl/err.h>
# include <openssl/provider.h>
-static int have_openssl_md4 = -1;
-
/** @copydoc fr_md4_ctx_reset
*
*/
if (!fr_cond_assert(len == MD4_DIGEST_LENGTH)) return;
}
+
+static fr_md4_funcs_t md4_openssl_funcs = {
+ .reset = fr_md4_openssl_ctx_reset,
+ .copy = fr_md4_openssl_ctx_copy,
+ .alloc = fr_md4_openssl_ctx_alloc,
+ .free = fr_md4_openssl_ctx_free,
+ .update = fr_md4_openssl_update,
+ .final = fr_md4_openssl_final
+};
#endif
/*
{
fr_md4_ctx_local_t *ctx_local;
-#ifdef HAVE_OPENSSL_EVP_H
- if (unlikely(have_openssl_md4 == -1)) {
- /*
- * If we're not in FIPS mode, then swap out the
- * md4 functions, and call the OpenSSL init
- * function.
- */
- if (!EVP_default_properties_is_fips_enabled(NULL)) {
- have_openssl_md4 = 1;
-
- /*
- * Swap out the functions pointers
- * for the OpenSSL versions.
- */
- fr_md4_ctx_reset = fr_md4_openssl_ctx_reset;
- fr_md4_ctx_copy = fr_md4_openssl_ctx_copy;
- fr_md4_ctx_alloc = fr_md4_openssl_ctx_alloc;
- fr_md4_ctx_free = fr_md4_openssl_ctx_free;
- fr_md4_update = fr_md4_openssl_update;
- fr_md4_final = fr_md4_openssl_final;
-
- return fr_md4_ctx_alloc();
- }
-
- have_openssl_md4 = 0;
- }
-#endif
ctx_local = talloc(NULL, fr_md4_ctx_local_t);
if (unlikely(!ctx_local)) return NULL;
fr_md4_local_ctx_reset(ctx_local);
return ctx_local;
}
+#ifdef HAVE_OPENSSL_EVP_H
+/** Initialize whether or not we use the local allocator, or the OpenSSL one.
+ *
+ */
+static fr_md4_ctx_t *fr_md4_local_ctx_init(void)
+{
+ /*
+ * If we are in FIPS mode, then use the local allocator.
+ */
+ if (!EVP_default_properties_is_fips_enabled(NULL)) {
+ /*
+ * OpenSSL isn't in FIPS mode. Swap out the functions
+ * pointers for the OpenSSL versions.
+ *
+ * We do this by swapping out a pointer to a structure
+ * containing the functions, as this prevents possible
+ * skew where some threads see a mixture of functions.
+ */
+ fr_md4_funcs = &md4_openssl_funcs;
+ } else {
+ md4_local_funcs.alloc = fr_md4_local_ctx_alloc; /* Don't call this (init) function again */
+ }
+
+ return fr_md4_ctx_alloc();
+}
+#endif
+
/** @copydoc fr_md4_ctx_free
*
*/
/* md4.c */
+typedef void (*fr_md4_ctx_reset_t)(fr_md4_ctx_t *ctx);
+typedef void (*fr_md4_ctx_copy_t)(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src);
+typedef fr_md4_ctx_t *(*fr_md4_ctx_alloc_t)(void);
+typedef void (*fr_md4_ctx_free_t)(fr_md4_ctx_t **ctx);
+typedef void (*fr_md4_update_t)(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen);
+typedef void (*fr_md4_final_t)(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx);
+
+typedef struct {
+ fr_md4_ctx_reset_t reset;
+ fr_md4_ctx_copy_t copy;
+ fr_md4_ctx_alloc_t alloc;
+ fr_md4_ctx_free_t free;
+ fr_md4_update_t update;
+ fr_md4_final_t final;
+} fr_md4_funcs_t;
+
+/** Swap a single pointer, so all functions get swapped as an atomic operation
+ */
+extern fr_md4_funcs_t const *fr_md4_funcs;
+
/** Reset the ctx to allow reuse
*
* @param[in] ctx To reuse.
*/
-typedef void (*fr_md4_ctx_reset_t)(fr_md4_ctx_t *ctx);
-extern fr_md4_ctx_reset_t fr_md4_ctx_reset;
+#define fr_md4_ctx_reset(_ctx) fr_md4_funcs->reset(_ctx)
/** 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_md4_ctx_copy_t)(fr_md4_ctx_t *dst, fr_md4_ctx_t const *src);
-extern fr_md4_ctx_copy_t fr_md4_ctx_copy;
+#define fr_md4_ctx_copy(_dst, _src) fr_md4_funcs->copy(_dst, _src)
/** Allocation function for MD4 digest context
*
* - An MD4 ctx.
* - NULL if out of memory.
*/
-typedef fr_md4_ctx_t *(*fr_md4_ctx_alloc_t)(void);
-extern fr_md4_ctx_alloc_t fr_md4_ctx_alloc;
+#define fr_md4_ctx_alloc() fr_md4_funcs->alloc()
/** Free function for MD4 digest ctx
*
* @param[in] ctx MD4 ctx to free. If the shared ctx is passed in
* then the ctx is reset but not freed.
*/
-typedef void (*fr_md4_ctx_free_t)(fr_md4_ctx_t **ctx);
-extern fr_md4_ctx_free_t fr_md4_ctx_free;
-
+#define fr_md4_ctx_free(_ctx) fr_md4_funcs->free(_ctx)
/** Ingest plaintext into the digest
*
* @param[in] in Data to ingest.
* @param[in] inlen Length of data to ingest.
*/
-typedef void (*fr_md4_update_t)(fr_md4_ctx_t *ctx, uint8_t const *in, size_t inlen);
-extern fr_md4_update_t fr_md4_update;
+#define fr_md4_update(_ctx, _in, _inlen) fr_md4_funcs->update(_ctx, _in, _inlen)
/** Finalise the ctx, producing the digest
*
* @param[out] out The MD4 digest.
* @param[in] ctx To finalise.
*/
-typedef void (*fr_md4_final_t)(uint8_t out[static MD4_DIGEST_LENGTH], fr_md4_ctx_t *ctx);
-extern fr_md4_final_t fr_md4_final;
+#define fr_md4_final(_out, _ctx) fr_md4_funcs->final(_out, _ctx)
/** Perform a single digest operation on a single input buffer
*
} fr_md5_free_list_t;
static _Thread_local fr_md5_free_list_t *md5_array;
+static void fr_md5_local_ctx_reset(fr_md5_ctx_t *ctx);
+static void fr_md5_local_ctx_copy(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src);
+#ifdef HAVE_OPENSSL_EVP_H
+static fr_md5_ctx_t *fr_md5_local_ctx_init(void);
+#else
+static fr_md5_ctx_t *fr_md5_local_ctx_alloc(void);
+#endif
+static void fr_md5_local_ctx_free(fr_md5_ctx_t **ctx);
+static void fr_md5_local_update(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen);
+static void fr_md5_local_final(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx);
+
+static fr_md5_funcs_t md5_local_funcs = {
+ .reset = fr_md5_local_ctx_reset,
+ .copy = fr_md5_local_ctx_copy,
+#ifdef HAVE_OPENSSL_EVP_H
+ .alloc = fr_md5_local_ctx_init,
+#else
+ .alloc = fr_md5_local_ctx_alloc,
+#endif
+ .free = fr_md5_local_ctx_free,
+ .update = fr_md5_local_update,
+ .final = fr_md5_local_final
+};
+fr_md5_funcs_t const *fr_md5_funcs = &md5_local_funcs;
+
/*
* If we have OpenSSL's EVP API available, then build wrapper functions.
*
if (!fr_cond_assert(len == MD5_DIGEST_LENGTH)) return;
}
+
+static fr_md5_funcs_t md5_openssl_funcs = {
+ .reset = fr_md5_openssl_ctx_reset,
+ .copy = fr_md5_openssl_ctx_copy,
+ .alloc = fr_md5_openssl_ctx_alloc,
+ .free = fr_md5_openssl_ctx_free,
+ .update = fr_md5_openssl_update,
+ .final = fr_md5_openssl_final
+};
#endif
# define MD5_BLOCK_LENGTH 64
/*
* If we are in FIPS mode, then use the local allocator.
*/
- if (EVP_default_properties_is_fips_enabled(NULL)) {
- fr_md5_ctx_alloc = fr_md5_local_ctx_alloc;
- return fr_md5_local_ctx_alloc();
+ if (!EVP_default_properties_is_fips_enabled(NULL)) {
+ /*
+ * OpenSSL isn't in FIPS mode. Swap out the functions
+ * pointers for the OpenSSL versions.
+ *
+ * We do this by swapping out a pointer to a structure
+ * containing the functions, as this prevents possible
+ * skew where some threads see a mixture of functions.
+ */
+ fr_md5_funcs = &md5_openssl_funcs;
+ } else {
+ md5_local_funcs.alloc = fr_md5_local_ctx_alloc; /* Don't call this (init) function again */
}
- /*
- * Otherwise OpenSSL isn't in FIPS mode. 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_openssl_ctx_alloc();
+ return fr_md5_ctx_alloc();
}
#endif
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;
-#ifdef HAVE_OPENSSL_EVP_H
-fr_md5_ctx_alloc_t fr_md5_ctx_alloc = fr_md5_local_ctx_init; /* check what we should do */
-#else
-fr_md5_ctx_alloc_t fr_md5_ctx_alloc = fr_md5_local_ctx_alloc;
-#endif
-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.
/* md5.c */
+typedef void (*fr_md5_ctx_reset_t)(fr_md5_ctx_t *ctx);
+typedef void (*fr_md5_ctx_copy_t)(fr_md5_ctx_t *dst, fr_md5_ctx_t const *src);
+typedef fr_md5_ctx_t *(*fr_md5_ctx_alloc_t)(void);
+typedef void (*fr_md5_ctx_free_t)(fr_md5_ctx_t **ctx);
+typedef void (*fr_md5_update_t)(fr_md5_ctx_t *ctx, uint8_t const *in, size_t inlen);
+typedef void (*fr_md5_final_t)(uint8_t out[static MD5_DIGEST_LENGTH], fr_md5_ctx_t *ctx);
+
+typedef struct {
+ fr_md5_ctx_reset_t reset;
+ fr_md5_ctx_copy_t copy;
+ fr_md5_ctx_alloc_t alloc;
+ fr_md5_ctx_free_t free;
+ fr_md5_update_t update;
+ fr_md5_final_t final;
+} fr_md5_funcs_t;
+
+/** Swap a single pointer, so all functions get swapped as an atomic operation
+ */
+extern fr_md5_funcs_t const *fr_md5_funcs;
+
/** 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;
+#define fr_md5_ctx_reset(_ctx) fr_md5_funcs->reset(_ctx)
/** 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;
+#define fr_md5_ctx_copy(_dst, _src) fr_md5_funcs->copy(_dst, _src)
/** Allocation function for MD5 digest context
*
* - An MD5 ctx.
* - NULL if out of memory.
*/
-typedef fr_md5_ctx_t *(*fr_md5_ctx_alloc_t)(void);
-extern fr_md5_ctx_alloc_t fr_md5_ctx_alloc;
+#define fr_md5_ctx_alloc() fr_md5_funcs->alloc()
/** Free function for MD5 digest ctx
*
* @param[in] ctx MD5 ctx to free. If the shared ctx is passed in
* then the ctx is reset but not freed.
*/
-typedef void (*fr_md5_ctx_free_t)(fr_md5_ctx_t **ctx);
-extern fr_md5_ctx_free_t fr_md5_ctx_free;
+#define fr_md5_ctx_free(_ctx) fr_md5_funcs->free(_ctx)
/** Ingest plaintext into the digest
*
* @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;
+#define fr_md5_update(_ctx, _in, _inlen) fr_md5_funcs->update(_ctx, _in, _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;
+#define fr_md5_final(_out, _ctx) fr_md5_funcs->final(_out, _ctx)
/** Perform a single digest operation on a single input buffer
*