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