summaryrefslogtreecommitdiff
path: root/scd/app-openpgp.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/app-openpgp.c')
-rw-r--r--scd/app-openpgp.c119
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;
}