* gpgsm.c (emergency_cleanup): New.

(main): Initialize the signal handler.

* sign.c (gpgsm_sign): Reset the hash context for subsequent
signers and release it at the end.
This commit is contained in:
Werner Koch 2002-08-09 18:12:22 +00:00
parent 1d81b994b8
commit 850a4d5214
8 changed files with 322 additions and 226 deletions

View File

@ -1,3 +1,30 @@
2002-08-09 Werner Koch <wk@gnupg.org>
* gpgsm.c (emergency_cleanup): New.
(main): Initialize the signal handler.
* sign.c (gpgsm_sign): Reset the hash context for subsequent
signers and release it at the end.
2002-08-05 Werner Koch <wk@gnupg.org>
* server.c (cmd_signer): New command "SIGNER"
(register_commands): Register it.
(cmd_sign): Pass the signer list to gpgsm_sign.
* certlist.c (gpgsm_add_to_certlist): Add SECRET argument, check
for secret key if set and changed all callers.
* sign.c (gpgsm_sign): New argument SIGNERLIST and implemt
multiple signers.
* gpgsm.c (main): Support more than one -u.
* server.c (cmd_recipient): Return reason code 1 for No_Public_Key
which is actually what gets returned from add_to_certlist.
2002-07-26 Werner Koch <wk@gnupg.org>
* certcheck.c (gpgsm_check_cert_sig): Implement proper cleanup.
(gpgsm_check_cms_signature): Ditto.
2002-07-22 Werner Koch <wk@gnupg.org>
* keydb.c (keydb_add_resource): Register a lock file.

View File

@ -138,12 +138,16 @@ gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
gcry_md_close (md);
ksba_free (p);
return GNUPG_Bug;
}
rc = gcry_sexp_sscan ( &s_sig, NULL, p, n);
ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
gcry_md_close (md);
return map_gcry_err (rc);
}
@ -152,29 +156,42 @@ gpgsm_check_cert_sig (KsbaCert issuer_cert, KsbaCert cert)
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
gcry_md_close (md);
ksba_free (p);
gcry_sexp_release (s_sig);
return GNUPG_Bug;
}
rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
gcry_md_close (md);
gcry_sexp_release (s_sig);
return map_gcry_err (rc);
}
rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
if (rc)
{
/* fixme: clean up some things */
gcry_md_close (md);
gcry_sexp_release (s_sig);
gcry_sexp_release (s_pkey);
return rc;
}
/* put hash into the S-Exp s_hash */
if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
BUG ();
gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
gcry_md_close (md);
gcry_sexp_release (s_sig);
gcry_sexp_release (s_hash);
gcry_sexp_release (s_pkey);
return map_gcry_err (rc);
}
@ -208,15 +225,19 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
if (!n)
{
log_error ("libksba did not return a proper S-Exp\n");
ksba_free (p);
gcry_sexp_release (s_sig);
return GNUPG_Bug;
}
if (DBG_X509)
log_printhex ("public key: ", p, n);
rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
ksba_free (p);
if (rc)
{
log_error ("gcry_sexp_scan failed: %s\n", gcry_strerror (rc));
gcry_sexp_release (s_sig);
return map_gcry_err (rc);
}
@ -224,17 +245,22 @@ gpgsm_check_cms_signature (KsbaCert cert, KsbaConstSexp sigval,
rc = do_encode_md (md, algo, gcry_pk_get_nbits (s_pkey), &frame);
if (rc)
{
/* fixme: clean up some things */
gcry_sexp_release (s_sig);
gcry_sexp_release (s_pkey);
return rc;
}
/* put hash into the S-Exp s_hash */
if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
BUG ();
gcry_mpi_release (frame);
rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
if (DBG_CRYPTO)
log_debug ("gcry_pk_verify: %s\n", gcry_strerror (rc));
gcry_sexp_release (s_sig);
gcry_sexp_release (s_hash);
gcry_sexp_release (s_sig);
return map_gcry_err (rc);
}

View File

