#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
-#define FUNC(ret, name, args, cargs) \
- err = ENSURE_SYMBOL(name); \
- if (err < 0) \
- return err;
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ { \
+ gnutls_brotlidec_dlhandle = NULL; \
+ return err; \
+ }
#define VOID_FUNC FUNC
#include "brotlidecfuncs.h"
#undef VOID_FUNC
#pragma GCC diagnostic pop
}
+unsigned
+gnutls_brotlidec_is_usable (void)
+{
+ return gnutls_brotlidec_dlhandle != NULL;
+}
+
#else /* GNUTLS_BROTLIDEC_ENABLE_DLOPEN */
int
{
}
+unsigned
+gnutls_brotlidec_is_usable (void)
+{
+ /* The library is linked at build time, thus always usable */
+ return 1;
+}
+
#endif /* !GNUTLS_BROTLIDEC_ENABLE_DLOPEN */
*/
void gnutls_brotlidec_unload_library (void);
+/* Return 1 if the library is loaded and usable.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+unsigned gnutls_brotlidec_is_usable (void);
+
#endif /* GNUTLS_LIB_DLWRAP_BROTLIDEC_H_ */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
-#define FUNC(ret, name, args, cargs) \
- err = ENSURE_SYMBOL(name); \
- if (err < 0) \
- return err;
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ { \
+ gnutls_brotlienc_dlhandle = NULL; \
+ return err; \
+ }
#define VOID_FUNC FUNC
#include "brotliencfuncs.h"
#undef VOID_FUNC
#pragma GCC diagnostic pop
}
+unsigned
+gnutls_brotlienc_is_usable (void)
+{
+ return gnutls_brotlienc_dlhandle != NULL;
+}
+
#else /* GNUTLS_BROTLIENC_ENABLE_DLOPEN */
int
{
}
+unsigned
+gnutls_brotlienc_is_usable (void)
+{
+ /* The library is linked at build time, thus always usable */
+ return 1;
+}
+
#endif /* !GNUTLS_BROTLIENC_ENABLE_DLOPEN */
*/
void gnutls_brotlienc_unload_library (void);
+/* Return 1 if the library is loaded and usable.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+unsigned gnutls_brotlienc_is_usable (void);
+
#endif /* GNUTLS_LIB_DLWRAP_BROTLIENC_H_ */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
-#define FUNC(ret, name, args, cargs) \
- err = ENSURE_SYMBOL(name); \
- if (err < 0) \
- return err;
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ { \
+ gnutls_oqs_dlhandle = NULL; \
+ return err; \
+ }
#define VOID_FUNC FUNC
#include "oqsfuncs.h"
#undef VOID_FUNC
#pragma GCC diagnostic pop
}
+unsigned
+gnutls_oqs_is_usable (void)
+{
+ return gnutls_oqs_dlhandle != NULL;
+}
+
#else /* GNUTLS_OQS_ENABLE_DLOPEN */
int
{
}
+unsigned
+gnutls_oqs_is_usable (void)
+{
+ /* The library is linked at build time, thus always usable */
+ return 1;
+}
+
#endif /* !GNUTLS_OQS_ENABLE_DLOPEN */
*/
void gnutls_oqs_unload_library (void);
+/* Return 1 if the library is loaded and usable.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+unsigned gnutls_oqs_is_usable (void);
+
#endif /* GNUTLS_LIB_DLWRAP_OQS_H_ */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
-#define FUNC(ret, name, args, cargs) \
- err = ENSURE_SYMBOL(name); \
- if (err < 0) \
- return err;
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ { \
+ gnutls_zlib_dlhandle = NULL; \
+ return err; \
+ }
#define VOID_FUNC FUNC
#include "zlibfuncs.h"
#undef VOID_FUNC
#pragma GCC diagnostic pop
}
+unsigned
+gnutls_zlib_is_usable (void)
+{
+ return gnutls_zlib_dlhandle != NULL;
+}
+
#else /* GNUTLS_ZLIB_ENABLE_DLOPEN */
int
{
}
+unsigned
+gnutls_zlib_is_usable (void)
+{
+ /* The library is linked at build time, thus always usable */
+ return 1;
+}
+
#endif /* !GNUTLS_ZLIB_ENABLE_DLOPEN */
*/
void gnutls_zlib_unload_library (void);
+/* Return 1 if the library is loaded and usable.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+unsigned gnutls_zlib_is_usable (void);
+
#endif /* GNUTLS_LIB_DLWRAP_ZLIB_H_ */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
-#define FUNC(ret, name, args, cargs) \
- err = ENSURE_SYMBOL(name); \
- if (err < 0) \
- return err;
+#define FUNC(ret, name, args, cargs) \
+ err = ENSURE_SYMBOL(name); \
+ if (err < 0) \
+ { \
+ gnutls_zstd_dlhandle = NULL; \
+ return err; \
+ }
#define VOID_FUNC FUNC
#include "zstdfuncs.h"
#undef VOID_FUNC
#pragma GCC diagnostic pop
}
+unsigned
+gnutls_zstd_is_usable (void)
+{
+ return gnutls_zstd_dlhandle != NULL;
+}
+
#else /* GNUTLS_ZSTD_ENABLE_DLOPEN */
int
{
}
+unsigned
+gnutls_zstd_is_usable (void)
+{
+ /* The library is linked at build time, thus always usable */
+ return 1;
+}
+
#endif /* !GNUTLS_ZSTD_ENABLE_DLOPEN */
*/
void gnutls_zstd_unload_library (void);
+/* Return 1 if the library is loaded and usable.
+ *
+ * Note that this function is NOT thread-safe; when calling it from
+ * multi-threaded programs, protect it with a locking mechanism.
+ */
+unsigned gnutls_zstd_is_usable (void);
+
#endif /* GNUTLS_LIB_DLWRAP_ZSTD_H_ */
goto out;
}
-#ifdef HAVE_LIBOQS
- ret = _gnutls_liboqs_init();
- if (ret < 0) {
- gnutls_assert();
- goto out;
- }
-#endif
-
#ifndef _WIN32
ret = _gnutls_register_fork_handler();
if (ret < 0) {
#endif
#include "errors.h"
+#include "locks.h"
#include "dlwrap/oqs.h"
#include "liboqs/rand.h"
#include "liboqs/sha3.h"
-int _gnutls_liboqs_init(void)
+/* We can't use GNUTLS_ONCE here, as it wouldn't allow manual unloading */
+GNUTLS_STATIC_MUTEX(liboqs_init_mutex);
+static int _liboqs_init = 0;
+
+int _gnutls_liboqs_ensure(void)
{
+ int ret;
+
+ if (_liboqs_init)
+ return GNUTLS_E_SUCCESS;
+
+ ret = gnutls_static_mutex_lock(&liboqs_init_mutex);
+ if (unlikely(ret < 0))
+ return gnutls_assert_val(ret);
+
if (gnutls_oqs_ensure_library(OQS_LIBRARY_SONAME,
- RTLD_NOW | RTLD_GLOBAL) < 0)
- return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ RTLD_NOW | RTLD_GLOBAL) < 0) {
+ _gnutls_debug_log(
+ "liboqs: unable to initialize liboqs functions\n");
+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ goto out;
+ }
_gnutls_liboqs_sha3_init();
GNUTLS_OQS_FUNC(OQS_init)();
_gnutls_liboqs_rand_init();
- return 0;
+
+ _liboqs_init = 1;
+ ret = GNUTLS_E_SUCCESS;
+
+out:
+ (void)gnutls_static_mutex_unlock(&liboqs_init_mutex);
+
+ return ret;
}
+/* This is not thread-safe: call this function only from
+ * gnutls_global_deinit, which has a proper protection.
+ */
void _gnutls_liboqs_deinit(void)
{
- _gnutls_liboqs_rand_deinit();
- _gnutls_liboqs_sha3_deinit();
- GNUTLS_OQS_FUNC(OQS_destroy)();
+ if (_liboqs_init) {
+ _gnutls_liboqs_rand_deinit();
+ _gnutls_liboqs_sha3_deinit();
+ GNUTLS_OQS_FUNC(OQS_destroy)();
+ }
+
gnutls_oqs_unload_library();
+ _liboqs_init = 0;
}
#ifndef GNUTLS_LIB_LIBOQS_LIBOQS_H
#define GNUTLS_LIB_LIBOQS_LIBOQS_H
-int _gnutls_liboqs_init(void);
+int _gnutls_liboqs_ensure(void);
void _gnutls_liboqs_deinit(void);
#endif /* GNUTLS_LIB_LIBOQS_LIBOQS_H */
#include "dh.h"
#ifdef HAVE_LIBOQS
#include "dlwrap/oqs.h"
+#include "liboqs/liboqs.h"
#endif
static inline const struct ecc_curve *get_supported_nist_curve(int curve);
OQS_KEM *kem = NULL;
OQS_STATUS rc;
+ if (_gnutls_liboqs_ensure() < 0)
+ return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768);
if (kem == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
OQS_KEM *kem = NULL;
OQS_STATUS rc;
+ if (_gnutls_liboqs_ensure() < 0)
+ return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768);
if (kem == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
case GNUTLS_PK_RSA_PSS:
case GNUTLS_PK_RSA_OAEP:
case GNUTLS_PK_EDDSA_ED25519:
-#ifdef HAVE_LIBOQS
- case GNUTLS_PK_EXP_KYBER768:
-#endif
#if ENABLE_GOST
case GNUTLS_PK_GOST_01:
case GNUTLS_PK_GOST_12_256:
case GNUTLS_PK_ECDH_X448:
case GNUTLS_PK_EDDSA_ED448:
return 1;
+#ifdef HAVE_LIBOQS
+ case GNUTLS_PK_EXP_KYBER768:
+ return _gnutls_liboqs_ensure() == 0;
+#endif
default:
return 0;
}
}
case GNUTLS_PK_ECDH_X25519:
case GNUTLS_PK_ECDH_X448:
+ break;
#ifdef HAVE_LIBOQS
case GNUTLS_PK_EXP_KYBER768:
+ if (_gnutls_liboqs_ensure() < 0) {
+ ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+ goto cleanup;
+ }
#endif
- ret = 0;
- goto cleanup;
+ break;
default:
ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
goto cleanup;
OQS_KEM *kem = NULL;
OQS_STATUS rc;
+#ifdef HAVE_LIBOQS
+ if (_gnutls_liboqs_ensure() < 0) {
+ ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+ goto cleanup;
+ }
+#endif
+
not_approved = true;
kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768);
}
#ifdef HAVE_LIBOQS
case GNUTLS_PK_EXP_KYBER768:
- ret = 0;
+ ret = _gnutls_liboqs_ensure();
+ if (ret < 0)
+ ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
break;
#endif
#if ENABLE_GOST