mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-02 12:01:32 +01:00
agent: Move confirmation handling into findkey.c.
* agent/agent.h (divert_tpm2_pksign, divert_tpm2_pkdecrypt): Fix API. (divert_pksign, divert_pkdecrypt): Likewise. * agent/divert-scd.c (ask_for_card): Remove. (divert_pksign, divert_pkdecrypt): Don't call ask_for_card. * agent/divert-tpm2.c (divert_tpm2_pksign, divert_tpm2_pkdecrypt): Remove DESC_TEXT argument. * agent/findkey.c (prompt_for_card): New (was: ask_for_card). (agent_key_from_file): Call prompt_for_card when it's a key on card. * agent/pkdecrypt.c (agent_pkdecrypt): Follow the change of API. * agent/pksign.c (agent_pksign_do): Likewise. -- Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
598b3fdfaa
commit
6a37240cf2
@ -593,11 +593,11 @@ void agent_reload_trustlist (void);
|
||||
|
||||
/*-- divert-tpm2.c --*/
|
||||
#ifdef HAVE_LIBTSS
|
||||
int divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
int divert_tpm2_pksign (ctrl_t ctrl,
|
||||
const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||
size_t *r_siglen);
|
||||
int divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
int divert_tpm2_pkdecrypt (ctrl_t ctrl,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len, int *r_padding);
|
||||
@ -605,25 +605,25 @@ int divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
|
||||
gcry_sexp_t s_skey);
|
||||
#else /*!HAVE_LIBTSS*/
|
||||
static inline int
|
||||
divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
divert_tpm2_pksign (ctrl_t ctrl,
|
||||
const unsigned char *digest,
|
||||
size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info,
|
||||
unsigned char **r_sig,
|
||||
size_t *r_siglen)
|
||||
{
|
||||
(void)ctrl; (void)desc_text; (void)digest; (void)digestlen;
|
||||
(void)ctrl; (void)digest; (void)digestlen;
|
||||
(void)algo; (void)shadow_info; (void)r_sig; (void)r_siglen;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
static inline int
|
||||
divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
divert_tpm2_pkdecrypt (ctrl_t ctrl,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len,
|
||||
int *r_padding)
|
||||
{
|
||||
(void)ctrl; (void)desc_text; (void)cipher; (void)shadow_info;
|
||||
(void)ctrl; (void)cipher; (void)shadow_info;
|
||||
(void)r_buf; (void)r_len; (void)r_padding;
|
||||
return gpg_error (GPG_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
@ -639,15 +639,14 @@ divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
|
||||
|
||||
|
||||
/*-- divert-scd.c --*/
|
||||
int divert_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
int divert_pksign (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||
unsigned char **r_sig,
|
||||
size_t *r_siglen);
|
||||
int divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
int divert_pkdecrypt (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len, int *r_padding);
|
||||
int divert_generic_cmd (ctrl_t ctrl,
|
||||
const char *cmdline, void *assuan_context);
|
||||
|
@ -32,113 +32,6 @@
|
||||
#include "../common/sexp-parse.h"
|
||||
|
||||
|
||||
static gpg_error_t
|
||||
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info,
|
||||
const unsigned char *grip, char **r_kid)
|
||||
{
|
||||
char *serialno;
|
||||
char *desc;
|
||||
char *want_sn;
|
||||
int len;
|
||||
gpg_error_t err;
|
||||
char hexgrip[41];
|
||||
|
||||
*r_kid = NULL;
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
|
||||
if (shadow_info)
|
||||
{
|
||||
err = parse_shadow_info (shadow_info, &want_sn, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
want_sn = NULL;
|
||||
|
||||
len = want_sn? strlen (want_sn) : 0;
|
||||
if (len == 32 && !strncmp (want_sn, "D27600012401", 12))
|
||||
{
|
||||
/* This is an OpenPGP card - reformat */
|
||||
if (!strncmp (want_sn+16, "0006", 4))
|
||||
{
|
||||
/* This is a Yubikey. Print the s/n as it would be printed
|
||||
* on Yubikey 5. Example: D2760001240100000006120808620000
|
||||
* mmmm^^^^^^^^ */
|
||||
unsigned long sn;
|
||||
|
||||
sn = atoi_4 (want_sn+20) * 10000;
|
||||
sn += atoi_4 (want_sn+24);
|
||||
snprintf (want_sn, 32, "%lu %03lu %03lu",
|
||||
(sn/1000000ul), (sn/1000ul % 1000ul), (sn % 1000ul));
|
||||
}
|
||||
else /* Default is the Zeitcontrol card print format. */
|
||||
{
|
||||
memmove (want_sn, want_sn+16, 4);
|
||||
want_sn[4] = ' ';
|
||||
memmove (want_sn+5, want_sn+20, 8);
|
||||
want_sn[13] = 0;
|
||||
}
|
||||
}
|
||||
else if (len == 20 && want_sn[19] == '0')
|
||||
{
|
||||
/* We assume that a 20 byte serial number is a standard one
|
||||
* which has the property to have a zero in the last nibble (Due
|
||||
* to BCD representation). We don't display this '0' because it
|
||||
* may confuse the user. */
|
||||
want_sn[19] = 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Scan device(s), and check if key for GRIP is available. */
|
||||
err = agent_card_serialno (ctrl, &serialno, NULL);
|
||||
if (!err)
|
||||
{
|
||||
struct card_key_info_s *keyinfo;
|
||||
|
||||
xfree (serialno);
|
||||
err = agent_card_keyinfo (ctrl, hexgrip, 0, &keyinfo);
|
||||
if (!err)
|
||||
{
|
||||
/* Key for GRIP found, use it directly. */
|
||||
agent_card_free_keyinfo (keyinfo);
|
||||
xfree (want_sn);
|
||||
if ((*r_kid = xtrystrdup (hexgrip)))
|
||||
return 0;
|
||||
else
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
}
|
||||
|
||||
if (!want_sn)
|
||||
; /* No shadow info so we can't ask; ERR is already set. */
|
||||
else if (asprintf (&desc,
|
||||
"%s:%%0A%%0A"
|
||||
" %s",
|
||||
L_("Please insert the card with serial number"),
|
||||
want_sn) < 0)
|
||||
{
|
||||
err = out_of_core ();
|
||||
}
|
||||
else
|
||||
{
|
||||
err = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
|
||||
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
|
||||
gpg_err_code (err) == GPG_ERR_NO_PIN_ENTRY)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
|
||||
xfree (desc);
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
xfree (want_sn);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Put the DIGEST into an DER encoded container and return it in R_VAL. */
|
||||
static int
|
||||
encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
|
||||
@ -426,44 +319,37 @@ getpin_cb (void *opaque, const char *desc_text, const char *info,
|
||||
|
||||
|
||||
/* This function is used when a sign operation has been diverted to a
|
||||
* smartcard. DESC_TEXT is the original text for a prompt has send by
|
||||
* gpg to gpg-agent.
|
||||
* smartcard.
|
||||
*
|
||||
* Note: If SHADOW_INFO is NULL the user can't be asked to insert the
|
||||
* card, we simply try to use an inserted card with the given keygrip.
|
||||
*
|
||||
* FIXME: Explain the other args. */
|
||||
int
|
||||
divert_pksign (ctrl_t ctrl, const char *desc_text, const unsigned char *grip,
|
||||
divert_pksign (ctrl_t ctrl, const unsigned char *grip,
|
||||
const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||
unsigned char **r_sig,
|
||||
size_t *r_siglen)
|
||||
{
|
||||
int rc;
|
||||
char *kid;
|
||||
char hexgrip[41];
|
||||
size_t siglen;
|
||||
unsigned char *sigval = NULL;
|
||||
|
||||
(void)desc_text;
|
||||
|
||||
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||
if (rc)
|
||||
return rc;
|
||||
/* Note that the KID may be an keyref or a keygrip. The signing
|
||||
* functions handle both. */
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
|
||||
if (!algo)
|
||||
{
|
||||
/* This is the PureEdDSA case. (DIGEST,DIGESTLEN) this the
|
||||
* entire data which will be signed. */
|
||||
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, NULL,
|
||||
rc = agent_card_pksign (ctrl, hexgrip, getpin_cb, ctrl, NULL,
|
||||
0, digest, digestlen, &sigval, &siglen);
|
||||
}
|
||||
else if (algo == MD_USER_TLS_MD5SHA1)
|
||||
{
|
||||
int save = ctrl->use_auth_call;
|
||||
ctrl->use_auth_call = 1;
|
||||
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, NULL,
|
||||
rc = agent_card_pksign (ctrl, hexgrip, getpin_cb, ctrl, NULL,
|
||||
algo, digest, digestlen, &sigval, &siglen);
|
||||
ctrl->use_auth_call = save;
|
||||
}
|
||||
@ -475,7 +361,7 @@ divert_pksign (ctrl_t ctrl, const char *desc_text, const unsigned char *grip,
|
||||
rc = encode_md_for_card (digest, digestlen, algo, &data, &ndata);
|
||||
if (!rc)
|
||||
{
|
||||
rc = agent_card_pksign (ctrl, kid, getpin_cb, ctrl, NULL,
|
||||
rc = agent_card_pksign (ctrl, hexgrip, getpin_cb, ctrl, NULL,
|
||||
algo, data, ndata, &sigval, &siglen);
|
||||
xfree (data);
|
||||
}
|
||||
@ -487,8 +373,6 @@ divert_pksign (ctrl_t ctrl, const char *desc_text, const unsigned char *grip,
|
||||
*r_siglen = siglen;
|
||||
}
|
||||
|
||||
xfree (kid);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -498,14 +382,13 @@ divert_pksign (ctrl_t ctrl, const char *desc_text, const unsigned char *grip,
|
||||
allocated buffer in R_BUF. The padding information is stored at
|
||||
R_PADDING with -1 for not known. */
|
||||
int
|
||||
divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
divert_pkdecrypt (ctrl_t ctrl,
|
||||
const unsigned char *grip,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len, int *r_padding)
|
||||
{
|
||||
int rc;
|
||||
char *kid;
|
||||
char hexgrip[41];
|
||||
const unsigned char *s;
|
||||
size_t n;
|
||||
int depth;
|
||||
@ -514,7 +397,7 @@ divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
char *plaintext;
|
||||
size_t plaintextlen;
|
||||
|
||||
(void)desc_text;
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
|
||||
*r_padding = -1;
|
||||
s = cipher;
|
||||
@ -591,11 +474,7 @@ divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
ciphertext = s;
|
||||
ciphertextlen = n;
|
||||
|
||||
rc = ask_for_card (ctrl, shadow_info, grip, &kid);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = agent_card_pkdecrypt (ctrl, kid, getpin_cb, ctrl, NULL,
|
||||
rc = agent_card_pkdecrypt (ctrl, hexgrip, getpin_cb, ctrl, NULL,
|
||||
ciphertext, ciphertextlen,
|
||||
&plaintext, &plaintextlen, r_padding);
|
||||
if (!rc)
|
||||
@ -603,7 +482,6 @@ divert_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
*r_buf = plaintext;
|
||||
*r_len = plaintextlen;
|
||||
}
|
||||
xfree (kid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,11 @@
|
||||
#include "../common/sexp-parse.h"
|
||||
|
||||
int
|
||||
divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
|
||||
divert_tpm2_pksign (ctrl_t ctrl,
|
||||
const unsigned char *digest, size_t digestlen, int algo,
|
||||
const unsigned char *shadow_info, unsigned char **r_sig,
|
||||
size_t *r_siglen)
|
||||
{
|
||||
(void)desc_text;
|
||||
(void)algo;
|
||||
return agent_tpm2d_pksign(ctrl, digest, digestlen,
|
||||
shadow_info, r_sig, r_siglen);
|
||||
@ -76,7 +75,7 @@ divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
|
||||
}
|
||||
|
||||
int
|
||||
divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
divert_tpm2_pkdecrypt (ctrl_t ctrl,
|
||||
const unsigned char *cipher,
|
||||
const unsigned char *shadow_info,
|
||||
char **r_buf, size_t *r_len, int *r_padding)
|
||||
@ -86,8 +85,6 @@ divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
|
||||
*r_padding = -1;
|
||||
|
||||
(void)desc_text;
|
||||
|
||||
s = cipher;
|
||||
if (*s != '(')
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
|
124
agent/findkey.c
124
agent/findkey.c
@ -961,6 +961,112 @@ remove_key_file (const unsigned char *grip)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prompt a user the card insertion, when it's not available yet.
|
||||
*/
|
||||
static gpg_error_t
|
||||
prompt_for_card (ctrl_t ctrl, const unsigned char *shadow_info,
|
||||
const unsigned char *grip)
|
||||
{
|
||||
char *serialno;
|
||||
char *desc;
|
||||
char *want_sn;
|
||||
int len;
|
||||
gpg_error_t err;
|
||||
char hexgrip[41];
|
||||
|
||||
bin2hex (grip, 20, hexgrip);
|
||||
|
||||
if (shadow_info)
|
||||
{
|
||||
err = parse_shadow_info (shadow_info, &want_sn, NULL, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
want_sn = NULL;
|
||||
|
||||
len = want_sn? strlen (want_sn) : 0;
|
||||
if (len == 32 && !strncmp (want_sn, "D27600012401", 12))
|
||||
{
|
||||
/* This is an OpenPGP card - reformat */
|
||||
if (!strncmp (want_sn+16, "0006", 4))
|
||||
{
|
||||
/* This is a Yubikey. Print the s/n as it would be printed
|
||||
* on Yubikey 5. Example: D2760001240100000006120808620000
|
||||
* mmmm^^^^^^^^ */
|
||||
unsigned long sn;
|
||||
|
||||
sn = atoi_4 (want_sn+20) * 10000;
|
||||
sn += atoi_4 (want_sn+24);
|
||||
snprintf (want_sn, 32, "%lu %03lu %03lu",
|
||||
(sn/1000000ul), (sn/1000ul % 1000ul), (sn % 1000ul));
|
||||
}
|
||||
else /* Default is the Zeitcontrol card print format. */
|
||||
{
|
||||
memmove (want_sn, want_sn+16, 4);
|
||||
want_sn[4] = ' ';
|
||||
memmove (want_sn+5, want_sn+20, 8);
|
||||
want_sn[13] = 0;
|
||||
}
|
||||
}
|
||||
else if (len == 20 && want_sn[19] == '0')
|
||||
{
|
||||
/* We assume that a 20 byte serial number is a standard one
|
||||
* which has the property to have a zero in the last nibble (Due
|
||||
* to BCD representation). We don't display this '0' because it
|
||||
* may confuse the user. */
|
||||
want_sn[19] = 0;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Scan device(s), and check if key for GRIP is available. */
|
||||
err = agent_card_serialno (ctrl, &serialno, NULL);
|
||||
if (!err)
|
||||
{
|
||||
struct card_key_info_s *keyinfo;
|
||||
|
||||
xfree (serialno);
|
||||
err = agent_card_keyinfo (ctrl, hexgrip, 0, &keyinfo);
|
||||
if (!err)
|
||||
{
|
||||
/* Key for GRIP found, use it directly. */
|
||||
agent_card_free_keyinfo (keyinfo);
|
||||
xfree (want_sn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!want_sn)
|
||||
; /* No shadow info so we can't ask; ERR is already set. */
|
||||
else if (asprintf (&desc,
|
||||
"%s:%%0A%%0A"
|
||||
" %s",
|
||||
L_("Please insert the card with serial number"),
|
||||
want_sn) < 0)
|
||||
{
|
||||
err = out_of_core ();
|
||||
}
|
||||
else
|
||||
{
|
||||
err = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
|
||||
if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK &&
|
||||
gpg_err_code (err) == GPG_ERR_NO_PIN_ENTRY)
|
||||
err = gpg_error (GPG_ERR_CARD_NOT_PRESENT);
|
||||
|
||||
xfree (desc);
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
xfree (want_sn);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return the secret key as an S-Exp in RESULT after locating it using
|
||||
the GRIP. Caller should set GRIP=NULL, when a key in a file is
|
||||
intended to be used for cryptographic operation. In this case,
|
||||
@ -1143,24 +1249,36 @@ agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
|
||||
if (shadow_info)
|
||||
{
|
||||
const unsigned char *s;
|
||||
unsigned char *shadow_type;
|
||||
size_t n;
|
||||
|
||||
err = agent_get_shadow_info (buf, &s);
|
||||
err = agent_get_shadow_info_type (buf, &s, &shadow_type);
|
||||
if (!err)
|
||||
{
|
||||
n = gcry_sexp_canon_len (s, 0, NULL,NULL);
|
||||
log_assert (n);
|
||||
*shadow_info = xtrymalloc (n);
|
||||
if (!*shadow_info)
|
||||
{
|
||||
err = out_of_core ();
|
||||
goto shadow_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (*shadow_info, s, n);
|
||||
err = 0;
|
||||
/*
|
||||
* When it's a key on card (not on tpm2), maks sure
|
||||
* it's available.
|
||||
*/
|
||||
if (strcmp (shadow_type, "t1-v1") == 0 && !grip)
|
||||
err = prompt_for_card (ctrl, *shadow_info, ctrl->keygrip);
|
||||
}
|
||||
}
|
||||
if (err)
|
||||
else
|
||||
shadow_error:
|
||||
log_error ("get_shadow_info failed: %s\n", gpg_strerror (err));
|
||||
|
||||
xfree (shadow_type);
|
||||
}
|
||||
else
|
||||
err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
|
||||
|
@ -89,11 +89,11 @@ agent_pkdecrypt (ctrl_t ctrl, const char *desc_text,
|
||||
}
|
||||
|
||||
if (agent_is_tpm2_key (s_skey))
|
||||
err = divert_tpm2_pkdecrypt (ctrl, desc_text, ciphertext, shadow_info,
|
||||
err = divert_tpm2_pkdecrypt (ctrl, ciphertext, shadow_info,
|
||||
&buf, &len, r_padding);
|
||||
else
|
||||
err = divert_pkdecrypt (ctrl, desc_text, ctrl->keygrip, ciphertext,
|
||||
shadow_info, &buf, &len, r_padding);
|
||||
err = divert_pkdecrypt (ctrl, ctrl->keygrip, ciphertext,
|
||||
&buf, &len, r_padding);
|
||||
if (err)
|
||||
{
|
||||
log_error ("smartcard decryption failed: %s\n", gpg_strerror (err));
|
||||
|
@ -392,23 +392,17 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
|
||||
}
|
||||
|
||||
{
|
||||
char *desc2 = NULL;
|
||||
|
||||
if (desc_text)
|
||||
agent_modify_description (desc_text, NULL, s_pkey, &desc2);
|
||||
|
||||
if (agent_is_tpm2_key (s_skey))
|
||||
err = divert_tpm2_pksign (ctrl, desc2? desc2 : desc_text,
|
||||
err = divert_tpm2_pksign (ctrl,
|
||||
data, datalen,
|
||||
ctrl->digest.algo,
|
||||
shadow_info, &buf, &len);
|
||||
else
|
||||
err = divert_pksign (ctrl, desc2? desc2 : desc_text,
|
||||
err = divert_pksign (ctrl,
|
||||
ctrl->keygrip,
|
||||
data, datalen,
|
||||
ctrl->digest.algo,
|
||||
shadow_info, &buf, &len);
|
||||
xfree (desc2);
|
||||
&buf, &len);
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user