diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 972362cb2..5983abac5 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -182,8 +182,6 @@ struct app_local_s { unsigned int sm_aes128:1; /* Use AES-128 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. */ @@ -300,7 +298,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; @@ -430,10 +428,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) { @@ -865,6 +860,22 @@ send_key_attr (ctrl_t ctrl, app_t app, const char *keyword, int number) } +#define RSA_SMALL_SIZE_KEY 1952 +#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].n_bits/8 + + 2 /* tag+len */ + app->app_local->keyattr[keyno].e_bits/8; + + 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 @@ -1199,10 +1210,11 @@ 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].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 { @@ -3042,12 +3054,11 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags, if (err) goto leave; - /* 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) + /* Test whether we will need extended length mode. */ + if (app->app_local->cardcap.ext_lc_le && keybits > RSA_SMALL_SIZE_KEY) { 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. */ @@ -3406,10 +3417,11 @@ 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].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].n_bits / 8; } else { @@ -3491,10 +3503,11 @@ 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].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].n_bits / 8; } else { @@ -3607,10 +3620,12 @@ do_decipher (app_t app, const char *keyidstr, padind = -1; /* Already padded. */ } - 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].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].n_bits / 8; } else if (app->app_local->cardcap.cmd_chaining && indatalen > 254) { @@ -3742,8 +3757,6 @@ show_caps (struct app_local_s *s) if (s->extcap.sm_supported) log_printf (" (%s)", s->extcap.sm_aes128? "AES-128":"3DES"); 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); @@ -3971,8 +3984,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);