1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-04-17 15:44:34 +02:00

agent: PKSIGN should return signature in same format for card.

* agent/pksign.c (agent_pksign_do):

--

It's best to keep same data format by libgcrypt.

For card (due to historical reasons), gpg-agent or scdaemon used to
prefix 0x00 when it starts 0x80, so that it can be parsed signed MPI
as well as unsigned MPI.  It used to do nothing for preceding zeros.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2019-02-27 10:37:26 +09:00
parent c2235d994d
commit 0173b249cf

View File

@ -367,20 +367,29 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
if (is_RSA) if (is_RSA)
{ {
check_signature = 1; unsigned char *p = buf;
if (*buf & 0x80)
{
len++;
buf = xtryrealloc (buf, len);
if (!buf)
goto leave;
memmove (buf + 1, buf, len - 1); check_signature = 1;
*buf = 0;
/*
* Smartcard returns fixed-size data, which is good for
* PKCS1. If variable-size unsigned MPI is needed, remove
* zeros.
*/
if (ctrl->digest.algo == MD_USER_TLS_MD5SHA1
|| ctrl->digest.raw_value)
{
int i;
for (i = 0; i < len - 1; i++)
if (p[i])
break;
p += i;
len -= i;
} }
err = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%b)))", err = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%b)))",
(int)len, buf); (int)len, p);
} }
else if (is_EdDSA) else if (is_EdDSA)
{ {
@ -389,53 +398,34 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
} }
else if (is_ECDSA) else if (is_ECDSA)
{ {
unsigned char *r_buf_allocated = NULL;
unsigned char *s_buf_allocated = NULL;
unsigned char *r_buf, *s_buf; unsigned char *r_buf, *s_buf;
int r_buflen, s_buflen; int r_buflen, s_buflen;
int i;
r_buflen = s_buflen = len/2; r_buflen = s_buflen = len/2;
if (*buf & 0x80) /*
{ * Smartcard returns fixed-size data. For ECDSA signature,
r_buflen++; * variable-size unsigned MPI is assumed, thus, remove
r_buf_allocated = xtrymalloc (r_buflen); * zeros.
if (!r_buf_allocated) */
{ r_buf = buf;
err = gpg_error_from_syserror (); for (i = 0; i < r_buflen - 1; i++)
goto leave; if (r_buf[i])
} break;
r_buf += i;
r_buflen -= i;
r_buf = r_buf_allocated; s_buf = buf + len/2;
memcpy (r_buf + 1, buf, len/2); for (i = 0; i < s_buflen - 1; i++)
*r_buf = 0; if (s_buf[i])
} break;
else s_buf += i;
r_buf = buf; s_buflen -= i;
if (*(buf + len/2) & 0x80)
{
s_buflen++;
s_buf_allocated = xtrymalloc (s_buflen);
if (!s_buf_allocated)
{
err = gpg_error_from_syserror ();
xfree (r_buf_allocated);
goto leave;
}
s_buf = s_buf_allocated;
memcpy (s_buf + 1, buf + len/2, len/2);
*s_buf = 0;
}
else
s_buf = buf + len/2;
err = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))", err = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))",
r_buflen, r_buf, r_buflen, r_buf,
s_buflen, s_buf); s_buflen, s_buf);
xfree (r_buf_allocated);
xfree (s_buf_allocated);
} }
else else
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);