Coverage Report

Created: 2024-02-25 06:27

/src/gnutls/lib/fips.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2013 Red Hat
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
#include "gnutls_int.h"
23
#include <gnutls/gnutls.h>
24
#include <gnutls/crypto.h>
25
#include <unistd.h>
26
#include "dirname.h"
27
#include "errors.h"
28
#include "file.h"
29
#include "inih/ini.h"
30
#include "str.h"
31
#include "fips.h"
32
#include <gnutls/self-test.h>
33
#include <stdio.h>
34
#include "extras/hex.h"
35
#include "random.h"
36
37
#include "gthreads.h"
38
39
#ifdef HAVE_DL_ITERATE_PHDR
40
#include <link.h>
41
#endif
42
43
unsigned int _gnutls_lib_state = LIB_STATE_POWERON;
44
45
struct gnutls_fips140_context_st {
46
  gnutls_fips140_operation_state_t state;
47
  struct gnutls_fips140_context_st *next;
48
};
49
50
#ifdef ENABLE_FIPS140
51
52
#include <dlfcn.h>
53
54
#define FIPS_KERNEL_FILE "/proc/sys/crypto/fips_enabled"
55
#define FIPS_SYSTEM_FILE "/etc/system-fips"
56
57
/* We provide a per-thread FIPS-mode so that an application
58
 * can use gnutls_fips140_set_mode() to override a specific
59
 * operation on a thread */
60
static gnutls_fips_mode_t _global_fips_mode = -1;
61
static _Thread_local gnutls_fips_mode_t _tfips_mode = -1;
62
63
static _Thread_local gnutls_fips140_context_t _tfips_context = NULL;
64
65
static int _skip_integrity_checks = 0;
66
67
/* Returns:
68
 * a gnutls_fips_mode_t value
69
 */
70
unsigned _gnutls_fips_mode_enabled(void)
71
{
72
  unsigned f1p = 0, f2p;
73
  FILE *fd;
74
  const char *p;
75
  unsigned ret;
76
77
  /* We initialize this threads' mode, and
78
   * the global mode if not already initialized.
79
   * When the global mode is initialized, then
80
   * the thread mode is copied from it. As this
81
   * is called on library initialization, the
82
   * _global_fips_mode is always set during app run.
83
   */
84
  if (_tfips_mode != (gnutls_fips_mode_t)-1)
85
    return _tfips_mode;
86
87
  if (_global_fips_mode != (gnutls_fips_mode_t)-1) {
88
    return _global_fips_mode;
89
  }
90
91
  p = secure_getenv("GNUTLS_SKIP_FIPS_INTEGRITY_CHECKS");
92
  if (p && p[0] == '1') {
93
    _skip_integrity_checks = 1;
94
  }
95
96
  p = secure_getenv("GNUTLS_FORCE_FIPS_MODE");
97
  if (p) {
98
    if (p[0] == '1')
99
      ret = GNUTLS_FIPS140_STRICT;
100
    else if (p[0] == '2')
101
      ret = GNUTLS_FIPS140_SELFTESTS;
102
    else if (p[0] == '3')
103
      ret = GNUTLS_FIPS140_LAX;
104
    else if (p[0] == '4')
105
      ret = GNUTLS_FIPS140_LOG;
106
    else
107
      ret = GNUTLS_FIPS140_DISABLED;
108
109
    goto exit;
110
  }
111
112
  fd = fopen(FIPS_KERNEL_FILE, "re");
113
  if (fd != NULL) {
114
    f1p = fgetc(fd);
115
    fclose(fd);
116
117
    if (f1p == '1')
118
      f1p = 1;
119
    else
120
      f1p = 0;
121
  }
122
123
  if (f1p != 0) {
124
    _gnutls_debug_log("FIPS140-2 mode enabled\n");
125
    ret = GNUTLS_FIPS140_STRICT;
126
    goto exit;
127
  }
128
129
  f2p = !access(FIPS_SYSTEM_FILE, F_OK);
130
  if (f2p != 0) {
131
    /* a funny state where self tests are performed
132
     * and ignored */
133
    _gnutls_debug_log("FIPS140-2 ZOMBIE mode enabled\n");
134
    ret = GNUTLS_FIPS140_SELFTESTS;
135
    goto exit;
136
  }
137
138
  ret = GNUTLS_FIPS140_DISABLED;
139
  goto exit;
140
141
exit:
142
  _global_fips_mode = ret;
143
  return ret;
144
}
145
146
/* This _fips_mode == 2 is a strange mode where checks are being
147
 * performed, but its output is ignored. */
