* ac.c (gcry_ac_open): Make sure HANDLE gets initialized even when
[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     {
215       /* Copy out.  */
216       *data_cp = data_new;
217     }
218   else
219     {
220       /* Deallocate resources.  */
221       if (data_new)
222         {
223           if (data_new->data)
224             {
225               for (; i >= 0; i--)
226                 {
227                   if (data_new->data[i].name)
228                     free ((void *) data_new->data[i].name);
229                   if (data_new->data[i].mpi)
230                     gcry_mpi_release (data_new->data[i].mpi);
231                 }
232               gcry_free (data_new->data);
233             }
234           gcry_free (data_new);
235         }
236     }
237
238   return err;
239 }
240
241 \f
242
243 /* 
244  * Functions for converting data between the native ac and the
245  * S-expression structure.
246  */
247
248 /* Extract the S-Expression DATA_SEXP into DATA under the control of
249    TYPE and NAME.  This function assumes that S-Expressions are of the
250    following structure:
251
252      (IDENTIFIER <data to be ignored>
253                  (ALGORITHM <list of named MPI values>))
254
255   IDENTIFIER is one of `private-key', `public-key', `enc-val',
256   `sig-val'; ALGORITHM is the name of the algorithm used.  */
257 static gcry_err_code_t
258 gcry_ac_data_extract (const char *identifier, const char *algorithm,
259                       gcry_sexp_t data_sexp, gcry_ac_data_t *data)
260 {
261   gcry_err_code_t err = GPG_ERR_NO_ERROR;
262   gcry_sexp_t data_element_sexp = NULL;
263   gcry_sexp_t inner_data_sexp = NULL;
264   size_t inner_data_n;
265
266   const char *name;
267   size_t name_n;
268
269   gcry_mpi_t data_elem_mpi = NULL;
270   char *data_elem_name = NULL;
271
272   gcry_ac_data_t data_new = NULL;
273
274   int i = 0;
275
276   /* Verify that the S-expression contains the correct identifier.  */
277   name = gcry_sexp_nth_data (data_sexp, 0, &name_n);
278   if (! name)
279     err = GPG_ERR_INTERNAL;
280   else if (strncmp (identifier, name, name_n))
281     err = GPG_ERR_INTERNAL;
282
283   if (! err)
284     {
285       /* Extract inner S-expression.  */
286       inner_data_sexp = gcry_sexp_find_token (data_sexp, algorithm, 0);
287       if (! inner_data_sexp)
288         err = GPG_ERR_INTERNAL;
289       else
290         /* Count data elements, this includes the name of the
291            algorithm.  */
292         inner_data_n = gcry_sexp_length (inner_data_sexp);
293     }
294
295   if (! err)
296     {
297       /* Allocate new data set.  */
298       data_new = gcry_malloc (sizeof (struct gcry_ac_data));
299       if (! data_new)
300         err = gpg_err_code_from_errno (errno);
301       else
302         {
303           data_new->data = gcry_malloc (sizeof (gcry_ac_mpi_t)
304                                         * (inner_data_n - 1));
305           if (! data_new->data)
306             err = gpg_err_code_from_errno (errno);
307         }
308     }
309
310   if (! err)
311     {
312       /* Iterate through list of data elements and add them to the
313          data set.  */
314
315       for (i = 1; i < inner_data_n; i++)
316         {
317           data_new->data[i - 1].name = NULL;
318           data_new->data[i - 1].mpi = NULL;
319
320           /* Get the S-expression of the named MPI, that contains the
321              name and the MPI value.  */
322           data_element_sexp = gcry_sexp_nth (inner_data_sexp, i);
323           if (! data_element_sexp)
324             err = GPG_ERR_INTERNAL;
325
326           if (! err)
327             {
328               /* Extract the name.  */
329               name = gcry_sexp_nth_data (data_element_sexp, 0, &name_n);
330               if (! name)
331                 err = GPG_ERR_INTERNAL;
332             }
333
334           if (! err)
335             {
336               /* Extract the MPI value.  */
337               data_elem_mpi = gcry_sexp_nth_mpi (data_element_sexp, 1,
338                                                  GCRYMPI_FMT_USG);
339               if (! data_elem_mpi)
340                 err = GPG_ERR_INTERNAL;
341             }
342
343           if (! err)
344             {
345               /* Duplicate the name.  */
346               data_elem_name = gcry_malloc (name_n + 1);
347               if (! data_elem_name)
348                 
349                 err = gpg_err_code_from_errno (errno);
350               else
351                 {
352                   strncpy (data_elem_name, name, name_n);
353                   data_elem_name[name_n] = 0;
354                 }
355             }
356
357           /* Done.  */
358
359           if (data_element_sexp)
360             gcry_sexp_release (data_element_sexp);
361
362           if (! err)
363             {
364               data_new->data[i - 1].name = data_elem_name;
365               data_new->data[i - 1].mpi = data_elem_mpi;
366             }
367           else
368             break;
369         }
370     }
371
372   if (! err)
373     {
374       /* Copy out.  */
375       data_new->data_n = inner_data_n - 1;
376       *data = data_new;
377     }
378   else
379     {
380       /* Deallocate resources.  */
381
382       if (data_new)
383         {
384           if (data_new->data)
385             {
386               int j;
387              
388               for (j = 0; j < i - 1; j++)
389                 {
390                   if (data_new->data[j].name)
391                     gcry_free ((void *) data_new->data[j].name);
392                   if (data_new->data[j].mpi)
393                     gcry_mpi_release (data_new->data[j].mpi);
394                 }
395
396               gcry_free (data_new->data);
397             }
398           gcry_free (data_new);
399         }
400     }
401
402   return err;
403 }
404
405 /* Construct an S-expression from the DATA and store it in
406    DATA_SEXP. The S-expression will be of the following structure:
407
408      (IDENTIFIER [(flags [...])]
409                  (ALGORITHM <list of named MPI values>))  */
410 static gcry_err_code_t
411 gcry_ac_data_construct (const char *identifier, int include_flags,
412                         unsigned int flags, const char *algorithm,
413                         gcry_ac_data_t data, gcry_sexp_t *data_sexp)
414 {
415   gcry_err_code_t err = GPG_ERR_NO_ERROR;
416   void **arg_list = NULL;
417
418   gcry_sexp_t data_sexp_new = NULL;
419
420   size_t data_format_n = 0;
421   char *data_format = NULL;
422
423   int i;
424
425   /* We build a list of arguments to pass to
426      gcry_sexp_build_array().  */
427   arg_list = gcry_malloc (sizeof (void *) * data->data_n);
428   if (! arg_list)
429     err = gpg_err_code_from_errno (errno);
430   else
431     /* Fill list with MPIs.  */
432     for (i = 0; i < data->data_n; i++)
433       arg_list[i] = (void *) &data->data[i].mpi;
434
435   if (! err)
436     {
437       /* Calculate size of format string.  */
438
439       data_format_n = (5 + (include_flags ? 7 : 0)
440                        + strlen (identifier) + strlen (algorithm));
441
442       for (i = 0; i < data->data_n; i++)
443         {
444           /* Per-element sizes.  */
445           data_format_n += 4 + strlen (data->data[i].name);
446         }
447
448       if (include_flags)
449         {
450           /* Add flags.  */
451           for (i = 0; gcry_ac_flags[i].number; i++)
452             if (flags & gcry_ac_flags[i].number)
453               data_format_n += strlen (gcry_ac_flags[i].string) + 1;
454         }
455
456       /* Done.  */
457       data_format = gcry_malloc (data_format_n);
458       if (! data_format)
459         err = gpg_err_code_from_errno (errno);
460     }
461
462   if (! err)
463     {
464       /* Construct the format string.  */
465
466       *data_format = 0;
467       strcat (data_format, "(");
468       strcat (data_format, identifier);
469       if (include_flags)
470         {
471           strcat (data_format, "(flags");
472           for (i = 0; gcry_ac_flags[i].number; i++)
473             if (flags & gcry_ac_flags[i].number)
474               {
475                 strcat (data_format, " ");
476                 strcat (data_format, gcry_ac_flags[i].string);
477               }
478           strcat (data_format, ")");
479         }
480       strcat (data_format, "(");
481       strcat (data_format, algorithm);
482       for (i = 0; i < data->data_n; i++)
483         {
484           strcat (data_format, "(");
485           strcat (data_format, data->data[i].name);
486           strcat (data_format, "%m)");
487         }
488       strcat (data_format, "))");
489
490       /* Create final S-expression.  */
491       err = gcry_sexp_build_array (&data_sexp_new, NULL,
492                                    data_format, arg_list);
493     }
494
495   if (err)
496     {
497       /* Deallocate resources.  */
498
499       if (arg_list)
500         gcry_free (arg_list);
501       if (data_format)
502         gcry_free (data_format);
503       if (data_sexp_new)
504         gcry_sexp_release (data_sexp_new);
505     }
506
507   else
508     /* Copy-out.  */
509     *data_sexp = data_sexp_new;
510
511   return err;
512 }
513
514 \f
515
516 /* 
517  * Functions for working with data sets.
518  */
519
520 /* Creates a new, empty data set and stores it in DATA.  */
521 gcry_error_t
522 gcry_ac_data_new (gcry_ac_data_t *data)
523 {
524   gcry_err_code_t err = GPG_ERR_NO_ERROR;
525   gcry_ac_data_t data_new = NULL;
526
527   data_new = gcry_malloc (sizeof (struct gcry_ac_data));
528   if (! data_new)
529     err = gpg_err_code_from_errno (errno);
530
531   if (! err)
532     {
533       data_new->data = NULL;
534       data_new->data_n = 0;
535       *data = data_new;
536     }
537
538   return gcry_error (err);
539 }
540
541 /* Destroys the data set DATA.  */
542 void
543 gcry_ac_data_destroy (gcry_ac_data_t data)
544 {
545   int i;
546
547   for (i = 0; i < data->data_n; i++)
548     {
549       gcry_free ((void *) data->data[i].name);
550       gcry_mpi_release (data->data[i].mpi);
551     }
552   gcry_free (data->data);
553   gcry_free (data);
554 }
555
556 /* Adds the value MPI to the data set DATA with the label NAME.  If
557    there is already a value with that label, it is replaced, otherwise
558    a new value is added. */
559 gcry_error_t
560 gcry_ac_data_set (gcry_ac_data_t data,
561                   const char *name, gcry_mpi_t mpi)
562 {
563   gcry_err_code_t err = GPG_ERR_NO_ERROR;
564   gcry_ac_mpi_t *ac_mpi;
565
566   gcry_ac_data_search (data, name, &ac_mpi);
567   if (ac_mpi)
568     {
569       /* An entry for NAME does already exist, replace it.  */
570       if (ac_mpi->mpi != mpi)
571         {
572           gcry_mpi_release (ac_mpi->mpi);
573           ac_mpi->mpi = mpi;
574         }
575     }
576   else
577     {
578       /* Create a new entry.  */
579
580       gcry_mpi_t mpi_cp = NULL;
581       char *name_cp = NULL;
582
583       name_cp = strdup (name);
584       if (name_cp)
585         mpi_cp = gcry_mpi_copy (mpi);
586       if (! (name_cp && mpi_cp))
587         err = gpg_err_code_from_errno (errno);
588
589       if (! err)
590         err = gcry_ac_data_add (data, name_cp, mpi_cp);
591
592       if (err)
593         {
594           if (name_cp)
595             gcry_free (name_cp);
596           if (mpi_cp)
597             gcry_mpi_release (mpi_cp);
598         }
599     }
600
601   return gcry_error (err);
602 }
603
604 /* Create a copy of the data set DATA and store it in DATA_CP.  */
605 gcry_error_t
606 gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data)
607 {
608   gcry_err_code_t err = GPG_ERR_NO_ERROR;
609
610   err = gcry_ac_data_copy_internal (data_cp, data);
611
612   return gcry_error (err);
613 }
614
615 /* Returns the number of named MPI values inside of the data set
616    DATA.  */
617 unsigned int
618 gcry_ac_data_length (gcry_ac_data_t data)
619 {
620   return data->data_n;
621 }
622
623 /* Stores the value labelled with NAME found in the data set DATA in
624    MPI.  The returned MPI value will be released in case
625    gcry_ac_data_set is used to associate the label NAME with a
626    different MPI value.  */
627 gcry_error_t
628 gcry_ac_data_get_name (gcry_ac_data_t data, const char *name,
629                        gcry_mpi_t *mpi)
630 {
631   gcry_err_code_t err = GPG_ERR_NO_DATA;
632   gcry_mpi_t mpi_found = NULL;
633   int i;
634   
635   for (i = 0; i < data->data_n && (! mpi_found); i++)
636     if (! strcmp (data->data[i].name, name))
637       {
638         mpi_found = data->data[i].mpi;
639         err = GPG_ERR_NO_ERROR;
640       }
641
642   if (! err)
643     *mpi = mpi_found;
644
645   return gcry_error (err);
646 }
647
648 /* Stores in NAME and MPI the named MPI value contained in the data
649    set DATA with the index INDEX.  NAME or MPI may be NULL.  The
650    returned MPI value will be released in case gcry_ac_data_set is
651    used to associate the label NAME with a different MPI value.  */
652 gcry_error_t
653 gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int idx,
654                         const char **name, gcry_mpi_t *mpi)
655 {
656   gcry_err_code_t err = GPG_ERR_NO_ERROR;
657
658   if (idx < data->data_n)
659     {
660       if (name)
661         *name = data->data[idx].name;
662       if (mpi)
663         *mpi = data->data[idx].mpi;
664     }
665   else
666     err = GPG_ERR_NO_DATA;
667
668   return gcry_error (err);
669 }
670
671 /* Destroys any values contained in the data set DATA.  */
672 void
673 gcry_ac_data_clear (gcry_ac_data_t data)
674 {
675   gcry_free (data->data);
676   data->data = NULL;
677   data->data_n = 0;
678 }
679
680 \f
681
682 /*
683  * Handle management.
684  */
685
686 /* Creates a new handle for the algorithm ALGORITHM and store it in
687    HANDLE.  FLAGS is not used yet.  */
688 gcry_error_t
689 gcry_ac_open (gcry_ac_handle_t *handle,
690               gcry_ac_id_t algorithm, unsigned int flags)
691 {
692   gcry_err_code_t err = GPG_ERR_NO_ERROR;
693   gcry_module_t module = NULL;
694   gcry_ac_handle_t handle_new;
695   const char *algorithm_name;
696
697   *handle = NULL;
698
699   /* Get name.  */
700   algorithm_name = _gcry_pk_aliased_algo_name (algorithm);
701   if (! *algorithm_name)
702     err = GPG_ERR_PUBKEY_ALGO;
703
704   if (! err)  /* Acquire reference to the pubkey module.  */
705     err = _gcry_pk_module_lookup (algorithm, &module);
706   
707   if (! err)
708     {
709       /* Allocate.  */
710       handle_new = gcry_malloc (sizeof (struct gcry_ac_handle));
711       if (! handle_new)
712         err = gpg_err_code_from_errno (errno);
713     }
714
715   if (! err)
716     {
717       /* Done.  */
718       handle_new->algorithm = algorithm;
719       handle_new->algorithm_name = algorithm_name;
720       handle_new->flags = flags;
721       handle_new->module = module;
722       *handle = handle_new;
723     }
724   else
725     {
726       /* Deallocate resources.  */
727       if (module)
728         _gcry_pk_module_release (module);
729     }
730
731   return gcry_error (err);
732 }
733
734 /* Destroys the handle HANDLE.  */
735 void
736 gcry_ac_close (gcry_ac_handle_t handle)
737 {
738   /* Release reference to pubkey module.  */
739   if (handle)
740     {
741       _gcry_pk_module_release (handle->module);
742       gcry_free (handle);
743     }
744 }
745
746 \f
747
748 /* 
749  * Key management.
750  */
751
752 /* Creates a new key of type TYPE, consisting of the MPI values
753    contained in the data set DATA and stores it in KEY.  */
754 gcry_error_t
755 gcry_ac_key_init (gcry_ac_key_t *key,
756                   gcry_ac_handle_t handle,
757                   gcry_ac_key_type_t type,
758                   gcry_ac_data_t data)
759 {
760   gcry_err_code_t err = GPG_ERR_NO_ERROR;
761   gcry_ac_data_t data_new = NULL;
762   gcry_sexp_t data_sexp = NULL;
763   gcry_ac_key_t key_new = NULL;
764
765   /* Allocate.  */
766   key_new = gcry_malloc (sizeof (struct gcry_ac_key));
767   if (! key_new)
768     err = gpg_err_code_from_errno (errno);
769
770   if (! err)
771     {
772       /* Create S-expression from data set.  */
773       err = gcry_ac_data_construct (ac_key_identifiers[type], 0, 0,
774                                     handle->algorithm_name, data, &data_sexp);
775     }
776
777   if (! err)
778     {
779       /* Copy data set.  */
780       err = gcry_ac_data_copy_internal (&data_new, data);
781     }
782
783   if (! err)
784     {
785       /* Done.  */
786       key_new->data_sexp = data_sexp;
787       key_new->data = data_new;
788       key_new->type = type;
789       *key = key_new;
790     }
791   else
792     {
793       /* Deallocate resources.  */
794       if (key_new)
795         gcry_free (key_new);
796       if (data_sexp)
797         gcry_sexp_release (data_sexp);
798     }
799
800   return gcry_error (err);
801 }
802
803 /* Generates a new key pair via the handle HANDLE of NBITS bits and
804    stores it in KEY_PAIR.  In case non-standard settings are wanted, a
805    pointer to a structure of type gcry_ac_key_spec_<algorithm>_t,
806    matching the selected algorithm, can be given as KEY_SPEC.  */
807 gcry_error_t
808 gcry_ac_key_pair_generate (gcry_ac_handle_t handle,
809                            gcry_ac_key_pair_t *key_pair,
810                            unsigned int nbits,
811                            void *key_spec)
812 {
813   gcry_err_code_t err = GPG_ERR_NO_ERROR;
814
815   gcry_ac_key_pair_t key_pair_new = NULL;
816
817   gcry_sexp_t genkey_sexp_request = NULL;
818   gcry_sexp_t genkey_sexp_reply = NULL;
819
820   char *genkey_format = NULL;
821   size_t genkey_format_n = 0;
822
823   void **arg_list = NULL;
824   size_t arg_list_n = 0;
825
826   unsigned int i = 0;
827
828   /* Allocate key pair.  */
829   key_pair_new = gcry_malloc (sizeof (struct gcry_ac_key_pair));
830   if (! key_pair_new)
831     err = gpg_err_code_from_errno (errno);
832
833   if (! err)
834     {
835       /* Allocate keys.  */
836       key_pair_new->secret = gcry_malloc (sizeof (struct gcry_ac_key));
837       key_pair_new->public = gcry_malloc (sizeof (struct gcry_ac_key));
838
839       if (! (key_pair_new->secret || key_pair_new->public))
840         err = gpg_err_code_from_errno (errno);
841       else
842         {
843           key_pair_new->secret->type = GCRY_AC_KEY_SECRET;
844           key_pair_new->public->type = GCRY_AC_KEY_PUBLIC;
845           key_pair_new->secret->data_sexp = NULL;
846           key_pair_new->public->data_sexp = NULL;
847           key_pair_new->secret->data = NULL;
848           key_pair_new->public->data = NULL;
849         }
850     }
851
852   if (! err)
853     {
854       /* Calculate size of the format string, that is used for
855          creating the request S-expression.  */
856       genkey_format_n = 23;
857
858       /* Respect any relevant algorithm specific commands.  */
859       if (key_spec)
860         for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
861           if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
862             genkey_format_n += 6;
863
864       /* Create format string.  */
865       genkey_format = gcry_malloc (genkey_format_n);
866       if (! genkey_format)
867         err = gpg_err_code_from_errno (errno);
868       else
869         {
870           /* Fill format string.  */
871           *genkey_format = 0;
872           strcat (genkey_format, "(genkey(%s(nbits%d)");
873           if (key_spec)
874             for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
875               if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
876                 strcat (genkey_format, "(%s%m)");
877           strcat (genkey_format, "))");
878         }
879     }
880
881   if (! err)
882     {
883       /* Build list of argument pointers, the algorithm name and the
884          nbits are needed always.  */
885       arg_list_n = 2;
886
887       /* Now the algorithm specific arguments.  */
888       if (key_spec)
889         for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
890           if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
891             arg_list_n += 2;
892
893       /* Allocate list.  */
894       arg_list = gcry_malloc (sizeof (void *) * arg_list_n);
895       if (! arg_list)
896         err = gpg_err_code_from_errno (errno);
897       else
898         {
899           /* Fill argument list. */
900           
901           int j;
902
903           arg_list[0] = (void *) &handle->algorithm_name;
904           arg_list[1] = (void *) &nbits;
905
906           if (key_spec)
907             for (j = 2, i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
908               if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
909                 {
910                   /* Add name of this specification flag and the
911                      according member of the spec strucuture.  */
912                   arg_list[j++] = (void *)(&gcry_ac_key_generate_specs[i].name);
913                   arg_list[j++] = (void *)
914                                   (((char *) key_spec)
915                                    + gcry_ac_key_generate_specs[i].offset);
916                 }
917         }
918     }
919
920   if (! err)
921     /* Construct final request S-expression.  */
922     err = gcry_err_code (gcry_sexp_build_array (&genkey_sexp_request, NULL,
923                                                genkey_format, arg_list));
924
925   if (! err)
926     /* Perform genkey operation.  */
927     err = gcry_err_code (gcry_pk_genkey (&genkey_sexp_reply,
928                                         genkey_sexp_request));
929
930   /* Split keys.  */
931   if (! err)
932     {
933       key_pair_new->secret->data_sexp = gcry_sexp_find_token (genkey_sexp_reply,
934                                                               "private-key", 0);
935       if (! key_pair_new->secret->data_sexp)
936         err = GPG_ERR_INTERNAL;
937     }
938   if (! err)
939     {
940       key_pair_new->public->data_sexp = gcry_sexp_find_token (genkey_sexp_reply,
941                                                               "public-key", 0);
942       if (! key_pair_new->public->data_sexp)
943         err = GPG_ERR_INTERNAL;
944     }
945
946   /* Extract key material.  */
947   if (! err)
948     err = gcry_ac_data_extract ("private-key", handle->algorithm_name,
949                                 key_pair_new->secret->data_sexp,
950                                 &key_pair_new->secret->data);
951   if (! err)
952     err = gcry_ac_data_extract ("public-key", handle->algorithm_name,
953                                 key_pair_new->public->data_sexp,
954                                 &key_pair_new->public->data);
955
956   /* Done.  */
957
958   if (! err)
959     *key_pair = key_pair_new;
960   else
961     {
962       /* Deallocate resources.  */
963
964       if (key_pair_new)
965         {
966           if (key_pair_new->secret)
967             gcry_ac_key_destroy (key_pair_new->secret);
968           if (key_pair_new->public)
969             gcry_ac_key_destroy (key_pair_new->public);
970
971           gcry_free (key_pair_new);
972         }
973
974       if (arg_list)
975         gcry_free (arg_list);
976
977       if (genkey_format)
978         gcry_free (genkey_format);
979
980       if (genkey_sexp_request)
981         gcry_sexp_release (genkey_sexp_request);
982       if (genkey_sexp_reply)
983         gcry_sexp_release (genkey_sexp_reply);
984     }
985
986   return gcry_error (err);
987 }
988
989 /* Returns the key of type WHICH out of the key pair KEY_PAIR.  */
990 gcry_ac_key_t
991 gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
992                           gcry_ac_key_type_t witch)
993 {
994   gcry_ac_key_t key = NULL;
995
996   switch (witch)
997     {
998     case GCRY_AC_KEY_SECRET:
999       key = key_pair->secret;
1000       break;
1001
1002     case GCRY_AC_KEY_PUBLIC:
1003       key = key_pair->public;
1004       break;
1005     }
1006
1007   return key;
1008 }
1009
1010 /* Destroys the key KEY.  */
1011 void
1012 gcry_ac_key_destroy (gcry_ac_key_t key)
1013 {
1014   int i;
1015
1016   if (key)
1017     {
1018       if (key->data)
1019         {
1020           for (i = 0; i < key->data->data_n; i++)
1021             if (key->data->data[i].mpi != NULL)
1022               gcry_mpi_release (key->data->data[i].mpi);
1023           gcry_free (key->data);
1024         }
1025       if (key->data_sexp)
1026         gcry_sexp_release (key->data_sexp);
1027       gcry_free (key);
1028     }
1029 }
1030
1031 /* Destroys the key pair KEY_PAIR.  */
1032 void
1033 gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair)
1034 {
1035   if (key_pair)
1036     {
1037       gcry_ac_key_destroy (key_pair->secret);
1038       gcry_ac_key_destroy (key_pair->public);
1039       gcry_free (key_pair);
1040     }
1041 }
1042
1043 /* Returns the data set contained in the key KEY.  */
1044 gcry_ac_data_t
1045 gcry_ac_key_data_get (gcry_ac_key_t key)
1046 {
1047   return  key->data;
1048 }
1049
1050 /* Verifies that the key KEY is sane.  */
1051 gcry_error_t
1052 gcry_ac_key_test (gcry_ac_key_t key)
1053 {
1054   gcry_err_code_t err;
1055
1056   err = gcry_err_code (gcry_pk_testkey (key->data_sexp));
1057
1058   return gcry_error (err);
1059 }
1060
1061 /* Stores the number of bits of the key KEY in NBITS.  */
1062 gcry_error_t
1063 gcry_ac_key_get_nbits (gcry_ac_key_t key, unsigned int *nbits)
1064 {
1065   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1066   unsigned int n;
1067
1068   n = gcry_pk_get_nbits (key->data_sexp);
1069   if (n)
1070     *nbits = n;
1071   else
1072     err = GPG_ERR_PUBKEY_ALGO;
1073
1074   return gcry_error (err);
1075 }
1076
1077 /* Writes the 20 byte long key grip of the key KEY to KEY_GRIP.  */
1078 gcry_error_t
1079 gcry_ac_key_get_grip (gcry_ac_key_t key, unsigned char *key_grip)
1080 {
1081   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1082   unsigned char *ret;
1083
1084   ret = gcry_pk_get_keygrip (key->data_sexp, key_grip);
1085   if (! ret)
1086     err = GPG_ERR_INV_OBJ;
1087
1088   return gcry_error (err);
1089 }
1090
1091 \f
1092
1093 /* 
1094  * Functions performing cryptographic operations.
1095  */
1096
1097 /* Encrypts the plain text MPI value DATA_PLAIN with the key public
1098    KEY under the control of the flags FLAGS and stores the resulting
1099    data set into DATA_ENCRYPTED.  */
1100 gcry_error_t
1101 gcry_ac_data_encrypt (gcry_ac_handle_t handle,
1102                       unsigned int flags,
1103                       gcry_ac_key_t key,
1104                       gcry_mpi_t data_plain,
1105                       gcry_ac_data_t *data_encrypted)
1106 {
1107   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1108   gcry_sexp_t sexp_request = NULL;
1109   gcry_sexp_t sexp_reply = NULL;
1110   char *request_format = NULL;
1111   size_t request_format_n = 0;
1112   gcry_ac_data_t data;
1113   
1114   int i;
1115
1116   if (key->type != GCRY_AC_KEY_PUBLIC)
1117     err = GPG_ERR_WRONG_KEY_USAGE;
1118
1119   if (! err)
1120     {
1121       /* Calculate request format string.  */
1122
1123       request_format_n += 23;
1124       for (i = 0; gcry_ac_flags[i].number; i++)
1125         if (flags & gcry_ac_flags[i].number)
1126           request_format_n += strlen (gcry_ac_flags[i].string) + 1;
1127
1128       /* Allocate request format string.  */
1129       request_format = gcry_malloc (request_format_n);
1130       if (! request_format)
1131         err = gpg_err_code_from_errno (errno);
1132     }
1133
1134   if (! err)
1135     {
1136       /* Fill format string.  */
1137       *request_format = 0;
1138       strcat (request_format, "(data(flags");
1139       for (i = 0; gcry_ac_flags[i].number; i++)
1140         if (flags & gcry_ac_flags[i].number)
1141           {
1142             strcat (request_format, " ");
1143             strcat (request_format, gcry_ac_flags[i].string);
1144           }
1145       strcat (request_format, ")(value%m))");
1146
1147       /* Create S-expression.  */
1148       err = gcry_sexp_build (&sexp_request, NULL,
1149                              request_format, data_plain);
1150     }
1151
1152   if (! err)
1153     /* Encrypt.  */
1154     err = gcry_pk_encrypt (&sexp_reply, sexp_request, key->data_sexp);
1155
1156   if (! err)
1157     /* Extract data.  */
1158     err = gcry_ac_data_extract ("enc-val", handle->algorithm_name,
1159                                 sexp_reply, &data);
1160
1161   /* Deallocate resources.  */
1162
1163   if (sexp_request)
1164     gcry_sexp_release (sexp_request);
1165   if (sexp_reply)
1166     gcry_sexp_release (sexp_reply);
1167
1168   if (! err)
1169     /* Copy out.  */
1170     *data_encrypted = data;
1171
1172   return gcry_error (err);
1173 }
1174
1175 /* Decrypts the encrypted data contained in the data set
1176    DATA_ENCRYPTED with the secret key KEY under the control of the
1177    flags FLAGS and stores the resulting plain text MPI value in
1178    DATA_PLAIN.  */
1179 gcry_error_t
1180 gcry_ac_data_decrypt (gcry_ac_handle_t handle,
1181                       unsigned int flags,
1182                       gcry_ac_key_t key,
1183                       gcry_mpi_t *data_plain,
1184                       gcry_ac_data_t data_encrypted)
1185 {
1186   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1187   gcry_mpi_t data_decrypted = NULL;
1188   gcry_sexp_t sexp_request = NULL;
1189   gcry_sexp_t sexp_reply = NULL;
1190
1191   if (key->type != GCRY_AC_KEY_SECRET)
1192     err = GPG_ERR_WRONG_KEY_USAGE;
1193
1194   if (! err)
1195     /* Create S-expression from data.  */
1196     err = gcry_ac_data_construct ("enc-val", 1, flags, handle->algorithm_name,
1197                                   data_encrypted, &sexp_request);
1198
1199   if (! err)
1200     /* Decrypt.  */
1201     err = gcry_pk_decrypt (&sexp_reply, sexp_request, key->data_sexp);
1202
1203   if (! err)
1204     {
1205       /* Extract plain text. */
1206
1207       gcry_sexp_t l;
1208
1209       l = gcry_sexp_find_token (sexp_reply, "value", 0);
1210       if (! l)
1211         err = GPG_ERR_GENERAL;
1212       else
1213         {
1214           data_decrypted = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
1215           if (! data_decrypted)
1216             err = GPG_ERR_GENERAL;
1217           gcry_sexp_release (l);
1218         }
1219     }
1220
1221   /* Done.  */
1222
1223   if (err)
1224     {
1225       /* Deallocate resources.  */
1226       if (sexp_request)
1227         gcry_sexp_release (sexp_request);
1228       if (sexp_reply)
1229         gcry_sexp_release (sexp_reply);
1230     }
1231   else
1232     *data_plain = data_decrypted;
1233
1234   return gcry_error (err);
1235
1236 }
1237
1238 /* Signs the data contained in DATA with the secret key KEY and stores
1239    the resulting signature data set in DATA_SIGNATURE.  */
1240 gcry_error_t
1241 gcry_ac_data_sign (gcry_ac_handle_t handle,
1242                    gcry_ac_key_t key,
1243                    gcry_mpi_t data,
1244                    gcry_ac_data_t *data_signature)
1245 {
1246   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1247   gcry_sexp_t sexp_request = NULL;
1248   gcry_sexp_t sexp_reply = NULL;
1249   gcry_ac_data_t ac_data;
1250
1251   if (key->type != GCRY_AC_KEY_SECRET)
1252     err = GPG_ERR_WRONG_KEY_USAGE;
1253
1254   if (! err)
1255     /* Create S-expression holding the data.  */
1256     err = gcry_sexp_build (&sexp_request, NULL,
1257                            "(data(flags)(value%m))", data);
1258   if (! err)
1259     /* Sign.  */
1260     err = gcry_pk_sign (&sexp_reply, sexp_request, key->data_sexp);
1261
1262   if (! err)
1263     /* Extract data.  */
1264     err = gcry_ac_data_extract ("sig-val", handle->algorithm_name,
1265                                 sexp_reply, &ac_data);
1266
1267   /* Done.  */
1268
1269   if (sexp_request)
1270     gcry_sexp_release (sexp_request);
1271   if (sexp_reply)
1272     gcry_sexp_release (sexp_reply);
1273
1274   if (! err)
1275     *data_signature = ac_data;
1276
1277   return gcry_error (err);
1278 }
1279
1280 /* Verifies that the signature contained in the data set
1281    DATA_SIGNATURE is indeed the result of signing the data contained
1282    in DATA with the secret key belonging to the public key KEY.  */
1283 gcry_error_t
1284 gcry_ac_data_verify (gcry_ac_handle_t handle,
1285                      gcry_ac_key_t key,
1286                      gcry_mpi_t data,
1287                      gcry_ac_data_t data_signature)
1288 {
1289   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1290   gcry_sexp_t sexp_request = NULL;
1291   gcry_sexp_t sexp_data = NULL;
1292
1293   if (key->type != GCRY_AC_KEY_PUBLIC)
1294     err = GPG_ERR_WRONG_KEY_USAGE;
1295
1296   if (! err)
1297     /* Construct S-expression holding the signature data.  */
1298     err = gcry_ac_data_construct ("sig-val", 1, 0, handle->algorithm_name,
1299                                   data_signature, &sexp_request);
1300
1301   if (! err)
1302     /* Construct S-expression holding the data.  */
1303     err = gcry_sexp_build (&sexp_data, NULL,
1304                            "(data(flags)(value%m))", data);
1305
1306   if (! err)
1307     /* Verify signature.  */
1308     err = gcry_pk_verify (sexp_request, sexp_data, key->data_sexp);
1309
1310   /* Done.  */
1311
1312   if (sexp_request)
1313     gcry_sexp_release (sexp_request);
1314   if (sexp_data)
1315     gcry_sexp_release (sexp_data);
1316
1317   return gcry_error (err);
1318 }
1319
1320 \f
1321
1322 /* 
1323  * General functions.
1324  */
1325
1326 /* Stores the textual representation of the algorithm whose id is
1327    given in ALGORITHM in NAME.  */
1328 gcry_error_t
1329 gcry_ac_id_to_name (gcry_ac_id_t algorithm, const char **name)
1330 {
1331   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1332   const char *n;
1333
1334   n = gcry_pk_algo_name (algorithm);
1335   if (*n)
1336     *name = n;
1337   else
1338     err = GPG_ERR_PUBKEY_ALGO;
1339
1340   return gcry_error (err);
1341 }
1342
1343 /* Stores the numeric ID of the algorithm whose textual representation
1344    is contained in NAME in ALGORITHM.  */
1345 gcry_error_t
1346 gcry_ac_name_to_id (const char *name, gcry_ac_id_t *algorithm)
1347 {
1348   gcry_err_code_t err = GPG_ERR_NO_ERROR;
1349   int algo;
1350
1351   algo = gcry_pk_map_name (name);
1352   if (algo)
1353     *algorithm = algo;
1354   else
1355     err = GPG_ERR_PUBKEY_ALGO;
1356     
1357   return gcry_error (err);
1358 }