1 /* sc-copykeys.c - A tool to store keys on a smartcard.
2 * Copyright (C) 2003 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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 3 of the License, or
9 * (at your option) any later version.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
30 #define JNLIB_NEED_LOG_LOGV
34 #include "../common/ttyio.h"
35 #include "../common/simple-pwquery.h"
36 #include "apdu.h" /* for open_reader */
38 #include "app-common.h"
43 enum cmd_and_opt_values
53 static ARGPARSE_OPTS opts
[] = {
55 { 301, NULL
, 0, "@Options:\n " },
57 { oVerbose
, "verbose", 0, "verbose" },
58 { oReaderPort
, "reader-port", 2, "|N|connect to reader at port N"},
59 { octapiDriver
, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"},
60 { oDebug
, "debug" ,4|16, "set debugging flags"},
61 { oDebugAll
, "debug-all" ,0, "enable full debugging"},
66 static void copykeys (APP app
, const char *fname
);
70 my_strusage (int level
)
75 case 11: p
= "sc-copykeys (GnuPG)";
77 case 13: p
= VERSION
; break;
78 case 17: p
= PRINTABLE_OS_NAME
; break;
79 case 19: p
= _("Please report bugs to <" PACKAGE_BUGREPORT
">.\n");
82 case 40: p
= _("Usage: sc-copykeys [options] (-h for help)\n");
84 case 41: p
= _("Syntax: sc-copykeys [options] "
86 "Copy keys to a smartcards\n");
96 main (int argc
, char **argv
)
100 const char *reader_port
= NULL
;
101 struct app_ctx_s appbuf
;
103 memset (&appbuf
, 0, sizeof appbuf
);
105 set_strusage (my_strusage
);
106 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN
);
107 log_set_prefix ("sc-copykeys", 1);
109 /* check that the libraries are suitable. Do it here because
110 the option parsing may need services of the library */
111 if (!gcry_check_version (NEED_LIBGCRYPT_VERSION
) )
113 log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
114 NEED_LIBGCRYPT_VERSION
, gcry_check_version (NULL
) );
117 setup_libgcrypt_logging ();
118 gcry_control (GCRYCTL_DISABLE_SECMEM
, 0); /* FIXME - we want to use it */
119 /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/
123 pargs
.flags
= 1; /* do not remove the args */
124 while (arg_parse (&pargs
, opts
) )
128 case oVerbose
: opt
.verbose
++; break;
129 case oDebug
: opt
.debug
|= pargs
.r
.ret_ulong
; break;
130 case oDebugAll
: opt
.debug
= ~0; break;
131 case oReaderPort
: reader_port
= pargs
.r
.ret_str
; break;
132 case octapiDriver
: opt
.ctapi_driver
= pargs
.r
.ret_str
; break;
133 default : pargs
.err
= 2; break;
136 if (log_get_errorcount(0))
142 slot
= apdu_open_reader (reader_port
);
145 if (apdu_connect (slot
))
148 /* FIXME: Use select_application. */
150 rc
= app_select_openpgp (&appbuf
);
153 log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc
));
156 appbuf
.initialized
= 1;
157 log_info ("openpgp application selected\n");
159 copykeys (&appbuf
, *argv
);
168 send_status_info (CTRL ctrl
, const char *keyword
, ...)
176 read_file (const char *fname
, size_t *r_length
)
183 fp
= fname
? fopen (fname
, "rb") : stdin
;
186 log_error ("can't open `%s': %s\n",
187 fname
? fname
: "[stdin]", strerror (errno
));
191 if (fstat (fileno(fp
), &st
))
193 log_error ("can't stat `%s': %s\n",
194 fname
? fname
: "[stdin]", strerror (errno
));
201 buf
= xmalloc (buflen
+1);
202 if (fread (buf
, buflen
, 1, fp
) != 1)
204 log_error ("error reading `%s': %s\n",
205 fname
? fname
: "[stdin]", strerror (errno
));
220 read_key (const char *fname
)
227 buf
= read_file (fname
, &buflen
);
231 rc
= gcry_sexp_new (&private, buf
, buflen
, 1);
234 log_error ("gcry_sexp_new failed: %s\n", gpg_strerror (rc
));
245 sexp_to_kparms (gcry_sexp_t sexp
, unsigned long *created
)
247 gcry_sexp_t list
, l2
;
256 list
= gcry_sexp_find_token (sexp
, "private-key", 0 );
260 /* quick hack to get the creation time. */
261 l2
= gcry_sexp_find_token (list
, "created", 0);
262 if (l2
&& (name
= gcry_sexp_nth_data (l2
, 1, &n
)))
264 char *tmp
= xmalloc (n
+1);
265 memcpy (tmp
, name
, n
);
267 *created
= strtoul (tmp
, NULL
, 10);
270 gcry_sexp_release (l2
);
271 l2
= gcry_sexp_cadr (list
);
272 gcry_sexp_release (list
);
274 name
= gcry_sexp_nth_data (list
, 0, &n
);
275 if(!name
|| n
!= 3 || memcmp (name
, "rsa", 3))
277 gcry_sexp_release (list
);
281 /* Parameter names used with RSA. */
283 array
= xcalloc (strlen(elems
) + 1, sizeof *array
);
284 for (idx
=0, s
=elems
; *s
; s
++, idx
++ )
286 l2
= gcry_sexp_find_token (list
, s
, 1);
289 for (i
=0; i
<idx
; i
++)
290 gcry_mpi_release (array
[i
]);
292 gcry_sexp_release (list
);
293 return NULL
; /* required parameter not found */
295 array
[idx
] = gcry_sexp_nth_mpi (l2
, 1, GCRYMPI_FMT_USG
);
296 gcry_sexp_release (l2
);
299 for (i
=0; i
<idx
; i
++)
300 gcry_mpi_release (array
[i
]);
302 gcry_sexp_release (list
);
303 return NULL
; /* required parameter is invalid */
307 gcry_sexp_release (list
);
312 /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
314 fpr_is_zero (const char *fpr
)
318 for (i
=0; i
< 20 && !fpr
[i
]; i
++)
325 show_sha1_fpr (const unsigned char *fpr
)
331 for (i
=0; i
< 20 ; i
+=2, fpr
+= 2 )
335 tty_printf (" %02X%02X", *fpr
, fpr
[1]);
339 tty_printf (" [none]");
343 /* Query the card, show a list of already stored keys and ask the user
344 where to store the key. Returns the key number or 0 for cancel
350 char *serialno
, *disp_name
, *pubkey_url
;
351 unsigned char *fpr1
, *fpr2
, *fpr3
;
354 if (app_openpgp_cardinfo (app
,
358 &fpr1
, &fpr2
, &fpr3
))
368 tty_printf ("Serial number ....: %s\n",
369 serialno
? serialno
: "[none]");
370 tty_printf ("Name of cardholder: %s\n",
371 disp_name
&& *disp_name
? disp_name
: "[not set]");
372 tty_printf ("URL of public key : %s\n",
373 pubkey_url
&& *pubkey_url
? pubkey_url
: "[not set]");
374 tty_printf ("Signature key ....:");
375 show_sha1_fpr (fpr1
);
376 tty_printf ("Encryption key....:");
377 show_sha1_fpr (fpr2
);
378 tty_printf ("Authentication key:");
379 show_sha1_fpr (fpr3
);
382 "1 - store as signature key and reset usage counter\n"
383 "2 - store as encryption key\n"
384 "3 - store as authentication key\n"
388 answer
= tty_get("Your selection? ");
390 if (strlen (answer
) != 1)
392 else if ( *answer
== '1' )
394 if ( (fpr1
&& !fpr_is_zero (fpr1
)) )
397 log_error ("WARNING: signature key does already exists!\n");
399 if ( tty_get_answer_is_yes ("Replace existing key? ") )
411 else if ( *answer
== '2' )
413 if ( (fpr2
&& !fpr_is_zero (fpr2
)) )
416 log_error ("WARNING: encryption key does already exists!\n");
418 if ( tty_get_answer_is_yes ("Replace existing key? ") )
430 else if ( *answer
== '3' )
432 if ( (fpr3
&& !fpr_is_zero (fpr3
)) )
435 log_error ("WARNING: authentication key does already exists!\n");
437 if ( tty_get_answer_is_yes ("Replace existing key? ") )
449 else if ( *answer
== 'q' || *answer
== 'Q')
467 /* Callback function to ask for a PIN. */
469 pincb (void *arg
, const char *prompt
, char **pinvalue
)
471 char *pin
= xstrdup ("12345678");
473 /* pin = simple_pwquery (NULL, NULL, prompt, */
474 /* "We need the admin's PIN to store the key on the card", */
477 /* return gpg_error (GPG_ERR_CANCELED); */
486 /* This function expects a file (or NULL for stdin) with the secret
487 and public key parameters. This file should consist of an
488 S-expression as used by gpg-agent. Only the unprotected format is
493 (n #00e0ce9..[some bytes not shown]..51#)
495 (d #046129F..[some bytes not shown]..81#)
496 (p #00e861b..[some bytes not shown]..f1#)
497 (q #00f7a7c..[some bytes not shown]..61#)
498 (u #304559a..[some bytes not shown]..9b#))
499 (uri http://foo.bar x-foo:whatever_you_want))
503 copykeys (APP app
, const char *fname
)
507 gcry_mpi_t
*mpis
, rsa_n
, rsa_e
, rsa_p
, rsa_q
;
510 unsigned char *template, *tp
;
511 unsigned char m
[128], e
[4];
513 unsigned long creation_date
;
517 if (!strcmp (fname
, "-"))
520 private = read_key (fname
);
524 mpis
= sexp_to_kparms (private, &creation_date
);
527 log_info ("no creation date found - assuming current date\n");
528 created_at
= time (NULL
);
531 created_at
= creation_date
;
532 gcry_sexp_release (private);
535 log_error ("invalid structure of key file or not RSA\n");
538 /* MPIS is now an array with the key parameters as defined by OpenPGP. */
541 gcry_mpi_release (mpis
[2]);
544 gcry_mpi_release (mpis
[5]);
547 nbits
= gcry_mpi_get_nbits (rsa_e
);
548 if (nbits
< 2 || nbits
> 32)
550 log_error ("public exponent too large (more than 32 bits)\n");
553 nbits
= gcry_mpi_get_nbits (rsa_p
);
556 log_error ("length of first RSA prime is not 512\n");
559 nbits
= gcry_mpi_get_nbits (rsa_q
);
562 log_error ("length of second RSA prime is not 512\n");
566 nbits
= gcry_mpi_get_nbits (rsa_n
);
569 log_error ("length of RSA modulus is not 1024\n");
573 keyno
= query_card (app
);
577 /* Build the private key template as described in section 4.3.3.6 of
579 0xC0 <length> public exponent
580 0xC1 <length> prime p
581 0xC2 <length> prime q */
582 template = tp
= xmalloc (1+2 + 1+1+4 + 1+1+64 + 1+1+64);
585 rc
= gcry_mpi_print (GCRYMPI_FMT_USG
, tp
, 4, &n
, rsa_e
);
588 log_error ("mpi_print failed: %s\n", gpg_strerror (rc
));
596 memmove (tp
+4-n
, tp
, 4-n
);
603 rc
= gcry_mpi_print (GCRYMPI_FMT_USG
, tp
, 64, &n
, rsa_p
);
606 log_error ("mpi_print failed: %s\n", gpg_strerror (rc
));
614 rc
= gcry_mpi_print (GCRYMPI_FMT_USG
, tp
, 64, &n
, rsa_q
);
617 log_error ("mpi_print failed: %s\n", gpg_strerror (rc
));
622 assert (tp
- template == 138);
624 /* (we need the modulus to calculate the fingerprint) */
625 rc
= gcry_mpi_print (GCRYMPI_FMT_USG
, m
, 128, &n
, rsa_n
);
628 log_error ("mpi_print failed: %s\n", gpg_strerror (rc
));
635 rc
= app_openpgp_storekey (app
, keyno
,
636 template, tp
- template,
644 log_error ("error storing key: %s\n", gpg_strerror (rc
));
647 log_info ("key successfully stored\n");
649 unsigned char *mm
, *ee
;
653 rc
= app_openpgp_readkey (app
, keyno
, &mm
, &mmlen
, &ee
, &eelen
);
656 log_error ("error reading key back: %s\n", gpg_strerror (rc
));
660 /* Strip leading zeroes. */
661 for (i
=0; i
< mmlen
&& !mm
[i
]; i
++)
664 memmove (mm
, mm
+i
, mmlen
);
665 for (i
=0; i
< eelen
&& !ee
[i
]; i
++)
668 memmove (ee
, ee
+i
, eelen
);
670 if (eelen
!= elen
|| mmlen
!= mlen
)
672 log_error ("key parameter length mismatch (n=%u/%u, e=%u/%u)\n",
673 (unsigned int)mlen
, (unsigned int)mmlen
,
674 (unsigned int)elen
, (unsigned int)eelen
);
680 if (memcmp (m
, mm
, mlen
))
682 log_error ("key parameter n mismatch\n");
683 log_printhex ("original n: ", m
, mlen
);
684 log_printhex (" copied n: ", mm
, mlen
);
689 if (memcmp (e
, ee
, elen
))
691 log_error ("key parameter e mismatch\n");
692 log_printhex ("original e: ", e
, elen
);
693 log_printhex (" copied e: ", ee
, elen
);
703 gcry_mpi_release (rsa_e
);
704 gcry_mpi_release (rsa_p
);
705 gcry_mpi_release (rsa_q
);
706 gcry_mpi_release (rsa_n
);
710 gcry_mpi_release (rsa_e
);
711 gcry_mpi_release (rsa_p
);
712 gcry_mpi_release (rsa_q
);
713 gcry_mpi_release (rsa_n
);