summaryrefslogtreecommitdiffabout
path: root/pwmanager/libcrypt/cipher/pubkey.c
authorzautrix <zautrix>2004-10-19 20:16:14 (UTC)
committer zautrix <zautrix>2004-10-19 20:16:14 (UTC)
commiteca49bb06a71980ef61d078904573f25890fc7f2 (patch) (unidiff)
treec5338e3b12430248979a9ac2c1c7e6646ea9ecdf /pwmanager/libcrypt/cipher/pubkey.c
parent53cc32b6e7b1f672bf91b2baf2df6c1e8baf3e0a (diff)
downloadkdepimpi-eca49bb06a71980ef61d078904573f25890fc7f2.zip
kdepimpi-eca49bb06a71980ef61d078904573f25890fc7f2.tar.gz
kdepimpi-eca49bb06a71980ef61d078904573f25890fc7f2.tar.bz2
Initial revision
Diffstat (limited to 'pwmanager/libcrypt/cipher/pubkey.c') (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/libcrypt/cipher/pubkey.c2352
1 files changed, 2352 insertions, 0 deletions
diff --git a/pwmanager/libcrypt/cipher/pubkey.c b/pwmanager/libcrypt/cipher/pubkey.c
new file mode 100644
index 0000000..45e816b
--- a/dev/null
+++ b/pwmanager/libcrypt/cipher/pubkey.c
@@ -0,0 +1,2352 @@
1 /* pubkey.c -pubkey dispatcher
2 * Copyright (C) 1998,1999,2000,2002,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 <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <errno.h>
26#include <assert.h>
27
28#include "g10lib.h"
29#include "mpi.h"
30#include "cipher.h"
31#include "ath.h"
32
33static gcry_err_code_t pubkey_decrypt (int algo, gcry_mpi_t *result,
34 gcry_mpi_t *data, gcry_mpi_t *skey,
35 int flags);
36static gcry_err_code_t pubkey_sign (int algo, gcry_mpi_t *resarr,
37 gcry_mpi_t hash, gcry_mpi_t *skey);
38static gcry_err_code_t pubkey_verify (int algo, gcry_mpi_t hash,
39 gcry_mpi_t *data, gcry_mpi_t *pkey,
40 int (*cmp) (void *, gcry_mpi_t),
41 void *opaque);
42
43/* This is the list of the default public-key ciphers included in
44 libgcrypt. */
45static struct pubkey_table_entry
46{
47 gcry_pk_spec_t *pubkey;
48 unsigned int algorithm;
49} pubkey_table[] =
50 {
51#if USE_RSA
52 { &_gcry_pubkey_spec_rsa, GCRY_PK_RSA },
53#endif
54#if USE_ELGAMAL
55 { &_gcry_pubkey_spec_elg, GCRY_PK_ELG },
56#endif
57#if USE_DSA
58 { &_gcry_pubkey_spec_dsa, GCRY_PK_DSA },
59#endif
60 { NULL, 0 },
61 };
62
63/* List of registered ciphers. */
64static gcry_module_t pubkeys_registered;
65
66/* This is the lock protecting PUBKEYS_REGISTERED. */
67static ath_mutex_t pubkeys_registered_lock;
68
69/* Flag to check wether the default pubkeys have already been
70 registered. */
71static int default_pubkeys_registered;
72
73/* Convenient macro for registering the default digests. */
74#define REGISTER_DEFAULT_PUBKEYS \
75 do \
76 { \
77 ath_mutex_lock (&pubkeys_registered_lock); \
78 if (! default_pubkeys_registered) \
79 { \
80 gcry_pk_register_default (); \
81 default_pubkeys_registered = 1; \
82 } \
83 ath_mutex_unlock (&pubkeys_registered_lock); \
84 } \
85 while (0)
86
87/* These dummy functions are used in case a cipher implementation
88 refuses to provide it's own functions. */
89
90static gcry_err_code_t
91dummy_generate (int algorithm, unsigned int nbits, unsigned long dummy,
92 gcry_mpi_t *skey, gcry_mpi_t **retfactors)
93{
94 log_bug ("no generate() for %d\n", algorithm);
95 return GPG_ERR_PUBKEY_ALGO;
96}
97
98static gcry_err_code_t
99dummy_check_secret_key (int algorithm, gcry_mpi_t *skey)
100{
101 log_bug ("no check_secret_key() for %d\n", algorithm);
102 return GPG_ERR_PUBKEY_ALGO;
103}
104
105static gcry_err_code_t
106dummy_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
107 gcry_mpi_t *pkey, int flags)
108{
109 log_bug ("no encrypt() for %d\n", algorithm);
110 return GPG_ERR_PUBKEY_ALGO;
111}
112
113static gcry_err_code_t
114dummy_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
115 gcry_mpi_t *skey, int flags)
116{
117 log_bug ("no decrypt() for %d\n", algorithm);
118 return GPG_ERR_PUBKEY_ALGO;
119}
120
121static gcry_err_code_t
122dummy_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
123 gcry_mpi_t *skey)
124{
125 log_bug ("no sign() for %d\n", algorithm);
126 return GPG_ERR_PUBKEY_ALGO;
127}
128
129static gcry_err_code_t
130dummy_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
131 gcry_mpi_t *pkey,
132 int (*cmp) (void *, gcry_mpi_t), void *opaquev)
133{
134 log_bug ("no verify() for %d\n", algorithm);
135 return GPG_ERR_PUBKEY_ALGO;
136}
137
138static unsigned
139dummy_get_nbits (int algorithm, gcry_mpi_t *pkey)
140{
141 log_bug ("no get_nbits() for %d\n", algorithm);
142 return 0;
143}
144
145/* Internal function. Register all the pubkeys included in
146 PUBKEY_TABLE. Returns zero on success or an error code. */
147static void
148gcry_pk_register_default (void)
149{
150 gcry_err_code_t err = 0;
151 int i;
152
153 for (i = 0; (! err) && pubkey_table[i].pubkey; i++)
154 {
155#define pubkey_use_dummy(func) \
156 if (! pubkey_table[i].pubkey->func) \
157 pubkey_table[i].pubkey->func = dummy_##func;
158
159 pubkey_use_dummy (generate);
160 pubkey_use_dummy (check_secret_key);
161 pubkey_use_dummy (encrypt);
162 pubkey_use_dummy (decrypt);
163 pubkey_use_dummy (sign);
164 pubkey_use_dummy (verify);
165 pubkey_use_dummy (get_nbits);
166#undef pubkey_use_dummy
167 err = _gcry_module_add (&pubkeys_registered,
168 pubkey_table[i].algorithm,
169 (void *) pubkey_table[i].pubkey, NULL);
170 }
171
172 if (err)
173 BUG ();
174}
175
176/* Internal callback function. Used via _gcry_module_lookup. */
177static int
178gcry_pk_lookup_func_name (void *spec, void *data)
179{
180 gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) spec;
181 char *name = (char *) data;
182 char **aliases = pubkey->aliases;
183 int ret = stricmp (name, pubkey->name);
184
185 while (ret && *aliases)
186 ret = stricmp (name, *aliases++);
187
188 return ! ret;
189}
190
191/* Internal function. Lookup a pubkey entry by it's name. */
192static gcry_module_t
193gcry_pk_lookup_name (const char *name)
194{
195 gcry_module_t pubkey;
196
197 pubkey = _gcry_module_lookup (pubkeys_registered, (void *) name,
198 gcry_pk_lookup_func_name);
199
200 return pubkey;
201}
202
203/* Register a new pubkey module whose specification can be found in
204 PUBKEY. On success, a new algorithm ID is stored in ALGORITHM_ID
205 and a pointer representhing this module is stored in MODULE. */
206gcry_error_t
207gcry_pk_register (gcry_pk_spec_t *pubkey,
208 unsigned int *algorithm_id,
209 gcry_module_t *module)
210{
211 gcry_err_code_t err = GPG_ERR_NO_ERROR;
212 gcry_module_t mod;
213
214 ath_mutex_lock (&pubkeys_registered_lock);
215 err = _gcry_module_add (&pubkeys_registered, 0,
216 (void *) pubkey, &mod);
217 ath_mutex_unlock (&pubkeys_registered_lock);
218
219 if (! err)
220 {
221 *module = mod;
222 *algorithm_id = mod->mod_id;
223 }
224
225 return err;
226}
227
228/* Unregister the pubkey identified by ID, which must have been
229 registered with gcry_pk_register. */
230void
231gcry_pk_unregister (gcry_module_t module)
232{
233 ath_mutex_lock (&pubkeys_registered_lock);
234 _gcry_module_release (module);
235 ath_mutex_unlock (&pubkeys_registered_lock);
236}
237
238static void
239release_mpi_array (gcry_mpi_t *array)
240{
241 for (; *array; array++)
242 {
243 mpi_free(*array);
244 *array = NULL;
245 }
246}
247
248/****************
249 * Map a string to the pubkey algo
250 */
251int
252gcry_pk_map_name (const char *string)
253{
254 gcry_module_t pubkey;
255 int algorithm = 0;
256
257 if (!string)
258 return 0;
259
260 REGISTER_DEFAULT_PUBKEYS;
261
262 ath_mutex_lock (&pubkeys_registered_lock);
263 pubkey = gcry_pk_lookup_name (string);
264 if (pubkey)
265 {
266 algorithm = pubkey->mod_id;
267 _gcry_module_release (pubkey);
268 }
269 ath_mutex_unlock (&pubkeys_registered_lock);
270
271 return algorithm;
272}
273
274
275/****************
276 * Map a pubkey algo to a string
277 */
278const char *
279gcry_pk_algo_name (int algorithm)
280{
281 const char *name = NULL;
282 gcry_module_t pubkey;
283
284 REGISTER_DEFAULT_PUBKEYS;
285
286 ath_mutex_lock (&pubkeys_registered_lock);
287 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
288 if (pubkey)
289 {
290 name = ((gcry_pk_spec_t *) pubkey->spec)->name;
291 _gcry_module_release (pubkey);
292 }
293 ath_mutex_unlock (&pubkeys_registered_lock);
294
295 return name;
296}
297
298
299/* A special version of gcry_pk_algo name to return the first aliased
300 name of the algorithm. This is required to adhere to the spki
301 specs where the algorithm names are lowercase. */
302const char *
303_gcry_pk_aliased_algo_name (int algorithm)
304{
305 const char *name = NULL;
306 gcry_module_t module;
307
308 REGISTER_DEFAULT_PUBKEYS;
309
310 ath_mutex_lock (&pubkeys_registered_lock);
311 module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
312 if (module)
313 {
314 gcry_pk_spec_t *pubkey = (gcry_pk_spec_t *) module->spec;
315
316 name = pubkey->aliases? *pubkey->aliases : NULL;
317 if (!name || !*name)
318 name = pubkey->name;
319 _gcry_module_release (module);
320 }
321 ath_mutex_unlock (&pubkeys_registered_lock);
322
323 return name;
324}
325
326
327static void
328disable_pubkey_algo (int algorithm)
329{
330 gcry_module_t pubkey;
331
332 ath_mutex_lock (&pubkeys_registered_lock);
333 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
334 if (pubkey)
335 {
336 if (! (pubkey-> flags & FLAG_MODULE_DISABLED))
337 pubkey->flags |= FLAG_MODULE_DISABLED;
338 _gcry_module_release (pubkey);
339 }
340 ath_mutex_unlock (&pubkeys_registered_lock);
341}
342
343
344/****************
345 * A USE of 0 means: don't care.
346 */
347static gcry_err_code_t
348check_pubkey_algo (int algorithm, unsigned use)
349{
350 gcry_err_code_t err = GPG_ERR_NO_ERROR;
351 gcry_pk_spec_t *pubkey;
352 gcry_module_t module;
353
354 REGISTER_DEFAULT_PUBKEYS;
355
356 ath_mutex_lock (&pubkeys_registered_lock);
357 module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
358 if (module)
359 {
360 pubkey = (gcry_pk_spec_t *) module->spec;
361
362 if (((use & GCRY_PK_USAGE_SIGN)
363 && (! (pubkey->use & GCRY_PK_USAGE_SIGN)))
364 || ((use & GCRY_PK_USAGE_ENCR)
365 && (! (pubkey->use & GCRY_PK_USAGE_ENCR))))
366 err = GPG_ERR_WRONG_PUBKEY_ALGO;
367 else if (module->flags & FLAG_MODULE_DISABLED)
368 err = GPG_ERR_PUBKEY_ALGO;
369 _gcry_module_release (module);
370 }
371 else
372 err = GPG_ERR_PUBKEY_ALGO;
373 ath_mutex_unlock (&pubkeys_registered_lock);
374
375 return err;
376}
377
378
379/****************
380 * Return the number of public key material numbers
381 */
382static int
383pubkey_get_npkey (int algorithm)
384{
385 gcry_module_t pubkey;
386 int npkey = 0;
387
388 REGISTER_DEFAULT_PUBKEYS;
389
390 ath_mutex_lock (&pubkeys_registered_lock);
391 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
392 if (pubkey)
393 {
394 npkey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_pkey);
395 _gcry_module_release (pubkey);
396 }
397 ath_mutex_unlock (&pubkeys_registered_lock);
398
399 return npkey;
400}
401
402/****************
403 * Return the number of secret key material numbers
404 */
405static int
406pubkey_get_nskey (int algorithm)
407{
408 gcry_module_t pubkey;
409 int nskey = 0;
410
411 REGISTER_DEFAULT_PUBKEYS;
412
413 ath_mutex_lock (&pubkeys_registered_lock);
414 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
415 if (pubkey)
416 {
417 nskey = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_skey);
418 _gcry_module_release (pubkey);
419 }
420 ath_mutex_unlock (&pubkeys_registered_lock);
421
422 return nskey;
423}
424
425/****************
426 * Return the number of signature material numbers
427 */
428static int
429pubkey_get_nsig (int algorithm)
430{
431 gcry_module_t pubkey;
432 int nsig = 0;
433
434 REGISTER_DEFAULT_PUBKEYS;
435
436 ath_mutex_lock (&pubkeys_registered_lock);
437 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
438 if (pubkey)
439 {
440 nsig = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_sig);
441 _gcry_module_release (pubkey);
442 }
443 ath_mutex_unlock (&pubkeys_registered_lock);
444
445 return nsig;
446}
447
448/****************
449 * Return the number of encryption material numbers
450 */
451static int
452pubkey_get_nenc (int algorithm)
453{
454 gcry_module_t pubkey;
455 int nenc = 0;
456
457 REGISTER_DEFAULT_PUBKEYS;
458
459 ath_mutex_lock (&pubkeys_registered_lock);
460 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
461 if (pubkey)
462 {
463 nenc = strlen (((gcry_pk_spec_t *) pubkey->spec)->elements_enc);
464 _gcry_module_release (pubkey);
465 }
466 ath_mutex_unlock (&pubkeys_registered_lock);
467
468 return nenc;
469}
470
471
472static gcry_err_code_t
473pubkey_generate (int algorithm, unsigned int nbits, unsigned long use_e,
474 gcry_mpi_t *skey, gcry_mpi_t **retfactors)
475{
476 gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
477 gcry_module_t pubkey;
478
479 REGISTER_DEFAULT_PUBKEYS;
480
481 ath_mutex_lock (&pubkeys_registered_lock);
482 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
483 if (pubkey)
484 {
485 err = ((gcry_pk_spec_t *) pubkey->spec)->generate
486 (algorithm, nbits, use_e, skey, retfactors);
487 _gcry_module_release (pubkey);
488 }
489 ath_mutex_unlock (&pubkeys_registered_lock);
490
491 return err;
492}
493
494static gcry_err_code_t
495pubkey_check_secret_key (int algorithm, gcry_mpi_t *skey)
496{
497 gcry_err_code_t err = GPG_ERR_PUBKEY_ALGO;
498 gcry_module_t pubkey;
499
500 REGISTER_DEFAULT_PUBKEYS;
501
502 ath_mutex_lock (&pubkeys_registered_lock);
503 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
504 if (pubkey)
505 {
506 err = ((gcry_pk_spec_t *) pubkey->spec)->check_secret_key
507 (algorithm, skey);
508 _gcry_module_release (pubkey);
509 }
510 ath_mutex_unlock (&pubkeys_registered_lock);
511
512 return err;
513}
514
515
516/****************
517 * This is the interface to the public key encryption. Encrypt DATA
518 * with PKEY and put it into RESARR which should be an array of MPIs
519 * of size PUBKEY_MAX_NENC (or less if the algorithm allows this -
520 * check with pubkey_get_nenc() )
521 */
522static gcry_err_code_t
523pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
524 gcry_mpi_t *pkey, int flags)
525{
526 gcry_pk_spec_t *pubkey;
527 gcry_module_t module;
528 gcry_err_code_t rc;
529 int i;
530
531 if (DBG_CIPHER)
532 {
533 log_debug ("pubkey_encrypt: algo=%d\n", algorithm);
534 for(i = 0; i < pubkey_get_npkey (algorithm); i++)
535 log_mpidump (" pkey:", pkey[i]);
536 log_mpidump (" data:", data);
537 }
538
539 ath_mutex_lock (&pubkeys_registered_lock);
540 module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
541 if (module)
542 {
543 pubkey = (gcry_pk_spec_t *) module->spec;
544 rc = pubkey->encrypt (algorithm, resarr, data, pkey, flags);
545 _gcry_module_release (module);
546 goto ready;
547 }
548 rc = GPG_ERR_PUBKEY_ALGO;
549
550 ready:
551 ath_mutex_unlock (&pubkeys_registered_lock);
552
553 if (!rc && DBG_CIPHER)
554 {
555 for(i = 0; i < pubkey_get_nenc (algorithm); i++)
556 log_mpidump(" encr:", resarr[i] );
557 }
558 return rc;
559}
560
561
562/****************
563 * This is the interface to the public key decryption.
564 * ALGO gives the algorithm to use and this implicitly determines
565 * the size of the arrays.
566 * result is a pointer to a mpi variable which will receive a
567 * newly allocated mpi or NULL in case of an error.
568 */
569static gcry_err_code_t
570pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data,
571 gcry_mpi_t *skey, int flags)
572{
573 gcry_pk_spec_t *pubkey;
574 gcry_module_t module;
575 gcry_err_code_t rc;
576 int i;
577
578 *result = NULL; /* so the caller can always do a mpi_free */
579 if (DBG_CIPHER)
580 {
581 log_debug ("pubkey_decrypt: algo=%d\n", algorithm);
582 for(i = 0; i < pubkey_get_nskey (algorithm); i++)
583 log_mpidump (" skey:", skey[i]);
584 for(i = 0; i < pubkey_get_nenc (algorithm); i++)
585 log_mpidump (" data:", data[i]);
586 }
587
588 ath_mutex_lock (&pubkeys_registered_lock);
589 module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
590 if (module)
591 {
592 pubkey = (gcry_pk_spec_t *) module->spec;
593 rc = pubkey->decrypt (algorithm, result, data, skey, flags);
594 _gcry_module_release (module);
595 goto ready;
596 }
597
598 rc = GPG_ERR_PUBKEY_ALGO;
599
600 ready:
601 ath_mutex_unlock (&pubkeys_registered_lock);
602
603 if (! rc && DBG_CIPHER)
604 log_mpidump (" plain:", *result);
605
606 return rc;
607}
608
609
610/****************
611 * This is the interface to the public key signing.
612 * Sign data with skey and put the result into resarr which
613 * should be an array of MPIs of size PUBKEY_MAX_NSIG (or less if the
614 * algorithm allows this - check with pubkey_get_nsig() )
615 */
616static gcry_err_code_t
617pubkey_sign (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data,
618 gcry_mpi_t *skey)
619{
620 gcry_pk_spec_t *pubkey;
621 gcry_module_t module;
622 gcry_err_code_t rc;
623 int i;
624
625 if (DBG_CIPHER)
626 {
627 log_debug ("pubkey_sign: algo=%d\n", algorithm);
628 for(i = 0; i < pubkey_get_nskey (algorithm); i++)
629 log_mpidump (" skey:", skey[i]);
630 log_mpidump(" data:", data );
631 }
632
633 ath_mutex_lock (&pubkeys_registered_lock);
634 module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
635 if (module)
636 {
637 pubkey = (gcry_pk_spec_t *) module->spec;
638 rc = pubkey->sign (algorithm, resarr, data, skey);
639 _gcry_module_release (module);
640 goto ready;
641 }
642
643 rc = GPG_ERR_PUBKEY_ALGO;
644
645 ready:
646 ath_mutex_unlock (&pubkeys_registered_lock);
647
648 if (! rc && DBG_CIPHER)
649 for (i = 0; i < pubkey_get_nsig (algorithm); i++)
650 log_mpidump (" sig:", resarr[i]);
651
652 return rc;
653}
654
655/****************
656 * Verify a public key signature.
657 * Return 0 if the signature is good
658 */
659static gcry_err_code_t
660pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data,
661 gcry_mpi_t *pkey,
662 int (*cmp)(void *, gcry_mpi_t), void *opaquev)
663{
664 gcry_pk_spec_t *pubkey;
665 gcry_module_t module;
666 gcry_err_code_t rc;
667 int i;
668
669 if (DBG_CIPHER)
670 {
671 log_debug ("pubkey_verify: algo=%d\n", algorithm);
672 for (i = 0; i < pubkey_get_npkey (algorithm); i++)
673 log_mpidump (" pkey:", pkey[i]);
674 for (i = 0; i < pubkey_get_nsig (algorithm); i++)
675 log_mpidump (" sig:", data[i]);
676 log_mpidump (" hash:", hash);
677 }
678
679 ath_mutex_lock (&pubkeys_registered_lock);
680 module = _gcry_module_lookup_id (pubkeys_registered, algorithm);
681 if (module)
682 {
683 pubkey = (gcry_pk_spec_t *) module->spec;
684 rc = pubkey->verify (algorithm, hash, data, pkey, cmp, opaquev);
685 _gcry_module_release (module);
686 goto ready;
687 }
688
689 rc = GPG_ERR_PUBKEY_ALGO;
690
691 ready:
692 ath_mutex_unlock (&pubkeys_registered_lock);
693 return rc;
694}
695
696
697/* Internal function. */
698static gcry_err_code_t
699sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names,
700 gcry_mpi_t *elements)
701{
702 gcry_err_code_t err = GPG_ERR_NO_ERROR;
703 int i, idx;
704 const char *name;
705 gcry_sexp_t list;
706
707 for (name = element_names, idx = 0; *name && !err; name++, idx++)
708 {
709 list = gcry_sexp_find_token (key_sexp, name, 1);
710 if (! list)
711 err = GPG_ERR_NO_OBJ;
712 else
713 {
714 elements[idx] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
715 gcry_sexp_release (list);
716 if (! elements[idx])
717 err = GPG_ERR_INV_OBJ;
718 }
719 }
720
721 if (err)
722 {
723 for (i = 0; i < idx; i++)
724 if (elements[i])
725 gcry_free (elements[i]);
726 }
727 return err;
728}
729
730/****************
731 * Convert a S-Exp with either a private or a public key to our
732 * internal format. Currently we do only support the following
733 * algorithms:
734 * dsa
735 * rsa
736 * openpgp-dsa
737 * openpgp-rsa
738 * openpgp-elg
739 * openpgp-elg-sig
740 * Provide a SE with the first element be either "private-key" or
741 * or "public-key". It is followed by a list with its first element
742 * be one of the above algorithm identifiers and the remaning
743 * elements are pairs with parameter-id and value.
744 * NOTE: we look through the list to find a list beginning with
745 * "private-key" or "public-key" - the first one found is used.
746 *
747 * FIXME: Allow for encrypted secret keys here.
748 *
749 * Returns: A pointer to an allocated array of MPIs if the return value is
750 * zero; the caller has to release this array.
751 *
752 * Example of a DSA public key:
753 * (private-key
754 * (dsa
755 *(p <mpi>)
756 *(g <mpi>)
757 *(y <mpi>)
758 *(x <mpi>)
759 * )
760 * )
761 * The <mpi> are expected to be in GCRYMPI_FMT_USG
762 */
763static gcry_err_code_t
764sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray,
765 gcry_module_t *retalgo)
766{
767 gcry_sexp_t list, l2;
768 const char *name;
769 size_t n;
770 const char *elems;
771 gcry_mpi_t *array;
772 gcry_err_code_t err = GPG_ERR_NO_ERROR;
773 gcry_module_t module;
774 gcry_pk_spec_t *pubkey;
775
776 /* check that the first element is valid */
777 list = gcry_sexp_find_token( sexp, want_private? "private-key"
778 :"public-key", 0 );
779 if( !list )
780 return GPG_ERR_INV_OBJ; /* Does not contain a public-
781 or private-key object */
782 l2 = gcry_sexp_cadr( list );
783 gcry_sexp_release ( list );
784 list = l2;
785 name = gcry_sexp_nth_data( list, 0, &n );
786 if( !name ) {
787 gcry_sexp_release ( list );
788 return GPG_ERR_INV_OBJ; /* invalid structure of object */
789 }
790
791 {
792 char *name_terminated = gcry_xmalloc (n + 1);
793 memcpy (name_terminated, name, n);
794 name_terminated[n] = 0;
795
796 ath_mutex_lock (&pubkeys_registered_lock);
797 module = gcry_pk_lookup_name (name_terminated);
798 ath_mutex_unlock (&pubkeys_registered_lock);
799
800 gcry_free (name_terminated);
801 }
802
803 if (! module)
804 {
805 gcry_sexp_release (list);
806 return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
807 }
808 else
809 pubkey = (gcry_pk_spec_t *) module->spec;
810
811 elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey;
812 array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
813 if (! array)
814 err = gpg_err_code_from_errno (errno);
815 if (! err)
816 err = sexp_elements_extract (list, elems, array);
817
818 if (list)
819 gcry_sexp_release (list);
820
821 if (err)
822 {
823 if (array)
824 gcry_free (array);
825
826 ath_mutex_lock (&pubkeys_registered_lock);
827 _gcry_module_release (module);
828 ath_mutex_unlock (&pubkeys_registered_lock);
829 }
830 else
831 {
832 *retarray = array;
833 *retalgo = module;
834 }
835
836 return err;
837}
838
839static gcry_err_code_t
840sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray,
841 gcry_module_t *retalgo)
842{
843 gcry_sexp_t list, l2;
844 const char *name;
845 size_t n;
846 const char *elems;
847 gcry_mpi_t *array;
848 gcry_err_code_t err = GPG_ERR_NO_ERROR;
849 gcry_module_t module;
850 gcry_pk_spec_t *pubkey;
851
852 /* check that the first element is valid */
853 list = gcry_sexp_find_token( sexp, "sig-val" , 0 );
854 if( !list )
855 return GPG_ERR_INV_OBJ; /* Does not contain a signature value object */
856 l2 = gcry_sexp_nth (list, 1);
857 if(! l2)
858 {
859 gcry_sexp_release (list);
860 return GPG_ERR_NO_OBJ; /* no cadr for the sig object */
861 }
862 name = gcry_sexp_nth_data( l2, 0, &n );
863 if( !name ) {
864 gcry_sexp_release ( list );
865 gcry_sexp_release ( l2 );
866 return GPG_ERR_INV_OBJ; /* invalid structure of object */
867 }
868 else if (n == 5 && (! memcmp (name, "flags", 5))) {
869 /* Skip flags, since they are not used but just here for the
870 sake of consistent S-expressions. */
871 gcry_sexp_release (l2);
872 l2 = gcry_sexp_nth (list, 2);
873 if (! l2)
874 {
875 gcry_sexp_release (list);
876 return GPG_ERR_INV_OBJ;
877 }
878 name = gcry_sexp_nth_data (l2, 0, &n);
879 }
880
881 {
882 char *name_terminated = gcry_xmalloc (n + 1);
883 memcpy (name_terminated, name, n);
884 name_terminated[n] = 0;
885
886 ath_mutex_lock (&pubkeys_registered_lock);
887 module = gcry_pk_lookup_name (name_terminated);
888 ath_mutex_unlock (&pubkeys_registered_lock);
889
890 gcry_free (name_terminated);
891 }
892
893 if (! module)
894 {
895 gcry_sexp_release (l2);
896 gcry_sexp_release (list);
897 return GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
898 }
899 else
900 pubkey = (gcry_pk_spec_t *) module->spec;
901
902 elems = pubkey->elements_sig;
903 array = gcry_calloc (strlen (elems) + 1 , sizeof (*array));
904 if (! array)
905 err = gpg_err_code_from_errno (errno);
906
907 if (! err)
908 err = sexp_elements_extract (list, elems, array);
909
910 gcry_sexp_release (l2);
911 gcry_sexp_release (list);
912
913 if (err)
914 {
915 ath_mutex_lock (&pubkeys_registered_lock);
916 _gcry_module_release (module);
917 ath_mutex_unlock (&pubkeys_registered_lock);
918
919 if (array)
920 gcry_free (array);
921 }
922 else
923 {
924 *retarray = array;
925 *retalgo = module;
926 }
927
928 return err;
929}
930
931
932/****************
933 * Take sexp and return an array of MPI as used for our internal decrypt
934 * function.
935 * s_data = (enc-val
936 * [(flags [pkcs1])
937 * (<algo>
938 * (<param_name1> <mpi>)
939 * ...
940 * (<param_namen> <mpi>)
941 * ))
942 * RET_MODERN is set to true when at least an empty flags list has been found.
943 */
944static gcry_err_code_t
945sexp_to_enc (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_module_t *retalgo,
946 int *ret_modern, int *ret_want_pkcs1, int *flags)
947{
948 gcry_sexp_t list = NULL, l2 = NULL;
949 gcry_pk_spec_t *pubkey = NULL;
950 gcry_module_t module = NULL;
951 const char *name;
952 size_t n;
953 int parsed_flags = 0;
954 const char *elems;
955 gcry_mpi_t *array = NULL;
956 gcry_err_code_t err = GPG_ERR_NO_ERROR;
957
958 *ret_want_pkcs1 = 0;
959 *ret_modern = 0;
960
961 /* check that the first element is valid */
962 list = gcry_sexp_find_token (sexp, "enc-val" , 0);
963 if (! list)
964 {
965 err = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object */
966 goto leave;
967 }
968
969 l2 = gcry_sexp_nth (list, 1);
970 if (! l2)
971 {
972 err = GPG_ERR_NO_OBJ; /* no cdr for the data object */
973 goto leave;
974 }
975
976 /* Extract identifier of sublist. */
977 name = gcry_sexp_nth_data (l2, 0, &n);
978 if (! name)
979 {
980 err = GPG_ERR_INV_OBJ; /* invalid structure of object */
981 goto leave;
982 }
983
984 if ((n == 5) && (! memcmp (name, "flags", 5)))
985 {
986 /* There is a flags element - process it */
987 const char *s;
988 int i;
989
990 *ret_modern = 1;
991 for (i = gcry_sexp_length (l2) - 1; i > 0; i--)
992 {
993 s = gcry_sexp_nth_data (l2, i, &n);
994 if (! s)
995 ; /* not a data element - ignore */
996 else if (n == 3 && ! memcmp (s, "raw", 3))
997 ; /* just a dummy because it is the default */
998 else if (n == 5 && ! memcmp (s, "pkcs1", 5))
999 *ret_want_pkcs1 = 1;
1000 else if (n == 11 && ! memcmp (s, "no-blinding", 11))
1001 parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
1002 else
1003 {
1004 err = GPG_ERR_INV_FLAG;
1005 goto leave;
1006 }
1007 }
1008
1009 /* Get the next which has the actual data */
1010 gcry_sexp_release (l2);
1011 l2 = gcry_sexp_nth (list, 2);
1012 if (! l2)
1013 {
1014 err = GPG_ERR_NO_OBJ; /* no cdr for the data object */
1015 goto leave;
1016 }
1017
1018 /* Extract sublist identifier. */
1019 name = gcry_sexp_nth_data (l2, 0, &n);
1020 if (! name)
1021 {
1022 err = GPG_ERR_INV_OBJ; /* invalid structure of object */
1023 goto leave;
1024 }
1025
1026 gcry_sexp_release (list);
1027 list = l2;
1028 l2 = NULL;
1029 }
1030
1031 {
1032 char *name_terminated = gcry_xmalloc (n + 1);
1033 memcpy (name_terminated, name, n);
1034 name_terminated[n] = 0;
1035
1036 ath_mutex_lock (&pubkeys_registered_lock);
1037 module = gcry_pk_lookup_name (name_terminated);
1038 ath_mutex_unlock (&pubkeys_registered_lock);
1039
1040 gcry_free (name_terminated);
1041
1042 if (! module)
1043 {
1044 err = GPG_ERR_PUBKEY_ALGO; /* unknown algorithm */
1045 goto leave;
1046 }
1047 pubkey = (gcry_pk_spec_t *) module->spec;
1048 }
1049
1050 elems = pubkey->elements_enc;
1051 array = gcry_calloc (strlen (elems) + 1, sizeof (*array));
1052 if (! array)
1053 {
1054 err = gpg_err_code_from_errno (errno);
1055 goto leave;
1056 }
1057
1058 err = sexp_elements_extract (list, elems, array);
1059
1060 leave:
1061 if (list)
1062 gcry_sexp_release (list);
1063 if (l2)
1064 gcry_sexp_release (l2);
1065
1066 if (err)
1067 {
1068 ath_mutex_lock (&pubkeys_registered_lock);
1069 _gcry_module_release (module);
1070 ath_mutex_unlock (&pubkeys_registered_lock);
1071 if (array)
1072 gcry_free (array);
1073 }
1074 else
1075 {
1076 *retarray = array;
1077 *retalgo = module;
1078 *flags = parsed_flags;
1079 }
1080
1081 return err;
1082}
1083
1084/* Take the hash value and convert into an MPI, suitable for for
1085 passing to the low level functions. We currently support the
1086 old style way of passing just a MPI and the modern interface which
1087 allows to pass flags so that we can choose between raw and pkcs1
1088 padding - may be more padding options later.
1089
1090 (<mpi>)
1091 or
1092 (data
1093 [(flags [pkcs1])]
1094 [(hash <algo> <value>)]
1095 [(value <text>)]
1096 )
1097
1098 Either the VALUE or the HASH element must be present for use
1099 with signatures. VALUE is used for encryption.
1100
1101 NBITS is the length of the key in bits.
1102
1103*/
1104static gcry_err_code_t
1105sexp_data_to_mpi (gcry_sexp_t input, unsigned int nbits, gcry_mpi_t *ret_mpi,
1106 int for_encryption, int *flags)
1107{
1108 gcry_err_code_t rc = 0;
1109 gcry_sexp_t ldata, lhash, lvalue;
1110 int i;
1111 size_t n;
1112 const char *s;
1113 int is_raw = 0, is_pkcs1 = 0, unknown_flag=0;
1114 int parsed_flags = 0, dummy_flags;
1115
1116 if (! flags)
1117 flags = &dummy_flags;
1118
1119 *ret_mpi = NULL;
1120 ldata = gcry_sexp_find_token (input, "data", 0);
1121 if (!ldata)
1122 { /* assume old style */
1123 *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
1124 return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
1125 }
1126
1127 /* see whether there is a flags object */
1128 {
1129 gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
1130 if (lflags)
1131 { /* parse the flags list. */
1132 for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
1133 {
1134 s = gcry_sexp_nth_data (lflags, i, &n);
1135 if (!s)
1136 ; /* not a data element*/
1137 else if ( n == 3 && !memcmp (s, "raw", 3))
1138 is_raw = 1;
1139 else if ( n == 5 && !memcmp (s, "pkcs1", 5))
1140 is_pkcs1 = 1;
1141 else if (n == 11 && ! memcmp (s, "no-blinding", 11))
1142 parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
1143 else
1144 unknown_flag = 1;
1145 }
1146 gcry_sexp_release (lflags);
1147 }
1148 }
1149
1150 if (!is_pkcs1 && !is_raw)
1151 is_raw = 1; /* default to raw */
1152
1153 /* Get HASH or MPI */
1154 lhash = gcry_sexp_find_token (ldata, "hash", 0);
1155 lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
1156
1157 if (!(!lhash ^ !lvalue))
1158 rc = GPG_ERR_INV_OBJ; /* none or both given */
1159 else if (unknown_flag)
1160 rc = GPG_ERR_INV_FLAG;
1161 else if (is_raw && is_pkcs1 && !for_encryption)
1162 rc = GPG_ERR_CONFLICT;
1163 else if (is_raw && lvalue)
1164 {
1165 *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, 0);
1166 if (!*ret_mpi)
1167 rc = GPG_ERR_INV_OBJ;
1168 }
1169 else if (is_pkcs1 && lvalue && for_encryption)
1170 { /* Create pkcs#1 block type 2 padding. */
1171 unsigned char *frame = NULL;
1172 size_t nframe = (nbits+7) / 8;
1173 const void * value;
1174 size_t valuelen;
1175 unsigned char *p;
1176
1177 if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
1178 rc = GPG_ERR_INV_OBJ;
1179 else if (valuelen + 7 > nframe || !nframe)
1180 {
1181 /* Can't encode a VALUELEN value in a NFRAME bytes frame. */
1182 rc = GPG_ERR_TOO_SHORT; /* the key is too short */
1183 }
1184 else if ( !(frame = gcry_malloc_secure (nframe)))
1185 rc = gpg_err_code_from_errno (errno);
1186 else
1187 {
1188 n = 0;
1189 frame[n++] = 0;
1190 frame[n++] = 2; /* block type */
1191 i = nframe - 3 - valuelen;
1192 assert (i > 0);
1193 p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM);
1194 /* Replace zero bytes by new values. */
1195 for (;;)
1196 {
1197 int j, k;
1198 unsigned char *pp;
1199
1200 /* Count the zero bytes. */
1201 for (j=k=0; j < i; j++)
1202 {
1203 if (!p[j])
1204 k++;
1205 }
1206 if (!k)
1207 break; /* Okay: no (more) zero bytes. */
1208
1209 k += k/128; /* Better get some more. */
1210 pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM);
1211 for (j=0; j < i && k; j++)
1212 {
1213 if (!p[j])
1214 p[j] = pp[--k];
1215 }
1216 gcry_free (pp);
1217 }
1218 memcpy (frame+n, p, i);
1219 n += i;
1220 gcry_free (p);
1221
1222 frame[n++] = 0;
1223 memcpy (frame+n, value, valuelen);
1224 n += valuelen;
1225 assert (n == nframe);
1226
1227 /* FIXME, error checking? */
1228 gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
1229 }
1230
1231 gcry_free(frame);
1232 }
1233 else if (is_pkcs1 && lhash && !for_encryption)
1234 { /* Create pkcs#1 block type 1 padding. */
1235 if (gcry_sexp_length (lhash) != 3)
1236 rc = GPG_ERR_INV_OBJ;
1237 else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
1238 rc = GPG_ERR_INV_OBJ;
1239 else
1240 {
1241 static struct { const char *name; int algo; } hashnames[] =
1242 { { "sha1", GCRY_MD_SHA1 },
1243 { "md5", GCRY_MD_MD5 },
1244 { "rmd160", GCRY_MD_RMD160 },
1245 { "sha256", GCRY_MD_SHA256 },
1246 { "sha384", GCRY_MD_SHA384 },
1247 { "sha512", GCRY_MD_SHA512 },
1248 { "md2", GCRY_MD_MD2 },
1249 { "md4", GCRY_MD_MD4 },
1250 { "tiger", GCRY_MD_TIGER },
1251 { "haval", GCRY_MD_HAVAL },
1252 { NULL }
1253 };
1254 int algo;
1255 byte asn[100];
1256 byte *frame = NULL;
1257 size_t nframe = (nbits+7) / 8;
1258 const void * value;
1259 size_t valuelen;
1260 size_t asnlen, dlen;
1261
1262 for (i=0; hashnames[i].name; i++)
1263 {
1264 if ( strlen (hashnames[i].name) == n
1265 && !memcmp (hashnames[i].name, s, n))
1266 break;
1267 }
1268
1269 algo = hashnames[i].algo;
1270 asnlen = DIM(asn);
1271 dlen = gcry_md_get_algo_dlen (algo);
1272
1273 if (!hashnames[i].name)
1274 rc = GPG_ERR_DIGEST_ALGO;
1275 else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
1276 || !valuelen )
1277 rc = GPG_ERR_INV_OBJ;
1278 else if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
1279 {
1280 /* We don't have yet all of the above algorithms. */
1281 rc = GPG_ERR_NOT_IMPLEMENTED;
1282 }
1283 else if ( valuelen != dlen )
1284 {
1285 /* Hash value does not match the length of digest for
1286 the given algorithm. */
1287 rc = GPG_ERR_CONFLICT;
1288 }
1289 else if( !dlen || dlen + asnlen + 4 > nframe)
1290 {
1291 /* Can't encode an DLEN byte digest MD into a NFRAME
1292 byte frame. */
1293 rc = GPG_ERR_TOO_SHORT;
1294 }
1295 else if ( !(frame = gcry_malloc (nframe)) )
1296 rc = gpg_err_code_from_errno (errno);
1297 else
1298 { /* Assemble the pkcs#1 block type 1. */
1299 n = 0;
1300 frame[n++] = 0;
1301 frame[n++] = 1; /* block type */
1302 i = nframe - valuelen - asnlen - 3 ;
1303 assert (i > 1);
1304 memset (frame+n, 0xff, i );
1305 n += i;
1306 frame[n++] = 0;
1307 memcpy (frame+n, asn, asnlen);
1308 n += asnlen;
1309 memcpy (frame+n, value, valuelen );
1310 n += valuelen;
1311 assert (n == nframe);
1312
1313 /* convert it into an MPI, FIXME: error checking? */
1314 gcry_mpi_scan (ret_mpi, GCRYMPI_FMT_USG, frame, n, &nframe);
1315 }
1316
1317 gcry_free (frame);
1318 }
1319 }
1320 else
1321 rc = GPG_ERR_CONFLICT;
1322
1323 gcry_sexp_release (ldata);
1324 gcry_sexp_release (lhash);
1325 gcry_sexp_release (lvalue);
1326
1327 if (!rc)
1328 *flags = parsed_flags;
1329
1330 return rc;
1331}
1332
1333
1334/*
1335 Do a PK encrypt operation
1336
1337 Caller has to provide a public key as the SEXP pkey and data as a
1338 SEXP with just one MPI in it. Alternativly S_DATA might be a
1339 complex S-Expression, similar to the one used for signature
1340 verification. This provides a flag which allows to handle PKCS#1
1341 block type 2 padding. The function returns a a sexp which may be
1342 passed to to pk_decrypt.
1343
1344 Returns: 0 or an errorcode.
1345
1346 s_data = See comment for sexp_data_to_mpi
1347 s_pkey = <key-as-defined-in-sexp_to_key>
1348 r_ciph = (enc-val
1349 (<algo>
1350 (<param_name1> <mpi>)
1351 ...
1352 (<param_namen> <mpi>)
1353 ))
1354
1355*/
1356gcry_error_t
1357gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey)
1358{
1359 gcry_mpi_t *pkey = NULL, data = NULL, *ciph = NULL;
1360 const char *algo_name, *algo_elems;
1361 int flags;
1362 gcry_err_code_t rc;
1363 gcry_pk_spec_t *pubkey = NULL;
1364 gcry_module_t module = NULL;
1365
1366 REGISTER_DEFAULT_PUBKEYS;
1367
1368 *r_ciph = NULL;
1369 /* get the key */
1370 rc = sexp_to_key (s_pkey, 0, &pkey, &module);
1371 if (rc)
1372 goto leave;
1373
1374 assert (module);
1375 pubkey = (gcry_pk_spec_t *) module->spec;
1376
1377 /* If aliases for the algorithm name exists, take the first one
1378 instead of the regular name to adhere to SPKI conventions. We
1379 assume that the first alias name is the lowercase version of the
1380 regular one. This change is required for compatibility with
1381 1.1.12 generated S-expressions. */
1382 algo_name = pubkey->aliases? *pubkey->aliases : NULL;
1383 if (!algo_name || !*algo_name)
1384 algo_name = pubkey->name;
1385
1386 algo_elems = pubkey->elements_enc;
1387
1388 /* Get the stuff we want to encrypt. */
1389 rc = sexp_data_to_mpi (s_data, gcry_pk_get_nbits (s_pkey), &data, 1,
1390 &flags);
1391 if (rc)
1392 goto leave;
1393
1394 /* Now we can encrypt DATA to CIPH. */
1395 ciph = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*ciph));
1396 rc = pubkey_encrypt (module->mod_id, ciph, data, pkey, flags);
1397 mpi_free (data);
1398 data = NULL;
1399 if (rc)
1400 goto leave;
1401
1402 /* We did it. Now build the return list */
1403 {
1404 char *string, *p;
1405 int i;
1406 size_t nelem = strlen (algo_elems);
1407 size_t needed = 19 + strlen (algo_name) + (nelem * 5);
1408 void **arg_list;
1409
1410 /* Build the string. */
1411 string = p = gcry_xmalloc (needed);
1412 p = stpcpy ( p, "(enc-val(" );
1413 p = stpcpy ( p, algo_name );
1414 for (i=0; algo_elems[i]; i++ )
1415 {
1416 *p++ = '(';
1417 *p++ = algo_elems[i];
1418 p = stpcpy ( p, "%m)" );
1419 }
1420 strcpy ( p, "))" );
1421
1422 /* And now the ugly part: We don't have a function to pass an
1423 * array to a format string, so we have to do it this way :-(. */
1424 /* FIXME: There is now such a format spefier, so we can could
1425 change the code to be more clear. */
1426 arg_list = malloc (nelem * sizeof *arg_list);
1427 if (!arg_list)
1428 {
1429 rc = gpg_err_code_from_errno (errno);
1430 goto leave;
1431 }
1432
1433 for (i = 0; i < nelem; i++)
1434 arg_list[i] = ciph + i;
1435
1436 rc = gcry_sexp_build_array (r_ciph, NULL, string, arg_list);
1437 free (arg_list);
1438 if (rc)
1439 BUG ();
1440 gcry_free (string);
1441 }
1442
1443 leave:
1444 if (pkey)
1445 {
1446 release_mpi_array (pkey);
1447 gcry_free (pkey);
1448 }
1449
1450 if (ciph)
1451 {
1452 release_mpi_array (ciph);
1453 gcry_free (ciph);
1454 }
1455
1456 if (module)
1457 {
1458 ath_mutex_lock (&pubkeys_registered_lock);
1459 _gcry_module_release (module);
1460 ath_mutex_unlock (&pubkeys_registered_lock);
1461 }
1462
1463 return gcry_error (rc);
1464}
1465
1466/*
1467 Do a PK decrypt operation
1468
1469 Caller has to provide a secret key as the SEXP skey and data in a
1470 format as created by gcry_pk_encrypt. For historic reasons the
1471 function returns simply an MPI as an S-expression part; this is
1472 deprecated and the new method should be used which returns a real
1473 S-expressionl this is selected by adding at least an empty flags
1474 list to S_DATA.
1475
1476 Returns: 0 or an errorcode.
1477
1478 s_data = (enc-val
1479 [(flags)]
1480 (<algo>
1481 (<param_name1> <mpi>)
1482 ...
1483 (<param_namen> <mpi>)
1484 ))
1485 s_skey = <key-as-defined-in-sexp_to_key>
1486 r_plain= Either an incomplete S-expression without the parentheses
1487 or if the flags list is used (even if empty) a real S-expression:
1488 (value PLAIN).
1489 */
1490gcry_error_t
1491gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey)
1492{
1493 gcry_mpi_t *skey = NULL, *data = NULL, plain = NULL;
1494 int modern, want_pkcs1, flags;
1495 gcry_err_code_t rc;
1496 gcry_module_t module_enc = NULL, module_key = NULL;
1497 gcry_pk_spec_t *pubkey = NULL;
1498
1499 REGISTER_DEFAULT_PUBKEYS;
1500
1501 *r_plain = NULL;
1502 rc = sexp_to_key (s_skey, 1, &skey, &module_key);
1503 if (rc)
1504 goto leave;
1505
1506 rc = sexp_to_enc (s_data, &data, &module_enc, &modern, &want_pkcs1, &flags);
1507 if (rc)
1508 goto leave;
1509
1510 if (module_key->mod_id != module_enc->mod_id)
1511 {
1512 rc = GPG_ERR_CONFLICT; /* Key algo does not match data algo. */
1513 goto leave;
1514 }
1515
1516 pubkey = (gcry_pk_spec_t *) module_key->spec;
1517
1518 rc = pubkey_decrypt (module_key->mod_id, &plain, data, skey, flags);
1519 if (rc)
1520 goto leave;
1521
1522 if (gcry_sexp_build (r_plain, NULL, modern? "(value %m)" : "%m", plain))
1523 BUG ();
1524
1525 leave:
1526 if (skey)
1527 {
1528 release_mpi_array (skey);
1529 gcry_free (skey);
1530 }
1531
1532 if (plain)
1533 mpi_free (plain);
1534
1535 if (data)
1536 {
1537 release_mpi_array (data);
1538 gcry_free (data);
1539 }
1540
1541 if (module_key || module_enc)
1542 {
1543 ath_mutex_lock (&pubkeys_registered_lock);
1544 if (module_key)
1545 _gcry_module_release (module_key);
1546 if (module_enc)
1547 _gcry_module_release (module_enc);
1548 ath_mutex_unlock (&pubkeys_registered_lock);
1549 }
1550
1551 return gcry_error (rc);
1552}
1553
1554
1555
1556/*
1557 Create a signature.
1558
1559 Caller has to provide a secret key as the SEXP skey and data
1560 expressed as a SEXP list hash with only one element which should
1561 instantly be available as a MPI. Alternatively the structure given
1562 below may be used for S_HASH, it provides the abiliy to pass flags
1563 to the operation; the only flag defined by now is "pkcs1" which
1564 does PKCS#1 block type 1 style padding.
1565
1566 Returns: 0 or an errorcode.
1567 In case of 0 the function returns a new SEXP with the
1568 signature value; the structure of this signature depends on the
1569 other arguments but is always suitable to be passed to
1570 gcry_pk_verify
1571
1572 s_hash = See comment for sexp_data_to_mpi
1573
1574 s_skey = <key-as-defined-in-sexp_to_key>
1575 r_sig = (sig-val
1576 (<algo>
1577 (<param_name1> <mpi>)
1578 ...
1579 (<param_namen> <mpi>)))
1580*/
1581gcry_error_t
1582gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey)
1583{
1584 gcry_mpi_t *skey = NULL, hash = NULL, *result = NULL;
1585 gcry_pk_spec_t *pubkey = NULL;
1586 gcry_module_t module = NULL;
1587 const char *algo_name, *algo_elems;
1588 int i;
1589 gcry_err_code_t rc;
1590
1591 REGISTER_DEFAULT_PUBKEYS;
1592
1593 *r_sig = NULL;
1594 rc = sexp_to_key (s_skey, 1, &skey, &module);
1595 if (rc)
1596 goto leave;
1597
1598 assert (module);
1599 pubkey = (gcry_pk_spec_t *) module->spec;
1600 algo_name = pubkey->aliases? *pubkey->aliases : NULL;
1601 if (!algo_name || !*algo_name)
1602 algo_name = pubkey->name;
1603
1604 algo_elems = pubkey->elements_sig;
1605
1606 /* Get the stuff we want to sign. Note that pk_get_nbits does also
1607 work on a private key. */
1608 rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_skey),
1609 &hash, 0, NULL);
1610 if (rc)
1611 goto leave;
1612
1613 result = gcry_xcalloc (strlen (algo_elems) + 1, sizeof (*result));
1614 rc = pubkey_sign (module->mod_id, result, hash, skey);
1615 if (rc)
1616 goto leave;
1617
1618 {
1619 char *string, *p;
1620 size_t nelem, needed = strlen (algo_name) + 20;
1621 void **arg_list;
1622
1623 nelem = strlen (algo_elems);
1624
1625 /* Count elements, so that we can allocate enough space. */
1626 needed += 10 * nelem;
1627
1628 /* Build the string. */
1629 string = p = gcry_xmalloc (needed);
1630 p = stpcpy (p, "(sig-val(");
1631 p = stpcpy (p, algo_name);
1632 for (i = 0; algo_elems[i]; i++)
1633 {
1634 *p++ = '(';
1635 *p++ = algo_elems[i];
1636 p = stpcpy (p, "%m)");
1637 }
1638 strcpy (p, "))");
1639
1640 arg_list = malloc (nelem * sizeof *arg_list);
1641 if (!arg_list)
1642 {
1643 rc = gpg_err_code_from_errno (errno);
1644 goto leave;
1645 }
1646
1647 for (i = 0; i < nelem; i++)
1648 arg_list[i] = result + i;
1649
1650 rc = gcry_sexp_build_array (r_sig, NULL, string, arg_list);
1651 free (arg_list);
1652 if (rc)
1653 BUG ();
1654 gcry_free (string);
1655 }
1656
1657 leave:
1658 if (skey)
1659 {
1660 release_mpi_array (skey);
1661 gcry_free (skey);
1662 }
1663
1664 if (hash)
1665 mpi_free (hash);
1666
1667 if (result)
1668 gcry_free (result);
1669
1670 return gcry_error (rc);
1671}
1672
1673
1674/*
1675 Verify a signature.
1676
1677 Caller has to supply the public key pkey, the signature sig and his
1678 hashvalue data. Public key has to be a standard public key given
1679 as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data
1680 must be an S-Exp like the one in sign too. */
1681gcry_error_t
1682gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey)
1683{
1684 gcry_module_t module_key = NULL, module_sig = NULL;
1685 gcry_mpi_t *pkey = NULL, hash = NULL, *sig = NULL;
1686 gcry_err_code_t rc;
1687
1688 REGISTER_DEFAULT_PUBKEYS;
1689
1690 rc = sexp_to_key (s_pkey, 0, &pkey, &module_key);
1691 if (rc)
1692 goto leave;
1693
1694 rc = sexp_to_sig (s_sig, &sig, &module_sig);
1695 if (rc)
1696 goto leave;
1697
1698 if (module_key->mod_id != module_sig->mod_id)
1699 {
1700 rc = GPG_ERR_CONFLICT;
1701 goto leave;
1702 }
1703
1704 rc = sexp_data_to_mpi (s_hash, gcry_pk_get_nbits (s_pkey), &hash, 0, 0);
1705 if (rc)
1706 goto leave;
1707
1708 rc = pubkey_verify (module_key->mod_id, hash, sig, pkey, NULL, NULL);
1709
1710 leave:
1711 if (pkey)
1712 {
1713 release_mpi_array (pkey);
1714 gcry_free (pkey);
1715 }
1716 if (sig)
1717 {
1718 release_mpi_array (sig);
1719 gcry_free (sig);
1720 }
1721 if (hash)
1722 mpi_free (hash);
1723
1724 if (module_key || module_sig)
1725 {
1726 ath_mutex_lock (&pubkeys_registered_lock);
1727 if (module_key)
1728 _gcry_module_release (module_key);
1729 if (module_sig)
1730 _gcry_module_release (module_sig);
1731 ath_mutex_unlock (&pubkeys_registered_lock);
1732 }
1733
1734 return gcry_error (rc);
1735}
1736
1737
1738/*
1739 Test a key.
1740
1741 This may be used either for a public or a secret key to see whether
1742 internal structre is valid.
1743
1744 Returns: 0 or an errorcode.
1745
1746 s_key = <key-as-defined-in-sexp_to_key> */
1747gcry_error_t
1748gcry_pk_testkey (gcry_sexp_t s_key)
1749{
1750 gcry_module_t module = NULL;
1751 gcry_mpi_t *key = NULL;
1752 gcry_err_code_t rc;
1753
1754 REGISTER_DEFAULT_PUBKEYS;
1755
1756 /* Note we currently support only secret key checking. */
1757 rc = sexp_to_key (s_key, 1, &key, &module);
1758 if (! rc)
1759 {
1760 rc = pubkey_check_secret_key (module->mod_id, key);
1761 release_mpi_array (key);
1762 gcry_free (key);
1763 }
1764 return gcry_error (rc);
1765}
1766
1767
1768/*
1769 Create a public key pair and return it in r_key.
1770 How the key is created depends on s_parms:
1771 (genkey
1772 (algo
1773 (parameter_name_1 ....)
1774 ....
1775 (parameter_name_n ....)
1776 ))
1777 The key is returned in a format depending on the
1778 algorithm. Both, private and secret keys are returned
1779 and optionally some additional informatin.
1780 For elgamal we return this structure:
1781 (key-data
1782 (public-key
1783 (elg
1784 (p <mpi>)
1785 (g <mpi>)
1786 (y <mpi>)
1787 )
1788 )
1789 (private-key
1790 (elg
1791 (p <mpi>)
1792 (g <mpi>)
1793 (y <mpi>)
1794 (x <mpi>)
1795 )
1796 )
1797 (misc-key-info
1798 (pm1-factors n1 n2 ... nn)
1799 ))
1800 */
1801gcry_error_t
1802gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms)
1803{
1804 gcry_pk_spec_t *pubkey = NULL;
1805 gcry_module_t module = NULL;
1806 gcry_sexp_t list = NULL, l2 = NULL;
1807 const char *name;
1808 size_t n;
1809 gcry_err_code_t rc = GPG_ERR_NO_ERROR;
1810 int i;
1811 const char *algo_name = NULL;
1812 int algo;
1813 const char *sec_elems = NULL, *pub_elems = NULL;
1814 gcry_mpi_t skey[10], *factors = NULL;
1815 unsigned int nbits = 0;
1816 unsigned long use_e = 0;
1817 char *name_terminated;
1818
1819 REGISTER_DEFAULT_PUBKEYS;
1820
1821 skey[0] = NULL;
1822 *r_key = NULL;
1823
1824 list = gcry_sexp_find_token (s_parms, "genkey", 0);
1825 if (!list)
1826 {
1827 rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */
1828 goto leave;
1829 }
1830
1831 l2 = gcry_sexp_cadr (list);
1832 gcry_sexp_release (list);
1833 list = l2;
1834 l2 = NULL;
1835 if (! list)
1836 {
1837 rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */
1838 goto leave;
1839 }
1840
1841 name = gcry_sexp_nth_data (list, 0, &n);
1842 if (! name)
1843 {
1844 rc = GPG_ERR_INV_OBJ; /* Algo string missing. */
1845 goto leave;
1846 }
1847
1848 name_terminated = gcry_xmalloc (n + 1);
1849 memcpy (name_terminated, name, n);
1850 name_terminated[n] = 0;
1851 ath_mutex_lock (&pubkeys_registered_lock);
1852 module = gcry_pk_lookup_name (name_terminated);
1853 ath_mutex_unlock (&pubkeys_registered_lock);
1854 gcry_free (name_terminated);
1855
1856 if (! module)
1857 {
1858 rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */
1859 goto leave;
1860 }
1861
1862 pubkey = (gcry_pk_spec_t *) module->spec;
1863 algo = module->mod_id;
1864 algo_name = pubkey->aliases? *pubkey->aliases : NULL;
1865 if (!algo_name || !*algo_name)
1866 algo_name = pubkey->name;
1867 pub_elems = pubkey->elements_pkey;
1868 sec_elems = pubkey->elements_skey;
1869
1870 /* Handle the optional rsa-use-e element. */
1871 l2 = gcry_sexp_find_token (list, "rsa-use-e", 0);
1872 if (l2)
1873 {
1874 char buf[50];
1875
1876 name = gcry_sexp_nth_data (l2, 1, &n);
1877 if ((! name) || (n >= DIM (buf) - 1))
1878 {
1879 rc = GPG_ERR_INV_OBJ; /* No value or value too large. */
1880 goto leave;
1881 }
1882 memcpy (buf, name, n);
1883 buf[n] = 0;
1884 use_e = strtoul (buf, NULL, 0);
1885 gcry_sexp_release (l2);
1886 l2 = NULL;
1887 }
1888 else
1889 use_e = 65537; /* Not given, use the value generated by old versions. */
1890
1891 l2 = gcry_sexp_find_token (list, "nbits", 0);
1892 gcry_sexp_release (list);
1893 list = l2;
1894 l2 = NULL;
1895
1896 if (! list)
1897 {
1898 rc = GPG_ERR_NO_OBJ; /* No nbits parameter. */
1899 goto leave;
1900 }
1901
1902 name = gcry_sexp_nth_data (list, 1, &n);
1903 if (! name)
1904 {
1905 rc = GPG_ERR_INV_OBJ; /* nbits without a cdr. */
1906 goto leave;
1907 }
1908
1909 name_terminated = gcry_xmalloc (n + 1);
1910 memcpy (name_terminated, name, n);
1911 name_terminated[n] = 0;
1912 nbits = (unsigned int) strtoul (name_terminated, NULL, 0);
1913 gcry_free (name_terminated);
1914
1915 rc = pubkey_generate (module->mod_id, nbits, use_e, skey, &factors);
1916 if (rc)
1917 goto leave;
1918
1919 {
1920 char *string, *p;
1921 size_t nelem=0, nelem_cp = 0, needed=0;
1922 gcry_mpi_t mpis[30];
1923
1924 nelem = strlen (pub_elems) + strlen (sec_elems);
1925 for (i = 0; factors[i]; i++)
1926 nelem++;
1927 nelem_cp = nelem;
1928
1929 needed += nelem * 10;
1930 needed += 2 * strlen (algo_name) + 300;
1931 if (nelem > DIM (mpis))
1932 BUG ();
1933
1934 /* Build the string. */
1935 nelem = 0;
1936 string = p = gcry_xmalloc (needed);
1937 p = stpcpy (p, "(key-data");
1938 p = stpcpy (p, "(public-key(");
1939 p = stpcpy (p, algo_name);
1940 for(i = 0; pub_elems[i]; i++)
1941 {
1942 *p++ = '(';
1943 *p++ = pub_elems[i];
1944 p = stpcpy (p, "%m)");
1945 mpis[nelem++] = skey[i];
1946 }
1947 p = stpcpy (p, "))");
1948 p = stpcpy (p, "(private-key(");
1949 p = stpcpy (p, algo_name);
1950 for (i = 0; sec_elems[i]; i++)
1951 {
1952 *p++ = '(';
1953 *p++ = sec_elems[i];
1954 p = stpcpy (p, "%m)");
1955 mpis[nelem++] = skey[i];
1956 }
1957 p = stpcpy (p, "))");
1958
1959 /* Very ugly hack to make release_mpi_array() work FIXME */
1960 skey[i] = NULL;
1961
1962 p = stpcpy (p, "(misc-key-info(pm1-factors");
1963 for(i = 0; factors[i]; i++)
1964 {
1965 p = stpcpy (p, "%m");
1966 mpis[nelem++] = factors[i];
1967 }
1968 strcpy (p, ")))");
1969
1970 while (nelem < DIM (mpis))
1971 mpis[nelem++] = NULL;
1972
1973 {
1974 int elem_n = strlen (pub_elems) + strlen (sec_elems);
1975 void **arg_list;
1976
1977 arg_list = malloc (nelem_cp * sizeof *arg_list);
1978 if (!arg_list)
1979 {
1980 rc = gpg_err_code_from_errno (errno);
1981 goto leave;
1982 }
1983 for (i = 0; i < elem_n; i++)
1984 arg_list[i] = mpis + i;
1985 for (; i < nelem_cp; i++)
1986 arg_list[i] = factors + i - elem_n;
1987
1988 rc = gcry_sexp_build_array (r_key, NULL, string, arg_list);
1989 free (arg_list);
1990 if (rc)
1991 BUG ();
1992 assert (DIM (mpis) == 30); /* Reminder to make sure that the
1993 array gets increased if new
1994 parameters are added. */
1995 }
1996 gcry_free (string);
1997 }
1998
1999 leave:
2000 release_mpi_array (skey);
2001 /* Don't free SKEY itself, it is a static array. */
2002
2003 if (factors)
2004 {
2005 release_mpi_array ( factors );
2006 gcry_free (factors);
2007 }
2008
2009 if (l2)
2010 gcry_sexp_release (l2);
2011 if (list)
2012 gcry_sexp_release (list);
2013
2014 if (module)
2015 {
2016 ath_mutex_lock (&pubkeys_registered_lock);
2017 _gcry_module_release (module);
2018 ath_mutex_unlock (&pubkeys_registered_lock);
2019 }
2020
2021 return gcry_error (rc);
2022}
2023
2024
2025/*
2026 Get the number of nbits from the public key.
2027
2028 Hmmm: Should we have really this function or is it better to have a
2029 more general function to retrieve different propoerties of the key? */
2030unsigned int
2031gcry_pk_get_nbits (gcry_sexp_t key)
2032{
2033 gcry_module_t module = NULL;
2034 gcry_pk_spec_t *pubkey;
2035 gcry_mpi_t *keyarr = NULL;
2036 unsigned int nbits = 0;
2037 gcry_err_code_t rc;
2038
2039 REGISTER_DEFAULT_PUBKEYS;
2040
2041 rc = sexp_to_key (key, 0, &keyarr, &module);
2042 if (rc == GPG_ERR_INV_OBJ)
2043 rc = sexp_to_key (key, 1, &keyarr, &module);
2044 if (rc)
2045 return 0; /* Error - 0 is a suitable indication for that. */
2046
2047 pubkey = (gcry_pk_spec_t *) module->spec;
2048 nbits = (*pubkey->get_nbits) (module->mod_id, keyarr);
2049
2050 ath_mutex_lock (&pubkeys_registered_lock);
2051 _gcry_module_release (module);
2052 ath_mutex_unlock (&pubkeys_registered_lock);
2053
2054 release_mpi_array (keyarr);
2055 gcry_free (keyarr);
2056
2057 return nbits;
2058}
2059
2060
2061/* Return the so called KEYGRIP which is the SHA-1 hash of the public
2062 key parameters expressed in a way depended on the algorithm.
2063
2064 ARRAY must either be 20 bytes long or NULL; in the latter case a
2065 newly allocated array of that size is returned, otherwise ARRAY or
2066 NULL is returned to indicate an error which is most likely an
2067 unknown algorithm. The function accepts public or secret keys. */
2068unsigned char *
2069gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
2070{
2071 gcry_sexp_t list = NULL, l2 = NULL;
2072 gcry_pk_spec_t *pubkey = NULL;
2073 gcry_module_t module = NULL;
2074 const char *s, *name;
2075 size_t n;
2076 int idx;
2077 int is_rsa;
2078 const char *elems;
2079 gcry_md_hd_t md = NULL;
2080
2081 REGISTER_DEFAULT_PUBKEYS;
2082
2083 /* Check that the first element is valid. */
2084 list = gcry_sexp_find_token (key, "public-key", 0);
2085 if (! list)
2086 list = gcry_sexp_find_token (key, "private-key", 0);
2087 if (! list)
2088 list = gcry_sexp_find_token (key, "protected-private-key", 0);
2089 if (! list)
2090 return NULL; /* No public- or private-key object. */
2091
2092 l2 = gcry_sexp_cadr (list);
2093 gcry_sexp_release (list);
2094 list = l2;
2095 l2 = NULL;
2096
2097 name = gcry_sexp_nth_data (list, 0, &n);
2098 if (! name)
2099 goto fail; /* Invalid structure of object. */
2100
2101 {
2102 char *name_terminated = gcry_xmalloc (n + 1);
2103 memcpy (name_terminated, name, n);
2104 name_terminated[n] = 0;
2105 ath_mutex_lock (&pubkeys_registered_lock);
2106 module = gcry_pk_lookup_name (name_terminated);
2107 ath_mutex_unlock (&pubkeys_registered_lock);
2108 gcry_free (name_terminated);
2109 }
2110
2111 if (! module)
2112 goto fail; /* unknown algorithm */
2113
2114 pubkey = (gcry_pk_spec_t *) module->spec;
2115
2116 /* FIXME, special handling should be implemented by the algorithms,
2117 not by the libgcrypt core. */
2118 is_rsa = module->mod_id == GCRY_PK_RSA;
2119 elems = pubkey->elements_grip;
2120 if (! elems)
2121 goto fail; /* no grip parameter */
2122
2123 if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
2124 goto fail;
2125
2126 for (idx = 0, s = elems; *s; s++, idx++)
2127 {
2128 const char *data;
2129 size_t datalen;
2130
2131 l2 = gcry_sexp_find_token (list, s, 1);
2132 if (! l2)
2133 goto fail;
2134 data = gcry_sexp_nth_data (l2, 1, &datalen);
2135 if (! data)
2136 goto fail;
2137 if (!is_rsa)
2138 {
2139 char buf[30];
2140
2141 sprintf (buf, "(1:%c%u:", *s, (unsigned int)datalen);
2142 gcry_md_write (md, buf, strlen (buf));
2143 }
2144
2145 /* PKCS-15 says that for RSA only the modulus should be hashed -
2146 however, it is not clear wether this is meant to has the raw
2147 bytes assuming this is an unsigned integer or whether the DER
2148 required 0 should be prefixed. We hash the raw bytes. For
2149 non-RSA we hash S-expressions. */
2150 gcry_md_write (md, data, datalen);
2151 gcry_sexp_release (l2);
2152 if (!is_rsa)
2153 gcry_md_write (md, ")", 1);
2154 }
2155
2156 if (!array)
2157 {
2158 array = gcry_malloc (20);
2159 if (! array)
2160 goto fail;
2161 }
2162
2163 memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
2164 gcry_md_close (md);
2165 gcry_sexp_release (list);
2166 return array;
2167
2168 fail:
2169 if (l2)
2170 gcry_sexp_release (l2);
2171 if (md)
2172 gcry_md_close (md);
2173 gcry_sexp_release (list);
2174 return NULL;
2175}
2176
2177
2178gcry_error_t
2179gcry_pk_ctl (int cmd, void *buffer, size_t buflen)
2180{
2181 gcry_err_code_t err = GPG_ERR_NO_ERROR;
2182
2183 REGISTER_DEFAULT_PUBKEYS;
2184
2185 switch (cmd)
2186 {
2187 case GCRYCTL_DISABLE_ALGO:
2188 /* This one expects a buffer pointing to an integer with the
2189 algo number. */
2190 if ((! buffer) || (buflen != sizeof (int)))
2191 err = GPG_ERR_INV_ARG;
2192 else
2193 disable_pubkey_algo (*((int *) buffer));
2194 break;
2195
2196 default:
2197 err = GPG_ERR_INV_OP;
2198 }
2199
2200 return gcry_error (err);
2201}
2202
2203
2204/*
2205 Return information about the given algorithm
2206 WHAT select the kind of information returned:
2207 GCRYCTL_TEST_ALGO:
2208 Returns 0 when the specified algorithm is available for use.
2209 Buffer must be NULL, nbytes may have the address of a variable
2210 with the required usage of the algorithm. It may be 0 for don't
2211 care or a combination of the GCRY_PK_USAGE_xxx flags;
2212 GCRYCTL_GET_ALGO_USAGE:
2213 Return the usage glafs for the give algo. An invalid alog
2214 does return 0. Disabled algos are ignored here becuase we
2215 only want to know whether the algo is at all capable of
2216 the usage.
2217
2218 Note: Because this function is in most cases used to return an
2219 integer value, we can make it easier for the caller to just look at
2220 the return value. The caller will in all cases consult the value
2221 and thereby detecting whether a error occured or not (i.e. while
2222 checking the block size) */
2223gcry_error_t
2224gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes)
2225{
2226 gcry_err_code_t err = GPG_ERR_NO_ERROR;
2227
2228 switch (what)
2229 {
2230 case GCRYCTL_TEST_ALGO:
2231 {
2232 int use = nbytes ? *nbytes : 0;
2233 if (buffer)
2234 err = GPG_ERR_INV_ARG;
2235 else if (check_pubkey_algo (algorithm, use))
2236 err = GPG_ERR_PUBKEY_ALGO;
2237 break;
2238 }
2239
2240 case GCRYCTL_GET_ALGO_USAGE:
2241 {
2242 gcry_module_t pubkey;
2243 int use = 0;
2244
2245 REGISTER_DEFAULT_PUBKEYS;
2246
2247 ath_mutex_lock (&pubkeys_registered_lock);
2248 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
2249 if (pubkey)
2250 {
2251 use = ((gcry_pk_spec_t *) pubkey->spec)->use;
2252 _gcry_module_release (pubkey);
2253 }
2254 ath_mutex_unlock (&pubkeys_registered_lock);
2255
2256 /* FIXME? */
2257 *nbytes = use;
2258 }
2259
2260 case GCRYCTL_GET_ALGO_NPKEY:
2261 {
2262 /* FIXME? */
2263 int npkey = pubkey_get_npkey (algorithm);
2264 *nbytes = npkey;
2265 break;
2266 }
2267 case GCRYCTL_GET_ALGO_NSKEY:
2268 {
2269 /* FIXME? */
2270 int nskey = pubkey_get_nskey (algorithm);
2271 *nbytes = nskey;
2272 break;
2273 }
2274 case GCRYCTL_GET_ALGO_NSIGN:
2275 {
2276 /* FIXME? */
2277 int nsign = pubkey_get_nsig (algorithm);
2278 *nbytes = nsign;
2279 break;
2280 }
2281 case GCRYCTL_GET_ALGO_NENCR:
2282 {
2283 /* FIXME? */
2284 int nencr = pubkey_get_nenc (algorithm);
2285 *nbytes = nencr;
2286 break;
2287 }
2288
2289 default:
2290 err = GPG_ERR_INV_OP;
2291 }
2292
2293 return gcry_error (err);
2294}
2295
2296
2297gcry_err_code_t
2298_gcry_pk_init (void)
2299{
2300 gcry_err_code_t err = GPG_ERR_NO_ERROR;
2301
2302 REGISTER_DEFAULT_PUBKEYS;
2303
2304 return err;
2305}
2306
2307
2308gcry_err_code_t
2309_gcry_pk_module_lookup (int algorithm, gcry_module_t *module)
2310{
2311 gcry_err_code_t err = GPG_ERR_NO_ERROR;
2312 gcry_module_t pubkey;
2313
2314 REGISTER_DEFAULT_PUBKEYS;
2315
2316 ath_mutex_lock (&pubkeys_registered_lock);
2317 pubkey = _gcry_module_lookup_id (pubkeys_registered, algorithm);
2318 if (pubkey)
2319 *module = pubkey;
2320 else
2321 err = GPG_ERR_PUBKEY_ALGO;
2322 ath_mutex_unlock (&pubkeys_registered_lock);
2323
2324 return err;
2325}
2326
2327
2328void
2329_gcry_pk_module_release (gcry_module_t module)
2330{
2331 ath_mutex_lock (&pubkeys_registered_lock);
2332 _gcry_module_release (module);
2333 ath_mutex_unlock (&pubkeys_registered_lock);
2334}
2335
2336/* Get a list consisting of the IDs of the loaded pubkey modules. If
2337 LIST is zero, write the number of loaded pubkey modules to
2338 LIST_LENGTH and return. If LIST is non-zero, the first
2339 *LIST_LENGTH algorithm IDs are stored in LIST, which must be of
2340 according size. In case there are less pubkey modules than
2341 *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */
2342gcry_error_t
2343gcry_pk_list (int *list, int *list_length)
2344{
2345 gcry_err_code_t err = GPG_ERR_NO_ERROR;
2346
2347 ath_mutex_lock (&pubkeys_registered_lock);
2348 err = _gcry_module_list (pubkeys_registered, list, list_length);
2349 ath_mutex_unlock (&pubkeys_registered_lock);
2350
2351 return err;
2352}