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