[PATCH] scdaemon change for OpenPGPcard V3: Please test
NIIBE Yutaka
gniibe at fsij.org
Fri Nov 25 08:12:02 CET 2016
On 11/22/2016 05:40 PM, NIIBE Yutaka wrote:
> I found that OpenPGPcard V3 specification changed the semantics
> of some data in Extended Capabilities. I think that it is good
> if scdaemon can support OpenPGPcard V2 and V3.
Here is an update. I'm going to apply this change to master (2.1
branch).
This change has a little risk breaking existing cards or tokens, while
supporting V3 card. I tested with OpenPGP card v2.0 and v2.2, it
works fine with limited tests. It should be OK for Gnuk as it doesn't
use extended Lc/Le at all.
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index d1c9efe..4af999f 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -197,8 +197,6 @@ struct app_local_s {
unsigned int sm_algo:2; /* Symmetric crypto algo for SM. */
unsigned int max_certlen_3:16;
unsigned int max_get_challenge:16; /* Maximum size for
get_challenge. */
- unsigned int max_cmd_data:16; /* Maximum data size for a
command. */
- unsigned int max_rsp_data:16; /* Maximum size of a response. */
} extcap;
/* Flags used to control the application. */
@@ -325,7 +323,7 @@ get_cached_data (app_t app, int tag,
}
if (try_extlen && app->app_local->cardcap.ext_lc_le)
- exmode = app->app_local->extcap.max_rsp_data;
+ exmode = app->app_local->extcap.max_certlen_3;
else
exmode = 0;
@@ -455,10 +453,7 @@ get_one_do (app_t app, int tag, unsigned char
**result, size_t *nbytes,
if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11)
{
- if (data_objects[i].try_extlen && app->app_local->cardcap.ext_lc_le)
- exmode = app->app_local->extcap.max_rsp_data;
- else
- exmode = 0;
+ exmode = 0;
rc = iso7816_get_data (app->slot, exmode, tag, &buffer, &buflen);
if (rc)
{
@@ -922,6 +917,25 @@ send_key_attr (ctrl_t ctrl, app_t app, const char
*keyword, int keyno)
}
+#define RSA_SMALL_SIZE_KEY 1960
+#define RSA_SMALL_SIZE_OP 2048
+
+static int
+determine_rsa_response (app_t app, int keyno)
+{
+ int size;
+
+ size = 2 + 3 /* header */
+ + 4 /* tag+len */ + app->app_local->keyattr[keyno].rsa.n_bits/8
+ + 2 /* tag+len */ + app->app_local->keyattr[keyno].rsa.e_bits/8;
+
+ if (app->app_local->keyattr[keyno].rsa.n_bits <= 1024)
+ size = size - 2;
+
+ return size;
+}
+
+
/* Implement the GETATTR command. This is similar to the LEARN
command but returns just one value via the status interface. */
static gpg_error_t
@@ -1531,10 +1545,12 @@ get_public_key (app_t app, int keyno)
int exmode, le_value;
/* We may simply read the public key out of these cards. */
- if (app->app_local->cardcap.ext_lc_le)
+ if (app->app_local->cardcap.ext_lc_le
+ && app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA
+ && app->app_local->keyattr[keyno].rsa.n_bits >
RSA_SMALL_SIZE_KEY)
{
exmode = 1; /* Use extended length. */
- le_value = app->app_local->extcap.max_rsp_data;
+ le_value = determine_rsa_response (app, keyno);
}
else
{
@@ -3769,12 +3785,11 @@ do_genkey (app_t app, ctrl_t ctrl, const char
*keynostr, unsigned int flags,
if (keybits > 4096)
return gpg_error (GPG_ERR_TOO_LARGE);
- /* Test whether we will need extended length mode. (1900 is an
- arbitrary length which for sure fits into a short apdu.) */
- if (app->app_local->cardcap.ext_lc_le && keybits > 1900)
+ if (app->app_local->cardcap.ext_lc_le && keybits > RSA_SMALL_SIZE_KEY
+ && app->app_local->keyattr[keyno].key_type == KEY_TYPE_RSA)
{
exmode = 1; /* Use extended length w/o a limit. */
- le_value = app->app_local->extcap.max_rsp_data;
+ le_value = determine_rsa_response (app, keyno);
/* No need to check le_value because it comes from a 16 bit
value and thus can't create an overflow on a 32 bit
system. */
@@ -4122,10 +4137,12 @@ do_sign (app_t app, const char *keyidstr, int
hashalgo,
}
- if (app->app_local->cardcap.ext_lc_le)
+ if (app->app_local->cardcap.ext_lc_le
+ && app->app_local->keyattr[0].key_type == KEY_TYPE_RSA
+ && app->app_local->keyattr[0].rsa.n_bits > RSA_SMALL_SIZE_OP)
{
exmode = 1; /* Use extended length. */
- le_value = app->app_local->extcap.max_rsp_data;
+ le_value = app->app_local->keyattr[0].rsa.n_bits / 8;
}
else
{
@@ -4225,10 +4242,12 @@ do_auth (app_t app, const char *keyidstr,
{
int exmode, le_value;
- if (app->app_local->cardcap.ext_lc_le)
+ if (app->app_local->cardcap.ext_lc_le
+ && app->app_local->keyattr[2].key_type == KEY_TYPE_RSA
+ && app->app_local->keyattr[2].rsa.n_bits > RSA_SMALL_SIZE_OP)
{
exmode = 1; /* Use extended length. */
- le_value = app->app_local->extcap.max_rsp_data;
+ le_value = app->app_local->keyattr[2].rsa.n_bits / 8;
}
else
{
@@ -4417,10 +4436,13 @@ do_decipher (app_t app, const char *keyidstr,
else
return gpg_error (GPG_ERR_INV_VALUE);
- if (app->app_local->cardcap.ext_lc_le && indatalen > 254 )
+ if (app->app_local->cardcap.ext_lc_le
+ && (indatalen > 254
+ || (app->app_local->keyattr[1].key_type == KEY_TYPE_RSA
+ && app->app_local->keyattr[1].rsa.n_bits >
RSA_SMALL_SIZE_OP)))
{
exmode = 1; /* Extended length w/o a limit. */
- le_value = app->app_local->extcap.max_rsp_data;
+ le_value = app->app_local->keyattr[1].rsa.n_bits / 8;
}
else if (app->app_local->cardcap.cmd_chaining && indatalen > 254)
{
@@ -4578,8 +4600,6 @@ show_caps (struct app_local_s *s)
log_printf (" (%s)", s->extcap.sm_algo==2? "3DES":
(s->extcap.sm_algo==2? "AES-128" : "AES-256"));
log_info ("Max-Cert3-Len ..: %u\n", s->extcap.max_certlen_3);
- log_info ("Max-Cmd-Data ...: %u\n", s->extcap.max_cmd_data);
- log_info ("Max-Rsp-Data ...: %u\n", s->extcap.max_rsp_data);
log_info ("Cmd-Chaining ...: %s\n", s->cardcap.cmd_chaining?"yes":"no");
log_info ("Ext-Lc-Le ......: %s\n", s->cardcap.ext_lc_le?"yes":"no");
log_info ("Status Indicator: %02X\n", s->status_indicator);
@@ -4883,8 +4903,6 @@ app_select_openpgp (app_t app)
app->app_local->extcap.max_get_challenge
= (buffer[2] << 8 |
buffer[3]);
app->app_local->extcap.max_certlen_3 = (buffer[4] << 8 |
buffer[5]);
- app->app_local->extcap.max_cmd_data = (buffer[6] << 8 |
buffer[7]);
- app->app_local->extcap.max_rsp_data = (buffer[8] << 8 |
buffer[9]);
}
xfree (relptr);
--
More information about the Gnupg-devel
mailing list