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

Generated by: LCOV version 1.11