Coverage Report

Created: 2026-11-12 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/global.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2001-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2015-2016 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
#include "gnutls_int.h"
25
#include "errors.h"
26
#include <libtasn1.h>
27
#include "dh.h"
28
#include "compress.h"
29
#include "random.h"
30
#include <gnutls/pkcs11.h>
31
32
#include "hello_ext.h" /* for _gnutls_hello_ext_init */
33
#include "supplemental.h" /* for _gnutls_supplemental_deinit */
34
#include "locks.h"
35
#include "system.h"
36
#include "accelerated/cryptodev.h"
37
#include "accelerated/afalg.h"
38
#include "accelerated/accelerated.h"
39
#include "fips.h"
40
#include "atfork.h"
41
#include "system-keys.h"
42
#include "str.h"
43
#include "global.h"
44
#ifdef HAVE_LEANCRYPTO
45
#include <leancrypto.h>
46
#endif
47
48
#ifdef ENABLE_PKCS11
49
#include "pkcs11/p11_provider.h"
50
#endif
51
52
#include "audit.h"
53
54
/* Minimum library versions we accept. */
55
4
#define GNUTLS_MIN_LIBTASN1_VERSION "0.3.4"
56
57
#ifdef __sun
58
#pragma fini(lib_deinit)
59
#pragma init(lib_init)
60
#define _CONSTRUCTOR
61
#define _DESTRUCTOR
62
#else
63
#define _CONSTRUCTOR __attribute__((constructor))
64
#define _DESTRUCTOR __attribute__((destructor))
65
#endif
66
67
#ifndef _WIN32
68
int __attribute__((weak)) _gnutls_global_init_skip(void);
69
int _gnutls_global_init_skip(void)
70
4
{
71
4
  return 0;
72
4
}
73
#else
74
inline static int _gnutls_global_init_skip(void)
75
{
76
  return 0;
77
}
78
#endif
79
80
/* created by asn1c */
81
extern const asn1_static_node gnutls_asn1_tab[];
82
extern const asn1_static_node pkix_asn1_tab[];
83
84
static asn1_node _gnutls_pkix1_asn = NULL;
85
static asn1_node _gnutls_gnutls_asn = NULL;
86
87
gnutls_log_func _gnutls_log_func = NULL;
88
gnutls_audit_log_func _gnutls_audit_log_func = NULL;
89
int _gnutls_log_level = 0; /* default log level */
90
91
unsigned int _gnutls_global_version = GNUTLS_VERSION_NUMBER;
92
93
static int _gnutls_global_init(unsigned constructor);
94
static void _gnutls_global_deinit(unsigned destructor);
95
96
static void default_log_func(int level, const char *str)
97
0
{
98
0
  fprintf(stderr, "gnutls[%d]: %s", level, str);
99
0
}
100
101
/**
102
 * gnutls_global_set_log_function:
103
 * @log_func: it's a log function
104
 *
105
 * This is the function where you set the logging function gnutls is
106
 * going to use.  This function only accepts a character array.
107
 * Normally you may not use this function since it is only used for
108
 * debugging purposes.
109
 *
110
 * @gnutls_log_func is of the form,
111
 * void (*gnutls_log_func)( int level, const char*);
112
 **/
113
void gnutls_global_set_log_function(gnutls_log_func log_func)
114
0
{
115
0
  _gnutls_log_func = log_func;
116
0
}
117
118
/**
119
 * gnutls_global_set_audit_log_function:
120
 * @log_func: it is the audit log function
121
 *
122
 * This is the function to set the audit logging function. This
123
 * is a function to report important issues, such as possible
124
 * attacks in the protocol. This is different from gnutls_global_set_log_function()
125
 * because it will report also session-specific events. The session
126
 * parameter will be null if there is no corresponding TLS session.
127
 *
128
 * @gnutls_audit_log_func is of the form,
129
 * void (*gnutls_audit_log_func)( gnutls_session_t, const char*);
130
 *
131
 * Since: 3.0
132
 **/
