aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to 'agent')
-rw-r--r--agent/agent.h3
-rw-r--r--agent/call-pinentry.c9
-rw-r--r--agent/call-scd.c53
-rw-r--r--agent/command-ssh.c2
-rw-r--r--agent/command.c1
-rw-r--r--agent/divert-scd.c8
-rw-r--r--agent/findkey.c2
-rw-r--r--agent/pksign.c92
8 files changed, 112 insertions, 58 deletions
diff --git a/agent/agent.h b/agent/agent.h
index 030b29520..2fd0b8b8a 100644
--- a/agent/agent.h
+++ b/agent/agent.h
@@ -405,7 +405,8 @@ void agent_reload_trustlist (void);
/*-- divert-scd.c --*/
int divert_pksign (ctrl_t ctrl,
const unsigned char *digest, size_t digestlen, int algo,
- const unsigned char *shadow_info, unsigned char **r_sig);
+ const unsigned char *shadow_info, unsigned char **r_sig,
+ size_t *r_siglen);
int divert_pkdecrypt (ctrl_t ctrl,
const unsigned char *cipher,
const unsigned char *shadow_info,
diff --git a/agent/call-pinentry.c b/agent/call-pinentry.c
index c6b6b5282..78e1c1106 100644
--- a/agent/call-pinentry.c
+++ b/agent/call-pinentry.c
@@ -596,18 +596,15 @@ static gpg_error_t
inq_quality (void *opaque, const char *line)
{
assuan_context_t ctx = opaque;
+ const char *s;
char *pin;
int rc;
int percent;
char numbuf[20];
- if (!strncmp (line, "QUALITY", 7) && (line[7] == ' ' || !line[7]))
+ if ((s = has_leading_keyword (line, "QUALITY")))
{
- line += 7;
- while (*line == ' ')
- line++;
-
- pin = unescape_passphrase_string (line);
+ pin = unescape_passphrase_string (s);
if (!pin)
rc = gpg_error_from_syserror ();
else
diff --git a/agent/call-scd.c b/agent/call-scd.c
index cbe4d1c34..a334b15a1 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -701,17 +701,15 @@ static gpg_error_t
inq_needpin (void *opaque, const char *line)
{
struct inq_needpin_s *parm = opaque;
+ const char *s;
char *pin;
size_t pinlen;
int rc;
parm->any_inq_seen = 1;
- if (!strncmp (line, "NEEDPIN", 7) && (line[7] == ' ' || !line[7]))
+ if ((s = has_leading_keyword (line, "NEEDPIN")))
{
- line += 7;
- while (*line == ' ')
- line++;
-
+ line = s;
pinlen = 90;
pin = gcry_malloc_secure (pinlen);
if (!pin)
@@ -722,17 +720,11 @@ inq_needpin (void *opaque, const char *line)
rc = assuan_send_data (parm->ctx, pin, pinlen);
xfree (pin);
}
- else if (!strncmp (line, "POPUPPINPADPROMPT", 17)
- && (line[17] == ' ' || !line[17]))
+ else if ((s = has_leading_keyword (line, "POPUPPINPADPROMPT")))
{
- line += 17;
- while (*line == ' ')
- line++;
-
- rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1);
+ rc = parm->getpin_cb (parm->getpin_cb_arg, s, NULL, 1);
}
- else if (!strncmp (line, "DISMISSPINPADPROMPT", 19)
- && (line[19] == ' ' || !line[19]))
+ else if ((s = has_leading_keyword (line, "DISMISSPINPADPROMPT")))
{
rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
}
@@ -833,10 +825,6 @@ agent_card_pksign (ctrl_t ctrl,
char *p, line[ASSUAN_LINELENGTH];
membuf_t data;
struct inq_needpin_s inqparm;
- size_t len;
- unsigned char *sigbuf;
- size_t sigbuflen;
- int prepend_nul;
*r_buf = NULL;
rc = start_scd (ctrl);
@@ -876,32 +864,13 @@ agent_card_pksign (ctrl_t ctrl,
if (rc)
{
+ size_t len;
+
xfree (get_membuf (&data, &len));
return unlock_scd (ctrl, rc);
}
- sigbuf = get_membuf (&data, &sigbuflen);
-
- /* Create an S-expression from it which is formatted like this:
- "(7:sig-val(3:rsa(1:sSIGBUFLEN:SIGBUF)))". We better make sure
- that this won't be interpreted as a negative number. */
- prepend_nul = (sigbuflen && (*sigbuf & 0x80));
-
- *r_buflen = 21 + 11 + prepend_nul + sigbuflen + 4;
- p = xtrymalloc (*r_buflen);
- *r_buf = (unsigned char*)p;
- if (!p)
- return unlock_scd (ctrl, out_of_core ());
- p = stpcpy (p, "(7:sig-val(3:rsa(1:s" );
- sprintf (p, "%u:", (unsigned int)sigbuflen + prepend_nul);
- p += strlen (p);
- if (prepend_nul)
- *p++ = 0;
- memcpy (p, sigbuf, sigbuflen);
- p += sigbuflen;
- strcpy (p, ")))");
- xfree (sigbuf);
-
- assert (gcry_sexp_canon_len (*r_buf, *r_buflen, NULL, NULL));
+
+ *r_buf = get_membuf (&data, r_buflen);
return unlock_scd (ctrl, 0);
}
@@ -1069,7 +1038,7 @@ inq_writekey_parms (void *opaque, const char *line)
{
struct writekey_parm_s *parm = opaque;
- if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
+ if (has_leading_keyword (line, "KEYDATA"))
return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
else
return inq_needpin (opaque, line);
diff --git a/agent/command-ssh.c b/agent/command-ssh.c
index c0b608a4a..94538b3d8 100644
--- a/agent/command-ssh.c
+++ b/agent/command-ssh.c
@@ -1247,6 +1247,8 @@ ssh_signature_encoder_ecdsa (ssh_key_type_spec_t *spec,
gpg_error_t err;
int i;
+ (void)spec;
+
innerlen = 0;
for (i = 0; i < DIM(data); i++)
{
diff --git a/agent/command.c b/agent/command.c
index 2844398f6..823b233bf 100644
--- a/agent/command.c
+++ b/agent/command.c
@@ -2197,6 +2197,7 @@ cmd_keytocard (assuan_context_t ctx, char *line)
gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
gcry_sexp_release (s_skey);
+ keydatalen--; /* Decrement for last '\0'. */
/* Add timestamp "created-at" in the private key */
timestamp = isotime2epoch (timestamp_str);
snprintf (keydata+keydatalen-1, 30, "(10:created-at10:%010lu))", timestamp);
diff --git a/agent/divert-scd.c b/agent/divert-scd.c
index 5fb037ee5..f0d847389 100644
--- a/agent/divert-scd.c
+++ b/agent/divert-scd.c
@@ -335,7 +335,8 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
int
divert_pksign (ctrl_t ctrl,
const unsigned char *digest, size_t digestlen, int algo,
- const unsigned char *shadow_info, unsigned char **r_sig)
+ const unsigned char *shadow_info, unsigned char **r_sig,
+ size_t *r_siglen)
{
int rc;
char *kid;
@@ -369,7 +370,10 @@ divert_pksign (ctrl_t ctrl,
}
if (!rc)
- *r_sig = sigval;
+ {
+ *r_sig = sigval;
+ *r_siglen = siglen;
+ }
xfree (kid);
diff --git a/agent/findkey.c b/agent/findkey.c
index b17870ef7..ebdcc038e 100644
--- a/agent/findkey.c
+++ b/agent/findkey.c
@@ -828,7 +828,7 @@ agent_public_key_from_file (ctrl_t ctrl,
int i, idx;
gcry_sexp_t s_skey;
char algoname[6];
- char elems[6];
+ char elems[7];
gcry_sexp_t uri_sexp, comment_sexp;
const char *uri, *comment;
size_t uri_length, comment_length;
diff --git a/agent/pksign.c b/agent/pksign.c
index dc44b881d..85187305c 100644
--- a/agent/pksign.c
+++ b/agent/pksign.c
@@ -278,24 +278,104 @@ agent_pksign_do (ctrl_t ctrl, const char *cache_nonce,
if (!s_skey)
{
/* Divert operation to the smartcard */
-
+ gcry_sexp_t s_pkey, l;
+ const char *name;
+ size_t len;
unsigned char *buf = NULL;
- size_t len = 0;
+ int is_RSA = 0;
+ int is_ECDSA = 0;
+
+ /* Check keytype by public key */
+ rc = agent_public_key_from_file (ctrl, ctrl->keygrip, &s_pkey);
+ if (rc)
+ {
+ log_error ("failed to read the public key\n");
+ goto leave;
+ }
+ l = gcry_sexp_cadr (s_pkey);
+ name = gcry_sexp_nth_data (l, 0, &len);
+ if (len == 3 && !memcmp (name, "rsa", 3))
+ is_RSA = 1;
+ else if (len == 5 && !memcmp (name, "ecdsa", 5))
+ is_ECDSA = 1;
+ gcry_sexp_release (l);
+ gcry_sexp_release (s_pkey);
rc = divert_pksign (ctrl,
ctrl->digest.value,
ctrl->digest.valuelen,
ctrl->digest.algo,
- shadow_info, &buf);
+ shadow_info, &buf, &len);
if (rc)
{
log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
goto leave;
}
- len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
- assert (len);
- rc = gcry_sexp_sscan (&s_sig, NULL, (char*)buf, len);
+ if (is_RSA)
+ {
+ if (*buf & 0x80)
+ {
+ len++;
+ buf = xtryrealloc (buf, len);
+ if (!buf)
+ goto leave;
+
+ memmove (buf + 1, buf, len - 1);
+ *buf = 0;
+ }
+
+ rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%b)))", len, buf);
+ }
+ else if (is_ECDSA)
+ {
+ unsigned char *r_buf_allocated = NULL;
+ unsigned char *s_buf_allocated = NULL;
+ unsigned char *r_buf, *s_buf;
+ int r_buflen, s_buflen;
+
+ r_buflen = s_buflen = len/2;
+
+ if (*buf & 0x80)
+ {
+ r_buflen++;
+ r_buf_allocated = xtrymalloc (r_buflen);
+ if (!r_buf_allocated)
+ goto leave;
+
+ r_buf = r_buf_allocated;
+ memcpy (r_buf + 1, buf, len/2);
+ *r_buf = 0;
+ }
+ else
+ r_buf = buf;
+
+ if (*(buf + len/2) & 0x80)
+ {
+ s_buflen++;
+ s_buf_allocated = xtrymalloc (s_buflen);
+ if (!s_buf_allocated)
+ {
+ 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;
+
+ rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%b)(s%b)))",
+ r_buflen, r_buf,
+ s_buflen, s_buf);
+ xfree (r_buf_allocated);
+ xfree (s_buf_allocated);
+ }
+ else
+ rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
xfree (buf);
if (rc)
{