2002-01-22 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / decrypt.c
1 /* decrypt.c -  decrypt functions
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *      Copyright (C) 2001 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
7  * GPGME is free software; you can redistribute it and/or modify
8  * it 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.
11  *
12  * GPGME is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include "util.h"
29 #include "context.h"
30 #include "ops.h"
31
32 struct decrypt_result_s
33 {
34   int okay;
35   int failed;
36 };
37
38 void
39 _gpgme_release_decrypt_result (DecryptResult result)
40 {
41   if (!result)
42     return;
43   xfree (result);
44 }
45
46 static GpgmeError
47 create_result_struct (GpgmeCtx ctx)
48 {
49   assert (!ctx->result.decrypt);
50   ctx->result.decrypt = xtrycalloc (1, sizeof *ctx->result.decrypt);
51   if (!ctx->result.decrypt)
52     return mk_error (Out_Of_Core);
53   return 0;    
54 }
55
56 void
57 _gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
58 {
59   _gpgme_passphrase_status_handler (ctx, code, args);
60
61   if (ctx->out_of_core)
62     return;
63
64   if (! ctx->result.decrypt)
65     {
66       if (create_result_struct (ctx))
67         {
68           ctx->out_of_core = 1;
69           return;
70         }
71     }
72
73   switch (code)
74     {
75     case STATUS_EOF:
76       break;
77
78     case STATUS_DECRYPTION_OKAY:
79       ctx->result.decrypt->okay = 1;
80       break;
81
82     case STATUS_DECRYPTION_FAILED:
83       ctx->result.decrypt->failed = 1;
84       break;
85         
86     default:
87       /* Ignore all other codes.  */
88       break;
89     }
90 }
91
92 GpgmeError
93 _gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
94                       void *status_handler)
95 {
96   GpgmeError err = 0;
97
98   fail_on_pending_request (ctx);
99   ctx->pending = 1;
100
101   _gpgme_release_result (ctx);
102   ctx->out_of_core = 0;
103
104   /* Create a process object.  */
105   _gpgme_engine_release (ctx->engine);
106   err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
107                            : GPGME_PROTOCOL_OpenPGP, &ctx->engine);
108   if (err)
109     goto leave;
110
111   /* Check the supplied data.  */
112   if (!ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE)
113     {
114       err = mk_error (No_Data);
115       goto leave;
116     }
117   _gpgme_data_set_mode (ciph, GPGME_DATA_MODE_OUT);
118
119   if (gpgme_data_get_type (plain) != GPGME_DATA_TYPE_NONE)
120     {
121       err = mk_error (Invalid_Value);
122       goto leave;
123     }
124   _gpgme_data_set_mode (plain, GPGME_DATA_MODE_IN);
125
126   err = _gpgme_passphrase_start (ctx);
127   if (err)
128     goto leave;
129
130   _gpgme_engine_set_status_handler (ctx->engine, status_handler, ctx);
131   _gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity);
132
133   err = _gpgme_engine_op_decrypt (ctx->engine, ciph, plain);
134
135   if (!err)     /* And kick off the process.  */
136     err = _gpgme_engine_start (ctx->engine, ctx);
137
138  leave:
139   if (err)
140     {
141       ctx->pending = 0; 
142       _gpgme_engine_release (ctx->engine);
143       ctx->engine = NULL;
144     }
145   return err;
146 }
147
148 GpgmeError
149 gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
150 {
151   return _gpgme_decrypt_start (ctx, ciph, plain,
152                                _gpgme_decrypt_status_handler);
153 }
154
155 GpgmeError
156 _gpgme_decrypt_result (GpgmeCtx ctx)
157 {
158   GpgmeError err = 0;
159
160   if (!ctx->result.decrypt)
161     err = mk_error (General_Error);
162   else if (ctx->out_of_core)
163     err = mk_error (Out_Of_Core);
164   else
165     {
166       err = _gpgme_passphrase_result (ctx);
167       if (! err)
168         {
169           if (ctx->result.decrypt->failed)
170             err = mk_error (Decryption_Failed);
171           else if (!ctx->result.decrypt->okay)
172             err = mk_error (No_Data);
173         }
174     }
175   return err;
176 }
177
178 /**
179  * gpgme_op_decrypt:
180  * @ctx: The context
181  * @in: ciphertext input
182  * @out: plaintext output
183  * 
184  * This function decrypts @in to @out.
185  * Other parameters are take from the context @ctx.
186  * The function does wait for the result.
187  * 
188  * Return value:  0 on success or an errorcode. 
189  **/
190 GpgmeError
191 gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out)
192 {
193   GpgmeError err = gpgme_op_decrypt_start (ctx, in, out);
194   if (!err)
195     {
196       gpgme_wait (ctx, 1);
197       err = _gpgme_decrypt_result (ctx);
198     }
199   return err;
200 }