1 /* decrypt.c - Decrypt 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
39 struct _gpgme_op_decrypt_result result;
44 /* A pointer to the next pointer of the last recipient in the list.
45 This makes appending new invalid signers painless while
46 preserving the order. */
47 gpgme_recipient_t *last_recipient_p;
52 release_op_data (void *hook)
54 op_data_t opd = (op_data_t) hook;
55 gpgme_recipient_t recipient = opd->result.recipients;
57 if (opd->result.unsupported_algorithm)
58 free (opd->result.unsupported_algorithm);
60 if (opd->result.file_name)
61 free (opd->result.file_name);
65 gpgme_recipient_t next = recipient->next;
72 gpgme_decrypt_result_t
73 gpgme_op_decrypt_result (gpgme_ctx_t ctx)
79 TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);
81 err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
85 TRACE_SUC0 ("result=(null)");
89 if (_gpgme_debug_trace ())
91 gpgme_recipient_t rcp;
93 if (opd->result.unsupported_algorithm)
95 TRACE_LOG1 ("result: unsupported_algorithm: %s",
96 opd->result.unsupported_algorithm);
98 if (opd->result.wrong_key_usage)
100 TRACE_LOG ("result: wrong key usage");
102 rcp = opd->result.recipients;
105 TRACE_LOG3 ("result: recipient: keyid=%s, pubkey_algo=%i, "
106 "status=%s", rcp->keyid, rcp->pubkey_algo,
107 gpg_strerror (rcp->status));
110 if (opd->result.file_name)
112 TRACE_LOG1 ("result: original file name: %s", opd->result.file_name);
116 TRACE_SUC1 ("result=%p", &opd->result);
122 parse_enc_to (char *args, gpgme_recipient_t *recp)
124 gpgme_recipient_t rec;
128 rec = malloc (sizeof (*rec));
130 return gpg_error_from_syserror ();
133 rec->keyid = rec->_keyid;
136 for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
138 if (args[i] == '\0' || args[i] == ' ')
141 rec->_keyid[i] = args[i];
143 rec->_keyid[i] = '\0';
146 if (*args != '\0' && *args != ' ')
149 return gpg_error (GPG_ERR_INV_ENGINE);
157 gpg_err_set_errno (0);
158 rec->pubkey_algo = strtol (args, &tail, 0);
159 if (errno || args == tail || *tail != ' ')
161 /* The crypto backend does not behave. */
163 return gpg_error (GPG_ERR_INV_ENGINE);
167 /* FIXME: The key length is always 0 right now, so no need to parse
176 _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
179 gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
184 err = _gpgme_passphrase_status_handler (priv, code, args);
188 err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
195 case GPGME_STATUS_EOF:
196 /* FIXME: These error values should probably be attributed to
197 the underlying crypto engine (as error source). */
199 return gpg_error (GPG_ERR_DECRYPT_FAILED);
201 return gpg_error (GPG_ERR_NO_DATA);
204 case GPGME_STATUS_DECRYPTION_INFO:
205 /* Fixme: Provide a way to return the used symmetric algorithm. */
208 case GPGME_STATUS_DECRYPTION_OKAY:
212 case GPGME_STATUS_DECRYPTION_FAILED:
216 case GPGME_STATUS_ERROR:
217 /* Note that this is an informational status code which should
218 not lead to an error return unless it is something not
219 related to the backend. */
221 const char d_alg[] = "decrypt.algorithm";
222 const char k_alg[] = "decrypt.keyusage";
224 if (!strncmp (args, d_alg, sizeof (d_alg) - 1))
226 args += sizeof (d_alg) - 1;
230 if (gpg_err_code (atoi (args)) == GPG_ERR_UNSUPPORTED_ALGORITHM)
234 while (*args && *args != ' ')
239 end = strchr (args, ' ');
243 if (!(*args == '?' && *(args + 1) == '\0'))
245 opd->result.unsupported_algorithm = strdup (args);
246 if (!opd->result.unsupported_algorithm)
247 return gpg_error_from_syserror ();
251 else if (!strncmp (args, k_alg, sizeof (k_alg) - 1))
253 args += sizeof (k_alg) - 1;
257 if (gpg_err_code (atoi (args)) == GPG_ERR_WRONG_KEY_USAGE)
258 opd->result.wrong_key_usage = 1;
263 case GPGME_STATUS_ENC_TO:
264 err = parse_enc_to (args, opd->last_recipient_p);
268 opd->last_recipient_p = &(*opd->last_recipient_p)->next;
271 case GPGME_STATUS_NO_SECKEY:
273 gpgme_recipient_t rec = opd->result.recipients;
277 if (!strcmp (rec->keyid, args))
279 rec->status = gpg_error (GPG_ERR_NO_SECKEY);
284 /* FIXME: Is this ok? */
286 return gpg_error (GPG_ERR_INV_ENGINE);
290 case GPGME_STATUS_PLAINTEXT:
291 err = _gpgme_parse_plaintext (args, &opd->result.file_name);
304 decrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
308 err = _gpgme_progress_status_handler (priv, code, args);
310 err = _gpgme_decrypt_status_handler (priv, code, args);
316 _gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
322 err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
323 sizeof (*opd), release_op_data);
328 opd->last_recipient_p = &opd->result.recipients;
334 decrypt_start (gpgme_ctx_t ctx, int synchronous,
335 gpgme_data_t cipher, gpgme_data_t plain)
339 err = _gpgme_op_reset (ctx, synchronous);
343 err = _gpgme_op_decrypt_init_result (ctx);
348 return gpg_error (GPG_ERR_NO_DATA);
350 return gpg_error (GPG_ERR_INV_VALUE);
355 if (ctx->passphrase_cb)
357 err = _gpgme_engine_set_command_handler
358 (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
363 _gpgme_engine_set_status_handler (ctx->engine, decrypt_status_handler, ctx);
365 return _gpgme_engine_op_decrypt (ctx->engine, cipher, plain);
370 gpgme_op_decrypt_start (gpgme_ctx_t ctx, gpgme_data_t cipher,
375 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt_start", ctx,
376 "cipher=%p, plain=%p", cipher, plain);
379 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
381 err = decrypt_start (ctx, 0, cipher, plain);
382 return TRACE_ERR (err);
386 /* Decrypt ciphertext CIPHER within CTX and store the resulting
387 plaintext in PLAIN. */
389 gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
393 TRACE_BEG2 (DEBUG_CTX, "gpgme_op_decrypt", ctx,
394 "cipher=%p, plain=%p", cipher, plain);
397 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
399 err = decrypt_start (ctx, 1, cipher, plain);
401 err = _gpgme_wait_one (ctx);
402 return TRACE_ERR (err);