2004-09-25 Moritz Schulte <moritz@g10code.com>

* agent.h: Declare: agent_pksign_do.
	(struct server_control_s): New member: raw_value.

	* pksign.c (do_encode_md): New argument: raw_value; support
	generation of raw (non-pkcs1) data objects; adjust callers.
	(agent_pksign_do): New function, based on code ripped
	out from agent_pksign.
	(agent_pksign): Use agent_pksign_do.

	* command.c (start_command_handler): Set ctrl.digest.raw_value.
This commit is contained in:
Moritz Schulte 2004-09-26 21:48:13 +00:00
parent f100401478
commit 1db08a412c
4 changed files with 113 additions and 40 deletions

View File

@ -1,3 +1,16 @@
2004-09-25 Moritz Schulte <moritz@g10code.com>
* agent.h: Declare: agent_pksign_do.
(struct server_control_s): New member: raw_value.
* pksign.c (do_encode_md): New argument: raw_value; support
generation of raw (non-pkcs1) data objects; adjust callers.
(agent_pksign_do): New function, based on code ripped
out from agent_pksign.
(agent_pksign): Use agent_pksign_do.
* command.c (start_command_handler): Set ctrl.digest.raw_value.
2004-09-09 Werner Koch <wk@g10code.de> 2004-09-09 Werner Koch <wk@g10code.de>
* gpg-agent.c (check_for_running_agent): New. * gpg-agent.c (check_for_running_agent): New.

View File

@ -95,6 +95,7 @@ struct server_control_s {
int algo; int algo;
unsigned char value[MAX_DIGEST_LEN]; unsigned char value[MAX_DIGEST_LEN];
int valuelen; int valuelen;
int raw_value: 1;
} digest; } digest;
char keygrip[20]; char keygrip[20];
int have_keygrip; int have_keygrip;
@ -159,6 +160,8 @@ void agent_unlock_cache_entry (void **cache_id);
/*-- pksign.c --*/ /*-- pksign.c --*/
int agent_pksign_do (CTRL ctrl, const char *desc_text,
gcry_sexp_t *signature_sexp, int ignore_cache);
int agent_pksign (ctrl_t ctrl, const char *desc_text, int agent_pksign (ctrl_t ctrl, const char *desc_text,
FILE *outfp, int ignore_cache); FILE *outfp, int ignore_cache);

View File

@ -854,6 +854,7 @@ start_command_handler (int listen_fd, int fd)
ctrl.server_local->assuan_ctx = ctx; ctrl.server_local->assuan_ctx = ctx;
ctrl.server_local->message_fd = -1; ctrl.server_local->message_fd = -1;
ctrl.server_local->use_cache_for_signing = 1; ctrl.server_local->use_cache_for_signing = 1;
ctrl.digest.raw_value = 0;
if (DBG_ASSUAN) if (DBG_ASSUAN)
assuan_set_log_stream (ctx, log_get_stream ()); assuan_set_log_stream (ctx, log_get_stream ());

View File

