aboutsummaryrefslogtreecommitdiffstats
path: root/agent
diff options
context:
space:
mode:
Diffstat (limited to 'agent')
-rw-r--r--agent/ChangeLog9
-rw-r--r--agent/agent.h9
-rw-r--r--agent/call-scd.c53
-rw-r--r--agent/divert-scd.c60
-rw-r--r--agent/pkdecrypt.c45
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);