1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-01 22:28:02 +02:00

Merge branch 'master' into key-storage-work

This commit is contained in:
Werner Koch 2013-02-12 19:17:42 +01:00
commit caddeef4a7
43 changed files with 6301 additions and 5133 deletions

9
NEWS
View File

@ -11,6 +11,15 @@ Noteworthy changes in version 2.1.0beta4 (unreleased)
* The hash algorithm is now printed for sig records in key listings. * The hash algorithm is now printed for sig records in key listings.
* New option --pinentry-mode for GPG.
* New option --enable-pinpad-varlen for scdaemon.
* Rename option --disable-pinpad for scdaemon (was: --disable-keypad).
* Better support fo CCID readers. Now, internal CCID driver supports
readers with no auto configuration feature.
Noteworthy changes in version 2.1.0beta3 (2011-12-20) Noteworthy changes in version 2.1.0beta3 (2011-12-20)
----------------------------------------------------- -----------------------------------------------------

View File

@ -34,6 +34,7 @@
#include "../common/membuf.h" #include "../common/membuf.h"
#include "../common/sysutils.h" /* (gnupg_fd_t) */ #include "../common/sysutils.h" /* (gnupg_fd_t) */
#include "../common/session-env.h" #include "../common/session-env.h"
#include "../common/shareddefs.h"
/* To convey some special hash algorithms we use algorithm numbers /* To convey some special hash algorithms we use algorithm numbers
reserved for application use. */ reserved for application use. */
@ -46,16 +47,6 @@
#define MAX_DIGEST_LEN 64 #define MAX_DIGEST_LEN 64
/* Values for the pinentry mode. */
typedef enum
{
PINENTRY_MODE_ASK = 0, /* Ask via pinentry (default). */
PINENTRY_MODE_CANCEL, /* Always return a cancel error. */
PINENTRY_MODE_ERROR, /* Return error code for no pinentry. */
PINENTRY_MODE_LOOPBACK,/* Use an inquiry to get the value. */
}
pinentry_mode_t;
/* A large struct name "opt" to keep global flags */ /* A large struct name "opt" to keep global flags */
struct struct
@ -421,6 +412,8 @@ int divert_pkdecrypt (ctrl_t ctrl,
char **r_buf, size_t *r_len); char **r_buf, size_t *r_len);
int divert_generic_cmd (ctrl_t ctrl, int divert_generic_cmd (ctrl_t ctrl,
const char *cmdline, void *assuan_context); const char *cmdline, void *assuan_context);
int divert_writekey (ctrl_t ctrl, int force, const char *serialno,
const char *id, const char *keydata, size_t keydatalen);
/*-- call-scd.c --*/ /*-- call-scd.c --*/
@ -454,6 +447,11 @@ int agent_card_pkdecrypt (ctrl_t ctrl,
int agent_card_readcert (ctrl_t ctrl, int agent_card_readcert (ctrl_t ctrl,
const char *id, char **r_buf, size_t *r_buflen); const char *id, char **r_buf, size_t *r_buflen);
int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf); int agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf);
int agent_card_writekey (ctrl_t ctrl, int force, const char *serialno,
const char *id, const char *keydata,
size_t keydatalen,
int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg);
gpg_error_t agent_card_getattr (ctrl_t ctrl, const char *name, char **result); gpg_error_t agent_card_getattr (ctrl_t ctrl, const char *name, char **result);
int agent_card_scd (ctrl_t ctrl, const char *cmdline, int agent_card_scd (ctrl_t ctrl, const char *cmdline,
int (*getpin_cb)(void *, const char *, char*, size_t), int (*getpin_cb)(void *, const char *, char*, size_t),

View File

@ -1266,9 +1266,9 @@ agent_popup_message_stop (ctrl_t ctrl)
/* Now wait for the thread to terminate. */ /* Now wait for the thread to terminate. */
rc = npth_join (popup_tid, NULL); rc = npth_join (popup_tid, NULL);
if (!rc) if (rc)
log_debug ("agent_popup_message_stop: pth_join failed: %s\n", log_debug ("agent_popup_message_stop: pth_join failed: %s\n",
strerror (errno)); strerror (rc));
/* Thread IDs are opaque, but we try our best here by resetting it /* Thread IDs are opaque, but we try our best here by resetting it
to the same content that a static global variable has. */ to the same content that a static global variable has. */
memset (&popup_tid, '\0', sizeof (popup_tid)); memset (&popup_tid, '\0', sizeof (popup_tid));

View File

@ -722,7 +722,7 @@ inq_needpin (void *opaque, const char *line)
rc = assuan_send_data (parm->ctx, pin, pinlen); rc = assuan_send_data (parm->ctx, pin, pinlen);
xfree (pin); xfree (pin);
} }
else if (!strncmp (line, "POPUPKEYPADPROMPT", 17) else if (!strncmp (line, "POPUPPINPADPROMPT", 17)
&& (line[17] == ' ' || !line[17])) && (line[17] == ' ' || !line[17]))
{ {
line += 17; line += 17;
@ -731,7 +731,7 @@ inq_needpin (void *opaque, const char *line)
rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1); rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1);
} }
else if (!strncmp (line, "DISMISSKEYPADPROMPT", 19) else if (!strncmp (line, "DISMISSPINPADPROMPT", 19)
&& (line[19] == ' ' || !line[19])) && (line[19] == ' ' || !line[19]))
{ {
rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0); rc = parm->getpin_cb (parm->getpin_cb_arg, "", NULL, 0);
@ -1050,6 +1050,64 @@ agent_card_readkey (ctrl_t ctrl, const char *id, unsigned char **r_buf)
} }
struct writekey_parm_s
{
assuan_context_t ctx;
int (*getpin_cb)(void *, const char *, char*, size_t);
void *getpin_cb_arg;
assuan_context_t passthru;
int any_inq_seen;
/**/
const unsigned char *keydata;
size_t keydatalen;
};
/* Handle a KEYDATA inquiry. Note, we only send the data,
assuan_transact takes care of flushing and writing the end */
static gpg_error_t
inq_writekey_parms (void *opaque, const char *line)
{
struct writekey_parm_s *parm = opaque;
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
else
return inq_needpin (opaque, line);
}
int
agent_card_writekey (ctrl_t ctrl, int force, const char *serialno,
const char *id, const char *keydata, size_t keydatalen,
int (*getpin_cb)(void *, const char *, char*, size_t),
void *getpin_cb_arg)
{
int rc;
char line[ASSUAN_LINELENGTH];
struct writekey_parm_s parms;
(void)serialno;
rc = start_scd (ctrl);
if (rc)
return rc;
snprintf (line, DIM(line)-1, "WRITEKEY %s%s", force ? "--force " : "", id);
line[DIM(line)-1] = 0;
parms.ctx = ctrl->scd_local->ctx;
parms.getpin_cb = getpin_cb;
parms.getpin_cb_arg = getpin_cb_arg;
parms.passthru = 0;
parms.any_inq_seen = 0;
parms.keydata = keydata;
parms.keydatalen = keydatalen;
rc = assuan_transact (ctrl->scd_local->ctx, line, NULL, NULL,
inq_writekey_parms, &parms, NULL, NULL);
if (parms.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
rc = cancel_inquire (ctrl, rc);
return unlock_scd (ctrl, rc);
}
/* Type used with the card_getattr_cb. */ /* Type used with the card_getattr_cb. */
struct card_getattr_parm_s { struct card_getattr_parm_s {

View File

@ -2119,9 +2119,133 @@ cmd_export_key (assuan_context_t ctx, char *line)
return leave_cmd (ctx, err); return leave_cmd (ctx, err);
} }
static const char hlp_keytocard[] =
"KEYTOCARD [--force] <hexstring_with_keygrip> <serialno> <id> <timestamp>\n"
"\n";
static gpg_error_t
cmd_keytocard (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int force;
gpg_error_t err = 0;
unsigned char grip[20];
gcry_sexp_t s_skey = NULL;
gcry_sexp_t s_pkey = NULL;
unsigned char *keydata;
size_t keydatalen, timestamplen;
const char *serialno, *timestamp_str, *id;
unsigned char *shadow_info;
unsigned char *shdkey;
time_t timestamp;
force = has_option (line, "--force");
line = skip_options (line);
err = parse_keygrip (ctx, line, grip);
if (err)
return err;
if (agent_key_available (grip))
return gpg_error (GPG_ERR_NO_SECKEY);
line += 40;
while (*line && (*line == ' ' || *line == '\t'))
line++;
serialno = line;
while (*line && (*line != ' ' && *line != '\t'))
line++;
if (!*line)
return gpg_error (GPG_ERR_MISSING_VALUE);
*line = '\0';
line++;
while (*line && (*line == ' ' || *line == '\t'))
line++;
id = line;
while (*line && (*line != ' ' && *line != '\t'))
line++;
if (!*line)
return gpg_error (GPG_ERR_MISSING_VALUE);
*line = '\0';
line++;
while (*line && (*line == ' ' || *line == '\t'))
line++;
timestamp_str = line;
while (*line && (*line != ' ' && *line != '\t'))
line++;
if (*line)
*line = '\0';
timestamplen = line - timestamp_str;
if (timestamplen != 15)
return gpg_error (GPG_ERR_INV_VALUE);
err = agent_key_from_file (ctrl, NULL, ctrl->server_local->keydesc, grip,
NULL, CACHE_MODE_IGNORE, NULL, &s_skey, NULL);
if (err)
return err;
if (!s_skey)
/* Key is on a smartcard already. */
return gpg_error (GPG_ERR_UNUSABLE_SECKEY);
keydatalen = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
keydata = xtrymalloc_secure (keydatalen + 30);
if (keydata == NULL)
{
gcry_sexp_release (s_skey);
return gpg_error_from_syserror ();
}
gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
gcry_sexp_release (s_skey);
/* Add timestamp "created-at" in the private key */
timestamp = isotime2epoch (timestamp_str);
snprintf (keydata+keydatalen-1, 30, "(10:created-at10:%010lu))", timestamp);
keydatalen += 10 + 19 - 1;
err = divert_writekey (ctrl, force, serialno, id, keydata, keydatalen);
if (err)
{
xfree (keydata);
goto leave;
}
xfree (keydata);
err = agent_public_key_from_file (ctrl, grip, &s_pkey);
if (err)
goto leave;
shadow_info = make_shadow_info (serialno, id);
if (!shadow_info)
{
err = gpg_error (GPG_ERR_ENOMEM);
gcry_sexp_release (s_pkey);
goto leave;
}
keydatalen = gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
keydata = xtrymalloc (keydatalen);
if (keydata == NULL)
{
err = gpg_error_from_syserror ();
gcry_sexp_release (s_pkey);
goto leave;
}
gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, keydata, keydatalen);
gcry_sexp_release (s_pkey);
err = agent_shadow_key (keydata, shadow_info, &shdkey);
xfree (keydata);
xfree (shadow_info);
if (err)
{
log_error ("shadowing the key failed: %s\n", gpg_strerror (err));
goto leave;
}
keydatalen = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
err = agent_write_private_key (grip, shdkey, keydatalen, 1);
xfree (shdkey);
leave:
return leave_cmd (ctx, err);
}
static const char hlp_getval[] = static const char hlp_getval[] =
"GETVAL <key>\n" "GETVAL <key>\n"
@ -2548,21 +2672,13 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
ctrl->server_local->allow_pinentry_notify = 1; ctrl->server_local->allow_pinentry_notify = 1;
else if (!strcmp (key, "pinentry-mode")) else if (!strcmp (key, "pinentry-mode"))
{ {
if (!strcmp (value, "ask") || !strcmp (value, "default")) int tmp = parse_pinentry_mode (value);
ctrl->pinentry_mode = PINENTRY_MODE_ASK; if (tmp == -1)
else if (!strcmp (value, "cancel"))
ctrl->pinentry_mode = PINENTRY_MODE_CANCEL;
else if (!strcmp (value, "error"))
ctrl->pinentry_mode = PINENTRY_MODE_ERROR;
else if (!strcmp (value, "loopback"))
{
if (opt.allow_loopback_pinentry)
ctrl->pinentry_mode = PINENTRY_MODE_LOOPBACK;
else
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
}
else
err = gpg_error (GPG_ERR_INV_VALUE); err = gpg_error (GPG_ERR_INV_VALUE);
else if (tmp == PINENTRY_MODE_LOOPBACK && !opt.allow_loopback_pinentry)
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else
ctrl->pinentry_mode = tmp;
} }
else if (!strcmp (key, "cache-ttl-opt-preset")) else if (!strcmp (key, "cache-ttl-opt-preset"))
{ {
@ -2682,6 +2798,7 @@ register_commands (assuan_context_t ctx)
{ "KILLAGENT", cmd_killagent, hlp_killagent }, { "KILLAGENT", cmd_killagent, hlp_killagent },
{ "RELOADAGENT", cmd_reloadagent,hlp_reloadagent }, { "RELOADAGENT", cmd_reloadagent,hlp_reloadagent },
{ "GETINFO", cmd_getinfo, hlp_getinfo }, { "GETINFO", cmd_getinfo, hlp_getinfo },
{ "KEYTOCARD", cmd_keytocard, hlp_keytocard },
{ NULL } { NULL }
}; };
int i, rc; int i, rc;

View File

@ -223,7 +223,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
else if (info && *info == '|') else if (info && *info == '|')
log_debug ("pin_cb called without proper PIN info hack\n"); log_debug ("pin_cb called without proper PIN info hack\n");
/* If BUF has been passed as NULL, we are in keypad mode: The /* If BUF has been passed as NULL, we are in pinpad mode: The
callback opens the popup and immediatley returns. */ callback opens the popup and immediatley returns. */
if (!buf) if (!buf)
{ {
@ -239,7 +239,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
char *desc; char *desc;
if ( asprintf (&desc, if ( asprintf (&desc,
_("%s%%0A%%0AUse the reader's keypad for input."), _("%s%%0A%%0AUse the reader's pinpad for input."),
info) < 0 ) info) < 0 )
rc = gpg_error_from_syserror (); rc = gpg_error_from_syserror ();
else else
@ -442,6 +442,13 @@ divert_pkdecrypt (ctrl_t ctrl,
return rc; return rc;
} }
int
divert_writekey (ctrl_t ctrl, int force, const char *serialno,
const char *id, const char *keydata, size_t keydatalen)
{
return agent_card_writekey (ctrl, force, serialno, id, keydata, keydatalen,
getpin_cb, ctrl);
}
int int
divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context) divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)

View File

