2003-07-01 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 /* Returns a new, empty data set 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 /* Destroy 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 there is already
512    a value with that label, replace it, otherwise add it.  */
513 gpg_error_t
514 gcry_ac_data_set (gcry_ac_data_t data,
515                   const char *name, gcry_mpi_t mpi)
516 {
517   gpg_err_code_t err = GPG_ERR_NO_ERROR;
518   gcry_ac_mpi_t *ac_mpi;
519
520   gcry_ac_data_search (data, name, &ac_mpi);
521   if (ac_mpi)
522     {
523       /* An entry for NAME does already exist, replace it.  */
524       gcry_mpi_release (ac_mpi->mpi);
525       ac_mpi->mpi = mpi;
526     }
527   else
528     {
529       /* Create a new entry.  */
530
531       gcry_mpi_t mpi_cp = NULL;
532       char *name_cp = NULL;
533
534       name_cp = strdup (name);
535       if (name_cp)
536         mpi_cp = gcry_mpi_copy (mpi);
537       if (! (name_cp && mpi_cp))
538         err = gpg_err_code_from_errno (errno);
539
540       if (! err)
541         err = gcry_ac_data_add (data, name_cp, mpi_cp);
542
543       if (err)
544         {
545           if (name_cp)
546             gcry_free (name_cp);
547           if (mpi_cp)
548             gcry_mpi_release (mpi_cp);
549         }
550     }
551
552   return gpg_error (err);
553 }
554
555 /* Return the number of named MPI values inside of the data set
556    DATA.  */
557 unsigned int
558 gcry_ac_data_length (gcry_ac_data_t data)
559 {
560   return data->data_n;
561 }
562
563 /* Store the value labelled with NAME found in DATA in MPI or NULL if
564    a value with that label was not found.  */
565 gpg_error_t
566 gcry_ac_data_get_name (gcry_ac_data_t data, const char *name,
567                        gcry_mpi_t *mpi)
568 {
569   gpg_err_code_t err = GPG_ERR_NO_DATA;
570   gcry_mpi_t mpi_found = NULL;
571   int i;
572   
573   for (i = 0; i < data->data_n && (! mpi_found); i++)
574     if (! strcmp (data->data[i].name, name))
575       {
576         mpi_found = data->data[i].mpi;
577         err = GPG_ERR_NO_ERROR;
578       }
579
580   if (! err)
581     *mpi = mpi_found;
582
583   return gpg_error (err);
584 }
585
586 /* Return the MPI value with index INDEX contained in the data set
587    DATA.  */
588 gpg_error_t
589 gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int index,
590                         const char **name, gcry_mpi_t *mpi)
591 {
592   gpg_err_code_t err = GPG_ERR_NO_ERROR;
593
594   if (index < data->data_n)
595     {
596       if (name)
597         *name = data->data[index].name;
598       if (mpi)
599         *mpi = data->data[index].mpi;
600     }
601   else
602     err = GPG_ERR_NO_DATA;
603
604   return gpg_error (err);
605 }
606
607 /* Destroy any values contained in the data set DATA.  */
608 void
609 gcry_ac_data_clear (gcry_ac_data_t data)
610 {
611   gcry_free (data->data);
612   data->data = NULL;
613   data->data_n = 0;
614 }
615
616 \f
617
618 /*
619  * Handle management.
620  */
621
622 /* Create a new ac handle.  */
623 gpg_error_t
624 gcry_ac_open (gcry_ac_handle_t *handle,
625               gcry_ac_id_t algorithm, unsigned int flags)
626 {
627   gpg_err_code_t err = GPG_ERR_NO_ERROR;
628   gcry_module_t *module = NULL;
629   gcry_ac_handle_t handle_new;
630   const char *algorithm_name;
631
632   /* Get name.  */
633   algorithm_name = gcry_pk_algo_name (algorithm);
634   if (! *algorithm_name)
635     err = GPG_ERR_PUBKEY_ALGO;
636
637   if (! err)
638     /* Acquire reference to the pubkey module.  */
639     err = _gcry_pk_module_lookup (algorithm, &module);
640   
641   if (! err)
642     {
643       /* Allocate.  */
644       handle_new = gcry_malloc (sizeof (struct gcry_ac_handle));
645       if (! handle_new)
646         err = gpg_err_code_from_errno (errno);
647     }
648
649   if (! err)
650     {
651       /* Done.  */
652       handle_new->algorithm = algorithm;
653       handle_new->algorithm_name = algorithm_name;
654       handle_new->flags = flags;
655       handle_new->module = module;
656       *handle = handle_new;
657     }
658   else
659     {
660       /* Deallocate resources.  */
661       if (module)
662         _gcry_pk_module_release (module);
663     }
664
665   return gpg_error (err);
666 }
667
668 /* Destroy an ac handle.  */
669 void
670 gcry_ac_close (gcry_ac_handle_t handle)
671 {
672   /* Release reference to pubkey module.  */
673   _gcry_pk_module_release (handle->module);
674   gcry_free (handle);
675 }
676
677 \f
678
679 /* 
680  * Key management.
681  */
682
683 /* Initialize a key from a given data set.  */
684 gpg_error_t
685 gcry_ac_key_init (gcry_ac_key_t *key,
686                   gcry_ac_handle_t handle,
687                   gcry_ac_key_type_t type,
688                   gcry_ac_data_t data)
689 {
690   gpg_err_code_t err = GPG_ERR_NO_ERROR;
691   gcry_ac_data_t data_new = NULL;
692   gcry_sexp_t data_sexp = NULL;
693   gcry_ac_key_t key_new = NULL;
694
695   /* Allocate.  */
696   key_new = gcry_malloc (sizeof (struct gcry_ac_key));
697   if (! key_new)
698     err = gpg_err_code_from_errno (errno);
699
700   if (! err)
701     /* Create S-expression from data set.  */
702     err = gcry_ac_data_construct (ac_key_identifiers[type], 0,
703                                   handle->algorithm_name, data, &data_sexp);
704
705   if (! err)
706     /* Copy data set.  */
707     err = gcry_ac_data_copy (&data_new, data);
708
709   if (! err)
710     {
711       /* Done.  */
712       key_new->data_sexp = data_sexp;
713       key_new->data = data_new;
714       key_new->type = type;
715       *key = key_new;
716     }
717   else
718     {
719       /* Deallocate resources.  */
720       if (key_new)
721         gcry_free (key_new);
722       if (data_sexp)
723         gcry_sexp_release (data_sexp);
724     }
725
726   return gpg_error (err);
727 }
728
729 /* Generate a new key pair.  */
730 gpg_error_t
731 gcry_ac_key_pair_generate (gcry_ac_handle_t handle,
732                            gcry_ac_key_pair_t *key_pair,
733                            unsigned int nbits,
734                            void *key_spec)
735 {
736   gpg_err_code_t err = GPG_ERR_NO_ERROR;
737
738   gcry_ac_key_pair_t key_pair_new = NULL;
739
740   gcry_sexp_t genkey_sexp_request = NULL;
741   gcry_sexp_t genkey_sexp_reply = NULL;
742
743   char *genkey_format = NULL;
744   size_t genkey_format_n = 0;
745
746   void **arg_list = NULL;
747   size_t arg_list_n = 0;
748
749   unsigned int i = 0;
750
751   /* Allocate key pair.  */
752   key_pair_new = gcry_malloc (sizeof (struct gcry_ac_key_pair));
753   if (! key_pair_new)
754     err = gpg_err_code_from_errno (errno);
755
756   if (! err)
757     {
758       /* Allocate keys.  */
759       key_pair_new->secret = gcry_malloc (sizeof (struct gcry_ac_key));
760       key_pair_new->public = gcry_malloc (sizeof (struct gcry_ac_key));
761
762       if (! (key_pair_new->secret || key_pair_new->public))
763         err = gpg_err_code_from_errno (errno);
764       else
765         {
766           key_pair_new->secret->type = GCRY_AC_KEY_SECRET;
767           key_pair_new->public->type = GCRY_AC_KEY_PUBLIC;
768           key_pair_new->secret->data_sexp = NULL;
769           key_pair_new->public->data_sexp = NULL;
770           key_pair_new->secret->data = NULL;
771           key_pair_new->public->data = NULL;
772         }
773     }
774
775   if (! err)
776     {
777       /* Calculate size of the format string, that is used for
778          creating the request S-expression.  */
779       genkey_format_n = 22;
780
781       /* Respect any relevant algorithm specific commands.  */
782       if (key_spec)
783         for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
784           if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
785             genkey_format_n += 4;
786
787       /* Create format string.  */
788       genkey_format = gcry_malloc (genkey_format_n);
789       if (! genkey_format)
790         err = gpg_err_code_from_errno (errno);
791       else
792         {
793           /* Fill format string.  */
794           *genkey_format = 0;
795           strcat (genkey_format, "(genkey(%s(nbits%d)");
796           if (key_spec)
797             for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
798               if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
799                 strcat (genkey_format, "(%s%m)");
800           strcat (genkey_format, "))");
801         }
802     }
803
804   if (! err)
805     {
806       /* Build list of argument pointers, the algorithm name and the
807          nbits are needed always.  */
808       arg_list_n = 2;
809
810       /* Now the algorithm specific arguments.  */
811       if (key_spec)
812         for (i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
813           if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
814             arg_list_n += 2;
815
816       /* Allocate list.  */
817       arg_list = gcry_malloc (sizeof (void *) * arg_list_n);
818       if (! arg_list)
819         err = gpg_err_code_from_errno (errno);
820       else
821         {
822           /* Fill argument list. */
823           
824           int j;
825
826           arg_list[0] = (void *) &handle->algorithm_name;
827           arg_list[1] = (void *) &nbits;
828
829           if (key_spec)
830             for (j = 2, i = 0; gcry_ac_key_generate_specs[i].algorithm; i++)
831               if (handle->algorithm == gcry_ac_key_generate_specs[i].algorithm)
832                 {
833                   /* Add name of this specification flag and the
834                      according member of the spec strucuture.  */
835                   arg_list[j++] = (void *) (&gcry_ac_key_generate_specs[i].name);
836                   arg_list[j++] = (void *) (((char *) key_spec)
837                                             + gcry_ac_key_generate_specs[i].offset);
838                 }
839         }
840     }
841
842   if (! err)
843     /* Construct final request S-expression.  */
844     err = gpg_err_code (gcry_sexp_build_array (&genkey_sexp_request, NULL,
845                                                genkey_format, arg_list));
846
847   if (! err)
848     /* Perform genkey operation.  */
849     err = gpg_err_code (gcry_pk_genkey (&genkey_sexp_reply,
850                                         genkey_sexp_request));
851
852   /* Split keys.  */
853   if (! err)
854     {
855       key_pair_new->secret->data_sexp = gcry_sexp_find_token (genkey_sexp_reply,
856                                                               "private-key", 0);
857       if (! key_pair_new->secret->data_sexp)
858         err = GPG_ERR_INTERNAL;
859     }
860   if (! err)
861     {
862       key_pair_new->public->data_sexp = gcry_sexp_find_token (genkey_sexp_reply,
863                                                               "public-key", 0);
864       if (! key_pair_new->public->data_sexp)
865         err = GPG_ERR_INTERNAL;
866     }
867
868   /* Extract key material.  */
869   if (! err)
870     err = gcry_ac_data_extract ("private-key", handle->algorithm_name,
871                                 key_pair_new->secret->data_sexp,
872                                 &key_pair_new->secret->data);
873   if (! err)
874     err = gcry_ac_data_extract ("public-key", handle->algorithm_name,
875                                 key_pair_new->public->data_sexp,
876                                 &key_pair_new->public->data);
877
878   /* Done.  */
879
880   if (! err)
881     *key_pair = key_pair_new;
882   else
883     {
884       /* Deallocate resources.  */
885
886       if (key_pair_new)
887         {
888           if (key_pair_new->secret)
889             gcry_ac_key_destroy (key_pair_new->secret);
890           if (key_pair_new->public)
891             gcry_ac_key_destroy (key_pair_new->public);
892
893           gcry_free (key_pair_new);
894         }
895
896       if (arg_list)
897         gcry_free (arg_list);
898
899       if (genkey_format)
900         gcry_free (genkey_format);
901
902       if (genkey_sexp_request)
903         gcry_sexp_release (genkey_sexp_request);
904       if (genkey_sexp_reply)
905         gcry_sexp_release (genkey_sexp_reply);
906     }
907
908   return gpg_error (err);
909 }
910
911 /* Returns a specified key from a key pair.  */
912 gcry_ac_key_t
913 gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair,
914                           gcry_ac_key_type_t witch)
915 {
916   gcry_ac_key_t key = NULL;
917
918   switch (witch)
919     {
920     case GCRY_AC_KEY_SECRET:
921       key = key_pair->secret;
922       break;
923
924     case GCRY_AC_KEY_PUBLIC:
925       key = key_pair->public;
926       break;
927     }
928
929   return key;
930 }
931
932 /* Destroy a key.  */
933 void
934 gcry_ac_key_destroy (gcry_ac_key_t key)
935 {
936   int i;
937
938   if (key->data)
939     {
940       for (i = 0; i < key->data->data_n; i++)
941         if (key->data->data[i].mpi != NULL)
942           gcry_mpi_release (key->data->data[i].mpi);
943       gcry_free (key->data);
944     }
945   if (key->data_sexp)
946     gcry_sexp_release (key->data_sexp);
947   gcry_free (key);
948 }
949
950 /* Destroy a key pair.  */
951 void
952 gcry_ac_key_pair_destroy (gcry_ac_key_pair_t key_pair)
953 {
954   gcry_ac_key_destroy (key_pair->secret);
955   gcry_ac_key_destroy (key_pair->public);
956   gcry_free (key_pair);
957 }
958
959 /* Verify that the key KEY is sane.  */
960 gpg_error_t
961 gcry_ac_key_test (gcry_ac_key_t key)
962 {
963   gpg_err_code_t err = GPG_ERR_NO_ERROR;
964
965   err = gpg_err_code (gcry_pk_testkey (key->data_sexp));
966
967   return gpg_error (err);
968 }
969
970 /* Return the number of bits of the key KEY in NBITS.  */
971 gpg_error_t
972 gcry_ac_key_get_nbits (gcry_ac_key_t key, unsigned int *nbits)
973 {
974   gpg_err_code_t err = GPG_ERR_NO_ERROR;
975   unsigned int n;
976
977   n = gcry_pk_get_nbits (key->data_sexp);
978   if (n)
979     *nbits = n;
980   else
981     err = GPG_ERR_PUBKEY_ALGO;
982
983   return gpg_error (err);
984 }
985
986 /* Write the 20 byte long key grip of the key KEY to KEY_GRIP.  */
987 gpg_error_t
988 gcry_ac_key_get_grip (gcry_ac_key_t key, unsigned char *key_grip)
989 {
990   gpg_err_code_t err = GPG_ERR_NO_ERROR;
991   unsigned char *ret;
992
993   ret = gcry_pk_get_keygrip (key->data_sexp, key_grip);
994   if (! ret)
995     err = GPG_ERR_INTERNAL;     /* FIXME.  */
996
997   return gpg_error (err);
998 }
999
1000 \f
1001
1002 /* 
1003  * Functions performing cryptographic operations.
1004  */
1005
1006 /* Encrypt the plain text MPI value DATA_PLAIN with the key KEY under
1007    the control of the flags FLAGS and store the resulting data set
1008    into DATA_ENCRYPTED.  */
1009 gpg_error_t
1010 gcry_ac_data_encrypt (gcry_ac_handle_t handle,
1011                       unsigned int flags,
1012                       gcry_ac_key_t key,
1013                       gcry_mpi_t data_plain,
1014                       gcry_ac_data_t *data_encrypted)
1015 {
1016   gpg_err_code_t err = GPG_ERR_NO_ERROR;
1017   gcry_sexp_t sexp_request = NULL;
1018   gcry_sexp_t sexp_reply = NULL;
1019   char *request_format = NULL;
1020   size_t request_format_n = 0;
1021   gcry_ac_data_t data;
1022   
1023   int i;
1024
1025   if (key->type != GCRY_AC_KEY_PUBLIC)
1026     err = GPG_ERR_WRONG_KEY_USAGE;
1027
1028   if (! err)
1029     {
1030       /* Calculate request format string.  */
1031
1032       request_format_n += 23;
1033       for (i = 0; gcry_ac_flags[i].number; i++)
1034         if (flags & gcry_ac_flags[i].number)
1035           request_format_n += strlen (gcry_ac_flags[i].string) + 1;
1036
1037       /* Allocate request format string.  */
1038       request_format = gcry_malloc (request_format_n);
1039       if (! request_format)
1040         err = gpg_err_code_from_errno (errno);
1041     }
1042
1043   if (! err)
1044     {
1045       /* Fill format string.  */
1046       *request_format = 0;
1047       strcat (request_format, "(data(flags");
1048       for (i = 0; gcry_ac_flags[i].number; i++)
1049         if (flags & gcry_ac_flags[i].number)
1050           {
1051             strcat (request_format, " ");
1052             strcat (request_format, gcry_ac_flags[i].string);
1053           }
1054       strcat (request_format, ")(value%m))");
1055
1056       /* Create S-expression.  */
1057       err = gcry_sexp_build (&sexp_request, NULL,
1058                              request_format, data_plain);
1059     }
1060
1061   if (! err)
1062     /* Encrypt.  */
1063     err = gcry_pk_encrypt (&sexp_reply, sexp_request, key->data_sexp);
1064
1065   if (! err)
1066     /* Extract data.  */
1067     err = gcry_ac_data_extract ("enc-val", handle->algorithm_name,
1068                                 sexp_reply, &data);
1069
1070   /* Deallocate resources.  */
1071
1072   if (sexp_request)
1073     gcry_sexp_release (sexp_request);
1074   if (sexp_reply)
1075     gcry_sexp_release (sexp_reply);
1076
1077   if (! err)
1078     /* Copy out.  */
1079     *data_encrypted = data;
1080
1081   return gpg_error (err);
1082 }
1083
1084 /* Decrypt the decrypted data contained in the data set DATA_ENCRYPTED
1085    with the key KEY under the control of the flags FLAGS and store the
1086    resulting plain text MPI value in DATA_PLAIN.  */
1087 gpg_error_t
1088 gcry_ac_data_decrypt (gcry_ac_handle_t handle,
1089                       unsigned int flags,
1090                       gcry_ac_key_t key,
1091                       gcry_mpi_t *data_plain,
1092                       gcry_ac_data_t data_encrypted)
1093 {
1094   gpg_err_code_t err = GPG_ERR_NO_ERROR;
1095   gcry_mpi_t data_decrypted = NULL;
1096   gcry_sexp_t sexp_request = NULL;
1097   gcry_sexp_t sexp_reply = NULL;
1098
1099   if (key->type != GCRY_AC_KEY_SECRET)
1100     err = GPG_ERR_WRONG_KEY_USAGE;
1101
1102   if (! err)
1103     /* Create S-expression from data.  */
1104     err = gcry_ac_data_construct ("enc-val", flags, handle->algorithm_name,
1105                                   data_encrypted, &sexp_request);
1106
1107   if (! err)
1108     /* Decrypt.  */
1109     err = gcry_pk_decrypt (&sexp_reply, sexp_request, key->data_sexp);
1110
1111   if (! err)
1112     {
1113       /* Extract plain text. */
1114
1115       gcry_sexp_t l;
1116
1117       l = gcry_sexp_find_token (sexp_reply, "value", 0);
1118       if (! l)
1119         err = GPG_ERR_GENERAL;
1120       else
1121         {
1122           data_decrypted = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG);
1123           if (! data_decrypted)
1124             err = GPG_ERR_GENERAL;
1125           gcry_sexp_release (l);
1126         }
1127     }
1128
1129   /* Done.  */
1130
1131   if (err)
1132     {
1133       /* Deallocate resources.  */
1134       if (sexp_request)
1135         gcry_sexp_release (sexp_request);
1136       if (sexp_reply)
1137         gcry_sexp_release (sexp_reply);
1138     }
1139   else
1140     *data_plain = data_decrypted;
1141
1142   return gpg_error (err);
1143
1144 }
1145
1146 /* Sign the data contained in DATA with the key KEY and store the
1147    resulting signature in the data set DATA_SIGNATURE.  */
1148 gpg_error_t
1149 gcry_ac_data_sign (gcry_ac_handle_t handle,
1150                    gcry_ac_key_t key,
1151                    gcry_mpi_t data,
1152                    gcry_ac_data_t *data_signature)
1153 {
1154   gpg_err_code_t err = GPG_ERR_NO_ERROR;
1155   gcry_sexp_t sexp_request = NULL;
1156   gcry_sexp_t sexp_reply = NULL;
1157   gcry_ac_data_t ac_data;
1158
1159   if (key->type != GCRY_AC_KEY_SECRET)
1160     err = GPG_ERR_WRONG_KEY_USAGE;
1161
1162   if (! err)
1163     /* Create S-expression holding the data.  */
1164     err = gcry_sexp_build (&sexp_request, NULL,
1165                            "(data(flags)(value%m))", data);
1166   if (! err)
1167     /* Sign.  */
1168     err = gcry_pk_sign (&sexp_reply, sexp_request, key->data_sexp);
1169
1170   if (! err)
1171     /* Extract data.  */
1172     err = gcry_ac_data_extract ("sig-val", handle->algorithm_name,
1173                                 sexp_reply, &ac_data);
1174
1175   /* Done.  */
1176
1177   if (sexp_request)
1178     gcry_sexp_release (sexp_request);
1179   if (sexp_reply)
1180     gcry_sexp_release (sexp_reply);
1181
1182   if (! err)
1183     *data_signature = ac_data;
1184
1185   return gpg_error (err);
1186 }
1187
1188 /* Verify that the signature contained in the data set DATA_SIGNATURE
1189    is indeed the result of signing the data contained in DATA with the
1190    secret key belonging to the public key KEY.  */
1191 gpg_error_t
1192 gcry_ac_data_verify (gcry_ac_handle_t handle,
1193                      gcry_ac_key_t key,
1194                      gcry_mpi_t data,
1195                      gcry_ac_data_t data_signature)
1196 {
1197   gpg_err_code_t err = GPG_ERR_NO_ERROR;
1198   gcry_sexp_t sexp_request = NULL;
1199   gcry_sexp_t sexp_data = NULL;
1200
1201   if (key->type != GCRY_AC_KEY_PUBLIC)
1202     err = GPG_ERR_WRONG_KEY_USAGE;
1203
1204   if (! err)
1205     /* Construct S-expression holding the signature data.  */
1206     err = gcry_ac_data_construct ("sig-val", 0, handle->algorithm_name,
1207                                   data_signature, &sexp_request);
1208
1209   if (! err)
1210     /* Construct S-expression holding the data.  */
1211     err = gcry_sexp_build (&sexp_data, NULL,
1212                            "(data(flags)(value%m))", data);
1213
1214   if (! err)
1215     /* Verify signature.  */
1216     err = gcry_pk_verify (sexp_request, sexp_data, key->data_sexp);
1217
1218   /* Done.  */
1219
1220   if (sexp_request)
1221     gcry_sexp_release (sexp_request);
1222   if (sexp_data)
1223     gcry_sexp_release (sexp_data);
1224
1225   return gpg_error (err);
1226 }
1227
1228 \f
1229
1230 /* 
1231  * General functions.
1232  */
1233
1234 /* Store the textual representation of the algorithm whose id is given
1235    in ALGORITHM in NAME.  */
1236 gpg_error_t
1237 gcry_ac_id_to_name (gcry_ac_id_t algorithm, const char **name)
1238 {
1239   gpg_err_code_t err = GPG_ERR_NO_ERROR;
1240   const char *n;
1241
1242   n = gcry_pk_algo_name (algorithm);
1243   if (*n)
1244     *name = n;
1245   else
1246     err = GPG_ERR_PUBKEY_ALGO;
1247
1248   return gpg_error (err);
1249 }
1250
1251 /* Store the numeric ID of the algorithm whose textual representation
1252    is contained in NAME in ALGORITHM.  */
1253 gpg_error_t
1254 gcry_ac_name_to_id (const char *name, gcry_ac_id_t *algorithm)
1255 {
1256   gpg_err_code_t err = GPG_ERR_NO_ERROR;
1257   int algo;
1258
1259   algo = gcry_pk_map_name (name);
1260   if (algo)
1261     *algorithm = algo;
1262   else
1263     err = GPG_ERR_PUBKEY_ALGO;
1264     
1265   return gpg_error (err);
1266 }