133
void gnutls_global_set_audit_log_function(gnutls_audit_log_func log_func)
134
0
{
135
0
  _gnutls_audit_log_func = log_func;
136
0
}
137
138
static void gettime_from_time(struct timespec *t)
139
0
{
140
0
  t->tv_sec = gnutls_time(NULL);
141
0
  t->tv_nsec = 0;
142
0
}
143
144
/**
145
 * gnutls_global_set_time_function:
146
 * @time_func: it's the system time function, a gnutls_time_func() callback.
147
 *
148
 * This is the function where you can override the default system time
149
 * function.  The application provided function should behave the same
150
 * as the standard function.
151
 *
152
 * Since: 2.12.0
153
 **/
154
void gnutls_global_set_time_function(gnutls_time_func time_func)
155
0
{
156
0
  gnutls_time = time_func;
157
158
  /* When the time function is overridden, also override the
159
   * gettime function to use the derived value, even if its
160
   * resolution is lower.
161
   */
162
0
  _gnutls_global_set_gettime_function(gettime_from_time);
163
0
}
164
165
/**
166
 * gnutls_global_set_log_level:
167
 * @level: it's an integer from 0 to 99.
168
 *
169
 * This is the function that allows you to set the log level.  The
170
 * level is an integer between 0 and 9.  Higher values mean more
171
 * verbosity. The default value is 0.  Larger values should only be
172
 * used with care, since they may reveal sensitive information.
173
 *
174
 * Use a log level over 10 to enable all debugging options.
175
 **/
176
void gnutls_global_set_log_level(int level)
177
0
{
178
0
  _gnutls_log_level = level;
179
0
}
180
181
/**
182
 * gnutls_global_set_mem_functions:
183
 * @alloc_func: it's the default memory allocation function. Like malloc().
184
 * @secure_alloc_func: This is the memory allocation function that will be used for sensitive data.
185
 * @is_secure_func: a function that returns 0 if the memory given is not secure. May be NULL.
186
 * @realloc_func: A realloc function
187
 * @free_func: The function that frees allocated data. Must accept a NULL pointer.
188
 *
189
 * Deprecated: since 3.3.0 it is no longer possible to replace the internally used 
190
 *  memory allocation functions
191
 *
192
 * This is the function where you set the memory allocation functions
193
 * gnutls is going to use. By default the libc's allocation functions
194
 * (malloc(), free()), are used by gnutls, to allocate both sensitive
195
 * and not sensitive data.  This function is provided to set the
196
 * memory allocation functions to something other than the defaults
197
 *
198
 * This function must be called before gnutls_global_init() is called.
199
 * This function is not thread safe.
200
 **/
201
void gnutls_global_set_mem_functions(gnutls_alloc_function alloc_func,
202
             gnutls_alloc_function secure_alloc_func,
203
             gnutls_is_secure_function is_secure_func,
204
             gnutls_realloc_function realloc_func,
205
             gnutls_free_function free_func)
206
0
{
207
0
  _gnutls_debug_log(
208
0
    "called the deprecated gnutls_global_set_mem_functions()\n");
209
0
}
210
211
asn1_node_const _gnutls_get_gnutls_asn(void)
212
0
{
213
0
  return (asn1_node_const)_gnutls_gnutls_asn;
214
0
}
215
216
asn1_node_const _gnutls_get_pkix(void)
217
0
{
218
0
  return (asn1_node_const)_gnutls_pkix1_asn;
219
0
}
220
221
GNUTLS_STATIC_MUTEX(global_init_mutex);
222
static int _gnutls_init = 0;
223
224
/* cache the return code */
225
static int _gnutls_init_ret = 0;
226
227
/**
228
 * gnutls_global_init:
229
 *
230
 * Since GnuTLS 3.3.0 this function is no longer necessary to be explicitly
231
 * called. To disable the implicit call (in a library constructor) of this
232
 * function set the environment variable %GNUTLS_NO_IMPLICIT_INIT to 1.
233
 *
234
 * This function performs any required precalculations, detects
235
 * the supported CPU capabilities and initializes the underlying
236
 * cryptographic backend. In order to free any resources 
237
 * taken by this call you should gnutls_global_deinit() 
238
 * when gnutls usage is no longer needed.
239
 *
240
 * This function increments a global counter, so that
241
 * gnutls_global_deinit() only releases resources when it has been
242
 * called as many times as gnutls_global_init().  This is useful when
243
 * GnuTLS is used by more than one library in an application.  This
244
 * function can be called many times, but will only do something the
245
 * first time. It is thread safe since GnuTLS 3.3.0.
246
 *
247
 * A subsequent call of this function if the initial has failed will
248
 * return the same error code.
249
 *
250
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
251
 *   otherwise a negative error code is returned.
252
 **/