@ -1075,7 +1075,11 @@ hash_passphrase (const char *passphrase, int hashalgo,
unsigned long s2kcount, unsigned long s2kcount,
unsigned char *key, size_t keylen) unsigned char *key, size_t keylen)
{ {
/* The key derive function does not support a zero length string for
the passphrase in the S2K modes. Return a better suited error
code than GPG_ERR_INV_DATA. */
if (!passphrase || !*passphrase)
return gpg_error (GPG_ERR_NO_PASSPHRASE);
return gcry_kdf_derive (passphrase, strlen (passphrase), return gcry_kdf_derive (passphrase, strlen (passphrase),
s2kmode == 3? GCRY_KDF_ITERSALTED_S2K : s2kmode == 3? GCRY_KDF_ITERSALTED_S2K :
s2kmode == 1? GCRY_KDF_SALTED_S2K : s2kmode == 1? GCRY_KDF_SALTED_S2K :

View File

@ -59,6 +59,7 @@ common_sources = \
util.h i18n.c i18n.h \ util.h i18n.c i18n.h \
estream.c estream.h estream-printf.c estream-printf.h \ estream.c estream.h estream-printf.c estream-printf.h \
status.c status.h\ status.c status.h\
shareddefs.h \
openpgpdefs.h \ openpgpdefs.h \
gc-opt-flags.h \ gc-opt-flags.h \
keyserver.h \ keyserver.h \
@ -92,6 +93,7 @@ common_sources = \
userids.c userids.h \ userids.c userids.h \
openpgp-oid.c \ openpgp-oid.c \
ssh-utils.c ssh-utils.h \ ssh-utils.c ssh-utils.h \
agent-opt.c \
helpfile.c helpfile.c
# To make the code easier to read we have split home some code into # To make the code easier to read we have split home some code into

71
common/agent-opt.c Normal file
View File

@ -0,0 +1,71 @@
/* agent-opt.c - Helper for certain agent options
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include "shareddefs.h"
/* Parse VALUE and return an integer representing a pinentry_mode_t.
(-1) is returned for an invalid VALUE. */
int
parse_pinentry_mode (const char *value)
{
int result;
if (!strcmp (value, "ask") || !strcmp (value, "default"))
result = PINENTRY_MODE_ASK;
else if (!strcmp (value, "cancel"))
result = PINENTRY_MODE_CANCEL;
else if (!strcmp (value, "error"))
result = PINENTRY_MODE_ERROR;
else if (!strcmp (value, "loopback"))
result = PINENTRY_MODE_LOOPBACK;
else
result = -1;
return result;
}
/* Return the string representation for the pinentry MODE. Returns
"?" for an invalid mode. */
const char *
str_pinentry_mode (pinentry_mode_t mode)
{
switch (mode)
{
case PINENTRY_MODE_ASK: return "ask";
case PINENTRY_MODE_CANCEL: return "cancel";
case PINENTRY_MODE_ERROR: return "error";
case PINENTRY_MODE_LOOPBACK: return "loopback";
}
return "?";
}

48
common/shareddefs.h Normal file
View File

@ -0,0 +1,48 @@
/* shareddefs.h - Constants and helpers useful for all modules
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either
*
* - the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* or
*
* - the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* or both in parallel, as here.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GNUPG_COMMON_SHAREDDEFS_H
#define GNUPG_COMMON_SHAREDDEFS_H
/* Values for the pinentry mode. */
typedef enum
{
PINENTRY_MODE_ASK = 0, /* Ask via pinentry (default). */
PINENTRY_MODE_CANCEL, /* Always return a cancel error. */
PINENTRY_MODE_ERROR, /* Return error code for no pinentry. */
PINENTRY_MODE_LOOPBACK /* Use an inquiry to get the value. */
}
pinentry_mode_t;
/*-- agent-opt.c --*/
int parse_pinentry_mode (const char *value);
const char *str_pinentry_mode (pinentry_mode_t mode);
#endif /*GNUPG_COMMON_SHAREDDEFS_H*/

View File

@ -84,8 +84,6 @@ enum
STATUS_NOTATION_NAME, STATUS_NOTATION_NAME,
STATUS_NOTATION_DATA, STATUS_NOTATION_DATA,
STATUS_POLICY_URL, STATUS_POLICY_URL,
STATUS_BEGIN_STREAM,
STATUS_END_STREAM,
STATUS_KEY_CREATED, STATUS_KEY_CREATED,
STATUS_USERID_HINT, STATUS_USERID_HINT,
STATUS_UNEXPECTED, STATUS_UNEXPECTED,
@ -97,7 +95,6 @@ enum
STATUS_ALREADY_SIGNED, STATUS_ALREADY_SIGNED,
STATUS_KEYEXPIRED, STATUS_KEYEXPIRED,
STATUS_KEYREVOKED, STATUS_KEYREVOKED,
STATUS_SIGEXPIRED,
STATUS_EXPSIG, STATUS_EXPSIG,
STATUS_EXPKEYSIG, STATUS_EXPKEYSIG,
@ -125,6 +122,8 @@ enum
STATUS_TRUNCATED, STATUS_TRUNCATED,
STATUS_MOUNTPOINT, STATUS_MOUNTPOINT,
STATUS_PINENTRY_LAUNCHED,
STATUS_ERROR, STATUS_ERROR,
STATUS_SUCCESS STATUS_SUCCESS
}; };

View File

@ -1519,7 +1519,7 @@ fi
build_scdaemon_extra="" build_scdaemon_extra=""
if test "$build_scdaemon" = "yes"; then if test "$build_scdaemon" = "yes"; then
if test $have_libusb = no; then if test $have_libusb = no; then
build_scdaemon_extra="${tmp}without internal CCID driver" build_scdaemon_extra="without internal CCID driver"
fi fi
if test -n "$build_scdaemon_extra"; then if test -n "$build_scdaemon_extra"; then
build_scdaemon_extra="(${build_scdaemon_extra})" build_scdaemon_extra="(${build_scdaemon_extra})"

File diff suppressed because it is too large Load Diff

View File

@ -2611,6 +2611,26 @@ Note that this passphrase is only used if the option @option{--batch}
has also been given. This is different from @command{gpg}. has also been given. This is different from @command{gpg}.
@end ifclear @end ifclear
@ifset gpgtwoone
@item --pinentry-mode @code{mode}
@opindex pinentry-mode
Set the pinentry mode to @code{mode}. Allowed values for @code{mode}
are:
@table @asis
@item default
Use the default of the agent, which is @code{ask}.
@item ask
Force the use of the Pinentry.
@item cancel
Emulate use of Pinentry's cancel button.
@item error
Return a Pinentry error (``No Pinentry'').
@item loopback
Redirect Pinentry queries to the caller. Note that in contrast to
Pinentry the user is not prompted again if he enters a bad password.
@end table
@end ifset
@item --command-fd @code{n} @item --command-fd @code{n}
@opindex command-fd @opindex command-fd
This is a replacement for the deprecated shared-memory IPC mode. This is a replacement for the deprecated shared-memory IPC mode.

View File

@ -1,4 +1,4 @@
# help..txt - GnuPG online help # help.ja.txt - Japanese GnuPG online help
# Copyright (C) 2007 Free Software Foundation, Inc. # Copyright (C) 2007 Free Software Foundation, Inc.
# #
# This file is part of GnuPG. # This file is part of GnuPG.
@ -16,268 +16,317 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>. # along with this program; if not, see <http://www.gnu.org/licenses/>.
.#pinentry.qualitybar.tooltip
# [ このエントリは有効にするには、上記のキーの # を削除してください。]
# これは例です。
このバーは、入力されたパスフレーズの品質を示しています。
.#gpg.edit_ownertrust.value バーが赤い色となっている場合、GnuPGはパスフレーズが弱すぎると判断し、受
# fixme: Please translate and remove the hash mark from the key line. け付けません。管理者にパスフレーズの制限の設定について詳細を問い合わせ
It's up to you to assign a value here; this value will never be exported てください。
to any 3rd party. We need it to implement the web-of-trust; it has nothing
to do with the (implicitly created) web-of-certificates.
. .
.#gpg.edit_ownertrust.set_ultimate.okay .gnupg.agent-problem
# fixme: Please translate and remove the hash mark from the key line. # There was a problem accessing or starting the agent.
To build the Web-of-Trust, GnuPG needs to know which keys are 動作中のGpg-Agentへの接続ができなかったか、通信の問題が発生しました。
ultimately trusted - those are usually the keys for which you have
access to the secret key. Answer "yes" to set this key to
ultimately trusted
システムは、Gpg-Agentと呼ばれるバックグラウンド・プロセスを利用し、秘密
鍵とパスフレーズの問い合わせを処理します。このエージェントは通常、ユー
ザがログインするときに開始され、ログインしている間、動いています。もし、
エージェントが利用可能でない場合、システムは、その場でエージェントの起
動を試しますが、この場合、機能がやや制限され、若干の問題がある場合があ
ります。
もしかしたら、管理者に問い合わせて、この問題をどのように解決したら良い
か聞いた方が良いかもしれません。とりあえずの方策としては、一度ログアウ
トしてもう一度ログインし、改善が見られるか試してみることがあります。も
し、これがうまくいくようであれば管理者に報告してください。それはおそら
く、ソフトウェアのバグであることを示していますので。
. .
.#gpg.untrusted_key.override
# fixme: Please translate and remove the hash mark from the key line. .gnupg.dirmngr-problem
If you want to use this untrusted key anyway, answer "yes". # There was a problen accessing the dirmngr.
動作中のDirmngrへの接続ができなかったか、通信の問題が発生しました。
証明書失効リスト(CRL)を検索し、OCSPの懸賞とLDAPサーバを通じて鍵を検索す
るため、システムは、Dirmngrと呼ばれる外部サービス・プログラムを利用しま
す。Dirmngrは通常、システムサービス(daemon)として実効されます、一般ユー
ザは気にする必要はありません。問題がある場合、システムは、要求に応じて、
Dirmngrを起動することがありますが、これは対応策であり、性能に制限が生じ
ます。
この問題がある場合、システム管理者に連絡し、どのように進めたら良いか問
い合わせてください。とりあえずの解決策としては、gpgsmの設定でCRLの検証
を停止させることが考えられます。
. .
.#gpg.pklist.user_id.enter
# fixme: Please translate and remove the hash mark from the key line. .gpg.edit_ownertrust.value
Enter the user ID of the addressee to whom you want to send the message. ここでの値の指定は、あなたに任されています。この値は、第三者に開示され
ることは決してありません。ウェブ・オブ・トラストを実装するためにこの値
が必要となりますが、(暗黙的に作られる)証明書の網には何も関係しません。
. .
.#gpg.keygen.algo .gpg.edit_ownertrust.set_ultimate.okay
# fixme: Please translate and remove the hash mark from the key line. ウェブ・オブ・トラストを構築するためにGnuPGは、どの鍵が究極的に信頼でき
Select the algorithm to use. るかを知る必要があります。その鍵は通常は、あなたが秘密鍵へアクセスでき
るものです。この鍵が究極的に信頼できる場合、"yes" と答えてください。
DSA (aka DSS) is the Digital Signature Algorithm and can only be used
for signatures.
Elgamal is an encrypt-only algorithm.
RSA may be used for signatures or encryption.
The first (primary) key must always be a key which is capable of signing.
. .
.#gpg.keygen.algo.rsa_se
# fixme: Please translate and remove the hash mark from the key line. .gpg.untrusted_key.override
In general it is not a good idea to use the same key for signing and この信頼されてない鍵をどちらにせよ使いたい場合、"yes" と答えてください。
encryption. This algorithm should only be used in certain domains.
Please consult your security expert first.
. .
.#gpg.keygen.size .gpg.pklist.user_id.enter
# fixme: Please translate and remove the hash mark from the key line. このメッセージを送りたい宛先のユーザIDを入力してください。
Enter the size of the key
. .
.#gpg.keygen.size.huge.okay .gpg.keygen.algo
# fixme: Please translate and remove the hash mark from the key line. 使用するアルゴリズムを選択してください。
Answer "yes" or "no"
DSA (別名 DSS)は電子署名アルゴリズムであり、署名にのみ使えます。
Elgamal は暗号化のみのアルゴリズムです。
RSA は署名と暗号化のどちらにも使えます。
主鍵は常に、署名が可能の鍵である必要があります。
. .
.#gpg.keygen.size.large.okay
# fixme: Please translate and remove the hash mark from the key line. .gpg.keygen.algo.rsa_se
Answer "yes" or "no" 一般的に、署名と暗号化に同一の鍵を用いることは良いことではありません。
このアルゴリズムはある特定の領域だけに使うべきです。まず、セキュリティ
の専門家に相談してください。
. .
.#gpg.keygen.valid
# fixme: Please translate and remove the hash mark from the key line. .gpg.keygen.size
Enter the required value as shown in the prompt. 鍵の長さを入力してください。
It is possible to enter a ISO date (YYYY-MM-DD) but you won't
get a good error response - instead the system tries to interpret 提案されたデフォルトが通常良い選択です。
the given value as an interval.
大きな鍵長を使いたい場合、たとえば4096ビットなど、本当に意味があるか再
検討してください。こちらのウェブページを見るのも良いと思います:
http://www.xkcd.com/538/
. .
.#gpg.keygen.valid.okay .gpg.keygen.size.huge.okay
# fixme: Please translate and remove the hash mark from the key line. "yes" か "no" で答えてください。
Answer "yes" or "no"
. .
.#gpg.keygen.name
# fixme: Please translate and remove the hash mark from the key line. .gpg.keygen.size.large.okay
Enter the name of the key holder "yes" か "no" で答えてください。
. .
.#gpg.keygen.email
# fixme: Please translate and remove the hash mark from the key line. .gpg.keygen.valid
please enter an optional but highly suggested email address プロンプトで示された必要な値を入力してください。ISO形式の日付
(YYYY-MM-DD)の入力が可能ですが、良いエラー対応が得られないかもしれませ
ん。システムが与えられた値を期間と解釈することがあります。.
. .
.#gpg.keygen.comment .gpg.keygen.valid.okay
# fixme: Please translate and remove the hash mark from the key line. "yes" か "no" で答えてください。
Please enter an optional comment
. .
.#gpg.keygen.userid.cmd
# fixme: Please translate and remove the hash mark from the key line. .gpg.keygen.name
N to change the name. 鍵の持ち主の名前を入力してください。
C to change the comment. 文字 "<" と ">" は許されていません。
E to change the email address. 例: Heinrich Heine
O to continue with key generation.
Q to to quit the key generation.
. .
.#gpg.keygen.sub.okay
# fixme: Please translate and remove the hash mark from the key line. .gpg.keygen.email
Answer "yes" (or just "y") if it is okay to generate the sub key. オプションですが推奨される電子メールアドレスを入力してください。
例: heinrichh@duesseldorf.de
. .
.#gpg.sign_uid.okay .gpg.keygen.comment
# fixme: Please translate and remove the hash mark from the key line. オプションのコメントを入力してください。
Answer "yes" or "no" 文字 "(" と ")" は許されていません。
一般的にコメントは必要ではありません。
. .
.#gpg.sign_uid.class
# fixme: Please translate and remove the hash mark from the key line.
When you sign a user ID on a key, you should first verify that the key
belongs to the person named in the user ID. It is useful for others to
know how carefully you verified this.
"0" means you make no particular claim as to how carefully you verified the .gpg.keygen.userid.cmd
key. # (Keep a leading empty line)
"1" means you believe the key is owned by the person who claims to own it N 名前の変更。
but you could not, or did not verify the key at all. This is useful for C コメントの変更。
a "persona" verification, where you sign the key of a pseudonymous user. E 電子メールアドレスの変更。
O 鍵生成に進む。
"2" means you did casual verification of the key. For example, this could Q 鍵生成を止める。
mean that you verified the key fingerprint and checked the user ID on the
key against a photo ID.
"3" means you did extensive verification of the key. For example, this could
mean that you verified the key fingerprint with the owner of the key in
person, and that you checked, by means of a hard to forge document with a
photo ID (such as a passport) that the name of the key owner matches the
name in the user ID on the key, and finally that you verified (by exchange
of email) that the email address on the key belongs to the key owner.
Note that the examples given above for levels 2 and 3 are *only* examples.
In the end, it is up to you to decide just what "casual" and "extensive"
mean to you when you sign other keys.
If you don't know what the right answer is, answer "0".
. .
.#gpg.change_passwd.empty.okay .gpg.keygen.sub.okay
# fixme: Please translate and remove the hash mark from the key line. 副鍵を生成してよければ、"yes" (あるいは単に "y") と答えてください。
Answer "yes" or "no"
. .
.#gpg.keyedit.save.okay .gpg.sign_uid.okay
# fixme: Please translate and remove the hash mark from the key line. "yes" か "no" で答えてください。
Answer "yes" or "no"
. .
.#gpg.keyedit.cancel.okay .gpg.sign_uid.class
# fixme: Please translate and remove the hash mark from the key line. ある鍵のユーザIDに署名するとき、あなたは、まず、その鍵がそのユーザIDの
Answer "yes" or "no" 人に属するかどうかを確認しなければなりません。あなたがどれくらいこれを
慎重に確認したかについて、ほかの人が知ることは有用です。
"0" は、どれくらい慎重に確認したかについて特になにも主張しないことを意味します。
"1" は、あなたは、主張するその人が所有する鍵であると考えるが、その鍵について、
確認できなかった、あるいはしなかったことを意味します。これは、ペンネームの
ユーザの鍵に署名するような "persona" 確認に有用です。
"2" は、その鍵に対し、通常の検証を行ったことを意味します。たとえば、鍵
のフィンガープリントを確認し、写真付きIDでユーザIDを確認したことを
意味します。
"3" は、その鍵に対し、広範な検証を行ったことを意味します。たとえば、鍵
のフィンガープリントを対面で確認し、パスポートなど偽造することが難
しい写真付きIDでユーザIDを確認し、所有者の名前が鍵のユーザIDに適合
し、メールの交換で、メールアドレスが所有者に属することを確認したこ
とを意味します。
上記のレベル2とレベル3で示した例は、単に例であることに注意してください。
結局は、ほかの鍵に署名するとき、なにがあなたにとって「通常」で、なにが
「広範」かをを決めるのは、あなた自身に任されています。
正しい答えがなにかわからないときは "0" と答えてください。
. .
.#gpg.keyedit.sign_all.okay .gpg.change_passwd.empty.okay
# fixme: Please translate and remove the hash mark from the key line. "yes" か "no" で答えてください。
Answer "yes" if you want to sign ALL the user IDs
. .
.#gpg.keyedit.remove.uid.okay
# fixme: Please translate and remove the hash mark from the key line. .gpg.keyedit.save.okay
Answer "yes" if you really want to delete this user ID. "yes" か "no" で答えてください。
All certificates are then also lost!
. .
.#gpg.keyedit.remove.subkey.okay
# fixme: Please translate and remove the hash mark from the key line. .gpg.keyedit.cancel.okay
Answer "yes" if it is okay to delete the subkey "yes" か "no" で答えてください。
. .
.#gpg.keyedit.delsig.valid .gpg.keyedit.sign_all.okay
# fixme: Please translate and remove the hash mark from the key line. すべてのユーザIDに対して署名したい場合、"yes"と答えてください。
This is a valid signature on the key; you normally don't want
to delete this signature because it may be important to establish a
trust connection to the key or another key certified by this key.
. .
.#gpg.keyedit.delsig.unknown .gpg.keyedit.remove.uid.okay
# fixme: Please translate and remove the hash mark from the key line. このユーザIDを本当に削除したい場合、"yes"と答えてください。
This signature can't be checked because you don't have the そうすると全部の証明書が失われます!
corresponding key. You should postpone its deletion until you
know which key was used because this signing key might establish
a trust connection through another already certified key.
. .
.#gpg.keyedit.delsig.invalid .gpg.keyedit.remove.subkey.okay
# fixme: Please translate and remove the hash mark from the key line. 副鍵を削除してよい場合、"yes"と答えてください。
The signature is not valid. It does make sense to remove it from
your keyring.
. .
.#gpg.keyedit.delsig.selfsig
# fixme: Please translate and remove the hash mark from the key line. .gpg.keyedit.delsig.valid
This is a signature which binds the user ID to the key. It is これは、この鍵の有効な署名です。通常、この署名を削除することは望まない
usually not a good idea to remove such a signature. Actually でしょう。この鍵(または、この鍵で証明された別の鍵)への信頼のコネクショ
GnuPG might not be able to use this key anymore. So do this ンが成立することが重要となる場合があるからです。
only if this self-signature is for some reason not valid and
a second one is available.
. .
.#gpg.keyedit.updpref.okay .gpg.keyedit.delsig.unknown
# fixme: Please translate and remove the hash mark from the key line. この署名は検証できませんでした。対応する鍵を持っていないからです。どの
Change the preferences of all user IDs (or just of the selected ones) 鍵が使われたかわかるまでこの削除を延期すべきです。この署名の鍵は、別の
to the current list of preferences. The timestamp of all affected すでに証明された鍵を通じて信頼のコネクションを成立することがあるからで
self-signatures will be advanced by one second. す。
. .
.#gpg.passphrase.enter .gpg.keyedit.delsig.invalid
# fixme: Please translate and remove the hash mark from the key line. この署名は有効ではありません。鍵リングから削除することに意味があります。
Please enter the passhrase; this is a secret sentence
. .
.#gpg.passphrase.repeat .gpg.keyedit.delsig.selfsig
# fixme: Please translate and remove the hash mark from the key line. これはこのユーザIDとこの鍵とを結ぶ署名です。通常、このような署名を削除
Please repeat the last passphrase, so you are sure what you typed in. することは良いことではありません。実際、GnuPGはこの鍵を使うことができな
くなってしまうかもしれません。ですから、この自己署名がなんらかの理由に
よって無効であり、第二のものが利用可能である場合にだけ、実行してくださ
い。
. .
.#gpg.detached_signature.filename .gpg.keyedit.updpref.okay
# fixme: Please translate and remove the hash mark from the key line. すべてのユーザID(もしくは単に選択された一つ)の優先指定を現行の優先指定
Give the name of the file to which the signature applies に変更します。すべての関係する自己署名のタイムスタンプは、一秒進んだも
のとなります。
. .
.#gpg.openfile.overwrite.okay .gpg.passphrase.enter
# fixme: Please translate and remove the hash mark from the key line. # (keep a leading empty line)
Answer "yes" if it is okay to overwrite the file
パスフレーズを入力してください。秘密の文です。
. .
.#gpg.openfile.askoutname
# fixme: Please translate and remove the hash mark from the key line. .gpg.passphrase.repeat
Please enter a new filename. If you just hit RETURN the default もう一度パスフレーズを入力し、間違いなく入力されたことを確認してください。
file (which is shown in brackets) will be used.
. .
.#gpg.ask_revocation_reason.code .gpg.detached_signature.filename
# fixme: Please translate and remove the hash mark from the key line. 署名が適用されるファイルの名前を与えてください。
You should specify a reason for the certification. Depending on the
context you have the ability to choose from this list:
"Key has been compromised"
Use this if you have a reason to believe that unauthorized persons
got access to your secret key.
"Key is superseded"
Use this if you have replaced this key with a newer one.
"Key is no longer used"
Use this if you have retired this key.
"User ID is no longer valid"
Use this to state that the user ID should not longer be used;
this is normally used to mark an email address invalid.
. .
.#gpg.ask_revocation_reason.text .gpg.openfile.overwrite.okay
# fixme: Please translate and remove the hash mark from the key line. # openfile.c (overwrite_filep)
If you like, you can enter a text describing why you issue this ファイルを上書きしてよければ、"yes"と答えてください。
revocation certificate. Please keep this text concise.
An empty line ends the text.
. .
.gpg.openfile.askoutname
# openfile.c (ask_outfile_name)
新しいファイル名を入力してください。単にEnterを打つと、カッコで示された
デフォルトのファイルが使われます。
.
.gpg.ask_revocation_reason.code
# revoke.c (ask_revocation_reason)
証明書の理由を指定します。下記のリストから選択してください:
"鍵が危うくなった"
承認していない人があなたの秘密鍵へのアクセスを得たと考える理由が
ある場合に、これを指定します。
"鍵を取り替えた"
新しい鍵でこの鍵を置き換えた場合に、これを指定します。
"鍵はもう使われない"
この鍵を使わなくなった場合に、これを指定します。
"ユーザIDが無効となった"
ユーザIDをもはや使うべきでない場合に、これを指定します。通常、こ
れは、電子メールアドレスが無効となった場合です。
.
.gpg.ask_revocation_reason.text
# revoke.c (ask_revocation_reason)
必要であれば、この失効証明書を発行する理由を記述する文章を入力する
ことができます。この文章は簡潔にしてください。空行は文章の終わりを
意味します。
.
.gpgsm.root-cert-not-trusted
# This text gets displayed by the audit log if
# a root certificates was not trusted.
ルート証明書(信頼の拠り所)が信頼できるとされていません。設定にもよりま
すが、そのルート証明書を信頼できるものと指定するように既に問われたかも
しれませんし、手動でGnuPGがその証明書を信頼できると扱うように設定する必
要があります。信頼できる証明書は、GnuPGのホームディレクトリのファイル
trustlist.txt に設定します。疑問のある場合、システム管理者にこの証明書
を信頼してよいものかどうか問い合わせてください。
.
.gpgsm.crl-problem
# This tex is displayed by the audit log for problems with
# the CRL or OCSP checking.
設定によりますが、CRLの取得か、OCSP検証の際に問題が起きました。これが動
かない場合、実に様々な理由がありえます。解決策は、マニュアルを見てくだ
さい。
.
# Local variables: # Local variables:

View File

@ -287,10 +287,18 @@ Note that with the current version of Scdaemon the card is powered
down immediately at the next timer tick for any value of @var{n} other down immediately at the next timer tick for any value of @var{n} other
than 0. than 0.
@item --enable-pinpad-varlen
@opindex enable-pinpad-varlen
Please specify this option when the card reader supports variable
length input for pinpad (default is no). For known readers listed in
ccid-driver, this option is not needed. Note that if your card reader
doesn't supports variable length input but you want to use it, you
need to specify your pinpad request on your card.
@item --disable-keypad
@opindex disable-keypad @item --disable-pinpad
Even if a card reader features a keypad, do not try to use it. @opindex disable-pinpad
Even if a card reader features a pinpad, do not try to use it.
@item --deny-admin @item --deny-admin

View File

@ -1,6 +1,6 @@
/* call-agent.c - Divert GPG operations to the agent. /* call-agent.c - Divert GPG operations to the agent.
* Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009, * Copyright (C) 2001, 2002, 2003, 2006, 2007, 2008, 2009,
* 2010, 2011 Free Software Foundation, Inc. * 2010, 2011, 2013 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -40,47 +40,60 @@
#include "sysutils.h" #include "sysutils.h"
#include "call-agent.h" #include "call-agent.h"
#include "status.h" #include "status.h"
#include "../common/shareddefs.h"
#ifndef DBG_ASSUAN #ifndef DBG_ASSUAN
# define DBG_ASSUAN 1 # define DBG_ASSUAN 1
#endif #endif
#define CONTROL_D ('D' - 'A' + 1)
static assuan_context_t agent_ctx = NULL; static assuan_context_t agent_ctx = NULL;
static int did_early_card_test; static int did_early_card_test;
struct cipher_parm_s struct default_inq_parm_s
{ {
ctrl_t ctrl; ctrl_t ctrl;
assuan_context_t ctx; assuan_context_t ctx;
struct {
u32 *keyid;
u32 *mainkeyid;
int pubkey_algo;
} keyinfo;
};
struct cipher_parm_s
{
struct default_inq_parm_s *dflt;
assuan_context_t ctx;
unsigned char *ciphertext; unsigned char *ciphertext;
size_t ciphertextlen; size_t ciphertextlen;
}; };
struct writecert_parm_s struct writecert_parm_s
{ {
assuan_context_t ctx; struct default_inq_parm_s *dflt;
const unsigned char *certdata; const unsigned char *certdata;
size_t certdatalen; size_t certdatalen;
}; };
struct writekey_parm_s struct writekey_parm_s
{ {
assuan_context_t ctx; struct default_inq_parm_s *dflt;
const unsigned char *keydata; const unsigned char *keydata;
size_t keydatalen; size_t keydatalen;
}; };
struct genkey_parm_s struct genkey_parm_s
{ {
ctrl_t ctrl; struct default_inq_parm_s *dflt;
assuan_context_t ctx;
const char *keyparms; const char *keyparms;
}; };
struct import_key_parm_s struct import_key_parm_s
{ {
ctrl_t ctrl; struct default_inq_parm_s *dflt;
assuan_context_t ctx;
const void *key; const void *key;
size_t keylen; size_t keylen;
}; };
@ -161,6 +174,19 @@ start_agent (ctrl_t ctrl, int for_card)
here used to indirectly enable GPG_ERR_FULLY_CANCELED. */ here used to indirectly enable GPG_ERR_FULLY_CANCELED. */
assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0", assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0",
NULL, NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL, NULL);
/* Pass on the pinentry mode. */
if (opt.pinentry_mode)
{
char *tmp = xasprintf ("OPTION pinentry-mode=%s",
str_pinentry_mode (opt.pinentry_mode));
rc = assuan_transact (agent_ctx, tmp,
NULL, NULL, NULL, NULL, NULL, NULL);
xfree (tmp);
if (rc)
log_error ("setting pinentry mode '%s' failed: %s\n",
str_pinentry_mode (opt.pinentry_mode),
gpg_strerror (rc));
}
} }
} }
@ -307,20 +333,46 @@ get_serialno_cb (void *opaque, const char *line)
static gpg_error_t static gpg_error_t
default_inq_cb (void *opaque, const char *line) default_inq_cb (void *opaque, const char *line)
{ {
(void)opaque; gpg_error_t err = 0;
struct default_inq_parm_s *parm = opaque;
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17])) if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
{ {
/* There is no working server mode yet thus we use err = gpg_proxy_pinentry_notify (parm->ctrl, line);
AllowSetForegroundWindow window right here. We might want to if (err)
do this anyway in case gpg is called on the console. */ log_error (_("failed to proxy %s inquiry to client\n"),
gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10)); "PINENTRY_LAUNCHED");
/* We do not pass errors to avoid breaking other code. */ /* We do not pass errors to avoid breaking other code. */
} }
else if (!strncmp (line, "PASSPHRASE", 10) && (line[10]==' '||!line[10])
&& opt.pinentry_mode == PINENTRY_MODE_LOOPBACK)
{
if (have_static_passphrase ())
{
const char *s = get_static_passphrase ();
err = assuan_send_data (parm->ctx, s, strlen (s));
}
else
{
char *pw;
if (parm->keyinfo.keyid)
emit_status_need_passphrase (parm->keyinfo.keyid,
parm->keyinfo.mainkeyid,
parm->keyinfo.pubkey_algo);
pw = cpr_get_hidden ("passphrase.enter", _("Enter passphrase: "));
cpr_kill_prompt ();
if (*pw == CONTROL_D && !pw[1])
err = gpg_error (GPG_ERR_CANCELED);
else
err = assuan_send_data (parm->ctx, pw, strlen (pw));
xfree (pw);
}
}
else else
log_debug ("ignoring gpg-agent inquiry '%s'\n", line); log_debug ("ignoring gpg-agent inquiry '%s'\n", line);
return 0; return err;
} }
@ -515,6 +567,9 @@ int
agent_learn (struct agent_card_info_s *info) agent_learn (struct agent_card_info_s *info)
{ {
int rc; int rc;
struct default_inq_parm_s parm;
memset (&parm, 0, sizeof parm);
rc = start_agent (NULL, 1); rc = start_agent (NULL, 1);
if (rc) if (rc)
@ -532,10 +587,10 @@ agent_learn (struct agent_card_info_s *info)
if (rc) if (rc)
return rc; return rc;
parm.ctx = agent_ctx;
memset (info, 0, sizeof *info); memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, "SCD LEARN --force", rc = assuan_transact (agent_ctx, "SCD LEARN --force",
dummy_data_cb, NULL, default_inq_cb, NULL, dummy_data_cb, NULL, default_inq_cb, &parm,
learn_status_cb, info); learn_status_cb, info);
/* Also try to get the key attributes. */ /* Also try to get the key attributes. */
if (!rc) if (!rc)
@ -544,6 +599,30 @@ agent_learn (struct agent_card_info_s *info)
return rc; return rc;
} }
int
agent_keytocard (const char *hexgrip, int keyno, int force,
const char *serialno, const char *timestamp)
{
int rc;
char line[ASSUAN_LINELENGTH];
snprintf (line, DIM(line)-1, "KEYTOCARD %s%s %s OPENPGP.%d %s",
force?"--force ": "", hexgrip, serialno, keyno, timestamp);
line[DIM(line)-1] = 0;
rc = start_agent (NULL, 1);
if (rc)
return rc;
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb,
NULL, NULL, NULL);
if (rc)
return rc;
return rc;
}
/* Call the agent to retrieve a data object. This function returns /* Call the agent to retrieve a data object. This function returns
the data in the same structure as used by the learn command. It is the data in the same structure as used by the learn command. It is
allowed to update such a structure using this commmand. */ allowed to update such a structure using this commmand. */
@ -552,6 +631,9 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s parm;
memset (&parm, 0, sizeof parm);
if (!*name) if (!*name)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
@ -565,7 +647,8 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
if (rc) if (rc)
return rc; return rc;
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, NULL, parm.ctx = agent_ctx;
rc = assuan_transact (agent_ctx, line, NULL, NULL, default_inq_cb, &parm,
learn_status_cb, info); learn_status_cb, info);
return rc; return rc;
@ -583,6 +666,9 @@ agent_scd_setattr (const char *name,
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
char *p; char *p;
struct default_inq_parm_s parm;
memset (&parm, 0, sizeof parm);
(void)serialno; (void)serialno;
@ -614,8 +700,9 @@ agent_scd_setattr (const char *name,
rc = start_agent (NULL, 1); rc = start_agent (NULL, 1);
if (!rc) if (!rc)
{ {
parm.ctx = agent_ctx;
rc = assuan_transact (agent_ctx, line, NULL, NULL, rc = assuan_transact (agent_ctx, line, NULL, NULL,
default_inq_cb, NULL, NULL, NULL); default_inq_cb, &parm, NULL, NULL);
} }
status_sc_op_failure (rc); status_sc_op_failure (rc);
@ -635,10 +722,11 @@ inq_writecert_parms (void *opaque, const char *line)
if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8])) if (!strncmp (line, "CERTDATA", 8) && (line[8]==' '||!line[8]))
{ {
rc = assuan_send_data (parm->ctx, parm->certdata, parm->certdatalen); rc = assuan_send_data (parm->dflt->ctx,
parm->certdata, parm->certdatalen);
} }
else else
rc = default_inq_cb (opaque, line); rc = default_inq_cb (parm->dflt, line);
return rc; return rc;
} }
@ -652,6 +740,9 @@ agent_scd_writecert (const char *certidstr,
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct writecert_parm_s parms; struct writecert_parm_s parms;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
rc = start_agent (NULL, 1); rc = start_agent (NULL, 1);
if (rc) if (rc)
@ -661,7 +752,8 @@ agent_scd_writecert (const char *certidstr,
snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr); snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
parms.ctx = agent_ctx; dfltparm.ctx = agent_ctx;
parms.dflt = &dfltparm;
parms.certdata = certdata; parms.certdata = certdata;
parms.certdatalen = certdatalen; parms.certdatalen = certdatalen;
@ -683,10 +775,10 @@ inq_writekey_parms (void *opaque, const char *line)
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
{ {
rc = assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen); rc = assuan_send_data (parm->dflt->ctx, parm->keydata, parm->keydatalen);
} }
else else
rc = default_inq_cb (opaque, line); rc = default_inq_cb (parm->dflt, line);
return rc; return rc;
} }
@ -700,6 +792,9 @@ agent_scd_writekey (int keyno, const char *serialno,
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct writekey_parm_s parms; struct writekey_parm_s parms;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno; (void)serialno;
@ -711,7 +806,8 @@ agent_scd_writekey (int keyno, const char *serialno,
snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno); snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
parms.ctx = agent_ctx; dfltparm.ctx = agent_ctx;
parms.dflt = &dfltparm;
parms.keydata = keydata; parms.keydata = keydata;
parms.keydatalen = keydatalen; parms.keydatalen = keydatalen;
@ -836,6 +932,9 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
gnupg_isotime_t tbuf; gnupg_isotime_t tbuf;
struct scd_genkey_parm_s parms; struct scd_genkey_parm_s parms;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno; (void)serialno;
@ -857,9 +956,10 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
keyno); keyno);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
dfltparm.ctx = agent_ctx;
memset (info, 0, sizeof *info); memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, line, rc = assuan_transact (agent_ctx, line,
NULL, NULL, default_inq_cb, NULL, NULL, NULL, default_inq_cb, &dfltparm,
scd_genkey_cb, &parms); scd_genkey_cb, &parms);
xfree (parms.savedbytes); xfree (parms.savedbytes);
@ -985,19 +1085,25 @@ agent_scd_readcert (const char *certidstr,
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
membuf_t data; membuf_t data;
size_t len; size_t len;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
*r_buf = NULL; *r_buf = NULL;
rc = start_agent (NULL, 1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
dfltparm.ctx = agent_ctx;
init_membuf (&data, 2048); init_membuf (&data, 2048);
snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr); snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, rc = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, membuf_data_cb, &data,
default_inq_cb, NULL, NULL, NULL); default_inq_cb, &dfltparm,
NULL, NULL);
if (rc) if (rc)
{ {
xfree (get_membuf (&data, &len)); xfree (get_membuf (&data, &len));
@ -1028,6 +1134,9 @@ agent_scd_change_pin (int chvno, const char *serialno)
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
const char *reset = ""; const char *reset = "";
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
(void)serialno; (void)serialno;
@ -1038,11 +1147,14 @@ agent_scd_change_pin (int chvno, const char *serialno)
rc = start_agent (NULL, 1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno); snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, NULL, NULL, rc = assuan_transact (agent_ctx, line,
default_inq_cb, NULL, NULL, NULL); NULL, NULL,
default_inq_cb, &dfltparm,
NULL, NULL);
status_sc_op_failure (rc); status_sc_op_failure (rc);
return rc; return rc;
} }
@ -1056,16 +1168,21 @@ agent_scd_checkpin (const char *serialno)
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
rc = start_agent (NULL, 1); rc = start_agent (NULL, 1);
if (rc) if (rc)
return rc; return rc;
dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno); snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
rc = assuan_transact (agent_ctx, line, rc = assuan_transact (agent_ctx, line,
NULL, NULL, NULL, NULL,
default_inq_cb, NULL, NULL, NULL); default_inq_cb, &dfltparm,
NULL, NULL);
status_sc_op_failure (rc); status_sc_op_failure (rc);
return rc; return rc;
} }
@ -1101,12 +1218,16 @@ agent_get_passphrase (const char *cache_id,
char *arg3 = NULL; char *arg3 = NULL;
char *arg4 = NULL; char *arg4 = NULL;
membuf_t data; membuf_t data;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
*r_passphrase = NULL; *r_passphrase = NULL;
rc = start_agent (NULL, 0); rc = start_agent (NULL, 0);
if (rc) if (rc)
return rc; return rc;
dfltparm.ctx = agent_ctx;
/* Check that the gpg-agent understands the repeat option. */ /* Check that the gpg-agent understands the repeat option. */
if (assuan_transact (agent_ctx, if (assuan_transact (agent_ctx,
@ -1144,7 +1265,8 @@ agent_get_passphrase (const char *cache_id,
init_membuf_secure (&data, 64); init_membuf_secure (&data, 64);
rc = assuan_transact (agent_ctx, line, rc = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, membuf_data_cb, &data,
default_inq_cb, NULL, NULL, NULL); default_inq_cb, &dfltparm,
NULL, NULL);
if (rc) if (rc)
xfree (get_membuf (&data, NULL)); xfree (get_membuf (&data, NULL));
@ -1171,6 +1293,9 @@ agent_clear_passphrase (const char *cache_id)
{ {
int rc; int rc;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
if (!cache_id || !*cache_id) if (!cache_id || !*cache_id)
return 0; return 0;
@ -1178,11 +1303,14 @@ agent_clear_passphrase (const char *cache_id)
rc = start_agent (NULL, 0); rc = start_agent (NULL, 0);
if (rc) if (rc)
return rc; return rc;
dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id); snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
return assuan_transact (agent_ctx, line, NULL, NULL, return assuan_transact (agent_ctx, line,
default_inq_cb, NULL, NULL, NULL); NULL, NULL,
default_inq_cb, &dfltparm,
NULL, NULL);
} }
@ -1194,10 +1322,14 @@ gpg_agent_get_confirmation (const char *desc)
int rc; int rc;
char *tmp; char *tmp;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
rc = start_agent (NULL, 0); rc = start_agent (NULL, 0);
if (rc) if (rc)
return rc; return rc;
dfltparm.ctx = agent_ctx;
tmp = percent_plus_escape (desc); tmp = percent_plus_escape (desc);
if (!tmp) if (!tmp)
@ -1206,8 +1338,10 @@ gpg_agent_get_confirmation (const char *desc)
line[DIM(line)-1] = 0; line[DIM(line)-1] = 0;
xfree (tmp); xfree (tmp);
rc = assuan_transact (agent_ctx, line, NULL, NULL, rc = assuan_transact (agent_ctx, line,
default_inq_cb, NULL, NULL, NULL); NULL, NULL,
default_inq_cb, &dfltparm,
NULL, NULL);
return rc; return rc;
} }
@ -1438,11 +1572,11 @@ inq_genkey_parms (void *opaque, const char *line)
if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8])) if (!strncmp (line, "KEYPARAM", 8) && (line[8]==' '||!line[8]))
{ {
err = assuan_send_data (parm->ctx, err = assuan_send_data (parm->dflt->ctx,
parm->keyparms, strlen (parm->keyparms)); parm->keyparms, strlen (parm->keyparms));
} }
else else
err = default_inq_cb (parm->ctrl, line); err = default_inq_cb (parm->dflt, line);
return err; return err;
} }
@ -1459,15 +1593,20 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
gpg_error_t err; gpg_error_t err;
struct genkey_parm_s gk_parm; struct genkey_parm_s gk_parm;
struct cache_nonce_parm_s cn_parm; struct cache_nonce_parm_s cn_parm;
struct default_inq_parm_s dfltparm;
membuf_t data; membuf_t data;
size_t len; size_t len;
unsigned char *buf; unsigned char *buf;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
*r_pubkey = NULL; *r_pubkey = NULL;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET", err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL, NULL);
@ -1475,8 +1614,7 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
return err; return err;
init_membuf (&data, 1024); init_membuf (&data, 1024);
gk_parm.ctrl = ctrl; gk_parm.dflt = &dfltparm;
gk_parm.ctx = agent_ctx;
gk_parm.keyparms = keyparms; gk_parm.keyparms = keyparms;
snprintf (line, sizeof line, "GENKEY%s%s%s", snprintf (line, sizeof line, "GENKEY%s%s%s",
no_protection? " --no-protection":"", no_protection? " --no-protection":"",
@ -1520,11 +1658,16 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
size_t len; size_t len;
unsigned char *buf; unsigned char *buf;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
*r_pubkey = NULL; *r_pubkey = NULL;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL); err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
if (err) if (err)
@ -1535,7 +1678,8 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
init_membuf (&data, 1024); init_membuf (&data, 1024);
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, membuf_data_cb, &data,
default_inq_cb, NULL, NULL, NULL); default_inq_cb, &dfltparm,
NULL, NULL);
if (err) if (err)
{ {
xfree (get_membuf (&data, &len)); xfree (get_membuf (&data, &len));
@ -1564,17 +1708,26 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
gpg_error_t gpg_error_t
agent_pksign (ctrl_t ctrl, const char *cache_nonce, agent_pksign (ctrl_t ctrl, const char *cache_nonce,
const char *keygrip, const char *desc, const char *keygrip, const char *desc,
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
unsigned char *digest, size_t digestlen, int digestalgo, unsigned char *digest, size_t digestlen, int digestalgo,
gcry_sexp_t *r_sigval) gcry_sexp_t *r_sigval)
{ {
gpg_error_t err; gpg_error_t err;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
membuf_t data; membuf_t data;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
dfltparm.keyinfo.keyid = keyid;
dfltparm.keyinfo.mainkeyid = mainkeyid;
dfltparm.keyinfo.pubkey_algo = pubkey_algo;
*r_sigval = NULL; *r_sigval = NULL;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
if (digestlen*2 + 50 > DIM(line)) if (digestlen*2 + 50 > DIM(line))
return gpg_error (GPG_ERR_GENERAL); return gpg_error (GPG_ERR_GENERAL);
@ -1612,8 +1765,9 @@ agent_pksign (ctrl_t ctrl, const char *cache_nonce,
cache_nonce? " -- ":"", cache_nonce? " -- ":"",
cache_nonce? cache_nonce:""); cache_nonce? cache_nonce:"");
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, default_inq_cb, ctrl, membuf_data_cb, &data,
NULL, NULL); default_inq_cb, &dfltparm,
NULL, NULL);
if (err) if (err)
xfree (get_membuf (&data, NULL)); xfree (get_membuf (&data, NULL));
else else
@ -1646,11 +1800,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10])) if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
{ {
assuan_begin_confidential (parm->ctx); assuan_begin_confidential (parm->ctx);
rc = assuan_send_data (parm->ctx, parm->ciphertext, parm->ciphertextlen); rc = assuan_send_data (parm->dflt->ctx,
parm->ciphertext, parm->ciphertextlen);
assuan_end_confidential (parm->ctx); assuan_end_confidential (parm->ctx);
} }
else else
rc = default_inq_cb (parm->ctrl, line); rc = default_inq_cb (parm->dflt, line);
return rc; return rc;
} }
@ -1659,9 +1814,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
/* Call the agent to do a decrypt operation using the key identified /* Call the agent to do a decrypt operation using the key identified
by the hex string KEYGRIP and the input data S_CIPHERTEXT. On the by the hex string KEYGRIP and the input data S_CIPHERTEXT. On the
success the decoded value is stored verbatim at R_BUF and its success the decoded value is stored verbatim at R_BUF and its
length at R_BUF; the callers needs to release it. */ length at R_BUF; the callers needs to release it. KEYID, MAINKEYID
and PUBKEY_ALGO are used to construct additional promots or status
messages. */
gpg_error_t gpg_error_t
agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
gcry_sexp_t s_ciphertext, gcry_sexp_t s_ciphertext,
unsigned char **r_buf, size_t *r_buflen) unsigned char **r_buf, size_t *r_buflen)
{ {
@ -1670,6 +1828,13 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
membuf_t data; membuf_t data;
size_t n, len; size_t n, len;
char *p, *buf, *endp; char *p, *buf, *endp;
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
dfltparm.keyinfo.keyid = keyid;
dfltparm.keyinfo.mainkeyid = mainkeyid;
dfltparm.keyinfo.pubkey_algo = pubkey_algo;
if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen) if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
@ -1678,6 +1843,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
err = assuan_transact (agent_ctx, "RESET", err = assuan_transact (agent_ctx, "RESET",
NULL, NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL, NULL);
@ -1703,7 +1869,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
{ {
struct cipher_parm_s parm; struct cipher_parm_s parm;
parm.ctrl = ctrl; parm.dflt = &dfltparm;
parm.ctx = agent_ctx; parm.ctx = agent_ctx;
err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen); err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen);
if (err) if (err)
@ -1772,11 +1938,16 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
size_t len; size_t len;
unsigned char *buf; unsigned char *buf;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
*r_kek = NULL; *r_kek = NULL;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s", snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s",
forexport? "--export":"--import"); forexport? "--export":"--import");
@ -1784,7 +1955,8 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
init_membuf_secure (&data, 64); init_membuf_secure (&data, 64);
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, membuf_data_cb, &data,
default_inq_cb, ctrl, NULL, NULL); default_inq_cb, &dfltparm,
NULL, NULL);
if (err) if (err)
{ {
xfree (get_membuf (&data, &len)); xfree (get_membuf (&data, &len));
@ -1809,10 +1981,10 @@ inq_import_key_parms (void *opaque, const char *line)
if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7])) if (!strncmp (line, "KEYDATA", 7) && (line[7]==' '||!line[7]))
{ {
err = assuan_send_data (parm->ctx, parm->key, parm->keylen); err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen);
} }
else else
err = default_inq_cb (parm->ctrl, line); err = default_inq_cb (parm->dflt, line);
return err; return err;
} }
@ -1827,10 +1999,15 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
struct import_key_parm_s parm; struct import_key_parm_s parm;
struct cache_nonce_parm_s cn_parm; struct cache_nonce_parm_s cn_parm;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
if (desc) if (desc)
{ {
@ -1842,8 +2019,7 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
return err; return err;
} }
parm.ctrl = ctrl; parm.dflt = &dfltparm;
parm.ctx = agent_ctx;
parm.key = key; parm.key = key;
parm.keylen = keylen; parm.keylen = keylen;
@ -1853,7 +2029,8 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
cn_parm.cache_nonce_addr = cache_nonce_addr; cn_parm.cache_nonce_addr = cache_nonce_addr;
cn_parm.passwd_nonce_addr = NULL; cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
NULL, NULL, inq_import_key_parms, &parm, NULL, NULL,
inq_import_key_parms, &parm,
cache_nonce_status_cb, &cn_parm); cache_nonce_status_cb, &cn_parm);
return err; return err;
} }
@ -1875,12 +2052,17 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
size_t len; size_t len;
unsigned char *buf; unsigned char *buf;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
*r_result = NULL; *r_result = NULL;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
if (desc) if (desc)
{ {
@ -1901,7 +2083,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
cn_parm.passwd_nonce_addr = NULL; cn_parm.passwd_nonce_addr = NULL;
err = assuan_transact (agent_ctx, line, err = assuan_transact (agent_ctx, line,
membuf_data_cb, &data, membuf_data_cb, &data,
default_inq_cb, ctrl, default_inq_cb, &dfltparm,
cache_nonce_status_cb, &cn_parm); cache_nonce_status_cb, &cn_parm);
if (err) if (err)
{ {
@ -1931,14 +2113,20 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
gpg_error_t err; gpg_error_t err;
struct cache_nonce_parm_s cn_parm; struct cache_nonce_parm_s cn_parm;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct default_inq_parm_s dfltparm;
memset (&dfltparm, 0, sizeof dfltparm);
dfltparm.ctrl = ctrl;
err = start_agent (ctrl, 0); err = start_agent (ctrl, 0);
if (err) if (err)
return err; return err;
dfltparm.ctx = agent_ctx;
if (!hexkeygrip || strlen (hexkeygrip) != 40) if (!hexkeygrip || strlen (hexkeygrip) != 40)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (desc) if (desc)
{ {
snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc); snprintf (line, DIM(line)-1, "SETKEYDESC %s", desc);
@ -1957,7 +2145,7 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
cn_parm.cache_nonce_addr = cache_nonce_addr; cn_parm.cache_nonce_addr = cache_nonce_addr;
cn_parm.passwd_nonce_addr = passwd_nonce_addr; cn_parm.passwd_nonce_addr = passwd_nonce_addr;
err = assuan_transact (agent_ctx, line, NULL, NULL, err = assuan_transact (agent_ctx, line, NULL, NULL,
default_inq_cb, ctrl, default_inq_cb, &dfltparm,
cache_nonce_status_cb, &cn_parm); cache_nonce_status_cb, &cn_parm);
return err; return err;
} }

View File

@ -81,6 +81,10 @@ int agent_learn (struct agent_card_info_s *info);
/* Update INFO with the attribute NAME. */ /* Update INFO with the attribute NAME. */
int agent_scd_getattr (const char *name, struct agent_card_info_s *info); int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
/* Send the KEYTOCARD command. */
int agent_keytocard (const char *hexgrip, int keyno, int force,
const char *serialno, const char *timestamp);
/* Send a SETATTR command to the SCdaemon. */ /* Send a SETATTR command to the SCdaemon. */
int agent_scd_setattr (const char *name, int agent_scd_setattr (const char *name,
const unsigned char *value, size_t valuelen, const unsigned char *value, size_t valuelen,
@ -155,12 +159,14 @@ gpg_error_t agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
/* Create a signature. */ /* Create a signature. */
gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce, gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
const char *hexkeygrip, const char *desc, const char *hexkeygrip, const char *desc,
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
unsigned char *digest, size_t digestlen, unsigned char *digest, size_t digestlen,
int digestalgo, int digestalgo,
gcry_sexp_t *r_sigval); gcry_sexp_t *r_sigval);
/* Decrypt a ciphertext. */ /* Decrypt a ciphertext. */
gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
gcry_sexp_t s_ciphertext, gcry_sexp_t s_ciphertext,
unsigned char **r_buf, size_t *r_buflen); unsigned char **r_buf, size_t *r_buflen);

View File

@ -1264,6 +1264,7 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key", if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
_("Replace existing key? (y/N) "))) _("Replace existing key? (y/N) ")))
return -1; return -1;
return 1;
} }
return 0; return 0;
} }
@ -1484,7 +1485,7 @@ card_generate_subkey (KBNODE pub_keyblock)
tty_printf(_("Invalid selection.\n")); tty_printf(_("Invalid selection.\n"));
} }
if (replace_existing_key_p (&info, keyno)) if (replace_existing_key_p (&info, keyno) < 0)
{ {
err = gpg_error (GPG_ERR_CANCELED); err = gpg_error (GPG_ERR_CANCELED);
goto leave; goto leave;
@ -1531,152 +1532,99 @@ card_generate_subkey (KBNODE pub_keyblock)
int int
card_store_subkey (KBNODE node, int use) card_store_subkey (KBNODE node, int use)
{ {
log_info ("FIXME: card_store_subkey has not yet been implemented\n"); struct agent_card_info_s info;
/* struct agent_card_info_s info; */ int okay = 0;
/* int okay = 0; */ unsigned int nbits;
/* int rc; */ int allow_keyno[3];
/* int keyno, i; */ int keyno;
/* PKT_secret_key *copied_sk = NULL; */ PKT_public_key *pk;
/* PKT_secret_key *sk; */ gpg_error_t err;
/* size_t n; */ char *hexgrip;
/* const char *s; */ int rc;
/* int allow_keyno[3]; */ gnupg_isotime_t timebuf;
/* unsigned int nbits; */
assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
/* assert (node->pkt->pkttype == PKT_SECRET_KEY */ pk = node->pkt->pkt.public_key;
/* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
/* sk = node->pkt->pkt.secret_key; */
/* if (get_info_for_key_operation (&info)) */ if (get_info_for_key_operation (&info))
/* return 0; */ return 0;
/* if (!info.extcap.ki) */ if (!info.extcap.ki)
/* { */ {
/* tty_printf ("The card does not support the import of keys\n"); */ tty_printf ("The card does not support the import of keys\n");
/* tty_printf ("\n"); */ tty_printf ("\n");
/* goto leave; */ goto leave;
/* } */ }
/* show_card_key_info (&info); */ nbits = nbits_from_pk (pk);
/* nbits = nbits_from_sk (sk); */ if (!is_RSA (pk->pubkey_algo) || (!info.is_v2 && nbits != 1024) )
{
tty_printf ("You may only store a 1024 bit RSA key on the card\n");
tty_printf ("\n");
goto leave;
}
/* if (!is_RSA (sk->pubkey_algo) || (!info.is_v2 && nbits != 1024) ) */ allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
/* { */ allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
/* tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */ allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
/* tty_printf ("\n"); */
/* goto leave; */
/* } */
/* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */ tty_printf (_("Please select where to store the key:\n"));
/* allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC))); */
/* allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH))); */
/* tty_printf (_("Please select where to store the key:\n")); */ if (allow_keyno[0])
tty_printf (_(" (1) Signature key\n"));
if (allow_keyno[1])
tty_printf (_(" (2) Encryption key\n"));
if (allow_keyno[2])
tty_printf (_(" (3) Authentication key\n"));
/* if (allow_keyno[0]) */ for (;;)
/* tty_printf (_(" (1) Signature key\n")); */ {
/* if (allow_keyno[1]) */ char *answer = cpr_get ("cardedit.genkeys.storekeytype",
/* tty_printf (_(" (2) Encryption key\n")); */ _("Your selection? "));
/* if (allow_keyno[2]) */ cpr_kill_prompt();
/* tty_printf (_(" (3) Authentication key\n")); */ if (*answer == CONTROL_D || !*answer)
{
xfree (answer);
goto leave;
}
keyno = *answer? atoi(answer): 0;
xfree(answer);
if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
{
if (info.is_v2 && !info.extcap.aac
&& info.key_attr[keyno-1].nbits != nbits)
{
tty_printf ("Key does not match the card's capability.\n");
}
else
break; /* Okay. */
}
else
tty_printf(_("Invalid selection.\n"));
}
/* for (;;) */ if ((rc = replace_existing_key_p (&info, keyno)) < 0)
/* { */ goto leave;
/* char *answer = cpr_get ("cardedit.genkeys.storekeytype", */
/* _("Your selection? ")); */
/* cpr_kill_prompt(); */
/* if (*answer == CONTROL_D || !*answer) */
/* { */
/* xfree (answer); */
/* goto leave; */
/* } */
/* keyno = *answer? atoi(answer): 0; */
/* xfree(answer); */
/* if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1]) */
/* { */
/* if (info.is_v2 && !info.extcap.aac */
/* && info.key_attr[keyno-1].nbits != nbits) */
/* { */
/* tty_printf ("Key does not match the card's capability.\n"); */
/* } */
/* else */
/* break; /\* Okay. *\/ */
/* } */
/* else */
/* tty_printf(_("Invalid selection.\n")); */
/* } */
/* if (replace_existing_key_p (&info, keyno)) */ err = hexkeygrip_from_pk (pk, &hexgrip);
/* goto leave; */ if (err)
goto leave;
/* /\* Unprotect key. *\/ */ epoch2isotime (timebuf, (time_t)pk->timestamp);
/* switch (is_secret_key_protected (sk) ) */ agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
/* { */
/* case 0: /\* Not protected. *\/ */
/* break; */
/* case -1: */
/* log_error (_("unknown key protection algorithm\n")); */
/* goto leave; */
/* default: */
/* if (sk->protect.s2k.mode == 1001) */
/* { */
/* log_error (_("secret parts of key are not available\n")); */
/* goto leave; */
/* } */
/* if (sk->protect.s2k.mode == 1002) */
/* { */
/* log_error (_("secret key already stored on a card\n")); */
/* goto leave; */
/* } */
/* /\* We better copy the key before we unprotect it. *\/ */
/* copied_sk = sk = copy_secret_key (NULL, sk); */
/* rc = 0/\*check_secret_key (sk, 0)*\/; */
/* if (rc) */
/* goto leave; */
/* } */
/* #warning code save_unprotected_key_to_card */ if (rc)
/* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */ log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
/* /\* if (rc) *\/ */ else
/* /\* { *\/ */ okay = 1;
/* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */ xfree (hexgrip);
/* /\* goto leave; *\/ */
/* /\* } *\/ */
/* /\* Get back to the maybe protected original secret key. *\/ */ leave:
/* if (copied_sk) */ agent_release_card_info (&info);
/* { */ return okay;
/* free_secret_key (copied_sk); */
/* copied_sk = NULL; */
/* } */
/* sk = node->pkt->pkt.secret_key; */
/* /\* Get rid of the secret key parameters and store the serial numer. *\/ */
/* n = pubkey_get_nskey (sk->pubkey_algo); */
/* for (i=pubkey_get_npkey (sk->pubkey_algo); i < n; i++) */
/* { */
/* gcry_mpi_release (sk->skey[i]); */
/* sk->skey[i] = NULL; */
/* } */
/* i = pubkey_get_npkey (sk->pubkey_algo); */
/* sk->skey[i] = gcry_mpi_set_opaque (NULL, xstrdup ("dummydata"), 10*8); */
/* sk->is_protected = 1; */
/* sk->protect.s2k.mode = 1002; */
/* s = info.serialno; */
/* for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; */
/* sk->protect.ivlen++, s += 2) */
/* sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); */
/* okay = 1; */
/* leave: */
/* if (copied_sk) */
/* free_secret_key (copied_sk); */
/* agent_release_card_info (&info); */
/* return okay; */
return -1;
} }

View File

@ -56,6 +56,7 @@
#include "asshelp.h" #include "asshelp.h"
#include "call-dirmngr.h" #include "call-dirmngr.h"
#include "../common/init.h" #include "../common/init.h"
#include "../common/shareddefs.h"
#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__) #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
#define MY_O_BINARY O_BINARY #define MY_O_BINARY O_BINARY
@ -217,6 +218,7 @@ enum cmd_and_opt_values
oPassphraseFD, oPassphraseFD,
oPassphraseFile, oPassphraseFile,
oPassphraseRepeat, oPassphraseRepeat,
oPinentryMode,
oCommandFD, oCommandFD,
oCommandFile, oCommandFile,
oQuickRandom, oQuickRandom,
@ -611,6 +613,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"), ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"),
ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"), ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"),
ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"), ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
ARGPARSE_s_i (oCommandFD, "command-fd", "@"), ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
ARGPARSE_s_s (oCommandFile, "command-file", "@"), ARGPARSE_s_s (oCommandFile, "command-file", "@"),
ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"), ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
@ -2594,7 +2597,16 @@ main (int argc, char **argv)
case oPassphraseFile: case oPassphraseFile:
pwfd = open_info_file (pargs.r.ret_str, 0, 1); pwfd = open_info_file (pargs.r.ret_str, 0, 1);
break; break;
case oPassphraseRepeat: opt.passphrase_repeat=pargs.r.ret_int; break; case oPassphraseRepeat:
opt.passphrase_repeat = pargs.r.ret_int;
break;
case oPinentryMode:
opt.pinentry_mode = parse_pinentry_mode (pargs.r.ret_str);
if (opt.pinentry_mode == -1)
log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
break;
case oCommandFD: case oCommandFD:
opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0); opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
break; break;

