2372a06ab63e2d7255da5cfd7cd829ce95c23246
[gpgme.git] / src / gpgme.c
1 /* gpgme.c - GnuPG Made Easy.
2    Copyright (C) 2000 Werner Koch (dd9jn)
3    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 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, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA.  */
21
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
30 #include <locale.h>
31
32 #include "util.h"
33 #include "context.h"
34 #include "ops.h"
35 #include "wait.h"
36 #include "debug.h"
37 #include "priv-io.h"
38
39 \f
40 /* The default locale.  */
41 DEFINE_STATIC_LOCK (def_lc_lock);
42 static char *def_lc_ctype;
43 static char *def_lc_messages;
44
45 \f
46 gpgme_error_t _gpgme_selftest = GPG_ERR_NOT_OPERATIONAL;
47
48 \f
49 /* Create a new context as an environment for GPGME crypto
50    operations.  */
51 gpgme_error_t
52 gpgme_new (gpgme_ctx_t *r_ctx)
53 {
54   gpgme_ctx_t ctx;
55   TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx);
56
57   if (_gpgme_selftest)
58     return TRACE_ERR (gpgme_error (_gpgme_selftest));
59
60   ctx = calloc (1, sizeof *ctx);
61   if (!ctx)
62     return TRACE_ERR (gpg_error_from_errno (errno));
63
64   INIT_LOCK (ctx->lock);
65   
66   _gpgme_engine_info_copy (&ctx->engine_info);
67   if (!ctx->engine_info)
68     {
69       free (ctx);
70       return TRACE_ERR (gpg_error_from_errno (errno));
71     }
72
73   ctx->keylist_mode = GPGME_KEYLIST_MODE_LOCAL;
74   ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
75   ctx->protocol = GPGME_PROTOCOL_OpenPGP;
76   _gpgme_fd_table_init (&ctx->fdt);
77
78   LOCK (def_lc_lock);
79   if (def_lc_ctype)
80     {
81       ctx->lc_ctype = strdup (def_lc_ctype);
82       if (!ctx->lc_ctype)
83         {
84           UNLOCK (def_lc_lock);
85           _gpgme_engine_info_release (ctx->engine_info);
86           free (ctx);
87           return TRACE_ERR (gpg_error_from_errno (errno));
88         }
89     }
90   else
91     def_lc_ctype = NULL;
92
93   if (def_lc_messages)
94     {
95       ctx->lc_messages = strdup (def_lc_messages);
96       if (!ctx->lc_messages)
97         {
98           UNLOCK (def_lc_lock);
99           if (ctx->lc_ctype)
100             free (ctx->lc_ctype);
101           _gpgme_engine_info_release (ctx->engine_info);
102           free (ctx);
103           return TRACE_ERR (gpg_error_from_errno (errno));
104         }
105     }
106   else
107     def_lc_messages = NULL;
108   UNLOCK (def_lc_lock);
109
110   *r_ctx = ctx;
111
112   return TRACE_SUC1 ("ctx=%p", ctx);
113 }
114
115
116 gpgme_error_t
117 _gpgme_cancel_with_err (gpgme_ctx_t ctx, gpg_error_t ctx_err)
118 {
119   gpgme_error_t err;
120   TRACE_BEG1 (DEBUG_CTX, "_gpgme_cancel_with_err", ctx, "ctx_err=%i",
121               ctx_err);
122
123   err = _gpgme_engine_cancel (ctx->engine);
124   if (err)
125     return TRACE_ERR (err);
126
127   _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_DONE, &ctx_err);
128
129   return TRACE_ERR (0);
130 }
131
132
133 /* Cancel a pending asynchronous operation.  */
134 gpgme_error_t
135 gpgme_cancel (gpgme_ctx_t ctx)
136 {
137   return _gpgme_cancel_with_err (ctx, gpg_error (GPG_ERR_CANCELED));
138 }
139
140
141 /* Cancel a pending operation asynchronously.  */
142 gpgme_error_t
143 gpgme_cancel_async (gpgme_ctx_t ctx)
144 {
145   TRACE_BEG (DEBUG_CTX, "gpgme_cancel_async", ctx);
146
147   LOCK (ctx->lock);
148   ctx->canceled = 1;
149   UNLOCK (ctx->lock);
150
151   return TRACE_ERR (0);
152 }
153
154
155 /* Release all resources associated with the given context.  */
156 void
157 gpgme_release (gpgme_ctx_t ctx)
158 {
159   TRACE (DEBUG_CTX, "gpgme_release", ctx);
160
161   _gpgme_engine_release (ctx->engine);
162   _gpgme_fd_table_deinit (&ctx->fdt);
163   _gpgme_release_result (ctx);
164   gpgme_signers_clear (ctx);
165   gpgme_sig_notation_clear (ctx);
166   if (ctx->signers)
167     free (ctx->signers);
168   if (ctx->lc_ctype)
169     free (ctx->lc_ctype);
170   if (ctx->lc_messages)
171     free (ctx->lc_messages);
172   _gpgme_engine_info_release (ctx->engine_info);
173   DESTROY_LOCK (ctx->lock);
174   free (ctx);
175 }
176
177
178 void
179 gpgme_result_ref (void *result)
180 {
181   struct ctx_op_data *data = result - sizeof (struct ctx_op_data);
182
183   if (! result)
184     return;
185
186   data->references++;
187 }
188
189
190 void
191 gpgme_result_unref (void *result)
192 {
193   struct ctx_op_data *data = result - sizeof (struct ctx_op_data);
194
195   if (! result)
196     return;
197
198   if (--data->references == 0)
199     {
200       if (data->cleanup)
201         (*data->cleanup) (data->hook);
202       free (data);
203     }
204 }
205
206
207 void
208 _gpgme_release_result (gpgme_ctx_t ctx)
209 {
210   struct ctx_op_data *data = ctx->op_data;
211
212   while (data)
213     {
214       struct ctx_op_data *next_data = data->next;
215       data->next = NULL;
216       gpgme_result_unref (data->hook);
217       data = next_data;
218     }
219   ctx->op_data = NULL;
220 }
221
222
223 gpgme_error_t
224 gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
225 {
226   TRACE_BEG2 (DEBUG_CTX, "gpgme_set_protocol", ctx, "protocol=%i (%s)",
227               protocol, gpgme_get_protocol_name (protocol)
228               ? gpgme_get_protocol_name (protocol) : "unknown");
229
230   if (protocol != GPGME_PROTOCOL_OpenPGP
231       && protocol != GPGME_PROTOCOL_CMS
232       && protocol != GPGME_PROTOCOL_ASSUAN)
233     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
234
235   if (ctx->protocol != protocol)
236     {
237       /* Shut down the engine when switching protocols.  */
238       if (ctx->engine)
239         {
240           TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine);
241           _gpgme_engine_release (ctx->engine);
242           ctx->engine = NULL;
243         }
244
245       ctx->protocol = protocol;
246     }
247   return TRACE_ERR (0);
248 }
249
250
251 gpgme_protocol_t
252 gpgme_get_protocol (gpgme_ctx_t ctx)
253 {
254   TRACE2 (DEBUG_CTX, "gpgme_get_protocol", ctx,
255           "ctx->protocol=%i (%s)", ctx->protocol,
256           gpgme_get_protocol_name (ctx->protocol)
257           ? gpgme_get_protocol_name (ctx->protocol) : "unknown");
258   return ctx->protocol;
259 }
260
261
262 const char *
263 gpgme_get_protocol_name (gpgme_protocol_t protocol)
264 {
265   switch (protocol)
266     {
267     case GPGME_PROTOCOL_OpenPGP:
268       return "OpenPGP";
269
270     case GPGME_PROTOCOL_CMS:
271       return "CMS";
272
273     case GPGME_PROTOCOL_ASSUAN:
274       return "Assuan";
275
276     case GPGME_PROTOCOL_UNKNOWN:
277       return "unknown";
278
279     default:
280       return NULL;
281     }
282 }
283
284 /* Enable or disable the use of an ascii armor for all output.  */
285 void
286 gpgme_set_armor (gpgme_ctx_t ctx, int use_armor)
287 {
288   TRACE2 (DEBUG_CTX, "gpgme_set_armor", ctx, "use_armor=%i (%s)",
289           use_armor, use_armor ? "yes" : "no");
290   ctx->use_armor = use_armor;
291 }
292
293
294 /* Return the state of the armor flag.  */
295 int
296 gpgme_get_armor (gpgme_ctx_t ctx)
297 {
298   TRACE2 (DEBUG_CTX, "gpgme_get_armor", ctx, "ctx->use_armor=%i (%s)",
299           ctx->use_armor, ctx->use_armor ? "yes" : "no");
300   return ctx->use_armor;
301 }
302
303
304 /* Enable or disable the use of the special textmode.  Textmode is for
305   example used for the RFC2015 signatures; note that the updated RFC
306   3156 mandates that the MUA does some preparations so that textmode
307   is not needed anymore.  */
308 void
309 gpgme_set_textmode (gpgme_ctx_t ctx, int use_textmode)
310 {
311   TRACE2 (DEBUG_CTX, "gpgme_set_textmode", ctx, "use_textmode=%i (%s)",
312           use_textmode, use_textmode ? "yes" : "no");
313   ctx->use_textmode = use_textmode;
314 }
315
316 /* Return the state of the textmode flag.  */
317 int
318 gpgme_get_textmode (gpgme_ctx_t ctx)
319 {
320   TRACE2 (DEBUG_CTX, "gpgme_get_textmode", ctx, "ctx->use_textmode=%i (%s)",
321           ctx->use_textmode, ctx->use_textmode ? "yes" : "no");
322   return ctx->use_textmode;
323 }
324
325
326 /* Set the number of certifications to include in an S/MIME message.
327    The default is GPGME_INCLUDE_CERTS_DEFAULT.  -1 means all certs,
328    and -2 means all certs except the root cert.  */
329 void
330 gpgme_set_include_certs (gpgme_ctx_t ctx, int nr_of_certs)
331 {
332   if (nr_of_certs == GPGME_INCLUDE_CERTS_DEFAULT)
333     ctx->include_certs = GPGME_INCLUDE_CERTS_DEFAULT;
334   else if (nr_of_certs < -2)
335     ctx->include_certs = -2;
336   else
337     ctx->include_certs = nr_of_certs;
338
339   TRACE2 (DEBUG_CTX, "gpgme_set_include_certs", ctx, "nr_of_certs=%i%s",
340           nr_of_certs, nr_of_certs == ctx->include_certs ? "" : " (-2)");
341 }
342
343
344 /* Get the number of certifications to include in an S/MIME
345    message.  */
346 int
347 gpgme_get_include_certs (gpgme_ctx_t ctx)
348 {
349   TRACE1 (DEBUG_CTX, "gpgme_get_include_certs", ctx, "ctx->include_certs=%i",
350           ctx->include_certs);
351   return ctx->include_certs;
352 }
353
354
355 /* This function changes the default behaviour of the keylisting
356    functions.  MODE is a bitwise-OR of the GPGME_KEYLIST_* flags.  The
357    default mode is GPGME_KEYLIST_MODE_LOCAL.  */
358 gpgme_error_t
359 gpgme_set_keylist_mode (gpgme_ctx_t ctx, gpgme_keylist_mode_t mode)
360 {
361   TRACE1 (DEBUG_CTX, "gpgme_set_keylist_mode", ctx, "keylist_mode=0x%x",
362           mode);
363
364   ctx->keylist_mode = mode;
365   return 0;
366 }
367
368 /* This function returns the default behaviour of the keylisting
369    functions.  */
370 gpgme_keylist_mode_t
371 gpgme_get_keylist_mode (gpgme_ctx_t ctx)
372 {
373   TRACE1 (DEBUG_CTX, "gpgme_get_keylist_mode", ctx,
374           "ctx->keylist_mode=0x%x", ctx->keylist_mode);
375   return ctx->keylist_mode;
376 }
377
378
379 /* This function sets a callback function to be used to pass a
380    passphrase to gpg.  */
381 void
382 gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb,
383                          void *cb_value)
384 {
385   TRACE2 (DEBUG_CTX, "gpgme_set_passphrase_cb", ctx,
386           "passphrase_cb=%p/%p", cb, cb_value);
387   ctx->passphrase_cb = cb;
388   ctx->passphrase_cb_value = cb_value;
389 }
390
391
392 /* This function returns the callback function to be used to pass a
393    passphrase to the crypto engine.  */
394 void
395 gpgme_get_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t *r_cb,
396                          void **r_cb_value)
397 {
398   TRACE2 (DEBUG_CTX, "gpgme_get_passphrase_cb", ctx,
399           "ctx->passphrase_cb=%p/%p",
400           ctx->passphrase_cb, ctx->passphrase_cb_value);
401   if (r_cb)
402     *r_cb = ctx->passphrase_cb;
403   if (r_cb_value)
404     *r_cb_value = ctx->passphrase_cb_value;
405 }
406
407
408 /* This function sets a callback function to be used as a progress
409    indicator.  */
410 void
411 gpgme_set_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t cb, void *cb_value)
412 {
413   TRACE2 (DEBUG_CTX, "gpgme_set_progress_cb", ctx, "progress_cb=%p/%p",
414           cb, cb_value);
415   ctx->progress_cb = cb;
416   ctx->progress_cb_value = cb_value;
417 }
418
419
420 /* This function returns the callback function to be used as a
421    progress indicator.  */
422 void
423 gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *r_cb,
424                        void **r_cb_value)
425 {
426   TRACE2 (DEBUG_CTX, "gpgme_get_progress_cb", ctx, "ctx->progress_cb=%p/%p",
427           ctx->progress_cb, ctx->progress_cb_value);
428   if (r_cb)
429     *r_cb = ctx->progress_cb;
430   if (r_cb_value)
431     *r_cb_value = ctx->progress_cb_value;
432 }
433
434
435 /* Set the I/O callback functions for CTX to IO_CBS.  */
436 void
437 gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
438 {
439   if (io_cbs)
440     {
441       TRACE6 (DEBUG_CTX, "gpgme_set_io_cbs", ctx,
442               "io_cbs=%p (add=%p/%p, remove=%p, event=%p/%p",
443               io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove,
444               io_cbs->event, io_cbs->event_priv);
445       ctx->io_cbs = *io_cbs;
446     }
447   else
448     {
449       TRACE1 (DEBUG_CTX, "gpgme_set_io_cbs", ctx,
450               "io_cbs=%p (default)", io_cbs);
451       ctx->io_cbs.add = NULL;
452       ctx->io_cbs.add_priv = NULL;
453       ctx->io_cbs.remove = NULL;
454       ctx->io_cbs.event = NULL;
455       ctx->io_cbs.event_priv = NULL;
456     }
457 }
458
459
460 /* This function provides access to the internal read function; it is
461    normally not used.  */
462 ssize_t
463 gpgme_io_read (int fd, void *buffer, size_t count)
464 {
465   int ret;
466
467   ret = _gpgme_io_read (fd, buffer, count);
468
469   return ret;
470 }
471
472
473 /* This function provides access to the internal write function.  It
474    is to be used by user callbacks to return data to gpgme.  See
475    gpgme_passphrase_cb_t and gpgme_edit_cb_t.  */
476 ssize_t
477 gpgme_io_write (int fd, const void *buffer, size_t count)
478 {
479   int ret;
480
481   ret = _gpgme_io_write (fd, buffer, count);
482
483   return ret;
484 }
485
486
487 /* This function returns the callback function for I/O.  */
488 void
489 gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
490 {
491   TRACE6 (DEBUG_CTX, "gpgme_get_io_cbs", ctx,
492           "io_cbs=%p, ctx->io_cbs.add=%p/%p, .remove=%p, .event=%p/%p",
493           io_cbs, io_cbs->add, io_cbs->add_priv, io_cbs->remove,
494           io_cbs->event, io_cbs->event_priv);
495
496   *io_cbs = ctx->io_cbs;
497 }
498
499 \f
500 /* This function sets the locale for the context CTX, or the default
501    locale if CTX is a null pointer.  */
502 gpgme_error_t
503 gpgme_set_locale (gpgme_ctx_t ctx, int category, const char *value)
504 {
505   int failed = 0;
506   char *new_lc_ctype = NULL;
507   char *new_lc_messages = NULL;
508
509   TRACE_BEG2 (DEBUG_CTX, "gpgme_set_locale", ctx,
510                "category=%i, value=%s", category, value ? value : "(null)");
511
512 #define PREPARE_ONE_LOCALE(lcat, ucat)                          \
513   if (!failed && value                                          \
514       && (category == LC_ALL || category == LC_ ## ucat))       \
515     {                                                           \
516       new_lc_ ## lcat = strdup (value);                         \
517       if (!new_lc_ ## lcat)                                     \
518         failed = 1;                                             \
519     }
520
521   PREPARE_ONE_LOCALE (ctype, CTYPE);
522 #ifdef LC_MESSAGES
523   PREPARE_ONE_LOCALE (messages, MESSAGES);
524 #endif
525
526   if (failed)
527     {
528       int saved_errno = errno;
529
530       if (new_lc_ctype)
531         free (new_lc_ctype);
532       if (new_lc_messages)
533         free (new_lc_messages);
534
535       return TRACE_ERR (gpg_error_from_errno (saved_errno));
536     }
537
538 #define SET_ONE_LOCALE(lcat, ucat)                      \
539   if (category == LC_ALL || category == LC_ ## ucat)    \
540     {                                                   \
541       if (ctx)                                          \
542         {                                               \
543           if (ctx->lc_ ## lcat)                         \
544             free (ctx->lc_ ## lcat);                    \
545           ctx->lc_ ## lcat = new_lc_ ## lcat;           \
546         }                                               \
547       else                                              \
548         {                                               \
549           if (def_lc_ ## lcat)                          \
550             free (def_lc_ ## lcat);                     \
551           def_lc_ ## lcat = new_lc_ ## lcat;            \
552         }                                               \
553     }
554
555   if (!ctx)
556     LOCK (def_lc_lock);
557   SET_ONE_LOCALE (ctype, CTYPE);
558 #ifdef LC_MESSAGES
559   SET_ONE_LOCALE (messages, MESSAGES);
560 #endif
561   if (!ctx)
562     UNLOCK (def_lc_lock);
563
564   return TRACE_ERR (0);
565 }
566
567 \f
568 /* Get the information about the configured engines.  A pointer to the
569    first engine in the statically allocated linked list is returned.
570    The returned data is valid until the next gpgme_ctx_set_engine_info.  */
571 gpgme_engine_info_t
572 gpgme_ctx_get_engine_info (gpgme_ctx_t ctx)
573 {
574   TRACE1 (DEBUG_CTX, "gpgme_ctx_get_engine_info", ctx,
575           "ctx->engine_info=%p", ctx->engine_info);
576   return ctx->engine_info;
577 }
578
579
580 /* Set the engine info for the context CTX, protocol PROTO, to the
581    file name FILE_NAME and the home directory HOME_DIR.  */
582 gpgme_error_t
583 gpgme_ctx_set_engine_info (gpgme_ctx_t ctx, gpgme_protocol_t proto,
584                            const char *file_name, const char *home_dir)
585 {
586   gpgme_error_t err;
587   TRACE_BEG4 (DEBUG_CTX, "gpgme_ctx_set_engine_info", ctx,
588               "protocol=%i (%s), file_name=%s, home_dir=%s",
589               proto, gpgme_get_protocol_name (proto)
590               ? gpgme_get_protocol_name (proto) : "unknown",
591               file_name ? file_name : "(default)",
592               home_dir ? home_dir : "(default)");
593               
594   /* Shut down the engine when changing engine info.  */
595   if (ctx->engine)
596     {
597       TRACE_LOG1 ("releasing ctx->engine=%p", ctx->engine);
598       _gpgme_engine_release (ctx->engine);
599       ctx->engine = NULL;
600     }
601   err = _gpgme_set_engine_info (ctx->engine_info, proto,
602                                 file_name, home_dir);
603   return TRACE_ERR (err);
604 }
605
606 \f
607 /* Clear all notation data from the context.  */
608 void
609 gpgme_sig_notation_clear (gpgme_ctx_t ctx)
610 {
611   gpgme_sig_notation_t notation;
612   TRACE (DEBUG_CTX, "gpgme_sig_notation_clear", ctx);
613
614   if (!ctx)
615     return;
616
617   notation = ctx->sig_notations;
618   while (notation)
619     {
620       gpgme_sig_notation_t next_notation = notation->next;
621       _gpgme_sig_notation_free (notation);
622       notation = next_notation;
623     }
624   ctx->sig_notations = NULL;
625 }
626
627
628 /* Add the human-readable notation data with name NAME and value VALUE
629    to the context CTX, using the flags FLAGS.  If NAME is NULL, then
630    VALUE should be a policy URL.  The flag
631    GPGME_SIG_NOTATION_HUMAN_READABLE is forced to be true for notation
632    data, and false for policy URLs.  */
633 gpgme_error_t
634 gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
635                         const char *value, gpgme_sig_notation_flags_t flags)
636 {
637   gpgme_error_t err;
638   gpgme_sig_notation_t notation;
639   gpgme_sig_notation_t *lastp;
640
641   TRACE_BEG3 (DEBUG_CTX, "gpgme_sig_notation_add", ctx,
642               "name=%s, value=%s, flags=0x%x",
643               name ? name : "(null)", value ? value : "(null)",
644               flags);
645   
646   if (!ctx)
647     return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
648
649   if (name)
650     flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
651   else
652     flags &= ~GPGME_SIG_NOTATION_HUMAN_READABLE;
653
654   err = _gpgme_sig_notation_create (&notation, name, name ? strlen (name) : 0,
655                                     value, value ? strlen (value) : 0, flags);
656   if (err)
657     return TRACE_ERR (err);
658
659   lastp = &ctx->sig_notations;
660   while (*lastp)
661     lastp = &(*lastp)->next;
662
663   *lastp = notation;
664   return TRACE_ERR (0);
665 }
666
667
668 /* Get the sig notations for this context.  */
669 gpgme_sig_notation_t
670 gpgme_sig_notation_get (gpgme_ctx_t ctx)
671 {
672   if (!ctx)
673     {
674       TRACE (DEBUG_CTX, "gpgme_sig_notation_get", ctx);
675       return NULL;
676     }
677   TRACE1 (DEBUG_CTX, "gpgme_sig_notation_get", ctx,
678           "ctx->sig_notations=%p", ctx->sig_notations);
679
680   return ctx->sig_notations;
681 }
682   
683 \f
684 const char *
685 gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
686 {
687   switch (algo)
688     {
689     case GPGME_PK_RSA:
690       return "RSA";
691
692     case GPGME_PK_RSA_E:
693       return "RSA-E";
694
695     case GPGME_PK_RSA_S:
696       return "RSA-S";
697
698     case GPGME_PK_ELG_E:
699       return "ELG-E";
700
701     case GPGME_PK_DSA:
702       return "DSA";
703
704     case GPGME_PK_ELG:
705       return "ELG";
706
707     default:
708       return NULL;
709     }
710 }
711
712
713 const char *
714 gpgme_hash_algo_name (gpgme_hash_algo_t algo)
715 {
716   switch (algo)
717     {
718     case GPGME_MD_MD5:
719       return "MD5";
720
721     case GPGME_MD_SHA1:
722       return "SHA1";
723
724     case GPGME_MD_RMD160:
725       return "RIPEMD160";
726
727     case GPGME_MD_MD2:
728       return "MD2";
729
730     case GPGME_MD_TIGER:
731       return "TIGER192";
732
733     case GPGME_MD_HAVAL:
734       return "HAVAL";
735
736     case GPGME_MD_SHA256:
737       return "SHA256";
738
739     case GPGME_MD_SHA384:
740       return "SHA384";
741
742     case GPGME_MD_SHA512:
743       return "SHA512";
744
745     case GPGME_MD_MD4:
746       return "MD4";
747
748     case GPGME_MD_CRC32:
749       return "CRC32";
750
751     case GPGME_MD_CRC32_RFC1510:
752       return "CRC32RFC1510";
753
754     case GPGME_MD_CRC24_RFC2440:
755       return "CRC24RFC2440";
756
757     default:
758       return NULL;
759     }
760 }