253
int gnutls_global_init(void)
254
0
{
255
0
  return _gnutls_global_init(0);
256
0
}
257
258
static int _gnutls_global_init(unsigned constructor)
259
4
{
260
4
  int ret = 0, res;
261
4
  int level;
262
4
  const char *e;
263
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
264
  const char *p11_provider_url = NULL;
265
  const char *p11_provider_pin = NULL;
266
#endif
267
268
4
  if (!constructor) {
269
0
    ret = gnutls_static_mutex_lock(&global_init_mutex);
270
0
    if (ret < 0) {
271
0
      return gnutls_assert_val(ret);
272
0
    }
273
0
  }
274
275
4
  _gnutls_init++;
276
4
  if (_gnutls_init > 1) {
277
0
    ret = _gnutls_init_ret;
278
0
    goto out;
279
0
  }
280
281
4
  _gnutls_switch_lib_state(LIB_STATE_INIT);
282
283
4
  e = secure_getenv("GNUTLS_DEBUG_LEVEL");
284
4
  if (e != NULL) {
285
0
    level = atoi(e);
286
0
    gnutls_global_set_log_level(level);
287
0
    if (_gnutls_log_func == NULL)
288
0
      gnutls_global_set_log_function(default_log_func);
289
0
    _gnutls_debug_log("Enabled GnuTLS " VERSION " logging...\n");
290
0
  }
291
292
4
#ifdef HAVE_DCGETTEXT
293
4
  bindtextdomain(PACKAGE, LOCALEDIR);
294
4
#endif
295
296
4
  e = secure_getenv("GNUTLS_BUFFER_RECLAIM");
297
4
  if (e != NULL) {
298
0
    bool reclaiming = e[0] == '1' && e[1] == '\0';
299
0
    _gnutls_debug_log("Using %s buffer allocator...\n",
300
0
          reclaiming ? "reclaiming" : "non-reclaiming");
301
0
    _gnutls_buffer_set_reclaiming(reclaiming);
302
0
  }
303
304
4
  res = gnutls_crypto_init();
305
4
  if (res != 0) {
306
0
    gnutls_assert();
307
0
    ret = GNUTLS_E_CRYPTO_INIT_FAILED;
308
0
    goto out;
309
0
  }
310
311
4
  ret = _gnutls_system_key_init();
312
4
  if (ret != 0) {
313
0
    gnutls_assert();
314
0
  }
315
316
  /* initialize ASN.1 parser
317
   */
318
4
  if (asn1_check_version(GNUTLS_MIN_LIBTASN1_VERSION) == NULL) {
319
0
    gnutls_assert();
320
0
    _gnutls_debug_log("Checking for libtasn1 failed: %s < %s\n",
321
0
          asn1_check_version(NULL),
322
0
          GNUTLS_MIN_LIBTASN1_VERSION);
323
0
    ret = GNUTLS_E_INCOMPATIBLE_LIBTASN1_LIBRARY;
324
0
    goto out;
325
0
  }
326
327
4
  _gnutls_pkix1_asn = NULL;
328
4
  res = asn1_array2tree(pkix_asn1_tab, &_gnutls_pkix1_asn, NULL);
329
4
  if (res != ASN1_SUCCESS) {
330
0
    gnutls_assert();
331
0
    ret = _gnutls_asn2err(res);
332
0
    goto out;
333
0
  }
334
335
4
  res = asn1_array2tree(gnutls_asn1_tab, &_gnutls_gnutls_asn, NULL);
336
4
  if (res != ASN1_SUCCESS) {
337
0
    gnutls_assert();
338
0
    ret = _gnutls_asn2err(res);
339
0
    goto out;
340
0
  }
341
342
  /* Initialize the random generator */
343
4
  ret = _gnutls_rnd_preinit();
344
4
  if (ret < 0) {
345
0
    gnutls_assert();
346
0
    goto out;
347
0
  }
348
349
  /* Initialize the default TLS extensions */
350
4
  ret = _gnutls_hello_ext_init();
351
4
  if (ret < 0) {
352
0
    gnutls_assert();
353
0
    goto out;
354
0
  }
355
356
4
  ret = gnutls_system_global_init();
357
4
  if (ret < 0) {
358
0
    gnutls_assert();
359
0
    goto out;
360
0
  }
361
362
4
#ifndef _WIN32
363
4
  ret = _gnutls_register_fork_handler();
364
4
  if (ret < 0) {
365
0
    gnutls_assert();
366
0
    goto out;
367
0
  }
368
4
#endif
369
370
#ifdef ENABLE_FIPS140
371
  res = _gnutls_fips_mode_enabled();
372
  /* res == 1 -> fips140-2 mode enabled
373
   * res == 2 -> only self checks performed - but no failure
374
   * res == not in fips140 mode
375
   */
376
  if (res != 0) {
377
    _gnutls_debug_log("FIPS140-2 mode: %d\n", res);
378
    _gnutls_priority_update_fips();
379
380
    /* first round of self checks, these are done on the
381
     * nettle algorithms which are used internally */
382
    _gnutls_switch_lib_state(LIB_STATE_SELFTEST);
383
    ret = _gnutls_fips_perform_self_checks1();
384
    if (ret < 0) {
385
      _gnutls_switch_lib_state(LIB_STATE_ERROR);
386
      _gnutls_audit_log(
387
        NULL, "FIPS140-2 self testing part1 failed\n");
388
      if (res != 2) {
389
        gnutls_assert();
390
        goto out;
391
      }
392
    }
393
  }
394
#endif
395
396
4
  _gnutls_register_accel_crypto();
397
4
  _gnutls_cryptodev_init();
398
4
  _gnutls_afalg_init();
399
#ifdef HAVE_LEANCRYPTO
400
  lc_init(0);
401
#endif
402
403
#ifdef ENABLE_FIPS140
404
  /* These self tests are performed on the overridden algorithms
405
   * (e.g., AESNI overridden AES). They are after _gnutls_register_accel_crypto()
406
   * intentionally */
407
  if (res != 0) {
408
    _gnutls_switch_lib_state(LIB_STATE_SELFTEST);
409
    ret = _gnutls_fips_perform_self_checks2();
410
    if (ret < 0) {
411
      _gnutls_switch_lib_state(LIB_STATE_ERROR);
412
      _gnutls_audit_log(
413
        NULL, "FIPS140-2 self testing part 2 failed\n");
414
      if (res != 2) {
415
        gnutls_assert();
416
        goto out;
417
      }
418
    }
419
    _gnutls_fips_mode_reset_zombie();
420
  }
421
#endif
422
423
4
  _gnutls_prepare_to_load_system_priorities();
424
425
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
426
  p11_provider_url = _gnutls_config_get_p11_provider_url();
427
  p11_provider_pin = _gnutls_config_get_p11_provider_pin();
428
429
  if (res == 1 && p11_provider_url != NULL) {
430
    ret = _p11_provider_init(p11_provider_url,
431
           (const uint8_t *)p11_provider_pin,
432
           strlen(p11_provider_pin));
433
    if (ret < 0) {
434
      gnutls_assert();
435
      goto out;
436
    }
437
  }
438
#endif
439
440
4
  _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
441
442
4
  ret = 0;
443
444
4
out:
445
4
  _gnutls_init_ret = ret;
446
4
  if (!constructor) {
447
0
    (void)gnutls_static_mutex_unlock(&global_init_mutex);
448
0
  }
449
4
  return ret;
450
4
}
451
452
static void _gnutls_global_deinit(unsigned destructor)
453
0
{
454
0
  if (!destructor) {
455
0
    if (gnutls_static_mutex_lock(&global_init_mutex) < 0) {
456
0
      return;
457
0
    }
458
0
  }
459
460
0
  if (_gnutls_init == 1) {
461
0
    _gnutls_init = 0;
462
0
    if (_gnutls_init_ret < 0) {
463
      /* only deinitialize if gnutls_global_init() has
464
       * succeeded */
465
0
      gnutls_assert();
466
0
      goto fail;
467
0
    }
468
469
0
    _gnutls_system_key_deinit();
470
0
    gnutls_crypto_deinit();
471
0
    _gnutls_compression_deinit();
472
0
    _gnutls_rnd_deinit();
473
0
    _gnutls_hello_ext_deinit();
474
0
    asn1_delete_structure(&_gnutls_gnutls_asn);
475
0
    asn1_delete_structure(&_gnutls_pkix1_asn);
476
477
0
    _gnutls_crypto_deregister();
478
0
    gnutls_system_global_deinit();
479
0
    _gnutls_cryptodev_deinit();
480
481
0
    _gnutls_supplemental_deinit();
482
0
    _gnutls_unload_system_priorities();
483
484
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
485
    _p11_provider_deinit();
486
#endif
487
488
#ifdef ENABLE_PKCS11
489
    /* Do not try to deinitialize the PKCS #11 libraries
490
     * from the destructor. If we do and the PKCS #11 modules
491
     * are already being unloaded, we may crash.
492
     */
493
    if (destructor == 0) {
494
      gnutls_pkcs11_deinit();
495
    }
496
#endif
497
#ifdef HAVE_TROUSERS
498
    _gnutls_tpm_global_deinit();
499
#endif
500
#ifdef HAVE_TPM2
501
    _gnutls_tpm2_deinit();
502
#endif
503
504
0
    _gnutls_nss_keylog_deinit();
505
0
  } else {
506
0
    if (_gnutls_init > 0)
507
0
      _gnutls_init--;
508
0
  }
509
510
0
fail:
511
0
  if (!destructor) {
512
0
    (void)gnutls_static_mutex_unlock(&global_init_mutex);
513
0
  }
514
0
}
515
516
/**
517
 * gnutls_global_deinit:
518
 *
519
 * This function deinitializes the global data, that were initialized
520
 * using gnutls_global_init().
521
 *
522
 * Since GnuTLS 3.3.0 this function is no longer necessary to be explicitly
523
 * called. GnuTLS will automatically deinitialize on library destructor. See
524
 * gnutls_global_init() for disabling the implicit initialization/deinitialization.
525
 *
526
 **/