View File

@ -181,6 +181,7 @@ unsigned char encode_s2k_iterations (int iterations);
assuan_context_t agent_open (int try, const char *orig_codeset); assuan_context_t agent_open (int try, const char *orig_codeset);
void agent_close (assuan_context_t ctx); void agent_close (assuan_context_t ctx);
int have_static_passphrase(void); int have_static_passphrase(void);
const char *get_static_passphrase (void);
void set_passphrase_from_string(const char *pass); void set_passphrase_from_string(const char *pass);
void read_passphrase_from_fd( int fd ); void read_passphrase_from_fd( int fd );
void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo ); void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
@ -196,6 +197,8 @@ void set_next_passphrase( const char *s );
char *get_last_passphrase(void); char *get_last_passphrase(void);
void next_to_last_passphrase(void); void next_to_last_passphrase(void);
void emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo);
char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped); char *gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped);

View File

@ -353,6 +353,8 @@ void unblock_all_signals(void);
/*-- server.c --*/ /*-- server.c --*/
int gpg_server (ctrl_t); int gpg_server (ctrl_t);
gpg_error_t gpg_proxy_pinentry_notify (ctrl_t ctrl,
const unsigned char *line);
#ifdef ENABLE_CARD_SUPPORT #ifdef ENABLE_CARD_SUPPORT
/*-- card-util.c --*/ /*-- card-util.c --*/

