diff options
Diffstat (limited to 'agent')
-rw-r--r-- | agent/ChangeLog | 9 | ||||
-rw-r--r-- | agent/agent.h | 9 | ||||
-rw-r--r-- | agent/call-scd.c | 53 | ||||
-rw-r--r-- | agent/divert-scd.c | 60 | ||||
-rw-r--r-- | agent/pkdecrypt.c | 45 |
5 files changed, 149 insertions, 27 deletions
diff --git a/agent/ChangeLog b/agent/ChangeLog index 94fb00241..bc0ca11ef 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,12 +1,19 @@ +2002-03-06 Werner Koch <[email protected]> + + * pkdecrypt.c (agent_pkdecrypt): Changed the way the diversion is done. + * divert-scd.c (divert_pkdecrypt): Changed interface and + implemented it. + 2002-03-05 Werner Koch <[email protected]> * call-scd.c (inq_needpin): New. (agent_card_pksign): Add getpin_cb args. + (agent_card_pkdecrypt): New. 2002-03-04 Werner Koch <[email protected]> * pksign.c (agent_pksign): Changed how the diversion is done. - * divert-scd.c (divert_pksign): Change interface and implemented it. + * divert-scd.c (divert_pksign): Changed interface and implemented it. (encode_md_for_card): New. * call-scd.c (agent_card_pksign): New. diff --git a/agent/agent.h b/agent/agent.h index 643ed60a1..2d92f94be 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -153,8 +153,8 @@ int agent_marktrusted (const char *name, const char *fpr, int flag); /*-- divert-scd.c --*/ int divert_pksign (const unsigned char *digest, size_t digestlen, int algo, const char *shadow_info, unsigned char **r_sig); -int divert_pkdecrypt (GCRY_SEXP *s_plain, GCRY_SEXP s_cipher, - const char *shadow_info); +int divert_pkdecrypt (const unsigned char *cipher, const char *shadow_info, + char **r_buf, size_t *r_len); /*-- call-scd.c --*/ int agent_card_learn (void); @@ -164,6 +164,11 @@ int agent_card_pksign (const char *keyid, void *getpin_cb_arg, const unsigned char *indata, size_t indatalen, char **r_buf, size_t *r_buflen); +int agent_card_pkdecrypt (const char *keyid, + int (*getpin_cb)(void *, const char *, char*,size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen); #endif /*AGENT_H*/ diff --git a/agent/call-scd.c b/agent/call-scd.c index 6cf53fdfd..dd8853f22 100644 --- a/agent/call-scd.c +++ b/agent/call-scd.c @@ -403,3 +403,56 @@ agent_card_pksign (const char *keyid, return 0; } +/* Decipher INDATA using the current card. Note that the returned value is */ +int +agent_card_pkdecrypt (const char *keyid, + int (*getpin_cb)(void *, const char *, char*, size_t), + void *getpin_cb_arg, + const unsigned char *indata, size_t indatalen, + char **r_buf, size_t *r_buflen) +{ + int rc, i; + char *p, line[ASSUAN_LINELENGTH]; + struct membuf data; + struct inq_needpin_s inqparm; + size_t len; + + *r_buf = NULL; + rc = start_scd (); + if (rc) + return rc; + + /* FIXME: use secure memory where appropriate */ + if (indatalen*2 + 50 > DIM(line)) + return seterr (General_Error); + + sprintf (line, "SETDATA "); + p = line + strlen (line); + for (i=0; i < indatalen ; i++, p += 2 ) + sprintf (p, "%02X", indata[i]); + rc = assuan_transact (scd_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL); + if (rc) + return map_assuan_err (rc); + + init_membuf (&data, 1024); + inqparm.ctx = scd_ctx; + inqparm.getpin_cb = getpin_cb; + inqparm.getpin_cb_arg = getpin_cb_arg; + snprintf (line, DIM(line)-1, "PKDECRYPT %s", keyid); + line[DIM(line)-1] = 0; + rc = assuan_transact (scd_ctx, line, + membuf_data_cb, &data, + inq_needpin, &inqparm, + NULL, NULL); + if (rc) + { + xfree (get_membuf (&data, &len)); + return map_assuan_err (rc); + } + *r_buf = get_membuf (&data, r_buflen); + if (!*r_buf) + return GNUPG_Out_Of_Core; + + return 0; +} + diff --git a/agent/divert-scd.c b/agent/divert-scd.c index d938d2618..33fd5ce26 100644 --- a/agent/divert-scd.c +++ b/agent/divert-scd.c @@ -258,21 +258,65 @@ divert_pksign (const unsigned char *digest, size_t digestlen, int algo, } -int -divert_pkdecrypt (GCRY_SEXP *s_plain, GCRY_SEXP s_cipher, - const char *shadow_info) +/* Decrypt the the value given asn an S-expression in CIPHER using the + key identified by SHADOW_INFO and return the plaintext in an + allocated buffer in R_BUF. */ +int +divert_pkdecrypt (const unsigned char *cipher, const char *shadow_info, + char **r_buf, size_t *r_len) { int rc; char *kid; + const unsigned char *s; + size_t n; + const unsigned char *ciphertext; + size_t ciphertextlen; + char *plaintext; + size_t plaintextlen; + + s = cipher; + if (*s != '(') + return GNUPG_Invalid_Sexp; + s++; + n = snext (&s); + if (!n) + return GNUPG_Invalid_Sexp; + if (!smatch (&s, n, "enc-val")) + return GNUPG_Unknown_Sexp; + if (*s != '(') + return GNUPG_Unknown_Sexp; + s++; + n = snext (&s); + if (!n) + return GNUPG_Invalid_Sexp; + if (!smatch (&s, n, "rsa")) + return GNUPG_Unsupported_Algorithm; + if (*s != '(') + return GNUPG_Unknown_Sexp; + s++; + n = snext (&s); + if (!n) + return GNUPG_Invalid_Sexp; + if (!smatch (&s, n, "a")) + return GNUPG_Unknown_Sexp; + n = snext (&s); + if (!n) + return GNUPG_Unknown_Sexp; + ciphertext = s; + ciphertextlen = n; rc = ask_for_card (shadow_info, &kid); if (rc) return rc; - + rc = agent_card_pkdecrypt (kid, getpin_cb, NULL, + ciphertext, ciphertextlen, + &plaintext, &plaintextlen); + if (!rc) + { + *r_buf = plaintext; + *r_len = plaintextlen; + } xfree (kid); - return GNUPG_Not_Implemented; + return rc; } - - - diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c index 33663a9f7..9a32e76d7 100644 --- a/agent/pkdecrypt.c +++ b/agent/pkdecrypt.c @@ -71,14 +71,27 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, rc = seterr (No_Secret_Key); goto leave; } + if (!s_skey) { /* divert operation to the smartcard */ - rc = divert_pkdecrypt (&s_plain, s_cipher, shadow_info); + + if (!gcry_sexp_canon_len (ciphertext, ciphertextlen, NULL, NULL)) + { + rc = GNUPG_Invalid_Sexp; + goto leave; + } + + rc = divert_pkdecrypt (ciphertext, shadow_info, &buf, &len ); if (rc) { log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc)); goto leave; } + /* FIXME: don't use buffering and change the protocol to return + a complete S-expression and not just a part. */ + fprintf (outfp, "%u:", (unsigned int)len); + fwrite (buf, 1, len, outfp); + putc (0, outfp); } else { /* no smartcard, but a private key */ @@ -95,23 +108,23 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen, rc = map_gcry_err (rc); goto leave; } + + if (DBG_CRYPTO) + { + log_debug ("plain: "); + gcry_sexp_dump (s_plain); + } + len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0); + assert (len); + buf = xmalloc (len); + len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len); + assert (len); + /* FIXME: we must make sure that no buffering takes place or we are + in full control of the buffer memory (easy to do) - should go + into assuan. */ + fwrite (buf, 1, len, outfp); } - if (DBG_CRYPTO) - { - log_debug ("plain: "); - gcry_sexp_dump (s_plain); - } - len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, NULL, 0); - assert (len); - buf = xmalloc (len); - len = gcry_sexp_sprint (s_plain, GCRYSEXP_FMT_CANON, buf, len); - assert (len); - - /* FIXME: we must make sure that no buffering takes place or we are - in full control of the buffer memory (easy to do) - should go - into assuan. */ - fwrite (buf, 1, len, outfp); leave: gcry_sexp_release (s_skey); |