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
38 struct _gpgme_op_verify_result result;
40 gpgme_signature_t current_sig;
41 int did_prepare_new_sig;
47 release_op_data (void *hook)
49 op_data_t opd = (op_data_t) hook;
50 gpgme_signature_t sig = opd->result.signatures;
54 gpgme_signature_t next = sig->next;
55 gpgme_sig_notation_t notation = sig->notations;
59 gpgme_sig_notation_t next_nota = notation->next;
61 _gpgme_sig_notation_free (notation);
71 if (opd->result.file_name)
72 free (opd->result.file_name);
77 gpgme_op_verify_result (gpgme_ctx_t ctx)
83 err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
92 /* Build a summary vector from RESULT. */
94 calc_sig_summary (gpgme_signature_t sig)
96 unsigned long sum = 0;
98 /* Calculate the red/green flag. */
99 if (sig->validity == GPGME_VALIDITY_FULL
100 || sig->validity == GPGME_VALIDITY_ULTIMATE)
102 if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
103 || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
104 || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
105 sum |= GPGME_SIGSUM_GREEN;
107 else if (sig->validity == GPGME_VALIDITY_NEVER)
109 if (gpg_err_code (sig->status) == GPG_ERR_NO_ERROR
110 || gpg_err_code (sig->status) == GPG_ERR_SIG_EXPIRED
111 || gpg_err_code (sig->status) == GPG_ERR_KEY_EXPIRED)
112 sum |= GPGME_SIGSUM_RED;
114 else if (gpg_err_code (sig->status) == GPG_ERR_BAD_SIGNATURE)
115 sum |= GPGME_SIGSUM_RED;
118 /* FIXME: handle the case when key and message are expired. */
119 switch (gpg_err_code (sig->status))
121 case GPG_ERR_SIG_EXPIRED:
122 sum |= GPGME_SIGSUM_SIG_EXPIRED;
125 case GPG_ERR_KEY_EXPIRED:
126 sum |= GPGME_SIGSUM_KEY_EXPIRED;
129 case GPG_ERR_NO_PUBKEY:
130 sum |= GPGME_SIGSUM_KEY_MISSING;
133 case GPG_ERR_BAD_SIGNATURE:
134 case GPG_ERR_NO_ERROR:
138 sum |= GPGME_SIGSUM_SYS_ERROR;
142 /* Now look at the certain reason codes. */
143 switch (gpg_err_code (sig->validity_reason))
145 case GPG_ERR_CRL_TOO_OLD:
146 if (sig->validity == GPGME_VALIDITY_UNKNOWN)
147 sum |= GPGME_SIGSUM_CRL_TOO_OLD;
150 case GPG_ERR_CERT_REVOKED:
151 sum |= GPGME_SIGSUM_KEY_REVOKED;
158 /* Check other flags. */
159 if (sig->wrong_key_usage)
160 sum |= GPGME_SIGSUM_BAD_POLICY;
162 /* Set the valid flag when the signature is unquestionable
164 if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
165 sum |= GPGME_SIGSUM_VALID;
172 prepare_new_sig (op_data_t opd)
174 gpgme_signature_t sig;
176 if (opd->only_newsig_seen && opd->current_sig)
178 /* We have only seen the NEWSIG status and nothing else - we
179 better skip this signature therefore and reuse it for the
180 next possible signature. */
181 sig = opd->current_sig;
182 memset (sig, 0, sizeof *sig);
183 assert (opd->result.signatures == sig);
187 sig = calloc (1, sizeof (*sig));
189 return gpg_error_from_errno (errno);
190 if (!opd->result.signatures)
191 opd->result.signatures = sig;
192 if (opd->current_sig)
193 opd->current_sig->next = sig;
194 opd->current_sig = sig;
196 opd->did_prepare_new_sig = 1;
197 opd->only_newsig_seen = 0;
202 parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args)
204 gpgme_signature_t sig;
205 char *end = strchr (args, ' ');
214 if (!opd->did_prepare_new_sig)
218 err = prepare_new_sig (opd);
222 assert (opd->did_prepare_new_sig);
223 opd->did_prepare_new_sig = 0;
225 assert (opd->current_sig);
226 sig = opd->current_sig;
228 /* FIXME: We should set the source of the state. */
231 case GPGME_STATUS_GOODSIG:
232 sig->status = gpg_error (GPG_ERR_NO_ERROR);
235 case GPGME_STATUS_EXPSIG:
236 sig->status = gpg_error (GPG_ERR_SIG_EXPIRED);
239 case GPGME_STATUS_EXPKEYSIG:
240 sig->status = gpg_error (GPG_ERR_KEY_EXPIRED);
243 case GPGME_STATUS_BADSIG:
244 sig->status = gpg_error (GPG_ERR_BAD_SIGNATURE);
247 case GPGME_STATUS_REVKEYSIG:
248 sig->status = gpg_error (GPG_ERR_CERT_REVOKED);
251 case GPGME_STATUS_ERRSIG:
252 /* Parse the pubkey algo. */
254 goto parse_err_sig_fail;
256 sig->pubkey_algo = strtol (end, &tail, 0);
257 if (errno || end == tail || *tail != ' ')
258 goto parse_err_sig_fail;
263 /* Parse the hash algo. */
265 goto parse_err_sig_fail;
267 sig->hash_algo = strtol (end, &tail, 0);
268 if (errno || end == tail || *tail != ' ')
269 goto parse_err_sig_fail;
274 /* Skip the sig class. */
275 end = strchr (end, ' ');
277 goto parse_err_sig_fail;
281 /* Parse the timestamp. */
282 sig->timestamp = _gpgme_parse_timestamp (end, &tail);
283 if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
284 return gpg_error (GPG_ERR_INV_ENGINE);
289 /* Parse the return code. */
290 if (end[0] && (!end[1] || end[1] == ' '))
295 sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
299 sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
303 sig->status = gpg_error (GPG_ERR_GENERAL);
307 goto parse_err_sig_fail;
309 goto parse_err_sig_ok;
312 sig->status = gpg_error (GPG_ERR_GENERAL);
317 return gpg_error (GPG_ERR_GENERAL);
322 sig->fpr = strdup (args);
324 return gpg_error_from_errno (errno);
331 parse_valid_sig (gpgme_signature_t sig, char *args)
333 char *end = strchr (args, ' ');
341 /* We require at least the fingerprint. */
342 return gpg_error (GPG_ERR_GENERAL);
346 sig->fpr = strdup (args);
348 return gpg_error_from_errno (errno);
350 /* Skip the creation date. */
351 end = strchr (end, ' ');
356 sig->timestamp = _gpgme_parse_timestamp (end, &tail);
357 if (sig->timestamp == -1 || end == tail || (*tail && *tail != ' '))
358 return gpg_error (GPG_ERR_INV_ENGINE);
361 sig->exp_timestamp = _gpgme_parse_timestamp (end, &tail);
362 if (sig->exp_timestamp == -1 || end == tail || (*tail && *tail != ' '))
363 return gpg_error (GPG_ERR_INV_ENGINE);
368 /* Skip the signature version. */
369 end = strchr (end, ' ');
375 /* Skip the reserved field. */
376 end = strchr (end, ' ');
379 /* Parse the pubkey algo. */
381 sig->pubkey_algo = strtol (end, &tail, 0);
382 if (errno || end == tail || *tail != ' ')
383 return gpg_error (GPG_ERR_INV_ENGINE);
391 /* Parse the hash algo. */
394 sig->hash_algo = strtol (end, &tail, 0);
395 if (errno || end == tail || *tail != ' ')
396 return gpg_error (GPG_ERR_INV_ENGINE);
407 parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
410 gpgme_sig_notation_t *lastp = &sig->notations;
411 gpgme_sig_notation_t notation = sig->notations;
412 char *end = strchr (args, ' ');
417 if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
419 /* FIXME: We could keep a pointer to the last notation in the list. */
420 while (notation && notation->value)
422 lastp = ¬ation->next;
423 notation = notation->next;
427 /* There is another notation name without data for the
428 previous one. The crypto backend misbehaves. */
429 return gpg_error (GPG_ERR_INV_ENGINE);
431 err = _gpgme_sig_notation_create (¬ation, NULL, 0, NULL, 0, 0);
435 if (code == GPGME_STATUS_NOTATION_NAME)
437 err = _gpgme_decode_percent_string (args, ¬ation->name, 0, 0);
440 _gpgme_sig_notation_free (notation);
444 notation->name_len = strlen (notation->name);
446 /* FIXME: For now we fake the human-readable flag. The
447 critical flag can not be reported as it is not
449 notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
450 notation->human_readable = 1;
454 /* This is a policy URL. */
456 err = _gpgme_decode_percent_string (args, ¬ation->value, 0, 0);
459 _gpgme_sig_notation_free (notation);
463 notation->value_len = strlen (notation->value);
467 else if (code == GPGME_STATUS_NOTATION_DATA)
469 int len = strlen (args) + 1;
472 /* FIXME: We could keep a pointer to the last notation in the list. */
473 while (notation && notation->next)
475 lastp = ¬ation->next;
476 notation = notation->next;
479 if (!notation || !notation->name)
480 /* There is notation data without a previous notation
481 name. The crypto backend misbehaves. */
482 return gpg_error (GPG_ERR_INV_ENGINE);
484 if (!notation->value)
486 dest = notation->value = malloc (len);
488 return gpg_error_from_errno (errno);
492 int cur_len = strlen (notation->value);
493 dest = realloc (notation->value, len + strlen (notation->value));
495 return gpg_error_from_errno (errno);
496 notation->value = dest;
500 err = _gpgme_decode_percent_string (args, &dest, len, 0);
504 notation->value_len += strlen (dest);
507 return gpg_error (GPG_ERR_INV_ENGINE);
513 parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
515 char *end = strchr (args, ' ');
522 case GPGME_STATUS_TRUST_UNDEFINED:
524 sig->validity = GPGME_VALIDITY_UNKNOWN;
527 case GPGME_STATUS_TRUST_NEVER:
528 sig->validity = GPGME_VALIDITY_NEVER;
531 case GPGME_STATUS_TRUST_MARGINAL:
532 sig->validity = GPGME_VALIDITY_MARGINAL;
535 case GPGME_STATUS_TRUST_FULLY:
536 case GPGME_STATUS_TRUST_ULTIMATE:
537 sig->validity = GPGME_VALIDITY_FULL;
542 sig->validity_reason = _gpgme_map_gnupg_error (args);
544 sig->validity_reason = 0;
551 parse_error (gpgme_signature_t sig, char *args)
554 char *where = strchr (args, ' ');
562 where = strchr (which, ' ');
569 return gpg_error (GPG_ERR_INV_ENGINE);
571 err = _gpgme_map_gnupg_error (which);
573 if (!strcmp (where, "verify.findkey"))
575 else if (!strcmp (where, "verify.keyusage")
576 && gpg_err_code (err) == GPG_ERR_WRONG_KEY_USAGE)
577 sig->wrong_key_usage = 1;
584 _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
586 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
590 gpgme_signature_t sig;
592 err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
597 sig = opd->current_sig;
601 case GPGME_STATUS_NEWSIG:
603 calc_sig_summary (sig);
604 err = prepare_new_sig (opd);
605 opd->only_newsig_seen = 1;
608 case GPGME_STATUS_GOODSIG:
609 case GPGME_STATUS_EXPSIG:
610 case GPGME_STATUS_EXPKEYSIG:
611 case GPGME_STATUS_BADSIG:
612 case GPGME_STATUS_ERRSIG:
613 case GPGME_STATUS_REVKEYSIG:
614 if (sig && !opd->did_prepare_new_sig)
615 calc_sig_summary (sig);
616 opd->only_newsig_seen = 0;
617 return parse_new_sig (opd, code, args);
619 case GPGME_STATUS_VALIDSIG:
620 opd->only_newsig_seen = 0;
621 return sig ? parse_valid_sig (sig, args)
622 : gpg_error (GPG_ERR_INV_ENGINE);
624 case GPGME_STATUS_NODATA:
625 opd->only_newsig_seen = 0;
627 return gpg_error (GPG_ERR_NO_DATA);
628 sig->status = gpg_error (GPG_ERR_NO_DATA);
631 case GPGME_STATUS_UNEXPECTED:
632 opd->only_newsig_seen = 0;
634 return gpg_error (GPG_ERR_GENERAL);
635 sig->status = gpg_error (GPG_ERR_NO_DATA);
638 case GPGME_STATUS_NOTATION_NAME:
639 case GPGME_STATUS_NOTATION_DATA:
640 case GPGME_STATUS_POLICY_URL:
641 opd->only_newsig_seen = 0;
642 return sig ? parse_notation (sig, code, args)
643 : gpg_error (GPG_ERR_INV_ENGINE);
645 case GPGME_STATUS_TRUST_UNDEFINED:
646 case GPGME_STATUS_TRUST_NEVER:
647 case GPGME_STATUS_TRUST_MARGINAL:
648 case GPGME_STATUS_TRUST_FULLY:
649 case GPGME_STATUS_TRUST_ULTIMATE:
650 opd->only_newsig_seen = 0;
651 return sig ? parse_trust (sig, code, args)
652 : gpg_error (GPG_ERR_INV_ENGINE);
654 case GPGME_STATUS_PKA_TRUST_BAD:
655 case GPGME_STATUS_PKA_TRUST_GOOD:
656 opd->only_newsig_seen = 0;
657 if (sig && !sig->pka_trust)
658 sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
659 /* FIXME: We should set the mailbox which is the argument to
660 these status codes into a new field. */
663 case GPGME_STATUS_ERROR:
664 opd->only_newsig_seen = 0;
665 /* The error status is informational, so we don't return an
666 error code if we are not ready to process this status. */
667 return sig ? parse_error (sig, args) : 0;
669 case GPGME_STATUS_EOF:
670 if (sig && !opd->did_prepare_new_sig)
671 calc_sig_summary (sig);
672 if (opd->only_newsig_seen && sig)
674 gpgme_signature_t sig2;
675 /* The last signature has no valid information - remove it
678 if (sig == opd->result.signatures)
679 opd->result.signatures = NULL;
682 for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
683 if (sig2->next == sig)
689 /* Note that there is no need to release the members of SIG
690 because we won't be here if they have been set. */
692 opd->current_sig = NULL;
694 opd->only_newsig_seen = 0;
697 case GPGME_STATUS_PLAINTEXT:
698 err = _gpgme_parse_plaintext (args, &opd->result.file_name);
710 verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
714 err = _gpgme_progress_status_handler (priv, code, args);
716 err = _gpgme_verify_status_handler (priv, code, args);
722 _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
727 return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
728 sizeof (*opd), release_op_data);
733 verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
734 gpgme_data_t signed_text, gpgme_data_t plaintext)
738 err = _gpgme_op_reset (ctx, synchronous);
742 err = _gpgme_op_verify_init_result (ctx);
746 _gpgme_engine_set_status_handler (ctx->engine, verify_status_handler, ctx);
749 return gpg_error (GPG_ERR_NO_DATA);
750 if (!signed_text && !plaintext)
751 return gpg_error (GPG_ERR_INV_VALUE);
753 return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
757 /* Decrypt ciphertext CIPHER and make a signature verification within
758 CTX and store the resulting plaintext in PLAIN. */
760 gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
761 gpgme_data_t signed_text, gpgme_data_t plaintext)
763 return verify_start (ctx, 0, sig, signed_text, plaintext);
767 /* Decrypt ciphertext CIPHER and make a signature verification within
768 CTX and store the resulting plaintext in PLAIN. */
770 gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
771 gpgme_data_t plaintext)
775 err = verify_start (ctx, 1, sig, signed_text, plaintext);
777 err = _gpgme_wait_one (ctx);
782 /* Compatibility interfaces. */
784 /* Get the key used to create signature IDX in CTX and return it in
787 gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
789 gpgme_verify_result_t result;
790 gpgme_signature_t sig;
792 result = gpgme_op_verify_result (ctx);
793 sig = result->signatures;
801 return gpg_error (GPG_ERR_EOF);
803 return gpgme_get_key (ctx, sig->fpr, r_key, 0);
807 /* Retrieve the signature status of signature IDX in CTX after a
808 successful verify operation in R_STAT (if non-null). The creation
809 time stamp of the signature is returned in R_CREATED (if non-null).
810 The function returns a string containing the fingerprint. */
811 const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
812 _gpgme_sig_stat_t *r_stat, time_t *r_created)
814 gpgme_verify_result_t result;
815 gpgme_signature_t sig;
817 result = gpgme_op_verify_result (ctx);
818 sig = result->signatures;
830 switch (gpg_err_code (sig->status))
832 case GPG_ERR_NO_ERROR:
833 *r_stat = GPGME_SIG_STAT_GOOD;
836 case GPG_ERR_BAD_SIGNATURE:
837 *r_stat = GPGME_SIG_STAT_BAD;
840 case GPG_ERR_NO_PUBKEY:
841 *r_stat = GPGME_SIG_STAT_NOKEY;
844 case GPG_ERR_NO_DATA:
845 *r_stat = GPGME_SIG_STAT_NOSIG;
848 case GPG_ERR_SIG_EXPIRED:
849 *r_stat = GPGME_SIG_STAT_GOOD_EXP;
852 case GPG_ERR_KEY_EXPIRED:
853 *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
857 *r_stat = GPGME_SIG_STAT_ERROR;
862 *r_created = sig->timestamp;
867 /* Retrieve certain attributes of a signature. IDX is the index
868 number of the signature after a successful verify operation. WHAT
869 is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
870 one. WHATIDX is to be passed as 0 for most attributes . */
871 unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
872 _gpgme_attr_t what, int whatidx)
874 gpgme_verify_result_t result;
875 gpgme_signature_t sig;
877 result = gpgme_op_verify_result (ctx);
878 sig = result->signatures;
890 case GPGME_ATTR_CREATED:
891 return sig->timestamp;
893 case GPGME_ATTR_EXPIRE:
894 return sig->exp_timestamp;
896 case GPGME_ATTR_VALIDITY:
897 return (unsigned long) sig->validity;
899 case GPGME_ATTR_SIG_STATUS:
900 switch (gpg_err_code (sig->status))
902 case GPG_ERR_NO_ERROR:
903 return GPGME_SIG_STAT_GOOD;
905 case GPG_ERR_BAD_SIGNATURE:
906 return GPGME_SIG_STAT_BAD;
908 case GPG_ERR_NO_PUBKEY:
909 return GPGME_SIG_STAT_NOKEY;
911 case GPG_ERR_NO_DATA:
912 return GPGME_SIG_STAT_NOSIG;
914 case GPG_ERR_SIG_EXPIRED:
915 return GPGME_SIG_STAT_GOOD_EXP;
917 case GPG_ERR_KEY_EXPIRED:
918 return GPGME_SIG_STAT_GOOD_EXPKEY;
921 return GPGME_SIG_STAT_ERROR;
924 case GPGME_ATTR_SIG_SUMMARY:
934 const char *gpgme_get_sig_string_attr (gpgme_ctx_t ctx, int idx,
935 _gpgme_attr_t what, int whatidx)
937 gpgme_verify_result_t result;
938 gpgme_signature_t sig;
940 result = gpgme_op_verify_result (ctx);
941 sig = result->signatures;
956 case GPGME_ATTR_ERRTOK:
958 return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";