148
void _gnutls_fips_mode_reset_zombie(void)
149
{
150
  if (_global_fips_mode == GNUTLS_FIPS140_SELFTESTS) {
151
    _global_fips_mode = GNUTLS_FIPS140_DISABLED;
152
  }
153
}
154
155
/* These only works with the platform where SONAME is part of the ABI.
156
 * For example, *_SONAME will be set to "none" on Windows platforms. */
157
#define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME
158
#define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME
159
#define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME
160
161
/* GMP can be statically linked. */
162
#ifdef GMP_LIBRARY_SONAME
163
#define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME
164
#endif
165
166
#define HMAC_SIZE 32
167
#define HMAC_ALGO GNUTLS_MAC_SHA256
168
#define HMAC_FORMAT_VERSION 1
169
170
struct hmac_entry {
171
  char path[GNUTLS_PATH_MAX];
172
  uint8_t hmac[HMAC_SIZE];
173
};
174
175
struct hmac_file {
176
  int version;
177
  struct hmac_entry gnutls;
178
  struct hmac_entry nettle;
179
  struct hmac_entry hogweed;
180
#ifdef GMP_LIBRARY_SONAME
181
  struct hmac_entry gmp;
182
#endif
183
};
184
185
struct lib_paths {
186
  char gnutls[GNUTLS_PATH_MAX];
187
  char nettle[GNUTLS_PATH_MAX];
188
  char hogweed[GNUTLS_PATH_MAX];
189
#ifdef GMP_LIBRARY_SONAME
190
  char gmp[GNUTLS_PATH_MAX];
191
#endif
192
};
193
194
/*
195
 * get_hmac:
196
 * @dest: buffer for the hex value
197
 * @value: hmac value
198
 *
199
 * Parses hmac data and copies hex value into dest.
200
 * dest must point to at least HMAC_SIZE amount of memory
201
 *
202
 * Returns: 0 on success, a negative error code otherwise
203
 */
204
static int get_hmac(uint8_t *dest, const char *value)
205
{
206
  int ret;
207
  size_t hmac_size;
208
  gnutls_datum_t data;
209
210
  data.size = strlen(value);
211
  data.data = (unsigned char *)value;
212
213
  hmac_size = HMAC_SIZE;
214
  ret = gnutls_hex_decode(&data, dest, &hmac_size);
215
  if (ret < 0)
216
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
217
218
  if (hmac_size != HMAC_SIZE)
219
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
220
221
  return 0;
222
}
223
224
static int lib_handler(struct hmac_entry *entry, const char *section,
225
           const char *name, const char *value)
226
{
227
  if (!strcmp(name, "path")) {
228
    snprintf(entry->path, GNUTLS_PATH_MAX, "%s", value);
229
  } else if (!strcmp(name, "hmac")) {
230
    if (get_hmac(entry->hmac, value) < 0)
231
      return 0;
232
  } else {
233
    return 0;
234
  }
235
  return 1;
236
}
237
238
static int handler(void *user, const char *section, const char *name,
239
       const char *value)
240
{
241
  struct hmac_file *p = (struct hmac_file *)user;
242
243
  if (!strcmp(section, "global")) {
244
    if (!strcmp(name, "format-version")) {
245
      p->version = strtol(value, NULL, 10);
246
    } else {
247
      return 0;
248
    }
249
  } else if (!strcmp(section, GNUTLS_LIBRARY_NAME)) {
250
    return lib_handler(&p->gnutls, section, name, value);
251
  } else if (!strcmp(section, NETTLE_LIBRARY_NAME)) {
252
    return lib_handler(&p->nettle, section, name, value);
253
  } else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) {
254
    return lib_handler(&p->hogweed, section, name, value);
255
#ifdef GMP_LIBRARY_SONAME
256
  } else if (!strcmp(section, GMP_LIBRARY_NAME)) {
257
    return lib_handler(&p->gmp, section, name, value);
258
#endif
259
  } else {
260
    return 0;
261
  }
262
  return 1;
