|
|
From ab4ea45f54006eba55db11263431c4c0c4f557dc Mon Sep 17 00:00:00 2001
|
|
|
From: Werner Koch <wk@gnupg.org>
|
|
|
Date: Tue, 6 Nov 2012 14:39:22 +0100
|
|
|
Subject: [PATCH 1/1] Allow decryption with card keys > 3072 bit
|
|
|
|
|
|
* scd/command.c (MAXLEN_SETDATA): New.
|
|
|
(cmd_setdata): Add option --append.
|
|
|
* g10/call-agent.c (agent_scd_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.
|
|
|
---
|
|
|
g10/call-agent.c | 22 ++++++++++++++--------
|
|
|
scd/app-openpgp.c | 10 ++++++++++
|
|
|
scd/command.c | 38 ++++++++++++++++++++++++++++++++------
|
|
|
3 files changed, 56 insertions(+), 14 deletions(-)
|
|
|
|
|
|
diff --git a/g10/call-agent.c b/g10/call-agent.c
|
|
|
index cded773..373d8c9 100644
|
|
|
--- a/g10/call-agent.c
|
|
|
+++ b/g10/call-agent.c
|
|
|
@@ -1034,7 +1034,7 @@ agent_scd_pksign (const char *serialno, int hashalgo,
|
|
|
|
|
|
|
|
|
/* Decrypt INDATA of length INDATALEN using the card identified by
|
|
|
- SERIALNO. Return the plaintext in a nwly allocated buffer stored
|
|
|
+ SERIALNO. Return the plaintext in a newly allocated buffer stored
|
|
|
at the address of R_BUF.
|
|
|
|
|
|
Note, we currently support only RSA or more exactly algorithms
|
|
|
@@ -1058,20 +1058,26 @@ agent_scd_pkdecrypt (const char *serialno,
|
|
|
return rc;
|
|
|
|
|
|
/* FIXME: use secure memory where appropriate */
|
|
|
- if (indatalen*2 + 50 > DIM(line))
|
|
|
- return gpg_error (GPG_ERR_GENERAL);
|
|
|
|
|
|
rc = select_openpgp (serialno);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- sprintf (line, "SCD SETDATA ");
|
|
|
- p = line + strlen (line);
|
|
|
- for (i=0; i < indatalen ; i++, p += 2 )
|
|
|
- sprintf (p, "%02X", indata[i]);
|
|
|
- rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
+ for (len = 0; len < indatalen;)
|
|
|
+ {
|
|
|
+ p = stpcpy (line, "SCD 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 (agent_ctx, line,
|
|
|
+ NULL, NULL, NULL, NULL, NULL, NULL);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
+ }
|
|
|
|
|
|
init_membuf (&data, 1024);
|
|
|
snprintf (line, DIM(line)-1, "SCD PKDECRYPT %s", serialno);
|
|
|
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
|
|
|
index ff26b36..141b2b7 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
|
|
|
{
|
|
|
@@ -3462,6 +3464,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;
|
|
|
@@ -3749,6 +3757,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 6053fc6..3ce4a57 100644
|
|
|
--- a/scd/command.c
|
|
|
+++ b/scd/command.c
|
|
|
@@ -46,6 +46,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
|
|
|
|
|
|
@@ -820,17 +823,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);
|
|
|
|
|
|
@@ -844,14 +854,30 @@ cmd_setdata (assuan_context_t ctx, char *line)
|
|
|
if ((n&1))
|
|
|
return set_error (GPG_ERR_ASS_PARAMETER, "odd number of digits");
|
|
|
n /= 2;
|
|
|
+ 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);
|
|
|
+
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
--
|
|
|
1.7.2.5
|
|
|
|