View File

@ -242,6 +242,7 @@ struct
} *auto_key_locate; } *auto_key_locate;
int passphrase_repeat; int passphrase_repeat;
int pinentry_mode;
} opt; } opt;
/* CTRL is used to keep some global variables we currently can't /* CTRL is used to keep some global variables we currently can't

View File

@ -43,7 +43,7 @@
#include "i18n.h" #include "i18n.h"
#include "status.h" #include "status.h"
#include "call-agent.h" #include "call-agent.h"
#include "../common/shareddefs.h"
static char *fd_passwd = NULL; static char *fd_passwd = NULL;
static char *next_pw = NULL; static char *next_pw = NULL;
@ -104,9 +104,21 @@ encode_s2k_iterations (int iterations)
int int
have_static_passphrase() have_static_passphrase()
{ {
return !!fd_passwd && opt.batch; return (!!fd_passwd
&& (opt.batch || opt.pinentry_mode == PINENTRY_MODE_LOOPBACK));
} }
/* Return a static passphrase. The returned value is only valid as
long as no other passphrase related function is called. NULL may
be returned if no passphrase has been set; better use
have_static_passphrase first. */
const char *
get_static_passphrase (void)
{
return fd_passwd;
}
/**************** /****************
* Set the passphrase to be used for the next query and only for the next * Set the passphrase to be used for the next query and only for the next
* one. * one.
@ -156,7 +168,7 @@ read_passphrase_from_fd( int fd )
int i, len; int i, len;
char *pw; char *pw;
if ( !opt.batch ) if ( !opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
{ /* Not used but we have to do a dummy read, so that it won't end { /* Not used but we have to do a dummy read, so that it won't end
up at the begin of the message if the quite usual trick to up at the begin of the message if the quite usual trick to
prepend the passphtrase to the message is used. */ prepend the passphtrase to the message is used. */
@ -187,7 +199,7 @@ read_passphrase_from_fd( int fd )
break; break;
} }
pw[i] = 0; pw[i] = 0;
if (!opt.batch) if (!opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
tty_printf("\b\b\b \n" ); tty_printf("\b\b\b \n" );
xfree ( fd_passwd ); xfree ( fd_passwd );
@ -458,30 +470,9 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
if ( keyid ) if ( keyid )
{ {
u32 used_kid[2]; emit_status_need_passphrase (keyid,
char *us; keyid[2] && keyid[3]? keyid+2:NULL,
pubkey_algo);
if ( keyid[2] && keyid[3] )
{
used_kid[0] = keyid[2];
used_kid[1] = keyid[3];
}
else
{
used_kid[0] = keyid[0];
used_kid[1] = keyid[1];
}
us = get_long_user_id_string ( keyid );
write_status_text ( STATUS_USERID_HINT, us );
xfree(us);
snprintf (buf, sizeof buf -1, "%08lX%08lX %08lX%08lX %d 0",
(ulong)keyid[0], (ulong)keyid[1],
(ulong)used_kid[0], (ulong)used_kid[1],
pubkey_algo );
write_status_text ( STATUS_NEED_PASSPHRASE, buf );
} }
else else
{ {
@ -614,6 +605,29 @@ passphrase_to_dek (u32 *keyid, int pubkey_algo,
} }
/* Emit the USERID_HINT and the NEED_PASSPHRASE status messages.
MAINKEYID may be NULL. */
void
emit_status_need_passphrase (u32 *keyid, u32 *mainkeyid, int pubkey_algo)
{
char buf[50];
char *us;
us = get_long_user_id_string (keyid);
write_status_text (STATUS_USERID_HINT, us);
xfree (us);
snprintf (buf, sizeof buf -1, "%08lX%08lX %08lX%08lX %d 0",
(ulong)keyid[0],
(ulong)keyid[1],
(ulong)(mainkeyid? mainkeyid[0]:keyid[0]),
(ulong)(mainkeyid? mainkeyid[1]:keyid[1]),
pubkey_algo);
write_status_text (STATUS_NEED_PASSPHRASE, buf);
}
/* Return an allocated utf-8 string describing the key PK. If ESCAPED /* Return an allocated utf-8 string describing the key PK. If ESCAPED
is true spaces and control characters are percent or plus escaped. is true spaces and control characters are percent or plus escaped.
MODE 0 is for the common prompt, MODE 1 for the import prompt. */ MODE 0 is for the common prompt, MODE 1 for the import prompt. */

View File

@ -201,7 +201,9 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
/* Decrypt. */ /* Decrypt. */
desc = gpg_format_keydesc (sk, 0, 1); desc = gpg_format_keydesc (sk, 0, 1);
err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe); err = agent_pkdecrypt (NULL, keygrip,
desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
s_data, &frame, &nframe);
xfree (desc); xfree (desc);
gcry_sexp_release (s_data); gcry_sexp_release (s_data);
if (err) if (err)

View File

@ -50,6 +50,9 @@ struct server_local_s
/* List of prepared recipients. */ /* List of prepared recipients. */
pk_list_t recplist; pk_list_t recplist;
/* Set if pinentry notifications should be passed back to the
client. */
int allow_pinentry_notify;
}; };
@ -105,9 +108,8 @@ has_option (const char *line, const char *name)
static gpg_error_t static gpg_error_t
option_handler (assuan_context_t ctx, const char *key, const char *value) option_handler (assuan_context_t ctx, const char *key, const char *value)
{ {
/* ctrl_t ctrl = assuan_get_pointer (ctx); */ ctrl_t ctrl = assuan_get_pointer (ctx);
(void)ctx;
(void)value; (void)value;
/* Fixme: Implement the tty and locale args. */ /* Fixme: Implement the tty and locale args. */
@ -136,6 +138,10 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
{ {
/* This is for now a dummy option. */ /* This is for now a dummy option. */
} }
else if (!strcmp (key, "allow-pinentry-notify"))
{
ctrl->server_local->allow_pinentry_notify = 1;
}
else else
return gpg_error (GPG_ERR_UNKNOWN_OPTION); return gpg_error (GPG_ERR_UNKNOWN_OPTION);
@ -768,3 +774,29 @@ gpg_server (ctrl_t ctrl)
assuan_release (ctx); assuan_release (ctx);
return rc; return rc;
} }
/* Helper to notify the client about Pinentry events. Because that
might disturb some older clients, this is only done when enabled
via an option. If it is not enabled we tell Windows to allow
setting the foreground window right here. Returns an gpg error
code. */
gpg_error_t
gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
{
if (!ctrl || !ctrl->server_local
|| !ctrl->server_local->allow_pinentry_notify)
{
gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
/* Client might be interested in that event - send as status line. */
if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
&& (line[17]==' '||!line[17]))
{
for (line += 17; *line && spacep (line); line++)
;
write_status_text (STATUS_PINENTRY_LAUNCHED, line);
}
return 0;
}
return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
}

View File

