NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
gpgme.c File Reference

Autocrypt GPGME handler. More...

#include "config.h"
#include <stddef.h>
#include <gpgme.h>
#include <stdbool.h>
#include "private.h"
#include "mutt/lib.h"
#include "address/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "ncrypt/lib.h"
#include "question/lib.h"
#include "globals.h"
+ Include dependency graph for gpgme.c:

Go to the source code of this file.

Functions

static int create_gpgme_context (gpgme_ctx_t *ctx)
 Create a GPGME context.
 
int mutt_autocrypt_gpgme_init (void)
 Initialise GPGME.
 
static int export_keydata (gpgme_ctx_t ctx, gpgme_key_t key, struct Buffer *keydata)
 Export Key data from GPGME into a Buffer.
 
int mutt_autocrypt_gpgme_create_key (struct Address *addr, struct Buffer *keyid, struct Buffer *keydata)
 Create a GPGME key.
 
int mutt_autocrypt_gpgme_select_key (struct Buffer *keyid, struct Buffer *keydata)
 Select a Autocrypt key.
 
int mutt_autocrypt_gpgme_select_or_create_key (struct Address *addr, struct Buffer *keyid, struct Buffer *keydata)
 Ask the user to select or create an Autocrypt key.
 
int mutt_autocrypt_gpgme_import_key (const char *keydata, struct Buffer *keyid)
 Read a key from GPGME.
 
bool mutt_autocrypt_gpgme_is_valid_key (const char *keyid)
 Is a key id valid?
 

Detailed Description

Autocrypt GPGME handler.

Authors
  • Kevin J. McCarthy
  • Richard Russon
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file gpgme.c.

Function Documentation

◆ create_gpgme_context()

static int create_gpgme_context ( gpgme_ctx_t *  ctx)
static

Create a GPGME context.

Parameters
ctxGPGME context to initialise
Return values
0Success
-1Error

Definition at line 50 of file gpgme.c.

51{
52 const char *const c_autocrypt_dir = cs_subset_path(NeoMutt->sub, "autocrypt_dir");
53 gpgme_error_t err = gpgme_new(ctx);
54 if (!err)
55 err = gpgme_ctx_set_engine_info(*ctx, GPGME_PROTOCOL_OpenPGP, NULL, c_autocrypt_dir);
56 if (err)
57 {
58 mutt_error(_("error creating GPGME context: %s"), gpgme_strerror(err));
59 return -1;
60 }
61
62 return 0;
63}
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
#define mutt_error(...)
Definition: logging2.h:92
#define _(a)
Definition: message.h:28
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_autocrypt_gpgme_init()

int mutt_autocrypt_gpgme_init ( void  )

Initialise GPGME.

Return values
0Always

Definition at line 69 of file gpgme.c.

70{
72 return 0;
73}
void pgp_gpgme_init(void)
Initialise the crypto module - Implements CryptModuleSpecs::init() -.
Definition: crypt_gpgme.c:3820
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ export_keydata()

static int export_keydata ( gpgme_ctx_t  ctx,
gpgme_key_t  key,
struct Buffer keydata 
)
static

Export Key data from GPGME into a Buffer.

Parameters
ctxGPGME context
keyGPGME key
keydataBuffer for results
Return values
0Success
-1Error

Definition at line 83 of file gpgme.c.

84{
85 int rc = -1;
86 gpgme_data_t dh = NULL;
87 gpgme_key_t export_keys[2] = { 0 };
88 size_t export_data_len;
89
90 if (gpgme_data_new(&dh))
91 goto cleanup;
92
93 /* This doesn't seem to work */
94#if 0
95 if (gpgme_data_set_encoding (dh, GPGME_DATA_ENCODING_BASE64))
96 goto cleanup;
97#endif
98
99 export_keys[0] = key;
100 export_keys[1] = NULL;
101 if (gpgme_op_export_keys(ctx, export_keys, GPGME_EXPORT_MODE_MINIMAL, dh))
102 goto cleanup;
103
104 char *export_data = gpgme_data_release_and_get_mem(dh, &export_data_len);
105 dh = NULL;
106
107 mutt_b64_buffer_encode(keydata, export_data, export_data_len);
108 gpgme_free(export_data);
109 export_data = NULL;
110
111 rc = 0;
112
113cleanup:
114 gpgme_data_release(dh);
115 return rc;
116}
size_t mutt_b64_buffer_encode(struct Buffer *buf, const char *in, size_t len)
Convert raw bytes to null-terminated base64 string.
Definition: base64.c:198
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_autocrypt_gpgme_create_key()

int mutt_autocrypt_gpgme_create_key ( struct Address addr,
struct Buffer keyid,
struct Buffer keydata 
)

Create a GPGME key.

Parameters
addrEmail Address
keyidKey id
keydataKey data
Return values
0Success
-1Error

