Diffstat (limited to 'pwmanager/libcrypt/cipher/ac.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | pwmanager/libcrypt/cipher/ac.c | 1390 |
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. */ | ||
40 | struct 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. */ | ||
52 | static const char *ac_key_identifiers[] = | ||
53 | { | ||
54 | "private-key", | ||
55 | "public-key", | ||
56 | }; | ||
57 | |||
58 | /* These specifications are needed for key-pair generation; the caller | ||
59 | is allowed to pass additional, algorithm-specific `specs' to | ||
60 | gcry_ac_key_pair_generate. This list is used for decoding the | ||
61 | provided values according to the selected algorithm. */ | ||
62 | struct gcry_ac_key_generate_spec | ||
63 | { | ||
64 | int algorithm; /* Algorithm for which this flag is | ||
65 | relevant. */ | ||
66 | const char *name; /* Name of this flag. */ | ||
67 | size_t offset; /* Offset in the cipher-specific spec | ||
68 | structure at which the MPI value | ||
69 | associated with this flag is to be | ||
70 | found. */ | ||
71 | } gcry_ac_key_generate_specs[] = | ||
72 | { | ||
73 | { GCRY_AC_RSA, "rsa-use-e", offsetof (gcry_ac_key_spec_rsa_t, e) }, | ||
74 | { 0 }, | ||
75 | }; | ||
76 | |||
77 | /* Handle structure. */ | ||
78 | struct gcry_ac_handle | ||
79 | { | ||
80 | int algorithm; /* Algorithm ID associated with this | ||
81 | handle. */ | ||
82 | const char *algorithm_name;/* Name of the algorithm. */ | ||
83 | unsigned int flags; /* Flags, not used yet. */ | ||
84 | gcry_module_t module; /* Reference to the algorithm | ||
85 | module. */ | ||
86 | }; | ||
87 | |||
88 | /* A named MPI value. */ | ||
89 | typedef struct gcry_ac_mpi | ||
90 | { | ||
91 | const char *name; /* 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. */ | ||
97 | struct 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. */ | ||
104 | struct 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. */ | ||
112 | struct 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. */ | ||
125 | static gcry_err_code_t | ||
126 | gcry_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. */ | ||
212 | static gcry_err_code_t | ||
213 | gcry_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>)) */ | ||
365 | static gcry_err_code_t | ||
366 | gcry_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. */ | ||
476 | gcry_error_t | ||
477 | gcry_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. */ | ||
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 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. */ | ||
516 | gcry_error_t | ||
517 | gcry_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. */ | ||
590 | gcry_error_t | ||
591 | gcry_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. */ | ||
602 | unsigned int | ||
603 | gcry_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. */ | ||
611 | gcry_error_t | ||
612 | gcry_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. */ | ||
651 | gcry_error_t | ||
652 | gcry_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. */ | ||
704 | void | ||
705 | gcry_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. */ | ||
720 | gcry_error_t | ||
721 | gcry_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. */ | ||
767 | void | ||
768 | gcry_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. */ | ||
786 | gcry_error_t | ||
787 | gcry_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. */ | ||
840 | gcry_error_t | ||
841 | gcry_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. */ | ||
1021 | gcry_ac_key_t | ||
1022 | gcry_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. */ | ||
1042 | void | ||
1043 | gcry_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. */ | ||
1063 | void | ||
1064 | gcry_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. */ | ||
1075 | gcry_ac_data_t | ||
1076 | gcry_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. */ | ||
1082 | gcry_error_t | ||
1083 | gcry_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. */ | ||
1093 | gcry_error_t | ||
1094 | gcry_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. */ | ||
1110 | gcry_error_t | ||
1111 | gcry_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. */ | ||
1132 | gcry_error_t | ||
1133 | gcry_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. */ | ||
1211 | gcry_error_t | ||
1212 | gcry_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. */ | ||
1272 | gcry_error_t | ||
1273 | gcry_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. */ | ||
1315 | gcry_error_t | ||
1316 | gcry_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. */ | ||
1360 | gcry_error_t | ||
1361 | gcry_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. */ | ||
1377 | gcry_error_t | ||
1378 | gcry_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 | } | ||