@ -32,41 +32,61 @@
static int static int
do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash) do_encode_md (const byte * md, size_t mdlen, int algo, gcry_sexp_t * r_hash,
int raw_value)
{ {
gcry_sexp_t hash; gcry_sexp_t hash;
const char *s; int rc;
char tmp[16+1];
int i, rc;
s = gcry_md_algo_name (algo); if (! raw_value)
if (s && strlen (s) < 16)
{ {
for (i=0; i < strlen (s); i++) const char *s;
tmp[i] = tolower (s[i]); char tmp[16+1];
tmp[i] = '\0'; int i;
s = gcry_md_algo_name (algo);
if (s && strlen (s) < 16)
{
for (i=0; i < strlen (s); i++)
tmp[i] = tolower (s[i]);
tmp[i] = '\0';
}
rc = gcry_sexp_build (&hash, NULL,
"(data (flags pkcs1) (hash %s %b))",
tmp, mdlen, md);
} }
rc = gcry_sexp_build (&hash, NULL, else
"(data (flags pkcs1) (hash %s %b))", {
tmp, gcry_mpi_t mpi;
mdlen, md);
rc = gcry_mpi_scan (&mpi, GCRYMPI_FMT_USG, md, mdlen, NULL);
if (! rc)
{
rc = gcry_sexp_build (&hash, NULL,
"(data (flags raw) (value %m))",
mpi);
gcry_mpi_release (mpi);
}
}
*r_hash = hash; *r_hash = hash;
return rc; return rc;
} }
/* SIGN whatever information we have accumulated in CTRL and write it /* SIGN whatever information we have accumulated in CTRL and return
back to OUTFP. */ the signature S-Expression. */
int int
agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache) agent_pksign_do (CTRL ctrl, const char *desc_text,
gcry_sexp_t *signature_sexp, int ignore_cache)
{ {
gcry_sexp_t s_skey = NULL, s_hash = NULL, s_sig = NULL; gcry_sexp_t s_skey = NULL, s_sig = NULL;
unsigned char *shadow_info = NULL; unsigned char *shadow_info = NULL;
int rc; unsigned int rc = 0; /* FIXME: gpg-error? */
char *buf = NULL;
size_t len;
if (!ctrl->have_keygrip) if (! ctrl->have_keygrip)
return gpg_error (GPG_ERR_NO_SECKEY); return gpg_error (GPG_ERR_NO_SECKEY);
rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip, rc = agent_key_from_file (ctrl, desc_text, ctrl->keygrip,
@ -77,32 +97,47 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache)
goto leave; goto leave;
} }
if (!s_skey) if (! s_skey)
{ /* divert operation to the smartcard */ {
unsigned char *sigbuf; /* divert operation to the smartcard */
unsigned char *buf = NULL;
size_t len = 0;
rc = divert_pksign (ctrl, rc = divert_pksign (ctrl,
ctrl->digest.value, ctrl->digest.value,
ctrl->digest.valuelen, ctrl->digest.valuelen,
ctrl->digest.algo, ctrl->digest.algo,
shadow_info, &sigbuf); shadow_info, &buf);
if (rc) if (rc)
{ {
log_error ("smartcard signing failed: %s\n", gpg_strerror (rc)); log_error ("smartcard signing failed: %s\n", gpg_strerror (rc));
goto leave; goto leave;
} }
len = gcry_sexp_canon_len (sigbuf, 0, NULL, NULL); len = gcry_sexp_canon_len (buf, 0, NULL, NULL);
assert (len); assert (len);
buf = sigbuf;
rc = gcry_sexp_sscan (&s_sig, NULL, buf, len);
xfree (buf);
if (rc)
{
log_error ("failed to convert sigbuf returned by divert_pksign "
"into S-Exp: %s", gpg_strerror (rc));
goto leave;
}
} }
else else
{ /* no smartcard, but a private key */ {
/* no smartcard, but a private key */
gcry_sexp_t s_hash = NULL;
/* put the hash into a sexp */ /* put the hash into a sexp */
rc = do_encode_md (ctrl->digest.value, rc = do_encode_md (ctrl->digest.value,
ctrl->digest.valuelen, ctrl->digest.valuelen,
ctrl->digest.algo, ctrl->digest.algo,
&s_hash); &s_hash,
ctrl->digest.raw_value);
if (rc) if (rc)
goto leave; goto leave;
@ -114,6 +149,7 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache)
/* sign */ /* sign */
rc = gcry_pk_sign (&s_sig, s_hash, s_skey); rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
gcry_sexp_release (s_hash);
if (rc) if (rc)
{ {
log_error ("signing failed: %s\n", gpg_strerror (rc)); log_error ("signing failed: %s\n", gpg_strerror (rc));
@ -125,26 +161,46 @@ agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache)
log_debug ("result: "); log_debug ("result: ");
gcry_sexp_dump (s_sig); gcry_sexp_dump (s_sig);
} }
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
assert (len);
buf = xmalloc (len);
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
assert (len);
} }
leave:
*signature_sexp = s_sig;
gcry_sexp_release (s_skey);
xfree (shadow_info);
return rc;
}
/* SIGN whatever information we have accumulated in CTRL and write it
back to OUTFP. */
int
agent_pksign (CTRL ctrl, const char *desc_text, FILE *outfp, int ignore_cache)
{
gcry_sexp_t s_sig = NULL;
char *buf = NULL;
size_t len = 0;
int rc = 0;
rc = agent_pksign_do (ctrl, desc_text, &s_sig, ignore_cache);
if (rc)
goto leave;
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
assert (len);
buf = xmalloc (len);
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, buf, len);
assert (len);
/* FIXME: we must make sure that no buffering takes place or we are /* 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 in full control of the buffer memory (easy to do) - should go
into assuan. */ into assuan. */
fwrite (buf, 1, len, outfp); fwrite (buf, 1, len, outfp);
leave: leave:
gcry_sexp_release (s_skey);
gcry_sexp_release (s_hash);
gcry_sexp_release (s_sig); gcry_sexp_release (s_sig);
xfree (buf); xfree (buf);
xfree (shadow_info);
return rc; return rc;
} }