@ -272,6 +272,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
desc = gpg_format_keydesc (pksk, 0, 1); desc = gpg_format_keydesc (pksk, 0, 1);
err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc, err = agent_pksign (NULL/*ctrl*/, cache_nonce, hexgrip, desc,
pksk->keyid, pksk->main_keyid, pksk->pubkey_algo,
dp, gcry_md_get_algo_dlen (mdalgo), mdalgo, dp, gcry_md_get_algo_dlen (mdalgo), mdalgo,
&s_sigval); &s_sigval);
xfree (desc); xfree (desc);
@ -1604,6 +1605,8 @@ update_keysig_packet( PKT_signature **ret_sig,
/* create a new signature packet */ /* create a new signature packet */
sig = copy_signature (NULL, orig_sig); sig = copy_signature (NULL, orig_sig);
sig->digest_algo=digest_algo;
/* We need to create a new timestamp so that new sig expiration /* We need to create a new timestamp so that new sig expiration
calculations are done correctly... */ calculations are done correctly... */
sig->timestamp=make_timestamp(); sig->timestamp=make_timestamp();

7212
po/ja.po

File diff suppressed because it is too large Load Diff

View File

@ -60,10 +60,9 @@
#include "exechelp.h" #include "exechelp.h"
#endif /* GNUPG_MAJOR_VERSION != 1 */ #endif /* GNUPG_MAJOR_VERSION != 1 */
#include "iso7816.h"
#include "apdu.h" #include "apdu.h"
#include "ccid-driver.h" #include "ccid-driver.h"
#include "iso7816.h"
/* Due to conflicting use of threading libraries we usually can't link /* Due to conflicting use of threading libraries we usually can't link
against libpcsclite. Instead we use a wrapper program. */ against libpcsclite. Instead we use a wrapper program. */
@ -83,16 +82,6 @@
#define DLSTDCALL #define DLSTDCALL
#endif #endif
/* Helper to pass parameters related to keypad based operations. */
struct pininfo_s
{
int mode;
int minlen;
int maxlen;
int padlen;
};
/* A structure to collect information pertaining to one reader /* A structure to collect information pertaining to one reader
slot. */ slot. */
struct reader_table_s { struct reader_table_s {
@ -107,12 +96,12 @@ struct reader_table_s {
int (*reset_reader)(int); int (*reset_reader)(int);
int (*get_status_reader)(int, unsigned int *); int (*get_status_reader)(int, unsigned int *);
int (*send_apdu_reader)(int,unsigned char *,size_t, int (*send_apdu_reader)(int,unsigned char *,size_t,
unsigned char *, size_t *, struct pininfo_s *); unsigned char *, size_t *, pininfo_t *);
int (*check_keypad)(int, int, int, int, int, int); int (*check_pinpad)(int, int, pininfo_t *);
void (*dump_status_reader)(int); void (*dump_status_reader)(int);
int (*set_progress_cb)(int, gcry_handler_progress_t, void*); int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *); int (*pinpad_verify)(int, int, int, int, int, pininfo_t *);
int (*keypad_modify)(int, int, int, int, int, struct pininfo_s *); int (*pinpad_modify)(int, int, int, int, int, pininfo_t *);
struct { struct {
ccid_driver_t handle; ccid_driver_t handle;
@ -330,12 +319,11 @@ static int reset_pcsc_reader (int slot);
static int apdu_get_status_internal (int slot, int hang, int no_atr_reset, static int apdu_get_status_internal (int slot, int hang, int no_atr_reset,
unsigned int *status, unsigned int *status,
unsigned int *changed); unsigned int *changed);
static int check_pcsc_keypad (int slot, int command, int pin_mode, static int check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo);
int pinlen_min, int pinlen_max, int pin_padlen); static int pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, pininfo_t *pininfo);
struct pininfo_s *pininfo); static int pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, pininfo_t *pininfo);
struct pininfo_s *pininfo);
@ -381,11 +369,11 @@ new_reader_slot (void)
reader_table[reader].reset_reader = NULL; reader_table[reader].reset_reader = NULL;
reader_table[reader].get_status_reader = NULL; reader_table[reader].get_status_reader = NULL;
reader_table[reader].send_apdu_reader = NULL; reader_table[reader].send_apdu_reader = NULL;
reader_table[reader].check_keypad = check_pcsc_keypad; reader_table[reader].check_pinpad = check_pcsc_pinpad;
reader_table[reader].dump_status_reader = NULL; reader_table[reader].dump_status_reader = NULL;
reader_table[reader].set_progress_cb = NULL; reader_table[reader].set_progress_cb = NULL;
reader_table[reader].keypad_verify = pcsc_keypad_verify; reader_table[reader].pinpad_verify = pcsc_pinpad_verify;
reader_table[reader].keypad_modify = pcsc_keypad_modify; reader_table[reader].pinpad_modify = pcsc_pinpad_modify;
reader_table[reader].used = 1; reader_table[reader].used = 1;
reader_table[reader].any_status = 0; reader_table[reader].any_status = 0;
@ -440,7 +428,7 @@ host_sw_string (long err)
case SW_HOST_GENERAL_ERROR: return "general error"; case SW_HOST_GENERAL_ERROR: return "general error";
case SW_HOST_NO_READER: return "no reader"; case SW_HOST_NO_READER: return "no reader";
case SW_HOST_ABORTED: return "aborted"; case SW_HOST_ABORTED: return "aborted";
case SW_HOST_NO_KEYPAD: return "no keypad"; case SW_HOST_NO_PINPAD: return "no pinpad";
case SW_HOST_ALREADY_CONNECTED: return "already connected"; case SW_HOST_ALREADY_CONNECTED: return "already connected";
default: return "unknown host status error"; default: return "unknown host status error";
} }
@ -608,7 +596,7 @@ ct_get_status (int slot, unsigned int *status)
set to BUFLEN. Returns: CT API error code. */ set to BUFLEN. Returns: CT API error code. */
static int static int
ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen, ct_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo) unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
{ {
int rc; int rc;
unsigned char dad[1], sad[1]; unsigned char dad[1], sad[1];
@ -673,10 +661,10 @@ open_ct_reader (int port)
reader_table[reader].reset_reader = reset_ct_reader; reader_table[reader].reset_reader = reset_ct_reader;
reader_table[reader].get_status_reader = ct_get_status; reader_table[reader].get_status_reader = ct_get_status;
reader_table[reader].send_apdu_reader = ct_send_apdu; reader_table[reader].send_apdu_reader = ct_send_apdu;
reader_table[reader].check_keypad = NULL; reader_table[reader].check_pinpad = NULL;
reader_table[reader].dump_status_reader = ct_dump_reader_status; reader_table[reader].dump_status_reader = ct_dump_reader_status;
reader_table[reader].keypad_verify = NULL; reader_table[reader].pinpad_verify = NULL;
reader_table[reader].keypad_modify = NULL; reader_table[reader].pinpad_modify = NULL;
dump_reader_status (reader); dump_reader_status (reader);
return reader; return reader;
@ -1039,7 +1027,7 @@ pcsc_get_status (int slot, unsigned int *status)
static int static int
pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen, pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, unsigned char *buffer, size_t *buflen,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
long err; long err;
struct pcsc_io_request_s send_pci; struct pcsc_io_request_s send_pci;
@ -1075,7 +1063,7 @@ pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
static int static int
pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen, pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, unsigned char *buffer, size_t *buflen,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
long err; long err;
reader_table_t slotp; reader_table_t slotp;
@ -1195,7 +1183,7 @@ pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
static int static int
pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, unsigned char *buffer, size_t *buflen,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
#ifdef NEED_PCSC_WRAPPER #ifdef NEED_PCSC_WRAPPER
return pcsc_send_apdu_wrapped (slot, apdu, apdulen, buffer, buflen, pininfo); return pcsc_send_apdu_wrapped (slot, apdu, apdulen, buffer, buflen, pininfo);
@ -1990,19 +1978,15 @@ open_pcsc_reader (const char *portstr)
/* Check whether the reader supports the ISO command code COMMAND /* Check whether the reader supports the ISO command code COMMAND
on the keypad. Return 0 on success. */ on the pinpad. Return 0 on success. */
static int static int
check_pcsc_keypad (int slot, int command, int pin_mode, check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo)
int pinlen_min, int pinlen_max, int pin_padlen)
{ {
unsigned char buf[256]; unsigned char buf[256];
size_t len = 256; size_t len = 256;
int sw; int sw;
(void)pin_mode; (void)pininfo; /* XXX: Identify reader and set pininfo->fixedlen. */
(void)pinlen_min;
(void)pinlen_max;
(void)pin_padlen;
check_again: check_again:
if (command == ISO7816_VERIFY) if (command == ISO7816_VERIFY)
@ -2053,12 +2037,12 @@ check_pcsc_keypad (int slot, int command, int pin_mode,
#define PIN_VERIFY_STRUCTURE_SIZE 24 #define PIN_VERIFY_STRUCTURE_SIZE 24
static int static int
pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1, pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
int sw; int sw;
unsigned char *pin_verify; unsigned char *pin_verify;
int len = PIN_VERIFY_STRUCTURE_SIZE; int len = PIN_VERIFY_STRUCTURE_SIZE + pininfo->fixedlen;
unsigned char result[2]; unsigned char result[2];
size_t resultlen = 2; size_t resultlen = 2;
@ -2066,10 +2050,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
&& (sw = reset_pcsc_reader (slot))) && (sw = reset_pcsc_reader (slot)))
return sw; return sw;
if (pininfo->mode != 1) if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
return SW_NOT_SUPPORTED;
if (pininfo->padlen != 0)
return SW_NOT_SUPPORTED; return SW_NOT_SUPPORTED;
if (!pininfo->minlen) if (!pininfo->minlen)
@ -2090,7 +2071,7 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify[0] = 0x00; /* bTimerOut */ pin_verify[0] = 0x00; /* bTimerOut */
pin_verify[1] = 0x00; /* bTimerOut2 */ pin_verify[1] = 0x00; /* bTimerOut2 */
pin_verify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */ pin_verify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
pin_verify[3] = 0x00; /* bmPINBlockString */ pin_verify[3] = pininfo->fixedlen; /* bmPINBlockString */
pin_verify[4] = 0x00; /* bmPINLengthFormat */ pin_verify[4] = 0x00; /* bmPINLengthFormat */
pin_verify[5] = pininfo->maxlen; /* wPINMaxExtraDigit */ pin_verify[5] = pininfo->maxlen; /* wPINMaxExtraDigit */
pin_verify[6] = pininfo->minlen; /* wPINMaxExtraDigit */ pin_verify[6] = pininfo->minlen; /* wPINMaxExtraDigit */
@ -2103,8 +2084,8 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify[11] = 0x00; /* bMsgIndex */ pin_verify[11] = 0x00; /* bMsgIndex */
pin_verify[12] = 0x00; /* bTeoPrologue[0] */ pin_verify[12] = 0x00; /* bTeoPrologue[0] */
pin_verify[13] = 0x00; /* bTeoPrologue[1] */ pin_verify[13] = 0x00; /* bTeoPrologue[1] */
pin_verify[14] = 0x00; /* bTeoPrologue[2] */ pin_verify[14] = pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
pin_verify[15] = 0x05; /* ulDataLength */ pin_verify[15] = pininfo->fixedlen + 0x05; /* ulDataLength */
pin_verify[16] = 0x00; /* ulDataLength */ pin_verify[16] = 0x00; /* ulDataLength */
pin_verify[17] = 0x00; /* ulDataLength */ pin_verify[17] = 0x00; /* ulDataLength */
pin_verify[18] = 0x00; /* ulDataLength */ pin_verify[18] = 0x00; /* ulDataLength */
@ -2112,7 +2093,9 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
pin_verify[20] = ins; /* abData[1] */ pin_verify[20] = ins; /* abData[1] */
pin_verify[21] = p0; /* abData[2] */ pin_verify[21] = p0; /* abData[2] */
pin_verify[22] = p1; /* abData[3] */ pin_verify[22] = p1; /* abData[3] */
pin_verify[23] = 0x00; /* abData[4] */ pin_verify[23] = pininfo->fixedlen; /* abData[4] */
if (pininfo->fixedlen)
memset (&pin_verify[24], 0xff, pininfo->fixedlen);
if (DBG_CARD_IO) if (DBG_CARD_IO)
log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n", log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
@ -2137,12 +2120,12 @@ pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
#define PIN_MODIFY_STRUCTURE_SIZE 29 #define PIN_MODIFY_STRUCTURE_SIZE 29
static int static int
pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1, pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
int sw; int sw;
unsigned char *pin_modify; unsigned char *pin_modify;
int len = PIN_MODIFY_STRUCTURE_SIZE; int len = PIN_MODIFY_STRUCTURE_SIZE + 2 * pininfo->fixedlen;
unsigned char result[2]; unsigned char result[2];
size_t resultlen = 2; size_t resultlen = 2;
@ -2150,10 +2133,7 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
&& (sw = reset_pcsc_reader (slot))) && (sw = reset_pcsc_reader (slot)))
return sw; return sw;
if (pininfo->mode != 1) if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
return SW_NOT_SUPPORTED;
if (pininfo->padlen != 0)
return SW_NOT_SUPPORTED; return SW_NOT_SUPPORTED;
if (!pininfo->minlen) if (!pininfo->minlen)
@ -2174,10 +2154,10 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
pin_modify[0] = 0x00; /* bTimerOut */ pin_modify[0] = 0x00; /* bTimerOut */
pin_modify[1] = 0x00; /* bTimerOut2 */ pin_modify[1] = 0x00; /* bTimerOut2 */
pin_modify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */ pin_modify[2] = 0x82; /* bmFormatString: Byte, pos=0, left, ASCII. */
pin_modify[3] = 0x00; /* bmPINBlockString */ pin_modify[3] = pininfo->fixedlen; /* bmPINBlockString */
pin_modify[4] = 0x00; /* bmPINLengthFormat */ pin_modify[4] = 0x00; /* bmPINLengthFormat */
pin_modify[5] = 0x00; /* bInsertionOffsetOld */ pin_modify[5] = 0x00; /* bInsertionOffsetOld */
pin_modify[6] = 0x00; /* bInsertionOffsetNew */ pin_modify[6] = pininfo->fixedlen; /* bInsertionOffsetNew */
pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */ pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */
pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */ pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */
pin_modify[9] = (p0 == 0 ? 0x03 : 0x01); pin_modify[9] = (p0 == 0 ? 0x03 : 0x01);
@ -2198,8 +2178,8 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
pin_modify[16] = 0x00; /* bMsgIndex3 */ pin_modify[16] = 0x00; /* bMsgIndex3 */
pin_modify[17] = 0x00; /* bTeoPrologue[0] */ pin_modify[17] = 0x00; /* bTeoPrologue[0] */
pin_modify[18] = 0x00; /* bTeoPrologue[1] */ pin_modify[18] = 0x00; /* bTeoPrologue[1] */
pin_modify[19] = 0x00; /* bTeoPrologue[2] */ pin_modify[19] = 2 * pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
pin_modify[20] = 0x05; /* ulDataLength */ pin_modify[20] = 2 * pininfo->fixedlen + 0x05; /* ulDataLength */
pin_modify[21] = 0x00; /* ulDataLength */ pin_modify[21] = 0x00; /* ulDataLength */
pin_modify[22] = 0x00; /* ulDataLength */ pin_modify[22] = 0x00; /* ulDataLength */
pin_modify[23] = 0x00; /* ulDataLength */ pin_modify[23] = 0x00; /* ulDataLength */
@ -2207,7 +2187,9 @@ pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
pin_modify[25] = ins; /* abData[1] */ pin_modify[25] = ins; /* abData[1] */
pin_modify[26] = p0; /* abData[2] */ pin_modify[26] = p0; /* abData[2] */
pin_modify[27] = p1; /* abData[3] */ pin_modify[27] = p1; /* abData[3] */
pin_modify[28] = 0x00; /* abData[4] */ pin_modify[28] = 2 * pininfo->fixedlen; /* abData[4] */
if (pininfo->fixedlen)
memset (&pin_modify[29], 0xff, 2 * pininfo->fixedlen);
if (DBG_CARD_IO) if (DBG_CARD_IO)
log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n", log_debug ("send secure: c=%02X i=%02X p1=%02X p2=%02X len=%d pinmax=%d\n",
@ -2312,7 +2294,7 @@ get_status_ccid (int slot, unsigned int *status)
static int static int
send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen, send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, unsigned char *buffer, size_t *buflen,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
long err; long err;
size_t maxbuflen; size_t maxbuflen;
@ -2328,11 +2310,7 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
maxbuflen = *buflen; maxbuflen = *buflen;
if (pininfo) if (pininfo)
err = ccid_transceive_secure (reader_table[slot].ccid.handle, err = ccid_transceive_secure (reader_table[slot].ccid.handle,
apdu, apdulen, apdu, apdulen, pininfo,
pininfo->mode,
pininfo->minlen,
pininfo->maxlen,
pininfo->padlen,
buffer, maxbuflen, buflen); buffer, maxbuflen, buflen);
else else
err = ccid_transceive (reader_table[slot].ccid.handle, err = ccid_transceive (reader_table[slot].ccid.handle,
@ -2347,25 +2325,22 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
/* Check whether the CCID reader supports the ISO command code COMMAND /* Check whether the CCID reader supports the ISO command code COMMAND
on the keypad. Return 0 on success. For a description of the pin on the pinpad. Return 0 on success. For a description of the pin
parameters, see ccid-driver.c */ parameters, see ccid-driver.c */
static int static int
check_ccid_keypad (int slot, int command, int pin_mode, check_ccid_pinpad (int slot, int command, pininfo_t *pininfo)
int pinlen_min, int pinlen_max, int pin_padlen)
{ {
unsigned char apdu[] = { 0, 0, 0, 0x81 }; unsigned char apdu[] = { 0, 0, 0, 0x81 };
apdu[1] = command; apdu[1] = command;
return ccid_transceive_secure (reader_table[slot].ccid.handle, return ccid_transceive_secure (reader_table[slot].ccid.handle, apdu,
apdu, sizeof apdu, sizeof apdu, pininfo, NULL, 0, NULL);
pin_mode, pinlen_min, pinlen_max, pin_padlen,
NULL, 0, NULL);
} }
static int static int
ccid_keypad_operation (int slot, int class, int ins, int p0, int p1, ccid_pinpad_operation (int slot, int class, int ins, int p0, int p1,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
unsigned char apdu[4]; unsigned char apdu[4];
int err, sw; int err, sw;
@ -2377,9 +2352,7 @@ ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
apdu[2] = p0; apdu[2] = p0;
apdu[3] = p1; apdu[3] = p1;
err = ccid_transceive_secure (reader_table[slot].ccid.handle, err = ccid_transceive_secure (reader_table[slot].ccid.handle,
apdu, sizeof apdu, apdu, sizeof apdu, pininfo,
pininfo->mode, pininfo->minlen, pininfo->maxlen,
pininfo->padlen,
result, 2, &resultlen); result, 2, &resultlen);
if (err) if (err)
return err; return err;
@ -2433,11 +2406,11 @@ open_ccid_reader (const char *portstr)
reader_table[slot].reset_reader = reset_ccid_reader; reader_table[slot].reset_reader = reset_ccid_reader;
reader_table[slot].get_status_reader = get_status_ccid; reader_table[slot].get_status_reader = get_status_ccid;
reader_table[slot].send_apdu_reader = send_apdu_ccid; reader_table[slot].send_apdu_reader = send_apdu_ccid;
reader_table[slot].check_keypad = check_ccid_keypad; reader_table[slot].check_pinpad = check_ccid_pinpad;
reader_table[slot].dump_status_reader = dump_ccid_reader_status; reader_table[slot].dump_status_reader = dump_ccid_reader_status;
reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader; reader_table[slot].set_progress_cb = set_progress_cb_ccid_reader;
reader_table[slot].keypad_verify = ccid_keypad_operation; reader_table[slot].pinpad_verify = ccid_pinpad_operation;
reader_table[slot].keypad_modify = ccid_keypad_operation; reader_table[slot].pinpad_modify = ccid_pinpad_operation;
/* Our CCID reader code does not support T=0 at all, thus reset the /* Our CCID reader code does not support T=0 at all, thus reset the
flag. */ flag. */
reader_table[slot].is_t0 = 0; reader_table[slot].is_t0 = 0;
@ -2597,7 +2570,7 @@ my_rapdu_get_status (int slot, unsigned int *status)
static int static int
my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen, my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, unsigned char *buffer, size_t *buflen,
struct pininfo_s *pininfo) pininfo_t *pininfo)
{ {
int err; int err;
reader_table_t slotp; reader_table_t slotp;
@ -2728,10 +2701,10 @@ open_rapdu_reader (int portno,
reader_table[slot].reset_reader = reset_rapdu_reader; reader_table[slot].reset_reader = reset_rapdu_reader;
reader_table[slot].get_status_reader = my_rapdu_get_status; reader_table[slot].get_status_reader = my_rapdu_get_status;
reader_table[slot].send_apdu_reader = my_rapdu_send_apdu; reader_table[slot].send_apdu_reader = my_rapdu_send_apdu;
reader_table[slot].check_keypad = NULL; reader_table[slot].check_pinpad = NULL;
reader_table[slot].dump_status_reader = NULL; reader_table[slot].dump_status_reader = NULL;
reader_table[slot].keypad_verify = NULL; reader_table[slot].pinpad_verify = NULL;
reader_table[slot].keypad_modify = NULL; reader_table[slot].pinpad_modify = NULL;
dump_reader_status (slot); dump_reader_status (slot);
rapdu_msg_release (msg); rapdu_msg_release (msg);
@ -3419,63 +3392,76 @@ apdu_get_status (int slot, int hang,
/* Check whether the reader supports the ISO command code COMMAND on /* Check whether the reader supports the ISO command code COMMAND on
the keypad. Return 0 on success. For a description of the pin the pinpad. Return 0 on success. For a description of the pin
parameters, see ccid-driver.c */ parameters, see ccid-driver.c */
int int
apdu_check_keypad (int slot, int command, int pin_mode, apdu_check_pinpad (int slot, int command, pininfo_t *pininfo)
int pinlen_min, int pinlen_max, int pin_padlen)
{ {
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER; return SW_HOST_NO_DRIVER;
if (reader_table[slot].check_keypad) if (opt.enable_pinpad_varlen)
return reader_table[slot].check_keypad (slot, command, pininfo->fixedlen = 0;
pin_mode, pinlen_min, pinlen_max,
pin_padlen); if (reader_table[slot].check_pinpad)
{
int sw;
if ((sw = lock_slot (slot)))
return sw;
sw = reader_table[slot].check_pinpad (slot, command, pininfo);
unlock_slot (slot);
return sw;
}
else else
return SW_HOST_NOT_SUPPORTED; return SW_HOST_NOT_SUPPORTED;
} }
int int
apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode, apdu_pinpad_verify (int slot, int class, int ins, int p0, int p1,
int pinlen_min, int pinlen_max, int pin_padlen) pininfo_t *pininfo)
{ {
struct pininfo_s pininfo;
pininfo.mode = pin_mode;
pininfo.minlen = pinlen_min;
pininfo.maxlen = pinlen_max;
pininfo.padlen = pin_padlen;
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER; return SW_HOST_NO_DRIVER;
if (reader_table[slot].keypad_verify) if (reader_table[slot].pinpad_verify)
return reader_table[slot].keypad_verify (slot, class, ins, p0, p1, {
&pininfo); int sw;
if ((sw = lock_slot (slot)))
return sw;
sw = reader_table[slot].pinpad_verify (slot, class, ins, p0, p1,
pininfo);
unlock_slot (slot);
return sw;
}
else else
return SW_HOST_NOT_SUPPORTED; return SW_HOST_NOT_SUPPORTED;
} }
int int
apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode, apdu_pinpad_modify (int slot, int class, int ins, int p0, int p1,
int pinlen_min, int pinlen_max, int pin_padlen) pininfo_t *pininfo)
{ {
struct pininfo_s pininfo;
pininfo.mode = pin_mode;
pininfo.minlen = pinlen_min;
pininfo.maxlen = pinlen_max;
pininfo.padlen = pin_padlen;
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER; return SW_HOST_NO_DRIVER;
if (reader_table[slot].keypad_modify) if (reader_table[slot].pinpad_modify)
return reader_table[slot].keypad_modify (slot, class, ins, p0, p1, {
&pininfo); int sw;
if ((sw = lock_slot (slot)))
return sw;
sw = reader_table[slot].pinpad_modify (slot, class, ins, p0, p1,
pininfo);
unlock_slot (slot);
return sw;
}
else else
return SW_HOST_NOT_SUPPORTED; return SW_HOST_NOT_SUPPORTED;
} }
@ -3485,7 +3471,7 @@ apdu_keypad_modify (int slot, int class, int ins, int p0, int p1, int pin_mode,
function should be called in locked state. */ function should be called in locked state. */
static int static int
send_apdu (int slot, unsigned char *apdu, size_t apdulen, send_apdu (int slot, unsigned char *apdu, size_t apdulen,
unsigned char *buffer, size_t *buflen, struct pininfo_s *pininfo) unsigned char *buffer, size_t *buflen, pininfo_t *pininfo)
{ {
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
return SW_HOST_NO_DRIVER; return SW_HOST_NO_DRIVER;
@ -3501,7 +3487,7 @@ send_apdu (int slot, unsigned char *apdu, size_t apdulen,
/* Core APDU tranceiver function. Parameters are described at /* Core APDU tranceiver function. Parameters are described at
apdu_send_le with the exception of PININFO which indicates keypad apdu_send_le with the exception of PININFO which indicates pinpad
related operations if not NULL. If EXTENDED_MODE is not 0 related operations if not NULL. If EXTENDED_MODE is not 0
command chaining or extended length will be used according to these command chaining or extended length will be used according to these
values: values:
@ -3517,7 +3503,7 @@ static int
send_le (int slot, int class, int ins, int p0, int p1, send_le (int slot, int class, int ins, int p0, int p1,
int lc, const char *data, int le, int lc, const char *data, int le,
unsigned char **retbuf, size_t *retbuflen, unsigned char **retbuf, size_t *retbuflen,
struct pininfo_s *pininfo, int extended_mode) pininfo_t *pininfo, int extended_mode)
{ {
#define SHORT_RESULT_BUFFER_SIZE 258 #define SHORT_RESULT_BUFFER_SIZE 258
/* We allocate 8 extra bytes as a safety margin towards a driver bug. */ /* We allocate 8 extra bytes as a safety margin towards a driver bug. */

View File

@ -69,7 +69,7 @@ enum {
SW_HOST_GENERAL_ERROR = 0x1000b, SW_HOST_GENERAL_ERROR = 0x1000b,
SW_HOST_NO_READER = 0x1000c, SW_HOST_NO_READER = 0x1000c,
SW_HOST_ABORTED = 0x1000d, SW_HOST_ABORTED = 0x1000d,
SW_HOST_NO_KEYPAD = 0x1000e, SW_HOST_NO_PINPAD = 0x1000e,
SW_HOST_ALREADY_CONNECTED = 0x1000f SW_HOST_ALREADY_CONNECTED = 0x1000f
}; };
@ -114,14 +114,11 @@ int apdu_set_progress_cb (int slot, gcry_handler_progress_t cb, void *cb_arg);
int apdu_reset (int slot); int apdu_reset (int slot);
int apdu_get_status (int slot, int hang, int apdu_get_status (int slot, int hang,
unsigned int *status, unsigned int *changed); unsigned int *status, unsigned int *changed);
int apdu_check_keypad (int slot, int command, int pin_mode, int apdu_check_pinpad (int slot, int command, pininfo_t *pininfo);
int pinlen_min, int pinlen_max, int pin_padlen); int apdu_pinpad_verify (int slot, int class, int ins, int p0, int p1,
int apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, pininfo_t *pininfo);
int pin_mode, int pinlen_min, int pinlen_max, int apdu_pinpad_modify (int slot, int class, int ins, int p0, int p1,
int pin_padlen); pininfo_t *pininfo);
int apdu_keypad_modify (int slot, int class, int ins, int p0, int p1,
int pin_mode, int pinlen_min, int pinlen_max,
int pin_padlen);
int apdu_send_simple (int slot, int extended_mode, int apdu_send_simple (int slot, int extended_mode,
int class, int ins, int p0, int p1, int class, int ins, int p0, int p1,
int lc, const char *data); int lc, const char *data);

View File

@ -282,21 +282,21 @@ verify_pin (app_t app,
{ {
const char *s; const char *s;
int rc; int rc;
iso7816_pininfo_t pininfo; pininfo_t pininfo;
if ( app->did_chv1 && !app->force_chv1 ) if ( app->did_chv1 && !app->force_chv1 )
return 0; /* No need to verify it again. */ return 0; /* No need to verify it again. */
memset (&pininfo, 0, sizeof pininfo); memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1; pininfo.fixedlen = -1;
pininfo.minlen = 6; pininfo.minlen = 6;
pininfo.maxlen = 8; pininfo.maxlen = 8;
if (!opt.disable_keypad if (!opt.disable_pinpad
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
{ {
rc = pincb (pincb_arg, rc = pincb (pincb_arg,
_("||Please enter your PIN at the reader's keypad"), _("||Please enter your PIN at the reader's pinpad"),
NULL); NULL);
if (rc) if (rc)
{ {
@ -308,7 +308,7 @@ verify_pin (app_t app,
/* Dismiss the prompt. */ /* Dismiss the prompt. */
pincb (pincb_arg, NULL, NULL); pincb (pincb_arg, NULL, NULL);
} }
else /* No Keypad. */ else /* No Pinpad. */
{ {
char *pinvalue; char *pinvalue;

View File

@ -781,19 +781,19 @@ verify_pin (app_t app, int pwid, const char *desc,
gpg_error_t (*pincb)(void*, const char *, char **), gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg) void *pincb_arg)
{ {
iso7816_pininfo_t pininfo; pininfo_t pininfo;
int rc; int rc;
if (!desc) if (!desc)
desc = "PIN"; desc = "PIN";
memset (&pininfo, 0, sizeof pininfo); memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1; pininfo.fixedlen = -1;
pininfo.minlen = 6; pininfo.minlen = 6;
pininfo.maxlen = 16; pininfo.maxlen = 16;
if (!opt.disable_keypad if (!opt.disable_pinpad
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
{ {
rc = pincb (pincb_arg, desc, NULL); rc = pincb (pincb_arg, desc, NULL);
if (rc) if (rc)
@ -1144,7 +1144,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
int is_sigg; int is_sigg;
const char *newdesc; const char *newdesc;
int pwid; int pwid;
iso7816_pininfo_t pininfo; pininfo_t pininfo;
(void)ctrl; (void)ctrl;

View File

@ -1,6 +1,6 @@
/* app-openpgp.c - The OpenPGP card application. /* app-openpgp.c - The OpenPGP card application.
* Copyright (C) 2003, 2004, 2005, 2007, 2008, * Copyright (C) 2003, 2004, 2005, 2007, 2008,
* 2009 Free Software Foundation, Inc. * 2009, 2013 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -191,6 +191,14 @@ struct app_local_s {
unsigned int def_chv2:1; /* Use 123456 for CHV2. */ unsigned int def_chv2:1; /* Use 123456 for CHV2. */
} flags; } flags;
/* Pinpad request specified on card. */
struct
{
unsigned int specified:1;
int fixedlen_user;
int fixedlen_admin;
} pinpad;
struct struct
{ {
unsigned int n_bits; /* Size of the modulus in bits. The rest unsigned int n_bits; /* Size of the modulus in bits. The rest
@ -581,17 +589,23 @@ count_bits (const unsigned char *a, size_t len)
Everything up to a LF is considered a mailbox or account name. If Everything up to a LF is considered a mailbox or account name. If
the first LF is followed by DC4 (0x14) control sequence are the first LF is followed by DC4 (0x14) control sequence are
expected up to the next LF. Control sequences are separated by FS expected up to the next LF. Control sequences are separated by FS
(0x18) and consist of key=value pairs. There is one key defined: (0x18) and consist of key=value pairs. There are two keys defined:
F=<flags> F=<flags>
Were FLAGS is a plain hexadecimal number representing flag values. Where FLAGS is a plain hexadecimal number representing flag values.
The lsb is here the rightmost bit. Defined flags bits are: The lsb is here the rightmost bit. Defined flags bits are:
Bit 0 = CHV1 and CHV2 are not syncronized Bit 0 = CHV1 and CHV2 are not syncronized
Bit 1 = CHV2 has been been set to the default PIN of "123456" Bit 1 = CHV2 has been been set to the default PIN of "123456"
(this implies that bit 0 is also set). (this implies that bit 0 is also set).
P=<pinpad-request>
Where PINPAD_REQUEST is in the format of: <n> or <n>,<m>.
N for user PIN, M for admin PIN. If M is missing it means M=N.
0 means to force not to use pinpad.
*/ */
static void static void
parse_login_data (app_t app) parse_login_data (app_t app)
@ -603,6 +617,9 @@ parse_login_data (app_t app)
/* Set defaults. */ /* Set defaults. */
app->app_local->flags.no_sync = 0; app->app_local->flags.no_sync = 0;
app->app_local->flags.def_chv2 = 0; app->app_local->flags.def_chv2 = 0;
app->app_local->pinpad.specified = 0;
app->app_local->pinpad.fixedlen_user = -1;
app->app_local->pinpad.fixedlen_admin = -1;
/* Read the DO. */ /* Read the DO. */
relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL); relptr = get_one_do (app, 0x005E, &buffer, &buflen, NULL);
@ -628,11 +645,54 @@ parse_login_data (app_t app)
any leading digits but bail out on invalid characters. */ any leading digits but bail out on invalid characters. */
for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--) for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
lastdig = xtoi_1 (p); lastdig = xtoi_1 (p);
buffer = p;
buflen = len;
if (len && !(*p == '\n' || *p == '\x18')) if (len && !(*p == '\n' || *p == '\x18'))
goto next; /* Invalid characters in field. */ goto next; /* Invalid characters in field. */
app->app_local->flags.no_sync = !!(lastdig & 1); app->app_local->flags.no_sync = !!(lastdig & 1);
app->app_local->flags.def_chv2 = (lastdig & 3) == 3; app->app_local->flags.def_chv2 = (lastdig & 3) == 3;
} }
else if (buflen > 1 && *buffer == 'P' && buffer[1] == '=')
{
/* Pinpad request control sequence found. */
buffer += 2;
buflen -= 2;
if (buflen)
{
if (digitp (buffer))
{
char *q;
int n, m;
n = strtol (buffer, &q, 10);
if (q >= (char *)buffer + buflen
|| *q == '\x18' || *q == '\n')
m = n;
else
{
if (*q++ != ',' || !digitp (q))
goto next;
m = strtol (q, &q, 10);
}
buffer = q;
if (buflen < ((unsigned char *)q - buffer))
{
buflen = 0;
break;
}
else
buflen -= ((unsigned char *)q - buffer);
if (buflen && !(*buffer == '\n' || *buffer == '\x18'))
goto next;
app->app_local->pinpad.specified = 1;
app->app_local->pinpad.fixedlen_user = n;
app->app_local->pinpad.fixedlen_admin = m;
}
}
}
next: next:
for (; buflen && *buffer != '\x18'; buflen--, buffer++) for (; buflen && *buffer != '\x18'; buflen--, buffer++)
if (*buffer == '\n') if (*buffer == '\n')
@ -1470,15 +1530,50 @@ do_readcert (app_t app, const char *certid,
} }
/* Decide if we use the pinpad of the reader for PIN input according
to the user preference on the card, and the capability of the
reader. This routine is only called when the reader has pinpad.
Returns 0 if we use pinpad, 1 otherwise. */
static int
check_pinpad_request (app_t app, pininfo_t *pininfo, int admin_pin)
{
if (app->app_local->pinpad.specified == 0) /* No preference on card. */
{
if (pininfo->fixedlen == 0) /* Reader has varlen capability. */
return 0; /* Then, use pinpad. */
else
/*
* Reader has limited capability, and it may not match PIN of
* the card.
*/
return 1;
}
if (admin_pin)
pininfo->fixedlen = app->app_local->pinpad.fixedlen_admin;
else
pininfo->fixedlen = app->app_local->pinpad.fixedlen_user;
if (pininfo->fixedlen == 0 /* User requests disable pinpad. */
|| pininfo->fixedlen < pininfo->minlen
|| pininfo->fixedlen > pininfo->maxlen
/* Reader doesn't have the capability to input a PIN which
* length is FIXEDLEN. */)
return 1;
return 0;
}
/* Verify a CHV either using using the pinentry or if possibile by /* Verify a CHV either using using the pinentry or if possibile by
using a keypad. PINCB and PINCB_ARG describe the usual callback using a pinpad. PINCB and PINCB_ARG describe the usual callback
for the pinentry. CHVNO must be either 1 or 2. SIGCOUNT is only for the pinentry. CHVNO must be either 1 or 2. SIGCOUNT is only
used with CHV1. PINVALUE is the address of a pointer which will used with CHV1. PINVALUE is the address of a pointer which will
receive a newly allocated block with the actual PIN (this is useful receive a newly allocated block with the actual PIN (this is useful
in case that PIN shall be used for another verify operation). The in case that PIN shall be used for another verify operation). The
caller needs to free this value. If the function returns with caller needs to free this value. If the function returns with
success and NULL is stored at PINVALUE, the caller should take this success and NULL is stored at PINVALUE, the caller should take this
as an indication that the keypad has been used. as an indication that the pinpad has been used.
*/ */
static gpg_error_t static gpg_error_t
verify_a_chv (app_t app, verify_a_chv (app_t app,
@ -1489,7 +1584,7 @@ verify_a_chv (app_t app,
int rc = 0; int rc = 0;
char *prompt_buffer = NULL; char *prompt_buffer = NULL;
const char *prompt; const char *prompt;
iso7816_pininfo_t pininfo; pininfo_t pininfo;
int minlen = 6; int minlen = 6;
assert (chvno == 1 || chvno == 2); assert (chvno == 1 || chvno == 2);
@ -1516,7 +1611,7 @@ verify_a_chv (app_t app,
} }
memset (&pininfo, 0, sizeof pininfo); memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1; pininfo.fixedlen = -1;
pininfo.minlen = minlen; pininfo.minlen = minlen;
@ -1536,12 +1631,13 @@ verify_a_chv (app_t app,
prompt = _("||Please enter the PIN"); prompt = _("||Please enter the PIN");
if (!opt.disable_keypad if (!opt.disable_pinpad
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo)
&& !check_pinpad_request (app, &pininfo, 0))
{ {
/* The reader supports the verify command through the keypad. /* The reader supports the verify command through the pinpad.
Note that the pincb appends a text to the prompt telling the Note that the pincb appends a text to the prompt telling the
user to use the keypad. */ user to use the pinpad. */
rc = pincb (pincb_arg, prompt, NULL); rc = pincb (pincb_arg, prompt, NULL);
prompt = NULL; prompt = NULL;
xfree (prompt_buffer); xfree (prompt_buffer);
@ -1560,7 +1656,7 @@ verify_a_chv (app_t app,
} }
else else
{ {
/* The reader has no keypad or we don't want to use it. */ /* The reader has no pinpad or we don't want to use it. */
rc = pincb (pincb_arg, prompt, pinvalue); rc = pincb (pincb_arg, prompt, pinvalue);
prompt = NULL; prompt = NULL;
xfree (prompt_buffer); xfree (prompt_buffer);
@ -1620,7 +1716,7 @@ verify_chv2 (app_t app,
/* For convenience we verify CHV1 here too. We do this only if /* For convenience we verify CHV1 here too. We do this only if
the card is not configured to require a verification before the card is not configured to require a verification before
each CHV1 controlled operation (force_chv1) and if we are not each CHV1 controlled operation (force_chv1) and if we are not
using the keypad (PINVALUE == NULL). */ using the pinpad (PINVALUE == NULL). */
rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
if (gpg_err_code (rc) == GPG_ERR_BAD_PIN) if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
@ -1707,22 +1803,23 @@ verify_chv3 (app_t app,
if (!app->did_chv3) if (!app->did_chv3)
{ {
iso7816_pininfo_t pininfo; pininfo_t pininfo;
int minlen = 8; int minlen = 8;
char *prompt; char *prompt;
memset (&pininfo, 0, sizeof pininfo); memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1; pininfo.fixedlen = -1;
pininfo.minlen = minlen; pininfo.minlen = minlen;
rc = build_enter_admin_pin_prompt (app, &prompt); rc = build_enter_admin_pin_prompt (app, &prompt);
if (rc) if (rc)
return rc; return rc;
if (!opt.disable_keypad if (!opt.disable_pinpad
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) ) && !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo)
&& !check_pinpad_request (app, &pininfo, 1))
{ {
/* The reader supports the verify command through the keypad. */ /* The reader supports the verify command through the pinpad. */
rc = pincb (pincb_arg, prompt, NULL); rc = pincb (pincb_arg, prompt, NULL);
xfree (prompt); xfree (prompt);
prompt = NULL; prompt = NULL;
@ -1917,13 +2014,13 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
char *pinvalue = NULL; char *pinvalue = NULL;
int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET); int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET);
int set_resetcode = 0; int set_resetcode = 0;
iso7816_pininfo_t pininfo; pininfo_t pininfo;
int use_keypad = 0; int use_pinpad = 0;
int minlen = 6; int minlen = 6;
(void)ctrl; (void)ctrl;
memset (&pininfo, 0, sizeof pininfo); memset (&pininfo, 0, sizeof pininfo);
pininfo.mode = 1; pininfo.fixedlen = -1;
pininfo.minlen = minlen; pininfo.minlen = minlen;
if (reset_mode && chvno == 3) if (reset_mode && chvno == 3)
@ -1968,15 +2065,16 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
{ {
/* Version 2 cards. */ /* Version 2 cards. */
if (!opt.disable_keypad if (!opt.disable_pinpad
&& !iso7816_check_keypad (app->slot, && !iso7816_check_pinpad (app->slot,
ISO7816_CHANGE_REFERENCE_DATA, &pininfo)) ISO7816_CHANGE_REFERENCE_DATA, &pininfo)
use_keypad = 1; && !check_pinpad_request (app, &pininfo, chvno == 3))
use_pinpad = 1;
if (reset_mode) if (reset_mode)
{ {
/* To reset a PIN the Admin PIN is required. */ /* To reset a PIN the Admin PIN is required. */
use_keypad = 0; use_pinpad = 0;
app->did_chv3 = 0; app->did_chv3 = 0;
rc = verify_chv3 (app, pincb, pincb_arg); rc = verify_chv3 (app, pincb, pincb_arg);
if (rc) if (rc)
@ -1987,7 +2085,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
} }
else if (chvno == 1 || chvno == 3) else if (chvno == 1 || chvno == 3)
{ {
if (!use_keypad) if (!use_pinpad)
{ {
char *promptbuf = NULL; char *promptbuf = NULL;
const char *prompt; const char *prompt;
@ -2030,7 +2128,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
size_t valuelen; size_t valuelen;
int remaining; int remaining;
use_keypad = 0; use_pinpad = 0;
minlen = 8; minlen = 8;
relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL); relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL);
if (!relptr || valuelen < 7) if (!relptr || valuelen < 7)
@ -2078,7 +2176,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
else else
app->did_chv1 = app->did_chv2 = 0; app->did_chv1 = app->did_chv2 = 0;
if (!use_keypad) if (!use_pinpad)
{ {
/* TRANSLATORS: Do not translate the "|*|" prefixes but /* TRANSLATORS: Do not translate the "|*|" prefixes but
keep it at the start of the string. We need this elsewhere keep it at the start of the string. We need this elsewhere
@ -2151,7 +2249,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
/* Version 2 cards. */ /* Version 2 cards. */
assert (chvno == 1 || chvno == 3); assert (chvno == 1 || chvno == 3);
if (use_keypad) if (use_pinpad)
{ {
rc = pincb (pincb_arg, rc = pincb (pincb_arg,
chvno == 3 ? chvno == 3 ?
@ -3226,7 +3324,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
sync, thus we verify CHV2 here using the given PIN. Cards sync, thus we verify CHV2 here using the given PIN. Cards
with version2 to not have the need for a separate CHV2 and with version2 to not have the need for a separate CHV2 and
internally use just one. Obviously we can't do that if the internally use just one. Obviously we can't do that if the
keypad has been used. */ pinpad has been used. */
if (!app->did_chv2 && pinvalue && !app->app_local->extcap.is_v2) if (!app->did_chv2 && pinvalue && !app->app_local->extcap.is_v2)
{ {
rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));

View File

@ -26,8 +26,8 @@
#include "scdaemon.h" #include "scdaemon.h"
#include "app-common.h" #include "app-common.h"
#include "apdu.h"
#include "iso7816.h" #include "iso7816.h"
#include "apdu.h"
#include "tlv.h" #include "tlv.h"
/* This table is used to keep track of locks on a per reader base. /* This table is used to keep track of locks on a per reader base.

View File

@ -1,6 +1,6 @@
/* ccid-driver.c - USB ChipCardInterfaceDevices driver /* ccid-driver.c - USB ChipCardInterfaceDevices driver
* Copyright (C) 2003, 2004, 2005, 2006, 2007 * Copyright (C) 2003, 2004, 2005, 2006, 2007
* 2008, 2009 Free Software Foundation, Inc. * 2008, 2009, 2013 Free Software Foundation, Inc.
* Written by Werner Koch. * Written by Werner Koch.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
@ -89,6 +89,8 @@
#include <usb.h> #include <usb.h>
#include "scdaemon.h"
#include "iso7816.h"
#include "ccid-driver.h" #include "ccid-driver.h"
#define DRVNAME "ccid-driver: " #define DRVNAME "ccid-driver: "
@ -207,6 +209,7 @@ enum {
VENDOR_SCM = 0x04e6, VENDOR_SCM = 0x04e6,
VENDOR_OMNIKEY= 0x076b, VENDOR_OMNIKEY= 0x076b,
VENDOR_GEMPC = 0x08e6, VENDOR_GEMPC = 0x08e6,
VENDOR_VEGA = 0x0982,
VENDOR_KAAN = 0x0d46, VENDOR_KAAN = 0x0d46,
VENDOR_FSIJ = 0x234b, VENDOR_FSIJ = 0x234b,
VENDOR_VASCO = 0x1a44 VENDOR_VASCO = 0x1a44
@ -220,6 +223,8 @@ enum {
#define SCM_SPR532 0xe003 #define SCM_SPR532 0xe003
#define CHERRY_ST2000 0x003e #define CHERRY_ST2000 0x003e
#define VASCO_920 0x0920 #define VASCO_920 0x0920
#define GEMPC_PINPAD 0x3478
#define VEGA_ALPHA 0x0008
/* A list and a table with special transport descriptions. */ /* A list and a table with special transport descriptions. */
enum { enum {
@ -264,6 +269,9 @@ struct ccid_driver_s
unsigned char apdu_level:2; /* Reader supports short APDU level unsigned char apdu_level:2; /* Reader supports short APDU level
exchange. With a value of 2 short exchange. With a value of 2 short
and extended level is supported.*/ and extended level is supported.*/
unsigned int auto_voltage:1;
unsigned int auto_param:1;
unsigned int auto_pps:1;
unsigned int auto_ifsd:1; unsigned int auto_ifsd:1;
unsigned int powered_off:1; unsigned int powered_off:1;
unsigned int has_pinpad:2; unsigned int has_pinpad:2;
@ -295,6 +303,9 @@ static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length,
size_t *nread, int expected_type, int seqno, int timeout, size_t *nread, int expected_type, int seqno, int timeout,
int no_debug); int no_debug);
static int abort_cmd (ccid_driver_t handle, int seqno); static int abort_cmd (ccid_driver_t handle, int seqno);
static int send_escape_cmd (ccid_driver_t handle, const unsigned char *data,
size_t datalen, unsigned char *result,
size_t resultmax, size_t *resultlen);
/* Convert a little endian stored 4 byte value into an unsigned /* Convert a little endian stored 4 byte value into an unsigned
integer. */ integer. */
@ -758,7 +769,7 @@ parse_ccid_descriptor (ccid_driver_t handle,
{ {
unsigned int i; unsigned int i;
unsigned int us; unsigned int us;
int have_t1 = 0, have_tpdu=0, have_auto_conf = 0; int have_t1 = 0, have_tpdu=0;
handle->nonnull_nad = 0; handle->nonnull_nad = 0;
@ -767,6 +778,9 @@ parse_ccid_descriptor (ccid_driver_t handle,
handle->ifsd = 0; handle->ifsd = 0;
handle->has_pinpad = 0; handle->has_pinpad = 0;
handle->apdu_level = 0; handle->apdu_level = 0;
handle->auto_voltage = 0;
handle->auto_param = 0;
handle->auto_pps = 0;
DEBUGOUT_3 ("idVendor: %04X idProduct: %04X bcdDevice: %04X\n", DEBUGOUT_3 ("idVendor: %04X idProduct: %04X bcdDevice: %04X\n",
handle->id_vendor, handle->id_product, handle->bcd_device); handle->id_vendor, handle->id_product, handle->bcd_device);
if (buflen < 54 || buf[0] < 54) if (buflen < 54 || buf[0] < 54)
@ -842,22 +856,31 @@ parse_ccid_descriptor (ccid_driver_t handle,
DEBUGOUT_1 (" dwFeatures %08X\n", us); DEBUGOUT_1 (" dwFeatures %08X\n", us);
if ((us & 0x0002)) if ((us & 0x0002))
{ {
DEBUGOUT (" Auto configuration based on ATR\n"); DEBUGOUT (" Auto configuration based on ATR (assumes auto voltage)\n");
have_auto_conf = 1; handle->auto_voltage = 1;
} }
if ((us & 0x0004)) if ((us & 0x0004))
DEBUGOUT (" Auto activation on insert\n"); DEBUGOUT (" Auto activation on insert\n");
if ((us & 0x0008)) if ((us & 0x0008))
DEBUGOUT (" Auto voltage selection\n"); {
DEBUGOUT (" Auto voltage selection\n");
handle->auto_voltage = 1;
}
if ((us & 0x0010)) if ((us & 0x0010))
DEBUGOUT (" Auto clock change\n"); DEBUGOUT (" Auto clock change\n");
if ((us & 0x0020)) if ((us & 0x0020))
DEBUGOUT (" Auto baud rate change\n"); DEBUGOUT (" Auto baud rate change\n");
if ((us & 0x0040)) if ((us & 0x0040))
DEBUGOUT (" Auto parameter negotiation made by CCID\n"); {
DEBUGOUT (" Auto parameter negotiation made by CCID\n");
handle->auto_param = 1;
}
else if ((us & 0x0080)) else if ((us & 0x0080))
DEBUGOUT (" Auto PPS made by CCID\n"); {
else if ((us & (0x0040 | 0x0080))) DEBUGOUT (" Auto PPS made by CCID\n");
handle->auto_pps = 1;
}
if ((us & (0x0040 | 0x0080)) == (0x0040 | 0x0080))
DEBUGOUT (" WARNING: conflicting negotiation features\n"); DEBUGOUT (" WARNING: conflicting negotiation features\n");
if ((us & 0x0100)) if ((us & 0x0100))
@ -935,11 +958,10 @@ parse_ccid_descriptor (ccid_driver_t handle,
DEBUGOUT_LF (); DEBUGOUT_LF ();
} }
if (!have_t1 || !(have_tpdu || handle->apdu_level) || !have_auto_conf) if (!have_t1 || !(have_tpdu || handle->apdu_level))
{ {
DEBUGOUT ("this drivers requires that the reader supports T=1, " DEBUGOUT ("this drivers requires that the reader supports T=1, "
"TPDU or APDU level exchange and auto configuration - " "TPDU or APDU level exchange - this is not available\n");
"this is not available\n");
return -1; return -1;
} }
@ -1506,6 +1528,29 @@ ccid_get_reader_list (void)
} }
/* Vendor specific custom initialization. */
static int
ccid_vendor_specific_init (ccid_driver_t handle)
{
if (handle->id_vendor == VENDOR_VEGA && handle->id_product == VEGA_ALPHA)
{
/*
* Vega alpha has a feature to show retry counter on the pinpad
* display. But it assumes that the card returns the value of
* retry counter by VERIFY with empty data (return code of
* 63Cx). Unfortunately, existing OpenPGP cards don't support
* VERIFY command with empty data. This vendor specific command
* sequence is to disable the feature.
*/
const unsigned char cmd[] = "\xb5\x01\x00\x03\x00";
return send_escape_cmd (handle, cmd, sizeof (cmd), NULL, 0, NULL);
}
return 0;
}
/* Open the reader with the internal number READERNO and return a /* Open the reader with the internal number READERNO and return a
pointer to be used as handle in HANDLE. Returns 0 on success. */ pointer to be used as handle in HANDLE. Returns 0 on success. */
int int
@ -1614,6 +1659,8 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
} }
} }
rc = ccid_vendor_specific_init (*handle);
leave: leave:
free (ifcdesc_extra); free (ifcdesc_extra);
if (rc) if (rc)
@ -2338,6 +2385,151 @@ ccid_slot_status (ccid_driver_t handle, int *statusbits)
} }
/* Parse ATR string (of ATRLEN) and update parameters at PARAM.
Calling this routine, it should prepare default values at PARAM
beforehand. This routine assumes that card is accessed by T=1
protocol. It doesn't analyze historical bytes at all.
Returns < 0 value on error:
-1 for parse error or integrity check error
-2 for card doesn't support T=1 protocol
-3 for parameters are nod explicitly defined by ATR
-4 for this driver doesn't support CRC
Returns >= 0 on success:
0 for card is negotiable mode
1 for card is specific mode (and not negotiable)
*/
static int
update_param_by_atr (unsigned char *param, unsigned char *atr, size_t atrlen)
{
int i = -1;
int t, y, chk;
int historical_bytes_num, negotiable = 1;
#define NEXTBYTE() do { i++; if (atrlen <= i) return -1; } while (0)
NEXTBYTE ();
if (atr[i] == 0x3F)
param[1] |= 0x02; /* Convention is inverse. */
NEXTBYTE ();
y = (atr[i] >> 4);
historical_bytes_num = atr[i] & 0x0f;
NEXTBYTE ();
if ((y & 1))
{
param[0] = atr[i]; /* TA1 - Fi & Di */
NEXTBYTE ();
}
if ((y & 2))
NEXTBYTE (); /* TB1 - ignore */
if ((y & 4))
{
param[2] = atr[i]; /* TC1 - Guard Time */
NEXTBYTE ();
}
if ((y & 8))
{
y = (atr[i] >> 4); /* TD1 */
t = atr[i] & 0x0f;
NEXTBYTE ();
if ((y & 1))
{ /* TA2 - PPS mode */
if ((atr[i] & 0x0f) != 1)
return -2; /* Wrong card protocol (!= 1). */
if ((atr[i] & 0x10) != 0x10)
return -3; /* Transmission parameters are implicitly defined. */
negotiable = 0; /* TA2 means specific mode. */
NEXTBYTE ();
}
if ((y & 2))
NEXTBYTE (); /* TB2 - ignore */
if ((y & 4))
NEXTBYTE (); /* TC2 - ignore */
if ((y & 8))
{
y = (atr[i] >> 4); /* TD2 */
t = atr[i] & 0x0f;
NEXTBYTE ();
}
else
y = 0;
while (y)
{
if ((y & 1))
{ /* TAx */
if (t == 1)
param[5] = atr[i]; /* IFSC */
else if (t == 15)
/* XXX: check voltage? */
param[4] = (atr[i] >> 6); /* ClockStop */
NEXTBYTE ();
}
if ((y & 2))
{
if (t == 1)
param[3] = atr[i]; /* TBx - BWI & CWI */
NEXTBYTE ();
}
if ((y & 4))
{
if (t == 1)
param[1] |= (atr[i] & 0x01); /* TCx - LRC/CRC */
NEXTBYTE ();
if (param[1] & 0x01)
return -4; /* CRC not supported yet. */
}
if ((y & 8))
{
y = (atr[i] >> 4); /* TDx */
t = atr[i] & 0x0f;
NEXTBYTE ();
}
else
y = 0;
}
}
i += historical_bytes_num - 1;
NEXTBYTE ();
if (atrlen != i+1)
return -1;
#undef NEXTBYTE
chk = 0;
do
{
chk ^= atr[i];
i--;
}
while (i > 0);
if (chk != 0)
return -1;
return negotiable;
}
/* Return the ATR of the card. This is not a cached value and thus an /* Return the ATR of the card. This is not a cached value and thus an
actual reset is done. */ actual reset is done. */
int int
@ -2354,6 +2546,15 @@ ccid_get_atr (ccid_driver_t handle,
unsigned int edc; unsigned int edc;
int tried_iso = 0; int tried_iso = 0;
int got_param; int got_param;
unsigned char param[7] = { /* For Protocol T=1 */
0x11, /* bmFindexDindex */
0x10, /* bmTCCKST1 */
0x00, /* bGuardTimeT1 */
0x4d, /* bmWaitingIntegersT1 */
0x00, /* bClockStop */
0x20, /* bIFSC */
0x00 /* bNadValue */
};
/* First check whether a card is available. */ /* First check whether a card is available. */
rc = ccid_slot_status (handle, &statusbits); rc = ccid_slot_status (handle, &statusbits);
@ -2368,7 +2569,8 @@ ccid_get_atr (ccid_driver_t handle,
msg[0] = PC_to_RDR_IccPowerOn; msg[0] = PC_to_RDR_IccPowerOn;
msg[5] = 0; /* slot */ msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++; msg[6] = seqno = handle->seqno++;
msg[7] = 0; /* power select (0=auto, 1=5V, 2=3V, 3=1.8V) */ /* power select (0=auto, 1=5V, 2=3V, 3=1.8V) */
msg[7] = handle->auto_voltage ? 0 : 1;
msg[8] = 0; /* RFU */ msg[8] = 0; /* RFU */
msg[9] = 0; /* RFU */ msg[9] = 0; /* RFU */
set_msg_len (msg, 0); set_msg_len (msg, 0);
@ -2410,23 +2612,73 @@ ccid_get_atr (ccid_driver_t handle,
*atrlen = n; *atrlen = n;
} }
param[6] = handle->nonnull_nad? ((1 << 4) | 0): 0;
rc = update_param_by_atr (param, msg+10, msglen - 10);
if (rc < 0)
{
DEBUGOUT_1 ("update_param_by_atr failed: %d\n", rc);
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
got_param = 0; got_param = 0;
msg[0] = PC_to_RDR_GetParameters;
msg[5] = 0; /* slot */ if (handle->auto_param)
msg[6] = seqno = handle->seqno++; {
msg[7] = 0; /* RFU */ msg[0] = PC_to_RDR_GetParameters;
msg[8] = 0; /* RFU */ msg[5] = 0; /* slot */
msg[9] = 0; /* RFU */ msg[6] = seqno = handle->seqno++;
set_msg_len (msg, 0); msg[7] = 0; /* RFU */
msglen = 10; msg[8] = 0; /* RFU */
rc = bulk_out (handle, msg, msglen, 0); msg[9] = 0; /* RFU */
if (!rc) set_msg_len (msg, 0);
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters, msglen = 10;
seqno, 2000, 0); rc = bulk_out (handle, msg, msglen, 0);
if (rc) if (!rc)
DEBUGOUT ("GetParameters failed\n"); rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
else if (msglen == 17 && msg[9] == 1) seqno, 2000, 0);
got_param = 1; if (rc)
DEBUGOUT ("GetParameters failed\n");
else if (msglen == 17 && msg[9] == 1)
got_param = 1;
}
else if (handle->auto_pps)
;
else if (rc == 1) /* It's negotiable, send PPS. */
{
msg[0] = PC_to_RDR_XfrBlock;
msg[5] = 0; /* slot */
msg[6] = seqno = handle->seqno++;
msg[7] = 0;
msg[8] = 0;
msg[9] = 0;
msg[10] = 0xff; /* PPSS */
msg[11] = 0x11; /* PPS0: PPS1, Protocol T=1 */
msg[12] = param[0]; /* PPS1: Fi / Di */
msg[13] = 0xff ^ 0x11 ^ param[0]; /* PCK */
set_msg_len (msg, 4);
msglen = 10 + 4;
rc = bulk_out (handle, msg, msglen, 0);
if (rc)
return rc;
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock,
seqno, 5000, 0);
if (rc)
return rc;
if (msglen != 10 + 4)
{
DEBUGOUT_1 ("Setting PPS failed: %d\n", msglen);
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
if (msg[10] != 0xff || msg[11] != 0x11 || msg[12] != param[0])
{
DEBUGOUT_1 ("Setting PPS failed: 0x%02x\n", param[0]);
return CCID_DRIVER_ERR_CARD_IO_ERROR;
}
}
/* Setup parameters to select T=1. */ /* Setup parameters to select T=1. */
msg[0] = PC_to_RDR_SetParameters; msg[0] = PC_to_RDR_SetParameters;
@ -2437,16 +2689,7 @@ ccid_get_atr (ccid_driver_t handle,
msg[9] = 0; /* RFU */ msg[9] = 0; /* RFU */
if (!got_param) if (!got_param)
{ memcpy (&msg[10], param, 7);
/* FIXME: Get those values from the ATR. */
msg[10]= 0x01; /* Fi/Di */
msg[11]= 0x10; /* LRC, direct convention. */
msg[12]= 0; /* Extra guardtime. */
msg[13]= 0x41; /* BWI/CWI */
msg[14]= 0; /* No clock stoppping. */
msg[15]= 254; /* IFSC */
msg[16]= 0; /* Does not support non default NAD values. */
}
set_msg_len (msg, 7); set_msg_len (msg, 7);
msglen = 10 + 7; msglen = 10 + 7;
@ -2463,6 +2706,12 @@ ccid_get_atr (ccid_driver_t handle,
else else
handle->ifsc = 128; /* Something went wrong, assume 128 bytes. */ handle->ifsc = 128; /* Something went wrong, assume 128 bytes. */
if (handle->nonnull_nad && msglen > 16 && msg[16] == 0)
{
DEBUGOUT ("Use Null-NAD, clearing handle->nonnull_nad.\n");
handle->nonnull_nad = 0;
}
handle->t1_ns = 0; handle->t1_ns = 0;
handle->t1_nr = 0; handle->t1_nr = 0;
@ -3071,7 +3320,7 @@ ccid_transceive (ccid_driver_t handle,
The APDU should me made up of 4 bytes without Lc. The APDU should me made up of 4 bytes without Lc.
PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0 PINLEN_MIN and PINLEN_MAX define the limits for the pin length. 0
may be used t enable reasonable defaults. PIN_PADLEN should be 0. may be used t enable reasonable defaults.
When called with RESP and NRESP set to NULL, the function will When called with RESP and NRESP set to NULL, the function will
merely check whether the reader supports the secure command for the merely check whether the reader supports the secure command for the
@ -3079,8 +3328,7 @@ ccid_transceive (ccid_driver_t handle,
int int
ccid_transceive_secure (ccid_driver_t handle, ccid_transceive_secure (ccid_driver_t handle,
const unsigned char *apdu_buf, size_t apdu_buflen, const unsigned char *apdu_buf, size_t apdu_buflen,
int pin_mode, int pinlen_min, int pinlen_max, pininfo_t *pininfo,
int pin_padlen,
unsigned char *resp, size_t maxresplen, size_t *nresp) unsigned char *resp, size_t maxresplen, size_t *nresp)
{ {
int rc; int rc;
@ -3091,6 +3339,7 @@ ccid_transceive_secure (ccid_driver_t handle,
size_t dummy_nresp; size_t dummy_nresp;
int testmode; int testmode;
int cherry_mode = 0; int cherry_mode = 0;
int enable_varlen = 0;
testmode = !resp && !nresp; testmode = !resp && !nresp;
@ -3103,23 +3352,17 @@ ccid_transceive_secure (ccid_driver_t handle,
else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2)) else if (apdu_buflen >= 4 && apdu_buf[1] == 0x24 && (handle->has_pinpad & 2))
; ;
else else
return CCID_DRIVER_ERR_NO_KEYPAD; return CCID_DRIVER_ERR_NO_PINPAD;
if (pin_mode != 1) if (!pininfo->minlen)
return CCID_DRIVER_ERR_NOT_SUPPORTED; pininfo->minlen = 1;
if (!pininfo->maxlen)
if (pin_padlen != 0) pininfo->maxlen = 25;
return CCID_DRIVER_ERR_NOT_SUPPORTED;
if (!pinlen_min)
pinlen_min = 1;
if (!pinlen_max)
pinlen_max = 25;
/* Note that the 25 is the maximum value the SPR532 allows. */ /* Note that the 25 is the maximum value the SPR532 allows. */
if (pinlen_min < 1 || pinlen_min > 25 if (pininfo->minlen < 1 || pininfo->minlen > 25
|| pinlen_max < 1 || pinlen_max > 25 || pininfo->maxlen < 1 || pininfo->maxlen > 25
|| pinlen_min > pinlen_max) || pininfo->minlen > pininfo->maxlen)
return CCID_DRIVER_ERR_INV_VALUE; return CCID_DRIVER_ERR_INV_VALUE;
/* We have only tested a few readers so better don't risk anything /* We have only tested a few readers so better don't risk anything
@ -3129,11 +3372,14 @@ ccid_transceive_secure (ccid_driver_t handle,
case VENDOR_SCM: /* Tested with SPR 532. */ case VENDOR_SCM: /* Tested with SPR 532. */
case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */ case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */
case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05). */ case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05). */
enable_varlen = 1;
break; break;
case VENDOR_VASCO: /* Tested with DIGIPASS 920 */ case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
pinlen_max = 15; enable_varlen = 1;
pininfo->maxlen = 15;
break; break;
case VENDOR_CHERRY: case VENDOR_CHERRY:
enable_varlen = 1;
/* The CHERRY XX44 keyboard echos an asterisk for each entered /* The CHERRY XX44 keyboard echos an asterisk for each entered
character on the keyboard channel. We use a special variant character on the keyboard channel. We use a special variant
of PC_to_RDR_Secure which directs these characters to the of PC_to_RDR_Secure which directs these characters to the
@ -3145,12 +3391,28 @@ ccid_transceive_secure (ccid_driver_t handle,
cherry_mode = 1; cherry_mode = 1;
break; break;
default: default:
if ((handle->id_vendor == VENDOR_GEMPC &&
handle->id_product == GEMPC_PINPAD)
|| (handle->id_vendor == VENDOR_VEGA &&
handle->id_product == VEGA_ALPHA))
{
enable_varlen = 0;
pininfo->minlen = 4;
pininfo->maxlen = 8;
break;
}
return CCID_DRIVER_ERR_NOT_SUPPORTED; return CCID_DRIVER_ERR_NOT_SUPPORTED;
} }
if (enable_varlen)
pininfo->fixedlen = 0;
if (testmode) if (testmode)
return 0; /* Success */ return 0; /* Success */
if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
return CCID_DRIVER_ERR_NOT_SUPPORTED;
msg = send_buffer; msg = send_buffer;
if (handle->id_vendor == VENDOR_SCM) if (handle->id_vendor == VENDOR_SCM)
{ {
@ -3180,9 +3442,9 @@ ccid_transceive_secure (ccid_driver_t handle,
} }
else else
{ {
msg[13] = 0x00; /* bmPINBlockString: msg[13] = pininfo->fixedlen; /* bmPINBlockString:
0 bits of pin length to insert. 0 bits of pin length to insert.
0 bytes of PIN block size. */ PIN block size by fixedlen. */
msg[14] = 0x00; /* bmPINLengthFormat: msg[14] = 0x00; /* bmPINLengthFormat:
Units are bytes, position is 0. */ Units are bytes, position is 0. */
} }
@ -3191,12 +3453,12 @@ ccid_transceive_secure (ccid_driver_t handle,
if (apdu_buf[1] == 0x24) if (apdu_buf[1] == 0x24)
{ {
msg[msglen++] = 0; /* bInsertionOffsetOld */ msg[msglen++] = 0; /* bInsertionOffsetOld */
msg[msglen++] = 0; /* bInsertionOffsetNew */ msg[msglen++] = pininfo->fixedlen; /* bInsertionOffsetNew */
} }
/* The following is a little endian word. */ /* The following is a little endian word. */
msg[msglen++] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */ msg[msglen++] = pininfo->maxlen; /* wPINMaxExtraDigit-Maximum. */
msg[msglen++] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */ msg[msglen++] = pininfo->minlen; /* wPINMaxExtraDigit-Minimum. */
if (apdu_buf[1] == 0x24) if (apdu_buf[1] == 0x24)
msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01; msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01;
@ -3209,12 +3471,12 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[msglen] = 0x02; /* bEntryValidationCondition: msg[msglen] = 0x02; /* bEntryValidationCondition:
Validation key pressed */ Validation key pressed */
if (pinlen_min && pinlen_max && pinlen_min == pinlen_max) if (pininfo->minlen && pininfo->maxlen && pininfo->minlen == pininfo->maxlen)
msg[msglen] |= 0x01; /* Max size reached. */ msg[msglen] |= 0x01; /* Max size reached. */
msglen++; msglen++;
if (apdu_buf[1] == 0x20) if (apdu_buf[1] == 0x20)
msg[msglen++] = 0xff; /* bNumberMessage: Default. */ msg[msglen++] = 0x01; /* bNumberMessage. */
else else
msg[msglen++] = 0x03; /* bNumberMessage. */ msg[msglen++] = 0x03; /* bNumberMessage. */
@ -3230,10 +3492,18 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[msglen++] = 2; /* bMsgIndex3. */ msg[msglen++] = 2; /* bMsgIndex3. */
} }
/* Calculate Lc. */
n = pininfo->fixedlen;
if (apdu_buf[1] == 0x24)
n += pininfo->fixedlen;
/* bTeoProlog follows: */ /* bTeoProlog follows: */
msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0; msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0;
msg[msglen++] = ((handle->t1_ns & 1) << 6); /* I-block */ msg[msglen++] = ((handle->t1_ns & 1) << 6); /* I-block */
msg[msglen++] = 0; /* The apdulen will be filled in by the reader. */ if (n)
msg[msglen++] = n + 5; /* apdulen should be filled for fixed length. */
else
msg[msglen++] = 0; /* The apdulen will be filled in by the reader. */
/* APDU follows: */ /* APDU follows: */
msg[msglen++] = apdu_buf[0]; /* CLA */ msg[msglen++] = apdu_buf[0]; /* CLA */
msg[msglen++] = apdu_buf[1]; /* INS */ msg[msglen++] = apdu_buf[1]; /* INS */
@ -3241,6 +3511,12 @@ ccid_transceive_secure (ccid_driver_t handle,
msg[msglen++] = apdu_buf[3]; /* P2 */ msg[msglen++] = apdu_buf[3]; /* P2 */
if (cherry_mode) if (cherry_mode)
msg[msglen++] = 0; msg[msglen++] = 0;
else if (pininfo->fixedlen != 0)
{
msg[msglen++] = n;
memset (&msg[msglen], 0xff, n);
msglen += n;
}
/* An EDC is not required. */ /* An EDC is not required. */
set_msg_len (msg, msglen - 10); set_msg_len (msg, msglen - 10);

View File

@ -72,7 +72,7 @@
#define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b #define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b
#define CCID_DRIVER_ERR_NO_READER 0x1000c #define CCID_DRIVER_ERR_NO_READER 0x1000c
#define CCID_DRIVER_ERR_ABORTED 0x1000d #define CCID_DRIVER_ERR_ABORTED 0x1000d
#define CCID_DRIVER_ERR_NO_KEYPAD 0x1000e #define CCID_DRIVER_ERR_NO_PINPAD 0x1000e
struct ccid_driver_s; struct ccid_driver_s;
typedef struct ccid_driver_s *ccid_driver_t; typedef struct ccid_driver_s *ccid_driver_t;
@ -93,8 +93,7 @@ int ccid_transceive (ccid_driver_t handle,
unsigned char *resp, size_t maxresplen, size_t *nresp); unsigned char *resp, size_t maxresplen, size_t *nresp);
int ccid_transceive_secure (ccid_driver_t handle, int ccid_transceive_secure (ccid_driver_t handle,
const unsigned char *apdu, size_t apdulen, const unsigned char *apdu, size_t apdulen,
int pin_mode, pininfo_t *pininfo,
int pinlen_min, int pinlen_max, int pin_padlen,
unsigned char *resp, size_t maxresplen, size_t *nresp); unsigned char *resp, size_t maxresplen, size_t *nresp);
int ccid_transceive_escape (ccid_driver_t handle, int ccid_transceive_escape (ccid_driver_t handle,
const unsigned char *data, size_t datalen, const unsigned char *data, size_t datalen,

View File

@ -34,6 +34,7 @@
#include <assuan.h> #include <assuan.h>
#include <ksba.h> #include <ksba.h>
#include "app-common.h" #include "app-common.h"
#include "iso7816.h"
#include "apdu.h" /* Required for apdu_*_reader (). */ #include "apdu.h" /* Required for apdu_*_reader (). */
#include "atr.h" #include "atr.h"
#include "exechelp.h" #include "exechelp.h"
@ -908,13 +909,13 @@ pin_cb (void *opaque, const char *info, char **retstr)
if (!retstr) if (!retstr)
{ {
/* We prompt for keypad entry. To make sure that the popup has /* We prompt for pinpad entry. To make sure that the popup has
been show we use an inquire and not just a status message. been show we use an inquire and not just a status message.
We ignore any value returned. */ We ignore any value returned. */
if (info) if (info)
{ {
log_debug ("prompting for keypad entry '%s'\n", info); log_debug ("prompting for pinpad entry '%s'\n", info);
rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info); rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info);
if (rc < 0) if (rc < 0)
return gpg_error (gpg_err_code_from_errno (errno)); return gpg_error (gpg_err_code_from_errno (errno));
rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN); rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
@ -922,8 +923,8 @@ pin_cb (void *opaque, const char *info, char **retstr)
} }
else else
{ {
log_debug ("dismiss keypad entry prompt\n"); log_debug ("dismiss pinpad entry prompt\n");
rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT", rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
&value, &valuelen, MAXLEN_PIN); &value, &valuelen, MAXLEN_PIN);
} }
if (!rc) if (!rc)

View File

@ -94,7 +94,7 @@ map_sw (int sw)
case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break; case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break;
case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break; case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; break;
case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break; case SW_HOST_ABORTED: ec = GPG_ERR_CANCELED; break;
case SW_HOST_NO_KEYPAD: ec = GPG_ERR_NOT_SUPPORTED; break; case SW_HOST_NO_PINPAD: ec = GPG_ERR_NOT_SUPPORTED; break;
default: default:
if ((sw & 0x010000)) if ((sw & 0x010000))
@ -267,30 +267,26 @@ iso7816_apdu_direct (int slot, const void *apdudata, size_t apdudatalen,
/* Check whether the reader supports the ISO command code COMMAND on /* Check whether the reader supports the ISO command code COMMAND on
the keypad. Returns 0 on success. */ the pinpad. Returns 0 on success. */
gpg_error_t gpg_error_t
iso7816_check_keypad (int slot, int command, iso7816_pininfo_t *pininfo) iso7816_check_pinpad (int slot, int command, pininfo_t *pininfo)
{ {
int sw; int sw;
sw = apdu_check_keypad (slot, command, sw = apdu_check_pinpad (slot, command, pininfo);
pininfo->mode, pininfo->minlen, pininfo->maxlen,
pininfo->padlen);
return iso7816_map_sw (sw); return iso7816_map_sw (sw);
} }
/* Perform a VERIFY command on SLOT using the card holder verification /* Perform a VERIFY command on SLOT using the card holder verification
vector CHVNO. With PININFO non-NULL the keypad of the reader will vector CHVNO. With PININFO non-NULL the pinpad of the reader will
be used. Returns 0 on success. */ be used. Returns 0 on success. */
gpg_error_t gpg_error_t
iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo) iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo)
{ {
int sw; int sw;
sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, sw = apdu_pinpad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, pininfo);
pininfo->mode, pininfo->minlen, pininfo->maxlen,
pininfo->padlen);
return map_sw (sw); return map_sw (sw);
} }
@ -306,19 +302,17 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
} }
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder /* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
verification vector CHVNO. With PININFO non-NULL the keypad of the verification vector CHVNO. With PININFO non-NULL the pinpad of the
reader will be used. If IS_EXCHANGE is 0, a "change reference reader will be used. If IS_EXCHANGE is 0, a "change reference
data" is done, otherwise an "exchange reference data". */ data" is done, otherwise an "exchange reference data". */
gpg_error_t gpg_error_t
iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange, iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange,
iso7816_pininfo_t *pininfo) pininfo_t *pininfo)
{ {
int sw; int sw;
sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA, sw = apdu_pinpad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
is_exchange ? 1 : 0, is_exchange ? 1 : 0, chvno, pininfo);
chvno, pininfo->mode, pininfo->minlen,
pininfo->maxlen, pininfo->padlen);
return map_sw (sw); return map_sw (sw);
} }

View File

@ -24,23 +24,26 @@
#include "cardglue.h" #include "cardglue.h"
#endif #endif
/* Command codes used by iso7816_check_keypad. */ /* Command codes used by iso7816_check_pinpad. */
#define ISO7816_VERIFY 0x20 #define ISO7816_VERIFY 0x20
#define ISO7816_CHANGE_REFERENCE_DATA 0x24 #define ISO7816_CHANGE_REFERENCE_DATA 0x24
#define ISO7816_RESET_RETRY_COUNTER 0x2C #define ISO7816_RESET_RETRY_COUNTER 0x2C
/* Information to be passed to keypad equipped readers. See /* Information to be passed to pinpad equipped readers. See
ccid-driver.c for details. */ ccid-driver.c for details. */
struct iso7816_pininfo_s struct pininfo_s
{ {
int mode; /* A mode of 0 means: Do not use the keypad. */ int fixedlen; /*
* -1: Variable length input is not supported,
* no information of fixed length yet.
* 0: Use variable length input.
* >0: Fixed length of PIN.
*/
int minlen; int minlen;
int maxlen; int maxlen;
int padlen;
int padchar;
}; };
typedef struct iso7816_pininfo_s iso7816_pininfo_t; typedef struct pininfo_s pininfo_t;
gpg_error_t iso7816_map_sw (int sw); gpg_error_t iso7816_map_sw (int sw);
@ -59,17 +62,17 @@ gpg_error_t iso7816_apdu_direct (int slot,
const void *apdudata, size_t apdudatalen, const void *apdudata, size_t apdudatalen,
int handle_more, int handle_more,
unsigned char **result, size_t *resultlen); unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_check_keypad (int slot, int command, gpg_error_t iso7816_check_pinpad (int slot, int command,
iso7816_pininfo_t *pininfo); pininfo_t *pininfo);
gpg_error_t iso7816_verify (int slot, gpg_error_t iso7816_verify (int slot,
int chvno, const char *chv, size_t chvlen); int chvno, const char *chv, size_t chvlen);
gpg_error_t iso7816_verify_kp (int slot, int chvno, iso7816_pininfo_t *pininfo); gpg_error_t iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo);
gpg_error_t iso7816_change_reference_data (int slot, int chvno, gpg_error_t iso7816_change_reference_data (int slot, int chvno,
const char *oldchv, size_t oldchvlen, const char *oldchv, size_t oldchvlen,
const char *newchv, size_t newchvlen); const char *newchv, size_t newchvlen);
gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno, gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
int is_exchange, int is_exchange,
iso7816_pininfo_t *pininfo); pininfo_t *pininfo);
gpg_error_t iso7816_reset_retry_counter (int slot, int chvno, gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
const char *newchv, size_t newchvlen); const char *newchv, size_t newchvlen);
gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno, gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,

View File

@ -33,6 +33,7 @@
#include "../common/ttyio.h" #include "../common/ttyio.h"
#include "../common/simple-pwquery.h" #include "../common/simple-pwquery.h"
#include "iso7816.h"
#include "apdu.h" /* for open_reader */ #include "apdu.h" /* for open_reader */
#include "atr.h" #include "atr.h"
#include "app-common.h" #include "app-common.h"

View File

@ -48,6 +48,7 @@
#include "i18n.h" #include "i18n.h"
#include "sysutils.h" #include "sysutils.h"
#include "app-common.h" #include "app-common.h"
#include "iso7816.h"
#include "apdu.h" #include "apdu.h"
#include "ccid-driver.h" #include "ccid-driver.h"
#include "mkdtemp.h" #include "mkdtemp.h"
@ -91,10 +92,11 @@ enum cmd_and_opt_values
opcscDriver, opcscDriver,
oDisableCCID, oDisableCCID,
oDisableOpenSC, oDisableOpenSC,
oDisableKeypad, oDisablePinpad,
oAllowAdmin, oAllowAdmin,
oDenyAdmin, oDenyAdmin,
oDisableApplication, oDisableApplication,
oEnablePinpadVarlen,
oDebugDisableTicker oDebugDisableTicker
}; };
@ -142,12 +144,14 @@ static ARGPARSE_OPTS opts[] = {
/* end --disable-ccid */), /* end --disable-ccid */),
ARGPARSE_s_u (oCardTimeout, "card-timeout", ARGPARSE_s_u (oCardTimeout, "card-timeout",
N_("|N|disconnect the card after N seconds of inactivity")), N_("|N|disconnect the card after N seconds of inactivity")),
ARGPARSE_s_n (oDisableKeypad, "disable-keypad", ARGPARSE_s_n (oDisablePinpad, "disable-pinpad",
N_("do not use a reader's keypad")), N_("do not use a reader's pinpad")),
ARGPARSE_s_n (oAllowAdmin, "allow-admin", "@"), ARGPARSE_s_n (oAllowAdmin, "allow-admin", "@"),
ARGPARSE_s_n (oDenyAdmin, "deny-admin", ARGPARSE_s_n (oDenyAdmin, "deny-admin",
N_("deny the use of admin card commands")), N_("deny the use of admin card commands")),
ARGPARSE_s_s (oDisableApplication, "disable-application", "@"), ARGPARSE_s_s (oDisableApplication, "disable-application", "@"),
ARGPARSE_s_n (oEnablePinpadVarlen, "enable-pinpad-varlen",
N_("use variable length input for pinpad")),
ARGPARSE_end () ARGPARSE_end ()
}; };
@ -575,7 +579,7 @@ main (int argc, char **argv )
case oDisableCCID: opt.disable_ccid = 1; break; case oDisableCCID: opt.disable_ccid = 1; break;
case oDisableOpenSC: break; case oDisableOpenSC: break;
case oDisableKeypad: opt.disable_keypad = 1; break; case oDisablePinpad: opt.disable_pinpad = 1; break;
case oAllowAdmin: /* Dummy because allow is now the default. */ case oAllowAdmin: /* Dummy because allow is now the default. */
break; break;
@ -587,6 +591,8 @@ main (int argc, char **argv )
add_to_strlist (&opt.disabled_applications, pargs.r.ret_str); add_to_strlist (&opt.disabled_applications, pargs.r.ret_str);
break; break;
case oEnablePinpadVarlen: opt.enable_pinpad_varlen = 1; break;
default: default:
pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR; pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
break; break;
@ -675,8 +681,9 @@ main (int argc, char **argv )
es_printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE ); es_printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE );
#endif #endif
es_printf ("deny-admin:%lu:\n", GC_OPT_FLAG_NONE ); es_printf ("deny-admin:%lu:\n", GC_OPT_FLAG_NONE );
es_printf ("disable-keypad:%lu:\n", GC_OPT_FLAG_NONE ); es_printf ("disable-pinpad:%lu:\n", GC_OPT_FLAG_NONE );
es_printf ("card-timeout:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, 0); es_printf ("card-timeout:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, 0);
es_printf ("enable-pinpad-varlen:%lu:\n", GC_OPT_FLAG_NONE );
scd_exit (0); scd_exit (0);
} }

View File

@ -56,7 +56,8 @@ struct
const char *pcsc_driver; /* Library to access the PC/SC system. */ const char *pcsc_driver; /* Library to access the PC/SC system. */
const char *reader_port; /* NULL or reder port to use. */ const char *reader_port; /* NULL or reder port to use. */
int disable_ccid; /* Disable the use of the internal CCID driver. */ int disable_ccid; /* Disable the use of the internal CCID driver. */
int disable_keypad; /* Do not use a keypad. */ int disable_pinpad; /* Do not use a pinpad. */
int enable_pinpad_varlen; /* Use variable length input for pinpad. */
int allow_admin; /* Allow the use of admin commands for certain int allow_admin; /* Allow the use of admin commands for certain
cards. */ cards. */
strlist_t disabled_applications; /* Card applications we do not strlist_t disabled_applications; /* Card applications we do not

View File

@ -617,8 +617,8 @@ static gc_option_t gc_options_scdaemon[] =
{ "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT, { "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
"gnupg", "do not use the internal CCID driver", "gnupg", "do not use the internal CCID driver",
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
{ "disable-keypad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, { "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
"gnupg", "do not use a reader's keypad", "gnupg", "do not use a reader's pinpad",
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON }, GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
{ "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC, { "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
"gnupg", "|N|disconnect the card after N seconds of inactivity", "gnupg", "|N|disconnect the card after N seconds of inactivity",