mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-21 14:47:03 +01:00
gpg: Allow decryption using PIV cards.
* g10/call-agent.c (struct getattr_one_parm_s): New. (getattr_one_status_cb): New. (agent_scd_getattr_one): New. * g10/pubkey-enc.c (get_it): Allow the standard leading zero byte from pkcs#1. * g10/skclist.c (enum_secret_keys): Handle non-OpenPGP cards. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
2b1135cf92
commit
ec6a677923
@ -947,6 +947,86 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Object used with the agent_scd_getattr_one. */
|
||||
struct getattr_one_parm_s {
|
||||
const char *keyword; /* Keyword to look for. */
|
||||
char *data; /* Malloced and unescaped data. */
|
||||
gpg_error_t err; /* Error code or 0 on success. */
|
||||
};
|
||||
|
||||
|
||||
/* Callback for agent_scd_getattr_one. */
|
||||
static gpg_error_t
|
||||
getattr_one_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
struct getattr_one_parm_s *parm = opaque;
|
||||
const char *s;
|
||||
|
||||
if (parm->data)
|
||||
return 0; /* We want only the first occurrence. */
|
||||
|
||||
if ((s=has_leading_keyword (line, parm->keyword)))
|
||||
{
|
||||
parm->data = percent_plus_unescape (s, 0xff);
|
||||
if (!parm->data)
|
||||
parm->err = gpg_error_from_syserror ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Simplified version of agent_scd_getattr. This function returns
|
||||
* only the first occurance of the attribute NAME and stores it at
|
||||
* R_VALUE. A nul in the result is silennly replaced by 0xff. On
|
||||
* error NULL is stored at R_VALUE. */
|
||||
gpg_error_t
|
||||
agent_scd_getattr_one (const char *name, char **r_value)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s inqparm;
|
||||
struct getattr_one_parm_s parm;
|
||||
|
||||
*r_value = NULL;
|
||||
|
||||
if (!*name)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
memset (&inqparm, 0, sizeof inqparm);
|
||||
inqparm.ctx = agent_ctx;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
parm.keyword = name;
|
||||
|
||||
/* We assume that NAME does not need escaping. */
|
||||
if (12 + strlen (name) > DIM(line)-1)
|
||||
return gpg_error (GPG_ERR_TOO_LARGE);
|
||||
stpcpy (stpcpy (line, "SCD GETATTR "), name);
|
||||
|
||||
err = start_agent (NULL, 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &inqparm,
|
||||
getattr_one_status_cb, &parm);
|
||||
if (!err && parm.err)
|
||||
err = parm.err;
|
||||
else if (!err && !parm.data)
|
||||
err = gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
if (!err)
|
||||
*r_value = parm.data;
|
||||
else
|
||||
xfree (parm.data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Call the agent to retrieve a data object. This function returns
|
||||
* the data in the same structure as used by the learn command. It is
|
||||
|
@ -96,6 +96,9 @@ int agent_scd_serialno (char **r_serialno, const char *demand);
|
||||
/* Send an APDU to the card. */
|
||||
gpg_error_t agent_scd_apdu (const char *hexapdu, unsigned int *r_sw);
|
||||
|
||||
/* Get attribute NAME from the card and store at R_VALUE. */
|
||||
gpg_error_t agent_scd_getattr_one (const char *name, char **r_value);
|
||||
|
||||
/* Update INFO with the attribute NAME. */
|
||||
int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
||||
|
||||
|
@ -319,6 +319,16 @@ get_it (ctrl_t ctrl,
|
||||
err = gpg_error (GPG_ERR_WRONG_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* FIXME: Actually the leading zero is required but due to
|
||||
* the way we encode the output in libgcrypt as an MPI we
|
||||
* are not able to encode that leading zero. However, when
|
||||
* using a Smartcard we are doing it the right way and
|
||||
* therefore we have to skip the zero. This should be fixed
|
||||
* in gpg-agent of course. */
|
||||
if (!frame[n])
|
||||
n++;
|
||||
|
||||
if (frame[n] == 1 && frame[nframe - 1] == 2)
|
||||
{
|
||||
log_info (_("old encoding of the DEK is not supported\n"));
|
||||
|
@ -340,6 +340,10 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
||||
SK_LIST results;
|
||||
} *c = *context;
|
||||
|
||||
#if MAX_FINGERPRINT_LEN < KEYGRIP_LEN
|
||||
# error buffer too short for this configuration
|
||||
#endif
|
||||
|
||||
if (!c)
|
||||
{
|
||||
/* Make a new context. */
|
||||
@ -430,17 +434,58 @@ enum_secret_keys (ctrl_t ctrl, void **context, PKT_public_key *sk)
|
||||
xfree (serialno);
|
||||
c->info.fpr2len = 0;
|
||||
err = agent_scd_getattr ("KEY-FPR", &c->info);
|
||||
if (!err)
|
||||
{
|
||||
if (c->info.fpr2len)
|
||||
{
|
||||
c->fpr2[0] = '0';
|
||||
c->fpr2[1] = 'x';
|
||||
bin2hex (c->info.fpr2, sizeof c->info.fpr2,
|
||||
c->fpr2 + 2);
|
||||
name = c->fpr2;
|
||||
}
|
||||
}
|
||||
else if (gpg_err_code (err) == GPG_ERR_INV_NAME)
|
||||
{
|
||||
/* KEY-FPR not supported by the card - get
|
||||
* the key using the keygrip. */
|
||||
char *keyref;
|
||||
strlist_t kplist, sl;
|
||||
const char *s;
|
||||
int i;
|
||||
|
||||
err = agent_scd_getattr_one ("$ENCRKEYID", &keyref);
|
||||
if (!err)
|
||||
{
|
||||
err = agent_scd_keypairinfo (ctrl, &kplist);
|
||||
if (!err)
|
||||
{
|
||||
for (sl = kplist; sl; sl = sl->next)
|
||||
if ((s = strchr (sl->d, ' '))
|
||||
&& !strcmp (s+1, keyref))
|
||||
break;
|
||||
if (sl)
|
||||
{
|
||||
c->fpr2[0] = '&';
|
||||
for (i=1, s=sl->d;
|
||||
(*s && *s != ' '
|
||||
&& i < sizeof c->fpr2 - 3);
|
||||
s++, i++)
|
||||
c->fpr2[i] = *s;
|
||||
c->fpr2[i] = 0;
|
||||
name = c->fpr2;
|
||||
}
|
||||
else /* Restore error. */
|
||||
err = gpg_error (GPG_ERR_INV_NAME);
|
||||
free_strlist (kplist);
|
||||
}
|
||||
}
|
||||
xfree (keyref);
|
||||
}
|
||||
if (err)
|
||||
log_error ("error retrieving key fingerprint from card: %s\n",
|
||||
log_error ("error retrieving key from card: %s\n",
|
||||
gpg_strerror (err));
|
||||
|
||||
if (c->info.fpr2len)
|
||||
{
|
||||
c->fpr2[0] = '0';
|
||||
c->fpr2[1] = 'x';
|
||||
bin2hex (c->info.fpr2, sizeof c->info.fpr2,c->fpr2+2);
|
||||
name = c->fpr2;
|
||||
}
|
||||
c->sl = c->sl->next;
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user