LCOV - code coverage report
Current view: top level - src - verify.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 355 635 55.9 %
Date: 2016-09-12 12:35:26 Functions: 18 22 81.8 %

          Line data    Source code
       1             : /* verify.c - Signature verification.
       2             :    Copyright (C) 2000 Werner Koch (dd9jn)
       3             :    Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
       4             : 
       5             :    This file is part of GPGME.
       6             : 
       7             :    GPGME is free software; you can redistribute it and/or modify it
       8             :    under the terms of the GNU Lesser General Public License as
       9             :    published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    GPGME is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, write to the Free Software
      19             :    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      20             :    02111-1307, USA.  */
      21             : 
      22             : #if HAVE_CONFIG_H
      23             : #include <config.h>
      24             : #endif
      25             : #include <stdlib.h>
      26             : #include <string.h>
      27             : #include <errno.h>
      28             : #include <assert.h>
      29             : #include <limits.h>
      30             : 
      31             : #include "gpgme.h"
      32             : #include "debug.h"
      33             : #include "util.h"
      34             : #include "context.h"
      35             : #include "ops.h"
      36             : 
      37             : 
      38             : typedef struct
      39             : {
      40             :   struct _gpgme_op_verify_result result;
      41             : 
      42             :   /* The error code from a FAILURE status line or 0.  */
      43             :   gpg_error_t failure_code;
      44             : 
      45             :   gpgme_signature_t current_sig;
      46             :   int did_prepare_new_sig;
      47             :   int only_newsig_seen;
      48             :   int plaintext_seen;
      49             : } *op_data_t;
      50             : 
      51             : 
      52             : static void
      53          38 : release_op_data (void *hook)
      54             : {
      55          38 :   op_data_t opd = (op_data_t) hook;
      56          38 :   gpgme_signature_t sig = opd->result.signatures;
      57             : 
      58         106 :   while (sig)
      59             :     {
      60          30 :       gpgme_signature_t next = sig->next;
      61          30 :       gpgme_sig_notation_t notation = sig->notations;
      62             : 
      63          81 :       while (notation)
      64             :         {
      65          21 :           gpgme_sig_notation_t next_nota = notation->next;
      66             : 
      67          21 :           _gpgme_sig_notation_free (notation);
      68          21 :           notation = next_nota;
      69             :         }
      70             : 
      71          30 :       if (sig->fpr)
      72          30 :         free (sig->fpr);
      73          30 :       if (sig->pka_address)
      74           0 :         free (sig->pka_address);
      75          30 :       if (sig->key)
      76           9 :         gpgme_key_unref (sig->key);
      77          30 :       free (sig);
      78          30 :       sig = next;
      79             :     }
      80             : 
      81          38 :   if (opd->result.file_name)
      82          13 :     free (opd->result.file_name);
      83          38 : }
      84             : 
      85             : 
      86             : gpgme_verify_result_t
      87          33 : gpgme_op_verify_result (gpgme_ctx_t ctx)
      88             : {
      89             :   void *hook;
      90             :   op_data_t opd;
      91             :   gpgme_error_t err;
      92             :   gpgme_signature_t sig;
      93             : 
      94          33 :   TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
      95          33 :   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
      96          33 :   opd = hook;
      97          33 :   if (err || !opd)
      98             :     {
      99           0 :       TRACE_SUC0 ("result=(null)");
     100           0 :       return NULL;
     101             :     }
     102             : 
     103             :   /* It is possible that we saw a new signature only followed by an
     104             :      ERROR line for that.  In particular a missing X.509 key triggers
     105             :      this.  In this case it is surprising that the summary field has
     106             :      not been updated.  We fix it here by explicitly looking for this
     107             :      case.  The real fix would be to have GPGME emit ERRSIG.  */
     108          63 :   for (sig = opd->result.signatures; sig; sig = sig->next)
     109             :     {
     110          30 :       if (!sig->summary)
     111             :         {
     112          13 :           switch (gpg_err_code (sig->status))
     113             :             {
     114             :             case GPG_ERR_KEY_EXPIRED:
     115           0 :               sig->summary |= GPGME_SIGSUM_KEY_EXPIRED;
     116           0 :               break;
     117             : 
     118             :             case GPG_ERR_NO_PUBKEY:
     119           0 :               sig->summary |= GPGME_SIGSUM_KEY_MISSING;
     120           0 :               break;
     121             : 
     122             :             default:
     123          13 :               break;
     124             :             }
     125             :         }
     126             :     }
     127             : 
     128             :   /* Now for some tracing stuff. */
     129             :   if (_gpgme_debug_trace ())
     130             :     {
     131             :       int i;
     132             : 
     133          63 :       for (sig = opd->result.signatures, i = 0; sig; sig = sig->next, i++)
     134             :         {
     135          30 :           TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
     136             :                       i, sig->fpr, sig->summary, gpg_strerror (sig->status));
     137          30 :           TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
     138             :                       i, sig->timestamp, sig->exp_timestamp,
     139             :                       sig->wrong_key_usage ? "wrong key usage" : "",
     140             :                       sig->pka_trust == 1 ? "pka bad"
     141             :                       : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
     142             :                       sig->chain_model ? "chain model" : "");
     143          30 :           TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
     144             :                       i, sig->validity, gpg_strerror (sig->validity_reason),
     145             :                       gpgme_pubkey_algo_name (sig->pubkey_algo),
     146             :                       gpgme_hash_algo_name (sig->hash_algo));
     147          30 :           if (sig->pka_address)
     148             :             {
     149           0 :               TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
     150             :             }
     151          30 :           if (sig->notations)
     152             :             {
     153           7 :               TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
     154             :             }
     155             :         }
     156             :     }
     157             : 
     158          33 :   TRACE_SUC1 ("result=%p", &opd->result);
     159          33 :   return &opd->result;
     160             : }
     161             : 
     162             : 
     163             : /* Build a summary vector from RESULT. */
     164             : static void
     165          30 : calc_sig_summary (gpgme_signature_t sig)
     166             : {
     167          30 :   unsigned long sum = 0;
     168             : 
     169             :   /* Calculate the red/green flag.  */
     170          30 :   if (sig->validity == GPGME_VALIDITY_FULL
     171          17 :       || sig->validity == GPGME_VALIDITY_ULTIMATE)
     172             :     {
     173          26 :       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
     174           0 :           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
     175           0 :           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
     176          13 :         sum |= GPGME_SIGSUM_GREEN;
     177             :     }
     178          17 :   else if (sig->validity == GPGME_VALIDITY_NEVER)
     179             :     {
     180           0 :       if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
     181           0 :           || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
     182           0 :           || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
     183           0 :         sum |= GPGME_SIGSUM_RED;
     184             :     }
     185          17 :   else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
     186           4 :     sum |= GPGME_SIGSUM_RED;
     187             : 
     188             : 
     189             :   /* FIXME: handle the case when key and message are expired. */
     190          30 :   switch (gpg_err_code (sig->status))
     191             :     {
     192             :     case GPG_ERR_SIG_EXPIRED:
     193           0 :       sum |= GPGME_SIGSUM_SIG_EXPIRED;
     194           0 :       break;
     195             : 
     196             :     case GPG_ERR_KEY_EXPIRED:
     197           0 :       sum |= GPGME_SIGSUM_KEY_EXPIRED;
     198           0 :       break;
     199             : 
     200             :     case GPG_ERR_NO_PUBKEY:
     201           0 :       sum |= GPGME_SIGSUM_KEY_MISSING;
     202           0 :       break;
     203             : 
     204             :     case GPG_ERR_CERT_REVOKED:
     205           0 :       sum |= GPGME_SIGSUM_KEY_REVOKED;
     206           0 :       break;
     207             : 
     208             :     case GPG_ERR_BAD_SIGNATURE:
     209             :     case GPG_ERR_NO_ERROR:
     210          30 :       break;
     211             : 
     212             :     default:
     213           0 :       sum |= GPGME_SIGSUM_SYS_ERROR;
     214           0 :       break;
     215             :     }
     216             : 
     217             :   /* Now look at the certain reason codes.  */
     218          30 :   switch (gpg_err_code (sig->validity_reason))
     219             :     {
     220             :     case GPG_ERR_CRL_TOO_OLD:
     221           0 :       if (sig->validity == GPGME_VALIDITY_UNKNOWN)
     222           0 :         sum |= GPGME_SIGSUM_CRL_TOO_OLD;
     223           0 :       break;
     224             : 
     225             :     case GPG_ERR_CERT_REVOKED:
     226             :       /* Note that this is a second way to set this flag.  It may also
     227             :          have been set due to a sig->status of STATUS_REVKEYSIG from
     228             :          parse_new_sig.  */
     229           0 :       sum |= GPGME_SIGSUM_KEY_REVOKED;
     230           0 :       break;
     231             : 
     232             :     default:
     233          30 :       break;
     234             :     }
     235             : 
     236             :   /* Check other flags. */
     237          30 :   if (sig->wrong_key_usage)
     238           0 :     sum |= GPGME_SIGSUM_BAD_POLICY;
     239             : 
     240             :   /* Set the valid flag when the signature is unquestionable
     241             :      valid.  (The test is identical to if(sum == GPGME_SIGSUM_GREEN)). */
     242          30 :   if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
     243          13 :     sum |= GPGME_SIGSUM_VALID;
     244             : 
     245          30 :   sig->summary = sum;
     246          30 : }
     247             : 
     248             : 
     249             : static gpgme_error_t
     250          30 : prepare_new_sig (op_data_t opd)
     251             : {
     252             :   gpgme_signature_t sig;
     253             : 
     254          30 :   if (opd->only_newsig_seen && opd->current_sig)
     255             :     {
     256             :       /* We have only seen the NEWSIG status and nothing else - we
     257             :          better skip this signature therefore and reuse it for the
     258             :          next possible signature. */
     259           0 :       sig = opd->current_sig;
     260           0 :       memset (sig, 0, sizeof *sig);
     261           0 :       assert (opd->result.signatures == sig);
     262             :     }
     263             :   else
     264             :     {
     265          30 :       sig = calloc (1, sizeof (*sig));
     266          30 :       if (!sig)
     267           0 :         return gpg_error_from_syserror ();
     268          30 :       if (!opd->result.signatures)
     269          30 :         opd->result.signatures = sig;
     270          30 :       if (opd->current_sig)
     271           0 :         opd->current_sig->next = sig;
     272          30 :       opd->current_sig = sig;
     273             :     }
     274          30 :   opd->did_prepare_new_sig = 1;
     275          30 :   opd->only_newsig_seen = 0;
     276          30 :   return 0;
     277             : }
     278             : 
     279             : static gpgme_error_t
     280          30 : parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
     281             :                gpgme_protocol_t protocol)
     282             : {
     283             :   gpgme_signature_t sig;
     284          30 :   char *end = strchr (args, ' ');
     285             :   char *tail;
     286             : 
     287          30 :   if (end)
     288             :     {
     289          30 :       *end = '\0';
     290          30 :       end++;
     291             :     }
     292             : 
     293          30 :   if (!opd->did_prepare_new_sig)
     294             :     {
     295             :       gpg_error_t err;
     296             : 
     297           0 :       err = prepare_new_sig (opd);
     298           0 :       if (err)
     299           0 :         return err;
     300             :     }
     301          30 :   assert (opd->did_prepare_new_sig);
     302          30 :   opd->did_prepare_new_sig = 0;
     303             : 
     304          30 :   assert (opd->current_sig);
     305          30 :   sig = opd->current_sig;
     306             : 
     307             :   /* FIXME: We should set the source of the state.  */
     308          30 :   switch (code)
     309             :     {
     310             :     case GPGME_STATUS_GOODSIG:
     311          26 :       sig->status = gpg_error (GPG_ERR_NO_ERROR);
     312          26 :       break;
     313             : 
     314             :     case GPGME_STATUS_EXPSIG:
     315           0 :       sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
     316           0 :       break;
     317             : 
     318             :     case GPGME_STATUS_EXPKEYSIG:
     319           0 :       sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
     320           0 :       break;
     321             : 
     322             :     case GPGME_STATUS_BADSIG:
     323           4 :       sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
     324           4 :       break;
     325             : 
     326             :     case GPGME_STATUS_REVKEYSIG:
     327           0 :       sig->status = gpg_error (GPG_ERR_CERT_REVOKED);
     328           0 :       break;
     329             : 
     330             :     case GPGME_STATUS_ERRSIG:
     331             :       /* Parse the pubkey algo.  */
     332           0 :       if (!end)
     333           0 :         goto parse_err_sig_fail;
     334           0 :       gpg_err_set_errno (0);
     335           0 :       sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0), protocol);
     336           0 :       if (errno || end == tail || *tail != ' ')
     337             :         goto parse_err_sig_fail;
     338           0 :       end = tail;
     339           0 :       while (*end == ' ')
     340           0 :         end++;
     341             : 
     342             :       /* Parse the hash algo.  */
     343           0 :       if (!*end)
     344           0 :         goto parse_err_sig_fail;
     345           0 :       gpg_err_set_errno (0);
     346           0 :       sig->hash_algo = strtol (end, &tail, 0);
     347           0 :       if (errno || end == tail || *tail != ' ')
     348             :         goto parse_err_sig_fail;
     349           0 :       end = tail;
     350           0 :       while (*end == ' ')
     351           0 :         end++;
     352             : 
     353             :       /* Skip the sig class.  */
     354           0 :       end = strchr (end, ' ');
     355           0 :       if (!end)
     356           0 :         goto parse_err_sig_fail;
     357           0 :       while (*end == ' ')
     358           0 :         end++;
     359             : 
     360             :       /* Parse the timestamp.  */
     361           0 :       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
     362           0 :       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
     363           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     364           0 :       end = tail;
     365           0 :       while (*end == ' ')
     366           0 :         end++;
     367             : 
     368             :       /* Parse the return code.  */
     369           0 :       if (end[0] && (!end[1] || end[1] == ' '))
     370             :         {
     371           0 :           switch (end[0])
     372             :             {
     373             :             case '4':
     374           0 :               sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
     375           0 :               break;
     376             : 
     377             :             case '9':
     378           0 :               sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
     379           0 :               break;
     380             : 
     381             :             default:
     382           0 :               sig->status = gpg_error (GPG_ERR_GENERAL);
     383             :             }
     384             :         }
     385             :       else
     386             :         goto parse_err_sig_fail;
     387             : 
     388           0 :       goto parse_err_sig_ok;
     389             : 
     390             :     parse_err_sig_fail:
     391           0 :       sig->status = gpg_error (GPG_ERR_GENERAL);
     392             :     parse_err_sig_ok:
     393           0 :       break;
     394             : 
     395             :     default:
     396           0 :       return gpg_error (GPG_ERR_GENERAL);
     397             :     }
     398             : 
     399          30 :   if (*args)
     400             :     {
     401          30 :       sig->fpr = strdup (args);
     402          30 :       if (!sig->fpr)
     403           0 :         return gpg_error_from_syserror ();
     404             :     }
     405          30 :   return 0;
     406             : }
     407             : 
     408             : 
     409             : static gpgme_error_t
     410          26 : parse_valid_sig (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
     411             : {
     412          26 :   char *end = strchr (args, ' ');
     413          26 :   if (end)
     414             :     {
     415          26 :       *end = '\0';
     416          26 :       end++;
     417             :     }
     418             : 
     419          26 :   if (!*args)
     420             :     /* We require at least the fingerprint.  */
     421           0 :     return gpg_error (GPG_ERR_GENERAL);
     422             : 
     423          26 :   if (sig->fpr)
     424          26 :     free (sig->fpr);
     425          26 :   sig->fpr = strdup (args);
     426          26 :   if (!sig->fpr)
     427           0 :     return gpg_error_from_syserror ();
     428             : 
     429             :   /* Skip the creation date.  */
     430          26 :   end = strchr (end, ' ');
     431          26 :   if (end)
     432             :     {
     433             :       char *tail;
     434             : 
     435          26 :       sig->timestamp = _gpgme_parse_timestamp (end, &tail);
     436          26 :       if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
     437           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     438          26 :       end = tail;
     439             : 
     440          26 :       sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
     441          26 :       if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
     442           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     443          26 :       end = tail;
     444             : 
     445          78 :       while (*end == ' ')
     446          26 :         end++;
     447             :       /* Skip the signature version.  */
     448          26 :       end = strchr (end, ' ');
     449          26 :       if (end)
     450             :         {
     451          78 :           while (*end == ' ')
     452          26 :             end++;
     453             : 
     454             :           /* Skip the reserved field.  */
     455          26 :           end = strchr (end, ' ');
     456          26 :           if (end)
     457             :             {
     458             :               /* Parse the pubkey algo.  */
     459          26 :               gpg_err_set_errno (0);
     460          26 :               sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0),
     461             :                                                      protocol);
     462          26 :               if (errno || end == tail || *tail != ' ')
     463           0 :                 return trace_gpg_error (GPG_ERR_INV_ENGINE);
     464          26 :               end = tail;
     465             : 
     466          78 :               while (*end == ' ')
     467          26 :                 end++;
     468             : 
     469          26 :               if (*end)
     470             :                 {
     471             :                   /* Parse the hash algo.  */
     472             : 
     473          26 :                   gpg_err_set_errno (0);
     474          26 :                   sig->hash_algo = strtol (end, &tail, 0);
     475          26 :                   if (errno || end == tail || *tail != ' ')
     476           0 :                     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     477          26 :                   end = tail;
     478             :                 }
     479             :             }
     480             :         }
     481             :     }
     482          26 :   return 0;
     483             : }
     484             : 
     485             : 
     486             : static gpgme_error_t
     487          54 : parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
     488             : {
     489             :   gpgme_error_t err;
     490          54 :   gpgme_sig_notation_t *lastp = &sig->notations;
     491          54 :   gpgme_sig_notation_t notation = sig->notations;
     492             :   char *p;
     493             : 
     494          54 :   if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
     495             :     {
     496          21 :       p = strchr (args, ' ');
     497          21 :       if (p)
     498           0 :         *p = '\0';
     499             : 
     500             :       /* FIXME: We could keep a pointer to the last notation in the list.  */
     501          63 :       while (notation && notation->value)
     502             :         {
     503          21 :           lastp = &notation->next;
     504          21 :           notation = notation->next;
     505             :         }
     506             : 
     507          21 :       if (notation)
     508             :         /* There is another notation name without data for the
     509             :            previous one.  The crypto backend misbehaves.  */
     510           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     511             : 
     512          21 :       err = _gpgme_sig_notation_create (&notation, NULL, 0, NULL, 0, 0);
     513          21 :       if (err)
     514           0 :         return err;
     515             : 
     516          21 :       if (code == GPGME_STATUS_NOTATION_NAME)
     517             :         {
     518          14 :           err = _gpgme_decode_percent_string (args, &notation->name, 0, 0);
     519          14 :           if (err)
     520             :             {
     521           0 :               _gpgme_sig_notation_free (notation);
     522           0 :               return err;
     523             :             }
     524             : 
     525          14 :           notation->name_len = strlen (notation->name);
     526             : 
     527             :           /* Set default flags for use with older gpg versions which
     528             :            * do not emit a NOTATIONS_FLAG line.  */
     529          14 :           notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
     530          14 :           notation->human_readable = 1;
     531             :         }
     532             :       else
     533             :         {
     534             :           /* This is a policy URL.  */
     535             : 
     536           7 :           err = _gpgme_decode_percent_string (args, &notation->value, 0, 0);
     537           7 :           if (err)
     538             :             {
     539           0 :               _gpgme_sig_notation_free (notation);
     540           0 :               return err;
     541             :             }
     542             : 
     543           7 :           notation->value_len = strlen (notation->value);
     544             :         }
     545          21 :       *lastp = notation;
     546             :     }
     547          33 :   else if (code == GPGME_STATUS_NOTATION_FLAGS)
     548             :     {
     549             :       char *field[2];
     550             : 
     551          49 :       while (notation && notation->next)
     552             :         {
     553          21 :           lastp = &notation->next;
     554          21 :           notation = notation->next;
     555             :         }
     556             : 
     557          14 :       if (!notation || !notation->name)
     558             :         { /* There are notation flags without a previous notation name.
     559             :            * The crypto backend misbehaves.  */
     560           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     561             :         }
     562          14 :       if (_gpgme_split_fields (args, field, DIM (field)) < 2)
     563             :         { /* Required args missing.  */
     564           0 :           return trace_gpg_error (GPG_ERR_INV_ENGINE);
     565             :         }
     566          14 :       notation->flags = 0;
     567          14 :       if (atoi (field[0]))
     568             :         {
     569           2 :           notation->flags |= GPGME_SIG_NOTATION_CRITICAL;
     570           2 :           notation->critical = 1;
     571             :         }
     572          14 :       if (atoi (field[1]))
     573             :         {
     574          14 :           notation->flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
     575          14 :           notation->human_readable = 1;
     576             :         }
     577             :     }
     578          19 :   else if (code == GPGME_STATUS_NOTATION_DATA)
     579             :     {
     580          19 :       int len = strlen (args) + 1;
     581             :       char *dest;
     582             : 
     583             :       /* FIXME: We could keep a pointer to the last notation in the list.  */
     584          69 :       while (notation && notation->next)
     585             :         {
     586          31 :           lastp = &notation->next;
     587          31 :           notation = notation->next;
     588             :         }
     589             : 
     590          19 :       if (!notation || !notation->name)
     591             :         /* There is notation data without a previous notation
     592             :            name.  The crypto backend misbehaves.  */
     593           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     594             : 
     595          19 :       if (!notation->value)
     596             :         {
     597          14 :           dest = notation->value = malloc (len);
     598          14 :           if (!dest)
     599           0 :             return gpg_error_from_syserror ();
     600             :         }
     601             :       else
     602             :         {
     603           5 :           int cur_len = strlen (notation->value);
     604           5 :           dest = realloc (notation->value, len + strlen (notation->value));
     605           5 :           if (!dest)
     606           0 :             return gpg_error_from_syserror ();
     607           5 :           notation->value = dest;
     608           5 :           dest += cur_len;
     609             :         }
     610             : 
     611          19 :       err = _gpgme_decode_percent_string (args, &dest, len, 0);
     612          19 :       if (err)
     613           0 :         return err;
     614             : 
     615          19 :       notation->value_len += strlen (dest);
     616             :     }
     617             :   else
     618           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     619          54 :   return 0;
     620             : }
     621             : 
     622             : 
     623             : static gpgme_error_t
     624          26 : parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
     625             : {
     626          26 :   char *end = strchr (args, ' ');
     627             : 
     628          26 :   if (end)
     629          26 :     *end = '\0';
     630             : 
     631          26 :   switch (code)
     632             :     {
     633             :     case GPGME_STATUS_TRUST_UNDEFINED:
     634             :     default:
     635           4 :       sig->validity = GPGME_VALIDITY_UNKNOWN;
     636           4 :       break;
     637             : 
     638             :     case GPGME_STATUS_TRUST_NEVER:
     639           0 :       sig->validity = GPGME_VALIDITY_NEVER;
     640           0 :       break;
     641             : 
     642             :     case GPGME_STATUS_TRUST_MARGINAL:
     643           9 :       sig->validity = GPGME_VALIDITY_MARGINAL;
     644           9 :       break;
     645             : 
     646             :     case GPGME_STATUS_TRUST_FULLY:
     647             :     case GPGME_STATUS_TRUST_ULTIMATE:
     648          13 :       sig->validity = GPGME_VALIDITY_FULL;
     649          13 :       break;
     650             :     }
     651             : 
     652          26 :   sig->validity_reason = 0;
     653          26 :   sig->chain_model = 0;
     654          26 :   if (*args)
     655             :     {
     656          26 :       sig->validity_reason = atoi (args);
     657          78 :       while (*args && *args != ' ')
     658          26 :         args++;
     659          26 :       if (*args)
     660             :         {
     661           0 :           while (*args == ' ')
     662           0 :             args++;
     663           0 :           if (!strncmp (args, "chain", 2) && (args[2] == ' ' || !args[2]))
     664           0 :             sig->chain_model = 1;
     665             :         }
     666             :     }
     667             : 
     668          26 :   return 0;
     669             : }
     670             : 
     671             : 
     672             : /* Parse a TOFU_USER line and put the info into SIG.  */
     673             : static gpgme_error_t
     674          15 : parse_tofu_user (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
     675             : {
     676             :   gpg_error_t err;
     677             :   char *tail;
     678             :   gpgme_user_id_t uid;
     679             :   gpgme_tofu_info_t ti;
     680          15 :   char *fpr = NULL;
     681          15 :   char *address = NULL;
     682             : 
     683          15 :   tail = strchr (args, ' ');
     684          15 :   if (!tail || tail == args)
     685             :     {
     686           0 :       err = trace_gpg_error (GPG_ERR_INV_ENGINE);  /* No fingerprint.  */
     687           0 :       goto leave;
     688             :     }
     689          15 :   *tail++ = 0;
     690             : 
     691          15 :   fpr = strdup (args);
     692          15 :   if (!fpr)
     693             :     {
     694           0 :       err = gpg_error_from_syserror ();
     695           0 :       goto leave;
     696             :     }
     697             : 
     698          15 :   args = tail;
     699          15 :   tail = strchr (args, ' ');
     700          15 :   if (tail == args)
     701             :     {
     702           0 :       err = trace_gpg_error (GPG_ERR_INV_ENGINE);  /* No addr-spec.  */
     703           0 :       goto leave;
     704             :     }
     705          15 :   if (tail)
     706           0 :     *tail = 0;
     707             : 
     708          15 :   err = _gpgme_decode_percent_string (args, &address, 0, 0);
     709          15 :   if (err)
     710           0 :     goto leave;
     711             : 
     712          15 :   if (!sig->key)
     713             :     {
     714           9 :       err = _gpgme_key_new (&sig->key);
     715           9 :       if (err)
     716           0 :         goto leave;
     717           9 :       sig->key->fpr = fpr;
     718           9 :       sig->key->protocol = protocol;
     719           9 :       fpr = NULL;
     720             :     }
     721           6 :   else if (!sig->key->fpr)
     722             :     {
     723           0 :       err = trace_gpg_error (GPG_ERR_INTERNAL);
     724           0 :       goto leave;
     725             :     }
     726           6 :   else if (strcmp (sig->key->fpr, fpr))
     727             :     {
     728             :       /* The engine did not emit NEWSIG before a new key.  */
     729           0 :       err = trace_gpg_error (GPG_ERR_INV_ENGINE);
     730           0 :       goto leave;
     731             :     }
     732             : 
     733          15 :   err = _gpgme_key_append_name (sig->key, address, 0);
     734          15 :   if (err)
     735           0 :     goto leave;
     736             : 
     737          15 :   uid = sig->key->_last_uid;
     738          15 :   assert (uid);
     739             : 
     740          15 :   ti = calloc (1, sizeof *ti);
     741          15 :   if (!ti)
     742             :     {
     743           0 :       err = gpg_error_from_syserror ();
     744           0 :       goto leave;
     745             :     }
     746          15 :   uid->tofu = ti;
     747             : 
     748             : 
     749             :  leave:
     750          15 :   free (fpr);
     751          15 :   free (address);
     752          15 :   return err;
     753             : }
     754             : 
     755             : 
     756             : /* Parse a TOFU_STATS line and store it in the last tofu info of SIG.
     757             :  *
     758             :  *   TOFU_STATS <validity> <sign-count> <encr-count> \
     759             :  *                         [<policy> [<tm1> <tm2> <tm3> <tm4>]]
     760             :  */
     761             : static gpgme_error_t
     762          15 : parse_tofu_stats (gpgme_signature_t sig, char *args)
     763             : {
     764             :   gpgme_error_t err;
     765             :   gpgme_tofu_info_t ti;
     766             :   char *field[8];
     767             :   int nfields;
     768             :   unsigned long uval;
     769             : 
     770          15 :   if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
     771           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen.  */
     772          15 :   if (ti->signfirst || ti->signcount || ti->validity || ti->policy)
     773           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set.  */
     774             : 
     775          15 :   nfields = _gpgme_split_fields (args, field, DIM (field));
     776          15 :   if (nfields < 3)
     777           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required args missing.  */
     778             : 
     779             :   /* Note that we allow a value of up to 7 which is what we can store
     780             :    * in the ti->validity.  */
     781          15 :   err = _gpgme_strtoul_field (field[0], &uval);
     782          15 :   if (err || uval > 7)
     783           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     784          15 :   ti->validity = uval;
     785             : 
     786             :   /* Parse the sign-count.  */
     787          15 :   err = _gpgme_strtoul_field (field[1], &uval);
     788          15 :   if (err)
     789           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     790          15 :   if (uval > USHRT_MAX)
     791           0 :     uval = USHRT_MAX;
     792          15 :   ti->signcount = uval;
     793             : 
     794             :   /* Parse the encr-count.  */
     795          15 :   err = _gpgme_strtoul_field (field[2], &uval);
     796          15 :   if (err)
     797           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     798          15 :   if (uval > USHRT_MAX)
     799           0 :     uval = USHRT_MAX;
     800          15 :   ti->encrcount = uval;
     801             : 
     802          15 :   if (nfields == 3)
     803           0 :     return 0; /* All mandatory fields parsed.  */
     804             : 
     805             :   /* Parse the policy.  */
     806          15 :   if (!strcmp (field[3], "none"))
     807           0 :     ti->policy = GPGME_TOFU_POLICY_NONE;
     808          15 :   else if (!strcmp (field[3], "auto"))
     809          15 :     ti->policy = GPGME_TOFU_POLICY_AUTO;
     810           0 :   else if (!strcmp (field[3], "good"))
     811           0 :     ti->policy = GPGME_TOFU_POLICY_GOOD;
     812           0 :   else if (!strcmp (field[3], "bad"))
     813           0 :     ti->policy = GPGME_TOFU_POLICY_BAD;
     814           0 :   else if (!strcmp (field[3], "ask"))
     815           0 :     ti->policy = GPGME_TOFU_POLICY_ASK;
     816             :   else /* "unknown" and invalid policy strings.  */
     817           0 :     ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
     818             : 
     819          15 :   if (nfields == 4)
     820           0 :     return 0; /* No more optional fields.  */
     821             : 
     822             :   /* Parse first and last seen timestamps (none or both are required).  */
     823          15 :   if (nfields < 6)
     824           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* "tm2" missing.  */
     825          15 :   err = _gpgme_strtoul_field (field[4], &uval);
     826          15 :   if (err)
     827           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     828          15 :   ti->signfirst = uval;
     829          15 :   err = _gpgme_strtoul_field (field[5], &uval);
     830          15 :   if (err)
     831           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     832          15 :   ti->signlast = uval;
     833          15 :   if (nfields > 7)
     834             :     {
     835             :       /* This condition is only to allow for gpg 2.1.15 - can
     836             :        * eventually be removed.  */
     837           0 :       err = _gpgme_strtoul_field (field[6], &uval);
     838           0 :       if (err)
     839           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     840           0 :       ti->encrfirst = uval;
     841           0 :       err = _gpgme_strtoul_field (field[7], &uval);
     842           0 :       if (err)
     843           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
     844           0 :       ti->encrlast = uval;
     845             :     }
     846             : 
     847          15 :   return 0;
     848             : }
     849             : 
     850             : 
     851             : /* Parse a TOFU_STATS_LONG line and store it in the last tofu info of SIG.  */
     852             : static gpgme_error_t
     853          15 : parse_tofu_stats_long (gpgme_signature_t sig, char *args, int raw)
     854             : {
     855             :   gpgme_error_t err;
     856             :   gpgme_tofu_info_t ti;
     857             :   char *p;
     858             : 
     859          15 :   if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
     860           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen.  */
     861          15 :   if (ti->description)
     862           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set.  */
     863             : 
     864          15 :   err = _gpgme_decode_percent_string (args, &ti->description, 0, 0);
     865          15 :   if (err)
     866           0 :     return err;
     867             : 
     868             :   /* Remove the non-breaking spaces.  */
     869          15 :   if (!raw)
     870             :     {
     871        1613 :       for (p = ti->description; *p; p++)
     872        1598 :         if (*p == '~')
     873          20 :           *p = ' ';
     874             :     }
     875          15 :   return 0;
     876             : }
     877             : 
     878             : 
     879             : /* Parse an error status line and if SET_STATUS is true update the
     880             :    result status as appropriate.  With SET_STATUS being false, only
     881             :    check for an error.  */
     882             : static gpgme_error_t
     883           3 : parse_error (gpgme_signature_t sig, char *args, int set_status)
     884             : {
     885             :   gpgme_error_t err;
     886           3 :   char *where = strchr (args, ' ');
     887             :   char *which;
     888             : 
     889           3 :   if (where)
     890             :     {
     891           3 :       *where = '\0';
     892           3 :       which = where + 1;
     893             : 
     894           3 :       where = strchr (which, ' ');
     895           3 :       if (where)
     896           0 :         *where = '\0';
     897             : 
     898           3 :       where = args;
     899             :     }
     900             :   else
     901           0 :     return trace_gpg_error (GPG_ERR_INV_ENGINE);
     902             : 
     903           3 :   err = atoi (which);
     904             : 
     905           3 :   if (!strcmp (where, "proc_pkt.plaintext")
     906           3 :       && gpg_err_code (err) == GPG_ERR_BAD_DATA)
     907             :     {
     908             :       /* This indicates a double plaintext.  The only solid way to
     909             :          handle this is by failing the oepration.  */
     910           3 :       return gpg_error (GPG_ERR_BAD_DATA);
     911             :     }
     912           0 :   else if (!set_status)
     913             :     ;
     914           0 :   else if (!strcmp (where, "verify.findkey"))
     915           0 :     sig->status = err;
     916           0 :   else if (!strcmp (where, "verify.keyusage")
     917           0 :            && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
     918           0 :     sig->wrong_key_usage = 1;
     919             : 
     920           0 :   return 0;
     921             : }
     922             : 
     923             : 
     924             : gpgme_error_t
     925         496 : _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
     926             : {
     927         496 :   gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
     928             :   gpgme_error_t err;
     929             :   void *hook;
     930             :   op_data_t opd;
     931             :   gpgme_signature_t sig;
     932             :   char *end;
     933             : 
     934         496 :   err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
     935         496 :   opd = hook;
     936         496 :   if (err)
     937           0 :     return err;
     938             : 
     939         496 :   sig = opd->current_sig;
     940             : 
     941         496 :   switch (code)
     942             :     {
     943             :     case GPGME_STATUS_NEWSIG:
     944          30 :       if (sig)
     945           0 :         calc_sig_summary (sig);
     946          30 :       err = prepare_new_sig (opd);
     947          30 :       opd->only_newsig_seen = 1;
     948          30 :       return err;
     949             : 
     950             :     case GPGME_STATUS_GOODSIG:
     951             :     case GPGME_STATUS_EXPSIG:
     952             :     case GPGME_STATUS_EXPKEYSIG:
     953             :     case GPGME_STATUS_BADSIG:
     954             :     case GPGME_STATUS_ERRSIG:
     955             :     case GPGME_STATUS_REVKEYSIG:
     956          30 :       if (sig && !opd->did_prepare_new_sig)
     957           0 :         calc_sig_summary (sig);
     958          30 :       opd->only_newsig_seen = 0;
     959          30 :       return parse_new_sig (opd, code, args, ctx->protocol);
     960             : 
     961             :     case GPGME_STATUS_VALIDSIG:
     962          26 :       opd->only_newsig_seen = 0;
     963          52 :       return sig ? parse_valid_sig (sig, args, ctx->protocol)
     964          52 :         : trace_gpg_error (GPG_ERR_INV_ENGINE);
     965             : 
     966             :     case GPGME_STATUS_NODATA:
     967           2 :       opd->only_newsig_seen = 0;
     968           2 :       if (!sig)
     969           2 :         return gpg_error (GPG_ERR_NO_DATA);
     970           0 :       sig->status = gpg_error (GPG_ERR_NO_DATA);
     971           0 :       break;
     972             : 
     973             :     case GPGME_STATUS_UNEXPECTED:
     974           0 :       opd->only_newsig_seen = 0;
     975           0 :       if (!sig)
     976           0 :         return gpg_error (GPG_ERR_GENERAL);
     977           0 :       sig->status = gpg_error (GPG_ERR_NO_DATA);
     978           0 :       break;
     979             : 
     980             :     case GPGME_STATUS_NOTATION_NAME:
     981             :     case GPGME_STATUS_NOTATION_FLAGS:
     982             :     case GPGME_STATUS_NOTATION_DATA:
     983             :     case GPGME_STATUS_POLICY_URL:
     984          54 :       opd->only_newsig_seen = 0;
     985          54 :       return sig ? parse_notation (sig, code, args)
     986          54 :         : trace_gpg_error (GPG_ERR_INV_ENGINE);
     987             : 
     988             :     case GPGME_STATUS_TRUST_UNDEFINED:
     989             :     case GPGME_STATUS_TRUST_NEVER:
     990             :     case GPGME_STATUS_TRUST_MARGINAL:
     991             :     case GPGME_STATUS_TRUST_FULLY:
     992             :     case GPGME_STATUS_TRUST_ULTIMATE:
     993          26 :       opd->only_newsig_seen = 0;
     994          26 :       return sig ? parse_trust (sig, code, args)
     995          26 :         : trace_gpg_error (GPG_ERR_INV_ENGINE);
     996             : 
     997             :     case GPGME_STATUS_PKA_TRUST_BAD:
     998             :     case GPGME_STATUS_PKA_TRUST_GOOD:
     999           0 :       opd->only_newsig_seen = 0;
    1000             :       /* Check that we only get one of these status codes per
    1001             :          signature; if not the crypto backend misbehaves.  */
    1002           0 :       if (!sig || sig->pka_trust || sig->pka_address)
    1003           0 :         return trace_gpg_error (GPG_ERR_INV_ENGINE);
    1004           0 :       sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
    1005           0 :       end = strchr (args, ' ');
    1006           0 :       if (end)
    1007           0 :         *end = 0;
    1008           0 :       sig->pka_address = strdup (args);
    1009           0 :       break;
    1010             : 
    1011             :     case GPGME_STATUS_TOFU_USER:
    1012          15 :       opd->only_newsig_seen = 0;
    1013          30 :       return sig ? parse_tofu_user (sig, args, ctx->protocol)
    1014          30 :         /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
    1015             : 
    1016             :     case GPGME_STATUS_TOFU_STATS:
    1017          15 :       opd->only_newsig_seen = 0;
    1018          15 :       return sig ? parse_tofu_stats (sig, args)
    1019          15 :         /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
    1020             : 
    1021             :     case GPGME_STATUS_TOFU_STATS_LONG:
    1022          15 :       opd->only_newsig_seen = 0;
    1023          30 :       return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description)
    1024          30 :         /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
    1025             : 
    1026             :     case GPGME_STATUS_ERROR:
    1027           3 :       opd->only_newsig_seen = 0;
    1028             :       /* Some  error stati are informational, so we don't return an
    1029             :          error code if we are not ready to process this status.  */
    1030           3 :       return parse_error (sig, args, !!sig );
    1031             : 
    1032             :     case GPGME_STATUS_FAILURE:
    1033           0 :       opd->failure_code = _gpgme_parse_failure (args);
    1034           0 :       break;
    1035             : 
    1036             :     case GPGME_STATUS_EOF:
    1037          33 :       if (sig && !opd->did_prepare_new_sig)
    1038          30 :         calc_sig_summary (sig);
    1039          33 :       if (opd->only_newsig_seen && sig)
    1040             :         {
    1041             :           gpgme_signature_t sig2;
    1042             :           /* The last signature has no valid information - remove it
    1043             :              from the list. */
    1044           0 :           assert (!sig->next);
    1045           0 :           if (sig == opd->result.signatures)
    1046           0 :             opd->result.signatures = NULL;
    1047             :           else
    1048             :             {
    1049           0 :               for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
    1050           0 :                 if (sig2->next == sig)
    1051             :                   {
    1052           0 :                     sig2->next = NULL;
    1053           0 :                     break;
    1054             :                   }
    1055             :             }
    1056             :           /* Note that there is no need to release the members of SIG
    1057             :              because we won't be here if they have been set. */
    1058           0 :           free (sig);
    1059           0 :           opd->current_sig = NULL;
    1060             :         }
    1061          33 :       opd->only_newsig_seen = 0;
    1062          33 :       if (opd->failure_code)
    1063           0 :         return opd->failure_code;
    1064          33 :       break;
    1065             : 
    1066             :     case GPGME_STATUS_PLAINTEXT:
    1067          26 :       if (++opd->plaintext_seen > 1)
    1068           0 :         return gpg_error (GPG_ERR_BAD_DATA);
    1069          26 :       err = _gpgme_parse_plaintext (args, &opd->result.file_name);
    1070          26 :       if (err)
    1071           0 :         return err;
    1072             : 
    1073             :     default:
    1074         247 :       break;
    1075             :     }
    1076         280 :   return 0;
    1077             : }
    1078             : 
    1079             : 
    1080             : static gpgme_error_t
    1081         374 : verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
    1082             : {
    1083             :   gpgme_error_t err;
    1084             : 
    1085         374 :   err = _gpgme_progress_status_handler (priv, code, args);
    1086         374 :   if (!err)
    1087         374 :     err = _gpgme_verify_status_handler (priv, code, args);
    1088         374 :   return err;
    1089             : }
    1090             : 
    1091             : 
    1092             : gpgme_error_t
    1093          38 : _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
    1094             : {
    1095             :   void *hook;
    1096             :   op_data_t opd;
    1097             : 
    1098          38 :   return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
    1099             :                                 sizeof (*opd), release_op_data);
    1100             : }
    1101             : 
    1102             : 
    1103             : static gpgme_error_t
    1104          31 : verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
    1105             :               gpgme_data_t signed_text, gpgme_data_t plaintext)
    1106             : {
    1107             :   gpgme_error_t err;
    1108             : 
    1109          31 :   err = _gpgme_op_reset (ctx, synchronous);
    1110          31 :   if (err)
    1111           0 :     return err;
    1112             : 
    1113          31 :   err = _gpgme_op_verify_init_result (ctx);
    1114          31 :   if (err)
    1115           0 :     return err;
    1116             : 
    1117          31 :   _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
    1118             : 
    1119          31 :   if (!sig)
    1120           0 :     return gpg_error (GPG_ERR_NO_DATA);
    1121             : 
    1122          31 :   return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
    1123             : }
    1124             : 
    1125             : 
    1126             : /* Decrypt ciphertext CIPHER and make a signature verification within
    1127             :    CTX and store the resulting plaintext in PLAIN.  */
    1128             : gpgme_error_t
    1129           2 : gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
    1130             :                        gpgme_data_t signed_text, gpgme_data_t plaintext)
    1131             : {
    1132             :   gpg_error_t err;
    1133           2 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
    1134             :               "sig=%p, signed_text=%p, plaintext=%p",
    1135             :               sig, signed_text, plaintext);
    1136             : 
    1137           2 :   if (!ctx)
    1138           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
    1139             : 
    1140           2 :   err = verify_start (ctx, 0, sig, signed_text, plaintext);
    1141           2 :   return TRACE_ERR (err);
    1142             : }
    1143             : 
    1144             : 
    1145             : /* Decrypt ciphertext CIPHER and make a signature verification within
    1146             :    CTX and store the resulting plaintext in PLAIN.  */
    1147             : gpgme_error_t
    1148          29 : gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
    1149             :                  gpgme_data_t plaintext)
    1150             : {
    1151             :   gpgme_error_t err;
    1152             : 
    1153          29 :   TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
    1154             :               "sig=%p, signed_text=%p, plaintext=%p",
    1155             :               sig, signed_text, plaintext);
    1156             : 
    1157          29 :   if (!ctx)
    1158           0 :     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
    1159             : 
    1160          29 :   err = verify_start (ctx, 1, sig, signed_text, plaintext);
    1161          29 :   if (!err)
    1162          29 :     err = _gpgme_wait_one (ctx);
    1163          29 :   return TRACE_ERR (err);
    1164             : }
    1165             : 
    1166             : 
    1167             : /* Compatibility interfaces.  */
    1168             : 
    1169             : /* Get the key used to create signature IDX in CTX and return it in
    1170             :    R_KEY.  */
    1171             : gpgme_error_t
    1172           0 : gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
    1173             : {
    1174             :   gpgme_verify_result_t result;
    1175             :   gpgme_signature_t sig;
    1176             : 
    1177           0 :   if (!ctx)
    1178           0 :     return gpg_error (GPG_ERR_INV_VALUE);
    1179             : 
    1180           0 :   result = gpgme_op_verify_result (ctx);
    1181           0 :   sig = result->signatures;
    1182             : 
    1183           0 :   while (sig && idx)
    1184             :     {
    1185           0 :       sig = sig->next;
    1186           0 :       idx--;
    1187             :     }
    1188           0 :   if (!sig || idx)
    1189           0 :     return gpg_error (GPG_ERR_EOF);
    1190             : 
    1191           0 :   return gpgme_get_key (ctx, sig->fpr, r_key, 0);
    1192             : }
    1193             : 
    1194             : 
    1195             : /* Retrieve the signature status of signature IDX in CTX after a
    1196             :    successful verify operation in R_STAT (if non-null).  The creation
    1197             :    time stamp of the signature is returned in R_CREATED (if non-null).
    1198             :    The function returns a string containing the fingerprint.  */
    1199             : const char *
    1200           0 : gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
    1201             :                       _gpgme_sig_stat_t *r_stat, time_t *r_created)
    1202             : {
    1203             :   gpgme_verify_result_t result;
    1204             :   gpgme_signature_t sig;
    1205             : 
    1206           0 :   result = gpgme_op_verify_result (ctx);
    1207           0 :   sig = result->signatures;
    1208             : 
    1209           0 :   while (sig && idx)
    1210             :     {
    1211           0 :       sig = sig->next;
    1212           0 :       idx--;
    1213             :     }
    1214           0 :   if (!sig || idx)
    1215           0 :     return NULL;
    1216             : 
    1217           0 :   if (r_stat)
    1218             :     {
    1219           0 :       switch (gpg_err_code (sig->status))
    1220             :         {
    1221             :         case GPG_ERR_NO_ERROR:
    1222           0 :           *r_stat = GPGME_SIG_STAT_GOOD;
    1223           0 :           break;
    1224             : 
    1225             :         case GPG_ERR_BAD_SIGNATURE:
    1226           0 :           *r_stat = GPGME_SIG_STAT_BAD;
    1227           0 :           break;
    1228             : 
    1229             :         case GPG_ERR_NO_PUBKEY:
    1230           0 :           *r_stat = GPGME_SIG_STAT_NOKEY;
    1231           0 :           break;
    1232             : 
    1233             :         case GPG_ERR_NO_DATA:
    1234           0 :           *r_stat = GPGME_SIG_STAT_NOSIG;
    1235           0 :           break;
    1236             : 
    1237             :         case GPG_ERR_SIG_EXPIRED:
    1238           0 :           *r_stat = GPGME_SIG_STAT_GOOD_EXP;
    1239           0 :           break;
    1240             : 
    1241             :         case GPG_ERR_KEY_EXPIRED:
    1242           0 :           *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
    1243           0 :           break;
    1244             : 
    1245             :         default:
    1246           0 :           *r_stat = GPGME_SIG_STAT_ERROR;
    1247           0 :           break;
    1248             :         }
    1249             :     }
    1250           0 :   if (r_created)
    1251           0 :     *r_created = sig->timestamp;
    1252           0 :   return sig->fpr;
    1253             : }
    1254             : 
    1255             : 
    1256             : /* Retrieve certain attributes of a signature.  IDX is the index
    1257             :    number of the signature after a successful verify operation.  WHAT
    1258             :    is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
    1259             :    one.  WHATIDX is to be passed as 0 for most attributes . */
    1260             : unsigned long
    1261           0 : gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
    1262             :                           _gpgme_attr_t what, int whatidx)
    1263             : {
    1264             :   gpgme_verify_result_t result;
    1265             :   gpgme_signature_t sig;
    1266             : 
    1267           0 :   result = gpgme_op_verify_result (ctx);
    1268           0 :   sig = result->signatures;
    1269             : 
    1270           0 :   while (sig && idx)
    1271             :     {
    1272           0 :       sig = sig->next;
    1273           0 :       idx--;
    1274             :     }
    1275           0 :   if (!sig || idx)
    1276           0 :     return 0;
    1277             : 
    1278           0 :   switch (what)
    1279             :     {
    1280             :     case GPGME_ATTR_CREATED:
    1281           0 :       return sig->timestamp;
    1282             : 
    1283             :     case GPGME_ATTR_EXPIRE:
    1284           0 :       return sig->exp_timestamp;
    1285             : 
    1286             :     case GPGME_ATTR_VALIDITY:
    1287           0 :       return (unsigned long) sig->validity;
    1288             : 
    1289             :     case GPGME_ATTR_SIG_STATUS:
    1290           0 :       switch (gpg_err_code (sig->status))
    1291             :         {
    1292             :         case GPG_ERR_NO_ERROR:
    1293           0 :           return GPGME_SIG_STAT_GOOD;
    1294             : 
    1295             :         case GPG_ERR_BAD_SIGNATURE:
    1296           0 :           return GPGME_SIG_STAT_BAD;
    1297             : 
    1298             :         case GPG_ERR_NO_PUBKEY:
    1299           0 :           return GPGME_SIG_STAT_NOKEY;
    1300             : 
    1301             :         case GPG_ERR_NO_DATA:
    1302           0 :           return GPGME_SIG_STAT_NOSIG;
    1303             : 
    1304             :         case GPG_ERR_SIG_EXPIRED:
    1305           0 :           return GPGME_SIG_STAT_GOOD_EXP;
    1306             : 
    1307             :         case GPG_ERR_KEY_EXPIRED:
    1308           0 :           return GPGME_SIG_STAT_GOOD_EXPKEY;
    1309             : 
    1310             :         default:
    1311           0 :           return GPGME_SIG_STAT_ERROR;
    1312             :         }
    1313             : 
    1314             :     case GPGME_ATTR_SIG_SUMMARY:
    1315           0 :       return sig->summary;
    1316             : 
    1317             :     default:
    1318           0 :       break;
    1319             :     }
    1320           0 :   return 0;
    1321             : }
    1322             : 
    1323             : 
    1324             : const char *
    1325           0 : gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
    1326             :                            _gpgme_attr_t what, int whatidx)
    1327             : {
    1328             :   gpgme_verify_result_t result;
    1329             :   gpgme_signature_t sig;
    1330             : 
    1331           0 :   result = gpgme_op_verify_result (ctx);
    1332           0 :   sig = result->signatures;
    1333             : 
    1334           0 :   while (sig && idx)
    1335             :     {
    1336           0 :       sig = sig->next;
    1337           0 :       idx--;
    1338             :     }
    1339           0 :   if (!sig || idx)
    1340           0 :     return NULL;
    1341             : 
    1342           0 :   switch (what)
    1343             :     {
    1344             :     case GPGME_ATTR_FPR:
    1345           0 :       return sig->fpr;
    1346             : 
    1347             :     case GPGME_ATTR_ERRTOK:
    1348           0 :       if (whatidx == 1)
    1349           0 :         return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
    1350             :       else
    1351           0 :         return "";
    1352             :     default:
    1353           0 :       break;
    1354             :     }
    1355             : 
    1356           0 :   return NULL;
    1357             : }

Generated by: LCOV version 1.11