diff options
Diffstat (limited to '')
-rw-r--r-- | scd/sc-copykeys.c | 731 |
1 files changed, 0 insertions, 731 deletions
diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c deleted file mode 100644 index 9caf39a8a..000000000 --- a/scd/sc-copykeys.c +++ /dev/null @@ -1,731 +0,0 @@ -/* sc-copykeys.c - A tool to store keys on a smartcard. - * Copyright (C) 2003 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include <config.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#define JNLIB_NEED_LOG_LOGV -#include "scdaemon.h" -#include <gcrypt.h> - -#include "../common/ttyio.h" -#include "../common/simple-pwquery.h" -#include "apdu.h" /* for open_reader */ -#include "atr.h" -#include "app-common.h" - -#define _(a) (a) - - -enum cmd_and_opt_values -{ oVerbose = 'v', - oReaderPort = 500, - oDebug, - oDebugAll, - -aTest }; - - -static ARGPARSE_OPTS opts[] = { - - { 301, NULL, 0, "@Options:\n " }, - - { oVerbose, "verbose", 0, "verbose" }, - { oReaderPort, "reader-port", 1, "|N|connect to reader at port N"}, - { oDebug, "debug" ,4|16, "set debugging flags"}, - { oDebugAll, "debug-all" ,0, "enable full debugging"}, - {0} -}; - - -static void copykeys (APP app, const char *fname); - - -static const char * -my_strusage (int level) -{ - const char *p; - switch (level) - { - case 11: p = "sc-copykeys (GnuPG)"; - break; - case 13: p = VERSION; break; - case 17: p = PRINTABLE_OS_NAME; break; - case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n"); - break; - case 1: - case 40: p = _("Usage: sc-copykeys [options] (-h for help)\n"); - break; - case 41: p = _("Syntax: sc-copykeys [options] " - "file-with-key\n" - "Copy keys to a smartcards\n"); - break; - - default: p = NULL; - } - return p; -} - -/* Used by gcry for logging */ -static void -my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr) -{ - /* translate the log levels */ - switch (level) - { - case GCRY_LOG_CONT: level = JNLIB_LOG_CONT; break; - case GCRY_LOG_INFO: level = JNLIB_LOG_INFO; break; - case GCRY_LOG_WARN: level = JNLIB_LOG_WARN; break; - case GCRY_LOG_ERROR:level = JNLIB_LOG_ERROR; break; - case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break; - case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break; - case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break; - default: level = JNLIB_LOG_ERROR; break; - } - log_logv (level, fmt, arg_ptr); -} - - -int -main (int argc, char **argv ) -{ - ARGPARSE_ARGS pargs; - int slot, rc; - int reader_port = 32768; /* First USB reader. */ - struct app_ctx_s appbuf; - - memset (&appbuf, 0, sizeof appbuf); - - set_strusage (my_strusage); - gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN); - log_set_prefix ("sc-copykeys", 1); - - /* check that the libraries are suitable. Do it here because - the option parsing may need services of the library */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) ) - { - log_fatal( _("libgcrypt is too old (need %s, have %s)\n"), - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) ); - } - - gcry_set_log_handler (my_gcry_logger, NULL); - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); /* FIXME - we want to use it */ - /* FIXME? gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);*/ - - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags= 1; /* do not remove the args */ - while (arg_parse (&pargs, opts) ) - { - switch (pargs.r_opt) - { - case oVerbose: opt.verbose++; break; - case oDebug: opt.debug |= pargs.r.ret_ulong; break; - case oDebugAll: opt.debug = ~0; break; - default : pargs.err = 2; break; - } - } - if (log_get_errorcount(0)) - exit(2); - - if (argc != 1) - usage (1); - - slot = apdu_open_reader (reader_port); - if (slot == -1) - exit (1); - - /* FIXME: Use select_application. */ - appbuf.slot = slot; - rc = app_select_openpgp (&appbuf, &appbuf.serialno, &appbuf.serialnolen); - if (rc) - { - log_error ("selecting openpgp failed: %s\n", gpg_strerror (rc)); - exit (1); - } - appbuf.initialized = 1; - log_info ("openpgp application selected\n"); - - copykeys (&appbuf, *argv); - - - return 0; -} - - - -void -send_status_info (CTRL ctrl, const char *keyword, ...) -{ - /* DUMMY */ -} - - - -static char * -read_file (const char *fname, size_t *r_length) -{ - FILE *fp; - struct stat st; - char *buf; - size_t buflen; - - fp = fname? fopen (fname, "rb") : stdin; - if (!fp) - { - log_error ("can't open `%s': %s\n", - fname? fname: "[stdin]", strerror (errno)); - return NULL; - } - - if (fstat (fileno(fp), &st)) - { - log_error ("can't stat `%s': %s\n", - fname? fname: "[stdin]", strerror (errno)); - if (fname) - fclose (fp); - return NULL; - } - - buflen = st.st_size; - buf = xmalloc (buflen+1); - if (fread (buf, buflen, 1, fp) != 1) - { - log_error ("error reading `%s': %s\n", - fname? fname: "[stdin]", strerror (errno)); - if (fname) - fclose (fp); - xfree (buf); - return NULL; - } - if (fname) - fclose (fp); - - *r_length = buflen; - return buf; -} - - -static gcry_sexp_t -read_key (const char *fname) -{ - char *buf; - size_t buflen; - gcry_sexp_t private; - int rc; - - buf = read_file (fname, &buflen); - if (!buf) - return NULL; - - rc = gcry_sexp_new (&private, buf, buflen, 1); - if (rc) - { - log_error ("gcry_sexp_new failed: %s\n", gpg_strerror (rc)); - return NULL; - } - xfree (buf); - - return private; -} - - - -static gcry_mpi_t * -sexp_to_kparms (gcry_sexp_t sexp, unsigned long *created) -{ - gcry_sexp_t list, l2; - const char *name; - const char *s; - size_t n; - int i, idx; - const char *elems; - gcry_mpi_t *array; - - *created = 0; - list = gcry_sexp_find_token (sexp, "private-key", 0 ); - if(!list) - return NULL; - - /* quick hack to get the creation time. */ - l2 = gcry_sexp_find_token (list, "created", 0); - if (l2 && (name = gcry_sexp_nth_data (l2, 1, &n))) - { - char *tmp = xmalloc (n+1); - memcpy (tmp, name, n); - tmp[n] = 0; - *created = strtoul (tmp, NULL, 10); - xfree (tmp); - } - gcry_sexp_release (l2); - l2 = gcry_sexp_cadr (list); - gcry_sexp_release (list); - list = l2; - name = gcry_sexp_nth_data (list, 0, &n); - if(!name || n != 3 || memcmp (name, "rsa", 3)) - { - gcry_sexp_release (list); - return NULL; - } - - /* Parameter names used with RSA. */ - elems = "nedpqu"; - array = xcalloc (strlen(elems) + 1, sizeof *array); - for (idx=0, s=elems; *s; s++, idx++ ) - { - l2 = gcry_sexp_find_token (list, s, 1); - if (!l2) - { - for (i=0; i<idx; i++) - gcry_mpi_release (array[i]); - xfree (array); - gcry_sexp_release (list); - return NULL; /* required parameter not found */ - } - array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); - gcry_sexp_release (l2); - if (!array[idx]) - { - for (i=0; i<idx; i++) - gcry_mpi_release (array[i]); - xfree (array); - gcry_sexp_release (list); - return NULL; /* required parameter is invalid */ - } - } - - gcry_sexp_release (list); - return array; -} - - -/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */ -static int -fpr_is_zero (const char *fpr) -{ - int i; - - for (i=0; i < 20 && !fpr[i]; i++) - ; - return (i == 20); -} - - -static void -show_sha1_fpr (const unsigned char *fpr) -{ - int i; - - if (fpr) - { - for (i=0; i < 20 ; i+=2, fpr += 2 ) - { - if (i == 10 ) - tty_printf (" "); - tty_printf (" %02X%02X", *fpr, fpr[1]); - } - } - else - tty_printf (" [none]"); - tty_printf ("\n"); -} - -/* Query the card, show a list of already stored keys and ask the user - where to store the key. Returns the key number or 0 for cancel - operation. */ -static int -query_card (APP app) -{ - int keyno = 0; - char *serialno, *disp_name, *pubkey_url; - unsigned char *fpr1, *fpr2, *fpr3; - - - if (app_openpgp_cardinfo (app, - &serialno, - &disp_name, - &pubkey_url, - &fpr1, &fpr2, &fpr3)) - return 0; - - - for (;;) - { - char *answer; - - tty_printf ("\n"); - - tty_printf ("Serial number ....: %s\n", - serialno? serialno : "[none]"); - tty_printf ("Name of cardholder: %s\n", - disp_name && *disp_name? disp_name : "[not set]"); - tty_printf ("URL of public key : %s\n", - pubkey_url && *pubkey_url? pubkey_url : "[not set]"); - tty_printf ("Signature key ....:"); - show_sha1_fpr (fpr1); - tty_printf ("Encryption key....:"); - show_sha1_fpr (fpr2); - tty_printf ("Authentication key:"); - show_sha1_fpr (fpr3); - - tty_printf ("\n" - "1 - store as signature key and reset usage counter\n" - "2 - store as encryption key\n" - "3 - store as authentication key\n" - "Q - quit\n" - "\n"); - - answer = tty_get("Your selection? "); - tty_kill_prompt(); - if (strlen (answer) != 1) - ; - else if ( *answer == '1' ) - { - if ( (fpr1 && !fpr_is_zero (fpr1)) ) - { - tty_printf ("\n"); - log_error ("WARNING: signature key does already exists!\n"); - tty_printf ("\n"); - if ( tty_get_answer_is_yes ("Replace existing key? ") ) - { - keyno = 1; - break; - } - } - else - { - keyno = 1; - break; - } - } - else if ( *answer == '2' ) - { - if ( (fpr2 && !fpr_is_zero (fpr2)) ) - { - tty_printf ("\n"); - log_error ("WARNING: encryption key does already exists!\n"); - tty_printf ("\n"); - if ( tty_get_answer_is_yes ("Replace existing key? ") ) - { - keyno = 2; - break; - } - } - else - { - keyno = 2; - break; - } - } - else if ( *answer == '3' ) - { - if ( (fpr3 && !fpr_is_zero (fpr3)) ) - { - tty_printf ("\n"); - log_error ("WARNING: authentication key does already exists!\n"); - tty_printf ("\n"); - if ( tty_get_answer_is_yes ("Replace existing key? ") ) - { - keyno = 3; - break; - } - } - else - { - keyno = 3; - break; - } - } - else if ( *answer == 'q' || *answer == 'Q') - { - keyno = 0; - break; - } - } - - xfree (serialno); - xfree (disp_name); - xfree (pubkey_url); - xfree (fpr1); - xfree (fpr2); - xfree (fpr3); - - return keyno; -} - - -/* Callback function to ask for a PIN. */ -static int -pincb (void *arg, const char *prompt, char **pinvalue) -{ - char *pin = xstrdup ("12345678"); - -/* pin = simple_pwquery (NULL, NULL, prompt, */ -/* "We need the admin's PIN to store the key on the card", */ -/* NULL); */ -/* if (!pin) */ -/* return gpg_error (GPG_ERR_CANCELED); */ - - - - *pinvalue = pin; - return 0; -} - - -/* This function expects a file (or NULL for stdin) with the secret - and public key parameters. This file should consist of an - S-expression as used by gpg-agent. Only the unprotected format is - supported. Example: - - (private-key - (rsa - (n #00e0ce9..[some bytes not shown]..51#) - (e #010001#) - (d #046129F..[some bytes not shown]..81#) - (p #00e861b..[some bytes not shown]..f1#) - (q #00f7a7c..[some bytes not shown]..61#) - (u #304559a..[some bytes not shown]..9b#)) - (uri http://foo.bar x-foo:whatever_you_want)) - -*/ -static void -copykeys (APP app, const char *fname) -{ - int rc; - gcry_sexp_t private; - gcry_mpi_t *mpis, rsa_n, rsa_e, rsa_p, rsa_q; - unsigned int nbits; - size_t n; - unsigned char *template, *tp; - unsigned char m[128], e[4]; - size_t mlen, elen; - unsigned long creation_date; - time_t created_at; - int keyno; - - if (!strcmp (fname, "-")) - fname = NULL; - - private = read_key (fname); - if (!private) - exit (1); - - mpis = sexp_to_kparms (private, &creation_date); - if (!creation_date) - { - log_info ("no creation date found - assuming current date\n"); - created_at = time (NULL); - } - else - created_at = creation_date; - gcry_sexp_release (private); - if (!mpis) - { - log_error ("invalid structure of key file or not RSA\n"); - exit (1); - } - /* MPIS is now an array with the key parameters as defined by OpenPGP. */ - rsa_n = mpis[0]; - rsa_e = mpis[1]; - gcry_mpi_release (mpis[2]); - rsa_p = mpis[3]; - rsa_q = mpis[4]; - gcry_mpi_release (mpis[5]); - xfree (mpis); - - nbits = gcry_mpi_get_nbits (rsa_e); - if (nbits < 2 || nbits > 32) - { - log_error ("public exponent too large (more than 32 bits)\n"); - goto failure; - } - nbits = gcry_mpi_get_nbits (rsa_p); - if (nbits != 512) - { - log_error ("length of first RSA prime is not 512\n"); - goto failure; - } - nbits = gcry_mpi_get_nbits (rsa_q); - if (nbits != 512) - { - log_error ("length of second RSA prime is not 512\n"); - goto failure; - } - - nbits = gcry_mpi_get_nbits (rsa_n); - if (nbits != 1024) - { - log_error ("length of RSA modulus is not 1024\n"); - goto failure; - } - - keyno = query_card (app); - if (!keyno) - goto failure; - - /* Build the private key template as described in section 4.3.3.6 of - the specs. - 0xC0 <length> public exponent - 0xC1 <length> prime p - 0xC2 <length> prime q */ - template = tp = xmalloc (1+2 + 1+1+4 + 1+1+64 + 1+1+64); - *tp++ = 0xC0; - *tp++ = 4; - rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 4, &n, rsa_e); - if (rc) - { - log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); - goto failure; - } - assert (n <= 4); - memcpy (e, tp, n); - elen = n; - if (n != 4) - { - memmove (tp+4-n, tp, 4-n); - memset (tp, 0, 4-n); - } - tp += 4; - - *tp++ = 0xC1; - *tp++ = 64; - rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_p); - if (rc) - { - log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); - goto failure; - } - assert (n == 64); - tp += 64; - - *tp++ = 0xC2; - *tp++ = 64; - rc = gcry_mpi_print (GCRYMPI_FMT_USG, tp, 64, &n, rsa_q); - if (rc) - { - log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); - goto failure; - } - assert (n == 64); - tp += 64; - assert (tp - template == 138); - - /* (we need the modulus to calculate the fingerprint) */ - rc = gcry_mpi_print (GCRYMPI_FMT_USG, m, 128, &n, rsa_n); - if (rc) - { - log_error ("mpi_print failed: %s\n", gpg_strerror (rc)); - goto failure; - } - assert (n == 128); - mlen = 128; - - - rc = app_openpgp_storekey (app, keyno, - template, tp - template, - created_at, - m, mlen, - e, elen, - pincb, NULL); - - if (rc) - { - log_error ("error storing key: %s\n", gpg_strerror (rc)); - goto failure; - } - log_info ("key successfully stored\n"); - { - unsigned char *mm, *ee; - size_t mmlen, eelen; - int i; - - rc = app_openpgp_readkey (app, keyno, &mm, &mmlen, &ee, &eelen); - if (rc) - { - log_error ("error reading key back: %s\n", gpg_strerror (rc)); - goto failure; - } - - /* Strip leading zeroes. */ - for (i=0; i < mmlen && !mm[i]; i++) - ; - mmlen -= i; - memmove (mm, mm+i, mmlen); - for (i=0; i < eelen && !ee[i]; i++) - ; - eelen -= i; - memmove (ee, ee+i, eelen); - - if (eelen != elen || mmlen != mlen) - { - log_error ("key parameter length mismatch (n=%u/%u, e=%u/%u)\n", - (unsigned int)mlen, (unsigned int)mmlen, - (unsigned int)elen, (unsigned int)eelen); - xfree (mm); - xfree (ee); - goto failure; - } - - if (memcmp (m, mm, mlen)) - { - log_error ("key parameter n mismatch\n"); - log_printhex ("original n: ", m, mlen); - log_printhex (" copied n: ", mm, mlen); - xfree (mm); - xfree (ee); - goto failure; - } - if (memcmp (e, ee, elen)) - { - log_error ("key parameter e mismatch\n"); - log_printhex ("original e: ", e, elen); - log_printhex (" copied e: ", ee, elen); - xfree (mm); - xfree (ee); - goto failure; - } - xfree (mm); - xfree (ee); - } - - - gcry_mpi_release (rsa_e); - gcry_mpi_release (rsa_p); - gcry_mpi_release (rsa_q); - gcry_mpi_release (rsa_n); - return; - - failure: - gcry_mpi_release (rsa_e); - gcry_mpi_release (rsa_p); - gcry_mpi_release (rsa_q); - gcry_mpi_release (rsa_n); - exit (1); -} - - |