aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2013-02-28 02:17:47 +0000
committerNIIBE Yutaka <[email protected]>2013-02-28 02:17:47 +0000
commitef1983d58b913306e9bf02a7189e530123839c59 (patch)
tree2ab0c7c692bb25c425f6436df13f7fe13126c67f
parentUse has_leading_keyword in the assuan callbacks. (diff)
downloadgnupg-ef1983d58b913306e9bf02a7189e530123839c59.tar.gz
gnupg-ef1983d58b913306e9bf02a7189e530123839c59.zip
agent: pksign result conversion to sexp to upper layer.
* agent/agent.h (divert_pksign): Add R_SIGLEN argument. * agent/divert-scd.c (divert_pksign): Return length at R_SIGLEN. * agent/call-scd.c (agent_card_pksign): Move composition of S-expression to... * agent/pksign.c (agent_pksign_do): ... here. -- Composing S-expression would be better to be done by SCDaemon.
-rw-r--r--agent/agent.h3
-rw-r--r--agent/call-scd.c31
-rw-r--r--agent/divert-scd.c8
-rw-r--r--agent/pksign.c92
4 files changed, 98 insertions, 36 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-scd.c b/agent/call-scd.c
index f4ea20bd3..a334b15a1 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -825,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);
@@ -868,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);
}
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/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)
{