Definition at line 157 of file gpgme.c.

159{
160 int rc = -1;
161 gpgme_ctx_t ctx = NULL;
162 gpgme_genkey_result_t keyresult = NULL;
163 gpgme_key_t primary_key = NULL;
164 struct Buffer *buf = buf_pool_get();
165
166 /* GPGME says addresses should not be in idna form */
167 struct Address *copy = mutt_addr_copy(addr);
168 mutt_addr_to_local(copy);
169 mutt_addr_write(buf, copy, false);
170 mutt_addr_free(&copy);
171
172 if (create_gpgme_context(&ctx))
173 goto cleanup;
174
175 /* L10N: Message displayed just before a GPG key is generated for a created
176 autocrypt account. */
177 mutt_message(_("Generating autocrypt key..."));
178
179 /* Primary key */
180 gpgme_error_t err = gpgme_op_createkey(ctx, buf_string(buf), "ed25519", 0, 0, NULL,
181 GPGME_CREATE_NOPASSWD | GPGME_CREATE_FORCE |
182 GPGME_CREATE_NOEXPIRE);
183 if (err)
184 {
185 /* L10N: GPGME was unable to generate a key for some reason.
186 %s is the error message returned by GPGME. */
187 mutt_error(_("Error creating autocrypt key: %s"), gpgme_strerror(err));
188 goto cleanup;
189 }
190 keyresult = gpgme_op_genkey_result(ctx);
191 if (!keyresult->fpr)
192 goto cleanup;
193 buf_strcpy(keyid, keyresult->fpr);
194 mutt_debug(LL_DEBUG1, "Generated key with id %s\n", buf_string(keyid));
195
196 /* Get gpgme_key_t to create the secondary key and export keydata */
197 err = gpgme_get_key(ctx, buf_string(keyid), &primary_key, 0);
198 if (err)
199 goto cleanup;
200
201 /* Secondary key */
202 err = gpgme_op_createsubkey(ctx, primary_key, "cv25519", 0, 0,
203 GPGME_CREATE_NOPASSWD | GPGME_CREATE_NOEXPIRE);
204 if (err)
205 {
206 mutt_error(_("Error creating autocrypt key: %s"), gpgme_strerror(err));
207 goto cleanup;
208 }
209
210 /* get keydata */
211 if (export_keydata(ctx, primary_key, keydata))
212 goto cleanup;
213 mutt_debug(LL_DEBUG1, "key has keydata *%s*\n", buf_string(keydata));
214
215 rc = 0;
216
217cleanup:
218 gpgme_key_unref(primary_key);
219 gpgme_release(ctx);
220 buf_pool_release(&buf);
221 return rc;
222}
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition: address.c:462
size_t mutt_addr_write(struct Buffer *buf, struct Address *addr, bool display)
Write a single Address to a buffer.
Definition: address.c:1050
struct Address * mutt_addr_copy(const struct Address *addr)
Copy the real address.
Definition: address.c:745
bool mutt_addr_to_local(struct Address *a)
Convert an Address from Punycode.
Definition: address.c:1340
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:394
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
static int create_gpgme_context(gpgme_ctx_t *ctx)
Create a GPGME context.
Definition: gpgme.c:50
static int export_keydata(gpgme_ctx_t ctx, gpgme_key_t key, struct Buffer *keydata)
Export Key data from GPGME into a Buffer.
Definition: gpgme.c:83
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
An email address.
Definition: address.h:36
String manipulation buffer.
Definition: buffer.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_autocrypt_gpgme_select_key()

int mutt_autocrypt_gpgme_select_key ( struct Buffer keyid,
struct Buffer keydata 
)

Select a Autocrypt key.

Parameters
[in]keyidKey id to select
[out]keydataBuffer for resulting Key data
Return values
0Success
-1Error

Definition at line 231 of file gpgme.c.

232{
233 int rc = -1;
234 gpgme_ctx_t ctx = NULL;
235 gpgme_key_t key = NULL;
236
237 OptAutocryptGpgme = true;
239 goto cleanup;
240
241 if (create_gpgme_context(&ctx))
242 goto cleanup;
243
244 if (gpgme_get_key(ctx, buf_string(keyid), &key, 0))
245 goto cleanup;
246
247 if (key->revoked || key->expired || key->disabled || key->invalid ||
248 !key->can_encrypt || !key->can_sign)
249 {
250 /* L10N: After selecting a key for an autocrypt account,
251 this is displayed if the key was revoked/expired/disabled/invalid
252 or can't be used for both signing and encryption.
253 %s is the key fingerprint. */
254 mutt_error(_("The key %s is not usable for autocrypt"), buf_string(keyid));
255 goto cleanup;
256 }
257
258 if (export_keydata(ctx, key, keydata))
259 goto cleanup;
260
261 rc = 0;
262
263cleanup:
264 OptAutocryptGpgme = false;
265 gpgme_key_unref(key);
266 gpgme_release(ctx);
267 return rc;
268}
int mutt_gpgme_select_secret_key(struct Buffer *keyid)
Select a private Autocrypt key for a new account.
Definition: crypt_gpgme.c:3639
bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: globals.c:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_autocrypt_gpgme_select_or_create_key()

