Line data Source code
1 : /* fips.c - FIPS mode management
2 : * Copyright (C) 2008 Free Software Foundation, Inc.
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include <config.h>
21 : #include <stdio.h>
22 : #include <stdlib.h>
23 : #include <errno.h>
24 : #include <unistd.h>
25 : #include <string.h>
26 : #ifdef ENABLE_HMAC_BINARY_CHECK
27 : # include <dlfcn.h>
28 : #endif
29 : #ifdef HAVE_SYSLOG
30 : # include <syslog.h>
31 : #endif /*HAVE_SYSLOG*/
32 :
33 : #include "g10lib.h"
34 : #include "cipher-proto.h"
35 : #include "hmac256.h"
36 :
37 :
38 : /* The name of the file used to force libgcrypt into fips mode. */
39 : #define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled"
40 :
41 :
42 : /* The states of the finite state machine used in fips mode. */
43 : enum module_states
44 : {
45 : /* POWEROFF cannot be represented. */
46 : STATE_POWERON = 0,
47 : STATE_INIT,
48 : STATE_SELFTEST,
49 : STATE_OPERATIONAL,
50 : STATE_ERROR,
51 : STATE_FATALERROR,
52 : STATE_SHUTDOWN
53 : };
54 :
55 :
56 : /* Flag telling whether we are in fips mode. It uses inverse logic so
57 : that fips mode is the default unless changed by the initialization
58 : code. To check whether fips mode is enabled, use the function
59 : fips_mode()! */
60 : static int no_fips_mode_required;
61 :
62 : /* Flag to indicate that we are in the enforced FIPS mode. */
63 : static int enforced_fips_mode;
64 :
65 : /* If this flag is set, the application may no longer assume that the
66 : process is running in FIPS mode. This flag is protected by the
67 : FSM_LOCK. */
68 : static int inactive_fips_mode;
69 :
70 : /* This is the lock we use to protect the FSM. */
71 : GPGRT_LOCK_DEFINE (fsm_lock);
72 :
73 : /* The current state of the FSM. The whole state machinery is only
74 : used while in fips mode. Change this only while holding fsm_lock. */
75 : static enum module_states current_state;
76 :
77 :
78 :
79 :
80 :
81 : static void fips_new_state (enum module_states new_state);
82 :
83 :
84 :
85 : /* Convert lowercase hex digits; assumes valid hex digits. */
86 : #define loxtoi_1(p) (*(p) <= '9'? (*(p)- '0'): (*(p)-'a'+10))
87 : #define loxtoi_2(p) ((loxtoi_1(p) * 16) + loxtoi_1((p)+1))
88 :
89 : /* Returns true if P points to a lowercase hex digit. */
90 : #define loxdigit_p(p) !!strchr ("01234567890abcdef", *(p))
91 :
92 :
93 :
94 : /* Check whether the OS is in FIPS mode and record that in a module
95 : local variable. If FORCE is passed as true, fips mode will be
96 : enabled anyway. Note: This function is not thread-safe and should
97 : be called before any threads are created. This function may only
98 : be called once. */
99 : void
100 34 : _gcry_initialize_fips_mode (int force)
101 : {
102 : static int done;
103 : gpg_error_t err;
104 :
105 : /* Make sure we are not accidentally called twice. */
106 34 : if (done)
107 : {
108 0 : if ( fips_mode () )
109 : {
110 0 : fips_new_state (STATE_FATALERROR);
111 0 : fips_noreturn ();
112 : }
113 : /* If not in fips mode an assert is sufficient. */
114 0 : gcry_assert (!done);
115 : }
116 34 : done = 1;
117 :
118 : /* If the calling application explicitly requested fipsmode, do so. */
119 34 : if (force)
120 : {
121 0 : gcry_assert (!no_fips_mode_required);
122 0 : goto leave;
123 : }
124 :
125 : /* For testing the system it is useful to override the system
126 : provided detection of the FIPS mode and force FIPS mode using a
127 : file. The filename is hardwired so that there won't be any
128 : confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is
129 : actually used. The file itself may be empty. */
130 34 : if ( !access (FIPS_FORCE_FILE, F_OK) )
131 : {
132 0 : gcry_assert (!no_fips_mode_required);
133 0 : goto leave;
134 : }
135 :
136 : /* Checking based on /proc file properties. */
137 : {
138 : static const char procfname[] = "/proc/sys/crypto/fips_enabled";
139 : FILE *fp;
140 : int saved_errno;
141 :
142 34 : fp = fopen (procfname, "r");
143 34 : if (fp)
144 : {
145 : char line[256];
146 :
147 34 : if (fgets (line, sizeof line, fp) && atoi (line))
148 : {
149 : /* System is in fips mode. */
150 0 : fclose (fp);
151 0 : gcry_assert (!no_fips_mode_required);
152 0 : goto leave;
153 : }
154 34 : fclose (fp);
155 : }
156 0 : else if ((saved_errno = errno) != ENOENT
157 0 : && saved_errno != EACCES
158 0 : && !access ("/proc/version", F_OK) )
159 : {
160 : /* Problem reading the fips file despite that we have the proc
161 : file system. We better stop right away. */
162 0 : log_info ("FATAL: error reading `%s' in libgcrypt: %s\n",
163 : procfname, strerror (saved_errno));
164 : #ifdef HAVE_SYSLOG
165 0 : syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
166 : "reading `%s' failed: %s - abort",
167 : procfname, strerror (saved_errno));
168 : #endif /*HAVE_SYSLOG*/
169 0 : abort ();
170 : }
171 : }
172 :
173 : /* Fips not not requested, set flag. */
174 34 : no_fips_mode_required = 1;
175 :
176 : leave:
177 34 : if (!no_fips_mode_required)
178 : {
179 : /* Yes, we are in FIPS mode. */
180 : FILE *fp;
181 :
182 : /* Intitialize the lock to protect the FSM. */
183 0 : err = gpgrt_lock_init (&fsm_lock);
184 0 : if (err)
185 : {
186 : /* If that fails we can't do anything but abort the
187 : process. We need to use log_info so that the FSM won't
188 : get involved. */
189 0 : log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n",
190 : gpg_strerror (err));
191 : #ifdef HAVE_SYSLOG
192 0 : syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
193 : "creating FSM lock failed: %s - abort",
194 : gpg_strerror (err));
195 : #endif /*HAVE_SYSLOG*/
196 0 : abort ();
197 : }
198 :
199 :
200 : /* If the FIPS force files exists, is readable and has a number
201 : != 0 on its first line, we enable the enforced fips mode. */
202 0 : fp = fopen (FIPS_FORCE_FILE, "r");
203 0 : if (fp)
204 : {
205 : char line[256];
206 :
207 0 : if (fgets (line, sizeof line, fp) && atoi (line))
208 0 : enforced_fips_mode = 1;
209 0 : fclose (fp);
210 : }
211 :
212 : /* Now get us into the INIT state. */
213 0 : fips_new_state (STATE_INIT);
214 :
215 : }
216 34 : return;
217 : }
218 :
219 : static void
220 4 : lock_fsm (void)
221 : {
222 : gpg_error_t err;
223 :
224 4 : err = gpgrt_lock_lock (&fsm_lock);
225 4 : if (err)
226 : {
227 0 : log_info ("FATAL: failed to acquire the FSM lock in libgrypt: %s\n",
228 : gpg_strerror (err));
229 : #ifdef HAVE_SYSLOG
230 0 : syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
231 : "acquiring FSM lock failed: %s - abort",
232 : gpg_strerror (err));
233 : #endif /*HAVE_SYSLOG*/
234 0 : abort ();
235 : }
236 4 : }
237 :
238 : static void
239 4 : unlock_fsm (void)
240 : {
241 : gpg_error_t err;
242 :
243 4 : err = gpgrt_lock_unlock (&fsm_lock);
244 4 : if (err)
245 : {
246 0 : log_info ("FATAL: failed to release the FSM lock in libgrypt: %s\n",
247 : gpg_strerror (err));
248 : #ifdef HAVE_SYSLOG
249 0 : syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
250 : "releasing FSM lock failed: %s - abort",
251 : gpg_strerror (err));
252 : #endif /*HAVE_SYSLOG*/
253 0 : abort ();
254 : }
255 4 : }
256 :
257 :
258 : /* This function returns true if fips mode is enabled. This is
259 : independent of the fips required finite state machine and only used
260 : to enable fips specific code. Please use the fips_mode macro
261 : instead of calling this function directly. */
262 : int
263 41297041 : _gcry_fips_mode (void)
264 : {
265 : /* No locking is required because we have the requirement that this
266 : variable is only initialized once with no other threads
267 : existing. */
268 41297041 : return !no_fips_mode_required;
269 : }
270 :
271 :
272 : /* Return a flag telling whether we are in the enforced fips mode. */
273 : int
274 1131844 : _gcry_enforced_fips_mode (void)
275 : {
276 1131844 : if (!_gcry_fips_mode ())
277 1131844 : return 0;
278 0 : return enforced_fips_mode;
279 : }
280 :
281 : /* Set a flag telling whether we are in the enforced fips mode. */
282 : void
283 0 : _gcry_set_enforced_fips_mode (void)
284 : {
285 0 : enforced_fips_mode = 1;
286 0 : }
287 :
288 : /* If we do not want to enforce the fips mode, we can set a flag so
289 : that the application may check whether it is still in fips mode.
290 : TEXT will be printed as part of a syslog message. This function
291 : may only be be called if in fips mode. */
292 : void
293 0 : _gcry_inactivate_fips_mode (const char *text)
294 : {
295 0 : gcry_assert (_gcry_fips_mode ());
296 :
297 0 : if (_gcry_enforced_fips_mode () )
298 : {
299 : /* Get us into the error state. */
300 0 : fips_signal_error (text);
301 0 : return;
302 : }
303 :
304 0 : lock_fsm ();
305 0 : if (!inactive_fips_mode)
306 : {
307 0 : inactive_fips_mode = 1;
308 0 : unlock_fsm ();
309 : #ifdef HAVE_SYSLOG
310 0 : syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
311 : "%s - FIPS mode inactivated", text);
312 : #endif /*HAVE_SYSLOG*/
313 : }
314 : else
315 0 : unlock_fsm ();
316 : }
317 :
318 :
319 : /* Return the FIPS mode inactive flag. If it is true the FIPS mode is
320 : not anymore active. */
321 : int
322 4 : _gcry_is_fips_mode_inactive (void)
323 : {
324 : int flag;
325 :
326 4 : if (!_gcry_fips_mode ())
327 0 : return 0;
328 4 : lock_fsm ();
329 4 : flag = inactive_fips_mode;
330 4 : unlock_fsm ();
331 4 : return flag;
332 : }
333 :
334 :
335 :
336 : static const char *
337 0 : state2str (enum module_states state)
338 : {
339 : const char *s;
340 :
341 0 : switch (state)
342 : {
343 0 : case STATE_POWERON: s = "Power-On"; break;
344 0 : case STATE_INIT: s = "Init"; break;
345 0 : case STATE_SELFTEST: s = "Self-Test"; break;
346 0 : case STATE_OPERATIONAL: s = "Operational"; break;
347 0 : case STATE_ERROR: s = "Error"; break;
348 0 : case STATE_FATALERROR: s = "Fatal-Error"; break;
349 0 : case STATE_SHUTDOWN: s = "Shutdown"; break;
350 0 : default: s = "?"; break;
351 : }
352 0 : return s;
353 : }
354 :
355 :
356 : /* Return true if the library is in the operational state. */
357 : int
358 39962994 : _gcry_fips_is_operational (void)
359 : {
360 : int result;
361 :
362 39962994 : if (!fips_mode ())
363 39962993 : result = 1;
364 : else
365 : {
366 0 : lock_fsm ();
367 0 : if (current_state == STATE_INIT)
368 : {
369 : /* If we are still in the INIT state, we need to run the
370 : selftests so that the FSM can eventually get into
371 : operational state. Given that we would need a 2-phase
372 : initialization of libgcrypt, but that has traditionally
373 : not been enforced, we use this on demand self-test
374 : checking. Note that Proper applications would do the
375 : application specific libgcrypt initialization between a
376 : gcry_check_version() and gcry_control
377 : (GCRYCTL_INITIALIZATION_FINISHED) where the latter will
378 : run the selftests. The drawback of these on-demand
379 : self-tests are a small chance that self-tests are
380 : performed by several threads; that is no problem because
381 : our FSM make sure that we won't oversee any error. */
382 0 : unlock_fsm ();
383 0 : _gcry_fips_run_selftests (0);
384 0 : lock_fsm ();
385 : }
386 :
387 0 : result = (current_state == STATE_OPERATIONAL);
388 0 : unlock_fsm ();
389 : }
390 39962993 : return result;
391 : }
392 :
393 :
394 : /* This is test on whether the library is in the operational state. In
395 : contrast to _gcry_fips_is_operational this function won't do a
396 : state transition on the fly. */
397 : int
398 0 : _gcry_fips_test_operational (void)
399 : {
400 : int result;
401 :
402 0 : if (!fips_mode ())
403 0 : result = 1;
404 : else
405 : {
406 0 : lock_fsm ();
407 0 : result = (current_state == STATE_OPERATIONAL);
408 0 : unlock_fsm ();
409 : }
410 0 : return result;
411 : }
412 :
413 :
414 : /* This is a test on whether the library is in the error or
415 : operational state. */
416 : int
417 0 : _gcry_fips_test_error_or_operational (void)
418 : {
419 : int result;
420 :
421 0 : if (!fips_mode ())
422 0 : result = 1;
423 : else
424 : {
425 0 : lock_fsm ();
426 0 : result = (current_state == STATE_OPERATIONAL
427 0 : || current_state == STATE_ERROR);
428 0 : unlock_fsm ();
429 : }
430 0 : return result;
431 : }
432 :
433 :
434 : static void
435 44 : reporter (const char *domain, int algo, const char *what, const char *errtxt)
436 : {
437 44 : if (!errtxt && !_gcry_log_verbosity (2))
438 44 : return;
439 :
440 0 : log_info ("libgcrypt selftest: %s %s%s (%d): %s%s%s%s\n",
441 0 : !strcmp (domain, "hmac")? "digest":domain,
442 0 : !strcmp (domain, "hmac")? "HMAC-":"",
443 0 : !strcmp (domain, "cipher")? _gcry_cipher_algo_name (algo) :
444 0 : !strcmp (domain, "digest")? _gcry_md_algo_name (algo) :
445 0 : !strcmp (domain, "hmac")? _gcry_md_algo_name (algo) :
446 0 : !strcmp (domain, "pubkey")? _gcry_pk_algo_name (algo) : "",
447 : algo, errtxt? errtxt:"Okay",
448 : what?" (":"", what? what:"", what?")":"");
449 : }
450 :
451 : /* Run self-tests for all required cipher algorithms. Return 0 on
452 : success. */
453 : static int
454 2 : run_cipher_selftests (int extended)
455 : {
456 : static int algos[] =
457 : {
458 : GCRY_CIPHER_3DES,
459 : GCRY_CIPHER_AES128,
460 : GCRY_CIPHER_AES192,
461 : GCRY_CIPHER_AES256,
462 : 0
463 : };
464 : int idx;
465 : gpg_error_t err;
466 2 : int anyerr = 0;
467 :
468 10 : for (idx=0; algos[idx]; idx++)
469 : {
470 8 : err = _gcry_cipher_selftest (algos[idx], extended, reporter);
471 8 : reporter ("cipher", algos[idx], NULL,
472 : err? gpg_strerror (err):NULL);
473 8 : if (err)
474 0 : anyerr = 1;
475 : }
476 2 : return anyerr;
477 : }
478 :
479 :
480 : /* Run self-tests for all required hash algorithms. Return 0 on
481 : success. */
482 : static int
483 2 : run_digest_selftests (int extended)
484 : {
485 : static int algos[] =
486 : {
487 : GCRY_MD_SHA1,
488 : GCRY_MD_SHA224,
489 : GCRY_MD_SHA256,
490 : GCRY_MD_SHA384,
491 : GCRY_MD_SHA512,
492 : 0
493 : };
494 : int idx;
495 : gpg_error_t err;
496 2 : int anyerr = 0;
497 :
498 12 : for (idx=0; algos[idx]; idx++)
499 : {
500 10 : err = _gcry_md_selftest (algos[idx], extended, reporter);
501 10 : reporter ("digest", algos[idx], NULL,
502 : err? gpg_strerror (err):NULL);
503 10 : if (err)
504 0 : anyerr = 1;
505 : }
506 2 : return anyerr;
507 : }
508 :
509 :
510 : /* Run self-tests for all HMAC algorithms. Return 0 on success. */
511 : static int
512 2 : run_hmac_selftests (int extended)
513 : {
514 : static int algos[] =
515 : {
516 : GCRY_MD_SHA1,
517 : GCRY_MD_SHA224,
518 : GCRY_MD_SHA256,
519 : GCRY_MD_SHA384,
520 : GCRY_MD_SHA512,
521 : GCRY_MD_SHA3_224,
522 : GCRY_MD_SHA3_256,
523 : GCRY_MD_SHA3_384,
524 : GCRY_MD_SHA3_512,
525 : 0
526 : };
527 : int idx;
528 : gpg_error_t err;
529 2 : int anyerr = 0;
530 :
531 20 : for (idx=0; algos[idx]; idx++)
532 : {
533 18 : err = _gcry_hmac_selftest (algos[idx], extended, reporter);
534 18 : reporter ("hmac", algos[idx], NULL,
535 : err? gpg_strerror (err):NULL);
536 18 : if (err)
537 0 : anyerr = 1;
538 : }
539 2 : return anyerr;
540 : }
541 :
542 :
543 : /* Run self-tests for all required public key algorithms. Return 0 on
544 : success. */
545 : static int
546 2 : run_pubkey_selftests (int extended)
547 : {
548 : static int algos[] =
549 : {
550 : GCRY_PK_RSA,
551 : GCRY_PK_DSA,
552 : GCRY_PK_ECC,
553 : 0
554 : };
555 : int idx;
556 : gpg_error_t err;
557 2 : int anyerr = 0;
558 :
559 8 : for (idx=0; algos[idx]; idx++)
560 : {
561 6 : err = _gcry_pk_selftest (algos[idx], extended, reporter);
562 6 : reporter ("pubkey", algos[idx], NULL,
563 : err? gpg_strerror (err):NULL);
564 6 : if (err)
565 0 : anyerr = 1;
566 : }
567 2 : return anyerr;
568 : }
569 :
570 :
571 : /* Run self-tests for the random number generator. Returns 0 on
572 : success. */
573 : static int
574 2 : run_random_selftests (void)
575 : {
576 : gpg_error_t err;
577 :
578 2 : err = _gcry_random_selftest (reporter);
579 2 : reporter ("random", 0, NULL, err? gpg_strerror (err):NULL);
580 :
581 2 : return !!err;
582 : }
583 :
584 : /* Run an integrity check on the binary. Returns 0 on success. */
585 : static int
586 2 : check_binary_integrity (void)
587 : {
588 : #ifdef ENABLE_HMAC_BINARY_CHECK
589 : gpg_error_t err;
590 : Dl_info info;
591 : unsigned char digest[32];
592 : int dlen;
593 : char *fname = NULL;
594 : const char key[] = "What am I, a doctor or a moonshuttle conductor?";
595 :
596 : if (!dladdr ("gcry_check_version", &info))
597 : err = gpg_error_from_syserror ();
598 : else
599 : {
600 : dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname,
601 : key, strlen (key));
602 : if (dlen < 0)
603 : err = gpg_error_from_syserror ();
604 : else if (dlen != 32)
605 : err = gpg_error (GPG_ERR_INTERNAL);
606 : else
607 : {
608 : fname = xtrymalloc (strlen (info.dli_fname) + 1 + 5 + 1 );
609 : if (!fname)
610 : err = gpg_error_from_syserror ();
611 : else
612 : {
613 : FILE *fp;
614 : char *p;
615 :
616 : /* Prefix the basename with a dot. */
617 : strcpy (fname, info.dli_fname);
618 : p = strrchr (fname, '/');
619 : if (p)
620 : p++;
621 : else
622 : p = fname;
623 : memmove (p+1, p, strlen (p)+1);
624 : *p = '.';
625 : strcat (fname, ".hmac");
626 :
627 : /* Open the file. */
628 : fp = fopen (fname, "r");
629 : if (!fp)
630 : err = gpg_error_from_syserror ();
631 : else
632 : {
633 : /* A buffer of 64 bytes plus one for a LF and one to
634 : detect garbage. */
635 : unsigned char buffer[64+1+1];
636 : const unsigned char *s;
637 : int n;
638 :
639 : /* The HMAC files consists of lowercase hex digits
640 : with an optional trailing linefeed or optional
641 : with two trailing spaces. The latter format
642 : allows the use of the usual sha1sum format. Fail
643 : if there is any garbage. */
644 : err = gpg_error (GPG_ERR_SELFTEST_FAILED);
645 : n = fread (buffer, 1, sizeof buffer, fp);
646 : if (n == 64
647 : || (n == 65 && buffer[64] == '\n')
648 : || (n == 66 && buffer[64] == ' ' && buffer[65] == ' '))
649 : {
650 : buffer[64] = 0;
651 : for (n=0, s= buffer;
652 : n < 32 && loxdigit_p (s) && loxdigit_p (s+1);
653 : n++, s += 2)
654 : buffer[n] = loxtoi_2 (s);
655 : if ( n == 32 && !memcmp (digest, buffer, 32) )
656 : err = 0;
657 : }
658 : fclose (fp);
659 : }
660 : }
661 : }
662 : }
663 : reporter ("binary", 0, fname, err? gpg_strerror (err):NULL);
664 : #ifdef HAVE_SYSLOG
665 : if (err)
666 : syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
667 : "integrity check using `%s' failed: %s",
668 : fname? fname:"[?]", gpg_strerror (err));
669 : #endif /*HAVE_SYSLOG*/
670 : xfree (fname);
671 : return !!err;
672 : #else
673 2 : return 0;
674 : #endif
675 : }
676 :
677 :
678 : /* Run the self-tests. If EXTENDED is true, extended versions of the
679 : selftest are run, that is more tests than required by FIPS. */
680 : gpg_err_code_t
681 2 : _gcry_fips_run_selftests (int extended)
682 : {
683 2 : enum module_states result = STATE_ERROR;
684 2 : gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED;
685 :
686 2 : if (fips_mode ())
687 0 : fips_new_state (STATE_SELFTEST);
688 :
689 2 : if (run_cipher_selftests (extended))
690 0 : goto leave;
691 :
692 2 : if (run_digest_selftests (extended))
693 0 : goto leave;
694 :
695 2 : if (run_hmac_selftests (extended))
696 0 : goto leave;
697 :
698 : /* Run random tests before the pubkey tests because the latter
699 : require random. */
700 2 : if (run_random_selftests ())
701 0 : goto leave;
702 :
703 2 : if (run_pubkey_selftests (extended))
704 0 : goto leave;
705 :
706 : /* Now check the integrity of the binary. We do this this after
707 : having checked the HMAC code. */
708 2 : if (check_binary_integrity ())
709 0 : goto leave;
710 :
711 : /* All selftests passed. */
712 2 : result = STATE_OPERATIONAL;
713 2 : ec = 0;
714 :
715 : leave:
716 2 : if (fips_mode ())
717 0 : fips_new_state (result);
718 :
719 2 : return ec;
720 : }
721 :
722 :
723 : /* This function is used to tell the FSM about errors in the library.
724 : The FSM will be put into an error state. This function should not
725 : be called directly but by one of the macros
726 :
727 : fips_signal_error (description)
728 : fips_signal_fatal_error (description)
729 :
730 : where DESCRIPTION is a string describing the error. */
731 : void
732 0 : _gcry_fips_signal_error (const char *srcfile, int srcline, const char *srcfunc,
733 : int is_fatal, const char *description)
734 : {
735 0 : if (!fips_mode ())
736 0 : return; /* Not required. */
737 :
738 : /* Set new state before printing an error. */
739 0 : fips_new_state (is_fatal? STATE_FATALERROR : STATE_ERROR);
740 :
741 : /* Print error. */
742 0 : log_info ("%serror in libgcrypt, file %s, line %d%s%s: %s\n",
743 : is_fatal? "fatal ":"",
744 : srcfile, srcline,
745 : srcfunc? ", function ":"", srcfunc? srcfunc:"",
746 : description? description : "no description available");
747 : #ifdef HAVE_SYSLOG
748 0 : syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
749 : "%serror in file %s, line %d%s%s: %s",
750 : is_fatal? "fatal ":"",
751 : srcfile, srcline,
752 : srcfunc? ", function ":"", srcfunc? srcfunc:"",
753 : description? description : "no description available");
754 : #endif /*HAVE_SYSLOG*/
755 : }
756 :
757 :
758 : /* Perform a state transition to NEW_STATE. If this is an invalid
759 : transition, the module will go into a fatal error state. */
760 : static void
761 0 : fips_new_state (enum module_states new_state)
762 : {
763 0 : int ok = 0;
764 : enum module_states last_state;
765 :
766 0 : lock_fsm ();
767 :
768 0 : last_state = current_state;
769 0 : switch (current_state)
770 : {
771 : case STATE_POWERON:
772 0 : if (new_state == STATE_INIT
773 0 : || new_state == STATE_ERROR
774 0 : || new_state == STATE_FATALERROR)
775 0 : ok = 1;
776 0 : break;
777 :
778 : case STATE_INIT:
779 0 : if (new_state == STATE_SELFTEST
780 0 : || new_state == STATE_ERROR
781 0 : || new_state == STATE_FATALERROR)
782 0 : ok = 1;
783 0 : break;
784 :
785 : case STATE_SELFTEST:
786 0 : if (new_state == STATE_OPERATIONAL
787 0 : || new_state == STATE_ERROR
788 0 : || new_state == STATE_FATALERROR)
789 0 : ok = 1;
790 0 : break;
791 :
792 : case STATE_OPERATIONAL:
793 0 : if (new_state == STATE_SHUTDOWN
794 0 : || new_state == STATE_SELFTEST
795 0 : || new_state == STATE_ERROR
796 0 : || new_state == STATE_FATALERROR)
797 0 : ok = 1;
798 0 : break;
799 :
800 : case STATE_ERROR:
801 0 : if (new_state == STATE_SHUTDOWN
802 0 : || new_state == STATE_ERROR
803 0 : || new_state == STATE_FATALERROR
804 0 : || new_state == STATE_SELFTEST)
805 0 : ok = 1;
806 0 : break;
807 :
808 : case STATE_FATALERROR:
809 0 : if (new_state == STATE_SHUTDOWN )
810 0 : ok = 1;
811 0 : break;
812 :
813 : case STATE_SHUTDOWN:
814 : /* We won't see any transition *from* Shutdown because the only
815 : allowed new state is Power-Off and that one can't be
816 : represented. */
817 0 : break;
818 :
819 : }
820 :
821 0 : if (ok)
822 : {
823 0 : current_state = new_state;
824 : }
825 :
826 0 : unlock_fsm ();
827 :
828 0 : if (!ok || _gcry_log_verbosity (2))
829 0 : log_info ("libgcrypt state transition %s => %s %s\n",
830 : state2str (last_state), state2str (new_state),
831 : ok? "granted":"denied");
832 :
833 0 : if (!ok)
834 : {
835 : /* Invalid state transition. Halting library. */
836 : #ifdef HAVE_SYSLOG
837 0 : syslog (LOG_USER|LOG_ERR,
838 : "Libgcrypt error: invalid state transition %s => %s",
839 : state2str (last_state), state2str (new_state));
840 : #endif /*HAVE_SYSLOG*/
841 0 : fips_noreturn ();
842 : }
843 0 : else if (new_state == STATE_ERROR || new_state == STATE_FATALERROR)
844 : {
845 : #ifdef HAVE_SYSLOG
846 0 : syslog (LOG_USER|LOG_WARNING,
847 : "Libgcrypt notice: state transition %s => %s",
848 : state2str (last_state), state2str (new_state));
849 : #endif /*HAVE_SYSLOG*/
850 : }
851 0 : }
852 :
853 :
854 :
855 :
856 : /* This function should be called to ensure that the execution shall
857 : not continue. */
858 : void
859 0 : _gcry_fips_noreturn (void)
860 : {
861 : #ifdef HAVE_SYSLOG
862 0 : syslog (LOG_USER|LOG_ERR, "Libgcrypt terminated the application");
863 : #endif /*HAVE_SYSLOG*/
864 0 : fflush (NULL);
865 0 : abort ();
866 : /*NOTREACHED*/
867 : }
|