527
void gnutls_global_deinit(void)
528
0
{
529
0
  _gnutls_global_deinit(0);
530
0
}
531
532
/**
533
 * gnutls_check_version:
534
 * @req_version: version string to compare with, or %NULL.
535
 *
536
 * Check the GnuTLS Library version against the provided string.
537
 * See %GNUTLS_VERSION for a suitable @req_version string.
538
 *
539
 * See also gnutls_check_version_numeric(), which provides this
540
 * functionality as a macro.
541
 *
542
 * Returns: Check that the version of the library is at
543
 *   minimum the one given as a string in @req_version and return the
544
 *   actual version string of the library; return %NULL if the
545
 *   condition is not met.  If %NULL is passed to this function no
546
 *   check is done and only the version string is returned.
547
 **/
548
const char *gnutls_check_version(const char *req_version)
549
0
{
550
0
  if (!req_version || strverscmp(req_version, VERSION) <= 0)
551
0
    return VERSION;
552
553
0
  return NULL;
554
0
}
555
556
static void _CONSTRUCTOR lib_init(void)
557
4
{
558
4
  int ret;
559
4
  const char *e;
560
561
4
  if (_gnutls_global_init_skip() != 0)
562
0
    return;
563
564
4
  e = secure_getenv("GNUTLS_NO_IMPLICIT_INIT");
565
4
  if (e != NULL) {
566
0
    ret = atoi(e);
567
0
    if (ret == 1)
568
0
      return;
569
0
  }
570
571
4
  e = secure_getenv("GNUTLS_NO_EXPLICIT_INIT");
572
4
  if (e != NULL) {
573
0
    _gnutls_debug_log(
574
0
      "GNUTLS_NO_EXPLICIT_INIT is deprecated; use GNUTLS_NO_IMPLICIT_INIT\n");
575
0
    ret = atoi(e);
576
0
    if (ret == 1)
577
0
      return;
578
0
  }
579
580
4
  ret = _gnutls_global_init(1);
581
4
  if (ret < 0) {
582
0
    fprintf(stderr, "Error in GnuTLS initialization: %s\n",
583
0
      gnutls_strerror(ret));
584
0
    _gnutls_switch_lib_state(LIB_STATE_ERROR);
585
0
  }
586
4
}
587
588
static void _DESTRUCTOR lib_deinit(void)
589
0
{
590
0
  int ret;
591
0
  const char *e;
592
593
0
  if (_gnutls_global_init_skip() != 0)
594
0
    return;
595
596
0
  e = secure_getenv("GNUTLS_NO_IMPLICIT_INIT");
597
0
  if (e != NULL) {
598
0
    ret = atoi(e);
599
0
    if (ret == 1)
600
0
      return;
601
0
  }
602
603
0
  e = secure_getenv("GNUTLS_NO_EXPLICIT_INIT");
604
0
  if (e != NULL) {
605
0
    _gnutls_debug_log(
606
0
      "GNUTLS_NO_EXPLICIT_INIT is deprecated; use GNUTLS_NO_IMPLICIT_INIT\n");
607
0
    ret = atoi(e);
608
0
    if (ret == 1)
609
0
      return;
610
0
  }
611
612
0
  _gnutls_global_deinit(1);
613
0
}
614
615
static const struct gnutls_library_config_st _gnutls_library_config[] = {
616
#ifdef FIPS_MODULE_NAME
617
  { "fips-module-name", FIPS_MODULE_NAME },
618
#endif
619
#ifdef FIPS_MODULE_VERSION
620
  { "fips-module-version", FIPS_MODULE_VERSION },
621
#endif
622
#ifdef GNUTLS_LIBRARY_SONAME
623
  { "libgnutls-soname", GNUTLS_LIBRARY_SONAME },
624
#endif
625
#ifdef NETTLE_LIBRARY_SONAME
626
  { "libnettle-soname", NETTLE_LIBRARY_SONAME },
627
#endif
628
#ifdef HOGWEED_LIBRARY_SONAME
629
  { "libhogweed-soname", HOGWEED_LIBRARY_SONAME },
630
#endif
631
#ifdef GMP_LIBRARY_SONAME
632
  { "libgmp-soname", GMP_LIBRARY_SONAME },
633
#endif
634
  { "hardware-features", HW_FEATURES },
635
  { "tls-features", TLS_FEATURES },
636
#ifdef DEFAULT_TRUST_STORE_PKCS11
637
  { "default-trust-store-pkcs11", DEFAULT_TRUST_STORE_PKCS11 },
638
#endif
639
#ifdef DEFAULT_TRUST_STORE_DIR
640
  { "default-trust-store-dir", DEFAULT_TRUST_STORE_DIR },
641
#endif
642
#ifdef DEFAULT_TRUST_STORE_FILE
643
  { "default-trust-store-file", DEFAULT_TRUST_STORE_FILE },
644
#endif
645
  { "default-system-config", SYSTEM_PRIORITY_FILE },
646
  { NULL, NULL }
647
};
648
649
/**
650
 * gnutls_get_library_config:
651
 *
652
 * Returns the library configuration as key value pairs.
653
 * Currently defined keys are:
654
 *
655
 *  - fips-module-name: the name of the FIPS140 module
656
 *
657
 *  - fips-module-version: the version of the FIPS140 module
658
 *
659
 *  - libgnutls-soname: the SONAME of the library itself
660
 *
661
 *  - libnettle-soname: the library SONAME of linked libnettle
662
 *
663
 *  - libhogweed-soname: the library SONAME of linked libhogweed
664
 *
665
 *  - libgmp-soname: the library SONAME of linked libgmp
666
 *
667
 *  - hardware-features: enabled hardware support features
668
 *
669
 *  - tls-features: enabled TLS protocol features
670
 *
671
 * Returns: a NUL-terminated %gnutls_library_config_st array
672
 *
673
 * Since: 3.7.3
674
 */
675
const gnutls_library_config_st *gnutls_get_library_config(void)
676
0
{
677
0
  return _gnutls_library_config;
678
0
}