263
}
264
265
/*
266
 * get_hmac_path:
267
 * @mac_file: buffer where the hmac file path will be written to
268
 * @mac_file_size: size of the mac_file buffer
269
 * @gnutls_path: path to the gnutls library, used to deduce hmac file path
270
 * 
271
 * Deduces hmac file path from the gnutls library path.
272
 *
273
 * Returns: 0 on success, a negative error code otherwise
274
 */
275
static int get_hmac_path(char *mac_file, size_t mac_file_size,
276
       const char *gnutls_path)
277
{
278
  int ret;
279
  char *p;
280
281
  p = strrchr(gnutls_path, '/');
282
283
  if (p == NULL)
284
    ret = snprintf(mac_file, mac_file_size, ".%s.hmac",
285
             gnutls_path);
286
  else
287
    ret = snprintf(mac_file, mac_file_size, "%.*s/.%s.hmac",
288
             (int)(p - gnutls_path), gnutls_path, p + 1);
289
290
  if ((size_t)ret >= mac_file_size)
291
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
292
293
  ret = _gnutls_file_exists(mac_file);
294
  if (ret == 0)
295
    return GNUTLS_E_SUCCESS;
296
297
  if (p == NULL)
298
    ret = snprintf(mac_file, mac_file_size, "fipscheck/.%s.hmac",
299
             gnutls_path);
300
  else
301
    ret = snprintf(mac_file, mac_file_size,
302
             "%.*s/fipscheck/.%s.hmac",
303
             (int)(p - gnutls_path), gnutls_path, p + 1);
304
305
  if ((size_t)ret >= mac_file_size)
306
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
307
308
  ret = _gnutls_file_exists(mac_file);
309
  if (ret == 0)
310
    return GNUTLS_E_SUCCESS;
311
312
  return GNUTLS_E_FILE_ERROR;
313
}
314
315
/*
316
 * load_hmac_file:
317
 * @hmac_file: hmac file structure
318
 * @hmac_path: path to the hmac file
319
 *
320
 * Loads the hmac file into the hmac file structure.
321
 *
322
 * Returns: 0 on success, a negative error code otherwise
323
 */
324
static int load_hmac_file(struct hmac_file *hmac_file, const char *hmac_path)
325
{
326
  int ret;
327
  FILE *stream;
328
329
  stream = fopen(hmac_path, "r");
330
  if (stream == NULL)
331
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
332
333
  gnutls_memset(hmac_file, 0, sizeof(*hmac_file));
334
  ret = ini_parse_file(stream, handler, hmac_file);
335
  fclose(stream);
336
  if (ret < 0)
337
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
338
339
  if (hmac_file->version != HMAC_FORMAT_VERSION)
340
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
341
342
  return 0;
343
}
344
345
/*
346
 * check_lib_hmac:
347
 * @entry: hmac file entry
348
 * @path: path to the library which hmac should be compared
349
 *
350
 * Verify that HMAC from hmac file entry matches HMAC of given library.
351
 *
352
 * Returns: 0 on successful HMAC verification, a negative error code otherwise
353
 */
