~ubuntu-branches/ubuntu/dapper/gnupg2/dapper

« back to all changes in this revision

Viewing changes to scd/sc-copykeys.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* sc-copykeys.c - A tool to store keys on a smartcard.
 
2
 *      Copyright (C) 2003 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GnuPG.
 
5
 *
 
6
 * GnuPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GnuPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
19
 */
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <assert.h>
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
#include <unistd.h>
 
30
 
 
31
#define JNLIB_NEED_LOG_LOGV
 
32
#include "scdaemon.h"
 
33
#include <gcrypt.h>
 
34
 
 
35
#include "../common/ttyio.h"
 
36
#include "../common/simple-pwquery.h"
 
37
#include "apdu.h" /* for open_reader */
 
38
#include "atr.h"
 
39
#include "app-common.h"
 
40
 
 
41
#define _(a) (a)
 
42
 
 
43
 
 
44
enum cmd_and_opt_values 
 
45
{ oVerbose        = 'v',
 
46
  oReaderPort     = 500,
 
47
  octapiDriver,
 
48
  oDebug,
 
49
  oDebugAll,
 
50
 
 
51
aTest };
 
52
 
 
53
 
 
54
static ARGPARSE_OPTS opts[] = {
 
55
  
 
56
  { 301, NULL, 0, "@Options:\n " },
 
57
 
 
58
  { oVerbose, "verbose",   0, "verbose" },
 
59
  { oReaderPort, "reader-port", 2, "|N|connect to reader at port N"},
 
60
  { octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"},
 
61
  { oDebug,     "debug"     ,4|16, "set debugging flags"},
 
62
  { oDebugAll, "debug-all" ,0, "enable full debugging"},
 
63
  {0}
 
64
};
 
65
 
 
66
 
 
67
static void copykeys (APP app, const char *fname);
 
68
 
 
69
 
 
70
static const char *
 
71
my_strusage (int level)
 
72
{
 
73
  const char *p;
 
74
  switch (level)
 
75
    {
 
76
    case 11: p = "sc-copykeys (GnuPG)";
 
77
      break;
 
78
    case 13: p = VERSION; break;
 
79
    case 17: p = PRINTABLE_OS_NAME; break;
 
80
    case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
 
81
      break;
 
82
    case 1:
 
83
    case 40: p =  _("Usage: sc-copykeys [options] (-h for help)\n");
 
84
      break;
 
85
    case 41: p = _("Syntax: sc-copykeys [options] "
 
86
                   "file-with-key\n"
 
87
                    "Copy keys to a smartcards\n");
 
88
    break;
 
89
    
 
90
    default: p = NULL;
 
91
    }
 
92
  return p;
 
93
}
 
94
 
 
95
/* Used by gcry for logging */
 
96
static void
 
97
my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
 
98
{
 
99
  /* translate the log levels */
 
100
  switch (level)
 
101
    {
 
102
    case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break;
 
103
    case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break;
 
104
    case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break;
 
105
    case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break;
 
106
    case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
 
107
    case GCRY_LOG_BUG:  level = JNLIB_LOG_BUG; break;
 
108
    case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
 
109
    default:            level = JNLIB_LOG_ERROR; break;  
 
110
    }
 
111
  log_logv (level, fmt, arg_ptr);
 
112
}
 
113
 
 
114
 
 
115
int
 
116
main (int argc, char **argv )
 
117
{
 
118
  ARGPARSE_ARGS pargs;
 
119
  int slot, rc;
 
120
  const char *reader_port = NULL;
 
121
  struct app_ctx_s appbuf;
 
122
 
 
123
  memset (&appbuf, 0, sizeof appbuf);
 
124
 
 
125
  set_strusage (my_strusage);
 
126
  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
 
127
  log_set_prefix ("sc-copykeys", 1); 
 
128
 
 
129
  /* check that the libraries are suitable.  Do it here because
 
130
     the option parsing may need services of the library */
 
131
  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
 
132
    {
 
133
      log_fatal( _("libgcrypt is too old (need %s, have %s)\n"),
 
134
                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
 
135
    }
 
136
 
 
137
  gcry_set_log_handler (my_gcry_logger, NULL);
 
138
  gcry_control (GCRYCTL_DISABLE_SECMEM, 0); /* FIXME - we want to use it */
 
139
  /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
 
140
 
 
141
  pargs.argc = &argc;
 
142
  pargs.argv = &argv;
 
143
  pargs.flags=  1;  /* do not remove the args */
 
144
  while (arg_parse (&pargs, opts) )
 
145
    {
 
146
      switch (pargs.r_opt)
 
147
        {
 
148
        case oVerbose: opt.verbose++; break;
 
149
        case oDebug: opt.debug |= pargs.r.ret_ulong; break;
 
150
        case oDebugAll: opt.debug = ~0; break;
 
151
        case oReaderPort: reader_port = pargs.r.ret_str; break;
 
152
        case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
 
153
        default : pargs.err = 2; break;
 
154
        }
 
155
    }
 
156
  if (log_get_errorcount(0))
 
157
    exit(2);
 
158
 
 
159
  if (argc != 1)
 
160
    usage (1);
 
161
 
 
162
  slot = apdu_open_reader (reader_port);
 
163
  if (slot == -1)
 
164
    exit (1);
 
165
 
 
166
  /* FIXME: Use select_application. */
 
167
  appbuf.slot = slot;
 
168
  rc = app_select_openpgp (&appbuf);
 
169
  if (rc)
 
170
    {
 
171
      log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc));
 
172
      exit (1);
 
173
    }
 
174
  appbuf.initialized = 1;
 
175
  log_info ("openpgp application selected\n");
 
176
 
 
177
  copykeys (&appbuf, *argv);
 
178
 
 
179
 
 
180
  return 0;
 
181
}
 
182
 
 
183
 
 
184
 
 
185
void
 
186
send_status_info (CTRL ctrl, const char *keyword, ...)
 
187
{
 
188
  /* DUMMY */
 
189
}
 
190
 
 
191
 
 
192
 
 
193
static char *
 
194
read_file (const char *fname, size_t *r_length)
 
195
{
 
196
  FILE *fp;
 
197
  struct stat st;
 
198
  char *buf;
 
199
  size_t buflen;
 
200
  
 
201
  fp = fname? fopen (fname, "rb") : stdin;
 
202
  if (!fp)
 
203
    {
 
204
      log_error ("can't open `%s': %s\n",
 
205
                 fname? fname: "[stdin]", strerror (errno));
 
206
      return NULL;
 
207
    }
 
208
  
 
209
  if (fstat (fileno(fp), &st))
 
210
    {
 
211
      log_error ("can't stat `%s': %s\n", 
 
212
                 fname? fname: "[stdin]", strerror (errno));
 
213
      if (fname)
 
214
        fclose (fp);
 
215
      return NULL;
 
216
    }
 
217
 
 
218
  buflen = st.st_size;
 
219
  buf = xmalloc (buflen+1);
 
220
  if (fread (buf, buflen, 1, fp) != 1)
 
221
    {
 
222
      log_error ("error reading `%s': %s\n", 
 
223
                 fname? fname: "[stdin]", strerror (errno));
 
224
      if (fname)
 
225
        fclose (fp);
 
226
      xfree (buf);
 
227
      return NULL;
 
228
    }
 
229
  if (fname)
 
230
    fclose (fp);
 
231
 
 
232
  *r_length = buflen;
 
233
  return buf;
 
234
}
 
235
 
 
236
 
 
237
static gcry_sexp_t
 
238
read_key (const char *fname)
 
239
{
 
240
  char *buf;
 
241
  size_t buflen;
 
242
  gcry_sexp_t private;
 
243
  int rc;
 
244
  
 
245
  buf = read_file (fname, &buflen);
 
246
  if (!buf)
 
247
    return NULL;
 
248
 
 
249
  rc = gcry_sexp_new (&private, buf, buflen, 1);
 
250
  if (rc)
 
251
    {
 
252
      log_error ("gcry_sexp_new failed: %s\n", gpg_strerror (rc));
 
253
      return NULL;
 
254
    } 
 
255
  xfree (buf);
 
256
 
 
257
  return private;
 
258
}
 
259
 
 
260
 
 
261
 
 
262
static gcry_mpi_t *
 
263
sexp_to_kparms (gcry_sexp_t sexp, unsigned long *created)
 
264
{
 
265
  gcry_sexp_t list, l2;
 
266
  const char *name;
 
267
  const char *s;
 
268
  size_t n;
 
269
  int i, idx;
 
270
  const char *elems;
 
271
  gcry_mpi_t *array;
 
272
 
 
273
  *created = 0;
 
274
  list = gcry_sexp_find_token (sexp, "private-key", 0 );
 
275
  if(!list)
 
276
    return NULL; 
 
277
 
 
278
  /* quick hack to get the creation time. */
 
279
  l2 = gcry_sexp_find_token (list, "created", 0);
 
280
  if (l2 && (name = gcry_sexp_nth_data (l2, 1, &n)))
 
281
    {
 
282
      char *tmp = xmalloc (n+1);
 
283
      memcpy (tmp, name, n);
 
284
      tmp[n] = 0;
 
285
      *created = strtoul (tmp, NULL, 10);
 
286
      xfree (tmp);
 
287
    }
 
288
  gcry_sexp_release (l2);
 
289
  l2 = gcry_sexp_cadr (list);
 
290
  gcry_sexp_release (list);
 
291
  list = l2;
 
292
  name = gcry_sexp_nth_data (list, 0, &n);
 
293
  if(!name || n != 3 || memcmp (name, "rsa", 3))
 
294
    {
 
295
      gcry_sexp_release (list);
 
296
      return NULL;
 
297
    }
 
298
 
 
299
  /* Parameter names used with RSA. */
 
300
  elems = "nedpqu";
 
301
  array = xcalloc (strlen(elems) + 1, sizeof *array);
 
302
  for (idx=0, s=elems; *s; s++, idx++ ) 
 
303
    {
 
304
      l2 = gcry_sexp_find_token (list, s, 1);
 
305
      if (!l2)
 
306
        {
 
307
          for (i=0; i<idx; i++)
 
308
            gcry_mpi_release (array[i]);
 
309
          xfree (array);
 
310
          gcry_sexp_release (list);
 
311
          return NULL; /* required parameter not found */
 
312
        }
 
313
      array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
 
314
      gcry_sexp_release (l2);
 
315
      if (!array[idx])
 
316
        {
 
317
          for (i=0; i<idx; i++)
 
318
            gcry_mpi_release (array[i]);
 
319
          xfree (array);
 
320
          gcry_sexp_release (list);
 
321
          return NULL; /* required parameter is invalid */
 
322
        }
 
323
    }
 
324
  
 
325
  gcry_sexp_release (list);
 
326
  return array;
 
327
}
 
328
 
 
329
 
 
330
/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
 
331
static int
 
332
fpr_is_zero (const char *fpr)
 
333
{
 
334
  int i;
 
335
 
 
336
  for (i=0; i < 20 && !fpr[i]; i++)
 
337
    ;
 
338
  return (i == 20);
 
339
}
 
340
 
 
341
 
 
342
static void
 
343
show_sha1_fpr (const unsigned char *fpr)
 
344
{
 
345
  int i;
 
346
 
 
347
  if (fpr)
 
348
    {
 
349
      for (i=0; i < 20 ; i+=2, fpr += 2 )
 
350
        {
 
351
          if (i == 10 )
 
352
            tty_printf (" ");
 
353
          tty_printf (" %02X%02X", *fpr, fpr[1]);
 
354
        }
 
355
    }
 
356
  else
 
357
    tty_printf (" [none]");
 
358
  tty_printf ("\n");
 
359
}
 
360
 
 
361
/* Query the card, show a list of already stored keys and ask the user
 
362
   where to store the key.  Returns the key number or 0 for cancel
 
363
   operation. */
 
364
static int
 
365
query_card (APP app)
 
366
{
 
367
  int keyno = 0;
 
368
  char *serialno, *disp_name, *pubkey_url;
 
369
  unsigned char *fpr1, *fpr2, *fpr3;
 
370
 
 
371
 
 
372
  if (app_openpgp_cardinfo (app,
 
373
                            &serialno,
 
374
                            &disp_name,
 
375
                            &pubkey_url,
 
376
                            &fpr1, &fpr2, &fpr3))
 
377
    return 0;
 
378
 
 
379
 
 
380
  for (;;)
 
381
    {
 
382
      char *answer;
 
383
 
 
384
      tty_printf ("\n");
 
385
 
 
386
      tty_printf ("Serial number ....: %s\n",
 
387
                  serialno? serialno : "[none]");
 
388
      tty_printf ("Name of cardholder: %s\n",
 
389
                  disp_name && *disp_name? disp_name : "[not set]");
 
390
      tty_printf ("URL of public key : %s\n",
 
391
                  pubkey_url && *pubkey_url? pubkey_url : "[not set]");
 
392
      tty_printf ("Signature key ....:");
 
393
      show_sha1_fpr (fpr1);
 
394
      tty_printf ("Encryption key....:");
 
395
      show_sha1_fpr (fpr2);
 
396
      tty_printf ("Authentication key:");
 
397
      show_sha1_fpr (fpr3);
 
398
 
 
399
      tty_printf ("\n"
 
400
                  "1 - store as signature key and reset usage counter\n"
 
401
                  "2 - store as encryption key\n"
 
402
                  "3 - store as authentication key\n"
 
403
                  "Q - quit\n"
 
404
                  "\n");
 
405
 
 
406
      answer = tty_get("Your selection? ");
 
407
      tty_kill_prompt();
 
408
      if (strlen (answer) != 1)
 
409
        ;
 
410
      else if ( *answer == '1' )
 
411
        {
 
412
          if ( (fpr1 && !fpr_is_zero (fpr1)) )
 
413
            {
 
414
              tty_printf ("\n");
 
415
              log_error ("WARNING: signature key does already exists!\n");
 
416
              tty_printf ("\n");
 
417
              if ( tty_get_answer_is_yes ("Replace existing key? ") )
 
418
                {
 
419
                  keyno = 1;
 
420
                  break;
 
421
                }
 
422
            }
 
423
          else
 
424
            {
 
425
              keyno = 1;
 
426
              break;
 
427
            }
 
428
        }
 
429
      else if ( *answer == '2' )
 
430
        {
 
431
          if ( (fpr2 && !fpr_is_zero (fpr2)) )
 
432
            {
 
433
              tty_printf ("\n");
 
434
              log_error ("WARNING: encryption key does already exists!\n");
 
435
              tty_printf ("\n");
 
436
              if ( tty_get_answer_is_yes ("Replace existing key? ") )
 
437
                {
 
438
                  keyno = 2;
 
439
                  break;
 
440
                }
 
441
            }
 
442
          else
 
443
            {
 
444
              keyno = 2;
 
445
              break;
 
446
            }
 
447
        }
 
448
      else if ( *answer == '3' )
 
449
        {
 
450
          if ( (fpr3 && !fpr_is_zero (fpr3)) )
 
451
            {
 
452
              tty_printf ("\n");
 
453
              log_error ("WARNING: authentication key does already exists!\n");
 
454
              tty_printf ("\n");
 
455
              if ( tty_get_answer_is_yes ("Replace existing key? ") )
 
456
                {
 
457
                  keyno = 3;
 
458
                  break;
 
459
                }
 
460
            }
 
461
          else
 
462
            {
 
463
              keyno = 3;
 
464
              break;
 
465
            }
 
466
        }
 
467
      else if ( *answer == 'q' || *answer == 'Q')
 
468
        {
 
469
          keyno = 0;
 
470
          break;
 
471
        }
 
472
    }
 
473
 
 
474
  xfree (serialno); 
 
475
  xfree (disp_name); 
 
476
  xfree (pubkey_url);
 
477
  xfree (fpr1);
 
478
  xfree (fpr2);
 
479
  xfree (fpr3);
 
480
 
 
481
  return keyno;
 
482
}
 
483
 
 
484
 
 
485
/* Callback function to ask for a PIN. */
 
486
static int 
 
487
pincb (void *arg, const char *prompt, char **pinvalue)
 
488
{
 
489
  char *pin = xstrdup ("12345678");
 
490
 
 
491
/*    pin = simple_pwquery (NULL, NULL, prompt, */
 
492
/*                          "We need the admin's PIN to store the key on the card", */
 
493
/*                          NULL); */
 
494
/*    if (!pin) */
 
495
/*      return gpg_error (GPG_ERR_CANCELED); */
 
496
 
 
497
 
 
498
 
 
499
  *pinvalue = pin;
 
500
  return 0;
 
501
}
 
502
 
 
503
 
 
504
/* This function expects a file (or NULL for stdin) with the secret
 
505
   and public key parameters.  This file should consist of an
 
506
   S-expression as used by gpg-agent. Only the unprotected format is
 
507
   supported.  Example:
 
508
 
 
509
   (private-key
 
510
    (rsa
 
511
     (n #00e0ce9..[some bytes not shown]..51#)
 
512
     (e #010001#)
 
513
     (d #046129F..[some bytes not shown]..81#)
 
514
     (p #00e861b..[some bytes not shown]..f1#)
 
515
     (q #00f7a7c..[some bytes not shown]..61#)
 
516
     (u #304559a..[some bytes not shown]..9b#))
 
517
    (uri http://foo.bar x-foo:whatever_you_want))
 
518
   
 
519
*/
 
520
static void
 
521
copykeys (APP app, const char *fname)
 
522
{
 
523
  int rc;
 
524
  gcry_sexp_t private;
 
525
  gcry_mpi_t *mpis, rsa_n, rsa_e, rsa_p, rsa_q;
 
526
  unsigned int nbits;
 
527
  size_t n;
 
528
  unsigned char *template, *tp;
 
529
  unsigned char m[128], e[4];
 
530
  size_t mlen, elen;
 
531
  unsigned long creation_date;
 
532
  time_t created_at;
 
533
  int keyno;
 
534
 
 
535
  if (!strcmp (fname, "-"))
 
536
    fname = NULL;
 
537
 
 
538
  private = read_key (fname);
 
539
  if (!private)
 
540
    exit (1);
 
541
  
 
542
  mpis = sexp_to_kparms (private, &creation_date);
 
543
  if (!creation_date)
 
544
    {
 
545
      log_info ("no creation date found - assuming current date\n");
 
546
      created_at = time (NULL);
 
547
    }
 
548
  else
 
549
    created_at = creation_date;
 
550
  gcry_sexp_release (private);
 
551
  if (!mpis)
 
552
    {
 
553
      log_error ("invalid structure of key file or not RSA\n");
 
554
      exit (1);
 
555
    }
 
556
  /* MPIS is now an array with the key parameters as defined by OpenPGP. */
 
557
  rsa_n = mpis[0];
 
558
  rsa_e = mpis[1];
 
559
  gcry_mpi_release (mpis[2]);
 
560
  rsa_p = mpis[3];
 
561
  rsa_q = mpis[4];
 
562
  gcry_mpi_release (mpis[5]);
 
563
  xfree (mpis);
 
564
 
 
565
  nbits = gcry_mpi_get_nbits (rsa_e);
 
566
  if (nbits < 2 || nbits > 32)
 
567
    {
 
568
      log_error ("public exponent too large (more than 32 bits)\n");
 
569
      goto failure;
 
570
    }
 
571
  nbits = gcry_mpi_get_nbits (rsa_p);
 
572
  if (nbits != 512)
 
573
    {
 
574
      log_error ("length of first RSA prime is not 512\n");
 
575
      goto failure;
 
576
    }
 
577
  nbits = gcry_mpi_get_nbits (rsa_q);
 
578
  if (nbits != 512)
 
579
    {
 
580
      log_error ("length of second RSA prime is not 512\n");
 
581
      goto failure;
 
582
    }
 
583
 
 
584
  nbits = gcry_mpi_get_nbits (rsa_n);
 
585
  if (nbits != 1024)
 
586
    {
 
587
      log_error ("length of RSA modulus is not 1024\n");
 
588
      goto failure;
 
589
    }
 
590
 
 
591
  keyno = query_card (app);
 
592
  if (!keyno)
 
593
    goto failure;
 
594
 
 
595
  /* Build the private key template as described in section 4.3.3.6 of
 
596
     the specs.
 
597
                   0xC0   <length> public exponent
 
598
                   0xC1   <length> prime p 
 
599
                   0xC2   <length> prime q  */
 
600
  template = tp = xmalloc (1+2 + 1+1+4 + 1+1+64 + 1+1+64);
 
601
  *tp++ = 0xC0;
 
602
  *tp++ = 4;
 
603
  rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 4, &n, rsa_e);
 
604
  if (rc)
 
605
    {
 
606
      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
 
607
      goto failure;
 
608
    }
 
609
  assert (n <= 4);
 
610
  memcpy (e, tp, n);
 
611
  elen = n;
 
612
  if (n != 4)
 
613
    {
 
614
      memmove (tp+4-n, tp, 4-n);
 
615
      memset (tp, 0, 4-n);
 
616
    }                 
 
617
  tp += 4;
 
618
 
 
619
  *tp++ = 0xC1;
 
620
  *tp++ = 64;
 
621
  rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_p);
 
622
  if (rc)
 
623
    {
 
624
      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
 
625
      goto failure;
 
626
    }
 
627
  assert (n == 64);
 
628
  tp += 64;
 
629
 
 
630
  *tp++ = 0xC2;
 
631
  *tp++ = 64;
 
632
  rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_q);
 
633
  if (rc)
 
634
    {
 
635
      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
 
636
      goto failure;
 
637
    }
 
638
  assert (n == 64);
 
639
  tp += 64;
 
640
  assert (tp - template == 138);
 
641
 
 
642
  /* (we need the modulus to calculate the fingerprint) */
 
643
  rc = gcry_mpi_print (GCRYMPI_FMT_USG, m, 128, &n, rsa_n);
 
644
  if (rc)
 
645
    {
 
646
      log_error ("mpi_print failed: %s\n", gpg_strerror (rc));
 
647
      goto failure;
 
648
    }
 
649
  assert (n == 128);
 
650
  mlen = 128;
 
651
 
 
652
 
 
653
  rc = app_openpgp_storekey (app, keyno,
 
654
                             template, tp - template,
 
655
                             created_at,
 
656
                             m, mlen,
 
657
                             e, elen,
 
658
                             pincb, NULL);
 
659
 
 
660
  if (rc)
 
661
    {
 
662
      log_error ("error storing key: %s\n", gpg_strerror (rc));
 
663
      goto failure;
 
664
    }
 
665
  log_info ("key successfully stored\n");
 
666
  {
 
667
    unsigned char *mm, *ee;
 
668
    size_t mmlen, eelen;
 
669
    int i;
 
670
 
 
671
    rc = app_openpgp_readkey (app, keyno, &mm, &mmlen, &ee, &eelen);
 
672
    if (rc)
 
673
      {
 
674
        log_error ("error reading key back: %s\n", gpg_strerror (rc));
 
675
        goto failure;
 
676
      }
 
677
 
 
678
    /* Strip leading zeroes. */
 
679
    for (i=0; i < mmlen && !mm[i]; i++)
 
680
      ;
 
681
    mmlen -= i;
 
682
    memmove (mm, mm+i, mmlen);
 
683
    for (i=0; i < eelen && !ee[i]; i++)
 
684
      ;
 
685
    eelen -= i;
 
686
    memmove (ee, ee+i, eelen);
 
687
 
 
688
    if (eelen != elen || mmlen != mlen)
 
689
      {
 
690
        log_error ("key parameter length mismatch (n=%u/%u, e=%u/%u)\n",
 
691
                   (unsigned int)mlen, (unsigned int)mmlen,
 
692
                   (unsigned int)elen, (unsigned int)eelen);
 
693
        xfree (mm);
 
694
        xfree (ee);
 
695
        goto failure;
 
696
      }
 
697
 
 
698
    if (memcmp (m, mm, mlen))
 
699
      {
 
700
        log_error ("key parameter n mismatch\n");
 
701
        log_printhex ("original n: ", m, mlen);
 
702
        log_printhex ("  copied n: ", mm, mlen);
 
703
        xfree (mm);
 
704
        xfree (ee);
 
705
        goto failure;
 
706
      }
 
707
    if (memcmp (e, ee, elen))
 
708
      {
 
709
        log_error ("key parameter e mismatch\n");
 
710
        log_printhex ("original e: ", e, elen);
 
711
        log_printhex ("  copied e: ", ee, elen);
 
712
        xfree (mm);
 
713
        xfree (ee);
 
714
        goto failure;
 
715
      }
 
716
    xfree (mm);
 
717
    xfree (ee);
 
718
  }
 
719
 
 
720
 
 
721
  gcry_mpi_release (rsa_e);
 
722
  gcry_mpi_release (rsa_p);
 
723
  gcry_mpi_release (rsa_q);
 
724
  gcry_mpi_release (rsa_n);
 
725
  return;
 
726
 
 
727
 failure:
 
728
  gcry_mpi_release (rsa_e);
 
729
  gcry_mpi_release (rsa_p);
 
730
  gcry_mpi_release (rsa_q);
 
731
  gcry_mpi_release (rsa_n);
 
732
  exit (1);
 
733
}
 
734
 
 
735