int mutt_autocrypt_gpgme_select_or_create_key ( struct Address addr,
struct Buffer keyid,
struct Buffer keydata 
)

Ask the user to select or create an Autocrypt key.

Parameters
addrEmail Address
keyidKey id
keydataKey data
Return values
0Success
-1Error

Definition at line 278 of file gpgme.c.

280{
281 int rc = -1;
282
283 /* L10N: During autocrypt account creation, this prompt asks the
284 user whether they want to create a new GPG key for the account,
285 or select an existing account from the keyring. */
286 const char *prompt = _("(c)reate new, or (s)elect existing GPG key?");
287 /* L10N: The letters corresponding to the
288 "(c)reate new, or (s)elect existing GPG key?" prompt. */
289 const char *letters = _("cs");
290
291 int choice = mw_multi_choice(prompt, letters);
292 switch (choice)
293 {
294 case 2: /* select existing */
295 rc = mutt_autocrypt_gpgme_select_key(keyid, keydata);
296 if (rc == 0)
297 break;
298
299 /* L10N: During autocrypt account creation, if selecting an existing key fails
300 for some reason, we prompt to see if they want to create a key instead. */
301 if (query_yesorno(_("Create a new GPG key for this account, instead?"), MUTT_YES) != MUTT_YES)
302 break;
304
305 case 1: /* create new */
306 rc = mutt_autocrypt_gpgme_create_key(addr, keyid, keydata);
307 }
308
309 return rc;
310}
int mutt_autocrypt_gpgme_create_key(struct Address *addr, struct Buffer *keyid, struct Buffer *keydata)
Create a GPGME key.
Definition: gpgme.c:157
int mutt_autocrypt_gpgme_select_key(struct Buffer *keyid, struct Buffer *keydata)
Select a Autocrypt key.
Definition: gpgme.c:231
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition: question.c:64
#define FALLTHROUGH
Definition: lib.h:111
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:327
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_autocrypt_gpgme_import_key()

int mutt_autocrypt_gpgme_import_key ( const char *  keydata,
struct Buffer keyid 
)

Read a key from GPGME.

Parameters
keydataBuffer for key data
keyidBuffer for key id
Return values
0Success
-1Error

Definition at line 319 of file gpgme.c.

320{
321 int rc = -1;
322 gpgme_ctx_t ctx = NULL;
323 gpgme_data_t dh = NULL;
324 struct Buffer *raw_keydata = NULL;
325
326 if (create_gpgme_context(&ctx))
327 goto cleanup;
328
329 raw_keydata = buf_pool_get();
330 if (!mutt_b64_buffer_decode(raw_keydata, keydata))
331 goto cleanup;
332
333 if (gpgme_data_new_from_mem(&dh, buf_string(raw_keydata), buf_len(raw_keydata), 0))
334 {
335 goto cleanup;
336 }
337
338 if (gpgme_op_import(ctx, dh))
339 goto cleanup;
340
341 gpgme_import_result_t result = gpgme_op_import_result(ctx);
342 if (!result->imports || !result->imports->fpr)
343 goto cleanup;
344 buf_strcpy(keyid, result->imports->fpr);
345
346 rc = 0;
347
348cleanup:
349 gpgme_data_release(dh);
350 gpgme_release(ctx);
351 buf_pool_release(&raw_keydata);
352 return rc;
353}
int mutt_b64_buffer_decode(struct Buffer *buf, const char *in)
Convert null-terminated base64 string to raw bytes.
Definition: base64.c:216
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_autocrypt_gpgme_is_valid_key()

bool mutt_autocrypt_gpgme_is_valid_key ( const char *  keyid)

Is a key id valid?

Parameters
keyidKey id to check
Return values
trueKey id is valid

Definition at line 360 of file gpgme.c.

361{
362 bool rc = false;
363 gpgme_ctx_t ctx = NULL;
364 gpgme_key_t key = NULL;
365
366 if (!keyid)
367 return false;
368
369 if (create_gpgme_context(&ctx))
370 goto cleanup;
371
372 if (gpgme_get_key(ctx, keyid, &key, 0))
373 goto cleanup;
374
375 rc = true;
376 if (key->revoked || key->expired || key->disabled || key->invalid || !key->can_encrypt)
377 rc = false;
378
379cleanup:
380 gpgme_key_unref(key);
381 gpgme_release(ctx);
382 return rc;
383}
+ Here is the call graph for this function:
+ Here is the caller graph for this function: