Support DSA2.

Support Camellia for testing.
More audit stuff.
This commit is contained in:
Werner Koch 2007-12-12 10:28:30 +00:00
parent c8b76e5621
commit bae4b256c7
34 changed files with 682 additions and 174 deletions

View File

@ -1,3 +1,7 @@
2007-12-12 Werner Koch <wk@g10code.com>
* configure.ac (USE_CAMELLIA): Define by new option --enable-camellia.
2007-12-03 Werner Koch <wk@g10code.com> 2007-12-03 Werner Koch <wk@g10code.com>
* configure.ac: Add test gt_LC_MESSAGES.. * configure.ac: Add test gt_LC_MESSAGES..

8
NEWS
View File

@ -14,6 +14,14 @@ Noteworthy changes in version 2.0.8
* The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the * The envvars XAUTHORITY and PINENTRY_USER_DATA are now passed to the
pinentry. pinentry.
* Allow encryption using Elgamal keys with the algorithm id 20.
* Fixed the auto creation of the key stub for smartcards.
* Fixed a rare bug in decryption using the OpenPGP card.
* Creating DSA2 keys is now possible.
Noteworthy changes in version 2.0.7 (2007-09-10) Noteworthy changes in version 2.0.7 (2007-09-10)
------------------------------------------------ ------------------------------------------------

2
TODO
View File

@ -91,7 +91,7 @@
** issue a NO_SECKEY xxxx if a -u key was not found. ** issue a NO_SECKEY xxxx if a -u key was not found.
* When switching to libgcrypt 1.3 * When switching to libgcrypt 1.4
** scd#encode_md_for_card, g10#encode_md_value, sm@do_encode_md ** scd#encode_md_for_card, g10#encode_md_value, sm@do_encode_md
Remove the extra test for a valid algorithm as libgcrypt will do it Remove the extra test for a valid algorithm as libgcrypt will do it
then in gcry_md_algo_info. then in gcry_md_algo_info.

View File

@ -1,3 +1,9 @@
2007-12-11 Werner Koch <wk@g10code.com>
* asshelp.c (send_pinentry_environment): Allow using of old
gpg-agents not capabale of the xauthority and pinentry_user_data
options.
2007-12-04 Werner Koch <wk@g10code.com> 2007-12-04 Werner Koch <wk@g10code.com>
* Makefile.am (t_helpfile_LDADD, module_maint_tests): New. * Makefile.am (t_helpfile_LDADD, module_maint_tests): New.

View File

@ -172,6 +172,8 @@ send_pinentry_environment (assuan_context_t ctx,
{ {
err = send_one_option (ctx, errsource, "xauthority", err = send_one_option (ctx, errsource, "xauthority",
opt_xauthority ? opt_xauthority : dft_xauthority); opt_xauthority ? opt_xauthority : dft_xauthority);
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
err = 0;
if (err) if (err)
return err; return err;
} }
@ -183,6 +185,8 @@ send_pinentry_environment (assuan_context_t ctx,
err = send_one_option (ctx, errsource, "pinentry-user-data", err = send_one_option (ctx, errsource, "pinentry-user-data",
opt_pinentry_user_data ? opt_pinentry_user_data ?
opt_pinentry_user_data : dft_pinentry_user_data); opt_pinentry_user_data : dft_pinentry_user_data);
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
err = 0;
if (err) if (err)
return err; return err;
} }

View File

@ -449,9 +449,9 @@ writeout_li (audit_ctx_t ctx, const char *oktext, const char *format, ...)
if (ctx->use_html && format && oktext) if (ctx->use_html && format && oktext)
{ {
if (!strcmp (oktext, "OK") || !strcmp (oktext, "Yes")) if (!strcmp (oktext, "Yes"))
color = "green"; color = "green";
else if (!strcmp (oktext, "FAIL") || !strcmp (oktext, "No")) else if (!strcmp (oktext, "No"))
color = "red"; color = "red";
} }
@ -648,42 +648,20 @@ get_cert_subject (ksba_cert_t cert, int idx)
} }
/* List the chain of certificates from STARTITEM up to STOPEVENT. The /* List the given certificiate. If CERT is NULL, this is a NOP. */
certifcates are written out as comments. */
static void static void
list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent) list_cert (audit_ctx_t ctx, ksba_cert_t cert, int with_subj)
{ {
log_item_t item;
char *name; char *name;
int idx; int idx;
startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent); name = get_cert_name (cert);
if (!startitem) writeout_rem (ctx, "%s", name);
xfree (name);
if (with_subj)
{ {
writeout_li (ctx, gpg_strerror (GPG_ERR_MISSING_CERT)
, _("Certificate chain"));
return;
}
writeout_li (ctx, "OK", _("Certificate chain"));
item = find_next_log_item (ctx, startitem,
AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
if (!item)
writeout_rem (ctx, "%s", _("root certificate missing"));
else
{
name = get_cert_name (item->cert);
writeout_rem (ctx, "%s", name);
xfree (name);
}
item = startitem;
while ( ((item = find_next_log_item (ctx, item,
AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
{
name = get_cert_name (item->cert);
writeout_rem (ctx, "%s", name);
xfree (name);
enter_li (ctx); enter_li (ctx);
for (idx=0; (name = get_cert_subject (item->cert, idx)); idx++) for (idx=0; (name = get_cert_subject (cert, idx)); idx++)
{ {
writeout_rem (ctx, "%s", name); writeout_rem (ctx, "%s", name);
xfree (name); xfree (name);
@ -693,8 +671,142 @@ list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
} }
/* List the chain of certificates from STARTITEM up to STOPEVENT. The
certifcates are written out as comments. */
static void
list_certchain (audit_ctx_t ctx, log_item_t startitem, audit_event_t stopevent)
{
log_item_t item;
startitem = find_next_log_item (ctx, startitem, AUDIT_CHAIN_BEGIN,stopevent);
writeout_li (ctx, startitem? "Yes":"No", _("Certificate chain available"));
if (!startitem)
return;
item = find_next_log_item (ctx, startitem,
AUDIT_CHAIN_ROOTCERT, AUDIT_CHAIN_END);
if (!item)
writeout_rem (ctx, "%s", _("root certificate missing"));
else
{
list_cert (ctx, item->cert, 0);
}
item = startitem;
while ( ((item = find_next_log_item (ctx, item,
AUDIT_CHAIN_CERT, AUDIT_CHAIN_END))))
{
list_cert (ctx, item->cert, 1);
}
}
/* Process a verification operation. */ /* Process an encrypt operation's log. */
static void
proc_type_encrypt (audit_ctx_t ctx)
{
log_item_t loopitem, item;
int recp_no, idx;
char numbuf[35];
int algo;
char *name;
item = find_log_item (ctx, AUDIT_ENCRYPTION_DONE, 0);
writeout_li (ctx, item?"Yes":"No", "%s", _("Data encryption succeeded"));
enter_li (ctx);
item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
item = find_log_item (ctx, AUDIT_SESSION_KEY, 0);
writeout_li (ctx, item? "Yes":"No", "%s", _("Session key created"));
if (item)
{
algo = gcry_cipher_map_name (item->string);
if (algo)
writeout_rem (ctx, _("algorithm: %s"), gcry_cipher_algo_name (algo));
else if (item->string && !strcmp (item->string, "1.2.840.113549.3.2"))
writeout_rem (ctx, _("unsupported algorithm: %s"), "RC2");
else if (item->string)
writeout_rem (ctx, _("unsupported algorithm: %s"), item->string);
else
writeout_rem (ctx, _("seems to be not encrypted"));
}
item = find_log_item (ctx, AUDIT_GOT_RECIPIENTS, 0);
snprintf (numbuf, sizeof numbuf, "%d",
item && item->have_intvalue? item->intvalue : 0);
writeout_li (ctx, numbuf, "%s", _("Number of recipients"));
/* Loop over all recipients. */
loopitem = NULL;
recp_no = 0;
while ((loopitem=find_next_log_item (ctx, loopitem, AUDIT_ENCRYPTED_TO, 0)))
{
recp_no++;
writeout_li (ctx, NULL, _("Recipient %d"), recp_no);
if (loopitem->cert)
{
name = get_cert_name (loopitem->cert);
writeout_rem (ctx, "%s", name);
xfree (name);
enter_li (ctx);
for (idx=0; (name = get_cert_subject (loopitem->cert, idx)); idx++)
{
writeout_rem (ctx, "%s", name);
xfree (name);
}
leave_li (ctx);
}
}
leave_li (ctx);
}
/* Process a sign operation's log. */
static void
proc_type_sign (audit_ctx_t ctx)
{
log_item_t item;
item = NULL;
writeout_li (ctx, item?"Yes":"No", "%s", _("Data signing succeeded"));
enter_li (ctx);
item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
leave_li (ctx);
}
/* Process a decrypt operation's log. */
static void
proc_type_decrypt (audit_ctx_t ctx)
{
log_item_t item;
item = NULL;
writeout_li (ctx, item?"Yes":"No", "%s", _("Data decryption succeeded"));
enter_li (ctx);
item = find_log_item (ctx, AUDIT_GOT_DATA, 0);
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
leave_li (ctx);
}
/* Process a verification operation's log. */
static void static void
proc_type_verify (audit_ctx_t ctx) proc_type_verify (audit_ctx_t ctx)
{ {
@ -702,13 +814,12 @@ proc_type_verify (audit_ctx_t ctx)
int signo, count, idx; int signo, count, idx;
char numbuf[35]; char numbuf[35];
/* If there is at least one signature status we claim that the
verifciation succeeded. This does not mean that the data has
verified okay. */
item = find_log_item (ctx, AUDIT_SIG_STATUS, 0);
writeout_li (ctx, item?"Yes":"No", "%s", _("Data verification succeeded"));
enter_li (ctx); enter_li (ctx);
writeout_li (ctx, "fixme", "%s", _("Signature verification"));
enter_li (ctx);
writeout_li (ctx, "fixme", "%s", _("Gpg-Agent ready"));
writeout_li (ctx, "fixme", "%s", _("Dirmngr ready"));
item = find_log_item (ctx, AUDIT_GOT_DATA, AUDIT_NEW_SIG); item = find_log_item (ctx, AUDIT_GOT_DATA, AUDIT_NEW_SIG);
writeout_li (ctx, item? "Yes":"No", "%s", _("Data available")); writeout_li (ctx, item? "Yes":"No", "%s", _("Data available"));
@ -721,19 +832,14 @@ proc_type_verify (audit_ctx_t ctx)
goto leave; goto leave;
item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG); item = find_log_item (ctx, AUDIT_DATA_HASH_ALGO, AUDIT_NEW_SIG);
if (item) writeout_li (ctx, item?"Yes":"No", "%s", _("Parsing signature succeeded"));
writeout_li (ctx, "OK", "%s", _("Parsing signature")); if (!item)
else
{ {
item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG); item = find_log_item (ctx, AUDIT_BAD_DATA_HASH_ALGO, AUDIT_NEW_SIG);
if (item) if (item)
{ writeout_rem (ctx, _("Bad hash algorithm: %s"),
writeout_li (ctx,"FAIL", "%s", _("Parsing signature")); item->string? item->string:"?");
writeout_rem (ctx, _("Bad hash algorithm: %s"),
item->string? item->string:"?");
}
else
writeout_li (ctx, "FAIL", "%s", _("Parsing signature") );
goto leave; goto leave;
} }
@ -761,19 +867,30 @@ proc_type_verify (audit_ctx_t ctx)
AUDIT_CHAIN_STATUS, AUDIT_NEW_SIG); AUDIT_CHAIN_STATUS, AUDIT_NEW_SIG);
if (item && item->have_err) if (item && item->have_err)
{ {
writeout_li (ctx, item->err? "FAIL":"OK", writeout_li (ctx, item->err? "No":"Yes",
_("Validation of certificate chain")); _("Certificate chain valid"));
if (item->err) if (item->err)
writeout_rem (ctx, "%s", gpg_strerror (item->err)); writeout_rem (ctx, "%s", gpg_strerror (item->err));
} }
/* Show whether the root certificate is fine. */ /* Show whether the root certificate is fine. */
writeout_li (ctx, "No", "%s", _("Root certificate trustworthy")); item = find_next_log_item (ctx, loopitem,
add_helptag (ctx, "gpgsm.root-cert-not-trusted"); AUDIT_ROOT_TRUSTED, AUDIT_CHAIN_STATUS);
if (item)
{
writeout_li (ctx, item->err?"No":"Yes", "%s",
_("Root certificate trustworthy"));
if (item->err)
{
add_helptag (ctx, "gpgsm.root-cert-not-trusted");
writeout_rem (ctx, "%s", gpg_strerror (item->err));
list_cert (ctx, item->cert, 0);
}
}
/* Show result of the CRL/OCSP check. */ /* Show result of the CRL/OCSP check. */
writeout_li (ctx, "-", "%s", _("CRL/OCSP check of certificates")); writeout_li (ctx, "-", "%s", _("CRL/OCSP check of certificates"));
add_helptag (ctx, "gpgsm.ocsp-problem"); /* add_helptag (ctx, "gpgsm.ocsp-problem"); */
leave_li (ctx); leave_li (ctx);
@ -805,8 +922,6 @@ proc_type_verify (audit_ctx_t ctx)
} }
leave_li (ctx); leave_li (ctx);
} }
leave_li (ctx);
leave_li (ctx); leave_li (ctx);
} }
@ -818,16 +933,24 @@ void
audit_print_result (audit_ctx_t ctx, estream_t out, int use_html) audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
{ {
int idx; int idx;
int maxlen;
size_t n; size_t n;
log_item_t item;
helptag_t helptag; helptag_t helptag;
const char *s;
if (getenv ("use_html")) int show_raw = 0;
use_html = 1;
if (!ctx) if (!ctx)
return; return;
/* We use an environment variable to include some debug info in the
log. */
if ((s = getenv ("gnupg_debug_audit")))
{
show_raw = 1;
if (!strcmp (s, "html"))
use_html = 1;
}
assert (!ctx->outstream); assert (!ctx->outstream);
ctx->outstream = out; ctx->outstream = out;
ctx->use_html = use_html; ctx->use_html = use_html;
@ -843,51 +966,87 @@ audit_print_result (audit_ctx_t ctx, estream_t out, int use_html)
goto leave; goto leave;
} }
for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++) if (show_raw)
{ {
n = strlen (eventstr_msgstr + eventstr_msgidx[idx]); int maxlen;
if (n > maxlen)
maxlen = n; for (idx=0,maxlen=0; idx < DIM (eventstr_msgidx); idx++)
{
n = strlen (eventstr_msgstr + eventstr_msgidx[idx]);
if (n > maxlen)
maxlen = n;
}
if (use_html)
es_fputs ("<pre>\n", out);
for (idx=0; idx < ctx->logused; idx++)
{
es_fprintf (out, "log: %-*s",
maxlen, event2str (ctx->log[idx].event));
if (ctx->log[idx].have_intvalue)
es_fprintf (out, " i=%d", ctx->log[idx].intvalue);
if (ctx->log[idx].string)
{
es_fputs (" s=`", out);
writeout (ctx, ctx->log[idx].string);
es_fputs ("'", out);
}
if (ctx->log[idx].cert)
es_fprintf (out, " has_cert");
if (ctx->log[idx].have_err)
{
es_fputs (" err=`", out);
writeout (ctx, gpg_strerror (ctx->log[idx].err));
es_fputs ("'", out);
}
es_fputs ("\n", out);
}
if (use_html)
es_fputs ("</pre>\n", out);
else
es_fputs ("\n", out);
} }
if (use_html) enter_li (ctx);
es_fputs ("<pre>\n", out);
for (idx=0; idx < ctx->logused; idx++)
{
es_fprintf (out, "log: %-*s",
maxlen, event2str (ctx->log[idx].event));
if (ctx->log[idx].have_intvalue)
es_fprintf (out, " i=%d", ctx->log[idx].intvalue);
if (ctx->log[idx].string)
{
es_fputs (" s=`", out);
writeout (ctx, ctx->log[idx].string);
es_fputs ("'", out);
}
if (ctx->log[idx].cert)
es_fprintf (out, " has_cert");
if (ctx->log[idx].have_err)
{
es_fputs (" err=`", out);
writeout (ctx, gpg_strerror (ctx->log[idx].err));
es_fputs ("'", out);
}
es_fputs ("\n", out);
}
if (use_html)
es_fputs ("</pre>\n", out);
else
es_fputs ("\n", out);
switch (ctx->type) switch (ctx->type)
{ {
case AUDIT_TYPE_NONE: case AUDIT_TYPE_NONE:
writeout_para (ctx, _("Audit of this operation is not supported.")); writeout_li (ctx, NULL, _("Unknown operation"));
break;
case AUDIT_TYPE_ENCRYPT:
proc_type_encrypt (ctx);
break;
case AUDIT_TYPE_SIGN:
proc_type_sign (ctx);
break;
case AUDIT_TYPE_DECRYPT:
proc_type_decrypt (ctx);
break; break;
case AUDIT_TYPE_VERIFY: case AUDIT_TYPE_VERIFY:
proc_type_verify (ctx); proc_type_verify (ctx);
break; break;
} }
item = find_log_item (ctx, AUDIT_AGENT_READY, 0);
if (item && item->have_err)
{
writeout_li (ctx, item->err? "No":"Yes", "%s", _("Gpg-Agent usable"));
if (item->err)
{
writeout_rem (ctx, "%s", gpg_strerror (item->err));
add_helptag (ctx, "gnupg.agent-problem");
}
}
item = find_log_item (ctx, AUDIT_DIRMNGR_READY, 0);
if (item && item->have_err)
{
writeout_li (ctx, item->err? "No":"Yes", "%s", _("Dirmngr usable"));
if (item->err)
{
writeout_rem (ctx, "%s", gpg_strerror (item->err));
add_helptag (ctx, "gnupg.dirmngr-problem");
}
}
leave_li (ctx);
/* Show the help from the collected help tags. */ /* Show the help from the collected help tags. */

View File

@ -31,6 +31,9 @@ typedef struct audit_ctx_s *audit_ctx_t;
typedef enum typedef enum
{ {
AUDIT_TYPE_NONE = 0, /* No type set. */ AUDIT_TYPE_NONE = 0, /* No type set. */
AUDIT_TYPE_ENCRYPT, /* Data encryption. */
AUDIT_TYPE_SIGN, /* Signature creation. */
AUDIT_TYPE_DECRYPT, /* Data decryption. */
AUDIT_TYPE_VERIFY /* Signature verification. */ AUDIT_TYPE_VERIFY /* Signature verification. */
} }
audit_type_t; audit_type_t;
@ -49,6 +52,16 @@ typedef enum
now. This indicates that all parameters are okay and we can now. This indicates that all parameters are okay and we can
start to process the actual data. */ start to process the actual data. */
AUDIT_AGENT_READY, /* err */
/* Indicates whether the gpg-agent is available. For some
operations the agent is not required and thus no such event
will be logged. */
AUDIT_DIRMNGR_READY, /* err */
/* Indicates whether the Dirmngr is available. For some
operations the Dirmngr is not required and thus no such event
will be logged. */
AUDIT_GOT_DATA, AUDIT_GOT_DATA,
/* Data to be processed has been seen. */ /* Data to be processed has been seen. */
@ -122,6 +135,28 @@ typedef enum
AUDIT_CHAIN_STATUS, /* err */ AUDIT_CHAIN_STATUS, /* err */
/* Tells the final status of the chain validation. */ /* Tells the final status of the chain validation. */
AUDIT_ROOT_TRUSTED, /* cert, err */
/* Tells whether the root certificate is trusted. This event is
emmited durcing chain validation. */
AUDIT_GOT_RECIPIENTS, /* int */
/* Records the number of recipients to be used for encryption.
This includes the recipients set by --encrypt-to but records 0
if no real recipient has been given. */
AUDIT_SESSION_KEY, /* string */
/* Mark the creation or availibility of the session key. The
parameter is the algorithm ID. */
AUDIT_ENCRYPTED_TO, /* cert, err */
/* Records the certificate used for encryption and whether the
session key could be encrypted to it (err==0). */
AUDIT_ENCRYPTION_DONE,
/* Encryption succeeded. */
AUDIT_LAST_EVENT /* Marker for parsing this list. */ AUDIT_LAST_EVENT /* Marker for parsing this list. */
} }

View File

@ -73,6 +73,7 @@ have_libusb=no
use_bzip2=yes use_bzip2=yes
use_exec=yes use_exec=yes
disable_keyserver_path=no disable_keyserver_path=no
use_camellia=no
GNUPG_BUILD_PROGRAM(gpg, yes) GNUPG_BUILD_PROGRAM(gpg, yes)
@ -172,6 +173,21 @@ AC_ARG_ENABLE(bzip2,
use_bzip2=$enableval) use_bzip2=$enableval)
AC_MSG_RESULT($use_bzip2) AC_MSG_RESULT($use_bzip2)
# Check whether testing support for Camellia has been requested
AC_MSG_CHECKING([whether to enable the CAMELLIA cipher for gpg])
AC_ARG_ENABLE(camellia,
AC_HELP_STRING([--enable-camellia],[enable the CAMELLIA cipher for gpg]),
use_camellia=$enableval)
AC_MSG_RESULT($use_camellia)
if test x"$use_camellia" = xyes ; then
AC_DEFINE(USE_CAMELLIA,1,[Define to include the CAMELLIA cipher into gpg])
AC_MSG_WARN([[
***
*** The Camellia cipher for gpg is for testing only and
*** is NOT for production use!
***]])
fi
# Configure option to allow or disallow execution of external # Configure option to allow or disallow execution of external
# programs, like a photo viewer. # programs, like a photo viewer.
@ -1417,4 +1433,10 @@ echo "
gpg-check-pattern will not be build. gpg-check-pattern will not be build.
" "
fi fi
if test x"$use_camellia" = xyes ; then
echo
echo "WARNING: The Camellia cipher for gpg is for testing only"
echo " and is NOT for production use!"
echo
fi

View File

@ -272,6 +272,6 @@ Eine Leerzeile beendet die Eingabe.
# Local variables: # Local variables:
# mode: fundamental # mode: default-generic
# coding: utf-8 # coding: utf-8
# End: # End:

View File

@ -52,6 +52,44 @@ configured passphrase constraints.
. .
.gnupg.agent-problem
# There was a problem accessing or starting the agent.
It was either not possible to connect to a running Gpg-Agent or a
communication problem with a running agent occurred.
The system uses a background process, called Gpg-Agent, for processing
private keys and to ask for passphrases. The agent is usually started
when the user logs in and runs as long the user is logged in. In case
that no agent is available, the system tries to start one on the fly
but that version of the agent is somewhat limited in functionality and
thus may lead to little problems.
You probably need to ask your administrator on how to solve the
problem. As a workaround you might try to log out and in to your
session and see whether this helps. If this helps please tell the
administrator anyway because this indicates a bug in the software.
.
.gnupg.dirmngr-problem
# There was a problen accessing the dirmngr.
It was either not possible to connect to a running Dirmngr or a
communication problem with a running Dirmngr occurred.
To lookup certificate revocation lists (CRLs), performing OCSP
validation and to lookup keys through LDAP servers, the system uses an
external service program named Dirmngr. The Dirmngr is usually running
as a system service (daemon) and does not need any attention by the
user. In case of problems the system might start its own copy of the
Dirmngr on a per request base; this is a workaround and yields limited
performance.
If you encounter this problem, you should ask your system
administrator how to proceed. As an interim solution you may try to
disable CRL checking in gpgsm's configuration.
.
.gpg.edit_ownertrust.value .gpg.edit_ownertrust.value
# The help identies prefixed with "gpg." used to be hard coded in gpg # The help identies prefixed with "gpg." used to be hard coded in gpg
# but may now be overridden by help texts from this file. # but may now be overridden by help texts from this file.
@ -312,6 +350,6 @@ your system administrator whether you should trust this certificate.
# Local variables: # Local variables:
# mode: fundamental # mode: default-generic
# coding: utf-8 # coding: utf-8
# End: # End:

View File