@ -133,10 +133,12 @@ same_subject_issuer (const char *subject, const char *issuer, KsbaCert cert)
/* add a certificate to a list of certificate and make sure that it is
a valid certificate */
/* Add a certificate to a list of certificate and make sure that it is
a valid certificate. With SECRET set to true a secret key must be
avaibale for the certificate. */
int
gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
CERTLIST *listaddr)
{
int rc;
KEYDB_SEARCH_DESC desc;
@ -161,7 +163,8 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
rc = keydb_get_cert (kh, &cert);
if (!rc)
{
rc = gpgsm_cert_use_encrypt_p (cert);
rc = secret? gpgsm_cert_use_sign_p (cert)
: gpgsm_cert_use_encrypt_p (cert);
if (rc == GNUPG_Wrong_Key_Usage)
{
/* There might be another certificate with the
@ -206,7 +209,8 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
if (!keydb_get_cert (kh, &cert2))
{
int tmp = (same_subject_issuer (subject, issuer, cert2)
&& (gpgsm_cert_use_encrypt_p (cert2)
&& ((secret? gpgsm_cert_use_sign_p (cert2):
gpgsm_cert_use_encrypt_p (cert2))
== GNUPG_Wrong_Key_Usage));
ksba_cert_release (cert2);
if (tmp)
@ -218,6 +222,19 @@ gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr)
xfree (subject);
xfree (issuer);
if (!rc && secret)
{
char *p;
rc = GNUPG_No_Secret_Key;
p = gpgsm_get_keygrip_hexstring (cert);
if (p)
{
if (!gpgsm_agent_havekey (p))
rc = 0;
xfree (p);
}
}
if (!rc)
rc = gpgsm_validate_path (ctrl, cert, NULL);
if (!rc)

View File

@ -403,6 +403,7 @@ static char *build_list (const char *text,
static void set_cmd (enum cmd_and_opt_values *ret_cmd,
enum cmd_and_opt_values new_cmd );
static void emergency_cleanup (void);
static int check_special_filename (const char *fname);
static int open_read (const char *filename);
static FILE *open_fwrite (const char *filename);
@ -601,6 +602,7 @@ main ( int argc, char **argv)
enum cmd_and_opt_values cmd = 0;
struct server_control_s ctrl;
CERTLIST recplist = NULL;
CERTLIST signerlist = NULL;
/* trap_unaligned ();*/
set_strusage (my_strusage);
@ -626,7 +628,7 @@ main ( int argc, char **argv)
may_coredump = disable_core_dumps ();
/* Fixme: init_signals();*/
gnupg_init_signals (0, emergency_cleanup);
create_dotlock (NULL); /* register locking cleanup */
i18n_init();
@ -922,9 +924,10 @@ main ( int argc, char **argv)
case oTextmodeShort: /*fixme:opt.textmode = 2;*/ break;
case oTextmode: /*fixme:opt.textmode=1;*/ break;
case oUser: /* store the local users */
opt.local_user = pargs.r.ret_str;
add_to_strlist ( &locusr, pargs.r.ret_str);
case oUser: /* store the local users, the first one is the default */
if (!opt.local_user)
opt.local_user = pargs.r.ret_str;
add_to_strlist (&locusr, pargs.r.ret_str);
break;
case oNoSecmemWarn:
@ -1059,15 +1062,39 @@ main ( int argc, char **argv)
keydb_add_resource (sl->d, 0, 0);
FREE_STRLIST(nrings);
for (sl = locusr; sl; sl = sl->next)
{
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist);
if (rc)
{
log_error (_("can't sign using `%s': %s\n"),
sl->d, gnupg_strerror (rc));
gpgsm_status2 (&ctrl, STATUS_INV_RECP,
rc == -1? "1":
rc == GNUPG_No_Public_Key? "1":
rc == GNUPG_Ambiguous_Name? "2":
rc == GNUPG_Wrong_Key_Usage? "3":
rc == GNUPG_Certificate_Revoked? "4":
rc == GNUPG_Certificate_Expired? "5":
rc == GNUPG_No_CRL_Known? "6":
rc == GNUPG_CRL_Too_Old? "7":
rc == GNUPG_No_Policy_Match? "8":
rc == GNUPG_No_Secret_Key? "9":
"0",
sl->d, NULL);
}
}
for (sl = remusr; sl; sl = sl->next)
{
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, &recplist);
int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 0, &recplist);
if (rc)
{
log_error (_("can't encrypt to `%s': %s\n"),
sl->d, gnupg_strerror (rc));
gpgsm_status2 (&ctrl, STATUS_INV_RECP,
rc == -1? "1":
rc == GNUPG_No_Public_Key? "1":
rc == GNUPG_Ambiguous_Name? "2":
rc == GNUPG_Wrong_Key_Usage? "3":
rc == GNUPG_Certificate_Revoked? "4":
@ -1109,69 +1136,25 @@ main ( int argc, char **argv)
break;
case aSign: /* sign the given file */
/* FIXME: W we don't handle --output yet. We should also allow
/* FIXME: We don't handle --output yet. We should also allow
to concatenate multiple files for signing because that is
what gpg does.*/
if (!argc)
gpgsm_sign (&ctrl, 0, detached_sig, stdout); /* create from stdin */
gpgsm_sign (&ctrl, signerlist,
0, detached_sig, stdout); /* create from stdin */
else if (argc == 1)
gpgsm_sign (&ctrl, open_read (*argv),
detached_sig, stdout); /* from file */
gpgsm_sign (&ctrl, signerlist,
open_read (*argv), detached_sig, stdout); /* from file */
else
wrong_args (_("--sign [datafile]"));
break;
#if 0
sl = NULL;
if (detached_sig)
{ /* sign all files */
for (; argc; argc--, argv++ )
add_to_strlist ( &sl, *argv );
}
else
{
if (argc > 1 )
wrong_args (_("--sign [filename]"));
if (argc)
{
sl = xcalloc (1, sizeof *sl + strlen(fname));
strcpy(sl->d, fname);
}
}
if ( (rc = sign_file( sl, detached_sig, locusr, 0, NULL, NULL)) )
log_error ("signing failed: %s\n", gpg_errstr(rc) );
free_strlist(sl);
#endif
break;
case aSignEncr: /* sign and encrypt the given file */
log_error ("this command has not yet been implemented\n");
#if 0
if (argc > 1)
wrong_args(_("--sign --encrypt [filename]"));
if (argc)
{
sl = xcalloc( 1, sizeof *sl + strlen(fname));
strcpy(sl->d, fname);
}
else
sl = NULL;
if ( (rc = sign_file(sl, detached_sig, locusr, 1, remusr, NULL)) )
log_error ("%s: sign+encrypt failed: %s\n",
print_fname_stdin(fname), gpg_errstr(rc) );
free_strlist(sl);
#endif
break;
case aClearsign: /* make a clearsig */
log_error ("this command has not yet been implemented\n");
#if 0
if (argc > 1)
wrong_args (_("--clearsign [filename]"));
if ( (rc = clearsign_file(fname, locusr, NULL)) )
log_error ("%s: clearsign failed: %s\n",
print_fname_stdin(fname), gpg_errstr(rc) );
#endif
break;
case aVerify:
@ -1199,8 +1182,6 @@ main ( int argc, char **argv)
case aVerifyFiles:
log_error ("this command has not yet been implemented\n");
/* if ((rc = verify_files( argc, argv ))) */
/* log_error ("verify files failed: %s\n", gpg_errstr(rc) ); */
break;
case aDecrypt:
@ -1244,18 +1225,6 @@ main ( int argc, char **argv)
case aKeygen: /* generate a key */
log_error ("this function is not yet available from the commandline\n");
/* if (opt.batch) */
/* { */
/* if (argc > 1) */
/* wrong_args("--gen-key [parameterfile]"); */
/* generate_keypair (argc? *argv : NULL); */
/* } */
/* else */
/* { */
/* if (argc) */
/* wrong_args ("--gen-key"); */
/* generate_keypair(NULL); */
/* } */
break;
case aImport:
@ -1279,16 +1248,6 @@ main ( int argc, char **argv)
case aSendKeys:
case aRecvKeys:
log_error ("this command has not yet been implemented\n");
/* sl = NULL; */
/* for ( ; argc; argc--, argv++ ) */
/* add_to_strlist (&sl, *argv); */
/* if ( cmd == aSendKeys ) */
/* ldap_export (sl); */
/* else if (cmd == aRecvKeys ) */
/* ldap_import (sl); */
/* else */
/* export_pubkeys (sl, (cmd == aExport)); */
/* free_strlist (sl); */
break;
@ -1305,34 +1264,26 @@ main ( int argc, char **argv)
default:
log_error ("invalid command\n");
#if 0
if (argc > 1)
wrong_args(_("[filename]"));
/* Issue some output for the unix newbie */
if ( !fname && !opt.outfile && isatty( fileno(stdin) )
&& isatty (fileno(stdout) ) && isatty (fileno(stderr) ) )
log_info (_("Go ahead and type your message ...\n"));
if ( !(a = iobuf_open(fname)) )
log_error (_("can't open `%s'\n"), print_fname_stdin(fname));
else
{
if (!opt.no_armor)
iobuf_close(a);
}
#endif
log_error ("invalid command (there is no implicit command)\n");
break;
}
/* cleanup */
gpgsm_release_certlist (recplist);
gpgsm_release_certlist (signerlist);
FREE_STRLIST(remusr);
FREE_STRLIST(locusr);
gpgsm_exit(0);
return 8; /*NEVER REACHED*/
}
/* Note: This function is used by signal handlers!. */
static void
emergency_cleanup (void)
{
gcry_control (GCRYCTL_TERM_SECMEM );
}
void
gpgsm_exit (int rc)
@ -1351,7 +1302,7 @@ gpgsm_exit (int rc)
if (opt.debug)
gcry_control (GCRYCTL_DUMP_SECMEM_STATS );
#endif
gcry_control (GCRYCTL_TERM_SECMEM );
emergency_cleanup ();
rc = rc? rc : log_get_errorcount(0)? 2 : gpgsm_errors_seen? 1 : 0;
exit (rc);
}

