1 /* verify.c - Signature verification.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2005 g10 Code GmbH
5 This file is part of GPGME.
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.
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.
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
40 struct _gpgme_op_verify_result result;
42 /* The error code from a FAILURE status line or 0. */
43 gpg_error_t failure_code;
45 gpgme_signature_t current_sig;
46 int did_prepare_new_sig;
49 int conflict_user_seen;
54 release_op_data (void *hook)
56 op_data_t opd = (op_data_t) hook;
57 gpgme_signature_t sig = opd->result.signatures;
61 gpgme_signature_t next = sig->next;
62 gpgme_sig_notation_t notation = sig->notations;
66 gpgme_sig_notation_t next_nota = notation->next;
68 _gpgme_sig_notation_free (notation);
75 free (sig->pka_address);
77 gpgme_key_unref (sig->key);
82 if (opd->result.file_name)
83 free (opd->result.file_name);
88 gpgme_op_verify_result (gpgme_ctx_t ctx)
93 gpgme_signature_t sig;
95 TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
96 err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
100 TRACE_SUC0 ("result=(null)");
104 /* It is possible that we saw a new signature only followed by an
105 ERROR line for that. In particular a missing X.509 key triggers
106 this. In this case it is surprising that the summary field has
107 not been updated. We fix it here by explicitly looking for this
108 case. The real fix would be to have GPGME emit ERRSIG. */
109 for (sig = opd->result.signatures; sig; sig = sig->next)
113 switch (gpg_err_code (sig->status))
115 case GPG_ERR_KEY_EXPIRED:
116 sig->summary |= GPGME_SIGSUM_KEY_EXPIRED;
119 case GPG_ERR_NO_PUBKEY:
120 sig->summary |= GPGME_SIGSUM_KEY_MISSING;
129 /* Now for some tracing stuff. */
130 if (_gpgme_debug_trace ())
134 for (sig = opd->result.signatures, i = 0; sig; sig = sig->next, i++)
136 TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
137 i, sig->fpr, sig->summary, gpg_strerror (sig->status));
138 TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
139 i, sig->timestamp, sig->exp_timestamp,
140 sig->wrong_key_usage ? "wrong key usage" : "",
141 sig->pka_trust == 1 ? "pka bad"
142 : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
143 sig->chain_model ? "chain model" : "");
144 TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
145 i, sig->validity, gpg_strerror (sig->validity_reason),
146 gpgme_pubkey_algo_name (sig->pubkey_algo),
147 gpgme_hash_algo_name (sig->hash_algo));
148 if (sig->pka_address)
150 TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
154 TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
159 TRACE_SUC1 ("result=%p", &opd->result);
164 /* Build a summary vector from RESULT. */
166 calc_sig_summary (gpgme_signature_t sig)
168 unsigned long sum = 0;
170 /* Calculate the red/green flag. */
171 if (sig->validity == GPGME_VALIDITY_FULL
172 || sig->validity == GPGME_VALIDITY_ULTIMATE)
174 if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
175 || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
176 || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
177 sum |= GPGME_SIGSUM_GREEN;
179 else if (sig->validity == GPGME_VALIDITY_NEVER)
181 if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
182 || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
183 || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
184 sum |= GPGME_SIGSUM_RED;
186 else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
187 sum |= GPGME_SIGSUM_RED;
190 /* FIXME: handle the case when key and message are expired. */
191 switch (gpg_err_code (sig->status))
193 case GPG_ERR_SIG_EXPIRED:
194 sum |= GPGME_SIGSUM_SIG_EXPIRED;
197 case GPG_ERR_KEY_EXPIRED:
198 sum |= GPGME_SIGSUM_KEY_EXPIRED;
201 case GPG_ERR_NO_PUBKEY:
202 sum |= GPGME_SIGSUM_KEY_MISSING;
205 case GPG_ERR_CERT_REVOKED:
206 sum |= GPGME_SIGSUM_KEY_REVOKED;
209 case GPG_ERR_BAD_SIGNATURE:
210 case GPG_ERR_NO_ERROR:
214 sum |= GPGME_SIGSUM_SYS_ERROR;
218 /* Now look at the certain reason codes. */
219 switch (gpg_err_code (sig->validity_reason))
221 case GPG_ERR_CRL_TOO_OLD:
222 if (sig->validity == GPGME_VALIDITY_UNKNOWN)
223 sum |= GPGME_SIGSUM_CRL_TOO_OLD;
226 case GPG_ERR_CERT_REVOKED:
227 /* Note that this is a second way to set this flag. It may also
228 have been set due to a sig->status of STATUS_REVKEYSIG from
230 sum |= GPGME_SIGSUM_KEY_REVOKED;
237 /* Check other flags. */
238 if (sig->wrong_key_usage)
239 sum |= GPGME_SIGSUM_BAD_POLICY;
241 /* Set the valid flag when the signature is unquestionable
242 valid. (The test is identical to if(sum == GPGME_SIGSUM_GREEN)). */
243 if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
244 sum |= GPGME_SIGSUM_VALID;
251 prepare_new_sig (op_data_t opd)
253 gpgme_signature_t sig;
255 if (opd->only_newsig_seen && opd->current_sig)
257 /* We have only seen the NEWSIG status and nothing else - we
258 better skip this signature therefore and reuse it for the
259 next possible signature. */
260 sig = opd->current_sig;
261 memset (sig, 0, sizeof *sig);
262 assert (opd->result.signatures == sig);
266 sig = calloc (1, sizeof (*sig));
268 return gpg_error_from_syserror ();
269 if (!opd->result.signatures)
270 opd->result.signatures = sig;
271 if (opd->current_sig)
272 opd->current_sig->next = sig;
273 opd->current_sig = sig;
275 opd->did_prepare_new_sig = 1;
276 opd->only_newsig_seen = 0;
281 parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
282 gpgme_protocol_t protocol)
284 gpgme_signature_t sig;
285 char *end = strchr (args, ' ');
294 if (!opd->did_prepare_new_sig)
298 err = prepare_new_sig (opd);
302 assert (opd->did_prepare_new_sig);
303 opd->did_prepare_new_sig = 0;
305 assert (opd->current_sig);
306 sig = opd->current_sig;
308 /* FIXME: We should set the source of the state. */
311 case GPGME_STATUS_GOODSIG:
312 sig->status = gpg_error (GPG_ERR_NO_ERROR);
315 case GPGME_STATUS_EXPSIG:
316 sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
319 case GPGME_STATUS_EXPKEYSIG:
320 sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
323 case GPGME_STATUS_BADSIG:
324 sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
327 case GPGME_STATUS_REVKEYSIG:
328 sig->status = gpg_error (GPG_ERR_CERT_REVOKED);
331 case GPGME_STATUS_ERRSIG:
332 /* Parse the pubkey algo. */
334 goto parse_err_sig_fail;
335 gpg_err_set_errno (0);
336 sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0), protocol);
337 if (errno || end == tail || *tail != ' ')
338 goto parse_err_sig_fail;
343 /* Parse the hash algo. */
345 goto parse_err_sig_fail;
346 gpg_err_set_errno (0);
347 sig->hash_algo = strtol (end, &tail, 0);
348 if (errno || end == tail || *tail != ' ')
349 goto parse_err_sig_fail;
354 /* Skip the sig class. */
355 end = strchr (end, ' ');
357 goto parse_err_sig_fail;
361 /* Parse the timestamp. */
362 sig->timestamp = _gpgme_parse_timestamp (end, &tail);
363 if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
364 return trace_gpg_error (GPG_ERR_INV_ENGINE);
369 /* Parse the return code. */
371 goto parse_err_sig_fail;
373 sig->status = strtoul (end, NULL, 10);
374 goto parse_err_sig_ok;
377 sig->status = gpg_error (GPG_ERR_GENERAL);
382 return gpg_error (GPG_ERR_GENERAL);
387 sig->fpr = strdup (args);
389 return gpg_error_from_syserror ();
396 parse_valid_sig (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
398 char *end = strchr (args, ' ');
406 /* We require at least the fingerprint. */
407 return gpg_error (GPG_ERR_GENERAL);
411 sig->fpr = strdup (args);
413 return gpg_error_from_syserror ();
415 /* Skip the creation date. */
416 end = strchr (end, ' ');
421 sig->timestamp = _gpgme_parse_timestamp (end, &tail);
422 if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
423 return trace_gpg_error (GPG_ERR_INV_ENGINE);
426 sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
427 if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
428 return trace_gpg_error (GPG_ERR_INV_ENGINE);
433 /* Skip the signature version. */
434 end = strchr (end, ' ');
440 /* Skip the reserved field. */
441 end = strchr (end, ' ');
444 /* Parse the pubkey algo. */
445 gpg_err_set_errno (0);
446 sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0),
448 if (errno || end == tail || *tail != ' ')
449 return trace_gpg_error (GPG_ERR_INV_ENGINE);
457 /* Parse the hash algo. */
459 gpg_err_set_errno (0);
460 sig->hash_algo = strtol (end, &tail, 0);
461 if (errno || end == tail || *tail != ' ')
462 return trace_gpg_error (GPG_ERR_INV_ENGINE);
473 parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
476 gpgme_sig_notation_t *lastp = &sig->notations;
477 gpgme_sig_notation_t notation = sig->notations;
480 if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
482 p = strchr (args, ' ');
486 /* FIXME: We could keep a pointer to the last notation in the list. */
487 while (notation && notation->value)
489 lastp = ¬ation->next;
490 notation = notation->next;
494 /* There is another notation name without data for the
495 previous one. The crypto backend misbehaves. */
496 return trace_gpg_error (GPG_ERR_INV_ENGINE);
498 err = _gpgme_sig_notation_create (¬ation, NULL, 0, NULL, 0, 0);
502 if (code == GPGME_STATUS_NOTATION_NAME)
504 err = _gpgme_decode_percent_string (args, ¬ation->name, 0, 0);
507 _gpgme_sig_notation_free (notation);
511 notation->name_len = strlen (notation->name);
513 /* Set default flags for use with older gpg versions which
514 * do not emit a NOTATIONS_FLAG line. */
515 notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
516 notation->human_readable = 1;
520 /* This is a policy URL. */
522 err = _gpgme_decode_percent_string (args, ¬ation->value, 0, 0);
525 _gpgme_sig_notation_free (notation);
529 notation->value_len = strlen (notation->value);
533 else if (code == GPGME_STATUS_NOTATION_FLAGS)
537 while (notation && notation->next)
539 lastp = ¬ation->next;
540 notation = notation->next;
543 if (!notation || !notation->name)
544 { /* There are notation flags without a previous notation name.
545 * The crypto backend misbehaves. */
546 return trace_gpg_error (GPG_ERR_INV_ENGINE);
548 if (_gpgme_split_fields (args, field, DIM (field)) < 2)
549 { /* Required args missing. */
550 return trace_gpg_error (GPG_ERR_INV_ENGINE);
555 notation->flags |= GPGME_SIG_NOTATION_CRITICAL;
556 notation->critical = 1;
560 notation->flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
561 notation->human_readable = 1;
564 else if (code == GPGME_STATUS_NOTATION_DATA)
566 int len = strlen (args) + 1;
569 /* FIXME: We could keep a pointer to the last notation in the list. */
570 while (notation && notation->next)
572 lastp = ¬ation->next;
573 notation = notation->next;
576 if (!notation || !notation->name)
577 /* There is notation data without a previous notation
578 name. The crypto backend misbehaves. */
579 return trace_gpg_error (GPG_ERR_INV_ENGINE);
581 if (!notation->value)
583 dest = notation->value = malloc (len);
585 return gpg_error_from_syserror ();
589 int cur_len = strlen (notation->value);
590 dest = realloc (notation->value, len + strlen (notation->value));
592 return gpg_error_from_syserror ();
593 notation->value = dest;
597 err = _gpgme_decode_percent_string (args, &dest, len, 0);
601 notation->value_len += strlen (dest);
604 return trace_gpg_error (GPG_ERR_INV_ENGINE);
610 parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
612 char *end = strchr (args, ' ');
619 case GPGME_STATUS_TRUST_UNDEFINED:
621 sig->validity = GPGME_VALIDITY_UNKNOWN;
624 case GPGME_STATUS_TRUST_NEVER:
625 sig->validity = GPGME_VALIDITY_NEVER;
628 case GPGME_STATUS_TRUST_MARGINAL:
629 sig->validity = GPGME_VALIDITY_MARGINAL;
632 case GPGME_STATUS_TRUST_FULLY:
633 case GPGME_STATUS_TRUST_ULTIMATE:
634 sig->validity = GPGME_VALIDITY_FULL;
638 sig->validity_reason = 0;
639 sig->chain_model = 0;
642 sig->validity_reason = atoi (args);
643 while (*args && *args != ' ')
649 if (!strncmp (args, "chain", 2) && (args[2] == ' ' || !args[2]))
650 sig->chain_model = 1;
658 /* Parse a TOFU_USER line and put the info into SIG. */
660 parse_tofu_user (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
665 gpgme_tofu_info_t ti;
667 char *address = NULL;
669 tail = strchr (args, ' ');
670 if (!tail || tail == args)
672 err = trace_gpg_error (GPG_ERR_INV_ENGINE); /* No fingerprint. */
680 err = gpg_error_from_syserror ();
684 if (sig->key && sig->key->fpr && strcmp (sig->key->fpr, fpr))
686 /* GnuPG since 2.1.17 emits multiple TOFU_USER lines with
687 different fingerprints in case of conflicts for a signature. */
688 err = gpg_error (GPG_ERR_DUP_VALUE);
693 tail = strchr (args, ' ');
696 err = trace_gpg_error (GPG_ERR_INV_ENGINE); /* No addr-spec. */
702 err = _gpgme_decode_percent_string (args, &address, 0, 0);
708 err = _gpgme_key_new (&sig->key);
712 sig->key->protocol = protocol;
715 else if (!sig->key->fpr)
717 err = trace_gpg_error (GPG_ERR_INTERNAL);
721 err = _gpgme_key_append_name (sig->key, address, 0);
725 uid = sig->key->_last_uid;
728 ti = calloc (1, sizeof *ti);
731 err = gpg_error_from_syserror ();
744 /* Parse a TOFU_STATS line and store it in the last tofu info of SIG.
746 * TOFU_STATS <validity> <sign-count> <encr-count> \
747 * [<policy> [<tm1> <tm2> <tm3> <tm4>]]
750 parse_tofu_stats (gpgme_signature_t sig, char *args)
753 gpgme_tofu_info_t ti;
758 if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
759 return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen. */
760 if (ti->signfirst || ti->signcount || ti->validity || ti->policy)
761 return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set. */
763 nfields = _gpgme_split_fields (args, field, DIM (field));
765 return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required args missing. */
767 /* Note that we allow a value of up to 7 which is what we can store
768 * in the ti->validity. */
769 err = _gpgme_strtoul_field (field[0], &uval);
771 return trace_gpg_error (GPG_ERR_INV_ENGINE);
774 /* Parse the sign-count. */
775 err = _gpgme_strtoul_field (field[1], &uval);
777 return trace_gpg_error (GPG_ERR_INV_ENGINE);
778 if (uval > USHRT_MAX)
780 ti->signcount = uval;
782 /* Parse the encr-count. */
783 err = _gpgme_strtoul_field (field[2], &uval);
785 return trace_gpg_error (GPG_ERR_INV_ENGINE);
786 if (uval > USHRT_MAX)
788 ti->encrcount = uval;
791 return 0; /* All mandatory fields parsed. */
793 /* Parse the policy. */
794 if (!strcmp (field[3], "none"))
795 ti->policy = GPGME_TOFU_POLICY_NONE;
796 else if (!strcmp (field[3], "auto"))
797 ti->policy = GPGME_TOFU_POLICY_AUTO;
798 else if (!strcmp (field[3], "good"))
799 ti->policy = GPGME_TOFU_POLICY_GOOD;
800 else if (!strcmp (field[3], "bad"))
801 ti->policy = GPGME_TOFU_POLICY_BAD;
802 else if (!strcmp (field[3], "ask"))
803 ti->policy = GPGME_TOFU_POLICY_ASK;
804 else /* "unknown" and invalid policy strings. */
805 ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
808 return 0; /* No more optional fields. */
810 /* Parse first and last seen timestamps (none or both are required). */
812 return trace_gpg_error (GPG_ERR_INV_ENGINE); /* "tm2" missing. */
813 err = _gpgme_strtoul_field (field[4], &uval);
815 return trace_gpg_error (GPG_ERR_INV_ENGINE);
816 ti->signfirst = uval;
817 err = _gpgme_strtoul_field (field[5], &uval);
819 return trace_gpg_error (GPG_ERR_INV_ENGINE);
823 /* This condition is only to allow for gpg 2.1.15 - can
824 * eventually be removed. */
825 err = _gpgme_strtoul_field (field[6], &uval);
827 return trace_gpg_error (GPG_ERR_INV_ENGINE);
828 ti->encrfirst = uval;
829 err = _gpgme_strtoul_field (field[7], &uval);
831 return trace_gpg_error (GPG_ERR_INV_ENGINE);
839 /* Parse a TOFU_STATS_LONG line and store it in the last tofu info of SIG. */
841 parse_tofu_stats_long (gpgme_signature_t sig, char *args, int raw)
844 gpgme_tofu_info_t ti;
847 if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
848 return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen. */
850 return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set. */
852 err = _gpgme_decode_percent_string (args, &ti->description, 0, 0);
856 /* Remove the non-breaking spaces. */
859 for (p = ti->description; *p; p++)
867 /* Parse an error status line and if SET_STATUS is true update the
868 result status as appropriate. With SET_STATUS being false, only
869 check for an error. */
871 parse_error (gpgme_signature_t sig, char *args, int set_status)
874 char *where = strchr (args, ' ');
882 where = strchr (which, ' ');
889 return trace_gpg_error (GPG_ERR_INV_ENGINE);
893 if (!strcmp (where, "proc_pkt.plaintext")
894 && gpg_err_code (err) == GPG_ERR_BAD_DATA)
896 /* This indicates a double plaintext. The only solid way to
897 handle this is by failing the oepration. */
898 return gpg_error (GPG_ERR_BAD_DATA);
900 else if (!set_status)
902 else if (!strcmp (where, "verify.findkey"))
904 else if (!strcmp (where, "verify.keyusage")
905 && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
906 sig->wrong_key_usage = 1;
913 _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
915 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
919 gpgme_signature_t sig;
922 err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
927 sig = opd->current_sig;
931 case GPGME_STATUS_NEWSIG:
933 calc_sig_summary (sig);
934 err = prepare_new_sig (opd);
935 opd->only_newsig_seen = 1;
936 opd->conflict_user_seen = 0;
939 case GPGME_STATUS_GOODSIG:
940 case GPGME_STATUS_EXPSIG:
941 case GPGME_STATUS_EXPKEYSIG:
942 case GPGME_STATUS_BADSIG:
943 case GPGME_STATUS_ERRSIG:
944 case GPGME_STATUS_REVKEYSIG:
945 if (sig && !opd->did_prepare_new_sig)
946 calc_sig_summary (sig);
947 opd->only_newsig_seen = 0;
948 return parse_new_sig (opd, code, args, ctx->protocol);
950 case GPGME_STATUS_VALIDSIG:
951 opd->only_newsig_seen = 0;
952 return sig ? parse_valid_sig (sig, args, ctx->protocol)
953 : trace_gpg_error (GPG_ERR_INV_ENGINE);
955 case GPGME_STATUS_NODATA:
956 opd->only_newsig_seen = 0;
958 return gpg_error (GPG_ERR_NO_DATA);
959 sig->status = gpg_error (GPG_ERR_NO_DATA);
962 case GPGME_STATUS_UNEXPECTED:
963 opd->only_newsig_seen = 0;
965 return gpg_error (GPG_ERR_GENERAL);
966 sig->status = gpg_error (GPG_ERR_NO_DATA);
969 case GPGME_STATUS_NOTATION_NAME:
970 case GPGME_STATUS_NOTATION_FLAGS:
971 case GPGME_STATUS_NOTATION_DATA:
972 case GPGME_STATUS_POLICY_URL:
973 opd->only_newsig_seen = 0;
974 return sig ? parse_notation (sig, code, args)
975 : trace_gpg_error (GPG_ERR_INV_ENGINE);
977 case GPGME_STATUS_TRUST_UNDEFINED:
978 case GPGME_STATUS_TRUST_NEVER:
979 case GPGME_STATUS_TRUST_MARGINAL:
980 case GPGME_STATUS_TRUST_FULLY:
981 case GPGME_STATUS_TRUST_ULTIMATE:
982 opd->only_newsig_seen = 0;
983 return sig ? parse_trust (sig, code, args)
984 : trace_gpg_error (GPG_ERR_INV_ENGINE);
986 case GPGME_STATUS_PKA_TRUST_BAD:
987 case GPGME_STATUS_PKA_TRUST_GOOD:
988 opd->only_newsig_seen = 0;
989 /* Check that we only get one of these status codes per
990 signature; if not the crypto backend misbehaves. */
991 if (!sig || sig->pka_trust || sig->pka_address)
992 return trace_gpg_error (GPG_ERR_INV_ENGINE);
993 sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
994 end = strchr (args, ' ');
997 sig->pka_address = strdup (args);
1000 case GPGME_STATUS_TOFU_USER:
1001 opd->only_newsig_seen = 0;
1003 return trace_gpg_error (GPG_ERR_INV_ENGINE);
1004 err = parse_tofu_user (sig, args, ctx->protocol);
1005 /* gpg emits TOFU User lines for each conflicting key.
1006 * GPGME does not expose this to have a clean API and
1007 * a GPGME user can do a keylisting with the address
1009 * So when a duplicated TOFU_USER line is encountered
1010 * we ignore the conflicting tofu stats emited afterwards.
1012 if (gpg_err_code (err) == GPG_ERR_DUP_VALUE)
1014 opd->conflict_user_seen = 1;
1017 opd->conflict_user_seen = 0;
1018 return trace_gpg_error (err);
1020 case GPGME_STATUS_TOFU_STATS:
1021 opd->only_newsig_seen = 0;
1022 if (opd->conflict_user_seen)
1024 return sig ? parse_tofu_stats (sig, args)
1025 /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
1027 case GPGME_STATUS_TOFU_STATS_LONG:
1028 opd->only_newsig_seen = 0;
1029 if (opd->conflict_user_seen)
1031 return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description)
1032 /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
1034 case GPGME_STATUS_ERROR:
1035 opd->only_newsig_seen = 0;
1036 /* Some error stati are informational, so we don't return an
1037 error code if we are not ready to process this status. */
1038 return parse_error (sig, args, !!sig );
1040 case GPGME_STATUS_FAILURE:
1041 opd->failure_code = _gpgme_parse_failure (args);
1044 case GPGME_STATUS_EOF:
1045 if (sig && !opd->did_prepare_new_sig)
1046 calc_sig_summary (sig);
1047 if (opd->only_newsig_seen && sig)
1049 gpgme_signature_t sig2;
1050 /* The last signature has no valid information - remove it
1052 assert (!sig->next);
1053 if (sig == opd->result.signatures)
1054 opd->result.signatures = NULL;
1057 for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
1058 if (sig2->next == sig)
1064 /* Note that there is no need to release the members of SIG
1065 because we won't be here if they have been set. */
1067 opd->current_sig = NULL;
1069 opd->only_newsig_seen = 0;
1070 if (opd->failure_code)
1071 return opd->failure_code;
1074 case GPGME_STATUS_PLAINTEXT:
1075 if (++opd->plaintext_seen > 1)
1076 return gpg_error (GPG_ERR_BAD_DATA);
1077 err = _gpgme_parse_plaintext (args, &opd->result.file_name);
1081 case GPGME_STATUS_VERIFICATION_COMPLIANCE_MODE:
1082 PARSE_COMPLIANCE_FLAGS (args, opd->current_sig);
1092 static gpgme_error_t
1093 verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
1097 err = _gpgme_progress_status_handler (priv, code, args);
1099 err = _gpgme_verify_status_handler (priv, code, args);
1105 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
1110 return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
1111 sizeof (*opd), release_op_data);
1115 static gpgme_error_t
1116 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
1117 gpgme_data_t signed_text, gpgme_data_t plaintext)
1121 err = _gpgme_op_reset (ctx, synchronous);
1125 err = _gpgme_op_verify_init_result (ctx);
1129 _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
1132 return gpg_error (GPG_ERR_NO_DATA);
1134 return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext,
1139 /* Decrypt ciphertext CIPHER and make a signature verification within
1140 CTX and store the resulting plaintext in PLAIN. */
1142 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
1143 gpgme_data_t signed_text, gpgme_data_t plaintext)
1146 TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify_start", ctx,
1147 "sig=%p, signed_text=%p, plaintext=%p",
1148 sig, signed_text, plaintext);
1151 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1153 err = verify_start (ctx, 0, sig, signed_text, plaintext);
1154 return TRACE_ERR (err);
1158 /* Decrypt ciphertext CIPHER and make a signature verification within
1159 CTX and store the resulting plaintext in PLAIN. */
1161 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
1162 gpgme_data_t plaintext)
1166 TRACE_BEG3 (DEBUG_CTX, "gpgme_op_verify", ctx,
1167 "sig=%p, signed_text=%p, plaintext=%p",
1168 sig, signed_text, plaintext);
1171 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
1173 err = verify_start (ctx, 1, sig, signed_text, plaintext);
1175 err = _gpgme_wait_one (ctx);
1176 return TRACE_ERR (err);
1180 /* Compatibility interfaces. */
1182 /* Get the key used to create signature IDX in CTX and return it in
1185 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
1187 gpgme_verify_result_t result;
1188 gpgme_signature_t sig;
1191 return gpg_error (GPG_ERR_INV_VALUE);
1193 result = gpgme_op_verify_result (ctx);
1194 sig = result->signatures;
1202 return gpg_error (GPG_ERR_EOF);
1204 return gpgme_get_key (ctx, sig->fpr, r_key, 0);
1208 /* Retrieve the signature status of signature IDX in CTX after a
1209 successful verify operation in R_STAT (if non-null). The creation
1210 time stamp of the signature is returned in R_CREATED (if non-null).
1211 The function returns a string containing the fingerprint. */
1213 gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
1214 _gpgme_sig_stat_t *r_stat, time_t *r_created)
1216 gpgme_verify_result_t result;
1217 gpgme_signature_t sig;
1219 result = gpgme_op_verify_result (ctx);
1220 sig = result->signatures;
1232 switch (gpg_err_code (sig->status))
1234 case GPG_ERR_NO_ERROR:
1235 *r_stat = GPGME_SIG_STAT_GOOD;
1238 case GPG_ERR_BAD_SIGNATURE:
1239 *r_stat = GPGME_SIG_STAT_BAD;
1242 case GPG_ERR_NO_PUBKEY:
1243 *r_stat = GPGME_SIG_STAT_NOKEY;
1246 case GPG_ERR_NO_DATA:
1247 *r_stat = GPGME_SIG_STAT_NOSIG;
1250 case GPG_ERR_SIG_EXPIRED:
1251 *r_stat = GPGME_SIG_STAT_GOOD_EXP;
1254 case GPG_ERR_KEY_EXPIRED:
1255 *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
1259 *r_stat = GPGME_SIG_STAT_ERROR;
1264 *r_created = sig->timestamp;
1269 /* Retrieve certain attributes of a signature. IDX is the index
1270 number of the signature after a successful verify operation. WHAT
1271 is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
1272 one. WHATIDX is to be passed as 0 for most attributes . */
1274 gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
1275 _gpgme_attr_t what, int whatidx)
1277 gpgme_verify_result_t result;
1278 gpgme_signature_t sig;
1282 result = gpgme_op_verify_result (ctx);
1283 sig = result->signatures;
1295 case GPGME_ATTR_CREATED:
1296 return sig->timestamp;
1298 case GPGME_ATTR_EXPIRE:
1299 return sig->exp_timestamp;
1301 case GPGME_ATTR_VALIDITY:
1302 return (unsigned long) sig->validity;
1304 case GPGME_ATTR_SIG_STATUS:
1305 switch (gpg_err_code (sig->status))
1307 case GPG_ERR_NO_ERROR:
1308 return GPGME_SIG_STAT_GOOD;
1310 case GPG_ERR_BAD_SIGNATURE:
1311 return GPGME_SIG_STAT_BAD;
1313 case GPG_ERR_NO_PUBKEY:
1314 return GPGME_SIG_STAT_NOKEY;
1316 case GPG_ERR_NO_DATA:
1317 return GPGME_SIG_STAT_NOSIG;
1319 case GPG_ERR_SIG_EXPIRED:
1320 return GPGME_SIG_STAT_GOOD_EXP;
1322 case GPG_ERR_KEY_EXPIRED:
1323 return GPGME_SIG_STAT_GOOD_EXPKEY;
1326 return GPGME_SIG_STAT_ERROR;
1329 case GPGME_ATTR_SIG_SUMMARY:
1330 return sig->summary;
1340 gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
1341 _gpgme_attr_t what, int whatidx)
1343 gpgme_verify_result_t result;
1344 gpgme_signature_t sig;
1346 result = gpgme_op_verify_result (ctx);
1347 sig = result->signatures;
1359 case GPGME_ATTR_FPR:
1362 case GPGME_ATTR_ERRTOK:
1364 return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";