@ -1,6 +1,30 @@
2007-12-12 Werner Koch <wk@g10code.com>
* misc.c (map_cipher_openpgp_to_gcry): New. Used to map Camellia
algorithms to Gcrypt.
(openpgp_cipher_test_algo): Call new map function. Replace
all remaining calls to gcry_cipher_test_algo by a call to this.
(openpgp_cipher_algo_name): New. Replace all remaining calls to
gcry_cipher_algo_name by a call to this.
(map_cipher_gcry_to_openpgp): New.
(string_to_cipher_algo): Use it.
* gpg.c (main): Print a warning if Camellia support is build in.
* gpg.c (print_algo_names): New. From the 1.4 branch by David.
(list_config): Use it here for the "ciphername" and "digestname"
config items so we can get a script-parseable list of the names.
* parse-packet.c (parse_onepass_sig): Sigclass is hex, so include
the 0x.
* sign.c (match_dsa_hash): Remove conditional builds dending on
USE_SHAxxx. We don't need this becuase it can be expected that
libgcrypt provides it. However we need to runtime test for SHA244
becuase that is only available with libgcrypt 2.4.
2007-12-11 Werner Koch <wk@g10code.com> 2007-12-11 Werner Koch <wk@g10code.com>
* mainproc.c (proc_pubkey_enc): Allo type 20 Elgamal key for * mainproc.c (proc_pubkey_enc): Allow type 20 Elgamal key for
decryption. decryption.
2007-12-10 Werner Koch <wk@g10code.com> 2007-12-10 Werner Koch <wk@g10code.com>

View File

@ -244,7 +244,7 @@ encode_simple( const char *filename, int mode, int use_seskey )
if(opt.verbose) if(opt.verbose)
log_info(_("using cipher %s\n"), log_info(_("using cipher %s\n"),
gcry_cipher_algo_name (cfx.dek->algo)); openpgp_cipher_algo_name (cfx.dek->algo));
cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo); cfx.dek->use_mdc=use_mdc(NULL,cfx.dek->algo);
} }
@ -558,7 +558,7 @@ encode_crypt( const char *filename, strlist_t remusr, int use_symkey )
opt.def_cipher_algo,NULL)!=opt.def_cipher_algo) opt.def_cipher_algo,NULL)!=opt.def_cipher_algo)
log_info(_("WARNING: forcing symmetric cipher %s (%d)" log_info(_("WARNING: forcing symmetric cipher %s (%d)"
" violates recipient preferences\n"), " violates recipient preferences\n"),
gcry_cipher_algo_name (opt.def_cipher_algo), openpgp_cipher_algo_name (opt.def_cipher_algo),
opt.def_cipher_algo); opt.def_cipher_algo);
cfx.dek->algo = opt.def_cipher_algo; cfx.dek->algo = opt.def_cipher_algo;
@ -750,7 +750,7 @@ encrypt_filter( void *opaque, int control,
NULL)!=opt.def_cipher_algo) NULL)!=opt.def_cipher_algo)
log_info(_("forcing symmetric cipher %s (%d) " log_info(_("forcing symmetric cipher %s (%d) "
"violates recipient preferences\n"), "violates recipient preferences\n"),
gcry_cipher_algo_name (opt.def_cipher_algo), openpgp_cipher_algo_name (opt.def_cipher_algo),
opt.def_cipher_algo); opt.def_cipher_algo);
efx->cfx.dek->algo = opt.def_cipher_algo; efx->cfx.dek->algo = opt.def_cipher_algo;
@ -847,7 +847,7 @@ write_pubkey_enc_from_list( PK_LIST pk_list, DEK *dek, IOBUF out )
char *ustr = get_user_id_string_native (enc->keyid); char *ustr = get_user_id_string_native (enc->keyid);
log_info(_("%s/%s encrypted for: \"%s\"\n"), log_info(_("%s/%s encrypted for: \"%s\"\n"),
gcry_pk_algo_name (enc->pubkey_algo), gcry_pk_algo_name (enc->pubkey_algo),
gcry_cipher_algo_name (dek->algo), openpgp_cipher_algo_name (dek->algo),
ustr ); ustr );
xfree(ustr); xfree(ustr);
} }

View File

