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