354
static int check_lib_hmac(struct hmac_entry *entry, const char *path)
355
{
356
  int ret;
357
  unsigned prev;
358
  uint8_t hmac[HMAC_SIZE];
359
  gnutls_datum_t data;
360
361
  _gnutls_debug_log("Loading: %s\n", path);
362
  ret = gnutls_load_file(path, &data);
363
  if (ret < 0) {
364
    _gnutls_debug_log("Could not load %s: %s\n", path,
365
          gnutls_strerror(ret));
366
    return gnutls_assert_val(ret);
367
  }
368
369
  prev = _gnutls_get_lib_state();
370
  _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
371
  ret = gnutls_hmac_fast(HMAC_ALGO, FIPS_KEY, sizeof(FIPS_KEY) - 1,
372
             data.data, data.size, hmac);
373
  _gnutls_switch_lib_state(prev);
374
375
  gnutls_free(data.data);
376
  if (ret < 0) {
377
    _gnutls_debug_log("Could not calculate HMAC for %s: %s\n", path,
378
          gnutls_strerror(ret));
379
    return gnutls_assert_val(ret);
380
  }
381
382
  if (gnutls_memcmp(entry->hmac, hmac, HMAC_SIZE)) {
383
    _gnutls_debug_log("Calculated MAC for %s does not match\n",
384
          path);
385
    gnutls_memset(hmac, 0, HMAC_SIZE);
386
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
387
  }
388
  _gnutls_debug_log("Successfully verified MAC for %s\n", path);
389
390
  gnutls_memset(hmac, 0, HMAC_SIZE);
391
  return 0;
392
}
393
394
#ifdef HAVE_DL_ITERATE_PHDR
395
396
static int callback(struct dl_phdr_info *info, size_t size, void *data)
397
{
398
  const char *path = info->dlpi_name;
399
  const char *soname = last_component(path);
400
  struct lib_paths *paths = (struct lib_paths *)data;
401
402
  if (!strcmp(soname, GNUTLS_LIBRARY_SONAME))
403
    _gnutls_str_cpy(paths->gnutls, GNUTLS_PATH_MAX, path);
404
  else if (!strcmp(soname, NETTLE_LIBRARY_SONAME))
405
    _gnutls_str_cpy(paths->nettle, GNUTLS_PATH_MAX, path);
406
  else if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
407
    _gnutls_str_cpy(paths->hogweed, GNUTLS_PATH_MAX, path);
408
#ifdef GMP_LIBRARY_SONAME
409
  else if (!strcmp(soname, GMP_LIBRARY_SONAME))
410
    _gnutls_str_cpy(paths->gmp, GNUTLS_PATH_MAX, path);
411
#endif
412
  return 0;
413
}
414
415
static int load_lib_paths(struct lib_paths *paths)
416
{
417
  memset(paths, 0, sizeof(*paths));
418
  dl_iterate_phdr(callback, paths);
419
420
  if (paths->gnutls[0] == '\0') {
421
    _gnutls_debug_log("Gnutls library path was not found\n");
422
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
423
  }
424
  if (paths->nettle[0] == '\0') {
425
    _gnutls_debug_log("Nettle library path was not found\n");
426
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
427
  }
428
  if (paths->hogweed[0] == '\0') {
429
    _gnutls_debug_log("Hogweed library path was not found\n");
430
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
431
  }
432
#ifdef GMP_LIBRARY_SONAME
433
  if (paths->gmp[0] == '\0') {
434
    _gnutls_debug_log("Gmp library path was not found\n");
435
    return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
436
  }
437
#endif
438
439
  return GNUTLS_E_SUCCESS;
440
}
441
442
#else
443
444
static int load_lib_paths(struct lib_paths *paths)
445
{
446
  (void)paths;
447
  _gnutls_debug_log("Function dl_iterate_phdr is missing\n");
448
  return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
449
}
450
451
#endif /* HAVE_DL_ITERATE_PHDR */
452
453
static int check_binary_integrity(void)
454
{
455
  int ret;
456
  struct lib_paths paths;
457
  struct hmac_file hmac;
458
  char hmac_path[GNUTLS_PATH_MAX];
459
460
  ret = load_lib_paths(&paths);
461
  if (ret < 0) {
462
    _gnutls_debug_log("Could not load library paths: %s\n",
463
          gnutls_strerror(ret));
464
    return ret;
465
  }
466
467
  ret = get_hmac_path(hmac_path, sizeof(hmac_path), paths.gnutls);
468
  if (ret < 0) {
469
    _gnutls_debug_log("Could not get hmac file path: %s\n",
470
          gnutls_strerror(ret));
471
    return ret;
472
  }
473
474
  ret = load_hmac_file(&hmac, hmac_path);
475
  if (ret < 0) {
476
    _gnutls_debug_log("Could not load hmac file: %s\n",
477
          gnutls_strerror(ret));
478
    return ret;
479
  }
480
481
  ret = check_lib_hmac(&hmac.gnutls, paths.gnutls);
482
  if (ret < 0)
483
    return ret;
484
  ret = check_lib_hmac(&hmac.nettle, paths.nettle);
485
  if (ret < 0)
486
    return ret;
487
  ret = check_lib_hmac(&hmac.hogweed, paths.hogweed);
488
  if (ret < 0)
489
    return ret;
490
#ifdef GMP_LIBRARY_SONAME
491
  ret = check_lib_hmac(&hmac.gmp, paths.gmp);
492
  if (ret < 0)
493
    return ret;
494
#endif
495
496
  return 0;
497
}
498
499
int _gnutls_fips_perform_self_checks1(void)
500
{
501
  int ret;
502
503
  /* Tests the FIPS algorithms used by nettle internally.
504
   * In our case we test AES-CBC since nettle's AES is used by
505
   * the DRBG-AES.
506
   */
507
508
  /* ciphers - one test per cipher */
509
  ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
510
  if (ret < 0) {
511
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
512
  }
513
514
  return 0;
515
}
516
517
int _gnutls_fips_perform_self_checks2(void)
518
{
519
  int ret;
520
521
  /* Tests the FIPS algorithms */
522
523
  /* ciphers - one test per cipher */
524
  ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC);