@ -88,8 +88,9 @@ decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
if ( opt.verbose && !dek->algo_info_printed ) if ( opt.verbose && !dek->algo_info_printed )
{ {
if (!gcry_cipher_test_algo (dek->algo)) if (!openpgp_cipher_test_algo (dek->algo))
log_info (_("%s encrypted data\n"), gcry_cipher_algo_name (dek->algo)); log_info (_("%s encrypted data\n"),
openpgp_cipher_algo_name (dek->algo));
else else
log_info (_("encrypted with unknown algorithm %d\n"), dek->algo ); log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
dek->algo_info_printed = 1; dek->algo_info_printed = 1;

View File

@ -791,7 +791,7 @@ my_strusage( int level )
case 35: case 35:
if( !ciphers ) if( !ciphers )
ciphers = build_list(_("Cipher: "), 'S', ciphers = build_list(_("Cipher: "), 'S',
gcry_cipher_algo_name, openpgp_cipher_algo_name,
openpgp_cipher_test_algo ); openpgp_cipher_test_algo );
p = ciphers; p = ciphers;
break; break;
@ -1384,6 +1384,24 @@ print_algo_numbers(int (*checker)(int))
} }
static void
print_algo_names(int (*checker)(int),const char *(*mapper)(int))
{
int i,first=1;
for(i=0;i<=110;i++)
{
if(!checker(i))
{
if(first)
first=0;
else
printf(";");
printf("%s",mapper(i));
}
}
}
/* In the future, we can do all sorts of interesting configuration /* In the future, we can do all sorts of interesting configuration
output here. For now, just give "group" as the Enigmail folks need output here. For now, just give "group" as the Enigmail folks need
it, and pubkey, cipher, hash, and compress as they may be useful it, and pubkey, cipher, hash, and compress as they may be useful
@ -1450,6 +1468,14 @@ list_config(char *items)
any=1; any=1;
} }
if (show_all || !ascii_strcasecmp (name,"ciphername"))
{
printf ("cfg:ciphername:");
print_algo_names (openpgp_cipher_test_algo,openpgp_cipher_algo_name);
printf ("\n");
any = 1;
}
if(show_all if(show_all
|| ascii_strcasecmp(name,"digest")==0 || ascii_strcasecmp(name,"digest")==0
|| ascii_strcasecmp(name,"hash")==0) || ascii_strcasecmp(name,"hash")==0)
@ -1460,6 +1486,16 @@ list_config(char *items)
any=1; any=1;
} }
if (show_all
|| !ascii_strcasecmp(name,"digestname")
|| !ascii_strcasecmp(name,"hashname"))
{
printf ("cfg:digestname:");
print_algo_names (openpgp_md_test_algo, gcry_md_algo_name);
printf("\n");
any=1;
}
if(show_all || ascii_strcasecmp(name,"compress")==0) if(show_all || ascii_strcasecmp(name,"compress")==0)
{ {
printf("cfg:compress:"); printf("cfg:compress:");
@ -2864,6 +2900,15 @@ main (int argc, char **argv )
log_set_prefix (NULL, 1|2|4); log_set_prefix (NULL, 1|2|4);
} }
#ifdef USE_CAMELLIA
/* We better also print a runtime warning if people build it with
support for Camellia (which is not yet defined by OpenPGP). */
log_info ("WARNING: This version has been built with support for the "
"Camellia cipher.\n");
log_info (" It is for testing only and is NOT for production "
"use!\n");
#endif
if (opt.verbose > 2) if (opt.verbose > 2)
log_info ("using character set `%s'\n", get_native_charset ()); log_info ("using character set `%s'\n", get_native_charset ());
@ -3129,7 +3174,7 @@ main (int argc, char **argv )
if(opt.def_cipher_algo if(opt.def_cipher_algo
&& !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL)) && !algo_available(PREFTYPE_SYM,opt.def_cipher_algo,NULL))
{ {
badalg = gcry_cipher_algo_name (opt.def_cipher_algo); badalg = openpgp_cipher_algo_name (opt.def_cipher_algo);
badtype = PREFTYPE_SYM; badtype = PREFTYPE_SYM;
} }
else if(opt.def_digest_algo else if(opt.def_digest_algo

View File

@ -602,9 +602,9 @@ check_prefs(KBNODE keyblock)
if (openpgp_cipher_test_algo (prefs->value)) if (openpgp_cipher_test_algo (prefs->value))
{ {
const char *algo = const char *algo =
(gcry_cipher_test_algo (prefs->value) (openpgp_cipher_test_algo (prefs->value)
? num ? num
: gcry_cipher_algo_name (prefs->value)); : openpgp_cipher_algo_name (prefs->value));
if(!problem) if(!problem)
check_prefs_warning(pk); check_prefs_warning(pk);
log_info(_(" \"%s\": preference for cipher" log_info(_(" \"%s\": preference for cipher"

View File

@ -2325,9 +2325,10 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
tty_printf (", "); tty_printf (", ");
any = 1; any = 1;
/* We don't want to display strings for experimental algos */ /* We don't want to display strings for experimental algos */
if (!gcry_cipher_test_algo (prefs[i].value) if (!openpgp_cipher_test_algo (prefs[i].value)
&& prefs[i].value < 100 ) && prefs[i].value < 100 )
tty_printf ("%s", gcry_cipher_algo_name (prefs[i].value)); tty_printf ("%s",
openpgp_cipher_algo_name (prefs[i].value));
else else
tty_printf ("[%d]", prefs[i].value); tty_printf ("[%d]", prefs[i].value);
if (prefs[i].value == CIPHER_ALGO_3DES ) if (prefs[i].value == CIPHER_ALGO_3DES )
@ -2337,7 +2338,7 @@ show_prefs (PKT_user_id *uid, PKT_signature *selfsig, int verbose)
if (!des_seen) { if (!des_seen) {
if (any) if (any)
tty_printf (", "); tty_printf (", ");
tty_printf ("%s", gcry_cipher_algo_name (CIPHER_ALGO_3DES)); tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
} }
tty_printf ("\n "); tty_printf ("\n ");
tty_printf (_("Digest: ")); tty_printf (_("Digest: "));

View File

@ -83,6 +83,7 @@ u16 checksum_mpi( gcry_mpi_t a );
u32 buffer_to_u32( const byte *buffer ); u32 buffer_to_u32( const byte *buffer );
const byte *get_session_marker( size_t *rlen ); const byte *get_session_marker( size_t *rlen );
int openpgp_cipher_test_algo( int algo ); int openpgp_cipher_test_algo( int algo );
const char *openpgp_cipher_algo_name (int algo);
int openpgp_pk_test_algo( int algo ); int openpgp_pk_test_algo( int algo );
int openpgp_pk_test_algo2 ( int algo, unsigned int use ); int openpgp_pk_test_algo2 ( int algo, unsigned int use );
int openpgp_pk_algo_usage ( int algo ); int openpgp_pk_algo_usage ( int algo );

View File

@ -274,9 +274,9 @@ proc_symkey_enc( CTX c, PACKET *pkt )
else if(!c->dek) else if(!c->dek)
{ {
int algo = enc->cipher_algo; int algo = enc->cipher_algo;
const char *s = gcry_cipher_algo_name (algo); const char *s = openpgp_cipher_algo_name (algo);
if (!gcry_cipher_test_algo (algo)) if (!openpgp_cipher_test_algo (algo))
{ {
if(!opt.quiet) if(!opt.quiet)
{ {
@ -524,8 +524,8 @@ proc_encrypted( CTX c, PACKET *pkt )
algo = opt.def_cipher_algo; algo = opt.def_cipher_algo;
if ( algo ) if ( algo )
log_info (_("assuming %s encrypted data\n"), log_info (_("assuming %s encrypted data\n"),
gcry_cipher_algo_name (algo)); openpgp_cipher_algo_name (algo));
else if ( gcry_cipher_test_algo (CIPHER_ALGO_IDEA) ) else if ( openpgp_cipher_test_algo (CIPHER_ALGO_IDEA) )
{ {
algo = opt.def_cipher_algo; algo = opt.def_cipher_algo;
if (!algo) if (!algo)
@ -533,7 +533,7 @@ proc_encrypted( CTX c, PACKET *pkt )
idea_cipher_warn(1); idea_cipher_warn(1);
log_info (_("IDEA cipher unavailable, " log_info (_("IDEA cipher unavailable, "
"optimistically attempting to use %s instead\n"), "optimistically attempting to use %s instead\n"),
gcry_cipher_algo_name (algo)); openpgp_cipher_algo_name (algo));
} }
else else
{ {

View File

@ -301,7 +301,7 @@ print_cipher_algo_note( int algo )
{ {
warn=1; warn=1;
log_info (_("WARNING: using experimental cipher algorithm %s\n"), log_info (_("WARNING: using experimental cipher algorithm %s\n"),
gcry_cipher_algo_name (algo)); openpgp_cipher_algo_name (algo));
} }
} }
} }
@ -324,6 +324,33 @@ print_digest_algo_note( int algo )
gcry_md_algo_name (algo)); gcry_md_algo_name (algo));
} }
/* Map OpenPGP algo numbers to those used by Libgcrypt. We need to do
this for algorithms we implemented in Libgcrypt after they become
part of OpenPGP. */
static int
map_cipher_openpgp_to_gcry (int algo)
{
switch (algo)
{
case CIPHER_ALGO_CAMELLIA128: return 310;
case CIPHER_ALGO_CAMELLIA256: return 312;
default: return algo;
}
}
/* The inverse fucntion of above. */
static int
map_cipher_gcry_to_openpgp (int algo)
{
switch (algo)
{
case 310: return CIPHER_ALGO_CAMELLIA128;
case 312: return CIPHER_ALGO_CAMELLIA256;
default: return algo;
}
}
/**************** /****************
* Wrapper around the libgcrypt function with additonal checks on * Wrapper around the libgcrypt function with additonal checks on
* the OpenPGP contraints for the algo ID. * the OpenPGP contraints for the algo ID.
@ -331,12 +358,32 @@ print_digest_algo_note( int algo )
int int
openpgp_cipher_test_algo( int algo ) openpgp_cipher_test_algo( int algo )
{ {
/* 5 and 6 are marked reserved by rfc2440bis. */ /* (5 and 6 are marked reserved by rfc4880.) */
if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 ) if ( algo < 0 || algo > 110 || algo == 5 || algo == 6 )
return gpg_error (GPG_ERR_CIPHER_ALGO); return gpg_error (GPG_ERR_CIPHER_ALGO);
return gcry_cipher_test_algo (algo);
/* Camellia is not yet defined for OpenPGP thus only allow it if
requested. */
#ifndef USE_CAMELLIA
if (algo == CIPHER_ALGO_CAMELLIA128
|| algo == CIPHER_ALGO_CAMELLIA256)
return gpg_error (GPG_ERR_CIPHER_ALGO);
#endif
return gcry_cipher_test_algo (map_cipher_openpgp_to_gcry (algo));
} }
/* Map the OpenPGP cipher algorithm whose ID is contained in ALGORITHM to a
string representation of the algorithm name. For unknown algorithm
IDs this function returns "?". */
const char *
openpgp_cipher_algo_name (int algo)
{
return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo));
}
int int
openpgp_pk_test_algo( int algo ) openpgp_pk_test_algo( int algo )
{ {
@ -690,7 +737,7 @@ string_to_cipher_algo (const char *string)
{ {
int val; int val;
val = gcry_cipher_map_name (string); val = map_cipher_gcry_to_openpgp (gcry_cipher_map_name (string));
if (!val && string && (string[0]=='S' || string[0]=='s')) if (!val && string && (string[0]=='S' || string[0]=='s'))
{ {
char *endptr; char *endptr;

View File

@ -1588,8 +1588,10 @@ parse_onepass_sig( IOBUF inp, int pkttype, unsigned long pktlen,
ops->keyid[1] = read_32(inp); pktlen -= 4; ops->keyid[1] = read_32(inp); pktlen -= 4;
ops->last = iobuf_get_noeof(inp); pktlen--; ops->last = iobuf_get_noeof(inp); pktlen--;
if( list_mode ) if( list_mode )
fprintf (listfp, ":onepass_sig packet: keyid %08lX%08lX\n" fprintf (listfp,
"\tversion %d, sigclass %02x, digest %d, pubkey %d, last=%d\n", ":onepass_sig packet: keyid %08lX%08lX\n"
"\tversion %d, sigclass 0x%02x, digest %d, pubkey %d, "
"last=%d\n",
(ulong)ops->keyid[0], (ulong)ops->keyid[1], (ulong)ops->keyid[0], (ulong)ops->keyid[1],
version, ops->sig_class, version, ops->sig_class,
ops->digest_algo, ops->pubkey_algo, ops->last ); ops->digest_algo, ops->pubkey_algo, ops->last );

View File

@ -282,7 +282,7 @@ get_it( PKT_pubkey_enc *enc, DEK *dek, PKT_secret_key *sk, u32 *keyid )
&& !opt.quiet && !opt.quiet
&& !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo )) && !is_algo_in_prefs( pkb, PREFTYPE_SYM, dek->algo ))
log_info (_("WARNING: cipher algorithm %s not found in recipient" log_info (_("WARNING: cipher algorithm %s not found in recipient"
" preferences\n"), gcry_cipher_algo_name (dek->algo)); " preferences\n"), openpgp_cipher_algo_name (dek->algo));
if (!rc) { if (!rc) {
KBNODE k; KBNODE k;

View File

@ -345,22 +345,24 @@ match_dsa_hash (unsigned int qbytes)
{ {
if (qbytes <= 20) if (qbytes <= 20)
return DIGEST_ALGO_SHA1; return DIGEST_ALGO_SHA1;
#ifdef USE_SHA256
if (qbytes <= 28) /* SHA244 is only available with libgcrypt 1.4 - thus do a runtime
test. */
if (qbytes <= 28 && !gcry_md_test_algo (DIGEST_ALGO_SHA224))
return DIGEST_ALGO_SHA224; return DIGEST_ALGO_SHA224;
if (qbytes <= 32) if (qbytes <= 32)
return DIGEST_ALGO_SHA256; return DIGEST_ALGO_SHA256;
#endif
#ifdef USE_SHA512
if (qbytes <= 48) if (qbytes <= 48)
return DIGEST_ALGO_SHA384; return DIGEST_ALGO_SHA384;
if (qbytes <= 64) if (qbytes <= 64)
return DIGEST_ALGO_SHA512; return DIGEST_ALGO_SHA512;
#endif
return DEFAULT_DIGEST_ALGO; return DEFAULT_DIGEST_ALGO;
/* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong /* DEFAULT_DIGEST_ALGO will certainly fail, but it's the best wrong
answer we have if the larger SHAs aren't there. */ answer we have if a digest larger than 512 bits is requested. */
} }
@ -1258,7 +1260,7 @@ sign_symencrypt_file (const char *fname, strlist_t locusr)
algo = default_cipher_algo(); algo = default_cipher_algo();
if (!opt.quiet || !opt.batch) if (!opt.quiet || !opt.batch)
log_info (_("%s encryption will be used\n"), log_info (_("%s encryption will be used\n"),
gcry_cipher_algo_name (algo) ); openpgp_cipher_algo_name (algo) );
cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled); cfx.dek = passphrase_to_dek( NULL, 0, algo, s2k, 2, NULL, &canceled);
if (!cfx.dek || !cfx.dek->keylen) { if (!cfx.dek || !cfx.dek->keylen) {

View File

@ -1,3 +1,7 @@
2007-12-12 Werner Koch <wk@g10code.com>
* cipher.h (CIPHER_ALGO_CAMELLIA128, CIPHER_ALGO_CAMELLIA256): New.
2006-09-20 Werner Koch <wk@g10code.com> 2006-09-20 Werner Koch <wk@g10code.com>
* errors.h, http.h, memory.h, mpi.h, util.h, i18n.h: Removed. * errors.h, http.h, memory.h, mpi.h, util.h, i18n.h: Removed.

View File

@ -1,5 +1,6 @@
/* cipher.h - Definitions for OpenPGP /* cipher.h - Definitions for OpenPGP
* Copyright (C) 1998, 1999, 2000, 2001, 2006 Free Software Foundation, Inc. * Copyright (C) 1998, 1999, 2000, 2001, 2006,
* 2007 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -44,6 +45,9 @@
#define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192 #define CIPHER_ALGO_RIJNDAEL192 CIPHER_ALGO_AES192
#define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256 #define CIPHER_ALGO_RIJNDAEL256 CIPHER_ALGO_AES256
#define CIPHER_ALGO_TWOFISH /* 10 */ GCRY_CIPHER_TWOFISH /* 256 bit */ #define CIPHER_ALGO_TWOFISH /* 10 */ GCRY_CIPHER_TWOFISH /* 256 bit */
/* Note: Camellia ids don't match those used by libgcrypt. */
#define CIPHER_ALGO_CAMELLIA128 11
#define CIPHER_ALGO_CAMELLIA256 12
#define CIPHER_ALGO_DUMMY 110 /* No encryption at all. */ #define CIPHER_ALGO_DUMMY 110 /* No encryption at all. */
#define PUBKEY_ALGO_RSA /* 1 */ GCRY_PK_RSA #define PUBKEY_ALGO_RSA /* 1 */ GCRY_PK_RSA
@ -66,8 +70,8 @@
#define DIGEST_ALGO_SHA256 /* 8 */ GCRY_MD_SHA256 #define DIGEST_ALGO_SHA256 /* 8 */ GCRY_MD_SHA256
#define DIGEST_ALGO_SHA384 /* 9 */ GCRY_MD_SHA384 #define DIGEST_ALGO_SHA384 /* 9 */ GCRY_MD_SHA384
#define DIGEST_ALGO_SHA512 /* 10 */ GCRY_MD_SHA512 #define DIGEST_ALGO_SHA512 /* 10 */ GCRY_MD_SHA512
/* SHA224 is as of now only defined in the libgcrypt SVN; thus we /* SHA224 is only available in libgcrypt 1.4.0; thus we
can't use that macro. */ can't use the GCRY macro here. */
#define DIGEST_ALGO_SHA224 /* 11 */ 11 /* GCRY_MD_SHA224 */ #define DIGEST_ALGO_SHA224 /* 11 */ 11 /* GCRY_MD_SHA224 */
#define COMPRESS_ALGO_NONE 0 #define COMPRESS_ALGO_NONE 0

View File

@ -1,6 +1,6 @@
2007-12-10 Werner Koch <wk@g10code.com> 2007-12-10 Werner Koch <wk@g10code.com>
* app-openpgp.c (do_decipher): Take care of cryptograms shiorther * app-openpgp.c (do_decipher): Take care of cryptograms shorter
that 128 bytes. Fixes bug#851. that 128 bytes. Fixes bug#851.
2007-11-14 Werner Koch <wk@g10code.com> 2007-11-14 Werner Koch <wk@g10code.com>

View File

@ -2461,7 +2461,7 @@ do_decipher (app_t app, const char *keyidstr,
/* We might encounter a couple of leading zeroes in the /* We might encounter a couple of leading zeroes in the
cryptogram. Due to internal use of MPIs thease leading cryptogram. Due to internal use of MPIs thease leading
zeroes are stripped. However the OpenPGp card expects zeroes are stripped. However the OpenPGP card expects
exactly 128 bytes for the cryptogram (for a 1k key). Thus we exactly 128 bytes for the cryptogram (for a 1k key). Thus we
need to fix it up. We do this for up to 16 leading zero need to fix it up. We do this for up to 16 leading zero
bytes; a cryptogram with more than this is with a very high bytes; a cryptogram with more than this is with a very high

View File

@ -1,3 +1,20 @@
2007-12-11 Werner Koch <wk@g10code.com>
* certchain.c (do_validate_chain): Log AUDIT_ROOT_TRUSTED.
* server.c (cmd_sign, cmd_decrypt, cmd_encrypt): Start audit log.
(cmd_recipient): Start audit session.
* gpgsm.c (main): Revamp creation of the audit log.
* gpgsm.h (struct server_control_s): Add AGENT_SEEN and DIRMNGR_SEEN.
* call-agent.c (start_agent): Record an audit event.
* call-dirmngr.c (start_dirmngr): Ditto. Add new arg CTRL and pass
it from all callers.
(prepare_dirmngr): New helper for start_dirmngr.
* encrypt.c (gpgsm_encrypt): Add calls to audit_log.
2007-12-03 Werner Koch <wk@g10code.com> 2007-12-03 Werner Koch <wk@g10code.com>
* gpgsm.c (main): All gnupg_reopen_std. * gpgsm.c (main): All gnupg_reopen_std.

View File

@ -1,5 +1,6 @@
/* call-agent.c - divert operations to the agent /* call-agent.c - divert operations to the agent
* Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * Copyright (C) 2001, 2002, 2003, 2005,
* 2007 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -69,13 +70,14 @@ struct learn_parm_s
static int static int
start_agent (ctrl_t ctrl) start_agent (ctrl_t ctrl)
{ {
int rc;
if (agent_ctx) if (agent_ctx)
return 0; /* fixme: We need a context for each thread or serialize rc = 0; /* fixme: We need a context for each thread or
the access to the agent (which is suitable given that serialize the access to the agent (which is
the agent is not MT. */ suitable given that the agent is not MT. */
else
rc = start_new_gpg_agent (&agent_ctx,
return start_new_gpg_agent (&agent_ctx,
GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_DEFAULT,
opt.homedir, opt.homedir,
opt.agent_program, opt.agent_program,
@ -84,7 +86,13 @@ start_agent (ctrl_t ctrl)
opt.xauthority, opt.pinentry_user_data, opt.xauthority, opt.pinentry_user_data,
opt.verbose, DBG_ASSUAN, opt.verbose, DBG_ASSUAN,
gpgsm_status2, ctrl); gpgsm_status2, ctrl);
if (!ctrl->agent_seen)
{
ctrl->agent_seen = 1;
audit_log_ok (ctrl->audit, AUDIT_AGENT_READY, rc);
}
return rc;
} }

View File

@ -1,5 +1,5 @@
/* call-dirmngr.c - communication with the dromngr /* call-dirmngr.c - communication with the dromngr
* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. * Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -134,13 +134,32 @@ get_membuf (struct membuf *mb, size_t *len)
} }
/* This fucntion prepares the dirmngr for a new session. The
audit-events option is used so that other dirmngr clients won't get
disturbed by such events. */
static void
prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
{
if (!ctrl->dirmngr_seen)
{
ctrl->dirmngr_seen = 1;
if (!err)
{
err = assuan_transact (ctx, "OPTION audit-events=1",
NULL, NULL, NULL, NULL, NULL, NULL);
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
err = 0; /* Allow the use of old dirmngr versions. */
}
audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
}
}
/* Try to connect to the agent via socket or fork it off and work by /* Try to connect to the agent via socket or fork it off and work by
pipes. Handle the server's initial greeting */ pipes. Handle the server's initial greeting */
static int static int
start_dirmngr (void) start_dirmngr (ctrl_t ctrl)
{ {
int rc; int rc;
char *infostr, *p; char *infostr, *p;
@ -148,8 +167,11 @@ start_dirmngr (void)
int try_default = 0; int try_default = 0;
if (dirmngr_ctx) if (dirmngr_ctx)
return 0; /* fixme: We need a context for each thread or serialize {
the access to the dirmngr */ prepare_dirmngr (ctrl, dirmngr_ctx, 0);
return 0; /* fixme: We need a context for each thread or serialize
the access to the dirmngr */
}
/* Note: if you change this to multiple connections, you also need /* Note: if you change this to multiple connections, you also need
to take care of the implicit option sending caching. */ to take care of the implicit option sending caching. */
@ -220,7 +242,7 @@ start_dirmngr (void)
log_error (_("malformed DIRMNGR_INFO environment variable\n")); log_error (_("malformed DIRMNGR_INFO environment variable\n"));
xfree (infostr); xfree (infostr);
force_pipe_server = 1; force_pipe_server = 1;
return start_dirmngr (); return start_dirmngr (ctrl);
} }
*p++ = 0; *p++ = 0;
pid = atoi (p); pid = atoi (p);
@ -233,7 +255,7 @@ start_dirmngr (void)
prot); prot);
xfree (infostr); xfree (infostr);
force_pipe_server = 1; force_pipe_server = 1;
return start_dirmngr (); return start_dirmngr (ctrl);
} }
} }
else else
@ -251,11 +273,13 @@ start_dirmngr (void)
{ {
log_error (_("can't connect to the dirmngr - trying fall back\n")); log_error (_("can't connect to the dirmngr - trying fall back\n"));
force_pipe_server = 1; force_pipe_server = 1;
return start_dirmngr (); return start_dirmngr (ctrl);
} }
#endif /*!HAVE_W32_SYSTEM*/ #endif /*!HAVE_W32_SYSTEM*/
} }
prepare_dirmngr (ctrl, ctx, rc);
if (rc) if (rc)
{ {
log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc)); log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
@ -424,7 +448,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
struct isvalid_status_parm_s stparm; struct isvalid_status_parm_s stparm;
rc = start_dirmngr (); rc = start_dirmngr (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -691,7 +715,7 @@ gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names,
struct lookup_parm_s parm; struct lookup_parm_s parm;
size_t len; size_t len;
rc = start_dirmngr (); rc = start_dirmngr (ctrl);
if (rc) if (rc)
return rc; return rc;
@ -821,7 +845,7 @@ gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
size_t len; size_t len;
struct run_command_parm_s parm; struct run_command_parm_s parm;
rc = start_dirmngr (); rc = start_dirmngr (ctrl);
if (rc) if (rc)
return rc; return rc;

View File

@ -1127,6 +1127,8 @@ do_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime_arg,
associated with that specific root certificate. */ associated with that specific root certificate. */
istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert, istrusted_rc = gpgsm_agent_istrusted (ctrl, subject_cert,
rootca_flags); rootca_flags);
audit_log_cert (ctrl->audit, AUDIT_ROOT_TRUSTED,
subject_cert, istrusted_rc);
/* If the chain model extended attribute is used, make sure /* If the chain model extended attribute is used, make sure
that our chain model flag is set. */ that our chain model flag is set. */
if (has_validation_model_chain (subject_cert, listmode, listfp)) if (has_validation_model_chain (subject_cert, listmode, listfp))

