diff options
Diffstat (limited to 'scd/app-openpgp.c')
-rw-r--r-- | scd/app-openpgp.c | 119 |
1 files changed, 87 insertions, 32 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 05e1f39..8bb346a 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -280,7 +280,7 @@ static gpg_error_t do_auth (app_t app, ctrl_t ctrl, const char *keyidstr, unsigned char **outdata, size_t *outdatalen); static const char *get_algorithm_attribute_string (const unsigned char *buffer, size_t buflen); -static void parse_algorithm_attribute (app_t app, int keyno); +static gpg_error_t parse_algorithm_attribute (app_t app, int keyno); static gpg_error_t change_keyattr_from_string (app_t app, ctrl_t ctrl, gpg_error_t (*pincb)(void*, const char *, char **), @@ -321,6 +321,7 @@ get_manufacturer (unsigned int no) case 0x63AF: return "Trustica"; case 0xBA53: return "c-base e.V."; case 0xBD0E: return "Paranoidlabs"; + case 0xCA05: return "Atos CardOS"; case 0xF1D0: return "CanoKeys"; case 0xF517: return "FSIJ"; case 0xF5EC: return "F-Secure"; @@ -423,7 +424,7 @@ get_cached_data (app_t app, int tag, { p = xtrymalloc (c->length); if (!p) - return gpg_error (gpg_err_code_from_errno (errno)); + return gpg_error_from_syserror (); memcpy (p, c->data, c->length); *result = p; } @@ -2042,6 +2043,21 @@ get_public_key (app_t app, int keyno) } +static const char * +get_usage_string (int keyno) +{ + const char *usage; + switch (keyno) + { + case 0: usage = "sc"; break; + case 1: usage = "e"; break; + case 2: usage = "sa"; break; + default: usage = "-"; break; + } + return usage; +} + + /* Send the KEYPAIRINFO back. KEY needs to be in the range [1,3]. This is used by the LEARN command. */ static gpg_error_t @@ -2061,13 +2077,7 @@ send_keypair_info (app_t app, ctrl_t ctrl, int key) if (!app->app_local->pk[keyno].key) goto leave; /* No such key - ignore. */ - switch (keyno) - { - case 0: usage = "sc"; break; - case 1: usage = "e"; break; - case 2: usage = "sa"; break; - default: usage = "-"; break; - } + usage = get_usage_string (keyno); if (retrieve_fprtime_from_card (app, keyno, &fprtime)) fprtime = 0; @@ -2256,7 +2266,28 @@ do_readcert (app_t app, const char *certid, *cert = NULL; *certlen = 0; - if (!ascii_strcasecmp (certid, "OPENPGP.3")) + if (strlen (certid) == 40) + { + int keyno; + const unsigned char *keygrip_str; + + for (keyno = 0; keyno < 3; keyno++) + { + keygrip_str = app->app_local->pk[keyno].keygrip_str; + if (!strncmp (keygrip_str, certid, 40)) + break; + } + + if (keyno == 2) + ; + else if (keyno == 1) + occurrence = 1; + else if (keyno == 0) + occurrence = 2; + else + return gpg_error (GPG_ERR_INV_ID); + } + else if (!ascii_strcasecmp (certid, "OPENPGP.3")) ; else if (!ascii_strcasecmp (certid, "OPENPGP.2")) occurrence = 1; @@ -3939,7 +3970,7 @@ change_keyattr (app_t app, ctrl_t ctrl, else log_info ("key attribute of OPENPGP.%d changed\n", keyno+1); flush_cache (app); - parse_algorithm_attribute (app, keyno); + err = parse_algorithm_attribute (app, keyno); app->did_chv1 = 0; app->did_chv2 = 0; app->did_chv3 = 0; @@ -5445,9 +5476,15 @@ do_auth (app_t app, ctrl_t ctrl, const char *keyidstr, goto indata_ready; } - if (app->app_local->keyattr[2].key_type == KEY_TYPE_RSA - && indatalen > 101) /* For a 2048 bit key. */ - return gpg_error (GPG_ERR_INV_VALUE); + if (app->app_local->keyattr[2].key_type == KEY_TYPE_RSA) + { + int size_40percent = (app->app_local->keyattr[2].rsa.n_bits+7)/8 * 4; + + /* OpenPGP card does PKCS#1 for RSA, data should not be larger + than 40% of the modulus length. */ + if (indatalen * 10 > size_40percent) + return gpg_error (GPG_ERR_INV_VALUE); + } if (app->app_local->keyattr[2].key_type == KEY_TYPE_ECC) { @@ -5490,6 +5527,11 @@ do_auth (app_t app, ctrl_t ctrl, const char *keyidstr, exmode = 1; /* Use extended length. */ le_value = app->app_local->keyattr[2].rsa.n_bits / 8; } + else if (app->app_local->cardcap.cmd_chaining && indatalen > 254) + { + exmode = -254; /* Command chaining with max. 254 bytes. */ + le_value = 0; + } else if (indatalen > 255) { if (!app->app_local->cardcap.ext_lc_le) @@ -5908,12 +5950,13 @@ send_keyinfo_if_available (app_t app, ctrl_t ctrl, char *serial, int data, int i) { char idbuf[50]; + const char *usage = get_usage_string (i); if (app->app_local->pk[i].read_done) { sprintf (idbuf, "OPENPGP.%d", i+1); send_keyinfo (ctrl, data, - app->app_local->pk[i].keygrip_str, serial, idbuf); + app->app_local->pk[i].keygrip_str, serial, idbuf, usage); } } @@ -6146,7 +6189,7 @@ get_algorithm_attribute_string (const unsigned char *buffer, /* Parse and optionally show the algorithm attributes for KEYNO. KEYNO must be in the range 0..2. */ -static void +static gpg_error_t parse_algorithm_attribute (app_t app, int keyno) { unsigned char *buffer; @@ -6156,6 +6199,7 @@ parse_algorithm_attribute (app_t app, int keyno) enum gcry_pk_algos galgo; unsigned int nbits; const char *curve; + gpg_error_t err = 0; log_assert (keyno >=0 && keyno <= 2); @@ -6166,13 +6210,13 @@ parse_algorithm_attribute (app_t app, int keyno) if (!relptr) { log_error ("error reading DO 0x%02X\n", 0xc1+keyno); - return; + return gpg_error (GPG_ERR_CARD); } if (buflen < 1) { log_error ("error reading DO 0x%02X\n", 0xc1+keyno); xfree (relptr); - return; + return gpg_error (GPG_ERR_CARD); } if (opt.verbose) @@ -6215,7 +6259,8 @@ parse_algorithm_attribute (app_t app, int keyno) app->app_local->keyattr[keyno].ecc.algo = *buffer; app->app_local->keyattr[keyno].ecc.flags = 0; - if (buffer[buflen-1] == 0x00 || buffer[buflen-1] == 0xff) + if (APP_CARD(app)->cardtype == CARDTYPE_YUBIKEY + || buffer[buflen-1] == 0x00 || buffer[buflen-1] == 0xff) { /* Found "pubkey required"-byte for private key template. */ oidlen--; if (buffer[buflen-1] == 0xff) @@ -6225,7 +6270,10 @@ parse_algorithm_attribute (app_t app, int keyno) curve = ecc_curve (buffer + 1, oidlen); if (!curve) - log_printhex (buffer+1, buflen-1, "Curve with OID not supported: "); + { + log_printhex (buffer+1, buflen-1, "Curve with OID not supported: "); + err = gpg_error (GPG_ERR_CARD); + } else { app->app_local->keyattr[keyno].key_type = KEY_TYPE_ECC; @@ -6255,6 +6303,7 @@ parse_algorithm_attribute (app_t app, int keyno) desc[keyno], app->app_local->keyattr[keyno].keyalgo); xfree (relptr); + return err; } @@ -6325,16 +6374,16 @@ gpg_error_t app_select_openpgp (app_t app) { int slot = app_get_slot (app); - int rc; + gpg_error_t err; unsigned char *buffer; size_t buflen; void *relptr; /* Note that the card can't cope with P2=0xCO, thus we need to pass a special flag value. */ - rc = iso7816_select_application (slot, - openpgp_aid, sizeof openpgp_aid, 0x0001); - if (!rc) + err = iso7816_select_application (slot, + openpgp_aid, sizeof openpgp_aid, 0x0001); + if (!err) { unsigned int manufacturer; @@ -6350,8 +6399,8 @@ app_select_openpgp (app_t app) replace a possibly already set one from a EF.GDO with this one. Note, that for current OpenPGP cards, no EF.GDO exists and thus it won't matter at all. */ - rc = iso7816_get_data (slot, 0, 0x004F, &buffer, &buflen); - if (rc) + err = iso7816_get_data (slot, 0, 0x004F, &buffer, &buflen); + if (err) goto leave; if (opt.verbose) { @@ -6385,7 +6434,7 @@ app_select_openpgp (app_t app) app->app_local = xtrycalloc (1, sizeof *app->app_local); if (!app->app_local) { - rc = gpg_error (gpg_err_code_from_errno (errno)); + err = gpg_error_from_syserror (); goto leave; } @@ -6419,6 +6468,7 @@ app_select_openpgp (app_t app) { log_error (_("can't access %s - invalid OpenPGP card?\n"), "CHV Status Bytes"); + err = gpg_error (GPG_ERR_CARD); goto leave; } app->force_chv1 = (buflen && *buffer == 0); @@ -6430,6 +6480,7 @@ app_select_openpgp (app_t app) { log_error (_("can't access %s - invalid OpenPGP card?\n"), "Extended Capability Flags" ); + err = gpg_error (GPG_ERR_CARD); goto leave; } if (buflen) @@ -6480,9 +6531,13 @@ app_select_openpgp (app_t app) if (opt.verbose) show_caps (app->app_local); - parse_algorithm_attribute (app, 0); - parse_algorithm_attribute (app, 1); - parse_algorithm_attribute (app, 2); + err = parse_algorithm_attribute (app, 0); + if (!err) + err = parse_algorithm_attribute (app, 1); + if (!err) + err = parse_algorithm_attribute (app, 2); + if (err) + goto leave; if (opt.verbose > 1) dump_all_do (slot); @@ -6511,7 +6566,7 @@ app_select_openpgp (app_t app) } leave: - if (rc) + if (err) do_deinit (app); - return rc; + return err; } |