mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-18 14:17:03 +01:00
agent: Allow to use SETHASH for arbitrary data.
* agent/agent.h (struct server_control_s): Add field digest.data. * agent/gpg-agent.c (agent_deinit_default_ctrl): Free that field. * agent/command.c (reset_notify): Ditto. (start_command_handler): ditto. (cmd_sethash): Add new option --inquire. * agent/call-scd.c (agent_card_pksign): For now return an error if inquire mode was used. * agent/command-ssh.c (ssh_handler_sign_request): Make sure digest.data is cleared. * agent/divert-scd.c (divert_pksign): Implement inquire mode. * agent/pksign.c (agent_pksign_do): Ditto. -- This is required to support EdDSA according to RFC8410. GnuPG-bug-id: 4888
This commit is contained in:
parent
b1694987bb
commit
b18fb0264a
@ -245,9 +245,12 @@ struct server_control_s
|
|||||||
|
|
||||||
/* Information on the currently used digest (for signing commands). */
|
/* Information on the currently used digest (for signing commands). */
|
||||||
struct {
|
struct {
|
||||||
|
char *data; /* NULL or malloced data of length VALUELEN. If
|
||||||
|
this is set The other fields are ignored. Used
|
||||||
|
for PureEdDSA. */
|
||||||
|
int valuelen;
|
||||||
int algo;
|
int algo;
|
||||||
unsigned char value[MAX_DIGEST_LEN];
|
unsigned char value[MAX_DIGEST_LEN];
|
||||||
int valuelen;
|
|
||||||
int raw_value: 1;
|
int raw_value: 1;
|
||||||
} digest;
|
} digest;
|
||||||
unsigned char keygrip[20];
|
unsigned char keygrip[20];
|
||||||
|
@ -1001,6 +1001,11 @@ agent_card_pksign (ctrl_t ctrl,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
/* FIXME: In the mdalgo case (INDATA,INDATALEN) might be long and
|
||||||
|
* thus we can't convey it on a single Assuan line. */
|
||||||
|
if (!mdalgo)
|
||||||
|
gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
if (indatalen*2 + 50 > DIM(line))
|
if (indatalen*2 + 50 > DIM(line))
|
||||||
return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
|
return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));
|
||||||
|
|
||||||
|
@ -2809,6 +2809,8 @@ ssh_handler_sign_request (ctrl_t ctrl, estream_t request, estream_t response)
|
|||||||
if (!hash_algo)
|
if (!hash_algo)
|
||||||
hash_algo = GCRY_MD_SHA1; /* Use the default. */
|
hash_algo = GCRY_MD_SHA1; /* Use the default. */
|
||||||
ctrl->digest.algo = hash_algo;
|
ctrl->digest.algo = hash_algo;
|
||||||
|
xfree (ctrl->digest.data);
|
||||||
|
ctrl->digest.data = NULL;
|
||||||
if ((spec.flags & SPEC_FLAG_USE_PKCS1V2))
|
if ((spec.flags & SPEC_FLAG_USE_PKCS1V2))
|
||||||
ctrl->digest.raw_value = 0;
|
ctrl->digest.raw_value = 0;
|
||||||
else
|
else
|
||||||
|
100
agent/command.c
100
agent/command.c
@ -243,6 +243,8 @@ reset_notify (assuan_context_t ctx, char *line)
|
|||||||
memset (ctrl->keygrip, 0, 20);
|
memset (ctrl->keygrip, 0, 20);
|
||||||
ctrl->have_keygrip = 0;
|
ctrl->have_keygrip = 0;
|
||||||
ctrl->digest.valuelen = 0;
|
ctrl->digest.valuelen = 0;
|
||||||
|
xfree (ctrl->digest.data);
|
||||||
|
ctrl->digest.data = NULL;
|
||||||
|
|
||||||
xfree (ctrl->server_local->keydesc);
|
xfree (ctrl->server_local->keydesc);
|
||||||
ctrl->server_local->keydesc = NULL;
|
ctrl->server_local->keydesc = NULL;
|
||||||
@ -704,20 +706,23 @@ cmd_setkeydesc (assuan_context_t ctx, char *line)
|
|||||||
|
|
||||||
|
|
||||||
static const char hlp_sethash[] =
|
static const char hlp_sethash[] =
|
||||||
"SETHASH (--hash=<name>)|(<algonumber>) <hexstring>\n"
|
"SETHASH (--hash=<name>)|(<algonumber>) <hexstring>]\n"
|
||||||
|
"SETHASH --inquire\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The client can use this command to tell the server about the data\n"
|
"The client can use this command to tell the server about the data\n"
|
||||||
"(which usually is a hash) to be signed.";
|
"(which usually is a hash) to be signed. The option --inquire is\n"
|
||||||
|
"used to ask back for to-be-signed data in case of PureEdDSA";
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
cmd_sethash (assuan_context_t ctx, char *line)
|
cmd_sethash (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
int rc;
|
gpg_error_t err;
|
||||||
size_t n;
|
size_t n;
|
||||||
char *p;
|
char *p;
|
||||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
char *endp;
|
char *endp;
|
||||||
int algo;
|
int algo;
|
||||||
|
int opt_inquire;
|
||||||
|
|
||||||
/* Parse the alternative hash options which may be used instead of
|
/* Parse the alternative hash options which may be used instead of
|
||||||
the algo number. */
|
the algo number. */
|
||||||
@ -740,47 +745,89 @@ cmd_sethash (assuan_context_t ctx, char *line)
|
|||||||
else if (has_option (line, "--hash=tls-md5sha1"))
|
else if (has_option (line, "--hash=tls-md5sha1"))
|
||||||
algo = MD_USER_TLS_MD5SHA1;
|
algo = MD_USER_TLS_MD5SHA1;
|
||||||
else
|
else
|
||||||
return set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
|
{
|
||||||
|
err = set_error (GPG_ERR_ASS_PARAMETER, "invalid hash algorithm");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
algo = 0;
|
algo = 0;
|
||||||
|
|
||||||
|
opt_inquire = has_option (line, "--inquire");
|
||||||
line = skip_options (line);
|
line = skip_options (line);
|
||||||
|
|
||||||
if (!algo)
|
if (!algo && !opt_inquire)
|
||||||
{
|
{
|
||||||
/* No hash option has been given: require an algo number instead */
|
/* No hash option has been given: require an algo number instead */
|
||||||
algo = (int)strtoul (line, &endp, 10);
|
algo = (int)strtoul (line, &endp, 10);
|
||||||
for (line = endp; *line == ' ' || *line == '\t'; line++)
|
for (line = endp; *line == ' ' || *line == '\t'; line++)
|
||||||
;
|
;
|
||||||
if (!algo || gcry_md_test_algo (algo))
|
if (!algo || gcry_md_test_algo (algo))
|
||||||
return set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
|
{
|
||||||
|
err = set_error (GPG_ERR_UNSUPPORTED_ALGORITHM, NULL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
xfree (ctrl->digest.data);
|
||||||
|
ctrl->digest.data = NULL;
|
||||||
ctrl->digest.algo = algo;
|
ctrl->digest.algo = algo;
|
||||||
ctrl->digest.raw_value = 0;
|
ctrl->digest.raw_value = 0;
|
||||||
|
|
||||||
/* Parse the hash value. */
|
if (opt_inquire)
|
||||||
n = 0;
|
{
|
||||||
rc = parse_hexstring (ctx, line, &n);
|
/* We limit the to-be-signed data to some reasonable size which
|
||||||
if (rc)
|
* may eventually allow us to pass that even to smartcards. */
|
||||||
return rc;
|
size_t maxlen = 2048;
|
||||||
n /= 2;
|
|
||||||
if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
|
|
||||||
;
|
|
||||||
else if (n != 16 && n != 20 && n != 24
|
|
||||||
&& n != 28 && n != 32 && n != 48 && n != 64)
|
|
||||||
return set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
|
|
||||||
|
|
||||||
if (n > MAX_DIGEST_LEN)
|
if (algo)
|
||||||
return set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
|
{
|
||||||
|
err = set_error (GPG_ERR_ASS_PARAMETER,
|
||||||
|
"both --inquire and an algo are specified");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
buf = ctrl->digest.value;
|
err = print_assuan_status (ctx, "INQUIRE_MAXLEN", "%zu", maxlen);
|
||||||
ctrl->digest.valuelen = n;
|
if (!err)
|
||||||
for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
|
err = assuan_inquire (ctx, "TBSDATA", &buf, &n, maxlen);
|
||||||
buf[n] = xtoi_2 (p);
|
if (err)
|
||||||
for (; n < ctrl->digest.valuelen; n++)
|
goto leave;
|
||||||
buf[n] = 0;
|
|
||||||
return 0;
|
ctrl->digest.data = buf;
|
||||||
|
ctrl->digest.valuelen = n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Parse the hash value. */
|
||||||
|
n = 0;
|
||||||
|
err = parse_hexstring (ctx, line, &n);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
n /= 2;
|
||||||
|
if (algo == MD_USER_TLS_MD5SHA1 && n == 36)
|
||||||
|
;
|
||||||
|
else if (n != 16 && n != 20 && n != 24
|
||||||
|
&& n != 28 && n != 32 && n != 48 && n != 64)
|
||||||
|
{
|
||||||
|
err = set_error (GPG_ERR_ASS_PARAMETER, "unsupported length of hash");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > MAX_DIGEST_LEN)
|
||||||
|
{
|
||||||
|
err = set_error (GPG_ERR_ASS_PARAMETER, "hash value to long");
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = ctrl->digest.value;
|
||||||
|
ctrl->digest.valuelen = n;
|
||||||
|
for (p=line, n=0; n < ctrl->digest.valuelen; p += 2, n++)
|
||||||
|
buf[n] = xtoi_2 (p);
|
||||||
|
for (; n < ctrl->digest.valuelen; n++)
|
||||||
|
buf[n] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
return leave_cmd (ctx, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3627,6 +3674,7 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
|
|||||||
ctrl->server_local->assuan_ctx = ctx;
|
ctrl->server_local->assuan_ctx = ctx;
|
||||||
ctrl->server_local->use_cache_for_signing = 1;
|
ctrl->server_local->use_cache_for_signing = 1;
|
||||||
|
|
||||||
|
ctrl->digest.data = NULL;
|
||||||
ctrl->digest.raw_value = 0;
|
ctrl->digest.raw_value = 0;
|
||||||
|
|
||||||
assuan_set_io_monitor (ctx, io_monitor, NULL);
|
assuan_set_io_monitor (ctx, io_monitor, NULL);
|
||||||
|
@ -437,7 +437,14 @@ divert_pksign (ctrl_t ctrl, const char *desc_text, const unsigned char *grip,
|
|||||||
/* Note that the KID may be an keyref or a keygrip. The signing
|
/* Note that the KID may be an keyref or a keygrip. The signing
|
||||||
* functions handle both. */
|
* functions handle both. */
|
||||||
|
|
||||||
if (algo == MD_USER_TLS_MD5SHA1)
|
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,
|
||||||
|
0, digest, digestlen, &sigval, &siglen);
|
||||||
|
}
|
||||||
|
else if (algo == MD_USER_TLS_MD5SHA1)
|
||||||
{
|
{
|
||||||
int save = ctrl->use_auth_call;
|
int save = ctrl->use_auth_call;
|
||||||
ctrl->use_auth_call = 1;
|
ctrl->use_auth_call = 1;
|
||||||
|
@ -1937,6 +1937,8 @@ agent_deinit_default_ctrl (ctrl_t ctrl)
|
|||||||
unregister_progress_cb ();
|
unregister_progress_cb ();
|
||||||
session_env_release (ctrl->session_env);
|
session_env_release (ctrl->session_env);
|
||||||
|
|
||||||
|
xfree (ctrl->digest.data);
|
||||||
|
ctrl->digest.data = NULL;
|
||||||
if (ctrl->lc_ctype)
|
if (ctrl->lc_ctype)
|
||||||
xfree (ctrl->lc_ctype);
|
xfree (ctrl->lc_ctype);
|
||||||
if (ctrl->lc_messages)
|
if (ctrl->lc_messages)
|
||||||
|
@ -304,6 +304,11 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
|
|||||||
data = overridedata;
|
data = overridedata;
|
||||||
datalen = overridedatalen;
|
datalen = overridedatalen;
|
||||||
}
|
}
|
||||||
|
else if (ctrl->digest.data)
|
||||||
|
{
|
||||||
|
data = ctrl->digest.data;
|
||||||
|
datalen = ctrl->digest.valuelen;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data = ctrl->digest.value;
|
data = ctrl->digest.value;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user