summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS6
-rw-r--r--devel/libgnutls.abignore18
-rw-r--r--devel/symbols.last5
-rw-r--r--doc/Makefile.am11
-rw-r--r--doc/cha-internals.texi24
-rw-r--r--doc/manpages/Makefile.am5
-rw-r--r--lib/fips.c182
-rw-r--r--lib/fips.h156
-rw-r--r--lib/includes/gnutls/gnutls.h.in39
-rw-r--r--lib/libgnutls.map5
10 files changed, 386 insertions, 65 deletions
diff --git a/NEWS b/NEWS
index 638b3b51c2..adb04a155e 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,12 @@ gnutls_sign_set_secure: Added.
gnutls_sign_set_secure_for_certs: Added.
gnutls_digest_set_secure: Added.
gnutls_protocol_set_enabled: Added.
+gnutls_fips140_context_init: New function
+gnutls_fips140_context_deinit: New function
+gnutls_fips140_push_context: New function
+gnutls_fips140_pop_context: New function
+gnutls_fips140_get_operation_state: New function
+gnutls_fips140_operation_state_t: New enum
* Version 3.7.2 (released 2021-05-29)
diff --git a/devel/libgnutls.abignore b/devel/libgnutls.abignore
index 1589707eeb..afa9168b79 100644
--- a/devel/libgnutls.abignore
+++ b/devel/libgnutls.abignore
@@ -105,3 +105,21 @@ name = gnutls_x509_ct_sct_get
[suppress_function]
name = gnutls_transport_is_ktls_enabled
+
+[suppress_function]
+name = gnutls_fips140_context_init
+
+[suppress_function]
+name = gnutls_fips140_context_deinit
+
+[suppress_function]
+name = gnutls_fips140_push_context
+
+[suppress_function]
+name = gnutls_fips140_pop_context
+
+[suppress_function]
+name = gnutls_fips140_get_operation_state
+
+[suppress_type]
+name = gnutls_fips140_operation_state_t
diff --git a/devel/symbols.last b/devel/symbols.last
index 9142d5a3ed..d10b12d3ed 100644
--- a/devel/symbols.last
+++ b/devel/symbols.last
@@ -250,7 +250,12 @@ gnutls_ffdhe_8192_group_prime@GNUTLS_3_4
gnutls_ffdhe_8192_group_q@GNUTLS_3_6_8
gnutls_ffdhe_8192_key_bits@GNUTLS_3_4
gnutls_fingerprint@GNUTLS_3_4
+gnutls_fips140_context_deinit@GNUTLS_3_7_3
+gnutls_fips140_context_init@GNUTLS_3_7_3
+gnutls_fips140_get_operation_state@GNUTLS_3_7_3
gnutls_fips140_mode_enabled@GNUTLS_3_4
+gnutls_fips140_pop_context@GNUTLS_3_7_3
+gnutls_fips140_push_context@GNUTLS_3_7_3
gnutls_fips140_set_mode@GNUTLS_3_6_3
gnutls_free@GNUTLS_3_4
gnutls_get_system_config_file@GNUTLS_3_6_9
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 3c2d5e68d3..ab414add8b 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -550,6 +550,7 @@ ENUMS += enums/gnutls_digest_algorithm_t
ENUMS += enums/gnutls_ecc_curve_t
ENUMS += enums/gnutls_ext_flags_t
ENUMS += enums/gnutls_ext_parse_type_t
+ENUMS += enums/gnutls_fips140_operation_state_t
ENUMS += enums/gnutls_fips_mode_t
ENUMS += enums/gnutls_gost_paramset_t
ENUMS += enums/gnutls_group_t
@@ -1042,8 +1043,18 @@ FUNCS += functions/gnutls_ext_set_data
FUNCS += functions/gnutls_ext_set_data.short
FUNCS += functions/gnutls_fingerprint
FUNCS += functions/gnutls_fingerprint.short
+FUNCS += functions/gnutls_fips140_context_deinit
+FUNCS += functions/gnutls_fips140_context_deinit.short
+FUNCS += functions/gnutls_fips140_context_init
+FUNCS += functions/gnutls_fips140_context_init.short
+FUNCS += functions/gnutls_fips140_get_operation_state
+FUNCS += functions/gnutls_fips140_get_operation_state.short
FUNCS += functions/gnutls_fips140_mode_enabled
FUNCS += functions/gnutls_fips140_mode_enabled.short
+FUNCS += functions/gnutls_fips140_pop_context
+FUNCS += functions/gnutls_fips140_pop_context.short
+FUNCS += functions/gnutls_fips140_push_context
+FUNCS += functions/gnutls_fips140_push_context.short
FUNCS += functions/gnutls_fips140_set_mode
FUNCS += functions/gnutls_fips140_set_mode.short
FUNCS += functions/gnutls_get_system_config_file
diff --git a/doc/cha-internals.texi b/doc/cha-internals.texi
index f188caecc9..9dd1d8b6cc 100644
--- a/doc/cha-internals.texi
+++ b/doc/cha-internals.texi
@@ -754,3 +754,27 @@ Applications could also switch FIPS140-2 mode explicitly off, by calling
@example
gnutls_fips140_set_mode(GNUTLS_FIPS140_LAX, 0);
@end example
+
+@subheading Service indicator
+
+The above restrictions may not cover all the requirements in every
+usage context, and as the FIPS140 standard evolves (like FIPS140-3),
+GnuTLS may not be able to add new restrictions without breaking
+compatibility.
+
+Therefore an additional set of API functions is provided to
+communicate with the user whether any approved mode of operations is
+performed within a given context.
+
+@showfuncD{gnutls_fips140_context_init,gnutls_fips140_context_deinit,gnutls_fips140_push_context,gnutls_fips140_pop_context}
+
+The @code{gnutls_fips140_context_t} represents the FIPS140-2 mode of
+operation. It can be attached to the current execution thread with
+@funcref{gnutls_fips140_push_context} and its internal state will be
+updated until it is detached with
+@funcref{gnutls_fips140_pop_context}. Afterwards
+@funcref{gnutls_fips140_get_operation_state} allows the user
+to examine whether any approved (or non-approved) security function is
+invoked.
+
+@showfuncdesc{gnutls_fips140_get_operation_state}
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
index 37ed4eb66e..c3bcac9f3b 100644
--- a/doc/manpages/Makefile.am
+++ b/doc/manpages/Makefile.am
@@ -323,7 +323,12 @@ APIMANS += gnutls_ext_raw_parse.3
APIMANS += gnutls_ext_register.3
APIMANS += gnutls_ext_set_data.3
APIMANS += gnutls_fingerprint.3
+APIMANS += gnutls_fips140_context_deinit.3
+APIMANS += gnutls_fips140_context_init.3
+APIMANS += gnutls_fips140_get_operation_state.3
APIMANS += gnutls_fips140_mode_enabled.3
+APIMANS += gnutls_fips140_pop_context.3
+APIMANS += gnutls_fips140_push_context.3
APIMANS += gnutls_fips140_set_mode.3
APIMANS += gnutls_get_system_config_file.3
APIMANS += gnutls_global_deinit.3
diff --git a/lib/fips.c b/lib/fips.c
index 51567953df..457a8c056e 100644
--- a/lib/fips.c
+++ b/lib/fips.c
@@ -33,6 +33,12 @@
#include "gthreads.h"
unsigned int _gnutls_lib_state = LIB_STATE_POWERON;
+
+struct gnutls_fips140_context_st {
+ gnutls_fips140_operation_state_t state;
+ struct gnutls_fips140_context_st *next;
+};
+
#ifdef ENABLE_FIPS140
#include <dlfcn.h>
@@ -46,6 +52,8 @@ unsigned int _gnutls_lib_state = LIB_STATE_POWERON;
static gnutls_fips_mode_t _global_fips_mode = -1;
static _Thread_local gnutls_fips_mode_t _tfips_mode = -1;
+static _Thread_local gnutls_fips140_context_t _tfips_context = NULL;
+
static int _skip_integrity_checks = 0;
/* Returns:
@@ -599,3 +607,177 @@ void _gnutls_lib_force_operational(void)
{
_gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
}
+
+/**
+ * gnutls_fips140_context_init:
+ * @context: location to store @gnutls_fips140_context_t
+ *
+ * Create and initialize the FIPS context object.
+ *
+ * Returns: 0 upon success, a negative error code otherwise
+ *
+ * Since: 3.7.3
+ */
+int
+gnutls_fips140_context_init(gnutls_fips140_context_t *context)
+{
+ *context = gnutls_malloc(sizeof(struct gnutls_fips140_context_st));
+ if (!*context) {
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ }
+ (*context)->state = GNUTLS_FIPS140_OP_INITIAL;
+ return 0;
+}
+
+/**
+ * gnutls_fips140_context_deinit:
+ * @context: a #gnutls_fips140_context_t
+ *
+ * Uninitialize and release the FIPS context @context.
+ *
+ * Since: 3.7.3
+ */
+void
+gnutls_fips140_context_deinit(gnutls_fips140_context_t context)
+{
+ gnutls_free(context);
+}
+
+/**
+ * gnutls_fips140_get_operation_state:
+ * @context: a #gnutls_fips140_context_t
+ *
+ * Get the previous operation state of @context in terms of FIPS.
+ *
+ * Returns: a #gnutls_fips140_operation_state_t
+ *
+ * Since: 3.7.3
+ */
+gnutls_fips140_operation_state_t
+gnutls_fips140_get_operation_state(gnutls_fips140_context_t context)
+{
+ return context->state;
+}
+
+/**
+ * gnutls_fips140_push_context:
+ * @context: a #gnutls_fips140_context_t
+ *
+ * Associate the FIPS @context to the current thread, diverting the
+ * currently active context. If a cryptographic operation is ongoing
+ * in the current thread, e.g., gnutls_aead_cipher_init() is called
+ * but gnutls_aead_cipher_deinit() is not yet called, it returns an
+ * error %GNUTLS_E_INVALID_REQUEST.
+ *
+ * The operation state of @context will be reset to
+ * %GNUTLS_FIPS140_OP_INITIAL.
+ *
+ * Returns: 0 upon success, a negative error code otherwise
+ *
+ * Since: 3.7.3
+ */
+int
+gnutls_fips140_push_context(gnutls_fips140_context_t context)
+{
+#ifdef ENABLE_FIPS140
+ context->next = _tfips_context;
+ _tfips_context = context;
+
+ context->state = GNUTLS_FIPS140_OP_INITIAL;
+ return 0;
+#else
+ return GNUTLS_E_INVALID_REQUEST;
+#endif
+}
+
+/**
+ * gnutls_fips140_pop_context:
+ *
+ * Dissociate the FIPS context currently
+ * active on the current thread, reverting to the previously active
+ * context. If a cryptographic operation is ongoing in the current
+ * thread, e.g., gnutls_aead_cipher_init() is called but
+ * gnutls_aead_cipher_deinit() is not yet called, it returns an error
+ * %GNUTLS_E_INVALID_REQUEST.
+ *
+ * Returns: 0 upon success, a negative error code otherwise
+ *
+ * Since: 3.7.3
+ */
+int
+gnutls_fips140_pop_context(void)
+{
+#ifdef ENABLE_FIPS140
+ if (!_tfips_context) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+
+ _tfips_context = _tfips_context->next;
+ return 0;
+#else
+ return GNUTLS_E_INVALID_REQUEST;
+#endif
+}
+
+static inline const char *
+operation_state_to_string(gnutls_fips140_operation_state_t state)
+{
+ switch (state) {
+ case GNUTLS_FIPS140_OP_INITIAL:
+ return "initial";
+ case GNUTLS_FIPS140_OP_APPROVED:
+ return "approved";
+ case GNUTLS_FIPS140_OP_NOT_APPROVED:
+ return "not-approved";
+ case GNUTLS_FIPS140_OP_ERROR:
+ return "error";
+ default:
+ /*NOTREACHED*/
+ assert(0);
+ return NULL;
+ }
+}
+
+gnutls_fips140_operation_state_t
+_gnutls_transit_fips_state(gnutls_fips140_operation_state_t current,
+ gnutls_fips140_operation_state_t next)
+{
+ switch (current) {
+ case GNUTLS_FIPS140_OP_INITIAL:
+ /* initial can be transitioned to any state */
+ _gnutls_debug_log("FIPS140-2 operation mode switched from initial to %s\n",
+ operation_state_to_string(next));
+ return next;
+ case GNUTLS_FIPS140_OP_APPROVED:
+ /* approved can only be transitioned to not-approved */
+ if (next == GNUTLS_FIPS140_OP_NOT_APPROVED) {
+ _gnutls_debug_log("FIPS140-2 operation mode switched from approved to %s\n",
+ operation_state_to_string(next));
+ return next;
+ }
+ FALLTHROUGH;
+ default:
+ /* other transitions are prohibited */
+ if (next != current) {
+ _gnutls_debug_log("FIPS140-2 operation mode cannot be switched from %s to %s\n",
+ operation_state_to_string(current),
+ operation_state_to_string(next));
+ }
+ return current;
+ }
+}
+
+void
+_gnutls_switch_fips_state(gnutls_fips140_operation_state_t state)
+{
+#ifdef ENABLE_FIPS140
+ if (!_tfips_context) {
+ _gnutls_debug_log("FIPS140-2 context is not set\n");
+ return;
+ }
+ _tfips_context->state =
+ _gnutls_transit_fips_state(_tfips_context->state, state);
+#else
+ (void)state;
+#endif
+}
diff --git a/lib/fips.h b/lib/fips.h
index f76f24da75..cb5ff6a5d3 100644
--- a/lib/fips.h
+++ b/lib/fips.h
@@ -41,6 +41,12 @@ typedef enum {
extern unsigned int _gnutls_lib_state;
extern gnutls_crypto_rnd_st _gnutls_fips_rnd_ops;
+gnutls_fips140_operation_state_t
+_gnutls_transit_fips_state(gnutls_fips140_operation_state_t current,
+ gnutls_fips140_operation_state_t next);
+
+void _gnutls_switch_fips_state(gnutls_fips140_operation_state_t state);
+
inline static
void _gnutls_switch_lib_state(gnutls_lib_state_t state)
{
@@ -89,85 +95,105 @@ void _gnutls_lib_force_operational(void);
} \
}}
-inline
-static unsigned is_mac_algo_forbidden(gnutls_mac_algorithm_t algo)
+inline static bool
+is_mac_algo_forbidden_in_fips(gnutls_mac_algorithm_t algo)
+{
+ switch (algo) {
+ case GNUTLS_MAC_SHA1:
+ case GNUTLS_MAC_SHA256:
+ case GNUTLS_MAC_SHA384:
+ case GNUTLS_MAC_SHA512:
+ case GNUTLS_MAC_SHA224:
+ case GNUTLS_MAC_SHA3_224:
+ case GNUTLS_MAC_SHA3_256:
+ case GNUTLS_MAC_SHA3_384:
+ case GNUTLS_MAC_SHA3_512:
+ case GNUTLS_MAC_AES_CMAC_128:
+ case GNUTLS_MAC_AES_CMAC_256:
+ case GNUTLS_MAC_AES_GMAC_128:
+ case GNUTLS_MAC_AES_GMAC_192:
+ case GNUTLS_MAC_AES_GMAC_256:
+ return false;
+ default:
+ return true;
+ }
+}
+
+inline static bool
+is_mac_algo_forbidden(gnutls_mac_algorithm_t algo)
{
gnutls_fips_mode_t mode = _gnutls_fips_mode_enabled();
- if (mode != GNUTLS_FIPS140_DISABLED &&
- _gnutls_get_lib_state() != LIB_STATE_SELFTEST) {
- switch(algo) {
- case GNUTLS_MAC_SHA1:
- case GNUTLS_MAC_SHA256:
- case GNUTLS_MAC_SHA384:
- case GNUTLS_MAC_SHA512:
- case GNUTLS_MAC_SHA224:
- case GNUTLS_MAC_SHA3_224:
- case GNUTLS_MAC_SHA3_256:
- case GNUTLS_MAC_SHA3_384:
- case GNUTLS_MAC_SHA3_512:
- case GNUTLS_MAC_AES_CMAC_128:
- case GNUTLS_MAC_AES_CMAC_256:
- case GNUTLS_MAC_AES_GMAC_128:
- case GNUTLS_MAC_AES_GMAC_192:
- case GNUTLS_MAC_AES_GMAC_256:
- return 0;
- default:
- if (mode == GNUTLS_FIPS140_LAX)
- return 0;
- else if (mode == GNUTLS_FIPS140_LOG) {
- _gnutls_audit_log(NULL, "fips140-2: allowing access to %s\n",
- gnutls_mac_get_name(algo));
- return 0;
- }
- return 1;
+ if (_gnutls_get_lib_state() != LIB_STATE_SELFTEST &&
+ is_mac_algo_forbidden_in_fips(algo)) {
+ switch (mode) {
+ case GNUTLS_FIPS140_LOG:
+ _gnutls_audit_log(NULL,
+ "fips140-2: allowing access to %s\n",
+ gnutls_mac_get_name(algo));
+ FALLTHROUGH;
+ case GNUTLS_FIPS140_DISABLED:
+ case GNUTLS_FIPS140_LAX:
+ return false;
+ default:
+ return true;
}
}
- return 0;
+ return false;
+}
+
+inline static bool
+is_cipher_algo_forbidden_in_fips(gnutls_cipher_algorithm_t algo)
+{
+ switch (algo) {
+ case GNUTLS_CIPHER_AES_128_CBC:
+ case GNUTLS_CIPHER_AES_256_CBC:
+ case GNUTLS_CIPHER_AES_192_CBC:
+ case GNUTLS_CIPHER_AES_128_GCM:
+ case GNUTLS_CIPHER_AES_192_GCM:
+ case GNUTLS_CIPHER_AES_256_GCM:
+ case GNUTLS_CIPHER_AES_128_CCM:
+ case GNUTLS_CIPHER_AES_256_CCM:
+ case GNUTLS_CIPHER_3DES_CBC:
+ case GNUTLS_CIPHER_AES_128_CCM_8:
+ case GNUTLS_CIPHER_AES_256_CCM_8:
+ case GNUTLS_CIPHER_AES_128_CFB8:
+ case GNUTLS_CIPHER_AES_192_CFB8:
+ case GNUTLS_CIPHER_AES_256_CFB8:
+ case GNUTLS_CIPHER_AES_128_XTS:
+ case GNUTLS_CIPHER_AES_256_XTS:
+ return false;
+ default:
+ return true;
+ }
}
-inline
-static unsigned is_cipher_algo_forbidden(gnutls_cipher_algorithm_t algo)
+inline static bool
+is_cipher_algo_forbidden(gnutls_cipher_algorithm_t algo)
{
gnutls_fips_mode_t mode = _gnutls_fips_mode_enabled();
- if (mode != GNUTLS_FIPS140_DISABLED &&
- _gnutls_get_lib_state() != LIB_STATE_SELFTEST) {
-
- switch(algo) {
- case GNUTLS_CIPHER_AES_128_CBC:
- case GNUTLS_CIPHER_AES_256_CBC:
- case GNUTLS_CIPHER_AES_192_CBC:
- case GNUTLS_CIPHER_AES_128_GCM:
- case GNUTLS_CIPHER_AES_192_GCM:
- case GNUTLS_CIPHER_AES_256_GCM:
- case GNUTLS_CIPHER_AES_128_CCM:
- case GNUTLS_CIPHER_AES_256_CCM:
- case GNUTLS_CIPHER_3DES_CBC:
- case GNUTLS_CIPHER_AES_128_CCM_8:
- case GNUTLS_CIPHER_AES_256_CCM_8:
- case GNUTLS_CIPHER_AES_128_CFB8:
- case GNUTLS_CIPHER_AES_192_CFB8:
- case GNUTLS_CIPHER_AES_256_CFB8:
- case GNUTLS_CIPHER_AES_128_XTS:
- case GNUTLS_CIPHER_AES_256_XTS:
- return 0;
- default:
- if (mode == GNUTLS_FIPS140_LAX)
- return 0;
- else if (mode == GNUTLS_FIPS140_LOG) {
- _gnutls_audit_log(NULL, "fips140-2: allowing access to %s\n",
- gnutls_cipher_get_name(algo));
- return 0;
- }
- return 1;
+ if (_gnutls_get_lib_state() != LIB_STATE_SELFTEST &&
+ is_cipher_algo_forbidden_in_fips(algo)) {
+ switch (mode) {
+ case GNUTLS_FIPS140_LOG:
+ _gnutls_audit_log(NULL, "fips140-2: allowing access to %s\n",
+ gnutls_cipher_get_name(algo));
+ FALLTHROUGH;
+ case GNUTLS_FIPS140_DISABLED:
+ case GNUTLS_FIPS140_LAX:
+ return false;
+ default:
+ return true;
}
}
- return 0;
+ return false;
}
#else
-# define is_mac_algo_forbidden(x) 0
-# define is_cipher_algo_forbidden(x) 0
+# define is_mac_algo_forbidden_in_fips(x) false
+# define is_mac_algo_forbidden(x) false
+# define is_cipher_algo_forbidden_in_fips(x) false
+# define is_cipher_algo_forbidden(x) false
# define FIPS_RULE(condition, ret_error, ...)
#endif
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 1e883aa8eb..0e96be81e8 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -3348,6 +3348,45 @@ void gnutls_fips140_set_mode(gnutls_fips_mode_t mode, unsigned flags);
gnutls_fips140_set_mode(GNUTLS_FIPS140_STRICT, GNUTLS_FIPS140_SET_MODE_THREAD); \
} while(0)
+typedef struct gnutls_fips140_context_st *gnutls_fips140_context_t;
+
+int gnutls_fips140_context_init(gnutls_fips140_context_t *context);
+void gnutls_fips140_context_deinit(gnutls_fips140_context_t context);
+
+/**
+ * gnutls_fips140_operation_state_t:
+ * @GNUTLS_FIPS140_OP_INITIAL: no previous operation has done
+ * @GNUTLS_FIPS140_OP_APPROVED: the previous operation was FIPS approved
+ * @GNUTLS_FIPS140_OP_NOT_APPROVED: the previous operation was not FIPS approved
+ * @GNUTLS_FIPS140_OP_ERROR: the previous operation caused an error regardless of FIPS
+ *
+ * The FIPS operation state set by the preceding operation.
+ *
+ * There are state transition rules among the enum values:
+ * - When the context is attached to a thread, it will be set to reset
+ * to the %GNUTLS_FIPS140_OP_INITIAL state
+ * - From the %GNUTLS_FIPS140_OP_INITIAL state, the context can
+ * transition to either %GNUTLS_FIPS140_OP_APPROVED,
+ * %GNUTLS_FIPS140_OP_NOT_APPROVED, or %GNUTLS_FIPS140_OP_ERROR
+ * - From the %GNUTLS_FIPS140_OP_APPROVED state, the context can
+ * transition to %GNUTLS_FIPS140_OP_NOT_APPROVED
+ * - All other transitions are prohibited.
+ *
+ * Since: 3.7.3
+ */
+typedef enum {
+ GNUTLS_FIPS140_OP_INITIAL,
+ GNUTLS_FIPS140_OP_APPROVED,
+ GNUTLS_FIPS140_OP_NOT_APPROVED,
+ GNUTLS_FIPS140_OP_ERROR
+} gnutls_fips140_operation_state_t;
+
+gnutls_fips140_operation_state_t
+gnutls_fips140_get_operation_state(gnutls_fips140_context_t context);
+
+int gnutls_fips140_push_context(gnutls_fips140_context_t context);
+int gnutls_fips140_pop_context(void);
+
/* Gnutls error codes. The mapping to a TLS alert is also shown in
* comments.
*/
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index e60f10104a..40a3984cbf 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1370,6 +1370,11 @@ GNUTLS_3_7_3
gnutls_digest_set_secure;
gnutls_protocol_set_enabled;
gnutls_transport_is_ktls_enabled;
+ gnutls_fips140_context_init;
+ gnutls_fips140_context_deinit;
+ gnutls_fips140_get_operation_state;
+ gnutls_fips140_push_context;
+ gnutls_fips140_pop_context;
local:
*;
} GNUTLS_3_7_2;