1 /* encrypt-sign.c -  encrypt and verify functions
2  * Copyright (C) 2000 Werner Koch (dd9jn)
3  * Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
4  *
5  * This file is part of GPGME.
6  *
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.
11  *
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.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this program; if not, see <https://gnu.org/licenses/>.
19  * SPDX-License-Identifier: LGPL-2.1-or-later
20  */
21 
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 
29 #include "gpgme.h"
30 #include "debug.h"
31 #include "context.h"
32 #include "ops.h"
33 
34 
35 static gpgme_error_t
encrypt_sign_status_handler(void * priv,gpgme_status_code_t code,char * args)36 encrypt_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
37 {
38   gpgme_error_t err;
39 
40   err = _gpgme_progress_status_handler (priv, code, args);
41   if (!err)
42     err = _gpgme_encrypt_status_handler (priv, code, args);
43   if (!err)
44     err = _gpgme_sign_status_handler (priv, code, args);
45   return err;
46 }
47 
48 
49 static gpgme_error_t
encrypt_sym_status_handler(void * priv,gpgme_status_code_t code,char * args)50 encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
51 {
52   gpgme_error_t err;
53 
54   err = _gpgme_progress_status_handler (priv, code, args);
55   if (!err)
56     err = _gpgme_sign_status_handler (priv, code, args);
57   if (!err)
58     err = _gpgme_passphrase_status_handler (priv, code, args);
59   return err;
60 }
61 
62 
63 static gpgme_error_t
encrypt_sign_start(gpgme_ctx_t ctx,int synchronous,gpgme_key_t recp[],const char * recpstring,gpgme_encrypt_flags_t flags,gpgme_data_t plain,gpgme_data_t cipher)64 encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
65                     const char *recpstring,
66 		    gpgme_encrypt_flags_t flags,
67 		    gpgme_data_t plain, gpgme_data_t cipher)
68 {
69   gpgme_error_t err;
70   int symmetric;
71 
72   err = _gpgme_op_reset (ctx, synchronous);
73   if (err)
74     return err;
75 
76   symmetric = (!recp && !recpstring) || (flags & GPGME_ENCRYPT_SYMMETRIC);
77 
78   if (!plain)
79     return gpg_error (GPG_ERR_NO_DATA);
80   if (!cipher)
81     return gpg_error (GPG_ERR_INV_VALUE);
82   if (recp && !*recp)
83     return gpg_error (GPG_ERR_INV_VALUE);
84 
85   err = _gpgme_op_encrypt_init_result (ctx);
86   if (err)
87     return err;
88 
89   err = _gpgme_op_sign_init_result (ctx);
90   if (err)
91     return err;
92 
93   if (ctx->passphrase_cb)
94     {
95       err = _gpgme_engine_set_command_handler
96 	(ctx->engine, _gpgme_passphrase_command_handler, ctx);
97       if (err)
98 	return err;
99     }
100 
101   _gpgme_engine_set_status_handler (ctx->engine,
102                                     symmetric
103                                     ? encrypt_sym_status_handler
104                                     : encrypt_sign_status_handler,
105 				    ctx);
106 
107   return _gpgme_engine_op_encrypt_sign (ctx->engine, recp, recpstring,
108                                         flags, plain,
109 					cipher, ctx->use_armor,
110 					ctx /* FIXME */);
111 }
112 
113 
114 /* Old version of gpgme_op_encrypt_sign_ext_start w/o RECPSTRING.  */
115 gpgme_error_t
gpgme_op_encrypt_sign_start(gpgme_ctx_t ctx,gpgme_key_t recp[],gpgme_encrypt_flags_t flags,gpgme_data_t plain,gpgme_data_t cipher)116 gpgme_op_encrypt_sign_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
117 			     gpgme_encrypt_flags_t flags,
118 			     gpgme_data_t plain, gpgme_data_t cipher)
119 {
120   return gpgme_op_encrypt_sign_ext_start (ctx, recp, NULL,
121                                           flags, plain, cipher);
122 }
123 
124 
125 /* Old version of gpgme_op_encrypt_sign_ext w/o RECPSTRING.  */
126 gpgme_error_t
gpgme_op_encrypt_sign(gpgme_ctx_t ctx,gpgme_key_t recp[],gpgme_encrypt_flags_t flags,gpgme_data_t plain,gpgme_data_t cipher)127 gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
128 		       gpgme_encrypt_flags_t flags,
129 		       gpgme_data_t plain, gpgme_data_t cipher)
130 {
131   return gpgme_op_encrypt_sign_ext (ctx, recp, NULL, flags, plain, cipher);
132 }
133 
134 
135 /* Encrypt plaintext PLAIN within CTX for the recipients RECP and
136  * store the resulting ciphertext in CIPHER.  Also sign the ciphertext
137  * with the signers in CTX.  */
138 gpgme_error_t
gpgme_op_encrypt_sign_ext(gpgme_ctx_t ctx,gpgme_key_t recp[],const char * recpstring,gpgme_encrypt_flags_t flags,gpgme_data_t plain,gpgme_data_t cipher)139 gpgme_op_encrypt_sign_ext (gpgme_ctx_t ctx, gpgme_key_t recp[],
140                            const char *recpstring,
141                            gpgme_encrypt_flags_t flags,
142                            gpgme_data_t plain, gpgme_data_t cipher)
143 {
144   gpgme_error_t err;
145 
146   TRACE_BEG  (DEBUG_CTX, "gpgme_op_encrypt_sign", ctx,
147 	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
148 
149   if (!ctx)
150     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
151 
152   if (_gpgme_debug_trace () && (recp || recpstring))
153     {
154       if (recp)
155         {
156           int i = 0;
157 
158           while (recp[i])
159             {
160               TRACE_LOG  ("recipient[%i] = %p (%s)", i, recp[i],
161                           (recp[i]->subkeys && recp[i]->subkeys->fpr) ?
162                           recp[i]->subkeys->fpr : "invalid");
163               i++;
164             }
165         }
166       else
167         {
168           TRACE_LOG  ("recipients = '%s'", recpstring);
169         }
170     }
171 
172   err = encrypt_sign_start (ctx, 1, recp, recpstring, flags, plain, cipher);
173   if (!err)
174     err = _gpgme_wait_one (ctx);
175   return TRACE_ERR (err);
176 }
177 
178 
179 /* Encrypt plaintext PLAIN within CTX for the recipients RECP and
180    store the resulting ciphertext in CIPHER.  Also sign the ciphertext
181    with the signers in CTX.  */
182 gpgme_error_t
gpgme_op_encrypt_sign_ext_start(gpgme_ctx_t ctx,gpgme_key_t recp[],const char * recpstring,gpgme_encrypt_flags_t flags,gpgme_data_t plain,gpgme_data_t cipher)183 gpgme_op_encrypt_sign_ext_start (gpgme_ctx_t ctx, gpgme_key_t recp[],
184                                  const char *recpstring,
185                                  gpgme_encrypt_flags_t flags,
186                                  gpgme_data_t plain, gpgme_data_t cipher)
187 {
188   gpgme_error_t err;
189 
190   TRACE_BEG  (DEBUG_CTX, "gpgme_op_encrypt_sign_start", ctx,
191 	      "flags=0x%x, plain=%p, cipher=%p", flags, plain, cipher);
192 
193   if (!ctx)
194     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
195 
196   if (_gpgme_debug_trace () && (recp || recpstring))
197     {
198       if (recp)
199         {
200           int i = 0;
201 
202           while (recp[i])
203             {
204               TRACE_LOG  ("recipient[%i] = %p (%s)", i, recp[i],
205                           (recp[i]->subkeys && recp[i]->subkeys->fpr) ?
206                           recp[i]->subkeys->fpr : "invalid");
207               i++;
208             }
209         }
210       else
211         {
212           TRACE_LOG  ("recipients = '%s'", recpstring);
213         }
214     }
215 
216   err = encrypt_sign_start (ctx, 0, recp, recpstring, flags, plain, cipher);
217   return err;
218 }
219