525
  if (ret < 0) {
526
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
527
  }
528
529
  ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
530
  if (ret < 0) {
531
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
532
  }
533
534
  ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_XTS);
535
  if (ret < 0) {
536
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
537
  }
538
539
  ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CFB8);
540
  if (ret < 0) {
541
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
542
  }
543
544
  /* Digest tests */
545
  ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_224);
546
  if (ret < 0) {
547
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
548
  }
549
550
  ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_256);
551
  if (ret < 0) {
552
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
553
  }
554
555
  ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_384);
556
  if (ret < 0) {
557
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
558
  }
559
560
  ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_512);
561
  if (ret < 0) {
562
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
563
  }
564
565
  /* MAC (includes message digest test) */
566
  ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA1);
567
  if (ret < 0) {
568
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
569
  }
570
571
  ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA224);
572
  if (ret < 0) {
573
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
574
  }
575
576
  ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA256);
577
  if (ret < 0) {
578
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
579
  }
580
581
  ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA384);
582
  if (ret < 0) {
583
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
584
  }
585
586
  ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA512);
587
  if (ret < 0) {
588
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
589
  }
590
591
  ret = gnutls_mac_self_test(0, GNUTLS_MAC_AES_CMAC_256);
592
  if (ret < 0) {
593
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
594
  }
595
596
  /* PK */
597
  ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA);
598
  if (ret < 0) {
599
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
600
  }
601
602
  ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
603
  if (ret < 0) {
604
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
605
  }
606
607
  ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
608
  if (ret < 0) {
609
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
610
  }
611
612
  ret = gnutls_pk_self_test(0, GNUTLS_PK_DH);
613
  if (ret < 0) {
614
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
615
  }
616
617
  /* HKDF */
618
  ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256);
619
  if (ret < 0) {
620
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
621
  }
622
623
  /* PBKDF2 */
624
  ret = gnutls_pbkdf2_self_test(0, GNUTLS_MAC_SHA256);
625
  if (ret < 0) {
626
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
627
  }
628
629
  /* TLS-PRF */
630
  ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256);
631
  if (ret < 0) {
632
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
633
  }
634
635
  if (_gnutls_rnd_ops.self_test == NULL) {
636
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
637
  }
638
639
  /* this does not require rng initialization */
640
  ret = _gnutls_rnd_ops.self_test();
641
  if (ret < 0) {
642
    return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
643
  }
644
645
  if (_skip_integrity_checks == 0) {
646
    ret = check_binary_integrity();
647
    if (ret < 0) {
648
      return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
649
    }
650
  }
651
652
  return 0;
653
}
654
#endif
655
656
/**
657
 * gnutls_fips140_mode_enabled:
658
 *
659
 * Checks whether this library is in FIPS140 mode. The returned
660
 * value corresponds to the library mode as set with
661
 * gnutls_fips140_set_mode().
662
 *
663
 * If gnutls_fips140_set_mode() was called with %GNUTLS_FIPS140_SET_MODE_THREAD
664
 * then this function will return the current thread's FIPS140 mode, otherwise
665
 * the global value is returned.
666
 *
667
 * Returns: return non-zero if true or zero if false.
668
 *
669
 * Since: 3.3.0
670
 **/