View File

@ -197,7 +197,8 @@ int gpgsm_cert_use_encrypt_p (KsbaCert cert);
int gpgsm_cert_use_verify_p (KsbaCert cert);
int gpgsm_cert_use_decrypt_p (KsbaCert cert);
int gpgsm_cert_use_cert_p (KsbaCert cert);
int gpgsm_add_to_certlist (CTRL ctrl, const char *name, CERTLIST *listaddr);
int gpgsm_add_to_certlist (CTRL ctrl, const char *name, int secret,
CERTLIST *listaddr);
void gpgsm_release_certlist (CERTLIST list);
int gpgsm_find_cert (const char *name, KsbaCert *r_cert);
@ -218,7 +219,8 @@ int gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp);
/*-- sign.c --*/
int gpgsm_get_default_cert (KsbaCert *r_cert);
int gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp);
int gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
int data_fd, int detached, FILE *out_fp);
/*-- encrypt.c --*/
int gpgsm_encrypt (CTRL ctrl, CERTLIST recplist, int in_fd, FILE *out_fp);

View File

@ -43,6 +43,7 @@ struct server_local_s {
int list_internal;
int list_external;
CERTLIST recplist;
CERTLIST signerlist;
};
@ -182,7 +183,9 @@ reset_notify (ASSUAN_CONTEXT ctx)
CTRL ctrl = assuan_get_pointer (ctx);
gpgsm_release_certlist (ctrl->server_local->recplist);
gpgsm_release_certlist (ctrl->server_local->signerlist);
ctrl->server_local->recplist = NULL;
ctrl->server_local->signerlist = NULL;
close_message_fd (ctrl);
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
@ -239,10 +242,11 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
rc = gpgsm_add_to_certlist (ctrl, line, &ctrl->server_local->recplist);
rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist);
if (rc)
gpgsm_status2 (ctrl, STATUS_INV_RECP,
rc == -1? "1":
rc == GNUPG_No_Public_Key? "1":
rc == GNUPG_Ambiguous_Name? "2":
rc == GNUPG_Wrong_Key_Usage? "3":
rc == GNUPG_Certificate_Revoked? "4":
@ -256,6 +260,47 @@ cmd_recipient (ASSUAN_CONTEXT ctx, char *line)
return map_to_assuan_status (rc);
}
/* SIGNER <userID>
Set the signer's keys for the signature creation. <userID> should
be the internal representation of the key; the server may accept any
other way of specification [we will support this]. If this is a
valid and usable signing key the server does respond with OK,
otherwise it returns an ERR with the reason why the key can't be
used, the signing will then not be done for this key. If the policy
is not to sign at all if not all signer keys are valid, the client
has to take care of this. All SIGNER commands are cumulative until
a RESET but they are *not* reset by an SIGN command becuase it can
be expected that set of signers are used for more than one sign
operation.
Note that this command returns an INV_RECP status which is a bit
strange, but they are very similar. */
static int
cmd_signer (ASSUAN_CONTEXT ctx, char *line)
{
CTRL ctrl = assuan_get_pointer (ctx);
int rc;
rc = gpgsm_add_to_certlist (ctrl, line, 1, &ctrl->server_local->signerlist);
if (rc)
gpgsm_status2 (ctrl, STATUS_INV_RECP,
rc == -1? "1":
rc == GNUPG_No_Public_Key? "1":
rc == GNUPG_Ambiguous_Name? "2":
rc == GNUPG_Wrong_Key_Usage? "3":
rc == GNUPG_Certificate_Revoked? "4":
rc == GNUPG_Certificate_Expired? "5":
rc == GNUPG_No_CRL_Known? "6":
rc == GNUPG_CRL_Too_Old? "7":
rc == GNUPG_No_Policy_Match? "8":
rc == GNUPG_No_Secret_Key? "9":
"0",
line, NULL);
return map_to_assuan_status (rc);
}
/* ENCRYPT
@ -407,7 +452,9 @@ cmd_sign (ASSUAN_CONTEXT ctx, char *line)
out_fp = fdopen ( dup(out_fd), "w");
if (!out_fp)
return set_error (General_Error, "fdopen() failed");
rc = gpgsm_sign (assuan_get_pointer (ctx), inp_fd, detached, out_fp);
rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
inp_fd, detached, out_fp);
fclose (out_fp);
/* close and reset the fd */
@ -676,6 +723,7 @@ register_commands (ASSUAN_CONTEXT ctx)
int (*handler)(ASSUAN_CONTEXT, char *line);
} table[] = {
{ "RECIPIENT", 0, cmd_recipient },
{ "SIGNER", 0, cmd_signer },
{ "ENCRYPT", 0, cmd_encrypt },
{ "DECRYPT", 0, cmd_decrypt },
{ "VERIFY", 0, cmd_verify },
@ -776,6 +824,8 @@ gpgsm_server (void)
gpgsm_release_certlist (ctrl.server_local->recplist);
ctrl.server_local->recplist = NULL;
gpgsm_release_certlist (ctrl.server_local->signerlist);
ctrl.server_local->signerlist = NULL;
assuan_deinit_server (ctx);
}

