LCOV - code coverage report
Current view: top level - lib - fko_encryption.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 290 326 89.0 %
Date: 2015-08-23 Functions: 29 29 100.0 %
Branches: 221 348 63.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *****************************************************************************
       3                 :            :  *
       4                 :            :  * File:    fko_encryption.c
       5                 :            :  *
       6                 :            :  * Purpose: Set/Get the spa encryption type.
       7                 :            :  *
       8                 :            :  *  Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
       9                 :            :  *  Copyright (C) 2009-2014 fwknop developers and contributors. For a full
      10                 :            :  *  list of contributors, see the file 'CREDITS'.
      11                 :            :  *
      12                 :            :  *  License (GNU General Public License):
      13                 :            :  *
      14                 :            :  *  This program is free software; you can redistribute it and/or
      15                 :            :  *  modify it under the terms of the GNU General Public License
      16                 :            :  *  as published by the Free Software Foundation; either version 2
      17                 :            :  *  of the License, or (at your option) any later version.
      18                 :            :  *
      19                 :            :  *  This program is distributed in the hope that it will be useful,
      20                 :            :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      21                 :            :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      22                 :            :  *  GNU General Public License for more details.
      23                 :            :  *
      24                 :            :  *  You should have received a copy of the GNU General Public License
      25                 :            :  *  along with this program; if not, write to the Free Software
      26                 :            :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
      27                 :            :  *  USA
      28                 :            :  *
      29                 :            :  *****************************************************************************
      30                 :            : */
      31                 :            : #include "fko_common.h"
      32                 :            : #include "fko.h"
      33                 :            : #include "cipher_funcs.h"
      34                 :            : #include "base64.h"
      35                 :            : #include "digest.h"
      36                 :            : 
      37                 :            : #if HAVE_LIBGPGME
      38                 :            :   #include "gpgme_funcs.h"
      39                 :            :   #if HAVE_SYS_STAT_H
      40                 :            :     #include <sys/stat.h>
      41                 :            :   #endif
      42                 :            : #endif
      43                 :            : 
      44                 :            : /* Prep and encrypt using Rijndael
      45                 :            : */
      46                 :            : static int
      47                 :     802608 : _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key, const int enc_key_len)
      48                 :            : {
      49                 :            :     char           *plaintext;
      50                 :            :     char           *b64ciphertext;
      51                 :            :     unsigned char  *ciphertext;
      52                 :            :     int             cipher_len;
      53                 :            :     int             pt_len;
      54                 :     802608 :     int             zero_free_rv = FKO_SUCCESS;
      55                 :            : 
      56         [ +  + ]:     802608 :     if(enc_key_len < 0 || enc_key_len > RIJNDAEL_MAX_KEYSIZE)
      57                 :            :         return(FKO_ERROR_INVALID_KEY_LEN);
      58                 :            : 
      59         [ +  - ]:     800679 :     if (! is_valid_encoded_msg_len(ctx->encoded_msg_len))
      60                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_MSGLEN_VALIDFAIL);
      61                 :            : 
      62         [ +  - ]:     800679 :     switch(ctx->digest_len)
      63                 :            :     {
      64                 :            :         case MD5_B64_LEN:
      65                 :            :             break;
      66                 :            :         case SHA1_B64_LEN:
      67                 :            :             break;
      68                 :            :         case SHA256_B64_LEN:
      69                 :            :             break;
      70                 :            :         case SHA384_B64_LEN:
      71                 :            :             break;
      72                 :            :         case SHA512_B64_LEN:
      73                 :            :             break;
      74                 :            :         default:
      75                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_DIGESTLEN_VALIDFAIL);
      76                 :            :     }
      77                 :            : 
      78                 :     800679 :     pt_len = ctx->encoded_msg_len + ctx->digest_len + RIJNDAEL_BLOCKSIZE + 2;
      79                 :            : 
      80                 :            :     /* Make a bucket big enough to hold the enc msg + digest (plaintext)
      81                 :            :      * and populate it appropriately.
      82                 :            :     */
      83                 :     800679 :     plaintext = calloc(1, pt_len);
      84                 :            : 
      85         [ +  + ]:     800679 :     if(plaintext == NULL)
      86                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
      87                 :            : 
      88                 :    1601300 :     pt_len = snprintf(plaintext, pt_len, "%s:%s", ctx->encoded_msg, ctx->digest);
      89                 :            : 
      90         [ +  + ]:     800650 :     if(! is_valid_pt_msg_len(pt_len))
      91                 :            :     {
      92         [ -  + ]:          1 :         if(zero_free(plaintext, pt_len) == FKO_SUCCESS)
      93                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_PTLEN_VALIDFAIL);
      94                 :            :         else
      95                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
      96                 :            :     }
      97                 :            : 
      98                 :            :     /* Make a bucket for the encrypted version and populate it.
      99                 :            :     */
     100                 :     800649 :     ciphertext = calloc(1, pt_len + 32); /* Plus padding for salt and Block */
     101         [ +  + ]:     800649 :     if(ciphertext == NULL)
     102                 :            :     {
     103         [ -  + ]:         16 :         if(zero_free(plaintext, pt_len) == FKO_SUCCESS)
     104                 :            :             return(FKO_ERROR_MEMORY_ALLOCATION);
     105                 :            :         else
     106                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
     107                 :            :     }
     108                 :            : 
     109                 :     800633 :     cipher_len = rij_encrypt(
     110                 :            :         (unsigned char*)plaintext, pt_len,
     111                 :            :         (char*)enc_key, enc_key_len,
     112                 :            :         ciphertext, ctx->encryption_mode
     113                 :            :     );
     114                 :            : 
     115                 :            :     /* Now make a bucket for the base64-encoded version and populate it.
     116                 :            :     */
     117                 :     800633 :     b64ciphertext = calloc(1, ((cipher_len / 3) * 4) + 8);
     118         [ +  + ]:     800633 :     if(b64ciphertext == NULL)
     119                 :            :     {
     120         [ +  - ]:         16 :         if(zero_free((char *) ciphertext, pt_len+32) == FKO_SUCCESS
     121         [ -  + ]:         16 :                 && zero_free(plaintext, pt_len) == FKO_SUCCESS)
     122                 :            :             return(FKO_ERROR_MEMORY_ALLOCATION);
     123                 :            :         else
     124                 :            :             return(FKO_ERROR_ZERO_OUT_DATA);
     125                 :            :     }
     126                 :            : 
     127                 :     800617 :     b64_encode(ciphertext, b64ciphertext, cipher_len);
     128                 :     800617 :     strip_b64_eq(b64ciphertext);
     129                 :            : 
     130         [ +  + ]:     800617 :     if(ctx->encrypted_msg != NULL)
     131                 :       3819 :         zero_free_rv = zero_free(ctx->encrypted_msg,
     132                 :       3819 :                 strnlen(ctx->encrypted_msg, MAX_SPA_ENCODED_MSG_SIZE));
     133                 :            : 
     134                 :     800617 :     ctx->encrypted_msg = strdup(b64ciphertext);
     135                 :            : 
     136                 :            :     /* Clean-up
     137                 :            :     */
     138         [ +  + ]:     800617 :     if(zero_free(plaintext, pt_len) != FKO_SUCCESS)
     139                 :          2 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     140                 :            : 
     141         [ +  + ]:     800617 :     if(zero_free((char *) ciphertext, pt_len+32) != FKO_SUCCESS)
     142                 :       6578 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     143                 :            : 
     144         [ +  + ]:     800617 :     if(zero_free(b64ciphertext, strnlen(b64ciphertext,
     145                 :            :                     MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS)
     146                 :          2 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     147                 :            : 
     148         [ +  - ]:     800617 :     if(ctx->encrypted_msg == NULL)
     149                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     150                 :            : 
     151                 :     800617 :     ctx->encrypted_msg_len = strnlen(ctx->encrypted_msg, MAX_SPA_ENCODED_MSG_SIZE);
     152                 :            : 
     153         [ +  + ]:     800617 :     if(! is_valid_encoded_msg_len(ctx->encrypted_msg_len))
     154                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_RESULT_MSGLEN_VALIDFAIL);
     155                 :            : 
     156                 :     757185 :     return(zero_free_rv);
     157                 :            : }
     158                 :            : 
     159                 :            : /* Decode, decrypt, and parse SPA data into the context.
     160                 :            : */
     161                 :            : static int
     162                 :     552461 : _rijndael_decrypt(fko_ctx_t ctx,
     163                 :            :     const char *dec_key, const int key_len, int encryption_mode)
     164                 :            : {
     165                 :            :     unsigned char  *ndx;
     166                 :            :     unsigned char  *cipher;
     167                 :     552461 :     int             cipher_len=0, pt_len, i, err = 0, res = FKO_SUCCESS;
     168                 :     552461 :     int             zero_free_rv = FKO_SUCCESS;
     169                 :            : 
     170         [ +  + ]:     552461 :     if(key_len < 0 || key_len > RIJNDAEL_MAX_KEYSIZE)
     171                 :            :         return(FKO_ERROR_INVALID_KEY_LEN);
     172                 :            : 
     173                 :            :     /* Now see if we need to add the "Salted__" string to the front of the
     174                 :            :      * encrypted data.
     175                 :            :     */
     176         [ +  + ]:     552460 :     if(! ctx->added_salted_str)
     177                 :            :     {
     178                 :       4759 :         res = add_salted_str(ctx);
     179         [ +  - ]:       4759 :         if(res != FKO_SUCCESS)
     180                 :            :             return res;
     181                 :            :     }
     182                 :            : 
     183                 :            :     /* Create a bucket for the (base64) decoded encrypted data and get the
     184                 :            :      * raw cipher data.
     185                 :            :     */
     186                 :     552460 :     cipher = calloc(1, ctx->encrypted_msg_len);
     187         [ +  - ]:     552460 :     if(cipher == NULL)
     188                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     189                 :            : 
     190                 :            : #if AFL_FUZZING
     191                 :            :     cipher_len = ctx->encrypted_msg_len;
     192                 :            :     memcpy(cipher, ctx->encrypted_msg, ctx->encrypted_msg_len);
     193                 :            : #else
     194         [ -  + ]:     552460 :     if((cipher_len = b64_decode(ctx->encrypted_msg, cipher)) < 0)
     195                 :            :     {
     196         [ #  # ]:          0 :         if(zero_free((char *)cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
     197                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_CIPHERLEN_DECODEFAIL);
     198                 :            :         else
     199                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
     200                 :            :     }
     201                 :            : #endif
     202                 :            : 
     203                 :            :     /* Since we're using AES, make sure the incoming data is a multiple of
     204                 :            :      * the blocksize
     205                 :            :     */
     206         [ +  + ]:     552460 :     if((cipher_len % RIJNDAEL_BLOCKSIZE) != 0)
     207                 :            :     {
     208         [ -  + ]:         17 :         if(zero_free((char *)cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
     209                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_CIPHERLEN_VALIDFAIL);
     210                 :            :         else
     211                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
     212                 :            :     }
     213                 :            : 
     214         [ +  + ]:     552443 :     if(ctx->encoded_msg != NULL)
     215                 :          4 :         zero_free_rv = zero_free(ctx->encoded_msg,
     216                 :          4 :                 strnlen(ctx->encoded_msg, MAX_SPA_ENCODED_MSG_SIZE));
     217                 :            : 
     218                 :            :     /* Create a bucket for the plaintext data and decrypt the message
     219                 :            :      * data into it.
     220                 :            :     */
     221                 :     552443 :     ctx->encoded_msg = calloc(1, cipher_len);
     222         [ -  + ]:     552443 :     if(ctx->encoded_msg == NULL)
     223                 :            :     {
     224         [ #  # ]:          0 :         if(zero_free((char *)cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
     225                 :            :             return(FKO_ERROR_MEMORY_ALLOCATION);
     226                 :            :         else
     227                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
     228                 :            :     }
     229                 :            : 
     230                 :     552443 :     pt_len = rij_decrypt(cipher, cipher_len, dec_key, key_len,
     231                 :            :                 (unsigned char*)ctx->encoded_msg, encryption_mode);
     232                 :            : 
     233                 :            :     /* Done with cipher...
     234                 :            :     */
     235         [ -  + ]:     552443 :     if(zero_free((char *)cipher, ctx->encrypted_msg_len) != FKO_SUCCESS)
     236                 :          0 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     237                 :            : 
     238                 :            :     /* The length of the decrypted data should be within 32 bytes of the
     239                 :            :      * length of the encrypted version.
     240                 :            :     */
     241 [ +  - ][ +  - ]:     552443 :     if(pt_len < (cipher_len - 32) || pt_len <= 0)
     242                 :            :         return(FKO_ERROR_DECRYPTION_SIZE);
     243                 :            : 
     244         [ +  - ]:     552443 :     if(ctx->encoded_msg == NULL)
     245                 :            :         return(FKO_ERROR_MISSING_ENCODED_DATA);
     246                 :            : 
     247         [ +  - ]:     552443 :     if(! is_valid_encoded_msg_len(pt_len))
     248                 :            :         return(FKO_ERROR_INVALID_DATA_DECODE_MSGLEN_VALIDFAIL);
     249                 :            : 
     250         [ +  - ]:     552443 :     if(zero_free_rv != FKO_SUCCESS)
     251                 :            :         return(zero_free_rv);
     252                 :            : 
     253                 :     552443 :     ctx->encoded_msg_len = pt_len;
     254                 :            : 
     255                 :            :     /* At this point we can check the data to see if we have a good
     256                 :            :      * decryption by ensuring the first field (16-digit random decimal
     257                 :            :      * value) is valid and is followed by a colon.  Additional checks
     258                 :            :      * are made in fko_decode_spa_data().
     259                 :            :     */
     260                 :     552443 :     ndx = (unsigned char *)ctx->encoded_msg;
     261         [ +  + ]:    9391531 :     for(i=0; i<FKO_RAND_VAL_SIZE; i++)
     262         [ +  + ]:    8839088 :         if(!isdigit(*(ndx++)))
     263                 :     764030 :             err++;
     264                 :            : 
     265 [ +  + ][ +  + ]:     552443 :     if(err > 0 || *ndx != ':')
     266                 :            :         return(FKO_ERROR_DECRYPTION_FAILURE);
     267                 :            : 
     268                 :            :     /* Call fko_decode and return the results.
     269                 :            :     */
     270                 :     439669 :     return(fko_decode_spa_data(ctx));
     271                 :            : }
     272                 :            : 
     273                 :            : 
     274                 :            : #if HAVE_LIBGPGME
     275                 :            : 
     276                 :            : /* Prep and encrypt using gpgme
     277                 :            : */
     278                 :            : static int
     279                 :         85 : gpg_encrypt(fko_ctx_t ctx, const char *enc_key)
     280                 :            : {
     281                 :            :     int             res;
     282                 :            :     char           *plain;
     283                 :         85 :     int             pt_len, zero_free_rv = FKO_SUCCESS;
     284                 :            :     char           *b64cipher;
     285                 :         85 :     unsigned char  *cipher = NULL;
     286                 :            :     size_t          cipher_len;
     287                 :         85 :     char           *empty_key = "";
     288                 :            : 
     289         [ +  - ]:         85 :     if (! is_valid_encoded_msg_len(ctx->encoded_msg_len))
     290                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_MESSAGE_VALIDFAIL);
     291                 :            : 
     292         [ +  - ]:         85 :     switch(ctx->digest_len)
     293                 :            :     {
     294                 :            :         case MD5_B64_LEN:
     295                 :            :             break;
     296                 :            :         case SHA1_B64_LEN:
     297                 :            :             break;
     298                 :            :         case SHA256_B64_LEN:
     299                 :            :             break;
     300                 :            :         case SHA384_B64_LEN:
     301                 :            :             break;
     302                 :            :         case SHA512_B64_LEN:
     303                 :            :             break;
     304                 :            :         default:
     305                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_DIGEST_VALIDFAIL);
     306                 :            :     }
     307                 :            : 
     308                 :            :     /* First make sure we have a recipient key set.
     309                 :            :     */
     310         [ +  + ]:         85 :     if(ctx->gpg_recipient == NULL)
     311                 :            :         return(FKO_ERROR_MISSING_GPG_KEY_DATA);
     312                 :            : 
     313                 :         77 :     pt_len = ctx->encoded_msg_len + ctx->digest_len + 2;
     314                 :            : 
     315                 :            :     /* Make a bucket big enough to hold the enc msg + digest (plaintext)
     316                 :            :      * and populate it appropriately.
     317                 :            :     */
     318                 :         77 :     plain = calloc(1, ctx->encoded_msg_len + ctx->digest_len + 2);
     319         [ +  - ]:         77 :     if(plain == NULL)
     320                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     321                 :            : 
     322                 :        154 :     pt_len = snprintf(plain, pt_len+1, "%s:%s", ctx->encoded_msg, ctx->digest);
     323                 :            : 
     324         [ -  + ]:         77 :     if(! is_valid_pt_msg_len(pt_len))
     325                 :            :     {
     326         [ #  # ]:          0 :         if(zero_free(plain, pt_len) == FKO_SUCCESS)
     327                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_MSGLEN_VALIDFAIL);
     328                 :            :         else
     329                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
     330                 :            :     }
     331                 :            : 
     332         [ +  - ]:         77 :     if (enc_key != NULL)
     333                 :            :     {
     334                 :         77 :         res = gpgme_encrypt(ctx, (unsigned char*)plain, pt_len,
     335                 :            :             enc_key, &cipher, &cipher_len
     336                 :            :         );
     337                 :            :     }
     338                 :            :     else
     339                 :            :     {
     340                 :          0 :         res = gpgme_encrypt(ctx, (unsigned char*)plain, pt_len,
     341                 :            :             empty_key, &cipher, &cipher_len
     342                 :            :         );
     343                 :            :     }
     344                 :            : 
     345                 :            :     /* --DSS XXX: Better parsing of what went wrong would be nice :)
     346                 :            :     */
     347         [ -  + ]:         77 :     if(res != FKO_SUCCESS)
     348                 :            :     {
     349                 :          0 :         zero_free_rv = zero_free(plain, pt_len);
     350                 :            : 
     351         [ #  # ]:          0 :         if(cipher != NULL)
     352         [ #  # ]:          0 :             if(zero_free((char *) cipher, cipher_len) != FKO_SUCCESS)
     353                 :          0 :                 zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     354                 :            : 
     355         [ #  # ]:          0 :         if(zero_free_rv == FKO_SUCCESS)
     356                 :            :             return(res);
     357                 :            :         else
     358                 :          0 :             return(zero_free_rv);
     359                 :            :     }
     360                 :            : 
     361                 :            :     /* Now make a bucket for the base64-encoded version and populate it.
     362                 :            :     */
     363                 :         77 :     b64cipher = calloc(1, ((cipher_len / 3) * 4) + 8);
     364         [ -  + ]:         77 :     if(b64cipher == NULL)
     365                 :            :     {
     366         [ #  # ]:          0 :         if(zero_free(plain, pt_len) != FKO_SUCCESS)
     367                 :          0 :             zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     368                 :            : 
     369         [ #  # ]:          0 :         if(cipher != NULL)
     370         [ #  # ]:          0 :             if(zero_free((char *) cipher, cipher_len) != FKO_SUCCESS)
     371                 :          0 :                 zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     372                 :            : 
     373         [ #  # ]:          0 :         if(zero_free_rv == FKO_SUCCESS)
     374                 :            :             return(FKO_ERROR_MEMORY_ALLOCATION);
     375                 :            :         else
     376                 :          0 :             return(zero_free_rv);
     377                 :            :     }
     378                 :            : 
     379                 :         77 :     b64_encode(cipher, b64cipher, cipher_len);
     380                 :         77 :     strip_b64_eq(b64cipher);
     381                 :            : 
     382         [ -  + ]:         77 :     if(ctx->encrypted_msg != NULL)
     383                 :          0 :         zero_free_rv = zero_free(ctx->encrypted_msg,
     384                 :          0 :                 strnlen(ctx->encrypted_msg, MAX_SPA_ENCODED_MSG_SIZE));
     385                 :            : 
     386                 :         77 :     ctx->encrypted_msg = strdup(b64cipher);
     387                 :            : 
     388                 :            :     /* Clean-up
     389                 :            :     */
     390         [ -  + ]:         77 :     if(zero_free(plain, pt_len) != FKO_SUCCESS)
     391                 :          0 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     392                 :            : 
     393         [ -  + ]:         77 :     if(zero_free((char *) cipher, cipher_len) != FKO_SUCCESS)
     394                 :          0 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     395                 :            : 
     396         [ -  + ]:         77 :     if(zero_free(b64cipher, strnlen(b64cipher,
     397                 :            :                     MAX_SPA_ENCODED_MSG_SIZE)) != FKO_SUCCESS)
     398                 :          0 :         zero_free_rv = FKO_ERROR_ZERO_OUT_DATA;
     399                 :            : 
     400         [ +  - ]:         77 :     if(ctx->encrypted_msg == NULL)
     401                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     402                 :            : 
     403                 :         77 :     ctx->encrypted_msg_len = strnlen(ctx->encrypted_msg, MAX_SPA_ENCODED_MSG_SIZE);
     404                 :            : 
     405         [ +  + ]:         77 :     if(! is_valid_encoded_msg_len(ctx->encrypted_msg_len))
     406                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_RESULT_MSGLEN_VALIDFAIL);
     407                 :            : 
     408                 :         76 :     return(zero_free_rv);
     409                 :            : }
     410                 :            : 
     411                 :            : /* Prep and decrypt using gpgme
     412                 :            : */
     413                 :            : static int
     414                 :         68 : gpg_decrypt(fko_ctx_t ctx, const char *dec_key)
     415                 :            : {
     416                 :            :     unsigned char  *cipher;
     417                 :            :     size_t          cipher_len;
     418                 :            :     int             res, pt_len, b64_decode_len;
     419                 :            : 
     420                 :            :     /* Now see if we need to add the "hQ" string to the front of the
     421                 :            :      * base64-encoded-GPG-encrypted data.
     422                 :            :     */
     423         [ +  + ]:         68 :     if(! ctx->added_gpg_prefix)
     424                 :         45 :         add_gpg_prefix(ctx);
     425                 :            : 
     426                 :            :     /* Create a bucket for the (base64) decoded encrypted data and get the
     427                 :            :      * raw cipher data.
     428                 :            :     */
     429                 :         68 :     cipher = calloc(1, ctx->encrypted_msg_len);
     430         [ +  - ]:         68 :     if(cipher == NULL)
     431                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     432                 :            : 
     433         [ -  + ]:         68 :     if((b64_decode_len = b64_decode(ctx->encrypted_msg, cipher)) < 0)
     434                 :            :     {
     435         [ #  # ]:          0 :         if(zero_free((char *) cipher, ctx->encrypted_msg_len) == FKO_SUCCESS)
     436                 :            :             return(FKO_ERROR_INVALID_DATA_ENCRYPT_GPG_CIPHER_DECODEFAIL);
     437                 :            :         else
     438                 :          0 :             return(FKO_ERROR_ZERO_OUT_DATA);
     439                 :            : 
     440                 :            :     }
     441                 :            : 
     442                 :         68 :     cipher_len = b64_decode_len;
     443                 :            : 
     444                 :            :     /* Create a bucket for the plaintext data and decrypt the message
     445                 :            :      * data into it.
     446                 :            :     */
     447                 :            :     /* --DSS Actually, the needed memory will be malloced in the gpgme_decrypt
     448                 :            :     //       function. Just leaving this here for reference (for now).
     449                 :            :     //ctx->encoded_msg = malloc(cipher_len);
     450                 :            :     //if(ctx->encoded_msg == NULL)
     451                 :            :     //    return(FKO_ERROR_MEMORY_ALLOCATION);
     452                 :            :     */
     453                 :            : 
     454                 :         68 :     res = gpgme_decrypt(ctx, cipher, cipher_len,
     455                 :         68 :         dec_key, (unsigned char**)&ctx->encoded_msg, &cipher_len
     456                 :            :     );
     457                 :            : 
     458                 :            :     /* Done with cipher...
     459                 :            :     */
     460         [ +  - ]:         68 :     if(zero_free((char *) cipher, ctx->encrypted_msg_len) != FKO_SUCCESS)
     461                 :            :         return(FKO_ERROR_ZERO_OUT_DATA);
     462                 :            :     else
     463         [ +  + ]:         68 :         if(res != FKO_SUCCESS) /* bail if there was some other problem */
     464                 :            :             return(res);
     465                 :            : 
     466                 :         61 :     pt_len = strnlen(ctx->encoded_msg, MAX_SPA_ENCODED_MSG_SIZE);
     467                 :            : 
     468         [ +  - ]:         61 :     if(ctx->encoded_msg == NULL)
     469                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_DECRYPTED_MESSAGE_MISSING);
     470                 :            : 
     471         [ +  - ]:         61 :     if(! is_valid_encoded_msg_len(pt_len))
     472                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_DECRYPTED_MSGLEN_VALIDFAIL);
     473                 :            : 
     474                 :         61 :     ctx->encoded_msg_len = pt_len;
     475                 :            : 
     476                 :            :     /* Call fko_decode and return the results.
     477                 :            :     */
     478                 :         61 :     return(fko_decode_spa_data(ctx));
     479                 :            : }
     480                 :            : 
     481                 :            : #endif /* HAVE_LIBGPGME */
     482                 :            : 
     483                 :            : /* Set the SPA encryption type.
     484                 :            : */
     485                 :            : int
     486                 :     871550 : fko_set_spa_encryption_type(fko_ctx_t ctx, const short encrypt_type)
     487                 :            : {
     488                 :            : #if HAVE_LIBFIU
     489         [ +  + ]:     871550 :     fiu_return_on("fko_set_spa_encryption_type_init",
     490                 :            :             FKO_ERROR_CTX_NOT_INITIALIZED);
     491                 :            : #endif
     492                 :            :     /* Must be initialized
     493                 :            :     */
     494 [ +  + ][ +  - ]:     871547 :     if(!CTX_INITIALIZED(ctx))
     495                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     496                 :            : 
     497                 :            : #if HAVE_LIBFIU
     498         [ +  + ]:     870725 :     fiu_return_on("fko_set_spa_encryption_type_val",
     499                 :            :             FKO_ERROR_INVALID_DATA_ENCRYPT_TYPE_VALIDFAIL);
     500                 :            : #endif
     501         [ +  + ]:     870722 :     if(encrypt_type < 0 || encrypt_type >= FKO_LAST_ENCRYPTION_TYPE)
     502                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_TYPE_VALIDFAIL);
     503                 :            : 
     504                 :     866681 :     ctx->encryption_type = encrypt_type;
     505                 :            : 
     506                 :     866681 :     ctx->state |= FKO_ENCRYPT_TYPE_MODIFIED;
     507                 :            : 
     508                 :     866681 :     return(FKO_SUCCESS);
     509                 :            : }
     510                 :            : 
     511                 :            : /* Return the SPA encryption type.
     512                 :            : */
     513                 :            : int
     514                 :       4777 : fko_get_spa_encryption_type(fko_ctx_t ctx, short *enc_type)
     515                 :            : {
     516                 :            :     /* Must be initialized
     517                 :            :     */
     518 [ +  + ][ +  - ]:       4777 :     if(!CTX_INITIALIZED(ctx))
     519                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     520                 :            : 
     521                 :       4367 :     *enc_type = ctx->encryption_type;
     522                 :            : 
     523                 :       4367 :     return(FKO_SUCCESS);
     524                 :            : }
     525                 :            : 
     526                 :            : /* Set the SPA encryption mode.
     527                 :            : */
     528                 :            : int
     529                 :    1664162 : fko_set_spa_encryption_mode(fko_ctx_t ctx, const int encrypt_mode)
     530                 :            : {
     531                 :            : #if HAVE_LIBFIU
     532         [ +  + ]:    1664162 :     fiu_return_on("fko_set_spa_encryption_mode_init",
     533                 :            :             FKO_ERROR_CTX_NOT_INITIALIZED);
     534                 :            : #endif
     535                 :            :     /* Must be initialized
     536                 :            :     */
     537 [ +  + ][ +  - ]:    1664158 :     if(!CTX_INITIALIZED(ctx))
     538                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     539                 :            : 
     540                 :            : #if HAVE_LIBFIU
     541         [ +  + ]:    1663316 :     fiu_return_on("fko_set_spa_encryption_mode_val",
     542                 :            :             FKO_ERROR_INVALID_DATA_ENCRYPT_MODE_VALIDFAIL);
     543                 :            : #endif
     544         [ +  + ]:    1663312 :     if(encrypt_mode < 0 || encrypt_mode >= FKO_LAST_ENC_MODE)
     545                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_MODE_VALIDFAIL);
     546                 :            : 
     547                 :    1659292 :     ctx->encryption_mode = encrypt_mode;
     548                 :            : 
     549                 :    1659292 :     ctx->state |= FKO_ENCRYPT_MODE_MODIFIED;
     550                 :            : 
     551                 :    1659292 :     return(FKO_SUCCESS);
     552                 :            : }
     553                 :            : 
     554                 :            : /* Return the SPA encryption mode.
     555                 :            : */
     556                 :            : int
     557                 :       5211 : fko_get_spa_encryption_mode(fko_ctx_t ctx, int *enc_mode)
     558                 :            : {
     559                 :            :     /* Must be initialized
     560                 :            :     */
     561 [ +  + ][ +  - ]:       5211 :     if(!CTX_INITIALIZED(ctx))
     562                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     563                 :            : 
     564         [ +  + ]:       4639 :     if(enc_mode == NULL)
     565                 :            :         return(FKO_ERROR_INVALID_DATA);
     566                 :            : 
     567                 :       4571 :     *enc_mode = ctx->encryption_mode;
     568                 :            : 
     569                 :       4571 :     return(FKO_SUCCESS);
     570                 :            : }
     571                 :            : 
     572                 :            : /* Encrypt the encoded SPA data.
     573                 :            : */
     574                 :            : int
     575                 :     866579 : fko_encrypt_spa_data(fko_ctx_t ctx, const char * const enc_key,
     576                 :            :         const int enc_key_len)
     577                 :            : {
     578                 :     866579 :     int             res = 0;
     579                 :            : 
     580                 :            :     /* Must be initialized
     581                 :            :     */
     582 [ +  - ][ +  - ]:     866579 :     if(!CTX_INITIALIZED(ctx))
     583                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     584                 :            : 
     585         [ +  - ]:     866579 :     if(enc_key_len < 0)
     586                 :            :         return(FKO_ERROR_INVALID_KEY_LEN);
     587                 :            : 
     588                 :            :     /* If there is no encoded data or the SPA data has been modified,
     589                 :            :      * go ahead and re-encode here.
     590                 :            :     */
     591 [ +  + ][ +  + ]:     866579 :     if(ctx->encoded_msg == NULL || FKO_IS_SPA_DATA_MODIFIED(ctx))
     592                 :      57340 :         res = fko_encode_spa_data(ctx);
     593                 :            : 
     594         [ +  + ]:     866579 :     if(res != FKO_SUCCESS)
     595                 :            :         return(res);
     596                 :            : 
     597                 :            :     /* Croak on invalid encoded message as well. At present this is a
     598                 :            :      * check for a somewhat arbitrary minimum length for the encoded
     599                 :            :      * data.
     600                 :            :     */
     601         [ +  + ]:     811765 :     if (! is_valid_encoded_msg_len(ctx->encoded_msg_len))
     602                 :            :         return(FKO_ERROR_MISSING_ENCODED_DATA);
     603                 :            : 
     604                 :            :     /* Encrypt according to type and return...
     605                 :            :     */
     606         [ +  + ]:     805093 :     if(ctx->encryption_type == FKO_ENCRYPTION_RIJNDAEL)
     607                 :            :     {
     608         [ +  + ]:     805008 :         if(enc_key == NULL)
     609                 :            :             return(FKO_ERROR_INVALID_KEY_LEN);
     610                 :     802608 :         res = _rijndael_encrypt(ctx, enc_key, enc_key_len);
     611                 :            :     }
     612         [ +  - ]:         85 :     else if(ctx->encryption_type == FKO_ENCRYPTION_GPG)
     613                 :            : #if HAVE_LIBGPGME
     614                 :         85 :         res = gpg_encrypt(ctx, enc_key);
     615                 :            : #else
     616                 :            :         res = FKO_ERROR_UNSUPPORTED_FEATURE;
     617                 :            : #endif
     618                 :            :     else
     619                 :            :         res = FKO_ERROR_INVALID_ENCRYPTION_TYPE;
     620                 :            : 
     621                 :     802693 :     return(res);
     622                 :            : }
     623                 :            : 
     624                 :            : /* Decode, decrypt, and parse SPA data into the context.
     625                 :            : */
     626                 :            : int
     627                 :     772917 : fko_decrypt_spa_data(fko_ctx_t ctx, const char * const dec_key, const int key_len)
     628                 :            : {
     629                 :            :     int     enc_type, res;
     630                 :            : 
     631 [ +  + ][ +  - ]:     772917 :     if(!CTX_INITIALIZED(ctx))
     632                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     633                 :            : 
     634         [ +  - ]:     772857 :     if(key_len < 0)
     635                 :            :         return(FKO_ERROR_INVALID_KEY_LEN);
     636                 :            : 
     637                 :            :     /* Get the (assumed) type of encryption used. This will also provide
     638                 :            :      * some data validation.
     639                 :            :     */
     640                 :     772857 :     enc_type = fko_encryption_type(ctx->encrypted_msg);
     641                 :            : 
     642         [ +  + ]:     772857 :     if(enc_type == FKO_ENCRYPTION_GPG
     643         [ +  + ]:     220302 :             && ctx->encryption_mode == FKO_ENC_MODE_ASYMMETRIC)
     644                 :            :     {
     645                 :         68 :         ctx->encryption_type = FKO_ENCRYPTION_GPG;
     646                 :            : #if HAVE_LIBGPGME
     647                 :         68 :         res = gpg_decrypt(ctx, dec_key);
     648                 :            : #else
     649                 :            :         res = FKO_ERROR_UNSUPPORTED_FEATURE;
     650                 :            : #endif
     651                 :            :     }
     652         [ +  + ]:     772789 :     else if(enc_type == FKO_ENCRYPTION_RIJNDAEL)
     653                 :            :     {
     654                 :     552461 :         ctx->encryption_type = FKO_ENCRYPTION_RIJNDAEL;
     655                 :     552461 :         res = _rijndael_decrypt(ctx,
     656                 :            :             dec_key, key_len, ctx->encryption_mode);
     657                 :            :     }
     658                 :            :     else
     659                 :            :         return(FKO_ERROR_INVALID_DATA_ENCRYPT_TYPE_UNKNOWN);
     660                 :            : 
     661                 :     552529 :     return(res);
     662                 :            : }
     663                 :            : 
     664                 :            : /* Return the assumed encryption type based on the raw encrypted data.
     665                 :            : */
     666                 :            : int
     667                 :     789691 : fko_encryption_type(const char * const enc_data)
     668                 :            : {
     669                 :            :     int enc_data_len;
     670                 :            : 
     671                 :            :     /* Sanity check the data.
     672                 :            :     */
     673         [ +  + ]:     789691 :     if(enc_data == NULL)
     674                 :            :         return(FKO_ENCRYPTION_INVALID_DATA);
     675                 :            : 
     676                 :     789597 :     enc_data_len = strnlen(enc_data, MAX_SPA_ENCODED_MSG_SIZE);
     677                 :            : 
     678         [ +  - ]:     789597 :     if(! is_valid_encoded_msg_len(enc_data_len))
     679                 :            :         return(FKO_ENCRYPTION_UNKNOWN);
     680                 :            : 
     681         [ +  + ]:     789597 :     if(enc_data_len >= MIN_GNUPG_MSG_SIZE)
     682                 :            :         return(FKO_ENCRYPTION_GPG);
     683                 :            : 
     684         [ -  + ]:     565051 :     else if(enc_data_len < MIN_GNUPG_MSG_SIZE
     685                 :     565051 :       && enc_data_len >= MIN_SPA_ENCODED_MSG_SIZE)
     686                 :            :         return(FKO_ENCRYPTION_RIJNDAEL);
     687                 :            : 
     688                 :            :     else
     689                 :          0 :         return(FKO_ENCRYPTION_UNKNOWN);
     690                 :            : }
     691                 :            : 
     692                 :            : /* Set the GPG recipient key name.
     693                 :            : */
     694                 :            : int
     695                 :        142 : fko_set_gpg_recipient(fko_ctx_t ctx, const char * const recip)
     696                 :            : {
     697                 :            : #if HAVE_LIBGPGME
     698                 :            :     int             res;
     699                 :        142 :     gpgme_key_t     key     = NULL;
     700                 :            : 
     701                 :            :     /* Must be initialized
     702                 :            :     */
     703 [ +  - ][ +  - ]:        142 :     if(!CTX_INITIALIZED(ctx))
     704                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     705                 :            : 
     706         [ +  + ]:        142 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
     707                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
     708                 :            : 
     709         [ -  + ]:         79 :     if(ctx->gpg_recipient != NULL)
     710                 :          0 :         free(ctx->gpg_recipient);
     711                 :            : 
     712                 :         79 :     ctx->gpg_recipient = strdup(recip);
     713         [ +  - ]:         79 :     if(ctx->gpg_recipient == NULL)
     714                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     715                 :            : 
     716                 :            :     /* Get the key.
     717                 :            :     */
     718                 :         79 :     res = get_gpg_key(ctx, &key, 0);
     719         [ +  + ]:         79 :     if(res != FKO_SUCCESS)
     720                 :            :     {
     721                 :          1 :         free(ctx->gpg_recipient);
     722                 :          1 :         ctx->gpg_recipient = NULL;
     723                 :          1 :         return(res);
     724                 :            :     }
     725                 :            : 
     726                 :         78 :     ctx->recipient_key = key;
     727                 :            : 
     728                 :         78 :     ctx->state |= FKO_DATA_MODIFIED;
     729                 :            : 
     730                 :         78 :     return(FKO_SUCCESS);
     731                 :            : #else
     732                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     733                 :            : #endif  /* HAVE_LIBGPGME */
     734                 :            : }
     735                 :            : 
     736                 :            : /* Set the GPG home dir.
     737                 :            : */
     738                 :            : int
     739                 :          6 : fko_set_gpg_exe(fko_ctx_t ctx, const char * const gpg_exe)
     740                 :            : {
     741                 :            : #if HAVE_LIBGPGME
     742                 :            :     struct stat     st;
     743                 :            : 
     744                 :            :     /* Must be initialized
     745                 :            :     */
     746 [ +  - ][ +  - ]:          6 :     if(!CTX_INITIALIZED(ctx))
     747                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     748                 :            : 
     749                 :            :     /* If we are unable to stat the given path/file and determine if it
     750                 :            :      * is a regular file or symbolic link, then return with error.
     751                 :            :     */
     752         [ +  + ]:          6 :     if(stat(gpg_exe, &st) != 0)
     753                 :            :         return(FKO_ERROR_GPGME_BAD_GPG_EXE);
     754                 :            : 
     755         [ +  - ]:          2 :     if(!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
     756                 :            :         return(FKO_ERROR_GPGME_BAD_GPG_EXE);
     757                 :            : 
     758         [ -  + ]:          2 :     if(ctx->gpg_exe != NULL)
     759                 :          0 :         free(ctx->gpg_exe);
     760                 :            : 
     761                 :          2 :     ctx->gpg_exe = strdup(gpg_exe);
     762         [ +  - ]:          2 :     if(ctx->gpg_exe == NULL)
     763                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     764                 :            : 
     765                 :          2 :     return(FKO_SUCCESS);
     766                 :            : #else
     767                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     768                 :            : #endif  /* HAVE_LIBGPGME */
     769                 :            : }
     770                 :            : 
     771                 :            : /* Get the GPG home dir.
     772                 :            : */
     773                 :            : int
     774                 :        137 : fko_get_gpg_exe(fko_ctx_t ctx, char **gpg_exe)
     775                 :            : {
     776                 :            : #if HAVE_LIBGPGME
     777                 :            :     /* Must be initialized
     778                 :            :     */
     779 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
     780                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     781                 :            : 
     782                 :        137 :     *gpg_exe = ctx->gpg_exe;
     783                 :            : 
     784                 :        137 :     return(FKO_SUCCESS);
     785                 :            : #else
     786                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     787                 :            : #endif  /* HAVE_LIBGPGME */
     788                 :            : }
     789                 :            : 
     790                 :            : /* Get the GPG recipient key name.
     791                 :            : */
     792                 :            : int
     793                 :        137 : fko_get_gpg_recipient(fko_ctx_t ctx, char **recipient)
     794                 :            : {
     795                 :            : #if HAVE_LIBGPGME
     796                 :            :     /* Must be initialized
     797                 :            :     */
     798 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
     799                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     800                 :            : 
     801                 :        137 :     *recipient = ctx->gpg_recipient;
     802                 :            : 
     803                 :        137 :     return(FKO_SUCCESS);
     804                 :            : #else
     805                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     806                 :            : #endif  /* HAVE_LIBGPGME */
     807                 :            : }
     808                 :            : 
     809                 :            : /* Set the GPG signer key name.
     810                 :            : */
     811                 :            : int
     812                 :         78 : fko_set_gpg_signer(fko_ctx_t ctx, const char * const signer)
     813                 :            : {
     814                 :            : #if HAVE_LIBGPGME
     815                 :            :     int             res;
     816                 :         78 :     gpgme_key_t     key     = NULL;
     817                 :            : 
     818                 :            :     /* Must be initialized
     819                 :            :     */
     820 [ +  - ][ +  - ]:         78 :     if(!CTX_INITIALIZED(ctx))
     821                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     822                 :            : 
     823         [ +  - ]:         78 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
     824                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
     825                 :            : 
     826         [ -  + ]:         78 :     if(ctx->gpg_signer != NULL)
     827                 :          0 :         free(ctx->gpg_signer);
     828                 :            : 
     829                 :         78 :     ctx->gpg_signer = strdup(signer);
     830         [ +  - ]:         78 :     if(ctx->gpg_signer == NULL)
     831                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     832                 :            : 
     833                 :            :     /* Get the key.
     834                 :            :     */
     835                 :         78 :     res = get_gpg_key(ctx, &key, 1);
     836         [ +  + ]:         78 :     if(res != FKO_SUCCESS)
     837                 :            :     {
     838                 :          1 :         free(ctx->gpg_signer);
     839                 :          1 :         ctx->gpg_signer = NULL;
     840                 :          1 :         return(res);
     841                 :            :     }
     842                 :            : 
     843                 :         77 :     ctx->signer_key = key;
     844                 :            : 
     845                 :         77 :     ctx->state |= FKO_DATA_MODIFIED;
     846                 :            : 
     847                 :         77 :     return(FKO_SUCCESS);
     848                 :            : #else
     849                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     850                 :            : #endif  /* HAVE_LIBGPGME */
     851                 :            : }
     852                 :            : 
     853                 :            : /* Get the GPG signer key name.
     854                 :            : */
     855                 :            : int
     856                 :        137 : fko_get_gpg_signer(fko_ctx_t ctx, char **signer)
     857                 :            : {
     858                 :            : #if HAVE_LIBGPGME
     859                 :            :     /* Must be initialized
     860                 :            :     */
     861 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
     862                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     863                 :            : 
     864                 :        137 :     *signer = ctx->gpg_signer;
     865                 :            : 
     866                 :        137 :     return(FKO_SUCCESS);
     867                 :            : #else
     868                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     869                 :            : #endif  /* HAVE_LIBGPGME */
     870                 :            : }
     871                 :            : 
     872                 :            : /* Set the GPG home dir.
     873                 :            : */
     874                 :            : int
     875                 :        148 : fko_set_gpg_home_dir(fko_ctx_t ctx, const char * const gpg_home_dir)
     876                 :            : {
     877                 :            : #if HAVE_LIBGPGME
     878                 :            :     struct stat     st;
     879                 :            : 
     880                 :            :     /* Must be initialized
     881                 :            :     */
     882 [ +  - ][ +  - ]:        148 :     if(!CTX_INITIALIZED(ctx))
     883                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     884                 :            : 
     885                 :            :     /* If we are unable to stat the given dir, then return with error.
     886                 :            :     */
     887         [ +  + ]:        148 :     if(stat(gpg_home_dir, &st) != 0)
     888                 :            :         return(FKO_ERROR_GPGME_BAD_HOME_DIR);
     889                 :            : 
     890         [ +  - ]:        147 :     if(!S_ISDIR(st.st_mode))
     891                 :            :         return(FKO_ERROR_GPGME_BAD_HOME_DIR);
     892                 :            : 
     893         [ -  + ]:        147 :     if(ctx->gpg_home_dir != NULL)
     894                 :          0 :         free(ctx->gpg_home_dir);
     895                 :            : 
     896                 :        147 :     ctx->gpg_home_dir = strdup(gpg_home_dir);
     897         [ +  - ]:        147 :     if(ctx->gpg_home_dir == NULL)
     898                 :            :         return(FKO_ERROR_MEMORY_ALLOCATION);
     899                 :            : 
     900                 :        147 :     return(FKO_SUCCESS);
     901                 :            : #else
     902                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     903                 :            : #endif  /* HAVE_LIBGPGME */
     904                 :            : }
     905                 :            : 
     906                 :            : /* Get the GPG home dir.
     907                 :            : */
     908                 :            : int
     909                 :        137 : fko_get_gpg_home_dir(fko_ctx_t ctx, char **home_dir)
     910                 :            : {
     911                 :            : #if HAVE_LIBGPGME
     912                 :            :     /* Must be initialized
     913                 :            :     */
     914 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
     915                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     916                 :            : 
     917                 :        137 :     *home_dir = ctx->gpg_home_dir;
     918                 :            : 
     919                 :        137 :     return(FKO_SUCCESS);
     920                 :            : #else
     921                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     922                 :            : #endif  /* HAVE_LIBGPGME */
     923                 :            : }
     924                 :            : 
     925                 :            : int
     926                 :         63 : fko_set_gpg_signature_verify(fko_ctx_t ctx, const unsigned char val)
     927                 :            : {
     928                 :            : #if HAVE_LIBGPGME
     929                 :            :     /* Must be initialized
     930                 :            :     */
     931 [ +  - ][ +  - ]:         63 :     if(!CTX_INITIALIZED(ctx))
     932                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     933                 :            : 
     934                 :         63 :     ctx->verify_gpg_sigs = (val != 0) ? 1 : 0;
     935                 :            : 
     936                 :         63 :     return(FKO_SUCCESS);
     937                 :            : #else
     938                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     939                 :            : #endif  /* HAVE_LIBGPGME */
     940                 :            : }
     941                 :            : 
     942                 :            : int
     943                 :        137 : fko_get_gpg_signature_verify(fko_ctx_t ctx, unsigned char * const val)
     944                 :            : {
     945                 :            : #if HAVE_LIBGPGME
     946                 :            :     /* Must be initialized
     947                 :            :     */
     948 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
     949                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     950                 :            : 
     951                 :        137 :     *val = ctx->verify_gpg_sigs;
     952                 :            : 
     953                 :        137 :     return(FKO_SUCCESS);
     954                 :            : #else
     955                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     956                 :            : #endif  /* HAVE_LIBGPGME */
     957                 :            : }
     958                 :            : 
     959                 :            : int
     960                 :         63 : fko_set_gpg_ignore_verify_error(fko_ctx_t ctx, const unsigned char val)
     961                 :            : {
     962                 :            : #if HAVE_LIBGPGME
     963                 :            :     /* Must be initialized
     964                 :            :     */
     965 [ +  - ][ +  - ]:         63 :     if(!CTX_INITIALIZED(ctx))
     966                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     967                 :            : 
     968                 :         63 :     ctx->ignore_gpg_sig_error = (val != 0) ? 1 : 0;
     969                 :            : 
     970                 :         63 :     return(FKO_SUCCESS);
     971                 :            : #else
     972                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     973                 :            : #endif  /* HAVE_LIBGPGME */
     974                 :            : }
     975                 :            : 
     976                 :            : int
     977                 :        137 : fko_get_gpg_ignore_verify_error(fko_ctx_t ctx, unsigned char * const val)
     978                 :            : {
     979                 :            : #if HAVE_LIBGPGME
     980                 :            :     /* Must be initialized
     981                 :            :     */
     982 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
     983                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
     984                 :            : 
     985                 :        137 :     *val = ctx->ignore_gpg_sig_error;
     986                 :            : 
     987                 :        137 :     return(FKO_SUCCESS);
     988                 :            : #else
     989                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
     990                 :            : #endif  /* HAVE_LIBGPGME */
     991                 :            : }
     992                 :            : 
     993                 :            : 
     994                 :            : int
     995                 :        192 : fko_get_gpg_signature_fpr(fko_ctx_t ctx, char **fpr)
     996                 :            : {
     997                 :            : #if HAVE_LIBGPGME
     998                 :            :     /* Must be initialized
     999                 :            :     */
    1000 [ +  - ][ +  - ]:        192 :     if(!CTX_INITIALIZED(ctx))
    1001                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
    1002                 :            : 
    1003                 :            :     /* Must be using GPG encryption.
    1004                 :            :     */
    1005         [ +  - ]:        192 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
    1006                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
    1007                 :            : 
    1008                 :            :     /* Make sure we are supposed to verify signatures.
    1009                 :            :     */
    1010         [ +  + ]:        192 :     if(ctx->verify_gpg_sigs == 0)
    1011                 :            :         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
    1012                 :            : 
    1013                 :            :     /* Make sure we have a signature to work with.
    1014                 :            :     */
    1015         [ +  + ]:        191 :     if(ctx->gpg_sigs == NULL)
    1016                 :            :         return(FKO_ERROR_GPGME_NO_SIGNATURE);
    1017                 :            : 
    1018                 :        115 :     *fpr = ctx->gpg_sigs->fpr;
    1019                 :            : 
    1020                 :        115 :     return(FKO_SUCCESS);
    1021                 :            : #else
    1022                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
    1023                 :            : #endif  /* HAVE_LIBGPGME */
    1024                 :            : }
    1025                 :            : 
    1026                 :            : int
    1027                 :        245 : fko_get_gpg_signature_id(fko_ctx_t ctx, char **id)
    1028                 :            : {
    1029                 :            : #if HAVE_LIBGPGME
    1030                 :            :     /* Must be initialized
    1031                 :            :     */
    1032 [ +  - ][ +  - ]:        245 :     if(!CTX_INITIALIZED(ctx))
    1033                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
    1034                 :            : 
    1035                 :            :     /* Must be using GPG encryption.
    1036                 :            :     */
    1037         [ +  - ]:        245 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
    1038                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
    1039                 :            : 
    1040                 :            :     /* Make sure we are supposed to verify signatures.
    1041                 :            :     */
    1042         [ +  + ]:        245 :     if(ctx->verify_gpg_sigs == 0)
    1043                 :            :         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
    1044                 :            : 
    1045                 :            :     /* Make sure we have a signature to work with.
    1046                 :            :     */
    1047         [ +  + ]:        244 :     if(ctx->gpg_sigs == NULL)
    1048                 :            :         return(FKO_ERROR_GPGME_NO_SIGNATURE);
    1049                 :            : 
    1050                 :        168 :     *id = ctx->gpg_sigs->fpr + strlen(ctx->gpg_sigs->fpr) - 8;
    1051                 :            : 
    1052                 :        168 :     return(FKO_SUCCESS);
    1053                 :            : #else
    1054                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
    1055                 :            : #endif  /* HAVE_LIBGPGME */
    1056                 :            : }
    1057                 :            : 
    1058                 :            : int
    1059                 :        137 : fko_get_gpg_signature_summary(fko_ctx_t ctx, int *sigsum)
    1060                 :            : {
    1061                 :            : #if HAVE_LIBGPGME
    1062                 :            :     /* Must be initialized
    1063                 :            :     */
    1064 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
    1065                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
    1066                 :            : 
    1067                 :            :     /* Must be using GPG encryption.
    1068                 :            :     */
    1069         [ +  - ]:        137 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
    1070                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
    1071                 :            : 
    1072                 :            :     /* Make sure we are supposed to verify signatures.
    1073                 :            :     */
    1074         [ +  + ]:        137 :     if(ctx->verify_gpg_sigs == 0)
    1075                 :            :         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
    1076                 :            : 
    1077                 :            :     /* Make sure we have a signature to work with.
    1078                 :            :     */
    1079         [ +  + ]:        136 :     if(ctx->gpg_sigs == NULL)
    1080                 :            :         return(FKO_ERROR_GPGME_NO_SIGNATURE);
    1081                 :            : 
    1082                 :         60 :     *sigsum = ctx->gpg_sigs->summary;
    1083                 :            : 
    1084                 :         60 :     return(FKO_SUCCESS);
    1085                 :            : #else
    1086                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
    1087                 :            : #endif  /* HAVE_LIBGPGME */
    1088                 :            : }
    1089                 :            : 
    1090                 :            : int
    1091                 :        137 : fko_get_gpg_signature_status(fko_ctx_t ctx, int *sigstat)
    1092                 :            : {
    1093                 :            : #if HAVE_LIBGPGME
    1094                 :            :     /* Must be initialized
    1095                 :            :     */
    1096 [ +  - ][ +  - ]:        137 :     if(!CTX_INITIALIZED(ctx))
    1097                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
    1098                 :            : 
    1099                 :            :     /* Must be using GPG encryption.
    1100                 :            :     */
    1101         [ +  - ]:        137 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
    1102                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
    1103                 :            : 
    1104                 :            :     /* Make sure we are supposed to verify signatures.
    1105                 :            :     */
    1106         [ +  + ]:        137 :     if(ctx->verify_gpg_sigs == 0)
    1107                 :            :         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
    1108                 :            : 
    1109                 :            :     /* Make sure we have a signature to work with.
    1110                 :            :     */
    1111         [ +  + ]:        136 :     if(ctx->gpg_sigs == NULL)
    1112                 :            :         return(FKO_ERROR_GPGME_NO_SIGNATURE);
    1113                 :            : 
    1114                 :         60 :     *sigstat = ctx->gpg_sigs->status;
    1115                 :            : 
    1116                 :         60 :     return(FKO_SUCCESS);
    1117                 :            : #else
    1118                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
    1119                 :            : #endif  /* HAVE_LIBGPGME */
    1120                 :            : }
    1121                 :            : 
    1122                 :            : int
    1123                 :         53 : fko_gpg_signature_id_match(fko_ctx_t ctx, const char * const id,
    1124                 :            :         unsigned char * const result)
    1125                 :            : {
    1126                 :            : #if HAVE_LIBGPGME
    1127                 :            :     char *curr_id;
    1128                 :         53 :     int   rv = FKO_SUCCESS;
    1129                 :            : 
    1130                 :            :     /* Must be initialized
    1131                 :            :     */
    1132 [ +  - ][ +  - ]:         53 :     if(!CTX_INITIALIZED(ctx))
    1133                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
    1134                 :            : 
    1135                 :            :     /* Must be using GPG encryption.
    1136                 :            :     */
    1137         [ +  - ]:         53 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
    1138                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
    1139                 :            : 
    1140                 :            :     /* Make sure we are supposed to verify signatures.
    1141                 :            :     */
    1142         [ +  - ]:         53 :     if(ctx->verify_gpg_sigs == 0)
    1143                 :            :         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
    1144                 :            : 
    1145                 :            :     /* Make sure we have a signature to work with.
    1146                 :            :     */
    1147         [ +  - ]:         53 :     if(ctx->gpg_sigs == NULL)
    1148                 :            :         return(FKO_ERROR_GPGME_NO_SIGNATURE);
    1149                 :            : 
    1150                 :         53 :     rv = fko_get_gpg_signature_id(ctx, &curr_id);
    1151         [ +  - ]:         53 :     if(rv != FKO_SUCCESS)
    1152                 :            :         return rv;
    1153                 :            : 
    1154                 :         53 :     *result = strcmp(id, curr_id) == 0 ? 1 : 0;
    1155                 :            : 
    1156                 :         53 :     return(FKO_SUCCESS);
    1157                 :            : #else
    1158                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
    1159                 :            : #endif  /* HAVE_LIBGPGME */
    1160                 :            : }
    1161                 :            : 
    1162                 :            : int
    1163                 :          2 : fko_gpg_signature_fpr_match(fko_ctx_t ctx, const char * const id,
    1164                 :            :         unsigned char * const result)
    1165                 :            : {
    1166                 :            : #if HAVE_LIBGPGME
    1167                 :            :     /* Must be initialized
    1168                 :            :     */
    1169 [ +  - ][ +  - ]:          2 :     if(!CTX_INITIALIZED(ctx))
    1170                 :            :         return(FKO_ERROR_CTX_NOT_INITIALIZED);
    1171                 :            : 
    1172                 :            :     /* Must be using GPG encryption.
    1173                 :            :     */
    1174         [ +  - ]:          2 :     if(ctx->encryption_type != FKO_ENCRYPTION_GPG)
    1175                 :            :         return(FKO_ERROR_WRONG_ENCRYPTION_TYPE);
    1176                 :            : 
    1177                 :            :     /* Make sure we are supposed to verify signatures.
    1178                 :            :     */
    1179         [ +  - ]:          2 :     if(ctx->verify_gpg_sigs == 0)
    1180                 :            :         return(FKO_ERROR_GPGME_SIGNATURE_VERIFY_DISABLED);
    1181                 :            : 
    1182                 :            :     /* Make sure we have a signature to work with.
    1183                 :            :     */
    1184         [ +  - ]:          2 :     if(ctx->gpg_sigs == NULL)
    1185                 :            :         return(FKO_ERROR_GPGME_NO_SIGNATURE);
    1186                 :            : 
    1187                 :          2 :     *result = strcmp(id, ctx->gpg_sigs->fpr) == 0 ? 1 : 0;
    1188                 :            : 
    1189                 :          2 :     return(FKO_SUCCESS);
    1190                 :            : #else
    1191                 :            :     return(FKO_ERROR_UNSUPPORTED_FEATURE);
    1192                 :            : #endif  /* HAVE_LIBGPGME */
    1193                 :            : }
    1194                 :            : 
    1195                 :            : /***EOF***/

Generated by: LCOV version 1.10