671
unsigned gnutls_fips140_mode_enabled(void)
672
0
{
673
#ifdef ENABLE_FIPS140
674
  unsigned ret = _gnutls_fips_mode_enabled();
675
676
  if (ret > GNUTLS_FIPS140_DISABLED) {
677
    /* If the previous run of selftests has failed, return as if
678
     * the FIPS mode is disabled. We could use HAVE_LIB_ERROR, if
679
     * we can assume that all the selftests run atomically from
680
     * the ELF constructor.
681
     */
682
    if (_gnutls_get_lib_state() == LIB_STATE_ERROR)
683
      return 0;
684
685
    return ret;
686
  }
687
#endif
688
0
  return 0;
689
0
}
690
691
/**
692
 * gnutls_fips140_set_mode:
693
 * @mode: the FIPS140-2 mode to switch to
694
 * @flags: should be zero or %GNUTLS_FIPS140_SET_MODE_THREAD
695
 *
696
 * That function is not thread-safe when changing the mode with no flags
697
 * (globally), and should be called prior to creating any threads. Its
698
 * behavior with no flags after threads are created is undefined.
699
 *
700
 * When the flag %GNUTLS_FIPS140_SET_MODE_THREAD is specified
701
 * then this call will change the FIPS140-2 mode for this particular
702
 * thread and not for the whole process. That way an application
703
 * can utilize this function to set and reset mode for specific
704
 * operations.
705
 *
706
 * This function never fails but will be a no-op if used when
707
 * the library is not in FIPS140-2 mode. When asked to switch to unknown
708
 * values for @mode or to %GNUTLS_FIPS140_SELFTESTS mode, the library
709
 * switches to %GNUTLS_FIPS140_STRICT mode.
710
 *
711
 * Since: 3.6.2
712
 **/
713
void gnutls_fips140_set_mode(gnutls_fips_mode_t mode, unsigned flags)
714
0
{
715
#ifdef ENABLE_FIPS140
716
  gnutls_fips_mode_t prev = _gnutls_fips_mode_enabled();
717
  if (prev == GNUTLS_FIPS140_DISABLED ||
718
      prev == GNUTLS_FIPS140_SELFTESTS) {
719
    /* we need to run self-tests first to be in FIPS140-2 mode */
720
    _gnutls_audit_log(
721
      NULL,
722
      "The library should be initialized in FIPS140-2 mode to do that operation\n");
723
    return;
724
  }
725
726
  switch (mode) {
727
  case GNUTLS_FIPS140_STRICT:
728
  case GNUTLS_FIPS140_LAX:
729
  case GNUTLS_FIPS140_LOG:
730
  case GNUTLS_FIPS140_DISABLED:
731
    break;
732
  case GNUTLS_FIPS140_SELFTESTS:
733
    _gnutls_audit_log(
734
      NULL,
735
      "Cannot switch library to FIPS140-2 self-tests mode; defaulting to strict\n");
736
    mode = GNUTLS_FIPS140_STRICT;
737
    break;
738
  default:
739
    _gnutls_audit_log(
740
      NULL,
741
      "Cannot switch library to mode %u; defaulting to strict\n",
742
      (unsigned)mode);
743
    mode = GNUTLS_FIPS140_STRICT;
744
    break;
745
  }
746
747
  if (flags & GNUTLS_FIPS140_SET_MODE_THREAD)
748
    _tfips_mode = mode;
749
  else {
750
    _global_fips_mode = mode;
751
    _tfips_mode = -1;
752
  }
753
#endif
754
0
}
755
756
void _gnutls_lib_simulate_error(void)
757
0
{
758
0
  _gnutls_switch_lib_state(LIB_STATE_ERROR);
759
0
}
760
761
void _gnutls_lib_force_operational(void)
762
0
{
763
0
  _gnutls_switch_lib_state(LIB_STATE_OPERATIONAL);
764
0
}
765
766
/**
767
 * gnutls_fips140_context_init:
768
 * @context: location to store @gnutls_fips140_context_t
769
 *
770
 * Create and initialize the FIPS context object.
771
 *
772
 * Returns: 0 upon success, a negative error code otherwise
773
 *
774
 * Since: 3.7.3
775
 */
776
int gnutls_fips140_context_init(gnutls_fips140_context_t *context)
777
0
{
778
0
  *context = gnutls_malloc(sizeof(struct gnutls_fips140_context_st));
779
0
  if (!*context) {
780
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
781
0
  }
782
0
  (*context)->state = GNUTLS_FIPS140_OP_INITIAL;
783
0
  return 0;
784
0
}
785
786
/**
787
 * gnutls_fips140_context_deinit:
788
 * @context: a #gnutls_fips140_context_t
789
 *
790
 * Uninitialize and release the FIPS context @context.
791
 *
792
 * Since: 3.7.3
793
 */
