LCOV - code coverage report
Current view: top level - src - global.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 248 453 54.7 %
Date: 2016-12-01 18:32:04 Functions: 28 31 90.3 %

          Line data    Source code
       1             : /* global.c  -  global control functions
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
       3             :  *               2004, 2005, 2006, 2008, 2011,
       4             :  *               2012  Free Software Foundation, Inc.
       5             :  * Copyright (C) 2013, 2014 g10 Code GmbH
       6             :  *
       7             :  * This file is part of Libgcrypt.
       8             :  *
       9             :  * Libgcrypt is free software; you can redistribute it and/or modify
      10             :  * it under the terms of the GNU Lesser general Public License as
      11             :  * published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * Libgcrypt is distributed in the hope that it will be useful,
      15             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :  * GNU Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public
      20             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      21             :  */
      22             : 
      23             : #include <config.h>
      24             : 
      25             : #include <stdio.h>
      26             : #include <stdlib.h>
      27             : #include <string.h>
      28             : #include <stdarg.h>
      29             : #include <ctype.h>
      30             : #include <limits.h>
      31             : #include <errno.h>
      32             : #include <unistd.h>
      33             : #ifdef HAVE_SYSLOG
      34             : # include <syslog.h>
      35             : #endif /*HAVE_SYSLOG*/
      36             : 
      37             : #include "g10lib.h"
      38             : #include "gcrypt-testapi.h"
      39             : #include "cipher.h"
      40             : #include "stdmem.h" /* our own memory allocator */
      41             : #include "secmem.h" /* our own secmem allocator */
      42             : 
      43             : 
      44             : 
      45             : 
      46             : /****************
      47             :  * flag bits: 0 : general cipher debug
      48             :  *            1 : general MPI debug
      49             :  */
      50             : static unsigned int debug_flags;
      51             : 
      52             : /* gcry_control (GCRYCTL_SET_FIPS_MODE), sets this flag so that the
      53             :    initialization code switched fips mode on.  */
      54             : static int force_fips_mode;
      55             : 
      56             : /* Controlled by global_init().  */
      57             : static int any_init_done;
      58             : 
      59             : /*
      60             :  * Functions called before and after blocking syscalls.
      61             :  * Initialized by global_init and used via
      62             :  * _gcry_pre_syscall and _gcry_post_syscall.
      63             :  */
      64             : static void (*pre_syscall_func)(void);
      65             : static void (*post_syscall_func)(void);
      66             : 
      67             : 
      68             : /* Memory management. */
      69             : 
      70             : static gcry_handler_alloc_t alloc_func;
      71             : static gcry_handler_alloc_t alloc_secure_func;
      72             : static gcry_handler_secure_check_t is_secure_func;
      73             : static gcry_handler_realloc_t realloc_func;
      74             : static gcry_handler_free_t free_func;
      75             : static gcry_handler_no_mem_t outofcore_handler;
      76             : static void *outofcore_handler_value;
      77             : static int no_secure_memory;
      78             : 
      79             : /* Prototypes.  */
      80             : static gpg_err_code_t external_lock_test (int cmd);
      81             : 
      82             : 
      83             : 
      84             : 
      85             : /* This is our handmade constructor.  It gets called by any function
      86             :    likely to be called at startup.  The suggested way for an
      87             :    application to make sure that this has been called is by using
      88             :    gcry_check_version. */
      89             : static void
      90          97 : global_init (void)
      91             : {
      92          97 :   gcry_error_t err = 0;
      93             : 
      94          97 :   if (any_init_done)
      95          65 :     return;
      96          32 :   any_init_done = 1;
      97             : 
      98             :   /* Tell the random module that we have seen an init call.  */
      99          32 :   _gcry_set_preferred_rng_type (0);
     100             : 
     101             :   /* Get the system call clamp functions.  */
     102          32 :   if (!pre_syscall_func)
     103          32 :     gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func);
     104             : 
     105             :   /* See whether the system is in FIPS mode.  This needs to come as
     106             :      early as possible but after ATH has been initialized.  */
     107          32 :   _gcry_initialize_fips_mode (force_fips_mode);
     108             : 
     109             :   /* Before we do any other initialization we need to test available
     110             :      hardware features.  */
     111          32 :   _gcry_detect_hw_features ();
     112             : 
     113             :   /* Initialize the modules - this is mainly allocating some memory and
     114             :      creating mutexes.  */
     115          32 :   err = _gcry_cipher_init ();
     116          32 :   if (err)
     117           0 :     goto fail;
     118          32 :   err = _gcry_md_init ();
     119          32 :   if (err)
     120           0 :     goto fail;
     121          32 :   err = _gcry_mac_init ();
     122          32 :   if (err)
     123           0 :     goto fail;
     124          32 :   err = _gcry_pk_init ();
     125          32 :   if (err)
     126           0 :     goto fail;
     127          32 :   err = _gcry_primegen_init ();
     128          32 :   if (err)
     129           0 :     goto fail;
     130          32 :   err = _gcry_secmem_module_init ();
     131          32 :   if (err)
     132           0 :     goto fail;
     133          32 :   err = _gcry_mpi_init ();
     134          32 :   if (err)
     135           0 :     goto fail;
     136             : 
     137          32 :   return;
     138             : 
     139             :  fail:
     140           0 :   BUG ();
     141             : }
     142             : 
     143             : 
     144             : /* This function is called by the macro fips_is_operational and makes
     145             :    sure that the minimal initialization has been done.  This is far
     146             :    from a perfect solution and hides problems with an improper
     147             :    initialization but at least in single-threaded mode it should work
     148             :    reliable.
     149             : 
     150             :    The reason we need this is that a lot of applications don't use
     151             :    Libgcrypt properly by not running any initialization code at all.
     152             :    They just call a Libgcrypt function and that is all what they want.
     153             :    Now with the FIPS mode, that has the side effect of entering FIPS
     154             :    mode (for security reasons, FIPS mode is the default if no
     155             :    initialization has been done) and bailing out immediately because
     156             :    the FSM is in the wrong state.  If we always run the init code,
     157             :    Libgcrypt can test for FIPS mode and at least if not in FIPS mode,
     158             :    it will behave as before.  Note that this on-the-fly initialization
     159             :    is only done for the cryptographic functions subject to FIPS mode
     160             :    and thus not all API calls will do such an initialization.  */
     161             : int
     162    31379160 : _gcry_global_is_operational (void)
     163             : {
     164    31379160 :   if (!any_init_done)
     165             :     {
     166             : #ifdef HAVE_SYSLOG
     167           0 :       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
     168             :               "missing initialization - please fix the application");
     169             : #endif /*HAVE_SYSLOG*/
     170           0 :       global_init ();
     171             :     }
     172    31379160 :   return _gcry_fips_is_operational ();
     173             : }
     174             : 
     175             : 
     176             : 
     177             : 
     178             : /* Version number parsing.  */
     179             : 
     180             : /* This function parses the first portion of the version number S and
     181             :    stores it in *NUMBER.  On success, this function returns a pointer
     182             :    into S starting with the first character, which is not part of the
     183             :    initial number portion; on failure, NULL is returned.  */
     184             : static const char*
     185         174 : parse_version_number( const char *s, int *number )
     186             : {
     187         174 :     int val = 0;
     188             : 
     189         174 :     if( *s == '0' && isdigit(s[1]) )
     190           0 :         return NULL; /* leading zeros are not allowed */
     191         348 :     for ( ; isdigit(*s); s++ ) {
     192         174 :         val *= 10;
     193         174 :         val += *s - '0';
     194             :     }
     195         174 :     *number = val;
     196         174 :     return val < 0? NULL : s;
     197             : }
     198             : 
     199             : /* This function breaks up the complete string-representation of the
     200             :    version number S, which is of the following struture: <major
     201             :    number>.<minor number>.<micro number><patch level>.  The major,
     202             :    minor and micro number components will be stored in *MAJOR, *MINOR
     203             :    and *MICRO.
     204             : 
     205             :    On success, the last component, the patch level, will be returned;
     206             :    in failure, NULL will be returned.  */
     207             : 
     208             : static const char *
     209          58 : parse_version_string( const char *s, int *major, int *minor, int *micro )
     210             : {
     211          58 :     s = parse_version_number( s, major );
     212          58 :     if( !s || *s != '.' )
     213           0 :         return NULL;
     214          58 :     s++;
     215          58 :     s = parse_version_number( s, minor );
     216          58 :     if( !s || *s != '.' )
     217           0 :         return NULL;
     218          58 :     s++;
     219          58 :     s = parse_version_number( s, micro );
     220          58 :     if( !s )
     221           0 :         return NULL;
     222          58 :     return s; /* patchlevel */
     223             : }
     224             : 
     225             : /* If REQ_VERSION is non-NULL, check that the version of the library
     226             :    is at minimum the requested one.  Returns the string representation
     227             :    of the library version if the condition is satisfied; return NULL
     228             :    if the requested version is newer than that of the library.
     229             : 
     230             :    If a NULL is passed to this function, no check is done, but the
     231             :    string representation of the library is simply returned.  */
     232             : const char *
     233          34 : _gcry_check_version (const char *req_version)
     234             : {
     235          34 :     const char *ver = VERSION;
     236             :     int my_major, my_minor, my_micro;
     237             :     int rq_major, rq_minor, rq_micro;
     238             :     const char *my_plvl;
     239             : 
     240          34 :     if (req_version && req_version[0] == 1 && req_version[1] == 1)
     241           0 :         return _gcry_compat_identification ();
     242             : 
     243             :     /* Initialize library.  */
     244          34 :     global_init ();
     245             : 
     246          34 :     if ( !req_version )
     247             :         /* Caller wants our version number.  */
     248           5 :         return ver;
     249             : 
     250             :     /* Parse own version number.  */
     251          29 :     my_plvl = parse_version_string( ver, &my_major, &my_minor, &my_micro );
     252          29 :     if ( !my_plvl )
     253             :         /* very strange our own version is bogus.  Shouldn't we use
     254             :            assert() here and bail out in case this happens?  -mo.  */
     255           0 :         return NULL;
     256             : 
     257             :     /* Parse requested version number.  */
     258          29 :     if (!parse_version_string (req_version, &rq_major, &rq_minor, &rq_micro))
     259           0 :       return NULL;  /* req version string is invalid, this can happen.  */
     260             : 
     261             :     /* Compare version numbers.  */
     262          29 :     if ( my_major > rq_major
     263          29 :         || (my_major == rq_major && my_minor > rq_minor)
     264          28 :         || (my_major == rq_major && my_minor == rq_minor                                                         && my_micro > rq_micro)
     265          28 :         || (my_major == rq_major && my_minor == rq_minor
     266          28 :                                  && my_micro == rq_micro))
     267             :       {
     268          29 :         return ver;
     269             :       }
     270             : 
     271           0 :     return NULL;
     272             : }
     273             : 
     274             : 
     275             : static void
     276           1 : print_config ( int (*fnc)(FILE *fp, const char *format, ...), FILE *fp)
     277             : {
     278             :   unsigned int hwfeatures, afeature;
     279             :   int i;
     280             :   const char *s;
     281             : 
     282           1 :   fnc (fp, "version:%s:\n", VERSION);
     283           1 :   fnc (fp, "ciphers:%s:\n", LIBGCRYPT_CIPHERS);
     284           1 :   fnc (fp, "pubkeys:%s:\n", LIBGCRYPT_PUBKEY_CIPHERS);
     285           1 :   fnc (fp, "digests:%s:\n", LIBGCRYPT_DIGESTS);
     286           1 :   fnc (fp, "rnd-mod:"
     287             : #if USE_RNDEGD
     288             :                 "egd:"
     289             : #endif
     290             : #if USE_RNDLINUX
     291             :                 "linux:"
     292             : #endif
     293             : #if USE_RNDUNIX
     294             :                 "unix:"
     295             : #endif
     296             : #if USE_RNDW32
     297             :                 "w32:"
     298             : #endif
     299             :        "\n");
     300           1 :   fnc (fp, "cpu-arch:"
     301             : #if defined(HAVE_CPU_ARCH_X86)
     302             :        "x86"
     303             : #elif defined(HAVE_CPU_ARCH_ALPHA)
     304             :        "alpha"
     305             : #elif defined(HAVE_CPU_ARCH_SPARC)
     306             :        "sparc"
     307             : #elif defined(HAVE_CPU_ARCH_MIPS)
     308             :        "mips"
     309             : #elif defined(HAVE_CPU_ARCH_M68K)
     310             :        "m68k"
     311             : #elif defined(HAVE_CPU_ARCH_PPC)
     312             :        "ppc"
     313             : #elif defined(HAVE_CPU_ARCH_ARM)
     314             :        "arm"
     315             : #endif
     316             :        ":\n");
     317           1 :   fnc (fp, "mpi-asm:%s:\n", _gcry_mpi_get_hw_config ());
     318           1 :   hwfeatures = _gcry_get_hw_features ();
     319           1 :   fnc (fp, "hwflist:");
     320          20 :   for (i=0; (s = _gcry_enum_hw_features (i, &afeature)); i++)
     321          19 :     if ((hwfeatures & afeature))
     322           7 :       fnc (fp, "%s:", s);
     323           1 :   fnc (fp, "\n");
     324             :   /* We use y/n instead of 1/0 for the simple reason that Emacsen's
     325             :      compile error parser would accidentally flag that line when printed
     326             :      during "make check" as an error.  */
     327           2 :   fnc (fp, "fips-mode:%c:%c:\n",
     328           1 :        fips_mode ()? 'y':'n',
     329           1 :        _gcry_enforced_fips_mode ()? 'y':'n' );
     330             :   /* The currently used RNG type.  */
     331             :   {
     332           1 :     i = _gcry_get_rng_type (0);
     333           1 :     switch (i)
     334             :       {
     335           1 :       case GCRY_RNG_TYPE_STANDARD: s = "standard"; break;
     336           0 :       case GCRY_RNG_TYPE_FIPS:     s = "fips"; break;
     337           0 :       case GCRY_RNG_TYPE_SYSTEM:   s = "system"; break;
     338           0 :       default: BUG ();
     339             :       }
     340           1 :     fnc (fp, "rng-type:%s:%d:\n", s, i);
     341             :   }
     342             : 
     343           1 : }
     344             : 
     345             : 
     346             : 
     347             : 
     348             : /* Command dispatcher function, acting as general control
     349             :    function.  */
     350             : gcry_err_code_t
     351       24623 : _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
     352             : {
     353             :   static int init_finished = 0;
     354       24623 :   gcry_err_code_t rc = 0;
     355             : 
     356       24623 :   switch (cmd)
     357             :     {
     358             :     case GCRYCTL_ENABLE_M_GUARD:
     359           0 :       _gcry_private_enable_m_guard ();
     360          24 :       break;
     361             : 
     362             :     case GCRYCTL_ENABLE_QUICK_RANDOM:
     363          16 :       _gcry_set_preferred_rng_type (0);
     364          16 :       _gcry_enable_quick_random_gen ();
     365          16 :       break;
     366             : 
     367             :     case GCRYCTL_FAKED_RANDOM_P:
     368             :       /* Return an error if the RNG is faked one (e.g. enabled by
     369             :          ENABLE_QUICK_RANDOM. */
     370           0 :       if (_gcry_random_is_faked ())
     371           0 :         rc = GPG_ERR_GENERAL;  /* Use as TRUE value.  */
     372           0 :       break;
     373             : 
     374             :     case GCRYCTL_DUMP_RANDOM_STATS:
     375           0 :       _gcry_random_dump_stats ();
     376           0 :       break;
     377             : 
     378             :     case GCRYCTL_DUMP_MEMORY_STATS:
     379             :       /*m_print_stats("[fixme: prefix]");*/
     380           0 :       break;
     381             : 
     382             :     case GCRYCTL_DUMP_SECMEM_STATS:
     383           0 :       _gcry_secmem_dump_stats ();
     384           0 :       break;
     385             : 
     386             :     case GCRYCTL_DROP_PRIVS:
     387           0 :       global_init ();
     388           0 :       _gcry_secmem_init (0);
     389           0 :       break;
     390             : 
     391             :     case GCRYCTL_DISABLE_SECMEM:
     392          31 :       global_init ();
     393          31 :       no_secure_memory = 1;
     394          31 :       break;
     395             : 
     396             :     case GCRYCTL_INIT_SECMEM:
     397           1 :       global_init ();
     398           1 :       _gcry_secmem_init (va_arg (arg_ptr, unsigned int));
     399           1 :       if ((_gcry_secmem_get_flags () & GCRY_SECMEM_FLAG_NOT_LOCKED))
     400           0 :         rc = GPG_ERR_GENERAL;
     401           1 :       break;
     402             : 
     403             :     case GCRYCTL_TERM_SECMEM:
     404           0 :       global_init ();
     405           0 :       _gcry_secmem_term ();
     406           0 :       break;
     407             : 
     408             :     case GCRYCTL_DISABLE_SECMEM_WARN:
     409           1 :       _gcry_set_preferred_rng_type (0);
     410           1 :       _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
     411             :                                | GCRY_SECMEM_FLAG_NO_WARNING));
     412           1 :       break;
     413             : 
     414             :     case GCRYCTL_SUSPEND_SECMEM_WARN:
     415           0 :       _gcry_set_preferred_rng_type (0);
     416           0 :       _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
     417             :                                | GCRY_SECMEM_FLAG_SUSPEND_WARNING));
     418           0 :       break;
     419             : 
     420             :     case GCRYCTL_RESUME_SECMEM_WARN:
     421           0 :       _gcry_set_preferred_rng_type (0);
     422           0 :       _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
     423             :                                & ~GCRY_SECMEM_FLAG_SUSPEND_WARNING));
     424           0 :       break;
     425             : 
     426             :     case GCRYCTL_USE_SECURE_RNDPOOL:
     427           0 :       global_init ();
     428           0 :       _gcry_secure_random_alloc (); /* Put random number into secure memory. */
     429           0 :       break;
     430             : 
     431             :     case GCRYCTL_SET_RANDOM_SEED_FILE:
     432           0 :       _gcry_set_preferred_rng_type (0);
     433           0 :       _gcry_set_random_seed_file (va_arg (arg_ptr, const char *));
     434           0 :       break;
     435             : 
     436             :     case GCRYCTL_UPDATE_RANDOM_SEED_FILE:
     437           0 :       _gcry_set_preferred_rng_type (0);
     438           0 :       if ( fips_is_operational () )
     439           0 :         _gcry_update_random_seed_file ();
     440           0 :       break;
     441             : 
     442             :     case GCRYCTL_SET_VERBOSITY:
     443           5 :       _gcry_set_preferred_rng_type (0);
     444           5 :       _gcry_set_log_verbosity (va_arg (arg_ptr, int));
     445           5 :       break;
     446             : 
     447             :     case GCRYCTL_SET_DEBUG_FLAGS:
     448           0 :       debug_flags |= va_arg (arg_ptr, unsigned int);
     449           0 :       break;
     450             : 
     451             :     case GCRYCTL_CLEAR_DEBUG_FLAGS:
     452           0 :       debug_flags &= ~va_arg (arg_ptr, unsigned int);
     453           0 :       break;
     454             : 
     455             :     case GCRYCTL_DISABLE_INTERNAL_LOCKING:
     456             :       /* Not used anymore.  */
     457           0 :       global_init ();
     458           0 :       break;
     459             : 
     460             :     case GCRYCTL_ANY_INITIALIZATION_P:
     461           0 :       if (any_init_done)
     462           0 :         rc = GPG_ERR_GENERAL;
     463           0 :       break;
     464             : 
     465             :     case GCRYCTL_INITIALIZATION_FINISHED_P:
     466           0 :       if (init_finished)
     467           0 :         rc = GPG_ERR_GENERAL; /* Yes.  */
     468           0 :       break;
     469             : 
     470             :     case GCRYCTL_INITIALIZATION_FINISHED:
     471             :       /* This is a hook which should be used by an application after
     472             :          all initialization has been done and right before any threads
     473             :          are started.  It is not really needed but the only way to be
     474             :          really sure that all initialization for thread-safety has
     475             :          been done. */
     476          30 :       if (! init_finished)
     477             :         {
     478          30 :           global_init ();
     479             :           /* Do only a basic random initialization, i.e. init the
     480             :              mutexes. */
     481          30 :           _gcry_random_initialize (0);
     482          30 :           init_finished = 1;
     483             :           /* Force us into operational state if in FIPS mode.  */
     484          30 :           (void)fips_is_operational ();
     485             :         }
     486          30 :       break;
     487             : 
     488             :     case GCRYCTL_SET_THREAD_CBS:
     489             :       /* This is now a dummy call.  We used to install our own thread
     490             :          library here. */
     491           0 :       _gcry_set_preferred_rng_type (0);
     492           0 :       global_init ();
     493           0 :       break;
     494             : 
     495             :     case GCRYCTL_FAST_POLL:
     496           0 :       _gcry_set_preferred_rng_type (0);
     497             :       /* We need to do make sure that the random pool is really
     498             :          initialized so that the poll function is not a NOP. */
     499           0 :       _gcry_random_initialize (1);
     500             : 
     501           0 :       if ( fips_is_operational () )
     502           0 :         _gcry_fast_random_poll ();
     503           0 :       break;
     504             : 
     505             :     case GCRYCTL_SET_RNDEGD_SOCKET:
     506             : #if USE_RNDEGD
     507             :       _gcry_set_preferred_rng_type (0);
     508             :       rc = _gcry_rndegd_set_socket_name (va_arg (arg_ptr, const char *));
     509             : #else
     510           0 :       rc = GPG_ERR_NOT_SUPPORTED;
     511             : #endif
     512           0 :       break;
     513             : 
     514             :     case GCRYCTL_SET_RANDOM_DAEMON_SOCKET:
     515           0 :       _gcry_set_preferred_rng_type (0);
     516           0 :       _gcry_set_random_daemon_socket (va_arg (arg_ptr, const char *));
     517           0 :       break;
     518             : 
     519             :     case GCRYCTL_USE_RANDOM_DAEMON:
     520             :       /* We need to do make sure that the random pool is really
     521             :          initialized so that the poll function is not a NOP. */
     522           0 :       _gcry_set_preferred_rng_type (0);
     523           0 :       _gcry_random_initialize (1);
     524           0 :       _gcry_use_random_daemon (!! va_arg (arg_ptr, int));
     525           0 :       break;
     526             : 
     527             :     case GCRYCTL_CLOSE_RANDOM_DEVICE:
     528           0 :       _gcry_random_close_fds ();
     529           0 :       break;
     530             : 
     531             :       /* This command dumps information pertaining to the
     532             :          configuration of libgcrypt to the given stream.  It may be
     533             :          used before the initialization has been finished but not
     534             :          before a gcry_version_check. */
     535             :     case GCRYCTL_PRINT_CONFIG:
     536             :       {
     537           1 :         FILE *fp = va_arg (arg_ptr, FILE *);
     538           1 :         _gcry_set_preferred_rng_type (0);
     539           1 :         print_config (fp?fprintf:_gcry_log_info_with_dummy_fp, fp);
     540             :       }
     541           1 :       break;
     542             : 
     543             :     case GCRYCTL_OPERATIONAL_P:
     544             :       /* Returns true if the library is in an operational state.  This
     545             :          is always true for non-fips mode.  */
     546           0 :       _gcry_set_preferred_rng_type (0);
     547           0 :       if (_gcry_fips_test_operational ())
     548           0 :         rc = GPG_ERR_GENERAL; /* Used as TRUE value */
     549           0 :       break;
     550             : 
     551             :     case GCRYCTL_FIPS_MODE_P:
     552         115 :       if (fips_mode ()
     553           4 :           && !_gcry_is_fips_mode_inactive ()
     554           4 :           && !no_secure_memory)
     555           4 :         rc = GPG_ERR_GENERAL; /* Used as TRUE value */
     556         115 :       break;
     557             : 
     558             :     case GCRYCTL_FORCE_FIPS_MODE:
     559             :       /* Performing this command puts the library into fips mode.  If
     560             :          the library has already been initialized into fips mode, a
     561             :          selftest is triggered.  It is not possible to put the libraty
     562             :          into fips mode after having passed the initialization. */
     563           0 :       _gcry_set_preferred_rng_type (0);
     564           0 :       if (!any_init_done)
     565             :         {
     566             :           /* Not yet intialized at all.  Set a flag so that we are put
     567             :              into fips mode during initialization.  */
     568           0 :           force_fips_mode = 1;
     569             :         }
     570             :       else
     571             :         {
     572             :           /* Already initialized.  If we are already operational we
     573             :              run a selftest.  If not we use the is_operational call to
     574             :              force us into operational state if possible.  */
     575           0 :           if (_gcry_fips_test_error_or_operational ())
     576           0 :             _gcry_fips_run_selftests (1);
     577           0 :           if (_gcry_fips_is_operational ())
     578           0 :             rc = GPG_ERR_GENERAL; /* Used as TRUE value */
     579             :       }
     580           0 :       break;
     581             : 
     582             :     case GCRYCTL_SELFTEST:
     583             :       /* Run a selftest.  This works in fips mode as well as in
     584             :          standard mode.  In contrast to the power-up tests, we use an
     585             :          extended version of the selftests. Returns 0 on success or an
     586             :          error code. */
     587           1 :       global_init ();
     588           1 :       rc = _gcry_fips_run_selftests (1);
     589           1 :       break;
     590             : 
     591             : #if _GCRY_GCC_VERSION >= 40600
     592             : # pragma GCC diagnostic push
     593             : # pragma GCC diagnostic ignored "-Wswitch"
     594             : #endif
     595             :     case PRIV_CTL_INIT_EXTRNG_TEST:  /* Init external random test.  */
     596           0 :       rc = GPG_ERR_NOT_SUPPORTED;
     597           0 :       break;
     598             :     case PRIV_CTL_RUN_EXTRNG_TEST:  /* Run external DRBG test.  */
     599             :       {
     600           0 :         struct gcry_drbg_test_vector *test =
     601           0 :           va_arg (arg_ptr, struct gcry_drbg_test_vector *);
     602           0 :         unsigned char *buf = va_arg (arg_ptr, unsigned char *);
     603             : 
     604           0 :         if (buf)
     605           0 :           rc = _gcry_rngdrbg_cavs_test (test, buf);
     606             :         else
     607           0 :           rc = _gcry_rngdrbg_healthcheck_one (test);
     608             :       }
     609           0 :       break;
     610             :     case PRIV_CTL_DEINIT_EXTRNG_TEST:  /* Deinit external random test.  */
     611           0 :       rc = GPG_ERR_NOT_SUPPORTED;
     612           0 :       break;
     613             :     case PRIV_CTL_EXTERNAL_LOCK_TEST:  /* Run external lock test */
     614       24328 :       rc = external_lock_test (va_arg (arg_ptr, int));
     615       24104 :       break;
     616             :     case 62:  /* RFU */
     617           0 :       break;
     618             : #if _GCRY_GCC_VERSION >= 40600
     619             : # pragma GCC diagnostic pop
     620             : #endif
     621             : 
     622             :     case GCRYCTL_DISABLE_HWF:
     623             :       {
     624           0 :         const char *name = va_arg (arg_ptr, const char *);
     625           0 :         rc = _gcry_disable_hw_feature (name);
     626             :       }
     627           0 :       break;
     628             : 
     629             :     case GCRYCTL_SET_ENFORCED_FIPS_FLAG:
     630           0 :       if (!any_init_done)
     631             :         {
     632             :           /* Not yet initialized at all.  Set the enforced fips mode flag */
     633           0 :           _gcry_set_preferred_rng_type (0);
     634           0 :           _gcry_set_enforced_fips_mode ();
     635             :         }
     636             :       else
     637           0 :         rc = GPG_ERR_GENERAL;
     638           0 :       break;
     639             : 
     640             :     case GCRYCTL_SET_PREFERRED_RNG_TYPE:
     641             :       /* This may be called before gcry_check_version.  */
     642             :       {
     643          30 :         int i = va_arg (arg_ptr, int);
     644             :         /* Note that we may not pass 0 to _gcry_set_preferred_rng_type.  */
     645          30 :         if (i > 0)
     646          30 :           _gcry_set_preferred_rng_type (i);
     647             :       }
     648          30 :       break;
     649             : 
     650             :     case GCRYCTL_GET_CURRENT_RNG_TYPE:
     651             :       {
     652          64 :         int *ip = va_arg (arg_ptr, int*);
     653          64 :         if (ip)
     654          64 :           *ip = _gcry_get_rng_type (!any_init_done);
     655             :       }
     656          64 :       break;
     657             : 
     658             :     case GCRYCTL_DISABLE_LOCKED_SECMEM:
     659           0 :       _gcry_set_preferred_rng_type (0);
     660           0 :       _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
     661             :                                | GCRY_SECMEM_FLAG_NO_MLOCK));
     662           0 :       break;
     663             : 
     664             :     case GCRYCTL_DISABLE_PRIV_DROP:
     665           0 :       _gcry_set_preferred_rng_type (0);
     666           0 :       _gcry_secmem_set_flags ((_gcry_secmem_get_flags ()
     667             :                                | GCRY_SECMEM_FLAG_NO_PRIV_DROP));
     668           0 :       break;
     669             : 
     670             :     case GCRYCTL_INACTIVATE_FIPS_FLAG:
     671             :     case GCRYCTL_REACTIVATE_FIPS_FLAG:
     672           0 :       rc = GPG_ERR_NOT_IMPLEMENTED;
     673           0 :       break;
     674             : 
     675             :     case GCRYCTL_DRBG_REINIT:
     676             :       {
     677           0 :         const char *flagstr = va_arg (arg_ptr, const char *);
     678           0 :         gcry_buffer_t *pers = va_arg (arg_ptr, gcry_buffer_t *);
     679           0 :         int npers = va_arg (arg_ptr, int);
     680           0 :         if (va_arg (arg_ptr, void *) || npers < 0)
     681           0 :           rc = GPG_ERR_INV_ARG;
     682           0 :         else if (_gcry_get_rng_type (!any_init_done) != GCRY_RNG_TYPE_FIPS)
     683           0 :           rc = GPG_ERR_NOT_SUPPORTED;
     684             :         else
     685           0 :           rc = _gcry_rngdrbg_reinit (flagstr, pers, npers);
     686             :       }
     687           0 :       break;
     688             : 
     689             :     case GCRYCTL_REINIT_SYSCALL_CLAMP:
     690           0 :       if (!pre_syscall_func)
     691           0 :         gpgrt_get_syscall_clamp (&pre_syscall_func, &post_syscall_func);
     692           0 :       break;
     693             : 
     694             :     default:
     695           0 :       _gcry_set_preferred_rng_type (0);
     696           0 :       rc = GPG_ERR_INV_OP;
     697             :     }
     698             : 
     699       24423 :   return rc;
     700             : }
     701             : 
     702             : 
     703             : 
     704             : /* Set custom allocation handlers.  This is in general not useful
     705             :  * because the libgcrypt allocation functions are guaranteed to
     706             :  * provide proper allocation handlers which zeroize memory if needed.
     707             :  * NOTE: All 5 functions should be set.  */
     708             : void
     709           0 : _gcry_set_allocation_handler (gcry_handler_alloc_t new_alloc_func,
     710             :                               gcry_handler_alloc_t new_alloc_secure_func,
     711             :                               gcry_handler_secure_check_t new_is_secure_func,
     712             :                               gcry_handler_realloc_t new_realloc_func,
     713             :                               gcry_handler_free_t new_free_func)
     714             : {
     715           0 :   global_init ();
     716             : 
     717           0 :   if (fips_mode ())
     718             :     {
     719             :       /* We do not want to enforce the fips mode, but merely set a
     720             :          flag so that the application may check whether it is still in
     721             :          fips mode.  */
     722           0 :       _gcry_inactivate_fips_mode ("custom allocation handler");
     723             :     }
     724             : 
     725           0 :   alloc_func = new_alloc_func;
     726           0 :   alloc_secure_func = new_alloc_secure_func;
     727           0 :   is_secure_func = new_is_secure_func;
     728           0 :   realloc_func = new_realloc_func;
     729           0 :   free_func = new_free_func;
     730           0 : }
     731             : 
     732             : 
     733             : 
     734             : /****************
     735             :  * Set an optional handler which is called in case the xmalloc functions
     736             :  * ran out of memory.  This handler may do one of these things:
     737             :  *   o free some memory and return true, so that the xmalloc function
     738             :  *     tries again.
     739             :  *   o Do whatever it like and return false, so that the xmalloc functions
     740             :  *     use the default fatal error handler.
     741             :  *   o Terminate the program and don't return.
     742             :  *
     743             :  * The handler function is called with 3 arguments:  The opaque value set with
     744             :  * this function, the requested memory size, and a flag with these bits
     745             :  * currently defined:
     746             :  *      bit 0 set = secure memory has been requested.
     747             :  */
     748             : void
     749           0 : _gcry_set_outofcore_handler (int (*f)(void*, size_t, unsigned int), void *value)
     750             : {
     751           0 :   global_init ();
     752             : 
     753           0 :   if (fips_mode () )
     754             :     {
     755           0 :       log_info ("out of core handler ignored in FIPS mode\n");
     756           0 :       return;
     757             :     }
     758             : 
     759           0 :   outofcore_handler = f;
     760           0 :   outofcore_handler_value = value;
     761             : }
     762             : 
     763             : /* Return the no_secure_memory flag.  */
     764             : static int
     765      962271 : get_no_secure_memory (void)
     766             : {
     767      962271 :   if (!no_secure_memory)
     768         452 :     return 0;
     769      961819 :   if (_gcry_enforced_fips_mode ())
     770             :     {
     771           0 :       no_secure_memory = 0;
     772           0 :       return 0;
     773             :     }
     774      961819 :   return no_secure_memory;
     775             : }
     776             : 
     777             : 
     778             : static gcry_err_code_t
     779    89216880 : do_malloc (size_t n, unsigned int flags, void **mem)
     780             : {
     781    89216880 :   gcry_err_code_t err = 0;
     782             :   void *m;
     783             : 
     784    89216880 :   if ((flags & GCRY_ALLOC_FLAG_SECURE) && !get_no_secure_memory ())
     785             :     {
     786           6 :       if (alloc_secure_func)
     787           0 :         m = (*alloc_secure_func) (n);
     788             :       else
     789           3 :         m = _gcry_private_malloc_secure (n);
     790             :     }
     791             :   else
     792             :     {
     793    89216877 :       if (alloc_func)
     794           0 :         m = (*alloc_func) (n);
     795             :       else
     796    89216877 :         m = _gcry_private_malloc (n);
     797             :     }
     798             : 
     799    89216880 :   if (!m)
     800             :     {
     801             :       /* Make sure that ERRNO has been set in case a user supplied
     802             :          memory handler didn't it correctly. */
     803           0 :       if (!errno)
     804           0 :         gpg_err_set_errno (ENOMEM);
     805           0 :       err = gpg_err_code_from_errno (errno);
     806             :     }
     807             :   else
     808    89216880 :     *mem = m;
     809             : 
     810    89216880 :   return err;
     811             : }
     812             : 
     813             : void *
     814    88616702 : _gcry_malloc (size_t n)
     815             : {
     816    88616702 :   void *mem = NULL;
     817             : 
     818    88616702 :   do_malloc (n, 0, &mem);
     819             : 
     820    88616702 :   return mem;
     821             : }
     822             : 
     823             : void *
     824      600178 : _gcry_malloc_secure (size_t n)
     825             : {
     826      600178 :   void *mem = NULL;
     827             : 
     828      600178 :   do_malloc (n, GCRY_ALLOC_FLAG_SECURE, &mem);
     829             : 
     830      600178 :   return mem;
     831             : }
     832             : 
     833             : int
     834      362093 : _gcry_is_secure (const void *a)
     835             : {
     836      362093 :   if (get_no_secure_memory ())
     837      361644 :     return 0;
     838         449 :   if (is_secure_func)
     839           0 :     return is_secure_func (a) ;
     840         449 :   return _gcry_private_is_secure (a);
     841             : }
     842             : 
     843             : void
     844           0 : _gcry_check_heap( const void *a )
     845             : {
     846             :   (void)a;
     847             : 
     848             :     /* FIXME: implement this*/
     849             : #if 0
     850             :     if( some_handler )
     851             :         some_handler(a)
     852             :     else
     853             :         _gcry_private_check_heap(a)
     854             : #endif
     855           0 : }
     856             : 
     857             : void *
     858      223872 : _gcry_realloc (void *a, size_t n)
     859             : {
     860             :   void *p;
     861             : 
     862             :   /* To avoid problems with non-standard realloc implementations and
     863             :      our own secmem_realloc, we divert to malloc and free here.  */
     864      223872 :   if (!a)
     865           0 :     return _gcry_malloc (n);
     866      223872 :   if (!n)
     867             :     {
     868           0 :       xfree (a);
     869           0 :       return NULL;
     870             :     }
     871             : 
     872      223872 :   if (realloc_func)
     873           0 :     p = realloc_func (a, n);
     874             :   else
     875      223872 :     p =  _gcry_private_realloc (a, n);
     876      223872 :   if (!p && !errno)
     877           0 :     gpg_err_set_errno (ENOMEM);
     878      223872 :   return p;
     879             : }
     880             : 
     881             : void
     882    89233280 : _gcry_free (void *p)
     883             : {
     884             :   int save_errno;
     885             : 
     886    89233280 :   if (!p)
     887    89250973 :     return;
     888             : 
     889             :   /* In case ERRNO is set we better save it so that the free machinery
     890             :      may not accidentally change ERRNO.  We restore it only if it was
     891             :      already set to comply with the usual C semantic for ERRNO.  */
     892    89215587 :   save_errno = errno;
     893    89215587 :   if (free_func)
     894           0 :     free_func (p);
     895             :   else
     896    89215587 :     _gcry_private_free (p);
     897             : 
     898    89215587 :   if (save_errno)
     899    89215579 :     gpg_err_set_errno (save_errno);
     900             : }
     901             : 
     902             : void *
     903        5280 : _gcry_calloc (size_t n, size_t m)
     904             : {
     905             :   size_t bytes;
     906             :   void *p;
     907             : 
     908        5280 :   bytes = n * m; /* size_t is unsigned so the behavior on overflow is
     909             :                     defined. */
     910        5280 :   if (m && bytes / m != n)
     911             :     {
     912           0 :       gpg_err_set_errno (ENOMEM);
     913           0 :       return NULL;
     914             :     }
     915             : 
     916        5280 :   p = _gcry_malloc (bytes);
     917        5280 :   if (p)
     918        5280 :     memset (p, 0, bytes);
     919        5280 :   return p;
     920             : }
     921             : 
     922             : void *
     923        1161 : _gcry_calloc_secure (size_t n, size_t m)
     924             : {
     925             :   size_t bytes;
     926             :   void *p;
     927             : 
     928        1161 :   bytes = n * m; /* size_t is unsigned so the behavior on overflow is
     929             :                     defined. */
     930        1161 :   if (m && bytes / m != n)
     931             :     {
     932           0 :       gpg_err_set_errno (ENOMEM);
     933           0 :       return NULL;
     934             :     }
     935             : 
     936        1161 :   p = _gcry_malloc_secure (bytes);
     937        1161 :   if (p)
     938        1161 :     memset (p, 0, bytes);
     939        1161 :   return p;
     940             : }
     941             : 
     942             : 
     943             : /* Create and return a copy of the null-terminated string STRING.  If
     944             :    it is contained in secure memory, the copy will be contained in
     945             :    secure memory as well.  In an out-of-memory condition, NULL is
     946             :    returned.  */
     947             : char *
     948        9242 : _gcry_strdup (const char *string)
     949             : {
     950        9242 :   char *string_cp = NULL;
     951        9242 :   size_t string_n = 0;
     952             : 
     953        9242 :   string_n = strlen (string);
     954             : 
     955        9242 :   if (_gcry_is_secure (string))
     956           0 :     string_cp = _gcry_malloc_secure (string_n + 1);
     957             :   else
     958        9242 :     string_cp = _gcry_malloc (string_n + 1);
     959             : 
     960        9242 :   if (string_cp)
     961        9242 :     strcpy (string_cp, string);
     962             : 
     963        9242 :   return string_cp;
     964             : }
     965             : 
     966             : 
     967             : void *
     968    88147795 : _gcry_xmalloc( size_t n )
     969             : {
     970             :   void *p;
     971             : 
     972   176295590 :   while ( !(p = _gcry_malloc( n )) )
     973             :     {
     974           0 :       if ( fips_mode ()
     975           0 :            || !outofcore_handler
     976           0 :            || !outofcore_handler (outofcore_handler_value, n, 0) )
     977             :         {
     978           0 :           _gcry_fatal_error (gpg_err_code_from_errno (errno), NULL);
     979             :         }
     980             :     }
     981    88147795 :     return p;
     982             : }
     983             : 
     984             : void *
     985      206746 : _gcry_xrealloc( void *a, size_t n )
     986             : {
     987             :   void *p;
     988             : 
     989      413492 :   while ( !(p = _gcry_realloc( a, n )) )
     990             :     {
     991           0 :       if ( fips_mode ()
     992           0 :            || !outofcore_handler
     993           0 :            || !outofcore_handler (outofcore_handler_value, n,
     994           0 :                                   _gcry_is_secure(a)? 3:2))
     995             :         {
     996           0 :           _gcry_fatal_error (gpg_err_code_from_errno (errno), NULL );
     997             :         }
     998             :     }
     999      206746 :     return p;
    1000             : }
    1001             : 
    1002             : void *
    1003      596160 : _gcry_xmalloc_secure( size_t n )
    1004             : {
    1005             :   void *p;
    1006             : 
    1007     1192320 :   while ( !(p = _gcry_malloc_secure( n )) )
    1008             :     {
    1009           0 :       if ( fips_mode ()
    1010           0 :            || !outofcore_handler
    1011           0 :            || !outofcore_handler (outofcore_handler_value, n, 1) )
    1012             :         {
    1013           0 :           _gcry_fatal_error (gpg_err_code_from_errno (errno),
    1014             :                              _("out of core in secure memory"));
    1015             :         }
    1016             :     }
    1017      596160 :   return p;
    1018             : }
    1019             : 
    1020             : 
    1021             : void *
    1022       77432 : _gcry_xcalloc( size_t n, size_t m )
    1023             : {
    1024             :   size_t nbytes;
    1025             :   void *p;
    1026             : 
    1027       77432 :   nbytes = n * m;
    1028       77432 :   if (m && nbytes / m != n)
    1029             :     {
    1030           0 :       gpg_err_set_errno (ENOMEM);
    1031           0 :       _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
    1032             :     }
    1033             : 
    1034       77432 :   p = _gcry_xmalloc ( nbytes );
    1035       77432 :   memset ( p, 0, nbytes );
    1036       77432 :   return p;
    1037             : }
    1038             : 
    1039             : void *
    1040        1234 : _gcry_xcalloc_secure( size_t n, size_t m )
    1041             : {
    1042             :   size_t nbytes;
    1043             :   void *p;
    1044             : 
    1045        1234 :   nbytes = n * m;
    1046        1234 :   if (m && nbytes / m != n)
    1047             :     {
    1048           0 :       gpg_err_set_errno (ENOMEM);
    1049           0 :       _gcry_fatal_error(gpg_err_code_from_errno (errno), NULL );
    1050             :     }
    1051             : 
    1052        1234 :   p = _gcry_xmalloc_secure ( nbytes );
    1053        1234 :   memset ( p, 0, nbytes );
    1054        1234 :   return p;
    1055             : }
    1056             : 
    1057             : char *
    1058        9242 : _gcry_xstrdup (const char *string)
    1059             : {
    1060             :   char *p;
    1061             : 
    1062       18484 :   while ( !(p = _gcry_strdup (string)) )
    1063             :     {
    1064           0 :       size_t n = strlen (string);
    1065           0 :       int is_sec = !!_gcry_is_secure (string);
    1066             : 
    1067           0 :       if (fips_mode ()
    1068           0 :           || !outofcore_handler
    1069           0 :           || !outofcore_handler (outofcore_handler_value, n, is_sec) )
    1070             :         {
    1071           0 :           _gcry_fatal_error (gpg_err_code_from_errno (errno),
    1072             :                              is_sec? _("out of core in secure memory"):NULL);
    1073             :         }
    1074             :     }
    1075             : 
    1076        9242 :   return p;
    1077             : }
    1078             : 
    1079             : 
    1080             : /* Used before blocking system calls.  */
    1081             : void
    1082         433 : _gcry_pre_syscall (void)
    1083             : {
    1084         433 :   if (pre_syscall_func)
    1085           0 :     pre_syscall_func ();
    1086         433 : }
    1087             : 
    1088             : 
    1089             : /* Used after blocking system calls.  */
    1090             : void
    1091         433 : _gcry_post_syscall (void)
    1092             : {
    1093         433 :   if (post_syscall_func)
    1094           0 :     post_syscall_func ();
    1095         433 : }
    1096             : 
    1097             : 
    1098             : int
    1099       33577 : _gcry_get_debug_flag (unsigned int mask)
    1100             : {
    1101       33577 :   if ( fips_mode () )
    1102           0 :     return 0;
    1103       33577 :   return (debug_flags & mask);
    1104             : }
    1105             : 
    1106             : 
    1107             : 
    1108             : /* It is often useful to get some feedback of long running operations.
    1109             :    This function may be used to register a handler for this.
    1110             :    The callback function CB is used as:
    1111             : 
    1112             :    void cb (void *opaque, const char *what, int printchar,
    1113             :            int current, int total);
    1114             : 
    1115             :    Where WHAT is a string identifying the the type of the progress
    1116             :    output, PRINTCHAR the character usually printed, CURRENT the amount
    1117             :    of progress currently done and TOTAL the expected amount of
    1118             :    progress.  A value of 0 for TOTAL indicates that there is no
    1119             :    estimation available.
    1120             : 
    1121             :    Defined values for WHAT:
    1122             : 
    1123             :    "need_entropy"  X    0  number-of-bytes-required
    1124             :             When running low on entropy
    1125             :    "primegen"      '\n'  0 0
    1126             :            Prime generated
    1127             :                    '!'
    1128             :            Need to refresh the prime pool
    1129             :                    '<','>'
    1130             :            Number of bits adjusted
    1131             :                    '^'
    1132             :            Looking for a generator
    1133             :                    '.'
    1134             :            Fermat tests on 10 candidates failed
    1135             :                   ':'
    1136             :            Restart with a new random value
    1137             :                   '+'
    1138             :            Rabin Miller test passed
    1139             :    "pk_elg"        '+','-','.','\n'   0  0
    1140             :             Only used in debugging mode.
    1141             :    "pk_dsa"
    1142             :             Only used in debugging mode.
    1143             : */
    1144             : void
    1145           1 : _gcry_set_progress_handler (void (*cb)(void *,const char*,int, int, int),
    1146             :                             void *cb_data)
    1147             : {
    1148             : #if USE_DSA
    1149           1 :   _gcry_register_pk_dsa_progress (cb, cb_data);
    1150             : #endif
    1151             : #if USE_ELGAMAL
    1152           1 :   _gcry_register_pk_elg_progress (cb, cb_data);
    1153             : #endif
    1154           1 :   _gcry_register_primegen_progress (cb, cb_data);
    1155           1 :   _gcry_register_random_progress (cb, cb_data);
    1156           1 : }
    1157             : 
    1158             : 
    1159             : 
    1160             : /* This is a helper for the regression test suite to test Libgcrypt's locks.
    1161             :    It works using a one test lock with CMD controlling what to do:
    1162             : 
    1163             :      30111 - Allocate and init lock
    1164             :      30112 - Take lock
    1165             :      30113 - Release lock
    1166             :      30114 - Destroy lock.
    1167             : 
    1168             :    This function is used by tests/t-lock.c - it is not part of the
    1169             :    public API!
    1170             :  */
    1171             : static gpg_err_code_t
    1172       24636 : external_lock_test (int cmd)
    1173             : {
    1174             :   GPGRT_LOCK_DEFINE (testlock);
    1175       24636 :   gpg_err_code_t rc = 0;
    1176             : 
    1177       24636 :   switch (cmd)
    1178             :     {
    1179             :     case 30111:  /* Init Lock.  */
    1180           2 :       rc = gpgrt_lock_init (&testlock);
    1181           0 :       break;
    1182             : 
    1183             :     case 30112:  /* Take Lock.  */
    1184       12271 :       rc = gpgrt_lock_lock (&testlock);
    1185       12361 :       break;
    1186             : 
    1187             :     case 30113:  /* Release Lock.  */
    1188       12361 :       rc = gpgrt_lock_unlock (&testlock);
    1189       12292 :       break;
    1190             : 
    1191             :     case 30114:  /* Destroy Lock.  */
    1192           2 :       rc = gpgrt_lock_destroy (&testlock);
    1193           2 :       break;
    1194             : 
    1195             :     default:
    1196           0 :       rc = GPG_ERR_INV_OP;
    1197           0 :       break;
    1198             :     }
    1199             : 
    1200       24121 :   return rc;
    1201             : }

Generated by: LCOV version 1.11