aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2012-11-06 11:02:25 +0000
committerWerner Koch <[email protected]>2012-11-06 13:48:06 +0000
commit905b6a36d3ca21b2f619721e1de892398e5eb759 (patch)
tree7295b89fde6788a7a93b890b6c85fc063e278c44
parentagent: Fix wrong use of gcry_sexp_build_array (diff)
downloadgnupg-905b6a36d3ca21b2f619721e1de892398e5eb759.tar.gz
gnupg-905b6a36d3ca21b2f619721e1de892398e5eb759.zip
Allow decryption with card keys > 3072 bits
* scd/command.c (MAXLEN_SETDATA): New. (cmd_setdata): Add option --append. * agent/call-scd.c (agent_card_pkdecrypt): Use new option for long data. * scd/app-openpgp.c (struct app_local_s): Add field manufacturer. (app_select_openpgp): Store manufacturer. (do_decipher): Print a note for broken cards. -- Please note that I was not able to run a full test because I only have broken cards (S/N < 346) available.
Diffstat (limited to '')
-rw-r--r--agent/call-scd.c25
-rw-r--r--scd/app-openpgp.c10
-rw-r--r--scd/command.c40
3 files changed, 58 insertions, 17 deletions
diff --git a/agent/call-scd.c b/agent/call-scd.c
index 8fc00542e..2bda3779d 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -926,17 +926,22 @@ agent_card_pkdecrypt (ctrl_t ctrl,
return rc;
/* FIXME: use secure memory where appropriate */
- if (indatalen*2 + 50 > DIM(line))
- return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
- sprintf (line, "SETDATA ");
- p = line + strlen (line);
- for (i=0; i < indatalen ; i++, p += 2 )
- sprintf (p, "%02X", indata[i]);
- rc = assuan_transact (ctrl->scd_local->ctx, line,
- NULL, NULL, NULL, NULL, NULL, NULL);
- if (rc)
- return unlock_scd (ctrl, rc);
+ for (len = 0; len < indatalen;)
+ {
+ p = stpcpy (line, "SETDATA ");
+ if (len)
+ p = stpcpy (p, "--append ");
+ for (i=0; len < indatalen && (i*2 < DIM(line)-50); i++, len++)
+ {
+ sprintf (p, "%02X", indata[len]);
+ p += 2;
+ }
+ rc = assuan_transact (ctrl->scd_local->ctx, line,
+ NULL, NULL, NULL, NULL, NULL, NULL);
+ if (rc)
+ return unlock_scd (ctrl, rc);
+ }
init_membuf (&data, 1024);
inqparm.ctx = ctrl->scd_local->ctx;
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 9c8ef59cb..5a9214c1c 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -158,6 +158,8 @@ struct app_local_s {
unsigned char status_indicator; /* The card status indicator. */
+ unsigned int manufacturer:16; /* Manufacturer ID from the s/n. */
+
/* Keep track of the ISO card capabilities. */
struct
{
@@ -3474,6 +3476,12 @@ do_decipher (app_t app, const char *keyidstr,
indata, indatalen, le_value, padind,
outdata, outdatalen);
xfree (fixbuf);
+
+ if (gpg_err_code (rc) == GPG_ERR_CARD /* actual SW is 0x640a */
+ && app->app_local->manufacturer == 5
+ && app->card_version == 0x0200)
+ log_info ("NOTE: Cards with manufacturer id 5 and s/n <= 346 (0x15a)"
+ " do not work with encryption keys > 2048 bits\n");
}
return rc;
@@ -3761,6 +3769,8 @@ app_select_openpgp (app_t app)
goto leave;
}
+ app->app_local->manufacturer = manufacturer;
+
if (app->card_version >= 0x0200)
app->app_local->extcap.is_v2 = 1;
diff --git a/scd/command.c b/scd/command.c
index 102715804..17da5b7ae 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -48,6 +48,9 @@
/* Maximum allowed size of key data as used in inquiries. */
#define MAXLEN_KEYDATA 4096
+/* Maximum allowed total data size for SETDATA. */
+#define MAXLEN_SETDATA 4096
+
/* Maximum allowed size of certificate data as used in inquiries. */
#define MAXLEN_CERTDATA 16384
@@ -848,17 +851,24 @@ cmd_readkey (assuan_context_t ctx, char *line)
static const char hlp_setdata[] =
- "SETDATA <hexstring> \n"
+ "SETDATA [--append] <hexstring>\n"
"\n"
- "The client should use this command to tell us the data he want to sign.";
+ "The client should use this command to tell us the data he want to sign.\n"
+ "With the option --append, the data is appended to the data set by a\n"
+ "previous SETDATA command.";
static gpg_error_t
cmd_setdata (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
- int n;
+ int append;
+ int n, i, off;
char *p;
unsigned char *buf;
+ append = (ctrl->in_data.value && has_option (line, "--append"));
+
+ line = skip_options (line);
+
if (locked_session && locked_session != ctrl->server_local)
return gpg_error (GPG_ERR_LOCKED);
@@ -872,15 +882,31 @@ cmd_setdata (assuan_context_t ctx, char *line)
if ((n&1))
return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
n /= 2;
- buf = xtrymalloc (n);
+ if (append)
+ {
+ if (ctrl->in_data.valuelen + n > MAXLEN_SETDATA)
+ return set_error (GPG_ERR_TOO_LARGE,
+ "limit on total size of data reached");
+ buf = xtrymalloc (ctrl->in_data.valuelen + n);
+ }
+ else
+ buf = xtrymalloc (n);
if (!buf)
return out_of_core ();
+ if (append)
+ {
+ memcpy (buf, ctrl->in_data.value, ctrl->in_data.valuelen);
+ off = ctrl->in_data.valuelen;
+ }
+ else
+ off = 0;
+ for (p=line, i=0; i < n; p += 2, i++)
+ buf[off+i] = xtoi_2 (p);
+
xfree (ctrl->in_data.value);
ctrl->in_data.value = buf;
- ctrl->in_data.valuelen = n;
- for (p=line, n=0; n < ctrl->in_data.valuelen; p += 2, n++)
- buf[n] = xtoi_2 (p);
+ ctrl->in_data.valuelen = off+n;
return 0;
}