247
sm/sign.c
View File

@ -1,5 +1,5 @@
/* sign.c - Sign a message
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -228,8 +228,6 @@ get_default_signer (void)
return cert;
}
/* Depending on the options in CTRL add the certificate CERT as well as
other certificate up in the chain to the Root-CA to the CMS
object. */
@ -290,10 +288,11 @@ add_certificate_list (CTRL ctrl, KsbaCMS cms, KsbaCert cert)
Sign the data received on DATA-FD in embedded mode or in detached
mode when DETACHED is true. Write the signature to OUT_FP. The
key used to sign is the default one - we will extend the function
to take a list of fingerprints in the future. */
keys used to sign are taken from SIGNERLIST or the default one will
be used if the value of this argument is NULL. */
int
gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
gpgsm_sign (CTRL ctrl, CERTLIST signerlist,
int data_fd, int detached, FILE *out_fp)
{
int i, rc;
KsbaError err;
@ -301,13 +300,14 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
KsbaWriter writer;
KsbaCMS cms = NULL;
KsbaStopReason stopreason;
KsbaCert cert = NULL;
KEYDB_HANDLE kh = NULL;
GCRY_MD_HD data_md = NULL;
int signer;
const char *algoid;
int algo;
time_t signed_at;
CERTLIST cl;
int release_signerlist = 0;
kh = keydb_new (0);
if (!kh)
@ -353,47 +353,60 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
goto leave;
}
/* gather certificates of signers and store in theCMS object */
/* fixme: process a list of fingerprints and store the certificate of
each given fingerprint */
cert = get_default_signer ();
if (!cert)
/* If no list of signers is given, use a default one. */
if (!signerlist)
{
log_error ("no default signer found\n");
rc = seterr (General_Error);
goto leave;
KsbaCert cert = get_default_signer ();
if (!cert)
{
log_error ("no default signer found\n");
rc = seterr (General_Error);
goto leave;
}
signerlist = xtrycalloc (1, sizeof *signerlist);
if (!signerlist)
{
rc = GNUPG_Out_Of_Core;
ksba_cert_release (cert);
goto leave;
}
signerlist->cert = cert;
release_signerlist = 1;
}
rc = gpgsm_cert_use_sign_p (cert);
if (rc)
goto leave;
err = ksba_cms_add_signer (cms, cert);
if (err)
{
log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
rc = add_certificate_list (ctrl, cms, cert);
if (rc)
{
log_error ("failed to store list of certificates: %s\n",
gnupg_strerror(rc));
goto leave;
}
ksba_cert_release (cert); cert = NULL;
/* Gather certificates of signers and store them in the CMS object. */
for (cl=signerlist; cl; cl = cl->next)
{
rc = gpgsm_cert_use_sign_p (cl->cert);
if (rc)
goto leave;
err = ksba_cms_add_signer (cms, cl->cert);
if (err)
{
log_error ("ksba_cms_add_signer failed: %s\n", ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
rc = add_certificate_list (ctrl, cms, cl->cert);
if (rc)
{
log_error ("failed to store list of certificates: %s\n",
gnupg_strerror(rc));
goto leave;
}
/* Set the hash algorithm we are going to use */
err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
if (err)
{
log_debug ("ksba_cms_add_digest_algo failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
}
/* Set the hash algorithm we are going to use */
err = ksba_cms_add_digest_algo (cms, "1.3.14.3.2.26" /*SHA-1*/);
if (err)
{
log_debug ("ksba_cms_add_digest_algo failed: %s\n", ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
/* Prepare hashing (actually we are figuring out what we have set above)*/
data_md = gcry_md_open (0, 0);
if (!data_md)
@ -417,7 +430,6 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
gcry_md_enable (data_md, algo);
}
signer = 0;
if (detached)
{ /* we hash the data right now so that we can store the message
digest. ksba_cms_build() takes this as an flag that detached
@ -437,24 +449,30 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
rc = GNUPG_Bug;
goto leave;
}
err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
if (err)
for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
log_error ("ksba_cms_set_message_digest failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
if (err)
{
log_error ("ksba_cms_set_message_digest failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
}
}
signed_at = gnupg_get_time ();
err = ksba_cms_set_signing_time (cms, signer, signed_at);
if (err)
for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
log_error ("ksba_cms_set_signing_time failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
err = ksba_cms_set_signing_time (cms, signer, signed_at);
if (err)
{
log_error ("ksba_cms_set_signing_time failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
}
do
@ -473,10 +491,10 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
size_t digest_len;
assert (!detached);
/* Fixme do this for all signers and get the algo to use from
the signer's certificate - does not make mich sense, bu we
should do this consistent as we have already done it above.
Code is mostly duplicated above. */
/* Fixme: get the algo to use from the signer's certificate
- does not make much sense, but we should do this
consistent as we have already done it above. Code is
mostly duplicated above. */
algo = GCRY_MD_SHA1;
rc = hash_and_copy_data (data_fd, data_md, writer);
@ -490,13 +508,17 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
rc = GNUPG_Bug;
goto leave;
}
err = ksba_cms_set_message_digest (cms, signer, digest, digest_len);
if (err)
for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
log_error ("ksba_cms_set_message_digest failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
err = ksba_cms_set_message_digest (cms, signer,
digest, digest_len);
if (err)
{
log_error ("ksba_cms_set_message_digest failed: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
}
}
else if (stopreason == KSBA_SR_NEED_SIG)
@ -504,7 +526,6 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
GCRY_MD_HD md;
algo = GCRY_MD_SHA1;
signer = 0;
md = gcry_md_open (algo, 0);
if (DBG_HASHING)
gcry_md_start_debug (md, "sign.attr");
@ -515,70 +536,67 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
goto leave;
}
ksba_cms_set_hash_function (cms, HASH_FNC, md);
rc = ksba_cms_hash_signed_attrs (cms, signer);
if (rc)
{
log_debug ("hashing signed attrs failed: %s\n",
ksba_strerror (rc));
gcry_md_close (md);
goto leave;
}
{ /* This is all an temporary hack */
char *sigval;
ksba_cert_release (cert);
cert = get_default_signer ();
if (!cert)
{
log_error ("oops - failed to get cert again\n");
rc = seterr (General_Error);
goto leave;
}
sigval = NULL;
rc = gpgsm_create_cms_signature (cert, md, algo, &sigval);
if (rc)
goto leave;
err = ksba_cms_set_sig_val (cms, signer, sigval);
xfree (sigval);
if (err)
{
log_error ("failed to store the signature: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
goto leave;
}
/* And write a status message */
for (cl=signerlist,signer=0; cl; cl = cl->next, signer++)
{
char *sigval = NULL;
char *buf, *fpr;
fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
if (signer)
gcry_md_reset (md);
rc = ksba_cms_hash_signed_attrs (cms, signer);
if (rc)
{
log_debug ("hashing signed attrs failed: %s\n",
ksba_strerror (rc));
gcry_md_close (md);
goto leave;
}
rc = gpgsm_create_cms_signature (cl->cert, md, algo, &sigval);
if (rc)
{
gcry_md_close (md);
goto leave;
}
err = ksba_cms_set_sig_val (cms, signer, sigval);
xfree (sigval);
if (err)
{
log_error ("failed to store the signature: %s\n",
ksba_strerror (err));
rc = map_ksba_err (err);
gcry_md_close (md);
goto leave;
}
/* write a status message */
fpr = gpgsm_get_fingerprint_hexstring (cl->cert, GCRY_MD_SHA1);
if (!fpr)
{
rc = seterr (Out_Of_Core);
gcry_md_close (md);
goto leave;
}
rc = asprintf (&buf, "%c %d %d 00 %lu %s",
detached? 'D':'S',
GCRY_PK_RSA, /* FIXME: get pk algo from cert */
algo,
(ulong)signed_at,
fpr);
detached? 'D':'S',
GCRY_PK_RSA, /* FIXME: get pk algo from cert */
algo,
(ulong)signed_at,
fpr);
xfree (fpr);
if (rc < 0)
{
rc = seterr (Out_Of_Core);
gcry_md_close (md);
goto leave;
}
rc = 0;
gpgsm_status (ctrl, STATUS_SIG_CREATED, buf );
gpgsm_status (ctrl, STATUS_SIG_CREATED, buf);
free (buf); /* yes, we must use the regular free() here */
}
gcry_md_close (md);
}
}
}
while (stopreason != KSBA_SR_READY);
@ -594,7 +612,8 @@ gpgsm_sign (CTRL ctrl, int data_fd, int detached, FILE *out_fp)
leave:
ksba_cert_release (cert);
if (release_signerlist)
gpgsm_release_certlist (signerlist);
ksba_cms_release (cms);
gpgsm_destroy_writer (b64writer);
keydb_release (kh);

View File

@ -1,5 +1,5 @@
/* verify.c - Verify a messages signature
* Copyright (C) 2001 Free Software Foundation, Inc.
* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@ -248,7 +248,7 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
cert = NULL;
err = 0;
for (signer=0; signer < 1; signer++)
for (signer=0; ; signer++)
{
char *issuer = NULL;
KsbaSexp sigval = NULL;
@ -265,7 +265,11 @@ gpgsm_verify (CTRL ctrl, int in_fd, int data_fd, FILE *out_fp)
break;
}
if (err)
break;
{
if (signer && err == -1)
err = 0;
break;
}
if (DBG_X509)
{
log_debug ("signer %d - issuer: `%s'\n",