~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/lib/libgcrypt/cipher/pubkey.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

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