1 /* sign.c - Signing function.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004, 2007 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
29 /* Suppress warning for accessing deprecated member "class". */
30 #define _GPGME_IN_GPGME 1
40 struct _gpgme_op_sign_result result;
42 /* A pointer to the next pointer of the last invalid signer in
43 the list. This makes appending new invalid signers painless
44 while preserving the order. */
45 gpgme_invalid_key_t *last_signer_p;
47 /* Likewise for signature information. */
48 gpgme_new_signature_t *last_sig_p;
50 /* Flags used while processing the status lines. */
51 unsigned int ignore_inv_recp:1;
52 unsigned int inv_sgnr_seen:1;
53 unsigned int sig_created_seen:1;
58 release_op_data (void *hook)
60 op_data_t opd = (op_data_t) hook;
61 gpgme_invalid_key_t invalid_signer = opd->result.invalid_signers;
62 gpgme_new_signature_t sig = opd->result.signatures;
64 while (invalid_signer)
66 gpgme_invalid_key_t next = invalid_signer->next;
67 if (invalid_signer->fpr)
68 free (invalid_signer->fpr);
69 free (invalid_signer);
70 invalid_signer = next;
75 gpgme_new_signature_t next = sig->next;
84 gpgme_op_sign_result (gpgme_ctx_t ctx)
90 TRACE_BEG (DEBUG_CTX, "gpgme_op_sign_result", ctx);
92 err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
96 TRACE_SUC0 ("result=(null)");
100 if (_gpgme_debug_trace ())
102 gpgme_invalid_key_t inv_key = opd->result.invalid_signers;
103 gpgme_new_signature_t sig = opd->result.signatures;
110 inv_key = inv_key->next;
118 TRACE_LOG2 ("result: invalid signers: %i, signatures: %i",
119 inv_signers, signatures);
120 inv_key = opd->result.invalid_signers;
123 TRACE_LOG3 ("result: invalid signer: fpr=%s, reason=%s <%s>",
124 inv_key->fpr, gpgme_strerror (inv_key->reason),
125 gpgme_strsource (inv_key->reason));
126 inv_key = inv_key->next;
128 sig = opd->result.signatures;
131 TRACE_LOG6 ("result: signature: type=%i, pubkey_algo=%i, "
132 "hash_algo=%i, timestamp=%li, fpr=%s, sig_class=%i",
133 sig->type, sig->pubkey_algo, sig->hash_algo,
134 sig->timestamp, sig->fpr, sig->sig_class);
139 TRACE_SUC1 ("result=%p", &opd->result);
145 parse_sig_created (char *args, gpgme_new_signature_t *sigp)
147 gpgme_new_signature_t sig;
150 sig = malloc (sizeof (*sig));
152 return gpg_error_from_syserror ();
158 sig->type = GPGME_SIG_MODE_NORMAL;
162 sig->type = GPGME_SIG_MODE_DETACH;
166 sig->type = GPGME_SIG_MODE_CLEAR;
170 /* The backend engine is not behaving. */
172 return gpg_error (GPG_ERR_INV_ENGINE);
179 return gpg_error (GPG_ERR_INV_ENGINE);
182 gpg_err_set_errno (0);
183 sig->pubkey_algo = strtol (args, &tail, 0);
184 if (errno || args == tail || *tail != ' ')
186 /* The crypto backend does not behave. */
188 return gpg_error (GPG_ERR_INV_ENGINE);
192 sig->hash_algo = strtol (args, &tail, 0);
193 if (errno || args == tail || *tail != ' ')
195 /* The crypto backend does not behave. */
197 return gpg_error (GPG_ERR_INV_ENGINE);
201 sig->sig_class = strtol (args, &tail, 0);
202 sig->class = sig->sig_class;
203 sig->_obsolete_class = sig->sig_class;
204 if (errno || args == tail || *tail != ' ')
206 /* The crypto backend does not behave. */
208 return gpg_error (GPG_ERR_INV_ENGINE);
212 sig->timestamp = _gpgme_parse_timestamp (args, &tail);
213 if (sig->timestamp == -1 || args == tail || *tail != ' ')
215 /* The crypto backend does not behave. */
217 return gpg_error (GPG_ERR_INV_ENGINE);
225 /* The crypto backend does not behave. */
227 return gpg_error (GPG_ERR_INV_ENGINE);
230 tail = strchr (args, ' ');
234 sig->fpr = strdup (args);
237 int saved_errno = errno;
239 return gpg_error_from_errno (saved_errno);
247 _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
249 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
254 err = _gpgme_passphrase_status_handler (priv, code, args);
258 err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
265 case GPGME_STATUS_SIG_CREATED:
266 opd->sig_created_seen = 1;
267 err = parse_sig_created (args, opd->last_sig_p);
271 opd->last_sig_p = &(*opd->last_sig_p)->next;
274 case GPGME_STATUS_INV_RECP:
275 if (opd->inv_sgnr_seen && opd->ignore_inv_recp)
278 case GPGME_STATUS_INV_SGNR:
279 if (code == GPGME_STATUS_INV_SGNR)
280 opd->inv_sgnr_seen = 1;
281 err = _gpgme_parse_inv_recp (args, opd->last_signer_p);
285 opd->last_signer_p = &(*opd->last_signer_p)->next;
288 case GPGME_STATUS_EOF:
289 /* The UI server does not send information about the created
290 signature. This is irrelevant for this protocol and thus we
291 should not check for that. */
292 if (opd->result.invalid_signers)
293 err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
294 else if (!opd->sig_created_seen
295 && ctx->protocol != GPGME_PROTOCOL_UISERVER)
296 err = gpg_error (GPG_ERR_GENERAL);
307 sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
311 err = _gpgme_progress_status_handler (priv, code, args);
313 err = _gpgme_sign_status_handler (priv, code, args);
319 sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
325 err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook,
326 sizeof (*opd), release_op_data);
330 opd->last_signer_p = &opd->result.invalid_signers;
331 opd->last_sig_p = &opd->result.signatures;
332 opd->ignore_inv_recp = !!ignore_inv_recp;
333 opd->inv_sgnr_seen = 0;
334 opd->sig_created_seen = 0;
339 _gpgme_op_sign_init_result (gpgme_ctx_t ctx)
341 return sign_init_result (ctx, 0);
346 sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
347 gpgme_data_t sig, gpgme_sig_mode_t mode)
351 err = _gpgme_op_reset (ctx, synchronous);
355 /* If we are using the CMS protocol, we ignore the INV_RECP status
356 code if a newer GPGSM is in use. GPGMS does not support combined
357 sign+encrypt and thus this can't harm. */
358 err = sign_init_result (ctx, (ctx->protocol == GPGME_PROTOCOL_CMS));
362 if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
363 && mode != GPGME_SIG_MODE_CLEAR)
364 return gpg_error (GPG_ERR_INV_VALUE);
367 return gpg_error (GPG_ERR_NO_DATA);
369 return gpg_error (GPG_ERR_INV_VALUE);
371 if (ctx->passphrase_cb)
373 err = _gpgme_engine_set_command_handler
374 (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
379 _gpgme_engine_set_status_handler (ctx->engine, sign_status_handler,
382 return _gpgme_engine_op_sign (ctx->engine, plain, sig, mode, ctx->use_armor,
383 ctx->use_textmode, ctx->include_certs,
388 /* Sign the plaintext PLAIN and store the signature in SIG. */
390 gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
391 gpgme_sig_mode_t mode)
394 TRACE_BEG3 (DEBUG_CTX, "gpgme_op_sign_start", ctx,
395 "plain=%p, sig=%p, mode=%i", plain, sig, mode);
398 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
400 err = sign_start (ctx, 0, plain, sig, mode);
401 return TRACE_ERR (err);
405 /* Sign the plaintext PLAIN and store the signature in SIG. */
407 gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
408 gpgme_sig_mode_t mode)
412 TRACE_BEG3 (DEBUG_CTX, "gpgme_op_sign", ctx,
413 "plain=%p, sig=%p, mode=%i", plain, sig, mode);
416 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
418 err = sign_start (ctx, 1, plain, sig, mode);
420 err = _gpgme_wait_one (ctx);
421 return TRACE_ERR (err);