[svn] GnuPG - r5359 - in trunk: agent common dirmngr doc g10 sm
svn author wk
cvs at cvs.gnupg.org
Thu Jun 17 17:44:47 CEST 2010
Author: wk
Date: 2010-06-17 17:44:44 +0200 (Thu, 17 Jun 2010)
New Revision: 5359
Added:
trunk/sm/minip12.c
trunk/sm/minip12.h
Removed:
trunk/agent/minip12.c
trunk/agent/minip12.h
Modified:
trunk/agent/ChangeLog
trunk/agent/Makefile.am
trunk/agent/agent.h
trunk/agent/command.c
trunk/agent/findkey.c
trunk/agent/genkey.c
trunk/agent/preset-passphrase.c
trunk/agent/protect-tool.c
trunk/agent/protect.c
trunk/common/ChangeLog
trunk/common/membuf.c
trunk/common/sexputil.c
trunk/common/util.h
trunk/dirmngr/http.c
trunk/doc/dirmngr.texi
trunk/g10/ChangeLog
trunk/g10/gpg.c
trunk/sm/ChangeLog
trunk/sm/Makefile.am
trunk/sm/call-agent.c
trunk/sm/gpgsm.h
trunk/sm/import.c
Log:
Avoid using the protect-tool to import pkcs#12.
[The diff below has been truncated]
Modified: trunk/agent/ChangeLog
===================================================================
--- trunk/agent/ChangeLog 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/ChangeLog 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1,3 +1,29 @@
+2010-06-15 Werner Koch <wk at g10code.com>
+
+ * command.c (cmd_keywrap_key, cmd_import_key): New.
+
+ * genkey.c (agent_genkey, agent_protect_and_store): Factor common
+ code out to...
+ (agent_ask_new_passphrase): .. new.
+
+ * findkey.c (agent_write_private_key): Return GPG_ERR_EEXIST
+ instead of GPG_ERR_GENERAL.
+
+2010-06-14 Werner Koch <wk at g10code.com>
+
+ * protect-tool.c: Remove commands --p12-import and --p12-export.
+ * minip12.c, minip12.h: Move to ../sm.
+ * Makefile.am (gpg_protect_tool_SOURCES): Remove them.
+ * preset-passphrase.c: Remove unneeded minip12.h.
+
+ * command.c (cmd_keywrap_key): New.
+
+ * command.c (leave_cmd): New.
+ (cmd_istrusted, cmd_listtrusted, cmd_marktrusted, cmd_pksign)
+ (cmd_pkdecrypt, cmd_genkey, cmd_readkey, cmd_keyinfo)
+ (cmd_get_passphrase, cmd_get_confirmation, cmd_learn)
+ (cmd_passwd, cmd_preset_passphrase, cmd_getval, cmd_putval): Use it.
+
2010-05-12 Werner Koch <wk at g10code.com>
* preset-passphrase.c (forget_passphrase): Actually implement
Modified: trunk/common/ChangeLog
===================================================================
--- trunk/common/ChangeLog 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/common/ChangeLog 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1,3 +1,11 @@
+2010-06-17 Werner Koch <wk at g10code.com>
+
+ * sexputil.c (make_canon_sexp_pad): New.
+
+2010-06-14 Werner Koch <wk at g10code.com>
+
+ * membuf.c (put_membuf): Add shortcut for !LEN.
+
2010-06-11 Marcus Brinkmann <marcus at g10code.de>
* sysutils.c (translate_sys2libc_fd): Revert last change.
Modified: trunk/g10/ChangeLog
===================================================================
--- trunk/g10/ChangeLog 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/g10/ChangeLog 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1,3 +1,8 @@
+2010-06-17 Werner Koch <wk at g10code.com>
+
+ * gpg.c (main): Use CAST5 as default s2k algo. The macro
+ USE_CAST5 was only used with GnuPG 1.x.
+
2010-06-07 Werner Koch <wk at g10code.com>
* cpr.c: Use estream for status output.
Modified: trunk/sm/ChangeLog
===================================================================
--- trunk/sm/ChangeLog 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/sm/ChangeLog 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1,3 +1,19 @@
+2010-06-17 Werner Koch <wk at g10code.com>
+
+ * import.c (parse_p12): Remove arg retfp. Use the agent's new
+ import command.
+ (import_one): Adjust call to pkcs12.
+ (store_cert_cb, rsa_key_check): New.
+ (popen_protect_tool): Remove.
+ * minip12.c (parse_bag_encrypted_data, p12_parse): Add arg
+ R_BADPASS.
+ * call-agent.c (gpgsm_agent_ask_passphrase): New.
+ (gpgsm_agent_keywrap_key): New.
+ (struct import_key_parm_s): New.
+ (gpgsm_agent_import_key): New.
+ * minip12.c, minip12.h: Move from ../agent/.
+ * Makefile.am (gpgsm_SOURCES): Add them.
+
2010-06-11 Marcus Brinkmann <marcus at g10code.de>
* server.c (cmd_message) [HAVE_W32CE_SYSTEM]: Finish pipe.
Modified: trunk/agent/Makefile.am
===================================================================
--- trunk/agent/Makefile.am 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/Makefile.am 2010-06-17 15:44:44 UTC (rev 5359)
@@ -79,8 +79,7 @@
gpg_protect_tool_SOURCES = \
protect-tool.c \
- protect.c \
- minip12.c minip12.h
+ protect.c
gpg_protect_tool_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS)
gpg_protect_tool_LDADD = $(common_libs) $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) \
Modified: trunk/agent/agent.h
===================================================================
--- trunk/agent/agent.h 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/agent.h 2010-06-17 15:44:44 UTC (rev 5359)
@@ -284,6 +284,8 @@
/*-- genkey.c --*/
int check_passphrase_constraints (ctrl_t ctrl, const char *pw, int silent);
+gpg_error_t agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
+ char **r_passphrase);
int agent_genkey (ctrl_t ctrl,
const char *keyparam, size_t keyparmlen, membuf_t *outbuf);
int agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey);
Modified: trunk/agent/command.c
===================================================================
--- trunk/agent/command.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/command.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -38,10 +38,14 @@
#include <assuan.h>
#include "i18n.h"
-/* maximum allowed size of the inquired ciphertext */
+/* Maximum allowed size of the inquired ciphertext. */
#define MAXLEN_CIPHERTEXT 4096
-/* maximum allowed size of the key parameters */
+/* Maximum allowed size of the key parameters. */
#define MAXLEN_KEYPARAM 1024
+/* Maximum allowed size of key data as used in inquiries (bytes). */
+#define MAXLEN_KEYDATA 4096
+/* The size of the import/export KEK key (in bytes). */
+#define KEYWRAP_KEYSIZE (128/8)
#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
@@ -63,6 +67,8 @@
the end of this session. */
int allow_pinentry_notify; /* Set if pinentry notifications should
be done. */
+ void *import_key; /* Malloced KEK for the import_key command. */
+ void *export_key; /* Malloced KEK for the export_key command. */
};
@@ -340,6 +346,26 @@
}
+/* Helper to print a message while leaving a command. */
+static gpg_error_t
+leave_cmd (assuan_context_t ctx, gpg_error_t err)
+{
+ if (err)
+ {
+ const char *name = assuan_get_command_name (ctx);
+ if (!name)
+ name = "?";
+ if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
+ log_error ("command '%s' failed: %s\n", name,
+ gpg_strerror (err));
+ else
+ log_error ("command '%s' failed: %s <%s>\n", name,
+ gpg_strerror (err), gpg_strsource (err));
+ }
+ return err;
+}
+
+
static const char hlp_geteventcounter[] =
"GETEVENTCOUNTER\n"
@@ -432,10 +458,7 @@
else if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF )
return gpg_error (GPG_ERR_NOT_TRUSTED);
else
- {
- log_error ("command is_trusted failed: %s\n", gpg_strerror (rc));
- return rc;
- }
+ return leave_cmd (ctx, rc);
}
@@ -451,9 +474,7 @@
(void)line;
rc = agent_listtrusted (ctx);
- if (rc)
- log_error ("command listtrusted failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -494,9 +515,7 @@
p++;
rc = agent_marktrusted (ctrl, p, fpr, flag);
- if (rc)
- log_error ("command marktrusted failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -695,11 +714,9 @@
clear_outbuf (&outbuf);
else
rc = write_and_clear_outbuf (ctx, &outbuf);
- if (rc)
- log_error ("command pksign failed: %s\n", gpg_strerror (rc));
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -734,11 +751,9 @@
clear_outbuf (&outbuf);
else
rc = write_and_clear_outbuf (ctx, &outbuf);
- if (rc)
- log_error ("command pkdecrypt failed: %s\n", gpg_strerror (rc));
xfree (ctrl->server_local->keydesc);
ctrl->server_local->keydesc = NULL;
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -780,9 +795,7 @@
clear_outbuf (&outbuf);
else
rc = write_and_clear_outbuf (ctx, &outbuf);
- if (rc)
- log_error ("command genkey failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -825,9 +838,7 @@
gcry_sexp_release (s_pkey);
}
- if (rc)
- log_error ("command readkey failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -967,7 +978,7 @@
if (dir)
closedir (dir);
if (err && gpg_err_code (err) != GPG_ERR_NOT_FOUND)
- log_error ("command keyinfo failed: %s\n", gpg_strerror (err));
+ leave_cmd (ctx, err);
return err;
}
@@ -1167,9 +1178,7 @@
}
}
- if (rc)
- log_error ("command get_passphrase failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1240,9 +1249,7 @@
plus_to_blank (desc);
rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
- if (rc)
- log_error ("command get_confirmation failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1259,9 +1266,7 @@
int rc;
rc = agent_handle_learn (ctrl, has_option (line, "--send")? ctx : NULL);
- if (rc)
- log_error ("command learn failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1304,9 +1309,7 @@
leave:
gcry_sexp_release (s_skey);
xfree (shadow_info);
- if (rc)
- log_error ("command passwd failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1371,10 +1374,7 @@
if (!rc)
rc = agent_put_cache (grip_clear, CACHE_MODE_ANY, passphrase, ttl);
- if (rc)
- log_error ("command preset_passphrase failed: %s\n", gpg_strerror (rc));
-
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1397,6 +1397,186 @@
+static const char hlp_keywrap_key[] =
+ "KEYWRAP_KEY [--clear] <mode>\n"
+ "\n"
+ "Return a key to wrap another key. For now the key is returned\n"
+ "verbatim and and thus makes not much sense because an eavesdropper on\n"
+ "the gpg-agent connection will see the key as well as the wrapped key.\n"
+ "However, this function may either be equipped with a public key\n"
+ "mechanism or not used at all if the key is a pre-shared key. In any\n"
+ "case wrapping the import and export of keys is a requirement for\n"
+ "certain cryptographic validations and thus useful. The key persists\n"
+ "a RESET command but may be cleared using the option --clear.\n"
+ "\n"
+ "Supported modes are:\n"
+ " --import - Return a key to import a key into gpg-agent\n"
+ " --export - Return a key to export a key from gpg-agent";
+static gpg_error_t
+cmd_keywrap_key (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err = 0;
+ int clearopt = has_option (line, "--clear");
+
+
+ assuan_begin_confidential (ctx);
+ if (has_option (line, "--import"))
+ {
+ xfree (ctrl->server_local->import_key);
+ if (clearopt)
+ ctrl->server_local->import_key = NULL;
+ else if (!(ctrl->server_local->import_key =
+ gcry_random_bytes (KEYWRAP_KEYSIZE, GCRY_STRONG_RANDOM)))
+ err = gpg_error_from_syserror ();
+ else
+ err = assuan_send_data (ctx, ctrl->server_local->import_key,
+ KEYWRAP_KEYSIZE);
+ }
+ else if (has_option (line, "--export"))
+ {
+ xfree (ctrl->server_local->export_key);
+ if (clearopt)
+ ctrl->server_local->export_key = NULL;
+ else if (!(ctrl->server_local->export_key =
+ gcry_random_bytes (KEYWRAP_KEYSIZE, GCRY_STRONG_RANDOM)))
+ err = gpg_error_from_syserror ();
+ else
+ err = assuan_send_data (ctx, ctrl->server_local->export_key,
+ KEYWRAP_KEYSIZE);
+ }
+ else
+ err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for MODE");
+ assuan_end_confidential (ctx);
+
+ return leave_cmd (ctx, err);
+}
+
+
+
+static const char hlp_import_key[] =
+ "IMPORT_KEY\n"
+ "\n"
+ "Import a secret key into the key store. The key is expected to be\n"
+ "encrypted using the current session's key wrapping key (cf. command\n"
+ "KEYWRAP_KEY) using the AESWRAP-128 algorithm. This function takes\n"
+ "no arguments but uses the inquiry \"KEYDATA\" to ask for the actual\n"
+ "key data. The unwrapped key must be a canonical S-expression.";
+static gpg_error_t
+cmd_import_key (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err;
+ unsigned char *wrappedkey = NULL;
+ size_t wrappedkeylen;
+ gcry_cipher_hd_t cipherhd = NULL;
+ unsigned char *key = NULL;
+ size_t keylen, realkeylen;
+ char *passphrase = NULL;
+ unsigned char *finalkey = NULL;
+ size_t finalkeylen;
+ unsigned char grip[20];
+
+ (void)line;
+
+ if (!ctrl->server_local->import_key)
+ {
+ err = gpg_error (GPG_ERR_BAD_KEY);
+ goto leave;
+ }
+
+ assuan_begin_confidential (ctx);
+ err = assuan_inquire (ctx, "KEYDATA",
+ &wrappedkey, &wrappedkeylen, MAXLEN_KEYDATA);
+ assuan_end_confidential (ctx);
+ if (err)
+ goto leave;
+ if (wrappedkeylen < 24)
+ {
+ err = gpg_error (GPG_ERR_INV_LENGTH);
+ goto leave;
+ }
+ keylen = wrappedkeylen - 8;
+ key = xtrymalloc_secure (keylen);
+ if (!key)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
+ GCRY_CIPHER_MODE_AESWRAP, 0);
+ if (err)
+ goto leave;
+ err = gcry_cipher_setkey (cipherhd,
+ ctrl->server_local->import_key, KEYWRAP_KEYSIZE);
+ if (err)
+ goto leave;
+ err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen);
+ if (err)
+ goto leave;
+ gcry_cipher_close (cipherhd);
+ cipherhd = NULL;
+ xfree (wrappedkey);
+ wrappedkey = NULL;
+
+ realkeylen = gcry_sexp_canon_len (key, keylen, NULL, &err);
+ if (!realkeylen)
+ goto leave; /* Invalid canonical encoded S-expression. */
+
+ err = keygrip_from_canon_sexp (key, realkeylen, grip);
+ if (err)
+ goto leave;
+
+ if (!agent_key_available (grip))
+ {
+ err = gpg_error (GPG_ERR_EEXIST);
+ goto leave;
+ }
+
+ err = agent_ask_new_passphrase
+ (ctrl, _("Please enter the passphrase to protect the "
+ "imported object within the GnuPG system."),
+ &passphrase);
+ if (err)
+ goto leave;
+
+ if (passphrase)
+ {
+ err = agent_protect (key, passphrase, &finalkey, &finalkeylen);
+ if (!err)
+ err = agent_write_private_key (grip, finalkey, finalkeylen, 0);
+ }
+ else
+ err = agent_write_private_key (grip, key, realkeylen, 0);
+
+ leave:
+ xfree (finalkey);
+ xfree (passphrase);
+ xfree (key);
+ gcry_cipher_close (cipherhd);
+ xfree (wrappedkey);
+ return leave_cmd (ctx, err);
+}
+
+
+
+static const char hlp_export_key[] =
+ "EXPORT_KEY\n"
+ "\n";
+static gpg_error_t
+cmd_export_key (assuan_context_t ctx, char *line)
+{
+ gpg_error_t err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+
+ /* leave: */
+ return leave_cmd (ctx, err);
+}
+
+
+
+
static const char hlp_getval[] =
"GETVAL <key>\n"
"\n"
@@ -1435,9 +1615,7 @@
else
return gpg_error (GPG_ERR_NO_DATA);
- if (rc)
- log_error ("command getval failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1520,9 +1698,7 @@
}
}
- if (rc)
- log_error ("command putval failed: %s\n", gpg_strerror (rc));
- return rc;
+ return leave_cmd (ctx, rc);
}
@@ -1641,7 +1817,7 @@
" std_session_env - List the standard session environment.\n"
" std_startup_env - List the standard startup environment.\n"
" cmd_has_option\n"
- " - Returns OK if the command CMD implements the option OPT.";
+ " - Returns OK if the command CMD implements the option OPT\n.";
static gpg_error_t
cmd_getinfo (assuan_context_t ctx, char *line)
{
@@ -1910,6 +2086,9 @@
{ "INPUT", NULL },
{ "OUTPUT", NULL },
{ "SCD", cmd_scd, hlp_scd },
+ { "KEYWRAP_KEY", cmd_keywrap_key, hlp_keywrap_key },
+ { "IMPORT_KEY", cmd_import_key, hlp_import_key },
+ { "EXPORT_KEY", cmd_export_key, hlp_export_key },
{ "GETVAL", cmd_getval, hlp_getval },
{ "PUTVAL", cmd_putval, hlp_putval },
{ "UPDATESTARTUPTTY", cmd_updatestartuptty, hlp_updatestartuptty },
@@ -2021,6 +2200,9 @@
/* Cleanup. */
assuan_release (ctx);
+ xfree (ctrl->server_local->keydesc);
+ xfree (ctrl->server_local->import_key);
+ xfree (ctrl->server_local->export_key);
if (ctrl->server_local->stopme)
agent_exit (0);
xfree (ctrl->server_local);
Modified: trunk/agent/findkey.c
===================================================================
--- trunk/agent/findkey.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/findkey.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -69,7 +69,7 @@
{
log_error ("secret key file `%s' already exists\n", fname);
xfree (fname);
- return gpg_error (GPG_ERR_GENERAL);
+ return gpg_error (GPG_ERR_EEXIST);
}
/* FIXME: On POSIX systems we used include S_IRGRP as well. */
@@ -883,8 +883,8 @@
-/* Return the secret key as an S-Exp after locating it using the grip.
- Returns NULL if key is not available. 0 = key is available */
+/* Check whether the the secret key identified by GRIP is available.
+ Returns 0 is the key is available. */
int
agent_key_available (const unsigned char *grip)
{
Modified: trunk/agent/genkey.c
===================================================================
--- trunk/agent/genkey.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/genkey.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1,5 +1,5 @@
/* genkey.c - Generate a keypair
- * Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
+ * Copyright (C) 2002, 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -286,7 +286,70 @@
}
+/* Ask the user for a new passphrase using PROMPT. On success the
+ function returns 0 and store the passphrase at R_PASSPHRASE; if the
+ user opted not to use a passphrase NULL will be stored there. The
+ user needs to free the returned string. In case of an error and
+ error code is returned and NULL stored at R_PASSPHRASE. */
+gpg_error_t
+agent_ask_new_passphrase (ctrl_t ctrl, const char *prompt,
+ char **r_passphrase)
+{
+ gpg_error_t err;
+ const char *text1 = prompt;
+ const char *text2 = _("Please re-enter this passphrase");
+ const char *initial_errtext = NULL;
+ struct pin_entry_info_s *pi, *pi2;
+
+ *r_passphrase = NULL;
+ pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
+ pi2 = pi + (sizeof *pi + 100);
+ pi->max_length = 100;
+ pi->max_tries = 3;
+ pi->with_qualitybar = 1;
+ pi2->max_length = 100;
+ pi2->max_tries = 3;
+ pi2->check_cb = reenter_compare_cb;
+ pi2->check_cb_arg = pi->pin;
+
+ next_try:
+ err = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
+ initial_errtext = NULL;
+ if (!err)
+ {
+ if (check_passphrase_constraints (ctrl, pi->pin, 0))
+ {
+ pi->failed_tries = 0;
+ pi2->failed_tries = 0;
+ goto next_try;
+ }
+ /* Unless the passphrase is empty, ask to confirm it. */
+ if (pi->pin && *pi->pin)
+ {
+ err = agent_askpin (ctrl, text2, NULL, NULL, pi2);
+ if (err == -1)
+ { /* The re-entered one did not match and the user did not
+ hit cancel. */
+ initial_errtext = _("does not match - try again");
+ goto next_try;
+ }
+ }
+ }
+
+ if (!err && *pi->pin)
+ {
+ /* User wants a passphrase. */
+ *r_passphrase = xtrystrdup (pi->pin);
+ if (!*r_passphrase)
+ err = gpg_error_from_syserror ();
+ }
+ xfree (pi);
+ return err;
+}
+
+
+
/* Generate a new keypair according to the parameters given in
KEYPARAM */
int
@@ -294,7 +357,7 @@
membuf_t *outbuf)
{
gcry_sexp_t s_keyparam, s_key, s_private, s_public;
- struct pin_entry_info_s *pi, *pi2;
+ char *passphrase = NULL;
int rc;
size_t len;
char *buf;
@@ -307,63 +370,19 @@
}
/* Get the passphrase now, cause key generation may take a while. */
- {
- const char *text1 = _("Please enter the passphrase to%0A"
- "to protect your new key");
- const char *text2 = _("Please re-enter this passphrase");
- const char *initial_errtext = NULL;
+ rc = agent_ask_new_passphrase (ctrl,
+ _("Please enter the passphrase to%0A"
+ "to protect your new key"),
+ &passphrase);
+ if (rc)
+ return rc;
- pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
- pi2 = pi + (sizeof *pi + 100);
- pi->max_length = 100;
- pi->max_tries = 3;
- pi->with_qualitybar = 1;
- pi2->max_length = 100;
- pi2->max_tries = 3;
- pi2->check_cb = reenter_compare_cb;
- pi2->check_cb_arg = pi->pin;
-
- next_try:
- rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
- initial_errtext = NULL;
- if (!rc)
- {
- if (check_passphrase_constraints (ctrl, pi->pin, 0))
- {
- pi->failed_tries = 0;
- pi2->failed_tries = 0;
- goto next_try;
- }
- if (pi->pin && *pi->pin)
- {
- rc = agent_askpin (ctrl, text2, NULL, NULL, pi2);
- if (rc == -1)
- { /* The re-entered one did not match and the user did not
- hit cancel. */
- initial_errtext = _("does not match - try again");
- goto next_try;
- }
- }
- }
- if (rc)
- {
- xfree (pi);
- return rc;
- }
-
- if (!*pi->pin)
- {
- xfree (pi);
- pi = NULL; /* User does not want a passphrase. */
- }
- }
-
rc = gcry_pk_genkey (&s_key, s_keyparam );
gcry_sexp_release (s_keyparam);
if (rc)
{
log_error ("key generation failed: %s\n", gpg_strerror (rc));
- xfree (pi);
+ xfree (passphrase);
return rc;
}
@@ -373,7 +392,7 @@
{
log_error ("key generation failed: invalid return value\n");
gcry_sexp_release (s_key);
- xfree (pi);
+ xfree (passphrase);
return gpg_error (GPG_ERR_INV_DATA);
}
s_public = gcry_sexp_find_token (s_key, "public-key", 0);
@@ -382,7 +401,7 @@
log_error ("key generation failed: invalid return value\n");
gcry_sexp_release (s_private);
gcry_sexp_release (s_key);
- xfree (pi);
+ xfree (passphrase);
return gpg_error (GPG_ERR_INV_DATA);
}
gcry_sexp_release (s_key); s_key = NULL;
@@ -390,8 +409,9 @@
/* store the secret key */
if (DBG_CRYPTO)
log_debug ("storing private key\n");
- rc = store_key (s_private, pi? pi->pin:NULL, 0);
- xfree (pi); pi = NULL;
+ rc = store_key (s_private, passphrase, 0);
+ xfree (passphrase);
+ passphrase = NULL;
gcry_sexp_release (s_private);
if (rc)
{
@@ -423,65 +443,20 @@
-/* Apply a new passpahrse to the key S_SKEY and store it. */
+/* Apply a new passphrase to the key S_SKEY and store it. */
int
agent_protect_and_store (ctrl_t ctrl, gcry_sexp_t s_skey)
{
- struct pin_entry_info_s *pi, *pi2;
int rc;
+ char *passphrase;
- {
- const char *text1 = _("Please enter the new passphrase");
- const char *text2 = _("Please re-enter this passphrase");
- const char *initial_errtext = NULL;
-
- pi = gcry_calloc_secure (2, sizeof (*pi) + 100);
- pi2 = pi + (sizeof *pi + 100);
- pi->max_length = 100;
- pi->max_tries = 3;
- pi->with_qualitybar = 1;
- pi2->max_length = 100;
- pi2->max_tries = 3;
- pi2->check_cb = reenter_compare_cb;
- pi2->check_cb_arg = pi->pin;
-
- next_try:
- rc = agent_askpin (ctrl, text1, NULL, initial_errtext, pi);
- initial_errtext = NULL;
- if (!rc)
- {
- if (check_passphrase_constraints (ctrl, pi->pin, 0))
- {
- pi->failed_tries = 0;
- pi2->failed_tries = 0;
- goto next_try;
- }
- /* Unless the passphrase is empty, ask to confirm it. */
- if (pi->pin && *pi->pin)
- {
- rc = agent_askpin (ctrl, text2, NULL, NULL, pi2);
- if (rc == -1)
- { /* The re-entered one did not match and the user did not
- hit cancel. */
- initial_errtext = _("does not match - try again");
- goto next_try;
- }
- }
- }
- if (rc)
- {
- xfree (pi);
- return rc;
- }
-
- if (!*pi->pin)
- {
- xfree (pi);
- pi = NULL; /* User does not want a passphrase. */
- }
- }
-
- rc = store_key (s_skey, pi? pi->pin:NULL, 1);
- xfree (pi);
+ rc = agent_ask_new_passphrase (ctrl,
+ _("Please enter the new passphrase"),
+ &passphrase);
+ if (!rc)
+ {
+ rc = store_key (s_skey, passphrase, 1);
+ xfree (passphrase);
+ }
return rc;
}
Modified: trunk/agent/preset-passphrase.c
===================================================================
--- trunk/agent/preset-passphrase.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/preset-passphrase.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -43,7 +43,6 @@
#define JNLIB_NEED_LOG_LOGV
#include "agent.h"
-#include "minip12.h"
#include "simple-pwquery.h"
#include "i18n.h"
#include "sysutils.h"
Modified: trunk/agent/protect-tool.c
===================================================================
--- trunk/agent/protect-tool.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/protect-tool.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -40,7 +40,6 @@
#define JNLIB_NEED_LOG_LOGV
#include "agent.h"
-#include "minip12.h"
#include "i18n.h"
#include "get-passphrase.h"
#include "sysutils.h"
@@ -63,8 +62,6 @@
oS2Kcalibration,
oCanonical,
- oP12Import,
- oP12Export,
oP12Charset,
oStore,
oForce,
@@ -116,11 +113,6 @@
ARGPARSE_c (oShadow, "shadow", "create a shadow entry for a public key"),
ARGPARSE_c (oShowShadowInfo, "show-shadow-info", "return the shadow info"),
ARGPARSE_c (oShowKeygrip, "show-keygrip", "show the \"keygrip\""),
- ARGPARSE_c (oP12Import, "p12-import",
- "import a pkcs#12 encoded private key"),
- ARGPARSE_c (oP12Export, "p12-export",
- "export a private key pkcs#12 encoded"),
-
ARGPARSE_c (oS2Kcalibration, "s2k-calibration", "@"),
ARGPARSE_group (301, N_("@\nOptions:\n ")),
@@ -635,7 +627,7 @@
return err? -1:0;
}
-
+#if 0
/* A callback used by p12_parse to return a certificate. */
static void
import_p12_cert_cb (void *opaque, const unsigned char *cert, size_t certlen)
@@ -793,6 +785,7 @@
xfree (result);
}
+#endif
@@ -865,6 +858,7 @@
}
+#if 0
static void
export_p12_file (const char *fname)
{
@@ -1009,6 +1003,7 @@
fwrite (key, keylen, 1, stdout);
xfree (key);
}
+#endif
@@ -1059,8 +1054,6 @@
case oShadow: cmd = oShadow; break;
case oShowShadowInfo: cmd = oShowShadowInfo; break;
case oShowKeygrip: cmd = oShowKeygrip; break;
- case oP12Import: cmd = oP12Import; break;
- case oP12Export: cmd = oP12Export; break;
case oP12Charset: opt_p12_charset = pargs.r.ret_str; break;
case oS2Kcalibration: cmd = oS2Kcalibration; break;
@@ -1105,10 +1098,6 @@
show_shadow_info (fname);
else if (cmd == oShowKeygrip)
show_keygrip (fname);
- else if (cmd == oP12Import)
- import_p12_file (fname);
- else if (cmd == oP12Export)
- export_p12_file (fname);
else if (cmd == oS2Kcalibration)
{
if (!opt.verbose)
Modified: trunk/agent/protect.c
===================================================================
--- trunk/agent/protect.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/agent/protect.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -415,7 +415,7 @@
unsigned char *p;
gcry_md_hd_t md;
- /* Create an S-expression with the procted-at timestamp. */
+ /* Create an S-expression with the protected-at timestamp. */
memcpy (timestamp_exp, "(12:protected-at15:", 19);
gnupg_get_isotime (timestamp_exp+19);
timestamp_exp[19+15] = ')';
Modified: trunk/common/membuf.c
===================================================================
--- trunk/common/membuf.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/common/membuf.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -59,7 +59,7 @@
void
put_membuf (membuf_t *mb, const void *buf, size_t len)
{
- if (mb->out_of_core)
+ if (mb->out_of_core || !len)
return;
if (mb->len + len >= mb->size)
Modified: trunk/common/sexputil.c
===================================================================
--- trunk/common/sexputil.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/common/sexputil.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -36,7 +36,7 @@
#include "sexp-parse.h"
-/* Helper function to create a a canonical encoded S-expression from a
+/* Helper function to create a canonical encoded S-expression from a
Libgcrypt S-expression object. The function returns 0 on success
and the malloced canonical S-expression is stored at R_BUFFER and
the allocated length at R_BUFLEN. On error an error code is
@@ -71,6 +71,36 @@
}
+/* Same as make_canon_sexp but pad the buffer to multiple of 64
+ bits. */
+gpg_error_t
+make_canon_sexp_pad (gcry_sexp_t sexp,
+ unsigned char **r_buffer, size_t *r_buflen)
+{
+ size_t len;
+ unsigned char *buf;
+
+ *r_buffer = NULL;
+ if (r_buflen)
+ *r_buflen = 0;;
+
+ len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
+ if (!len)
+ return gpg_error (GPG_ERR_BUG);
+ len += (8 - len % 8) % 8;
+ buf = xtrycalloc (1, len);
+ if (!buf)
+ return gpg_error_from_syserror ();
+ if (!gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len))
+ return gpg_error (GPG_ERR_BUG);
+
+ *r_buffer = buf;
+ if (r_buflen)
+ *r_buflen = len;
+
+ return 0;
+}
+
/* Return the so called "keygrip" which is the SHA-1 hash of the
public key parameters expressed in a way depended on the algorithm.
Modified: trunk/common/util.h
===================================================================
--- trunk/common/util.h 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/common/util.h 2010-06-17 15:44:44 UTC (rev 5359)
@@ -146,6 +146,8 @@
/*-- sexputil.c */
gpg_error_t make_canon_sexp (gcry_sexp_t sexp,
unsigned char **r_buffer, size_t *r_buflen);
+gpg_error_t make_canon_sexp_pad (gcry_sexp_t sexp,
+ unsigned char **r_buffer, size_t *r_buflen);
gpg_error_t keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
unsigned char *grip);
int cmp_simple_canon_sexp (const unsigned char *a, const unsigned char *b);
Modified: trunk/dirmngr/http.c
===================================================================
--- trunk/dirmngr/http.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/dirmngr/http.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -38,6 +38,8 @@
an exit handler to cleanup the socket layer.
*/
+#warning Duplicated code with common/http.c
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
Modified: trunk/doc/dirmngr.texi
===================================================================
--- trunk/doc/dirmngr.texi 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/doc/dirmngr.texi 2010-06-17 15:44:44 UTC (rev 5359)
@@ -786,3 +786,254 @@
@end ifset
@include see-also-note.texi
+ at c
+ at c !!! UNDER CONSTRUCTION !!!
+ at c
+ at c
+ at c @section Verifying a Certificate
+ at c
+ at c There are several ways to request services from Dirmngr. Almost all of
+ at c them are done using the Assuan protocol. What we describe here is the
+ at c Assuan command CHECKCRL as used for example by the dirmnr-client tool if
+ at c invoked as
+ at c
+ at c @example
+ at c dirmngr-client foo.crt
+ at c @end example
+ at c
+ at c This command will send an Assuan request to an already running Dirmngr
+ at c instance. foo.crt is expected to be a standard X.509 certificate and
+ at c dirmngr will receive the Assuan command
+ at c
+ at c @example
+ at c CHECKCRL @var [{fingerprint}]
+ at c @end example
+ at c
+ at c @var{fingerprint} is optional and expected to be the SHA-1 has of the
+ at c DER encoding of the certificate under question. It is to be HEX
+ at c encoded. The rationale for sending the fingerprint is that it allows
+ at c dirmngr to reply immediatly if it has already cached such a request. If
+ at c this is not the case and no certificate has been found in dirmngr's
+ at c internal certificate storage, dirmngr will request the certificate using
+ at c the Assuan inquiry
+ at c
+ at c @example
+ at c INQUIRE TARGETCERT
+ at c @end example
+ at c
+ at c The caller (in our example dirmngr-client) is then expected to return
+ at c the certificate for the request (which should match @var{fingerprint})
+ at c as a binary blob.
+ at c
+ at c Dirmngr now passes control to @code{crl_cache_cert_isvalid}. This
+ at c function checks whether a CRL item exists for target certificate. These
+ at c CRL items are kept in a database of already loaded and verified CRLs.
+ at c This mechanism is called the CRL cache. Obviously timestamps are kept
+ at c there with each item to cope with the expiration date of the CRL. The
+ at c possible return values are: @code{0} to indicate that a valid CRL is
+ at c available for the certificate and the certificate itself is not listed
+ at c in this CRL, @code{GPG_ERR_CERT_REVOKED} to indicate that the certificate is
+ at c listed in the CRL or @code{GPG_ERR_NO_CRL_KNOWN} in cases where no CRL or no
+ at c information is available. The first two codes are immediatly returned to
+ at c the caller and the processing of this request has been done.
+ at c
+ at c Only the @code{GPG_ERR_NO_CRL_KNOWN} needs more attention: Dirmngr now
+ at c calls @code{clr_cache_reload_crl} and if this succeeds calls
+ at c @code{crl_cache_cert_isvald) once more. All further errors are
+ at c immediately returned to the caller.
+ at c
+ at c @code{crl_cache_reload_crl} is the actual heart of the CRL management.
+ at c It locates the corresponding CRL for the target certificate, reads and
+ at c verifies this CRL and stores it in the CRL cache. It works like this:
+ at c
+ at c * Loop over all crlDPs in the target certificate.
+ at c * If the crlDP is invalid immediately terminate the loop.
+ at c * Loop over all names in the current crlDP.
+ at c * If the URL scheme is unknown or not enabled
+ at c (--ignore-http-dp, --ignore-ldap-dp) continues with
+ at c the next name.
+ at c * @code{crl_fetch} is called to actually retrieve the CRL.
+ at c In case of problems this name is ignore and we continue with
+ at c the next name. Note that @code{crl_fetch} does only return
+ at c a descriptor for the CRL for further reading so does the CRL
+ at c does not yet end up in memory.
+ at c * @code{crl_cache_insert} is called with that descriptor to
+ at c actually read the CRL into the cache. See below for a
+ at c description of this function. If there is any error (e.g. read
+ at c problem, CRL not correctly signed or verification of signature
+ at c not possible), this descriptor is rejected and we continue
+ at c with the next name. If the CRL has been successfully loaded,
+ at c the loop is terminated.
+ at c * If no crlDP has been found in the previous loop use a default CRL.
+ at c Note, that if any crlDP has been found but loading of the CRL failed,
+ at c this condition is not true.
+ at c * Try to load a CRL from all configured servers (ldapservers.conf)
+ at c in turn. The first server returning a CRL is used.
+ at c * @code(crl_cache_insert) is then used to actually insert the CRL
+ at c into the cache. If this failed we give up immediatley without
+ at c checking the rest of the servers from the first step.
+ at c * Ready.
+ at c
+ at c
+ at c The @code{crl_cache_insert} function takes care of reading the bulk of
+ at c the CRL, parsing it and checking the signature. It works like this: A
+ at c new database file is created using a temporary file name. The CRL
+ at c parsing machinery is started and all items of the CRL are put into
+ at c this database file. At the end the issuer certificate of the CRL
+ at c needs to be retrieved. Three cases are to be distinguished:
+ at c
+ at c a) An authorityKeyIdentifier with an issuer and serialno exits: The
+ at c certificate is retrieved using @code{find_cert_bysn}. If
+ at c the certificate is in the certificate cache, it is directly
+ at c returned. Then the requester (i.e. the client who requested the
+ at c CRL check) is asked via the Assuan inquiry ``SENDCERT'' whether
+ at c he can provide this certificate. If this succeed the returned
+ at c certificate gets cached and returned. Note, that dirmngr does not
+ at c verify in any way whether the expected certificate is returned.
+ at c It is in the interest of the client to return a useful certificate
+ at c as otherwise the service request will fail due to a bad signature.
+ at c The last way to get the certificate is by looking it up at
+ at c external resources. This is done using the @code{ca_cert_fetch}
+ at c and @code{fetch_next_ksba_cert} and comparing the returned
+ at c certificate to match the requested issuer and seriano (This is
+ at c needed because the LDAP layer may return several certificates as
+ at c LDAP as no standard way to retrieve by serial number).
+ at c
+ at c b) An authorityKeyIdentifier with a key ID exists: The certificate is
+ at c retrieved using @code{find_cert_bysubject}. If the certificate is
+ at c in the certificate cache, it is directly returned. Then the
+ at c requester is asked via the Assuan inquiry ``SENDCERT_SKI'' whether
+ at c he can provide this certificate. If this succeed the returned
+ at c certificate gets cached and returned. Note, that dirmngr does not
+ at c verify in any way whether the expected certificate is returned.
+ at c It is in the interest of the client to return a useful certificate
+ at c as otherwise the service request will fail due to a bad signature.
+ at c The last way to get the certificate is by looking it up at
+ at c external resources. This is done using the @code{ca_cert_fetch}
+ at c and @code{fetch_next_ksba_cert} and comparing the returned
+ at c certificate to match the requested subject and key ID.
+ at c
+ at c c) No authorityKeyIdentifier exits: The certificate is retrieved
+ at c using @code{find_cert_bysubject} without the key ID argument. If
+ at c the certificate is in the certificate cache the first one with a
+ at c matching subject is is directly returned. Then the requester is
+ at c asked via the Assuan inquiry ``SENDCERT'' and an exact
+ at c specification of the subject whether he can
+ at c provide this certificate. If this succeed the returned
+ at c certificate gets cached and returned. Note, that dirmngr does not
+ at c verify in any way whether the expected certificate is returned.
+ at c It is in the interest of the client to return a useful certificate
+ at c as otherwise the service request will fail due to a bad signature.
+ at c The last way to get the certificate is by looking it up at
+ at c external resources. This is done using the @code{ca_cert_fetch}
+ at c and @code{fetch_next_ksba_cert} and comparing the returned
+ at c certificate to match the requested subject; the first certificate
+ at c with a matching subject is then returned.
+ at c
+ at c If no certificate was found, the function returns with the error
+ at c GPG_ERR_MISSING_CERT. Now the signature is verified. If this fails,
+ at c the erro is returned. On success the @code{validate_cert_chain} is
+ at c used to verify that the certificate is actually valid.
+ at c
+ at c Here we may encounter a recursive situation:
+ at c @code{validate_cert_chain} needs to look at other certificates and
+ at c also at CRLs to check whether tehse other certificates and well, the
+ at c CRL issuer certificate itself are not revoked. FIXME: We need to make
+ at c sure that @code{validate_cert_chain} does not try to lookup the CRL we
+ at c are currently processing. This would be a catch-22 and may indicate a
+ at c broken PKI. However, due to overlapping expiring times and imprecise
+ at c clocks thsi may actually happen.
+ at c
+ at c For historical reasons the Assuan command ISVALID is a bit different
+ at c to CHECKCRL but this is mainly due to different calling conventions.
+ at c In the end the same fucntionality is used, albeit hidden by a couple
+ at c of indirection and argument and result code mangling. It furthere
+ at c ingetrages OCSP checking depending on options are the way it is
+ at c called. GPGSM still uses this command but might eventuall switch over
+ at c to CHECKCRL and CHECKOCSP so that ISVALID can be retired.
+ at c
+ at c
+ at c @section Validating a certificate
+ at c
+ at c We describe here how the internal function @code{validate_cert_chain}
+ at c works. Note that mainly testing purposes this functionality may be
+ at c called directly using @cmd{dirmngr-client --validate @file{foo.crt}}.
+ at c
+ at c For backward compatibility this function returns success if Dirmngr is
+ at c not used as a system daemon. Thus not validating the certicates at
+ at c all. FIXME: This is definitely not correct and should be fixed ASAP.
+ at c
+ at c The function takes the target certificate and a mode argument as
+ at c parameters and returns an error code and optionally the closes
+ at c expiration time of all certificates in the chain.
+ at c
+ at c We first check that the certificate may be used for the requested
+ at c purpose (i.e. OCSP or CRL signing). If this is not the case
+ at c GPG_ERR_WRONG_KEY_USAGE is returned.
+ at c
+ at c The next step is to find the trust anchor (root certificate) and to
+ at c assemble the chain in memory: Starting with the target certificate,
+ at c the expiration time is checked against the current date, unknown
+ at c critical extensions are detected and certificate policies are matched
+ at c (We only allow 2.289.9.9 but I have no clue about that OID and from
+ at c where I got it - it does not even seem to be assigned - debug cruft?).
+ at c
+ at c Now if this certificate is a self-signed one, we have reached the
+ at c trust anchor. In this case we check that the signature is good, the
+ at c certificate is allowed to act as a CA, that it is a trusted one (by
+ at c checking whether it is has been put into the trusted-certs
+ at c configuration directory) and finally prepend into to our list
+ at c representing the certificate chain. This steps ends then.
+ at c
+ at c If it is not a self-signed certificate, we check that the chain won't
+ at c get too long (current limit is 100), if this is the case we terminate
+ at c with the error GPG_ERR_BAD_CERT_CHAIN.
+ at c
+ at c Now the issuer's certificate is looked up: If an
+ at c authorityKeyIdentifier is available, this one is used to locate the
+ at c certificate either using issuer and serialnumber or subject DN
+ at c (i.e. the issuer's DN) and the keyID. The functions
+ at c @code{find_cert_bysn) and @code{find_cert_bysubject} are used
+ at c respectively. The have already been described above under the
+ at c description of @code{crl_cache_insert}. If no certificate was found
+ at c or with no authorityKeyIdentifier, only the cache is consulted using
+ at c @code{get_cert_bysubject}. The latter is is done under the assumption
+ at c that a matching certificate has explicitly been put into the
+ at c certificate cache. If the issuer's certificate could not be found,
+ at c the validation terminates with the error code @code{GPG_ERR_MISSING_CERT}.
+ at c
+ at c If the issuer's certificate has been found, the signature of the
+ at c actual certificate is checked and in case this fails the error
+ at c #code{GPG_ERR_BAD_CERT_CHAIN} is returned. If the signature checks out, the
+ at c maximum cahin length of the issueing certificate is checked as well as
+ at c the capiblity of the certificate (i.e. whether he may be used for
+ at c certificate signing). Then the certificate is prepended to our list
+ at c representing the certificate chain. Finally the loop is continued now
+ at c with the issuer's certificate as the current certificate.
+ at c
+ at c After the end of the loop and if no error as been encountered
+ at c (i.e. the certificate chain has been assempled correctly), a check is
+ at c done whether any certificate expired or a critical policy has not been
+ at c met. In any of these cases the validation terminates with an
+ at c appropriate error.
+ at c
+ at c Finally the function @code{check_revocations} is called to verify no
+ at c certificate in the assempled chain has been revoked: This is an
+ at c recursive process because a CRL has to be checked for each certificate
+ at c in the chain except for the root certificate, of which we already know
+ at c that it is trusted and we avoid checking a CRL here due to common
+ at c setup problems and the assumption that a revoked root certifcate has
+ at c been removed from the list of trusted certificates.
+ at c
+ at c
+ at c
+ at c
+ at c @section Looking up certificates through LDAP.
+ at c
+ at c This describes the LDAP layer to retrieve certificates.
+ at c the functions @code{ca_cert_fetch} and @code{fetch_next_ksba_cert} are
+ at c used for this. The first one starts a search and the second one is
+ at c used to retrieve certificate after certificate.
+ at c
+
+
Modified: trunk/g10/gpg.c
===================================================================
--- trunk/g10/gpg.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/g10/gpg.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1976,11 +1976,7 @@
opt.compress_algo = -1; /* defaults to DEFAULT_COMPRESS_ALGO */
opt.s2k_mode = 3; /* iterated+salted */
opt.s2k_count = 0; /* Auto-calibrate when needed. */
-#ifdef USE_CAST5
opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
-#else
- opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
-#endif
opt.completes_needed = 1;
opt.marginals_needed = 3;
opt.max_cert_depth = 5;
Modified: trunk/sm/Makefile.am
===================================================================
--- trunk/sm/Makefile.am 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/sm/Makefile.am 2010-06-17 15:44:44 UTC (rev 5359)
@@ -49,6 +49,7 @@
delete.c \
certreqgen.c \
certreqgen-ui.c \
+ minip12.c minip12.h \
qualified.c
Modified: trunk/sm/call-agent.c
===================================================================
--- trunk/sm/call-agent.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/sm/call-agent.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -1,6 +1,6 @@
/* call-agent.c - Divert GPGSM operations to the agent
* Copyright (C) 2001, 2002, 2003, 2005, 2007,
- * 2008, 2009 Free Software Foundation, Inc.
+ * 2008, 2009, 2010 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
@@ -66,7 +66,15 @@
membuf_t *data;
};
+struct import_key_parm_s
+{
+ ctrl_t ctrl;
+ assuan_context_t ctx;
+ const void *key;
+ size_t keylen;
+};
+
/* Try to connect to the agent via socket or fork it off and work by
pipes. Handle the server's initial greeting */
@@ -1066,3 +1074,130 @@
return err;
}
+
+
+/* Ask for the passphrase (this is used for pkcs#12 import/export. On
+ success the caller needs to free the string stored at R_PASSPHRASE.
+ On error NULL will be stored at R_PASSPHRASE and an appropriate
+ error code returned. */
+gpg_error_t
+gpgsm_agent_ask_passphrase (ctrl_t ctrl, const char *desc_msg,
+ char **r_passphrase)
+{
+ gpg_error_t err;
+ char line[ASSUAN_LINELENGTH];
+ char *arg4 = NULL;
+ membuf_t data;
+
+ *r_passphrase = NULL;
+
+ err = start_agent (ctrl);
+ if (err)
+ return err;
+
+ if (desc_msg && *desc_msg && !(arg4 = percent_plus_escape (desc_msg)))
+ return gpg_error_from_syserror ();
+
+ snprintf (line, DIM(line)-1, "GET_PASSPHRASE --data -- X X X %s", arg4);
+ xfree (arg4);
+
+ init_membuf_secure (&data, 64);
+ err = assuan_transact (agent_ctx, line,
+ membuf_data_cb, &data,
+ default_inq_cb, NULL, NULL, NULL);
+
+ if (err)
+ xfree (get_membuf (&data, NULL));
+ else
+ {
+ put_membuf (&data, "", 1);
+ *r_passphrase = get_membuf (&data, NULL);
+ if (!*r_passphrase)
+ err = gpg_error_from_syserror ();
+ }
+ return err;
+}
+
+
+
+/* Retrieve a key encryption key from the agent. With FOREXPORT true
+ the key shall be use for export, with false for import. On success
+ the new key is stored at R_KEY and its length at R_KEKLEN. */
+gpg_error_t
+gpgsm_agent_keywrap_key (ctrl_t ctrl, int forexport,
+ void **r_kek, size_t *r_keklen)
+{
+ gpg_error_t err;
+ membuf_t data;
+ size_t len;
+ unsigned char *buf;
+ char line[ASSUAN_LINELENGTH];
+
+ *r_kek = NULL;
+ err = start_agent (ctrl);
+ if (err)
+ return err;
+
+ snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s",
+ forexport? "--export":"--import");
+
+ init_membuf_secure (&data, 64);
+ err = assuan_transact (agent_ctx, line,
+ membuf_data_cb, &data,
+ default_inq_cb, ctrl, NULL, NULL);
+ if (err)
+ {
+ xfree (get_membuf (&data, &len));
+ return err;
+ }
+ buf = get_membuf (&data, &len);
+ if (!buf)
+ return gpg_error_from_syserror ();
+ *r_kek = buf;
+ *r_keklen = len;
+ return 0;
+}
+
+
+
+
+/* Handle the inquiry for an IMPORT_KEY command. */
+static gpg_error_t
+inq_import_key_parms (void *opaque, const char *line)
+{
+ struct import_key_parm_s *parm = opaque;
+ gpg_error_t err;
+
+ if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
+ {
+ assuan_begin_confidential (parm->ctx);
+ err = assuan_send_data (parm->ctx, parm->key, parm->keylen);
+ assuan_end_confidential (parm->ctx);
+ }
+ else
+ err = default_inq_cb (parm->ctrl, line);
+
+ return err;
+}
+
+
+/* Call the agent to import a key into the agent. */
+gpg_error_t
+gpgsm_agent_import_key (ctrl_t ctrl, const void *key, size_t keylen)
+{
+ gpg_error_t err;
+ struct import_key_parm_s parm;
+
+ err = start_agent (ctrl);
+ if (err)
+ return err;
+
+ parm.ctrl = ctrl;
+ parm.ctx = agent_ctx;
+ parm.key = key;
+ parm.keylen = keylen;
+
+ err = assuan_transact (agent_ctx, "IMPORT_KEY",
+ NULL, NULL, inq_import_key_parms, &parm, NULL, NULL);
+ return err;
+}
Modified: trunk/sm/gpgsm.h
===================================================================
--- trunk/sm/gpgsm.h 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/sm/gpgsm.h 2010-06-17 15:44:44 UTC (rev 5359)
@@ -405,6 +405,12 @@
gpg_error_t gpgsm_agent_send_nop (ctrl_t ctrl);
gpg_error_t gpgsm_agent_keyinfo (ctrl_t ctrl, const char *hexkeygrip,
char **r_serialno);
+gpg_error_t gpgsm_agent_ask_passphrase (ctrl_t ctrl, const char *desc_msg,
+ char **r_passphrase);
+gpg_error_t gpgsm_agent_keywrap_key (ctrl_t ctrl, int forexport,
+ void **r_kek, size_t *r_keklen);
+gpg_error_t gpgsm_agent_import_key (ctrl_t ctrl,
+ const void *key, size_t keylen);
/*-- call-dirmngr.c --*/
int gpgsm_dirmngr_isvalid (ctrl_t ctrl,
Modified: trunk/sm/import.c
===================================================================
--- trunk/sm/import.c 2010-06-17 12:58:51 UTC (rev 5358)
+++ trunk/sm/import.c 2010-06-17 15:44:44 UTC (rev 5359)
@@ -35,8 +35,13 @@
#include "i18n.h"
#include "sysutils.h"
#include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
+#include "../common/membuf.h"
+#include "minip12.h"
+/* The arbitrary limit of one PKCS#12 object. */
+#define MAX_P12OBJ_SIZE 128 /*kb*/
+
struct stats_s {
unsigned long count;
unsigned long imported;
@@ -48,8 +53,19 @@
};
+struct rsa_secret_key_s
+{
+ gcry_mpi_t n; /* public modulus */
+ gcry_mpi_t e; /* public exponent */
+ gcry_mpi_t d; /* exponent */
+ gcry_mpi_t p; /* prime p. */
+ gcry_mpi_t q; /* prime q. */
+ gcry_mpi_t u; /* inverse of p mod q. */
+};
+
+
static gpg_error_t parse_p12 (ctrl_t ctrl, ksba_reader_t reader,
- estream_t *retfp, struct stats_s *stats);
+ struct stats_s *stats);
@@ -325,51 +341,11 @@
any = 1;
}
else if (ct == KSBA_CT_PKCS12)
- { /* This seems to be a pkcs12 message. We use an external
- tool to parse the message and to store the private keys.
- We need to use a another reader here to parse the
- certificate we included in the p12 file; then we continue
- to look for other pkcs12 files (works only if they are in
- PEM format. */
- estream_t certfp;
- Base64Context b64p12rdr;
- ksba_reader_t p12rdr;
-
- rc = parse_p12 (ctrl, reader, &certfp, stats);
+ {
+ /* This seems to be a pkcs12 message. */
+ rc = parse_p12 (ctrl, reader, stats);
if (!rc)
- {
More information about the Gnupg-commits
mailing list