1 /* sign.c - Signing function.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003 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 General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (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 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GPGME; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
35 struct _gpgme_op_sign_result result;
37 /* A pointer to the next pointer of the last invalid signer in
38 the list. This makes appending new invalid signers painless
39 while preserving the order. */
40 gpgme_invalid_key_t *last_signer_p;
42 /* Likewise for signature information. */
43 gpgme_new_signature_t *last_sig_p;
48 release_op_data (void *hook)
50 op_data_t opd = (op_data_t) hook;
51 gpgme_invalid_key_t invalid_signer = opd->result.invalid_signers;
52 gpgme_new_signature_t sig = opd->result.signatures;
54 while (invalid_signer)
56 gpgme_invalid_key_t next = invalid_signer->next;
57 if (invalid_signer->fpr)
58 free (invalid_signer->fpr);
59 free (invalid_signer);
60 invalid_signer = next;
65 gpgme_new_signature_t next = sig->next;
74 gpgme_op_sign_result (gpgme_ctx_t ctx)
80 err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
90 parse_sig_created (char *args, gpgme_new_signature_t *sigp)
92 gpgme_new_signature_t sig;
95 sig = malloc (sizeof (*sig));
97 return gpg_error_from_errno (errno);
103 sig->type = GPGME_SIG_MODE_NORMAL;
107 sig->type = GPGME_SIG_MODE_DETACH;
111 sig->type = GPGME_SIG_MODE_CLEAR;
115 /* The backend engine is not behaving. */
117 return gpg_error (GPG_ERR_INV_ENGINE);
124 return gpg_error (GPG_ERR_INV_ENGINE);
128 sig->pubkey_algo = strtol (args, &tail, 0);
129 if (errno || args == tail || *tail != ' ')
131 /* The crypto backend does not behave. */
133 return gpg_error (GPG_ERR_INV_ENGINE);
137 sig->hash_algo = strtol (args, &tail, 0);
138 if (errno || args == tail || *tail != ' ')
140 /* The crypto backend does not behave. */
142 return gpg_error (GPG_ERR_INV_ENGINE);
146 sig->class = strtol (args, &tail, 0);
147 sig->_obsolete_class = sig->class;
148 if (errno || args == tail || *tail != ' ')
150 /* The crypto backend does not behave. */
152 return gpg_error (GPG_ERR_INV_ENGINE);
156 sig->timestamp = strtol (args, &tail, 0);
157 if (errno || args == tail || *tail != ' ')
159 /* The crypto backend does not behave. */
161 return gpg_error (GPG_ERR_INV_ENGINE);
169 /* The crypto backend does not behave. */
171 return gpg_error (GPG_ERR_INV_ENGINE);
174 tail = strchr (args, ' ');
178 sig->fpr = strdup (args);
181 int saved_errno = errno;
183 return gpg_error_from_errno (saved_errno);
191 _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
193 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
198 err = _gpgme_passphrase_status_handler (priv, code, args);
202 err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook, -1, NULL);
209 case GPGME_STATUS_SIG_CREATED:
210 err = parse_sig_created (args, opd->last_sig_p);
214 opd->last_sig_p = &(*opd->last_sig_p)->next;
217 case GPGME_STATUS_INV_RECP:
218 err = _gpgme_parse_inv_recp (args, opd->last_signer_p);
222 opd->last_signer_p = &(*opd->last_signer_p)->next;
225 case GPGME_STATUS_EOF:
226 if (opd->result.invalid_signers)
227 return gpg_error (GPG_ERR_UNUSABLE_SECKEY);
238 sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
242 err = _gpgme_progress_status_handler (priv, code, args);
244 err = _gpgme_sign_status_handler (priv, code, args);
250 _gpgme_op_sign_init_result (gpgme_ctx_t ctx)
256 err = _gpgme_op_data_lookup (ctx, OPDATA_SIGN, &hook,
257 sizeof (*opd), release_op_data);
261 opd->last_signer_p = &opd->result.invalid_signers;
262 opd->last_sig_p = &opd->result.signatures;
268 sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
269 gpgme_data_t sig, gpgme_sig_mode_t mode)
273 err = _gpgme_op_reset (ctx, synchronous);
277 err = _gpgme_op_sign_init_result (ctx);
281 if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
282 && mode != GPGME_SIG_MODE_CLEAR)
283 return gpg_error (GPG_ERR_INV_VALUE);
286 return gpg_error (GPG_ERR_NO_DATA);
288 return gpg_error (GPG_ERR_INV_VALUE);
290 if (ctx->passphrase_cb)
292 err = _gpgme_engine_set_command_handler
293 (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
298 _gpgme_engine_set_status_handler (ctx->engine, sign_status_handler,
301 return _gpgme_engine_op_sign (ctx->engine, plain, sig, mode, ctx->use_armor,
302 ctx->use_textmode, ctx->include_certs,
307 /* Sign the plaintext PLAIN and store the signature in SIG. */
309 gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
310 gpgme_sig_mode_t mode)
312 return sign_start (ctx, 0, plain, sig, mode);
316 /* Sign the plaintext PLAIN and store the signature in SIG. */
318 gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
319 gpgme_sig_mode_t mode)
321 gpgme_error_t err = sign_start (ctx, 1, plain, sig, mode);
323 err = _gpgme_wait_one (ctx);