LCOV - code coverage report
Current view: top level - src/plugins/crypto - crypto.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 101 146 69.2 %
Date: 2019-09-12 12:28:41 Functions: 18 25 72.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief filter plugin providing cryptographic operations
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #ifndef HAVE_KDBCONFIG
      11             : #include "kdbconfig.h"
      12             : #endif
      13             : #include "crypto.h"
      14             : #include "crypto_kdb_functions.h"
      15             : #ifdef ELEKTRA_CRYPTO_API_GCRYPT
      16             : #include "gcrypt_operations.h"
      17             : #endif
      18             : #ifdef ELEKTRA_CRYPTO_API_OPENSSL
      19             : #include "openssl_operations.h"
      20             : #endif
      21             : #ifdef ELEKTRA_CRYPTO_API_BOTAN
      22             : #include "botan_operations.h"
      23             : #endif
      24             : #include "gpg.h"
      25             : #include "helper.h"
      26             : #include <kdb.h>
      27             : #include <kdberrors.h>
      28             : #include <kdbtypes.h>
      29             : #include <pthread.h>
      30             : #include <stdlib.h>
      31             : #include <string.h>
      32             : 
      33             : static pthread_mutex_t mutex_ref_cnt = PTHREAD_MUTEX_INITIALIZER;
      34             : static unsigned int ref_cnt = 0;
      35             : 
      36             : // gurads against compiler warnings because the functions are only used within the specified compile variants
      37             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT) || defined(ELEKTRA_CRYPTO_API_OPENSSL) || defined(ELEKTRA_CRYPTO_API_BOTAN)
      38             : 
      39             : /**
      40             :  * @brief checks if a Key has been marked for encryption by checking the Key's metadata.
      41             :  *
      42             :  * If the metakey ELEKTRA_CRYPTO_META_ENCRYPT has the value "1" it is considered to be true.
      43             :  * Every other value or the non-existence of the metakey is considered to be false.
      44             :  *
      45             :  * @param k the Key to be checked
      46             :  * @retval 0 if the Key has not been marked for encryption
      47             :  * @retval 1 if the Key has been marked for encryption
      48             :  */
      49          16 : static int isMarkedForEncryption (const Key * k)
      50             : {
      51          16 :         const Key * metaEncrypt = keyGetMeta (k, ELEKTRA_CRYPTO_META_ENCRYPT);
      52          16 :         if (metaEncrypt && strcmp (keyString (metaEncrypt), "1") == 0)
      53             :         {
      54             :                 return 1;
      55             :         }
      56             :         return 0;
      57             : }
      58             : 
      59             : /**
      60             :  * @brief checks if a given Key k is in the spec namespace.
      61             :  * @retval 0 if the Key k is in the spec namespace.
      62             :  * @retval 1 if the Key k is NOT in the spec namespace.
      63             :  */
      64             : static inline int isSpecNamespace (const Key * k)
      65             : {
      66          12 :         return (keyGetNamespace (k) == KEY_NS_SPEC);
      67             : }
      68             : 
      69             : #endif
      70             : 
      71             : /**
      72             :  * @brief verify the version of the cryptographic payload of the given key.
      73             :  * @param k holds the encrypted payload.
      74             :  * @param errorKey holds an error description if the version does not match or the format is wrong at all.
      75             :  * @return 1 if the payload version could be verified.
      76             :  * @return 0 otherwise.
      77             :  */
      78           6 : static int checkPayloadVersion (Key * k, Key * errorKey)
      79             : {
      80           6 :         if (keyGetValueSize (k) < ((ssize_t) ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN))
      81             :         {
      82           0 :                 ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (
      83             :                         errorKey,
      84             :                         "The provided data could not be recognized as valid cryptographic payload. The data is possibly "
      85             :                         "corrupted. Keyname: %s",
      86             :                         keyName (k));
      87           0 :                 return 0; // failure
      88             :         }
      89             : 
      90             :         // check the magic number without the version
      91           6 :         const kdb_octet_t * value = (kdb_octet_t *) keyValue (k);
      92           6 :         if (memcmp (value, ELEKTRA_CRYPTO_MAGIC_NUMBER, ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN - 2))
      93             :         {
      94           0 :                 ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (
      95             :                         errorKey,
      96             :                         "The provided data could not be recognized as valid cryptographic payload. The data is possibly "
      97             :                         "corrupted. Keyname: %s",
      98             :                         keyName (k));
      99           0 :                 return 0; // failure
     100             :         }
     101             : 
     102             :         // check the version
     103           6 :         const size_t versionOffset = ELEKTRA_CRYPTO_MAGIC_NUMBER_LEN - 2;
     104           6 :         if (memcmp (&value[versionOffset], ELEKTRA_CRYPTO_PAYLOAD_VERSION, 2))
     105             :         {
     106           0 :                 ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (
     107             :                         errorKey, "The version of the cryptographic payload is not compatible with the version of the plugin. Keyname: %s",
     108             :                         keyName (k));
     109           0 :                 return 0; // failure
     110             :         }
     111             : 
     112             :         return 1; // success
     113             : }
     114             : 
     115             : /**
     116             :  * @brief initialize the crypto backend
     117             :  * @retval 1 on success
     118             :  * @retval -1 on failure
     119             :  */
     120             : static int elektraCryptoInit (Key * errorKey ELEKTRA_UNUSED)
     121             : {
     122             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT)
     123          17 :         return elektraCryptoGcryInit (errorKey);
     124             : #elif defined(ELEKTRA_CRYPTO_API_OPENSSL)
     125          16 :         return elektraCryptoOpenSSLInit (errorKey);
     126             : #elif defined(ELEKTRA_CRYPTO_API_BOTAN)
     127          16 :         return elektraCryptoBotanInit (errorKey);
     128             : #else
     129             :         return 1;
     130             : #endif
     131             : }
     132             : 
     133             : /**
     134             :  * @brief clean up the crypto backend
     135             :  *
     136             :  * Some libraries may need extra code for cleaning up the environment.
     137             :  */
     138             : static void elektraCryptoTeardown (void)
     139             : {
     140             : }
     141             : 
     142             : /**
     143             :  * @brief read the plugin configuration for the supposed length of the master password.
     144             :  * @param errorKey may hold a warning if the provided configuration is invalid
     145             :  * @param conf the plugin configuration
     146             :  * @return the expected length of the master password
     147             :  */
     148           1 : static kdb_unsigned_short_t elektraCryptoGetRandomPasswordLength (Key * errorKey, KeySet * conf)
     149             : {
     150           1 :         Key * k = ksLookupByName (conf, ELEKTRA_CRYPTO_PARAM_MASTER_PASSWORD_LEN, 0);
     151           1 :         if (k && keyIsString (k) > 0)
     152             :         {
     153           0 :                 kdb_unsigned_short_t passwordLen = (kdb_unsigned_short_t) strtoul (keyString (k), NULL, 10);
     154           0 :                 if (passwordLen > 0)
     155             :                 {
     156             :                         return passwordLen;
     157             :                 }
     158             :                 else
     159             :                 {
     160           0 :                         ELEKTRA_ADD_INSTALLATION_WARNING (errorKey,
     161             :                                                           "Master password length provided at " ELEKTRA_CRYPTO_PARAM_MASTER_PASSWORD_LEN
     162             :                                                           " is invalid. Using default value instead.");
     163             :                 }
     164             :         }
     165             :         return ELEKTRA_CRYPTO_DEFAULT_MASTER_PWD_LENGTH;
     166             : }
     167             : 
     168             : /**
     169             :  * @brief create a random master password using the crypto backend's SRNG.
     170             :  * @param errorKey holds an error description in case of failure.
     171             :  * @param buffer is used to store the allocated hex-encoded random string. Must be freed by the caller.
     172             :  * @param length limit the length of the generated string to length characters (including the 0x00 terminator)
     173             :  * @retval 1 on success
     174             :  * @retval -1 on error. errorKey holds a description.
     175             :  */
     176             : static int elektraCryptoCreateRandomString (Key * errorKey ELEKTRA_UNUSED, char ** buffer ELEKTRA_UNUSED,
     177             :                                             const kdb_unsigned_short_t length ELEKTRA_UNUSED)
     178             : {
     179           1 :         *buffer = NULL;
     180             : 
     181             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT)
     182           1 :         *buffer = elektraCryptoGcryCreateRandomString (errorKey, length);
     183             : #elif defined(ELEKTRA_CRYPTO_API_OPENSSL)
     184           0 :         *buffer = elektraCryptoOpenSSLCreateRandomString (errorKey, length);
     185             : #elif defined(ELEKTRA_CRYPTO_API_BOTAN)
     186           0 :         *buffer = elektraCryptoBotanCreateRandomString (errorKey, length);
     187             : #endif
     188             : 
     189           1 :         if (*buffer) return 1;
     190             :         return -1;
     191             : }
     192             : 
     193             : /**
     194             :  * @brief overwrites the value of the key with zeroes and then releases the Key.
     195             :  * @param key to be overwritten and released
     196             :  */
     197           3 : static void elektraCryptoSafelyReleaseKey (Key * key)
     198             : {
     199           3 :         if (key)
     200             :         {
     201             :                 // overwrite key content with zeroes
     202           2 :                 ssize_t length = keyGetValueSize (key);
     203           2 :                 if (length > 0)
     204             :                 {
     205           2 :                         memset ((void *) keyValue (key), 0, length);
     206             :                 }
     207             : 
     208             :                 // release the key
     209           2 :                 keyDel (key);
     210             :         }
     211           3 : }
     212             : 
     213             : /**
     214             :  * @brief encrypt the (Elektra) Keys contained in data.
     215             :  * @param handle for the current plugin instance
     216             :  * @param data the KeySet holding the data
     217             :  * @param errorKey holds an error description in case of failure
     218             :  * @retval 1 on success
     219             :  * @retval -1 on failure. errorKey holds an error description.
     220             :  */
     221           2 : static int elektraCryptoEncrypt (Plugin * handle ELEKTRA_UNUSED, KeySet * data ELEKTRA_UNUSED, Key * errorKey ELEKTRA_UNUSED)
     222             : {
     223             :         Key * k;
     224           2 :         Key * masterKey = NULL;
     225             : 
     226             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT) || defined(ELEKTRA_CRYPTO_API_OPENSSL) || defined(ELEKTRA_CRYPTO_API_BOTAN)
     227           2 :         KeySet * pluginConfig = elektraPluginGetConfig (handle);
     228           2 :         masterKey = ELEKTRA_PLUGIN_FUNCTION (getMasterPassword) (errorKey, pluginConfig);
     229           2 :         if (!masterKey)
     230             :         {
     231             :                 goto error; // error has been set by getMasterPassword
     232             :         }
     233             : #endif
     234             : 
     235             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT) || defined(ELEKTRA_CRYPTO_API_OPENSSL)
     236           1 :         elektraCryptoHandle * cryptoHandle = NULL;
     237             : #endif
     238             : 
     239           1 :         ksRewind (data);
     240          10 :         while ((k = ksNext (data)) != 0)
     241             :         {
     242          14 :                 if (!isMarkedForEncryption (k) || isSpecNamespace (k))
     243             :                 {
     244           2 :                         continue;
     245             :                 }
     246             : 
     247             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT)
     248             : 
     249           6 :                 if (elektraCryptoGcryHandleCreate (&cryptoHandle, pluginConfig, errorKey, masterKey, k, ELEKTRA_CRYPTO_ENCRYPT) != 1)
     250             :                 {
     251             :                         goto error;
     252             :                 }
     253             : 
     254           6 :                 if (elektraCryptoGcryEncrypt (cryptoHandle, k, errorKey) != 1)
     255             :                 {
     256           0 :                         elektraCryptoGcryHandleDestroy (cryptoHandle);
     257           0 :                         goto error;
     258             :                 }
     259             : 
     260           6 :                 elektraCryptoGcryHandleDestroy (cryptoHandle);
     261           6 :                 cryptoHandle = NULL;
     262             : 
     263             : #elif defined(ELEKTRA_CRYPTO_API_OPENSSL)
     264             : 
     265           0 :                 if (elektraCryptoOpenSSLHandleCreate (&cryptoHandle, pluginConfig, errorKey, masterKey, k, ELEKTRA_CRYPTO_ENCRYPT) != 1)
     266             :                 {
     267           0 :                         elektraCryptoOpenSSLHandleDestroy (cryptoHandle);
     268           0 :                         goto error;
     269             :                 }
     270             : 
     271           0 :                 if (elektraCryptoOpenSSLEncrypt (cryptoHandle, k, errorKey) != 1)
     272             :                 {
     273           0 :                         elektraCryptoOpenSSLHandleDestroy (cryptoHandle);
     274           0 :                         goto error;
     275             :                 }
     276             : 
     277           0 :                 elektraCryptoOpenSSLHandleDestroy (cryptoHandle);
     278           0 :                 cryptoHandle = NULL;
     279             : 
     280             : #elif defined(ELEKTRA_CRYPTO_API_BOTAN)
     281             : 
     282           0 :                 if (elektraCryptoBotanEncrypt (pluginConfig, k, errorKey, masterKey) != 1)
     283             :                 {
     284             :                         goto error; // failure, error has been set by elektraCryptoBotanEncrypt
     285             :                 }
     286             : 
     287             : #endif
     288             :         }
     289           1 :         elektraCryptoSafelyReleaseKey (masterKey);
     290           1 :         return 1;
     291             : 
     292             : error:
     293           1 :         elektraCryptoSafelyReleaseKey (masterKey);
     294           1 :         return -1;
     295             : }
     296             : 
     297             : /**
     298             :  * @brief decrypt the (Elektra) Keys contained in data.
     299             :  * @param handle for the current plugin instance
     300             :  * @param data the KeySet holding the data
     301             :  * @param errorKey holds an error description in case of failure
     302             :  * @retval 1 on success
     303             :  * @retval -1 on failure. errorKey holds an error description.
     304             :  */
     305           1 : static int elektraCryptoDecrypt (Plugin * handle ELEKTRA_UNUSED, KeySet * data, Key * errorKey)
     306             : {
     307             :         Key * k;
     308           1 :         Key * masterKey = NULL;
     309             : 
     310             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT) || defined(ELEKTRA_CRYPTO_API_OPENSSL) || defined(ELEKTRA_CRYPTO_API_BOTAN)
     311           1 :         KeySet * pluginConfig = elektraPluginGetConfig (handle);
     312           1 :         masterKey = ELEKTRA_PLUGIN_FUNCTION (getMasterPassword) (errorKey, pluginConfig);
     313           1 :         if (!masterKey)
     314             :         {
     315             :                 goto error; // error has been set by getMasterPassword
     316             :         }
     317             : #endif
     318             : 
     319             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT) || defined(ELEKTRA_CRYPTO_API_OPENSSL)
     320           1 :         elektraCryptoHandle * cryptoHandle = NULL;
     321             : #endif
     322             : 
     323           1 :         ksRewind (data);
     324          10 :         while ((k = ksNext (data)) != 0)
     325             :         {
     326          14 :                 if (!isMarkedForEncryption (k) || isSpecNamespace (k))
     327             :                 {
     328           2 :                         continue;
     329             :                 }
     330             : 
     331           6 :                 if (!checkPayloadVersion (k, errorKey))
     332             :                 {
     333             :                         // error has been set by checkPayloadVersion()
     334             :                         goto error;
     335             :                 }
     336             : 
     337             : #if defined(ELEKTRA_CRYPTO_API_GCRYPT)
     338             : 
     339           6 :                 if (elektraCryptoGcryHandleCreate (&cryptoHandle, pluginConfig, errorKey, masterKey, k, ELEKTRA_CRYPTO_DECRYPT) != 1)
     340             :                 {
     341             :                         goto error;
     342             :                 }
     343             : 
     344           6 :                 if (elektraCryptoGcryDecrypt (cryptoHandle, k, errorKey) != 1)
     345             :                 {
     346           0 :                         elektraCryptoGcryHandleDestroy (cryptoHandle);
     347           0 :                         goto error;
     348             :                 }
     349             : 
     350           6 :                 elektraCryptoGcryHandleDestroy (cryptoHandle);
     351           6 :                 cryptoHandle = NULL;
     352             : 
     353             : #elif defined(ELEKTRA_CRYPTO_API_OPENSSL)
     354             : 
     355           0 :                 if (elektraCryptoOpenSSLHandleCreate (&cryptoHandle, pluginConfig, errorKey, masterKey, k, ELEKTRA_CRYPTO_DECRYPT) != 1)
     356             :                 {
     357           0 :                         elektraCryptoOpenSSLHandleDestroy (cryptoHandle);
     358           0 :                         goto error;
     359             :                 }
     360             : 
     361           0 :                 if (elektraCryptoOpenSSLDecrypt (cryptoHandle, k, errorKey) != 1)
     362             :                 {
     363           0 :                         elektraCryptoOpenSSLHandleDestroy (cryptoHandle);
     364           0 :                         goto error;
     365             :                 }
     366             : 
     367           0 :                 elektraCryptoOpenSSLHandleDestroy (cryptoHandle);
     368           0 :                 cryptoHandle = NULL;
     369             : 
     370             : #elif defined(ELEKTRA_CRYPTO_API_BOTAN)
     371             : 
     372           0 :                 if (elektraCryptoBotanDecrypt (pluginConfig, k, errorKey, masterKey) != 1)
     373             :                 {
     374             :                         goto error; // failure, error has been set by elektraCryptoBotanDecrypt
     375             :                 }
     376             : 
     377             : #endif
     378             :         }
     379           1 :         elektraCryptoSafelyReleaseKey (masterKey);
     380           1 :         return 1;
     381             : 
     382             : error:
     383           0 :         elektraCryptoSafelyReleaseKey (masterKey);
     384           0 :         return -1;
     385             : }
     386             : 
     387             : /**
     388             :  * @brief initialize the crypto provider for the first instance of the plugin.
     389             :  *
     390             :  * @param handle holds the plugin handle
     391             :  * @param errorKey holds an error description in case of failure
     392             :  * @retval 1 on success
     393             :  * @retval -1 on failure. Check errorKey
     394             :  */
     395          64 : int ELEKTRA_PLUGIN_FUNCTION (open) (Plugin * handle ELEKTRA_UNUSED, Key * errorKey)
     396             : {
     397          64 :         pthread_mutex_lock (&mutex_ref_cnt);
     398          64 :         if (ref_cnt == 0)
     399             :         {
     400          49 :                 if (elektraCryptoInit (errorKey) != 1)
     401             :                 {
     402           0 :                         pthread_mutex_unlock (&mutex_ref_cnt);
     403           0 :                         return -1;
     404             :                 }
     405             :         }
     406          64 :         ref_cnt++;
     407          64 :         pthread_mutex_unlock (&mutex_ref_cnt);
     408          64 :         return 1;
     409             : }
     410             : 
     411             : /**
     412             :  * @brief finalizes the crypto provider for the last instance of the plugin.
     413             :  *
     414             :  * @param handle holds the plugin handle
     415             :  * @param errorKey holds an error description in case of failure. Not used at the moment.
     416             :  * @retval 1 on success
     417             :  * @retval -1 on failure
     418             :  */
     419          65 : int ELEKTRA_PLUGIN_FUNCTION (close) (Plugin * handle, Key * errorKey ELEKTRA_UNUSED)
     420             : {
     421             :         /* default behaviour: no teardown except the user/system requests it */
     422          65 :         KeySet * pluginConfig = elektraPluginGetConfig (handle);
     423          65 :         if (!pluginConfig)
     424             :         {
     425             :                 return -1; // failure because of missing plugin config
     426             :         }
     427             : 
     428          65 :         Key * shutdown = ksLookupByName (pluginConfig, ELEKTRA_CRYPTO_PARAM_SHUTDOWN, 0);
     429          65 :         if (!shutdown)
     430             :         {
     431             :                 return 1; // applying default behaviour -> success
     432             :         }
     433             :         else
     434             :         {
     435           1 :                 if (strcmp (keyString (shutdown), "1") != 0)
     436             :                 {
     437             :                         return 1; // applying default behaviour -> success
     438             :                 }
     439             :         }
     440             : 
     441           1 :         pthread_mutex_lock (&mutex_ref_cnt);
     442           1 :         if (--ref_cnt == 0)
     443             :         {
     444             :                 elektraCryptoTeardown ();
     445             :         }
     446           1 :         pthread_mutex_unlock (&mutex_ref_cnt);
     447           1 :         return 1; // success
     448             : }
     449             : 
     450             : /**
     451             :  * @brief establish the Elektra plugin contract and decrypt values, if possible.
     452             :  *
     453             :  * The crypto configuration is expected to be contained within the KeySet ks.
     454             :  * All keys having a metakey "crypto/encrypted" with a strlen() > 0 are being decrypted.
     455             :  *
     456             :  * @param handle holds the plugin handle
     457             :  * @param ks holds the data to be operated on
     458             :  * @param parentKey holds an error description in case of failure
     459             :  * @retval 1 on success
     460             :  * @retval -1 on failure. Check parentKey.
     461             :  */
     462          62 : int ELEKTRA_PLUGIN_FUNCTION (get) (Plugin * handle, KeySet * ks, Key * parentKey)
     463             : {
     464             :         // Publish module configuration to Elektra (establish the contract)
     465          62 :         if (!strcmp (keyName (parentKey), "system/elektra/modules/" ELEKTRA_PLUGIN_NAME))
     466             :         {
     467          61 :                 KeySet * moduleConfig = ksNew (30,
     468             : #include "contract.h"
     469             :                                                KS_END);
     470          61 :                 ksAppend (ks, moduleConfig);
     471          61 :                 ksDel (moduleConfig);
     472          61 :                 return 1;
     473             :         }
     474             : 
     475           1 :         return elektraCryptoDecrypt (handle, ks, parentKey);
     476             : }
     477             : 
     478             : /**
     479             :  * @brief Encrypt values marked for encryption.
     480             :  *
     481             :  * If a key has the metakey "crypto/encrypt" with a strlen() > 0, then the value
     482             :  * will be encrypted using the configuration stored in the KeySet ks.
     483             :  *
     484             :  * @param handle holds the plugin handle
     485             :  * @param ks holds the data to be operated on
     486             :  * @param parentKey holds an error description in case of failure
     487             :  * @retval 1 on success
     488             :  * @retval -1 on failure. Check parentKey.
     489             :  */
     490           2 : int ELEKTRA_PLUGIN_FUNCTION (set) (Plugin * handle, KeySet * ks, Key * parentKey)
     491             : {
     492           2 :         return elektraCryptoEncrypt (handle, ks, parentKey);
     493             : }
     494             : 
     495             : /**
     496             :  * @brief Checks for the existence of the master password, that is used for encryption and decryption.
     497             :  *
     498             :  * If the master password can not be found it will be generated randomly.
     499             :  * Then it will be encrypted and stored in conf.
     500             :  *
     501             :  * If the master password can be found, it will be decrypted temporarily in order to verify its correctness.
     502             :  * conf will not be modified in this case.
     503             :  *
     504             :  * An error might occur during the password generation, encryption and decryption.
     505             :  * The error will be appended to errorKey.
     506             :  *
     507             :  * @param errorKey holds an error description in case of failure
     508             :  * @param conf holds the plugin configuration
     509             :  * @retval 0 no changes were made to the configuration
     510             :  * @retval 1 the master password has been appended to the configuration
     511             :  * @retval -1 an error occurred. Check errorKey
     512             :  */
     513           1 : int ELEKTRA_PLUGIN_FUNCTION (checkconf) (Key * errorKey, KeySet * conf)
     514             : {
     515           1 :         Key * k = ksLookupByName (conf, ELEKTRA_CRYPTO_PARAM_MASTER_PASSWORD, 0);
     516           1 :         if (k)
     517             :         {
     518             :                 // call gpg module to verify that we own the required key
     519           0 :                 Key * msg = keyDup (k);
     520           0 :                 if (ELEKTRA_PLUGIN_FUNCTION (gpgDecryptMasterPassword) (conf, errorKey, msg) != 1)
     521             :                 {
     522           0 :                         keyDel (msg);
     523           0 :                         return -1; // error set by ELEKTRA_PLUGIN_FUNCTION(gpgDecryptMasterPassword)()
     524             :                 }
     525           0 :                 keyDel (msg);
     526           0 :                 return 0;
     527             :         }
     528             :         else
     529             :         {
     530             :                 // generate random master password
     531           1 :                 const kdb_unsigned_short_t passwordLen = elektraCryptoGetRandomPasswordLength (errorKey, conf);
     532           1 :                 char * r = NULL;
     533           2 :                 if (elektraCryptoCreateRandomString (errorKey, &r, passwordLen) != 1)
     534             :                 {
     535             :                         return -1; // error set by elektraCryptoCreateRandomString()
     536             :                 }
     537             : 
     538             :                 // store password in configuration
     539           1 :                 k = keyNew ("user/" ELEKTRA_CRYPTO_PARAM_MASTER_PASSWORD, KEY_END);
     540           1 :                 keySetString (k, r);
     541           1 :                 elektraFree (r);
     542           1 :                 if (ELEKTRA_PLUGIN_FUNCTION (gpgEncryptMasterPassword) (conf, errorKey, k) != 1)
     543             :                 {
     544           0 :                         keyDel (k);
     545           0 :                         return -1; // error set by ELEKTRA_PLUGIN_FUNCTION(gpgEncryptMasterPassword)()
     546             :                 }
     547           1 :                 ksAppendKey (conf, k);
     548           1 :                 return 1;
     549             :         }
     550             : }
     551             : 
     552          63 : Plugin * ELEKTRA_PLUGIN_EXPORT
     553             : {
     554             :         // clang-format off
     555          63 :         return elektraPluginExport(ELEKTRA_PLUGIN_NAME,
     556             :                         ELEKTRA_PLUGIN_OPEN,  &ELEKTRA_PLUGIN_FUNCTION(open),
     557             :                         ELEKTRA_PLUGIN_CLOSE, &ELEKTRA_PLUGIN_FUNCTION(close),
     558             :                         ELEKTRA_PLUGIN_GET,   &ELEKTRA_PLUGIN_FUNCTION(get),
     559             :                         ELEKTRA_PLUGIN_SET,   &ELEKTRA_PLUGIN_FUNCTION(set),
     560             :                         ELEKTRA_PLUGIN_END);
     561             : }

Generated by: LCOV version 1.13