1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-01-10 13:04:23 +01:00

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.
This commit is contained in:
Werner Koch 2012-11-06 14:39:22 +01:00
parent c0a20d6124
commit ab4ea45f54
3 changed files with 56 additions and 14 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}