View File

@ -1,5 +1,5 @@
/* encrypt.c - Encrypt a message /* encrypt.c - Encrypt a message
* Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. * Copyright (C) 2001, 2003, 2004, 2007 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -318,9 +318,12 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
int recpno; int recpno;
FILE *data_fp = NULL; FILE *data_fp = NULL;
certlist_t cl; certlist_t cl;
int count;
memset (&encparm, 0, sizeof encparm); memset (&encparm, 0, sizeof encparm);
audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT);
/* Check that the certificate list is not empty and that at least /* Check that the certificate list is not empty and that at least
one certificate is not flagged as encrypt_to; i.e. is a real one certificate is not flagged as encrypt_to; i.e. is a real
recipient. */ recipient. */
@ -331,10 +334,15 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
{ {
log_error(_("no valid recipients given\n")); log_error(_("no valid recipients given\n"));
gpgsm_status (ctrl, STATUS_NO_RECP, "0"); gpgsm_status (ctrl, STATUS_NO_RECP, "0");
audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0);
rc = gpg_error (GPG_ERR_NO_PUBKEY); rc = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave; goto leave;
} }
for (count = 0, cl = recplist; cl; cl = cl->next)
count++;
audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count);
kh = keydb_new (0); kh = keydb_new (0);
if (!kh) if (!kh)
{ {
@ -385,6 +393,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
goto leave; goto leave;
} }
audit_log (ctrl->audit, AUDIT_GOT_DATA);
/* We are going to create enveloped data with uninterpreted data as /* We are going to create enveloped data with uninterpreted data as
inner content */ inner content */
err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA); err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
@ -432,6 +442,8 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
rc = out_of_core (); rc = out_of_core ();
goto leave; goto leave;
} }
audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);
/* Gather certificates of recipients, encrypt the session key for /* Gather certificates of recipients, encrypt the session key for
each and store them in the CMS object */ each and store them in the CMS object */
@ -442,6 +454,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
rc = encrypt_dek (dek, cl->cert, &encval); rc = encrypt_dek (dek, cl->cert, &encval);
if (rc) if (rc)
{ {
audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc);
log_error ("encryption failed for recipient no. %d: %s\n", log_error ("encryption failed for recipient no. %d: %s\n",
recpno, gpg_strerror (rc)); recpno, gpg_strerror (rc));
goto leave; goto leave;
@ -450,6 +463,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
err = ksba_cms_add_recipient (cms, cl->cert); err = ksba_cms_add_recipient (cms, cl->cert);
if (err) if (err)
{ {
audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
log_error ("ksba_cms_add_recipient failed: %s\n", log_error ("ksba_cms_add_recipient failed: %s\n",
gpg_strerror (err)); gpg_strerror (err));
rc = err; rc = err;
@ -459,6 +473,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
err = ksba_cms_set_enc_val (cms, recpno, encval); err = ksba_cms_set_enc_val (cms, recpno, encval);
xfree (encval); xfree (encval);
audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
if (err) if (err)
{ {
log_error ("ksba_cms_set_enc_val failed: %s\n", log_error ("ksba_cms_set_enc_val failed: %s\n",
@ -466,7 +481,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
rc = err; rc = err;
goto leave; goto leave;
} }
} }
/* Main control loop for encryption. */ /* Main control loop for encryption. */
recpno = 0; recpno = 0;
@ -496,6 +511,7 @@ gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
log_error ("write failed: %s\n", gpg_strerror (rc)); log_error ("write failed: %s\n", gpg_strerror (rc));
goto leave; goto leave;
} }
audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
log_info ("encrypted data created\n"); log_info ("encrypted data created\n");
leave: leave:

View File

@ -848,6 +848,7 @@ main ( int argc, char **argv)
certlist_t signerlist = NULL; certlist_t signerlist = NULL;
int do_not_setup_keys = 0; int do_not_setup_keys = 0;
int recp_required = 0; int recp_required = 0;
estream_t auditfp = NULL;
/*mtrace();*/ /*mtrace();*/
@ -1482,6 +1483,26 @@ main ( int argc, char **argv)
keydb_add_resource (sl->d, 0, 0, NULL); keydb_add_resource (sl->d, 0, 0, NULL);
FREE_STRLIST(nrings); FREE_STRLIST(nrings);
/* Prepare the audit log feature for certain commands. */
if (auditlog)
{
switch (cmd)
{
case aEncr:
case aSign:
case aDecrypt:
case aVerify:
audit_release (ctrl.audit);
ctrl.audit = audit_new ();
auditfp = open_es_fwrite (auditlog);
break;
default:
break;
}
}
if (!do_not_setup_keys) if (!do_not_setup_keys)
{ {
for (sl = locusr; sl ; sl = sl->next) for (sl = locusr; sl ; sl = sl->next)
@ -1528,6 +1549,7 @@ main ( int argc, char **argv)
fname = argc? *argv : NULL; fname = argc? *argv : NULL;
/* Dispatch command. */
switch (cmd) switch (cmd)
{ {
case aGPGConfList: case aGPGConfList:
@ -1650,7 +1672,6 @@ main ( int argc, char **argv)
case aVerify: case aVerify:
{ {
FILE *fp = NULL; FILE *fp = NULL;
estream_t auditfp = NULL;
set_binary (stdin); set_binary (stdin);
if (argc == 2 && opt.outfile) if (argc == 2 && opt.outfile)
@ -1658,13 +1679,6 @@ main ( int argc, char **argv)
else if (opt.outfile) else if (opt.outfile)
fp = open_fwrite (opt.outfile); fp = open_fwrite (opt.outfile);
if (auditlog)
{
audit_release (ctrl.audit);
ctrl.audit = audit_new ();
auditfp = open_es_fwrite (auditlog);
}
if (!argc) if (!argc)
gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */ gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
else if (argc == 1) else if (argc == 1)
@ -1674,16 +1688,8 @@ main ( int argc, char **argv)
else else
wrong_args ("--verify [signature [detached_data]]"); wrong_args ("--verify [signature [detached_data]]");
if (auditlog)
{
audit_print_result (ctrl.audit, auditfp, 0);
audit_release (ctrl.audit);
ctrl.audit = NULL;
}
if (fp && fp != stdout) if (fp && fp != stdout)
fclose (fp); fclose (fp);
es_fclose (auditfp);
} }
break; break;
@ -1846,6 +1852,15 @@ main ( int argc, char **argv)
log_error ("invalid command (there is no implicit command)\n"); log_error ("invalid command (there is no implicit command)\n");
break; break;
} }
/* Print the audit result if needed. */
if (auditlog && auditfp)
{
audit_print_result (ctrl.audit, auditfp, 0);
audit_release (ctrl.audit);
ctrl.audit = NULL;
es_fclose (auditfp);
}
/* cleanup */ /* cleanup */
gpgsm_release_certlist (recplist); gpgsm_release_certlist (recplist);

View File

@ -152,6 +152,10 @@ struct server_control_s
struct server_local_s *server_local; struct server_local_s *server_local;
audit_ctx_t audit; /* NULL or a context for the audit subsystem. */ audit_ctx_t audit; /* NULL or a context for the audit subsystem. */
int agent_seen; /* Flag indicating that the gpg-agent has been
accessed. */
int dirmngr_seen; /* Flag indicating that the dirmngr has been
accessed. */
int with_colons; /* Use column delimited output format */ int with_colons; /* Use column delimited output format */
int with_chain; /* Include the certifying certs in a listing */ int with_chain; /* Include the certifying certs in a listing */

View File

@ -366,7 +366,14 @@ cmd_recipient (assuan_context_t ctx, char *line)
ctrl_t ctrl = assuan_get_pointer (ctx); ctrl_t ctrl = assuan_get_pointer (ctx);
int rc; int rc;
rc = gpgsm_add_to_certlist (ctrl, line, 0, &ctrl->server_local->recplist, 0); if (!ctrl->audit)
rc = start_audit_session (ctrl);
else
rc = 0;
if (!rc)
rc = gpgsm_add_to_certlist (ctrl, line, 0,
&ctrl->server_local->recplist, 0);
if (rc) if (rc)
{ {
gpg_err_code_t r = gpg_err_code (rc); gpg_err_code_t r = gpg_err_code (rc);
@ -477,6 +484,8 @@ cmd_encrypt (assuan_context_t ctx, char *line)
rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert, rc = gpgsm_add_cert_to_certlist (ctrl, cl->cert,
&ctrl->server_local->recplist, 1); &ctrl->server_local->recplist, 1);
} }
if (!rc)
rc = ctrl->audit? 0 : start_audit_session (ctrl);
if (!rc) if (!rc)
rc = gpgsm_encrypt (assuan_get_pointer (ctx), rc = gpgsm_encrypt (assuan_get_pointer (ctx),
ctrl->server_local->recplist, ctrl->server_local->recplist,
@ -492,6 +501,7 @@ cmd_encrypt (assuan_context_t ctx, char *line)
return rc; return rc;
} }
/* DECRYPT /* DECRYPT
This performs the decrypt operation after doing some check on the This performs the decrypt operation after doing some check on the
@ -517,7 +527,10 @@ cmd_decrypt (assuan_context_t ctx, char *line)
out_fp = fdopen (dup(out_fd), "w"); out_fp = fdopen (dup(out_fd), "w");
if (!out_fp) if (!out_fp)
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed"); return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
rc = start_audit_session (ctrl);
if (!rc)
rc = gpgsm_decrypt (ctrl, inp_fd, out_fp);
fclose (out_fp); fclose (out_fp);
/* close and reset the fd */ /* close and reset the fd */
@ -600,8 +613,10 @@ cmd_sign (assuan_context_t ctx, char *line)
if (!out_fp) if (!out_fp)
return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed"); return set_error (GPG_ERR_ASS_GENERAL, "fdopen() failed");
rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist, rc = start_audit_session (ctrl);
inp_fd, detached, out_fp); if (!rc)
rc = gpgsm_sign (assuan_get_pointer (ctx), ctrl->server_local->signerlist,
inp_fd, detached, out_fp);
fclose (out_fp); fclose (out_fp);
/* close and reset the fd */ /* close and reset the fd */