794
void gnutls_fips140_context_deinit(gnutls_fips140_context_t context)
795
0
{
796
0
  gnutls_free(context);
797
0
}
798
799
/**
800
 * gnutls_fips140_get_operation_state:
801
 * @context: a #gnutls_fips140_context_t
802
 *
803
 * Get the previous operation state of @context in terms of FIPS.
804
 *
805
 * Returns: a #gnutls_fips140_operation_state_t
806
 *
807
 * Since: 3.7.3
808
 */
809
gnutls_fips140_operation_state_t
810
gnutls_fips140_get_operation_state(gnutls_fips140_context_t context)
811
0
{
812
0
  return context->state;
813
0
}
814
815
/**
816
 * gnutls_fips140_push_context:
817
 * @context: a #gnutls_fips140_context_t
818
 *
819
 * Associate the FIPS @context to the current thread, diverting the
820
 * currently active context. If a cryptographic operation is ongoing
821
 * in the current thread, e.g., gnutls_aead_cipher_init() is called
822
 * but gnutls_aead_cipher_deinit() is not yet called, it returns an
823
 * error %GNUTLS_E_INVALID_REQUEST.
824
 *
825
 * The operation state of @context will be reset to
826
 * %GNUTLS_FIPS140_OP_INITIAL.
827
 *
828
 * This function is no-op if FIPS140 is not compiled in nor enabled
829
 * at run-time.
830
 *
831
 * Returns: 0 upon success, a negative error code otherwise
832
 *
833
 * Since: 3.7.3
834
 */
835
int gnutls_fips140_push_context(gnutls_fips140_context_t context)
836
0
{
837
#ifdef ENABLE_FIPS140
838
  if (_gnutls_fips_mode_enabled() != GNUTLS_FIPS140_DISABLED) {
839
    context->next = _tfips_context;
840
    _tfips_context = context;
841
842
    context->state = GNUTLS_FIPS140_OP_INITIAL;
843
  }
844
  return 0;
845
#else
846
0
  return GNUTLS_E_INVALID_REQUEST;
847
0
#endif
848
0
}
849
850
/**
851
 * gnutls_fips140_pop_context:
852
 *
853
 * Dissociate the FIPS context currently
854
 * active on the current thread, reverting to the previously active
855
 * context. If a cryptographic operation is ongoing in the current
856
 * thread, e.g., gnutls_aead_cipher_init() is called but
857
 * gnutls_aead_cipher_deinit() is not yet called, it returns an error
858
 * %GNUTLS_E_INVALID_REQUEST.
859
 *
860
 * This function is no-op if FIPS140 is not compiled in nor enabled
861
 * at run-time.
862
 *
863
 * Returns: 0 upon success, a negative error code otherwise
864
 *
865
 * Since: 3.7.3
866
 */
