From fb44677c9f2cab6bac08d04d675554b38f64382a Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 7 Jul 2011 11:20:53 +0200 Subject: [PATCH] Allow generation of card keys up to 4096 bit. This patch implementes a chunk mode to pass the key parameters from scdaemon to gpg. This allows to pass arbitrary long key paremeters; it is used for keys larger than 3072 bit. --- NEWS | 4 ++ configure.ac | 44 ++++++------ g10/call-agent.c | 180 ++++++++++++++++++++++++++++++---------------- g10/card-util.c | 2 +- scd/app-openpgp.c | 29 +++++--- scd/command.c | 8 ++- 6 files changed, 173 insertions(+), 94 deletions(-) diff --git a/NEWS b/NEWS index 492fe410f..b3ce8e053 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,10 @@ Noteworthy changes in version 2.0.18 (unreleased) ------------------------------------------------- + * Allow generation of card keys up to 4096 bit. + + * Bug fix for newer versions of Libgcrypt. + Noteworthy changes in version 2.0.17 (2011-01-13) ------------------------------------------------- diff --git a/configure.ac b/configure.ac index 3527c438c..36c8901ff 100644 --- a/configure.ac +++ b/configure.ac @@ -1,19 +1,19 @@ # configure.ac - for GnuPG 2.0 # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, # 2006, 2007, 2008, 2010, 2011 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 3 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, see . @@ -31,7 +31,7 @@ m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) m4_define([git_revision], m4_esyscmd([git branch -v 2>/dev/null \ | awk '/^\* / {printf "%s",$3}'])) -AC_INIT([gnupg], +AC_INIT([gnupg], [my_version[]m4_if(my_issvn,[yes], [m4_if(git_revision,[],[-svn[]svn_revision],[-git[]git_revision])])], [http://bugs.gnupg.org]) @@ -67,7 +67,7 @@ AC_GNU_SOURCE # Some status variables. have_gpg_error=no -have_libgcrypt=no +have_libgcrypt=no have_libassuan=no have_ksba=no have_pth=no @@ -369,10 +369,10 @@ AH_BOTTOM([ #ifdef HAVE_DRIVE_LETTERS #define GNUPG_DEFAULT_HOMEDIR "c:/gnupg" #elif defined(__VMS) -#define GNUPG_DEFAULT_HOMEDIR "/SYS\$LOGIN/gnupg" +#define GNUPG_DEFAULT_HOMEDIR "/SYS\$LOGIN/gnupg" #else #define GNUPG_DEFAULT_HOMEDIR "~/.gnupg" -#endif +#endif #define GNUPG_PRIVATE_KEYS_DIR "private-keys-v1.d" /* For some systems (DOS currently), we hardcode the path here. For @@ -380,7 +380,7 @@ AH_BOTTOM([ the values may be overridden by the make invocations; this is to comply with the GNU coding standards. */ #ifdef HAVE_DRIVE_LETTERS - /* FIXME: We need to use a function to determine these values depending + /* FIXME: We need to use a function to determine these values depending on the actual installation directory. */ #define GNUPG_BINDIR "c:\\gnupg" #define GNUPG_LIBEXECDIR "c:\\gnupg" @@ -574,7 +574,7 @@ esac if test "$have_dosish_system" = yes; then AC_DEFINE(HAVE_DOSISH_SYSTEM,1, - [Defined if we run on some of the PCDOS like systems + [Defined if we run on some of the PCDOS like systems (DOS, Windoze. OS/2) with special properties like no file modes]) fi @@ -726,7 +726,7 @@ else *** To support concurrent access to the gpg-agent and the SCdaemon *** we need the support of the GNU Portable Threads Library. *** Download it from ftp://ftp.gnu.org/gnu/pth/ -*** On a Debian GNU/Linux system you might want to try +*** On a Debian GNU/Linux system you might want to try *** apt-get install libpth-dev ***]]) fi @@ -766,7 +766,7 @@ if test "$with_adns" != "no"; then [CPPFLAGS=${_cppflags} LDFLAGS=${_ldflags}]) fi if test "$have_adns" = "yes"; then - ADNSLIBS="-ladns" + ADNSLIBS="-ladns" fi AC_SUBST(ADNSLIBS) # Newer adns versions feature a free function to be used under W32. @@ -820,7 +820,7 @@ if test x"$use_dns_pka" = xyes || test x"$use_dns_srv" = xyes \ #include ], [[unsigned char answer[PACKETSZ]; res_query("foo.bar",C_IN,T_A,answer,PACKETSZ); - dn_skipname(0,0); + dn_skipname(0,0); dn_expand(0,0,0,0,0); ]])],have_resolver=yes,have_resolver=no) AC_MSG_RESULT($have_resolver) @@ -1155,7 +1155,7 @@ if test "$use_regex" = yes ; then CPPFLAGS="${CPPFLAGS} -I$withval/include" LDFLAGS="${LDFLAGS} -L$withval/lib" fi - ],withval="") + ],withval="") # Does the system have regex functions at all? AC_SEARCH_LIBS([regcomp], [regex]) @@ -1215,7 +1215,7 @@ AC_CHECK_HEADER(zlib.h, # # Check whether we can support bzip2 -# +# if test "$use_bzip2" = yes ; then _cppflags="${CPPFLAGS}" _ldflags="${LDFLAGS}" @@ -1229,7 +1229,7 @@ if test "$use_bzip2" = yes ; then ],withval="") # Checking alongside stdio.h as an early version of bzip2 (1.0) - # required stdio.h to be included before bzlib.h, and Solaris 9 is + # required stdio.h to be included before bzlib.h, and Solaris 9 is # woefully out of date. if test "$withval" != no ; then AC_CHECK_HEADER(bzlib.h, @@ -1254,7 +1254,7 @@ GNUPG_CHECK_READLINE # # Allow users to append something to the version string without # flagging it as development version. The user version parts is -# considered everything after a dash. +# considered everything after a dash. # if test "$development_version" != yes; then changequote(,)dnl @@ -1428,7 +1428,7 @@ die=no if test "$have_gpg_error" = "no"; then die=yes AC_MSG_NOTICE([[ -*** +*** *** You need libgpg-error to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libgpg-error @@ -1438,7 +1438,7 @@ fi if test "$have_libgcrypt" = "no"; then die=yes AC_MSG_NOTICE([[ -*** +*** *** You need libgcrypt to build this program. ** This library is for example available at *** ftp://ftp.gnupg.org/gcrypt/libgcrypt/ @@ -1471,7 +1471,7 @@ if test "$missing_pth" = "yes"; then *** GNU Portable Threads Library (Pth). Please install this *** library first. The library is for example available at *** ftp://ftp.gnu.org/gnu/pth/ -*** On a Debian GNU/Linux system you can install it using +*** On a Debian GNU/Linux system you can install it using *** apt-get install libpth-dev *** To build GnuPG for Windows you need to use the W32PTH *** package; available at: @@ -1490,7 +1490,7 @@ fi -AC_CONFIG_FILES([ m4/Makefile +AC_CONFIG_FILES([ m4/Makefile Makefile po/Makefile.in gl/Makefile @@ -1517,7 +1517,7 @@ AC_OUTPUT echo " GnuPG v${VERSION} has been configured as follows: - + Platform: $PRINTABLE_OS_NAME ($host) OpenPGP: $build_gpg diff --git a/g10/call-agent.c b/g10/call-agent.c index 8906082b7..cded773c8 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -1,5 +1,5 @@ /* call-agent.c - Divert GPG operations to the agent. - * Copyright (C) 2001, 2002, 2003, 2006, 2007, + * Copyright (C) 2001, 2002, 2003, 2006, 2007, * 2008, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #ifdef HAVE_LOCALE_H @@ -48,7 +48,7 @@ static assuan_context_t agent_ctx = NULL; static int did_early_card_test; -struct cipher_parm_s +struct cipher_parm_s { assuan_context_t ctx; const char *ciphertext; @@ -69,13 +69,19 @@ struct writekey_parm_s size_t keydatalen; }; -struct genkey_parm_s +struct genkey_parm_s { assuan_context_t ctx; const char *sexp; size_t sexplen; }; +struct scd_genkey_parm_s +{ + struct agent_card_genkey_s *cgk; + char *savedbytes; /* Malloced space to save key parameter chunks. */ +}; + static gpg_error_t learn_status_cb (void *opaque, const char *line); @@ -99,7 +105,7 @@ status_sc_op_failure (int rc) write_status (STATUS_SC_OP_FAILURE); break; } -} +} @@ -162,7 +168,7 @@ start_agent (int for_card) if (!rc && is_status_enabled () && info.serialno) { char *buf; - + buf = xasprintf ("3 %s", info.serialno); write_status_text (STATUS_CARDCTRL, buf); xfree (buf); @@ -174,7 +180,7 @@ start_agent (int for_card) did_early_card_test = 1; } - + return rc; } @@ -267,7 +273,7 @@ get_serialno_cb (void *opaque, const char *line) memcpy (*serialno, line, n); (*serialno)[n] = 0; } - + return 0; } @@ -329,7 +335,7 @@ learn_status_cb (void *opaque, const char *line) { xfree (parm->serialno); parm->serialno = store_serialno (line); - parm->is_v2 = (strlen (parm->serialno) >= 16 + parm->is_v2 = (strlen (parm->serialno) >= 16 && xtoi_2 (parm->serialno+12) >= 2 ); } else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen)) @@ -510,7 +516,7 @@ agent_learn (struct agent_card_info_s *info) /* Also try to get the key attributes. */ if (!rc) agent_scd_getattr ("KEY-ATTR", info); - + return rc; } @@ -529,7 +535,7 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info) /* We assume that NAME does not need escaping. */ if (12 + strlen (name) > DIM(line)-1) return gpg_error (GPG_ERR_TOO_LARGE); - stpcpy (stpcpy (line, "SCD GETATTR "), name); + stpcpy (stpcpy (line, "SCD GETATTR "), name); rc = start_agent (1); if (rc) @@ -537,7 +543,7 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info) rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, learn_status_cb, info); - + return rc; } @@ -562,8 +568,8 @@ agent_scd_setattr (const char *name, /* We assume that NAME does not need escaping. */ if (12 + strlen (name) > DIM(line)-1) return gpg_error (GPG_ERR_TOO_LARGE); - - p = stpcpy (stpcpy (line, "SCD SETATTR "), name); + + p = stpcpy (stpcpy (line, "SCD SETATTR "), name); *p++ = ' '; for (; valuelen; value++, valuelen--) { @@ -584,7 +590,7 @@ agent_scd_setattr (const char *name, rc = start_agent (1); if (!rc) { - rc = assuan_transact (agent_ctx, line, NULL, NULL, + rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, NULL, NULL); } @@ -601,7 +607,7 @@ static gpg_error_t inq_writecert_parms (void *opaque, const char *line) { int rc; - struct writecert_parm_s *parm = opaque; + struct writecert_parm_s *parm = opaque; if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8])) { @@ -615,7 +621,7 @@ inq_writecert_parms (void *opaque, const char *line) /* Send a WRITECERT command to the SCdaemon. */ -int +int agent_scd_writecert (const char *certidstr, const unsigned char *certdata, size_t certdatalen) { @@ -634,7 +640,7 @@ agent_scd_writecert (const char *certidstr, parms.ctx = agent_ctx; parms.certdata = certdata; parms.certdatalen = certdatalen; - + rc = assuan_transact (agent_ctx, line, NULL, NULL, inq_writecert_parms, &parms, NULL, NULL); @@ -649,7 +655,7 @@ static gpg_error_t inq_writekey_parms (void *opaque, const char *line) { int rc; - struct writekey_parm_s *parm = opaque; + struct writekey_parm_s *parm = opaque; if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) { @@ -663,7 +669,7 @@ inq_writekey_parms (void *opaque, const char *line) /* Send a WRITEKEY command to the SCdaemon. */ -int +int agent_scd_writekey (int keyno, const char *serialno, const unsigned char *keydata, size_t keydatalen) { @@ -684,7 +690,7 @@ agent_scd_writekey (int keyno, const char *serialno, parms.ctx = agent_ctx; parms.keydata = keydata; parms.keydatalen = keydatalen; - + rc = assuan_transact (agent_ctx, line, NULL, NULL, inq_writekey_parms, &parms, NULL, NULL); @@ -694,14 +700,44 @@ agent_scd_writekey (int keyno, const char *serialno, +static gpg_error_t +scd_genkey_cb_append_savedbytes (struct scd_genkey_parm_s *parm, + const char *line) +{ + gpg_error_t err = 0; + char *p; + + if (!parm->savedbytes) + { + parm->savedbytes = xtrystrdup (line); + if (!parm->savedbytes) + err = gpg_error_from_syserror (); + } + else + { + p = xtrymalloc (strlen (parm->savedbytes) + strlen (line) + 1); + if (!p) + err = gpg_error_from_syserror (); + else + { + strcpy (stpcpy (p, parm->savedbytes), line); + xfree (parm->savedbytes); + parm->savedbytes = p; + } + } + + return err; +} + + /* Status callback for the SCD GENKEY command. */ static gpg_error_t scd_genkey_cb (void *opaque, const char *line) { - struct agent_card_genkey_s *parm = opaque; + struct scd_genkey_parm_s *parm = opaque; const char *keyword = line; int keywordlen; - gpg_error_t rc; + gpg_error_t rc = 0; for (keywordlen=0; *line && !spacep (line); line++, keywordlen++) ; @@ -710,7 +746,7 @@ scd_genkey_cb (void *opaque, const char *line) if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen)) { - parm->fprvalid = unhexify_fpr (line, parm->fpr); + parm->cgk->fprvalid = unhexify_fpr (line, parm->cgk->fpr); } else if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen)) { @@ -722,29 +758,47 @@ scd_genkey_cb (void *opaque, const char *line) while (spacep (line)) line++; - rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL); - if (rc) - log_error ("error parsing received key data: %s\n", gpg_strerror (rc)); - else if (*name == 'n' && spacep (name+1)) - parm->n = a; - else if (*name == 'e' && spacep (name+1)) - parm->e = a; + if (*name == '-' && spacep (name+1)) + rc = scd_genkey_cb_append_savedbytes (parm, line); else { - log_info ("unknown parameter name in received key data\n"); - gcry_mpi_release (a); + if (parm->savedbytes) + { + rc = scd_genkey_cb_append_savedbytes (parm, line); + if (!rc) + rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, + parm->savedbytes, 0, NULL); + } + else + rc = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, line, 0, NULL); + if (rc) + log_error ("error parsing received key data: %s\n", + gpg_strerror (rc)); + else if (*name == 'n' && spacep (name+1)) + parm->cgk->n = a; + else if (*name == 'e' && spacep (name+1)) + parm->cgk->e = a; + else + { + log_info ("unknown parameter name in received key data\n"); + gcry_mpi_release (a); + rc = gpg_error (GPG_ERR_INV_PARAMETER); + } + + xfree (parm->savedbytes); + parm->savedbytes = NULL; } } else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen)) { - parm->created_at = (u32)strtoul (line, NULL, 10); + parm->cgk->created_at = (u32)strtoul (line, NULL, 10); } else if (keywordlen == 8 && !memcmp (keyword, "PROGRESS", keywordlen)) { write_status_text (STATUS_PROGRESS, line); } - return 0; + return rc; } /* Send a GENKEY command to the SCdaemon. SERIALNO is not used in @@ -759,9 +813,13 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, int rc; char line[ASSUAN_LINELENGTH]; gnupg_isotime_t tbuf; + struct scd_genkey_parm_s parms; (void)serialno; + memset (&parms, 0, sizeof parms); + parms.cgk = info; + rc = start_agent (1); if (rc) return rc; @@ -774,15 +832,17 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force, memset (info, 0, sizeof *info); snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d", *tbuf? "--timestamp=":"", tbuf, - force? "--force":"", + force? "--force":"", keyno); line[DIM(line)-1] = 0; memset (info, 0, sizeof *info); rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, - scd_genkey_cb, info); - + scd_genkey_cb, &parms); + + xfree (parms.savedbytes); + status_sc_op_failure (rc); return rc; } @@ -800,7 +860,7 @@ select_openpgp (const char *serialno) /* Send the serialno command to initialize the connection. Without a given S/N we don't care about the data returned. If the card has already been initialized, this is a very fast command. We - request the openpgp card because that is what we expect. + request the openpgp card because that is what we expect. Note that an opt.limit_card_insert_tries of 1 means: No tries at all whereas 0 means do not limit the number of tries. Due to the @@ -816,7 +876,7 @@ select_openpgp (const char *serialno) int ask; char *want_sn; char *p; - + want_sn = xtrystrdup (serialno); if (!want_sn) return gpg_error_from_syserror (); @@ -824,14 +884,14 @@ select_openpgp (const char *serialno) if (p) *p = 0; - do + do { ask = 0; err = assuan_transact (agent_ctx, "SCD SERIALNO openpgp", - NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, get_serialno_cb, &this_sn); if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT) - ask = 1; + ask = 1; else if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED) ask = 2; else if (err) @@ -844,19 +904,19 @@ select_openpgp (const char *serialno) xfree (this_sn); this_sn = NULL; - + if (ask) { char *formatted = NULL; char *ocodeset = i18n_switchto_utf8 (); - if (!strncmp (want_sn, "D27600012401", 12) + if (!strncmp (want_sn, "D27600012401", 12) && strlen (want_sn) == 32 ) formatted = xtryasprintf ("(%.4s) %.8s", want_sn + 16, want_sn + 20); - + err = 0; - desc = xtryasprintf + desc = xtryasprintf ("%s:\n\n" " \"%s\"", ask == 1 @@ -891,7 +951,7 @@ membuf_data_cb (void *opaque, const void *buffer, size_t length) put_membuf (data, buffer, length); return 0; } - + /* Helper returning a command option to describe the used hash algorithm. See scd/command.c:cmd_pksign. */ @@ -1004,7 +1064,7 @@ agent_scd_pkdecrypt (const char *serialno, rc = select_openpgp (serialno); if (rc) return rc; - + sprintf (line, "SCD SETDATA "); p = line + strlen (line); for (i=0; i < indatalen ; i++, p += 2 ) @@ -1037,7 +1097,7 @@ agent_scd_pkdecrypt (const char *serialno, /* Send a READCERT command to the SCdaemon. */ -int +int agent_scd_readcert (const char *certidstr, void **r_buf, size_t *r_buflen) { @@ -1157,8 +1217,8 @@ agent_get_passphrase (const char *cache_id, int rc; char line[ASSUAN_LINELENGTH]; char *arg1 = NULL; - char *arg2 = NULL; - char *arg3 = NULL; + char *arg2 = NULL; + char *arg3 = NULL; char *arg4 = NULL; membuf_t data; @@ -1169,7 +1229,7 @@ agent_get_passphrase (const char *cache_id, return rc; /* Check that the gpg-agent understands the repeat option. */ - if (assuan_transact (agent_ctx, + if (assuan_transact (agent_ctx, "GETINFO cmd_has_option GET_PASSPHRASE repeat", NULL, NULL, NULL, NULL, NULL, NULL)) return gpg_error (GPG_ERR_NOT_SUPPORTED); @@ -1187,9 +1247,9 @@ agent_get_passphrase (const char *cache_id, if (!(arg4 = percent_plus_escape (desc_msg))) goto no_mem; - snprintf (line, DIM(line)-1, - "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s", - repeat, + snprintf (line, DIM(line)-1, + "GET_PASSPHRASE --data --repeat=%d%s -- %s %s %s %s", + repeat, check? " --check --qualitybar":"", arg1? arg1:"X", arg2? arg2:"X", @@ -1202,13 +1262,13 @@ agent_get_passphrase (const char *cache_id, xfree (arg4); init_membuf_secure (&data, 64); - rc = assuan_transact (agent_ctx, line, + rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data, default_inq_cb, NULL, NULL, NULL); if (rc) xfree (get_membuf (&data, NULL)); - else + else { put_membuf (&data, "", 1); *r_passphrase = get_membuf (&data, NULL); @@ -1287,12 +1347,12 @@ agent_get_s2k_count (unsigned long *r_count) return err; init_membuf (&data, 32); - err = assuan_transact (agent_ctx, "GETINFO s2k_count", + err = assuan_transact (agent_ctx, "GETINFO s2k_count", membuf_data_cb, &data, NULL, NULL, NULL, NULL); if (err) xfree (get_membuf (&data, NULL)); - else + else { put_membuf (&data, "", 1); buf = get_membuf (&data, NULL); diff --git a/g10/card-util.c b/g10/card-util.c index caf934dd2..801de5799 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1284,7 +1284,7 @@ static unsigned int ask_card_keysize (int keyno, unsigned int nbits) { unsigned int min_nbits = 1024; - unsigned int max_nbits = 3072; /* GnuPG limit due to Assuan. */ + unsigned int max_nbits = 4096; char *prompt, *answer; unsigned int req_nbits; diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index d4685916e..8a71caf36 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -756,20 +756,29 @@ static void send_key_data (ctrl_t ctrl, const char *name, const unsigned char *a, size_t alen) { - char *buf; - - buf = bin2hex (a, alen, NULL); - if (!buf) + char *buffer, *buf; + size_t buflen; + + buffer = buf = bin2hex (a, alen, NULL); + if (!buffer) { log_error ("memory allocation error in send_key_data\n"); return; } + buflen = strlen (buffer); + /* 768 is the hexified size for the modulus of an 3072 bit key. We + use extra chunks to transmit larger data (i.e for 4096 bit). */ + for ( ;buflen > 768; buflen -= 768, buf += 768) + send_status_info (ctrl, "KEY-DATA", + "-", 1, + buf, 768, + NULL, 0); send_status_info (ctrl, "KEY-DATA", - name, (size_t)strlen(name), - buf, (size_t)strlen (buf), + name, (size_t)strlen(name), + buf, buflen, NULL, 0); - xfree (buf); + xfree (buffer); } @@ -2365,7 +2374,7 @@ change_keyattr (app_t app, int keyno, unsigned int nbits, assert (keyno >=0 && keyno <= 2); - if (nbits > 3072) + if (nbits > 4096) return gpg_error (GPG_ERR_TOO_LARGE); /* Read the current attributes into a buffer. */ @@ -2823,7 +2832,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, already lead to a 527 byte long status line and thus a 4096 bit key would exceed the Assuan line length limit. */ keybits = app->app_local->keyattr[keyno].n_bits; - if (keybits > 3072) + if (keybits > 4096) return gpg_error (GPG_ERR_TOO_LARGE); /* Prepare for key generation by verifying the Admin PIN. */ @@ -3377,6 +3386,8 @@ do_decipher (app_t app, const char *keyidstr, fixuplen = 256 - indatalen; else if (indatalen >= (384-16) && indatalen < 384) /* 3072 bit key. */ fixuplen = 384 - indatalen; + else if (indatalen >= (512-16) && indatalen < 512) /* 4096 bit key. */ + fixuplen = 512 - indatalen; else fixuplen = 0; diff --git a/scd/command.c b/scd/command.c index 28bc4df41..52b22c6a0 100644 --- a/scd/command.c +++ b/scd/command.c @@ -1287,11 +1287,15 @@ static const char hlp_genkey[] = "\n" "Generate a key on-card identified by NO, which is application\n" "specific. Return values are application specific. For OpenPGP\n" - "cards 2 status lines are returned:\n" + "cards 3 status lines are returned:\n" "\n" " S KEY-FPR \n" " S KEY-CREATED-AT \n" - " S KEY-DATA [p|n] \n" + " S KEY-DATA [-|p|n] \n" + "\n" + " 'p' and 'n' are the names of the RSA parameters; '-' is used to\n" + " indicate that HEXDATA is the first chunk of a parameter given\n" + " by the next KEY-DATA.\n" "\n" "--force is required to overwrite an already existing key. The\n" "KEY-CREATED-AT is required for further processing because it is\n"