* acinclude.m4 (AC_CHECK_PTH): Added.
[libgcrypt.git] / cipher / ac.c
1 /* ac.c - Alternative interface for asymmetric cryptography.
2    Copyright (C) 2003 Free Software Foundation, Inc.
3  
4    This file is part of Libgcrypt.
5   
6    Libgcrypt is free software; you can redistribute it and/or modify
7    it under the terms of the GNU Lesser general Public License as
8    published by the Free Software Foundation; either version 2.1 of
9    the License, or (at your option) any later version.
10   
11    Libgcrypt is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU Lesser General Public License for more details.
15   
16    You should have received a copy of the GNU Lesser General Public
17    License along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <assert.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <stddef.h>
28
29 #include "g10lib.h"
30 #include "cipher.h"
31
32 \f
33
34 /* At the moment the ac interface is a wrapper around the pk
35    interface, but this might change somewhen in the future, depending
36    on how much people prefer the ac interface.  */
37
38 /* Mapping of flag numbers to the according strings as it is expected
39    for S-expressions.  */
40 struct number_string
41 {
42   int number;
43   const char *string;
44 } gcry_ac_flags[] =
45   {
46     { GCRY_AC_FLAG_DATA_NO_BLINDING, "no-blinding" },
47     { 0, NULL },
48   };
49
50 /* The positions in this list correspond to the values contained in
51    the gcry_ac_key_type_t enumeration list.  */
52 static const char *ac_key_identifiers[] =
53   {
54     "private-key",
55     "public-key",
56   };
57
58 /* These specifications are needed for key-pair generation; the caller
59    is allowed to pass additional, algorithm-specific `specs' to
60    gcry_ac_key_pair_generate.  This list is used for decoding the
61    provided values according to the selected algorithm.  */
62 struct gcry_ac_key_generate_spec
63 {
64   int algorithm;                /* Algorithm for which this flag is
65                                    relevant.  */
66   const char *name;             /* Name of this flag.  */
67   size_t offset;                /* Offset in the cipher-specific spec
68                                    structure at which the MPI value
69                                    associated with this flag is to be
70                                    found.  */
71 } gcry_ac_key_generate_specs[] =
72   {
73     { GCRY_AC_RSA, "rsa-use-e", offsetof (gcry_ac_key_spec_rsa_t, e) },
74     { 0 },
75   };
76
77 /* Handle structure.  */
78 struct gcry_ac_handle
79 {
80   int algorithm;                /* Algorithm ID associated with this
81                                    handle.  */
82   const char *algorithm_name;   /* Name of the algorithm.  */
83   unsigned int flags;           /* Flags, not used yet.  */
84   gcry_module_t module;         /* Reference to the algorithm
85                                    module.  */
86 };
87
88 /* A named MPI value.  */
89 typedef struct gcry_ac_mpi
90 {
91   const char *name;
92   gcry_mpi_t mpi;
93 } gcry_ac_mpi_t;
94
95 /* A data set, that is simply a list of named MPI values.  */
96 struct gcry_ac_data
97 {
98   gcry_ac_mpi_t *data;          /* List of named values.      */
99   unsigned int data_n;          /* Number of values in DATA.  */
100 };
101
102 /* The key in `native' ac form and as an S-expression. */
103 struct gcry_ac_key
104 {
105   gcry_ac_data_t data;          /* Data in native ac structure.  */
106   gcry_sexp_t data_sexp;        /* Data as an S-expression.      */
107   gcry_ac_key_type_t type;      /* Type of the key.              */
108 };
109
110 /* Two keys.  */
111 struct gcry_ac_key_pair
112 {
113   gcry_ac_key_t public;
114   gcry_ac_key_t secret;
115 };
116
117 \f
118
119 /*
120  * Primitive functions for the manipulation of `data sets'.
121  */
122
123 /* Return in AC_MPI a pointer to the named MPI contained in DATA that
124    is labelled with NAME or NULL in case there is no MPI with the that
125    name.  */
126 static void
127 gcry_ac_data_search (gcry_ac_data_t data,
128                      const char *name,
129                      gcry_ac_mpi_t **ac_mpi)
130 {
131   gcry_ac_mpi_t *ac_mpi_found = NULL;
132   int i;
133
134   /* Search.  */
135   for (i = 0; i < data->data_n; i++)
136     if (! strcmp (name, data->data[i].name))
137       ac_mpi_found = &data->data[i];
138
139   *ac_mpi = ac_mpi_found;
140 }
141
142 /* Add MPI to DATA, with the label being NAME.  */
143 static gcry_err_code_t
144 gcry_ac_data_add (gcry_ac_data_t data,
145                   const char *name, gcry_mpi_t mpi)
146 {
147   gcry_err_code_t err = GPG_ERR_NO_ERROR;
148   gcry_ac_mpi_t *ac_mpis = NULL;
149
150   /* Allocate.  */
151   ac_mpis = gcry_realloc (data->data,
152                           sizeof (gcry_ac_mpi_t) * (data->data_n + 1));
153   if (! ac_mpis)
154     err = gpg_err_code_from_errno (errno);
155
156   if (! err)
157     {
158       /* Fill. */
159       if (ac_mpis != data->data)
160         data->data = ac_mpis;
161       data->data[data->data_n].name = name;
162       data->data[data->data_n].mpi = mpi;
163       data->data_n++;
164     }
165
166   return err;
167 }
168
169 /* Create a copy of the data set DATA and store it in DATA_CP.  */
170 static gcry_err_code_t
171 gcry_ac_data_copy_internal (gcry_ac_data_t *data_cp, gcry_ac_data_t data)
172 {
173   gcry_err_code_t err = GPG_ERR_NO_ERROR;
174   gcry_ac_data_t data_new;
175   void *p = NULL;
176   int i = 0;
177
178   /* Allocate data set.  */
179   err = _gcry_malloc (sizeof (struct gcry_ac_data), 0, &p);
180   data_new = p;
181   if (! err)
182     data_new->data_n = data->data_n;
183
184   if (! err)
185     /* Allocate space for named MPIs.  */
186     err = _gcry_malloc (sizeof (gcry_ac_mpi_t) * data->data_n, 0,
187                         (void **) &data_new->data);
188
189   if (! err)
190     {
191       /* Copy named MPIs.  */
192       
193       for (i = 0; i < data_new->data_n && (! err); i++)
194         {
195           data_new->data[i].name = NULL;
196           data_new->data[i].mpi = NULL;
197
198           /* Name.  */
199           data_new->data[i].name = strdup (data->data[i].name);
200           if (! data_new->data[i].name)
201             err = gpg_err_code_from_errno (errno);
202
203           if (! err)
204             {
205               /* MPI.  */
206               data_new->data[i].mpi = gcry_mpi_copy (data->data[i].mpi);
207               if (! data_new->data[i].mpi)
208                 err = gpg_err_code_from_errno (errno);
209             }
210         }
211     }
212
213   if (! err)
214     /* Copy out.  */
215     *data_cp = data_new;
216   else
217     {
218       /* Deallocate resources.  */
219       if (data_new)
220         {
221           if (data_new->data)
222             {
223               for (; i >= 0; i--)
224                 {
225                   if (data_new->data[i].name)
226                     free ((void *) data_new->data[i].name);
227                   if (data_new->data[i].mpi)
228                     gcry_mpi_release (data_new->data[i].mpi);
229                 }
230               gcry_free (data_new->data);
231             }
232           gcry_free (data_new);
233         }
234     }
235
236   return err;
237 }
238
239 \f
240
241 /* 
242  * Functions for converting data between the native ac and the
243  * S-expression structure.
244  */
245
246 /* Extract the S-Expression DATA_SEXP into DATA under the control of
247    TYPE and NAME.  This function assumes that S-Expressions are of the
248    following structure:
249
250      (IDENTIFIER <data to be ignored>
251                  (ALGORITHM <list of named MPI values>))
252
253   IDENTIFIER is one of `private-key', `public-key', `enc-val',
254   `sig-val'; ALGORITHM is the name of the algorithm used.  */
255 static gcry_err_code_t
256 gcry_ac_data_extract (const char *identifier, const char *algorithm,
257                       gcry_sexp_t data_sexp, gcry_ac_data_t *data)
258 {
259   gcry_err_code_t err = GPG_ERR_NO_ERROR;
260   gcry_sexp_t data_element_sexp = NULL;
261   gcry_sexp_t inner_data_sexp = NULL;
262   size_t inner_data_n;
263
264   const char *name;
265   size_t name_n;
266
267   gcry_mpi_t data_elem_mpi = NULL;
268   char *data_elem_name = NULL;
269
270   gcry_ac_data_t data_new = NULL;
271
272   int i = 0;
273
274   /* Verify that the S-expression contains the correct identifier.  */
275   name = gcry_sexp_nth_data (data_sexp, 0, &name_n);
276   if (! name)
277     err = GPG_ERR_INTERNAL;
278   else if (strncmp (identifier, name, name_n))
279     err = GPG_ERR_INTERNAL;
280
281   if (! err)
282     {
283       /* Extract inner S-expression.  */
284       inner_data_sexp = gcry_sexp_find_token (data_sexp, algorithm, 0);
285       if (! inner_data_sexp)
286         err = GPG_ERR_INTERNAL;
287       else
288         /* Count data elements, this includes the name of the
289            algorithm.  */
290         inner_data_n = gcry_sexp_length (inner_data_sexp);
291     }
292
293   if (! err)
294     {
295       /* Allocate new data set.  */
296       data_new = gcry_malloc (sizeof (struct gcry_ac_data));
297       if (! data_new)
298         err = gpg_err_code_from_errno (errno);
299       else
300         {
301           data_new->data = gcry_malloc (sizeof (gcry_ac_mpi_t) * (inner_data_n - 1));
302           if (! data_new->data)
303             err = gpg_err_code_from_errno (errno);
304         }
305     }
306
307   if (! err)
308     {
309       /* Iterate through list of data elements and add them to the
310          data set.  */
311
312       for (i = 1; i < inner_data_n; i++)
313         {
314           data_new->data[i - 1].name = NULL;
315           data_new->data[i - 1].mpi = NULL;
316
317           /* Get the S-expression of the named MPI, that contains the
318              name and the MPI value.  */
319           data_element_sexp = gcry_sexp_nth (inner_data_sexp, i);
320           if (! data_element_sexp)
321             err = GPG_ERR_INTERNAL;
322
323           if (! err)
324             {
325               /* Extract the name.  */
326               name = gcry_sexp_nth_data (data_element_sexp, 0, &name_n);
327               if (! name)
328                 err = GPG_ERR_INTERNAL;
329             }
330
331           if (! err)
332             {
333               /* Extract the MPI value.  */
334               data_elem_mpi = gcry_sexp_nth_mpi (data_element_sexp, 1,
335                                                  GCRYMPI_FMT_USG);
336               if (! data_elem_mpi)
337                 err = GPG_ERR_INTERNAL;
338             }
339
340           if (! err)
341             {
342               /* Duplicate the name.  */
343               data_elem_name = gcry_malloc (name_n + 1);
344               if (! data_elem_name)
345                 
346                 err = gpg_err_code_from_errno (errno);
347               else
348                 {
349                   strncpy (data_elem_name, name, name_n);
350                   data_elem_name[name_n] = 0;
351                 }
352             }
353
354           /* Done.  */
355
356           if (data_element_sexp)
357             gcry_sexp_release (data_element_sexp);
358
359           if (! err)
360             {
361               data_new->data[i - 1].name = data_elem_name;
362               data_new->data[i - 1].mpi = data_elem_mpi;
363             }
364           else
365             break;
366         }
367     }
368
369   if (! err)
370     {
371       /* Copy out.  */
372       data_new->data_n = inner_data_n - 1;
373       *data = data_new;
374     }
375   else
376     {
377       /* Deallocate resources.  */
378
379       if (data_new)
380         {
381           if (data_new->data)
382             {
383               int j;
384              
385               for (j = 0; j < i - 1; j++)
386                 {
387                   if (data_new->data[j].name)
388                     gcry_free ((void *) data_new->data[j].name);
389                   if (data_new->data[j].mpi)
390                     gcry_mpi_release (data_new->data[j].mpi);
391                 }
392
393               gcry_free (data_new->data);
394             }
395           gcry_free (data_new);
396         }
397     }
398
399   return err;
400 }
401
402 /* Construct an S-expression from the DATA and store it in
403    DATA_SEXP. The S-expression will be of the following structure:
404
405      (IDENTIFIER [(flags [...])]
406                  (ALGORITHM <list of named MPI values>))  */
407 static gcry_err_code_t
408 gcry_ac_data_construct (const char *identifier, int include_flags,
409                         unsigned int flags, const char *algorithm,
410                         gcry_ac_data_t data, gcry_sexp_t *data_sexp)
411 {
412   gcry_err_code_t err = GPG_ERR_NO_ERROR;
413   void **arg_list = NULL;
414
415   gcry_sexp_t data_sexp_new = NULL;
416
417   size_t data_format_n = 0;
418   char *data_format = NULL;
419
420   int i;
421
422   /* We build a list of arguments to pass to
423      gcry_sexp_build_array().  */
424   arg_list = gcry_malloc (sizeof (void *) * data->data_n);
425   if (! arg_list)
426     err = gpg_err_code_from_errno (errno);
427   else
428     /* Fill list with MPIs.  */
429     for (i = 0; i < data->data_n; i++)
430       arg_list[i] = (void *) &data->data[i].mpi;
431
432   if (! err)
433     {
434       /* Calculate size of format string.  */
435
436       data_format_n = 5 + (include_flags ? 7 : 0) + strlen (identifier) + strlen (algorithm);
437       for (i = 0; i < data->data_n; i++)
438         /* Per-element sizes.  */
439         data_format_n += 4 + strlen (data->data[i].name);
440
441       if (include_flags)
442         /* Add flags.  */
443         for (i = 0; gcry_ac_flags[i].number; i++)
444           if (flags & gcry_ac_flags[i].number)
445             data_format_n += strlen (gcry_ac_flags[i].string) + 1;
446
447       /* Done.  */
448       data_format = gcry_malloc (data_format_n);
449       if (! data_format)
450         err = gpg_err_code_from_errno (errno);
451     }
452
453   if (! err)
454     {
455       /* Construct the format string.  */
456
457       *data_format = 0;
458       strcat (data_format, "(");
459       strcat (data_format, identifier);
460       if (include_flags)
461         {
462           strcat (data_format, "(flags");
463           for (i = 0; gcry_ac_flags[i].number; i++)
464             if (flags & gcry_ac_flags[i].number)
465               {
466                 strcat (data_format, " ");
467                 strcat (data_format, gcry_ac_flags[i].string);
468               }
469           strcat (data_format, ")");
470         }
471       strcat (data_format, "(");
472       strcat (data_format, algorithm);
473       for (i = 0; i < data->data_n; i++)
474         {
475           strcat (data_format, "(");
476           strcat (data_format, data->data[i].name);
477           strcat (data_format, "%m)");
478         }
479       strcat (data_format, "))");
480
481       /* Create final S-expression.  */
482       err = gcry_sexp_build_array (&data_sexp_new, NULL,
483                                    data_format, arg_list);
484     }
485
486   if (err)
487     {
488       /* Deallocate resources.  */
489
490       if (arg_list)
491         gcry_free (arg_list);
492       if (data_format)
493         gcry_free (data_format);
494       if (data_sexp_new)
495         gcry_sexp_release (data_sexp_new);
496     }
497
498   else
499     /* Copy-out.  */
500     *data_sexp = data_sexp_new;
501
502   return err;
503 }
504
505 \f
506
507 /* 
508  * Functions for working with data sets.
509  */
510
511 /* Creates a new, empty data set and stores it in DATA.  */
512 gcry_error_t
513 gcry_ac_data_new (gcry_ac_data_t *data)
514 {
515   gcry_err_code_t err = GPG_ERR_NO_ERROR;
516   gcry_ac_data_t data_new = NULL;
517
518   data_new = gcry_malloc (sizeof (struct gcry_ac_data));
519   if (! data_new)
520     err = gpg_err_code_from_errno (errno);
521
522   if (! err)
523     {
524       data_new->data = NULL;
525       data_new->data_n = 0;
526       *data = data_new;
527     }
528
529   return gcry_error (err);
530 }
531
532 /* Destroys the data set DATA.  */
533 void
534 gcry_ac_data_destroy (gcry_ac_data_t data)
535 {
536   int i;
537
538   for (i = 0; i < data->data_n; i++)
539     {
540       gcry_free ((void *) data->data[i].name);
541       gcry_mpi_release (data->data[i].mpi);
542     }
543   gcry_free (data->data);
544   gcry_free (data);
545 }
546
547 /* Adds the value MPI to the data set DATA with the label NAME.  If
548    there is already a value with that label, it is replaced, otherwise
549    a new value is added. */
550 gcry_error_t
551 gcry_ac_data_set (gcry_ac_data_t data,
552                   const char *name, gcry_mpi_t mpi)
553 {
554   gcry_err_code_t err = GPG_ERR_NO_ERROR;
555   gcry_ac_mpi_t *ac_mpi;
556
557   gcry_ac_data_search (data, name, &ac_mpi);
558   if (ac_mpi)
559     {
560       /* An entry for NAME does already exist, replace it.  */
561       if (ac_mpi->mpi != mpi)
562         {
563           gcry_mpi_release (ac_mpi->mpi);
564           ac_mpi->mpi = mpi;
565         }
566     }
567   else
568     {
569       /* Create a new entry.  */
570
571       gcry_mpi_t mpi_cp = NULL;
572       char *name_cp = NULL;
573
574       name_cp = strdup (name);
575       if (name_cp)
576         mpi_cp = gcry_mpi_copy (mpi);
577       if (! (name_cp && mpi_cp))
578         err = gpg_err_code_from_errno (errno);
579
580       if (! err)
581         err = gcry_ac_data_add (data, name_cp, mpi_cp);
582
583       if (err)
584         {
585           if (name_cp)
586             gcry_free (name_cp);
587           if (mpi_cp)
588             gcry_mpi_release (mpi_cp);
589         }
590     }
591
592   return gcry_error (err);
593 }
594
595 /* Create a copy of the data set DATA and store it in DATA_CP.  */
596 gcry_error_t
597 gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data)
598 {
599   gcry_err_code_t err = GPG_ERR_NO_ERROR;
600
601   err = gcry_ac_data_copy_internal (data_cp, data);
602
603   return gcry_error (err);
604 }
605
606 /* Returns the number of named MPI values inside of the data set
607    DATA.  */
608 unsigned int
609 gcry_ac_data_length (gcry_ac_data_t data)
610 {
611   return data->data_n;
612 }
613
614 /* Stores the value labelled with NAME found in the data set DATA in
615    MPI.  The returned MPI value will be released in case
616    gcry_ac_data_set is used to associate the label NAME with a
617    different MPI value.  */
618 gcry_error_t
619 gcry_ac_data_get_name (gcry_ac_data_t data, const char *name,
620                        gcry_mpi_t *mpi)
621 {
622   gcry_err_code_t err = GPG_ERR_NO_DATA;
623   gcry_mpi_t mpi_found = NULL;
624   int i;
625   
626   for (i = 0; i < data->data_n && (! mpi_found); i++)
627     if (! strcmp (data->data[i].name, name))
628       {
629         mpi_found = data->data[i].mpi;
630         err = GPG_ERR_NO_ERROR;
631       }
632
633   if (! err)
634     *mpi = mpi_found;
635
636   return gcry_error (err);
637 }
638
639 /* Stores in NAME and MPI the named MPI value contained in the data
640    set DATA with the index INDEX.  NAME or MPI may be NULL.  The
641    returned MPI value will be released in case gcry_ac_data_set is
642    used to associate the label NAME with a different MPI value.  */
643 gcry_error_t
644 gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int idx,
645                         const char **name, gcry_mpi_t *mpi)
646 {
647   gcry_err_code_t err = GPG_ERR_NO_ERROR;
648
649   if (idx < data->data_n)
650     {
651       if (name)
652         *name = data->data[idx].name;
653       if (mpi)
654         *mpi = data->data[idx].mpi;
655     }
656   else
657     err = GPG_ERR_NO_DATA;
658
659   return gcry_error (err);
660 }
661
662 /* Destroys any values contained in the data set DATA.  */
663 void
664 gcry_ac_data_clear (gcry_ac_data_t data)
665 {
666   gcry_free (data->data);
667   data->data = NULL;
668   data->data_n = 0;
669 }
670
671 \f
672
673 /*
674  * Handle management.
675  */
676
677 /* Creates a new handle for the algorithm ALGORITHM and store it in
678    HANDLE.  FLAGS is not used yet.  */
679 gcry_error_t
680 gcry_ac_open (gcry_ac_handle_t *handle,
681               gcry_ac_id_t algorithm, unsigned int flags)
682 {
683   gcry_err_code_t err = GPG_ERR_NO_ERROR;
684   gcry_module_t module = NULL;
685   gcry_ac_handle_t handle_new;
686   const char *algorithm_name;
687
688   /* Get name.  */
689   algorithm_name = _gcry_pk_aliased_algo_name (algorithm);
690   if (! *algorithm_name)
691     err = GPG_ERR_PUBKEY_ALGO;
692
693   if (! err)  /* Acquire reference to the pubkey module.  */
694     err = _gcry_pk_module_lookup (algorithm, &module);
695   
696   if (! err)
697     {
698       /* Allocate.  */
699       handle_new = gcry_malloc (sizeof (struct gcry_ac_handle));
700       if (! handle_new)
701         err = gpg_err_code_from_errno (errno);
702     }
703
704   if (! err)
705     {
706       /* Done.  */
707       handle_new->algorithm = algorithm;
708       handle_new->algorithm_name = algorithm_name;
709       handle_new->flags = flags;
710       handle_new->module = module;
711       *handle = handle_new;
712     }
713   else
714     {
715       /* Deallocate resources.  */
716       if (module)
717         _gcry_pk_module_release (module);
718     }
719
720   return gcry_error (err);
721 }
722
723 /* Destroys the handle HANDLE.  */
724 void
725 gcry_ac_close (gcry_ac_handle_t handle)
726 {
727   /* Release reference to pubkey module.  */
728   _gcry_pk_module_release (handle->module);
729   gcry_free (handle);
730 }
731
732 \f
733
734 /* 
735  * Key management.
736  */
737
738 /* Creates a new key of type TYPE, consisting of the MPI values
739    contained in the data set DATA and stores it in KEY.  */
740 gcry_error_t
741 gcry_ac_key_init (gcry_ac_key_t *key,
742                   gcry_ac_handle_t handle,
743                   gcry_ac_key_type_t type,
744                   gcry_ac_data_t data)
745 {
746   gcry_err_code_t err = GPG_ERR_NO_ERROR;
747   gcry_ac_data_t data_new = NULL;
748   gcry_sexp_t data_sexp = NULL;
749   gcry_ac_key_t key_new = NULL;
750
751   /* Allocate.  */
752   key_new = gcry_malloc (sizeof (struct gcry_ac_key));
753   if (! key_new)
754     err = gpg_err_code_from_errno (errno);
755
756   if (! err)
757     /* Create S-expression from data set.  */
758     err = gcry_ac_data_construct (ac_key_identifiers[type], 0, 0,
759                                   handle->algorithm_name, data, &data_sexp);
760
761   if (! err)
762     /* Copy data set.  */
763     err = gcry_ac_data_copy_internal (&data_new, data);
764
765   if (! err)
766     {
767       /* Done.  */
768       key_new->data_sexp = data_sexp;
769       key_new->data = data_new;
770       key_new->type = type;
771       *key = key_new;
772     }
773   else
774     {
775       /* Deallocate resources.  */
776       if (key_new)
777         gcry_free (key_new);
778       if (data_sexp)
779         gcry_sexp_release (data_sexp);
780     }
781
782   return gcry_error (err);
783 }
784
785 /* Generates a new key pair via the handle HANDLE of NBITS bits and
786    stores it in KEY_PAIR.  In case non-standard settings are wanted, a
787    pointer to a structure of type gcry_ac_key_spec_<algorithm>_t,
788    matching the selected algorithm, can be given as KEY_SPEC.  */
789 gcry_error_t
790 gcry_ac_key_pair_generate (gcry_ac_handle_t handle,
791                            gcry_ac_key_pair_t *key_pair,
792                            unsigned int nbits,
793                            void *key_spec)
794 {
795   gcry_err_code_t err = GPG_ERR_NO_ERROR;
796
797   gcry_ac_key_pair_t key_pair_new = NULL;
798
799   gcry_sexp_t genkey_sexp_request = NULL;
800   gcry_sexp_t genkey_sexp_reply = NULL;
801
802   char *genkey_format = NULL;
803   size_t genkey_format_n = 0;
804
805   void **arg_list = NULL;
806   size_t arg_list_n = 0;
807
808   unsigned int i = 0;
809
810   /* Allocate key pair.  */
811   key_pair_new = gcry_malloc (sizeof (struct gcry_ac_key_pair));
812   if (! key_pair_new)
813     err = gpg_err_code_from_errno (errno);
814
815   if (! err)
816     {
817       /* Allocate keys.  */
818       key_pair_new->secret = gcry_malloc (sizeof (struct gcry_ac_key));
819       key_pair_new->public = gcry_malloc (sizeof (struct gcry_ac_key));
820
821       if (! (key_pair_new->secret || key_pair_new->public))
822         err = gpg_err_code_from_errno (errno);
823       else
824         {
825           key_pair_new->secret->type = GCRY_AC_KEY_SECRET;
826           key_pair_new->public->type = GCRY_AC_KEY_PUBLIC;
827           key_pair_new->secret->data_sexp = NULL;
828           key_pair_new->public->data_sexp = NULL;
829           key_pair_new->secret->data = NULL;
830           key_pair_new->public->data = NULL;
831         }
832     }
833
834   if (! err)
835     {
836       /* Calculate size of the format string, that is used for
837          creating the request S-expression.  */
838       genkey_format_n = 23;
839
840       /* Respect any relevant algorithm specific commands.  */
841       if (key_spec)
842         for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
843           if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
844             genkey_format_n += 6;
845
846       /* Create format string.  */
847       genkey_format = gcry_malloc (genkey_format_n);
848       if (! genkey_format)
849         err = gpg_err_code_from_errno (errno);
850       else
851         {
852           /* Fill format string.  */
853           *genkey_format = 0;
854           strcat (genkey_format, "(genkey(%s(nbits%d)");
855           if (key_spec)
856             for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
857               if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
858                 strcat (genkey_format, "(%s%m)");
859           strcat (genkey_format, "))");
860         }
861     }
862
863   if (! err)
864     {
865       /* Build list of argument pointers, the algorithm name and the
866          nbits are needed always.  */
867       arg_list_n = 2;
868
869       /* Now the algorithm specific arguments.  */
870       if (key_spec)
871         for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
872           if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
873             arg_list_n += 2;
874
875       /* Allocate list.  */
876       arg_list = gcry_malloc (sizeof (void *) * arg_list_n);
877       if (! arg_list)
878         err = gpg_err_code_from_errno (errno);
879       else
880         {
881           /* Fill argument list. */
882           
883           int j;
884
885           arg_list[0] = (void *) &handle->algorithm_name;
886           arg_list[1] = (void *) &nbits;
887
888           if (key_spec)
889             for (j = 2, i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
890               if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
891                 {
892                   /* Add name of this specification flag and the
893                      according member of the spec strucuture.  */
894                   arg_list[j++] = (void *) (&gcry_ac_key_generate_specs[i].name);
895                   arg_list[j++] = (void *) (((char *) key_spec)
896                                             + gcry_ac_key_generate_specs[i].offset);
897                 }
898         }
899     }
900
901   if (! err)
902     /* Construct final request S-expression.  */
903     err = gcry_err_code (gcry_sexp_build_array (&genkey_sexp_request, NULL,
904                                                genkey_format, arg_list));
905
906   if (! err)
907     /* Perform genkey operation.  */
908     err = gcry_err_code (gcry_pk_genkey (&genkey_sexp_reply,
909                                         genkey_sexp_request));
910
911   /* Split keys.  */
912   if (! err)
913     {
914       key_pair_new->secret->data_sexp = gcry_sexp_find_token (genkey_sexp_reply,
915                                                               "private-key", 0);
916       if (! key_pair_new->secret->data_sexp)
917         err = GPG_ERR_INTERNAL;
918     }
919   if (! err)
920     {
921       key_pair_new->public->data_sexp = gcry_sexp_find_token (genkey_sexp_reply,
922                                                               "public-key", 0);
923       if (! key_pair_new->public->data_sexp)
924         err = GPG_ERR_INTERNAL;
925     }
926
927   /* Extract key material.  */
928   if (! err)
929     err = gcry_ac_data_extract ("private-key", handle->algorithm_name,
930                                 key_pair_new->secret->data_sexp,
931                                 &key_pair_new->secret->data);
932   if (! err)
933     err = gcry_ac_data_extract ("public-key", handle->algorithm_name,
934                                 key_pair_new->public->data_sexp,
935                                 &key_pair_new->public->data);
936
937   /* Done.  */
938
939   if (! err)
940     *key_pair = key_pair_new;
941   else
942     {
943       /* Deallocate resources.  */
944
945       if (key_pair_new)
946         {
947           if (key_pair_new->secret)
948             gcry_ac_key_destroy (key_pair_new->secret);
949           if (key_pair_new->public)
950             gcry_ac_key_destroy (key_pair_new->public);
951
952           gcry_free (key_pair_new);
953         }
954
955       if (arg_list)
956         gcry_free (arg_list);
957
958       if (genkey_format)
959         gcry_free (genkey_format);
960
961       if (genkey_sexp_request)
962         gcry_sexp_release (genkey_sexp_request);
963       if (genkey_sexp_reply)
964         gcry_sexp_release (genkey_sexp_reply);
965     }
966
967   return gcry_error (err);
968 }
969
970 /* Returns the key of type WHICH out of the key pair KEY_PAIR.  */
971 gcry_ac_key_t
972 gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
973                           gcry_ac_key_type_t witch)
974 {
975   gcry_ac_key_t key = NULL;
976
977   switch (witch)
978     {
979     case GCRY_AC_KEY_SECRET:
980       key = key_pair->secret;
981       break;
982
983     case GCRY_AC_KEY_PUBLIC:
984       key = key_pair->public;
985       break;
986     }
987
988   return key;
989 }
990
991 /* Destroys the key KEY.  */
992 void
993 gcry_ac_key_destroy (gcry_ac_key_t key)
994 {
995   int i;
996
997   if (key->data)
998     {
999       for (i = 0; i < key->data->data_n; i++)
1000         if (key->data->data[i].mpi != NULL)
1001           gcry_mpi_release (key->data->data[i].mpi);
1002       gcry_free (key->data);
1003     }
1004   if (key->data_sexp)
1005     gcry_sexp_release (key->data_sexp);
1006   gcry_free (key);
1007 }
1008
1009 /* Destroys the key pair KEY_PAIR.  */
1010 void
1011 gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair)
1012 {
1013   gcry_ac_key_destroy (key_pair->secret);
1014   gcry_ac_key_destroy (key_pair->public);
1015   gcry_free (key_pair);
1016 }
1017
1018 /* Returns the data set contained in the key KEY.  */
1019 gcry_ac_data_t
1020 gcry_ac_key_data_get (gcry_ac_key_t key)
1021 {
1022   return  key->data;
1023 }
1024
1025 /* Verifies that the key KEY is sane.  */
1026 gcry_error_t
1027 gcry_ac_key_test (gcry_ac_key_t key)
1028 {
1029   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1030
1031   err = gcry_err_code (gcry_pk_testkey (key->data_sexp));
1032
1033   return gcry_error (err);
1034 }
1035
1036 /* Stores the number of bits of the key KEY in NBITS.  */
1037 gcry_error_t
1038 gcry_ac_key_get_nbits (gcry_ac_key_t key, unsigned int *nbits)
1039 {
1040   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1041   unsigned int n;
1042
1043   n = gcry_pk_get_nbits (key->data_sexp);
1044   if (n)
1045     *nbits = n;
1046   else
1047     err = GPG_ERR_PUBKEY_ALGO;
1048
1049   return gcry_error (err);
1050 }
1051
1052 /* Writes the 20 byte long key grip of the key KEY to KEY_GRIP.  */
1053 gcry_error_t
1054 gcry_ac_key_get_grip (gcry_ac_key_t key, unsigned char *key_grip)
1055 {
1056   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1057   unsigned char *ret;
1058
1059   ret = gcry_pk_get_keygrip (key->data_sexp, key_grip);
1060   if (! ret)
1061     err = GPG_ERR_INTERNAL;     /* FIXME.  */
1062
1063   return gcry_error (err);
1064 }
1065
1066 \f
1067
1068 /* 
1069  * Functions performing cryptographic operations.
1070  */
1071
1072 /* Encrypts the plain text MPI value DATA_PLAIN with the key public
1073    KEY under the control of the flags FLAGS and stores the resulting
1074    data set into DATA_ENCRYPTED.  */
1075 gcry_error_t
1076 gcry_ac_data_encrypt (gcry_ac_handle_t handle,
1077                       unsigned int flags,
1078                       gcry_ac_key_t key,
1079                       gcry_mpi_t data_plain,
1080                       gcry_ac_data_t *data_encrypted)
1081 {
1082   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1083   gcry_sexp_t sexp_request = NULL;
1084   gcry_sexp_t sexp_reply = NULL;
1085   char *request_format = NULL;
1086   size_t request_format_n = 0;
1087   gcry_ac_data_t data;
1088   
1089   int i;
1090
1091   if (key->type != GCRY_AC_KEY_PUBLIC)
1092     err = GPG_ERR_WRONG_KEY_USAGE;
1093
1094   if (! err)
1095     {
1096       /* Calculate request format string.  */
1097
1098       request_format_n += 23;
1099       for (i = 0; gcry_ac_flags[i].number; i++)
1100         if (flags & gcry_ac_flags[i].number)
1101           request_format_n += strlen (gcry_ac_flags[i].string) + 1;
1102
1103       /* Allocate request format string.  */
1104       request_format = gcry_malloc (request_format_n);
1105       if (! request_format)
1106         err = gpg_err_code_from_errno (errno);
1107     }
1108
1109   if (! err)
1110     {
1111       /* Fill format string.  */
1112       *request_format = 0;
1113       strcat (request_format, "(data(flags");
1114       for (i = 0; gcry_ac_flags[i].number; i++)
1115         if (flags & gcry_ac_flags[i].number)
1116           {
1117             strcat (request_format, " ");
1118             strcat (request_format, gcry_ac_flags[i].string);
1119           }
1120       strcat (request_format, ")(value%m))");
1121
1122       /* Create S-expression.  */
1123       err = gcry_sexp_build (&sexp_request, NULL,
1124                              request_format, data_plain);
1125     }
1126
1127   if (! err)
1128     /* Encrypt.  */
1129     err = gcry_pk_encrypt (&sexp_reply, sexp_request, key->data_sexp);
1130
1131   if (! err)
1132     /* Extract data.  */
1133     err = gcry_ac_data_extract ("enc-val", handle->algorithm_name,
1134                                 sexp_reply, &data);
1135
1136   /* Deallocate resources.  */
1137
1138   if (sexp_request)
1139     gcry_sexp_release (sexp_request);
1140   if (sexp_reply)
1141     gcry_sexp_release (sexp_reply);
1142
1143   if (! err)
1144     /* Copy out.  */
1145     *data_encrypted = data;
1146
1147   return gcry_error (err);
1148 }
1149
1150 /* Decrypts the encrypted data contained in the data set
1151    DATA_ENCRYPTED with the secret key KEY under the control of the
1152    flags FLAGS and stores the resulting plain text MPI value in
1153    DATA_PLAIN.  */
1154 gcry_error_t
1155 gcry_ac_data_decrypt (gcry_ac_handle_t handle,
1156                       unsigned int flags,
1157                       gcry_ac_key_t key,
1158                       gcry_mpi_t *data_plain,
1159                       gcry_ac_data_t data_encrypted)
1160 {
1161   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1162   gcry_mpi_t data_decrypted = NULL;
1163   gcry_sexp_t sexp_request = NULL;
1164   gcry_sexp_t sexp_reply = NULL;
1165
1166   if (key->type != GCRY_AC_KEY_SECRET)
1167     err = GPG_ERR_WRONG_KEY_USAGE;
1168
1169   if (! err)
1170     /* Create S-expression from data.  */
1171     err = gcry_ac_data_construct ("enc-val", 1, flags, handle->algorithm_name,
1172                                   data_encrypted, &sexp_request);
1173
1174   if (! err)
1175     /* Decrypt.  */
1176     err = gcry_pk_decrypt (&sexp_reply, sexp_request, key->data_sexp);
1177
1178   if (! err)
1179     {
1180       /* Extract plain text. */
1181
1182       gcry_sexp_t l;
1183
1184       l = gcry_sexp_find_token (sexp_reply, "value", 0);
1185       if (! l)
1186         err = GPG_ERR_GENERAL;
1187       else
1188         {
1189           data_decrypted = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
1190           if (! data_decrypted)
1191             err = GPG_ERR_GENERAL;
1192           gcry_sexp_release (l);
1193         }
1194     }
1195
1196   /* Done.  */
1197
1198   if (err)
1199     {
1200       /* Deallocate resources.  */
1201       if (sexp_request)
1202         gcry_sexp_release (sexp_request);
1203       if (sexp_reply)
1204         gcry_sexp_release (sexp_reply);
1205     }
1206   else
1207     *data_plain = data_decrypted;
1208
1209   return gcry_error (err);
1210
1211 }
1212
1213 /* Signs the data contained in DATA with the secret key KEY and stores
1214    the resulting signature data set in DATA_SIGNATURE.  */
1215 gcry_error_t
1216 gcry_ac_data_sign (gcry_ac_handle_t handle,
1217                    gcry_ac_key_t key,
1218                    gcry_mpi_t data,
1219                    gcry_ac_data_t *data_signature)
1220 {
1221   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1222   gcry_sexp_t sexp_request = NULL;
1223   gcry_sexp_t sexp_reply = NULL;
1224   gcry_ac_data_t ac_data;
1225
1226   if (key->type != GCRY_AC_KEY_SECRET)
1227     err = GPG_ERR_WRONG_KEY_USAGE;
1228
1229   if (! err)
1230     /* Create S-expression holding the data.  */
1231     err = gcry_sexp_build (&sexp_request, NULL,
1232                            "(data(flags)(value%m))", data);
1233   if (! err)
1234     /* Sign.  */
1235     err = gcry_pk_sign (&sexp_reply, sexp_request, key->data_sexp);
1236
1237   if (! err)
1238     /* Extract data.  */
1239     err = gcry_ac_data_extract ("sig-val", handle->algorithm_name,
1240                                 sexp_reply, &ac_data);
1241
1242   /* Done.  */
1243
1244   if (sexp_request)
1245     gcry_sexp_release (sexp_request);
1246   if (sexp_reply)
1247     gcry_sexp_release (sexp_reply);
1248
1249   if (! err)
1250     *data_signature = ac_data;
1251
1252   return gcry_error (err);
1253 }
1254
1255 /* Verifies that the signature contained in the data set
1256    DATA_SIGNATURE is indeed the result of signing the data contained
1257    in DATA with the secret key belonging to the public key KEY.  */
1258 gcry_error_t
1259 gcry_ac_data_verify (gcry_ac_handle_t handle,
1260                      gcry_ac_key_t key,
1261                      gcry_mpi_t data,
1262                      gcry_ac_data_t data_signature)
1263 {
1264   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1265   gcry_sexp_t sexp_request = NULL;
1266   gcry_sexp_t sexp_data = NULL;
1267
1268   if (key->type != GCRY_AC_KEY_PUBLIC)
1269     err = GPG_ERR_WRONG_KEY_USAGE;
1270
1271   if (! err)
1272     /* Construct S-expression holding the signature data.  */
1273     err = gcry_ac_data_construct ("sig-val", 1, 0, handle->algorithm_name,
1274                                   data_signature, &sexp_request);
1275
1276   if (! err)
1277     /* Construct S-expression holding the data.  */
1278     err = gcry_sexp_build (&sexp_data, NULL,
1279                            "(data(flags)(value%m))", data);
1280
1281   if (! err)
1282     /* Verify signature.  */
1283     err = gcry_pk_verify (sexp_request, sexp_data, key->data_sexp);
1284
1285   /* Done.  */
1286
1287   if (sexp_request)
1288     gcry_sexp_release (sexp_request);
1289   if (sexp_data)
1290     gcry_sexp_release (sexp_data);
1291
1292   return gcry_error (err);
1293 }
1294
1295 \f
1296
1297 /* 
1298  * General functions.
1299  */
1300
1301 /* Stores the textual representation of the algorithm whose id is
1302    given in ALGORITHM in NAME.  */
1303 gcry_error_t
1304 gcry_ac_id_to_name (gcry_ac_id_t algorithm, const char **name)
1305 {
1306   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1307   const char *n;
1308
1309   n = gcry_pk_algo_name (algorithm);
1310   if (*n)
1311     *name = n;
1312   else
1313     err = GPG_ERR_PUBKEY_ALGO;
1314
1315   return gcry_error (err);
1316 }
1317
1318 /* Stores the numeric ID of the algorithm whose textual representation
1319    is contained in NAME in ALGORITHM.  */
1320 gcry_error_t
1321 gcry_ac_name_to_id (const char *name, gcry_ac_id_t *algorithm)
1322 {
1323   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1324   int algo;
1325
1326   algo = gcry_pk_map_name (name);
1327   if (algo)
1328     *algorithm = algo;
1329   else
1330     err = GPG_ERR_PUBKEY_ALGO;
1331     
1332   return gcry_error (err);
1333 }