867
int gnutls_fips140_pop_context(void)
868
0
{
869
#ifdef ENABLE_FIPS140
870
  if (_gnutls_fips_mode_enabled() != GNUTLS_FIPS140_DISABLED) {
871
    if (!_tfips_context) {
872
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
873
    }
874
875
    _tfips_context = _tfips_context->next;
876
  }
877
  return 0;
878
#else
879
0
  return GNUTLS_E_INVALID_REQUEST;
880
0
#endif
881
0
}
882
883
#ifdef ENABLE_FIPS140
884
885
static inline const char *
886
operation_state_to_string(gnutls_fips140_operation_state_t state)
887
{
888
  switch (state) {
889
  case GNUTLS_FIPS140_OP_INITIAL:
890
    return "initial";
891
  case GNUTLS_FIPS140_OP_APPROVED:
892
    return "approved";
893
  case GNUTLS_FIPS140_OP_NOT_APPROVED:
894
    return "not-approved";
895
  case GNUTLS_FIPS140_OP_ERROR:
896
    return "error";
897
  default:
898
    /*NOTREACHED*/ assert(0);
899
    return NULL;
900
  }
901
}
902
903
void _gnutls_switch_fips_state(gnutls_fips140_operation_state_t state)
904
{
905
  gnutls_fips_mode_t mode = _gnutls_fips_mode_enabled();
906
  if (mode == GNUTLS_FIPS140_DISABLED) {
907
    return;
908
  }
909
910
  if (!_tfips_context) {
911
    _gnutls_debug_log("FIPS140-2 context is not set\n");
912
    return;
913
  }
914
915
  if (_tfips_context->state == state) {
916
    return;
917
  }
918
919
  switch (_tfips_context->state) {
920
  case GNUTLS_FIPS140_OP_INITIAL:
921
    /* initial can be transitioned to any state */
922
    if (mode != GNUTLS_FIPS140_LAX) {
923
      _gnutls_audit_log(
924
        NULL,
925
        "FIPS140-2 operation mode switched from initial to %s\n",
926
        operation_state_to_string(state));
927
    }
928
    _tfips_context->state = state;
929
    break;
930
  case GNUTLS_FIPS140_OP_APPROVED:
931
    /* approved can only be transitioned to not-approved */
932
    if (likely(state == GNUTLS_FIPS140_OP_NOT_APPROVED)) {
933
      if (mode != GNUTLS_FIPS140_LAX) {
934
        _gnutls_audit_log(
935
          NULL,
936
          "FIPS140-2 operation mode switched from approved to %s\n",
937
          operation_state_to_string(state));
938
      }
939
      _tfips_context->state = state;
940
      return;
941
    }
942
    FALLTHROUGH;
943
  default:
944
    /* other transitions are prohibited */
945
    if (mode != GNUTLS_FIPS140_LAX) {
946
      _gnutls_audit_log(
947
        NULL,
948
        "FIPS140-2 operation mode cannot be switched from %s to %s\n",
949
        operation_state_to_string(
950
          _tfips_context->state),
951
        operation_state_to_string(state));
952
    }
953
    break;
954
  }
955
}
956
957
#else
958
959
void _gnutls_switch_fips_state(gnutls_fips140_operation_state_t state)
960
0
{
961
0
  (void)state;
962
0
}
963
964
#endif
965
966
/**
967
 * gnutls_fips140_run_self_tests:
968
 *
969
 * Manually perform the second round of the FIPS140 self-tests,
970
 * including:
971
 *
972
 * - Known answer tests (KAT) for the selected set of symmetric
973
 *   cipher, MAC, public key, KDF, and DRBG
974
 * - Library integrity checks
975
 *
976
 * Upon failure with FIPS140 mode enabled, it makes the library
977
 * unusable.  This function is not thread-safe.
978
 *
979
 * Returns: 0 upon success, a negative error code otherwise
980
 *
981
 * Since: 3.7.7
982
 */
983
int gnutls_fips140_run_self_tests(void)
984
0
{
985
#ifdef ENABLE_FIPS140
986
  int ret;
987
  unsigned prev_lib_state;
988
  gnutls_fips140_context_t fips_context = NULL;
989
990
  /* Save the FIPS context, because self tests change it */
991
  if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED) {
992
    if (gnutls_fips140_context_init(&fips_context) < 0 ||
993
        gnutls_fips140_push_context(fips_context) < 0) {
994
      gnutls_fips140_context_deinit(fips_context);
995
      fips_context = NULL;
996
    }
997
  }
998
999
  /* Temporarily switch to LIB_STATE_SELFTEST as some of the
1000
   * algorithms are implemented using special constructs in
1001
   * self-tests (such as deterministic variants) */
1002
  prev_lib_state = _gnutls_get_lib_state();
1003
  _gnutls_switch_lib_state(LIB_STATE_SELFTEST);
1004
1005
  ret = _gnutls_fips_perform_self_checks2();
1006
  if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED &&
1007
      ret < 0) {
1008
    _gnutls_switch_lib_state(LIB_STATE_ERROR);
1009
    _gnutls_audit_log(NULL,
1010
          "FIPS140-2 self testing part 2 failed\n");
1011
  } else {
1012
    /* Restore the previous library state */
1013
    _gnutls_switch_lib_state(prev_lib_state);
1014
  }
1015
1016
  /* Restore the previous FIPS context */
1017
  if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED &&
1018
      fips_context) {
1019
    if (gnutls_fips140_pop_context() < 0) {
1020
      _gnutls_switch_lib_state(LIB_STATE_ERROR);
1021
      _gnutls_audit_log(
1022
        NULL, "FIPS140-2 context restoration failed\n");
1023
    }
1024
    gnutls_fips140_context_deinit(fips_context);
1025
  }
1026
  return ret;
1027
#else
1028
0
  return 0;
1029
0
#endif
1030
0
}