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