From ef1983d58b913306e9bf02a7189e530123839c59 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 28 Feb 2013 11:17:47 +0900 Subject: [PATCH] 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. --- agent/agent.h | 3 +- agent/call-scd.c | 29 ++------------- agent/divert-scd.c | 8 +++- agent/pksign.c | 92 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 97 insertions(+), 35 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) {