1 /* encrypt.c - Encrypt function.
2 Copyright (C) 2000 Werner Koch (dd9jn)
3 Copyright (C) 2001, 2002, 2003, 2004 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
37 struct _gpgme_op_encrypt_result result;
39 /* The error code from a FAILURE status line or 0. */
40 gpg_error_t failure_code;
42 /* The fingerprint from the last KEY_CONSIDERED status line. */
45 /* The flags from the last KEY_CONSIDERED status line. */
46 unsigned int kc_flags;
48 /* A pointer to the next pointer of the last invalid recipient in
49 the list. This makes appending new invalid recipients painless
50 while preserving the order. */
51 gpgme_invalid_key_t *lastp;
56 release_op_data (void *hook)
58 op_data_t opd = (op_data_t) hook;
59 gpgme_invalid_key_t invalid_recipient = opd->result.invalid_recipients;
61 while (invalid_recipient)
63 gpgme_invalid_key_t next = invalid_recipient->next;
64 if (invalid_recipient->fpr)
65 free (invalid_recipient->fpr);
66 free (invalid_recipient);
67 invalid_recipient = next;
74 gpgme_encrypt_result_t
75 gpgme_op_encrypt_result (gpgme_ctx_t ctx)
81 TRACE_BEG (DEBUG_CTX, "gpgme_op_encrypt_result", ctx);
83 err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, -1, NULL);
88 TRACE_SUC0 ("result=(null)");
92 if (_gpgme_debug_trace ())
94 gpgme_invalid_key_t invkeys = opd->result.invalid_recipients;
99 TRACE_LOG3 ("invalid_recipients[%i] = %s (%s)",
100 i, invkeys->fpr ? invkeys->fpr : "(null)",
101 gpg_strerror (invkeys->reason));
102 invkeys = invkeys->next;
107 TRACE_SUC1 ("result=%p", &opd->result);
113 _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
116 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
121 err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, -1, NULL);
128 case GPGME_STATUS_FAILURE:
129 opd->failure_code = _gpgme_parse_failure (args);
132 case GPGME_STATUS_EOF:
133 if (opd->result.invalid_recipients)
134 return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
135 if (opd->failure_code)
136 return opd->failure_code;
139 case GPGME_STATUS_KEY_CONSIDERED:
140 /* This is emitted during gpg's key lookup to give information
141 * about the lookup results. We store the last one so it can be
142 * used in connection with INV_RECP. */
145 err = _gpgme_parse_key_considered (args, &opd->kc_fpr, &opd->kc_flags);
150 case GPGME_STATUS_INV_RECP:
151 err = _gpgme_parse_inv_recp (args, 0, opd->kc_fpr, opd->kc_flags,
156 opd->lastp = &(*opd->lastp)->next;
161 case GPGME_STATUS_NO_RECP:
162 /* Should not happen, because we require at least one recipient. */
163 return gpg_error (GPG_ERR_GENERAL);
173 encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
177 err = _gpgme_progress_status_handler (priv, code, args);
179 err = _gpgme_passphrase_status_handler (priv, code, args);
185 encrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
189 err = _gpgme_progress_status_handler (priv, code, args);
191 err = _gpgme_encrypt_status_handler (priv, code, args);
198 _gpgme_op_encrypt_init_result (gpgme_ctx_t ctx)
204 err = _gpgme_op_data_lookup (ctx, OPDATA_ENCRYPT, &hook, sizeof (*opd),
210 opd->lastp = &opd->result.invalid_recipients;
216 encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
217 const char *recpstring,
218 gpgme_encrypt_flags_t flags,
219 gpgme_data_t plain, gpgme_data_t cipher)
224 err = _gpgme_op_reset (ctx, synchronous);
228 err = _gpgme_op_encrypt_init_result (ctx);
232 symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC);
235 return gpg_error (GPG_ERR_NO_DATA);
237 return gpg_error (GPG_ERR_INV_VALUE);
239 return gpg_error (GPG_ERR_INV_VALUE);
241 if (symmetric && ctx->passphrase_cb)
243 /* Symmetric encryption requires a passphrase. */
244 err = _gpgme_engine_set_command_handler
245 (ctx->engine, _gpgme_passphrase_command_handler, ctx);
250 _gpgme_engine_set_status_handler (ctx->engine,
252 ? encrypt_sym_status_handler
253 : encrypt_status_handler,
256 return _gpgme_engine_op_encrypt (ctx->engine, recp, recpstring,
257 flags, plain, cipher, ctx->use_armor);
261 /* Old version of gpgme_op_encrypt_ext without RECPSTRING. */
263 gpgme_op_encrypt (gpgme_ctx_t ctx, gpgme_key_t recp[],
264 gpgme_encrypt_flags_t flags,
265 gpgme_data_t plain, gpgme_data_t cipher)
267 return gpgme_op_encrypt_ext (ctx, recp, NULL, flags, plain, cipher);
271 /* Old version of gpgme_op_encrypt_ext_start without RECPSTRING. */
273 gpgme_op_encrypt_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
274 gpgme_encrypt_flags_t flags,
275 gpgme_data_t plain, gpgme_data_t cipher)
277 return gpgme_op_encrypt_ext_start (ctx, recp, NULL, flags, plain, cipher);
281 /* Encrypt plaintext PLAIN within CTX for the recipients RECP and
282 * store the resulting ciphertext in CIPHER. RECPSTRING can be used
283 * instead of the RECP array to directly specify recipients as LF
284 * delimited strings; these may be any kind of recipient specification
285 * patterns as supported by the backend. */
287 gpgme_op_encrypt_ext (gpgme_ctx_t ctx, gpgme_key_t recp[],
288 const char *recpstring,
289 gpgme_encrypt_flags_t flags,
290 gpgme_data_t plain, gpgme_data_t cipher)
294 TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt", ctx,
295 "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
298 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
300 if (_gpgme_debug_trace () && (recp || recpstring))
308 TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
309 (recp[i]->subkeys && recp[i]->subkeys->fpr) ?
310 recp[i]->subkeys->fpr : "invalid");
316 TRACE_LOG1 ("recipients = '%s'", recpstring);
320 err = encrypt_start (ctx, 1, recp, recpstring, flags, plain, cipher);
322 err = _gpgme_wait_one (ctx);
323 return TRACE_ERR (err);
328 gpgme_op_encrypt_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
329 const char *recpstring,
330 gpgme_encrypt_flags_t flags,
331 gpgme_data_t plain, gpgme_data_t cipher)
335 TRACE_BEG3 (DEBUG_CTX, "gpgme_op_encrypt_start", ctx,
336 "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
339 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
341 if (_gpgme_debug_trace () && (recp || recpstring))
349 TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i],
350 (recp[i]->subkeys && recp[i]->subkeys->fpr) ?
351 recp[i]->subkeys->fpr : "invalid");
357 TRACE_LOG1 ("recipients = '%s'", recpstring);
361 err = encrypt_start (ctx, 0, recp, recpstring, flags, plain, cipher);
362 return TRACE_ERR (err);