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