mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-19 19:28:03 +01:00
Merge branch 'master' into key-storage-work
This commit is contained in:
commit
caddeef4a7
9
NEWS
9
NEWS
@ -11,6 +11,15 @@ Noteworthy changes in version 2.1.0beta4 (unreleased)
|
||||
|
||||
* 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)
|
||||
-----------------------------------------------------
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "../common/membuf.h"
|
||||
#include "../common/sysutils.h" /* (gnupg_fd_t) */
|
||||
#include "../common/session-env.h"
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
/* To convey some special hash algorithms we use algorithm numbers
|
||||
reserved for application use. */
|
||||
@ -46,16 +47,6 @@
|
||||
#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 */
|
||||
struct
|
||||
@ -421,6 +412,8 @@ int divert_pkdecrypt (ctrl_t ctrl,
|
||||
char **r_buf, size_t *r_len);
|
||||
int divert_generic_cmd (ctrl_t ctrl,
|
||||
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 --*/
|
||||
@ -454,6 +447,11 @@ int agent_card_pkdecrypt (ctrl_t ctrl,
|
||||
int agent_card_readcert (ctrl_t ctrl,
|
||||
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_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);
|
||||
int agent_card_scd (ctrl_t ctrl, const char *cmdline,
|
||||
int (*getpin_cb)(void *, const char *, char*, size_t),
|
||||
|
@ -1266,9 +1266,9 @@ agent_popup_message_stop (ctrl_t ctrl)
|
||||
|
||||
/* Now wait for the thread to terminate. */
|
||||
rc = npth_join (popup_tid, NULL);
|
||||
if (!rc)
|
||||
if (rc)
|
||||
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
|
||||
to the same content that a static global variable has. */
|
||||
memset (&popup_tid, '\0', sizeof (popup_tid));
|
||||
|
@ -722,7 +722,7 @@ inq_needpin (void *opaque, const char *line)
|
||||
rc = assuan_send_data (parm->ctx, pin, pinlen);
|
||||
xfree (pin);
|
||||
}
|
||||
else if (!strncmp (line, "POPUPKEYPADPROMPT", 17)
|
||||
else if (!strncmp (line, "POPUPPINPADPROMPT", 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);
|
||||
}
|
||||
else if (!strncmp (line, "DISMISSKEYPADPROMPT", 19)
|
||||
else if (!strncmp (line, "DISMISSPINPADPROMPT", 19)
|
||||
&& (line[19] == ' ' || !line[19]))
|
||||
{
|
||||
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. */
|
||||
struct card_getattr_parm_s {
|
||||
|
145
agent/command.c
145
agent/command.c
@ -2119,9 +2119,133 @@ cmd_export_key (assuan_context_t ctx, char *line)
|
||||
|
||||
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[] =
|
||||
"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;
|
||||
else if (!strcmp (key, "pinentry-mode"))
|
||||
{
|
||||
if (!strcmp (value, "ask") || !strcmp (value, "default"))
|
||||
ctrl->pinentry_mode = PINENTRY_MODE_ASK;
|
||||
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
|
||||
int tmp = parse_pinentry_mode (value);
|
||||
if (tmp == -1)
|
||||
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"))
|
||||
{
|
||||
@ -2682,6 +2798,7 @@ register_commands (assuan_context_t ctx)
|
||||
{ "KILLAGENT", cmd_killagent, hlp_killagent },
|
||||
{ "RELOADAGENT", cmd_reloadagent,hlp_reloadagent },
|
||||
{ "GETINFO", cmd_getinfo, hlp_getinfo },
|
||||
{ "KEYTOCARD", cmd_keytocard, hlp_keytocard },
|
||||
{ NULL }
|
||||
};
|
||||
int i, rc;
|
||||
|
@ -223,7 +223,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
else if (info && *info == '|')
|
||||
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. */
|
||||
if (!buf)
|
||||
{
|
||||
@ -239,7 +239,7 @@ getpin_cb (void *opaque, const char *info, char *buf, size_t maxbuf)
|
||||
char *desc;
|
||||
|
||||
if ( asprintf (&desc,
|
||||
_("%s%%0A%%0AUse the reader's keypad for input."),
|
||||
_("%s%%0A%%0AUse the reader's pinpad for input."),
|
||||
info) < 0 )
|
||||
rc = gpg_error_from_syserror ();
|
||||
else
|
||||
@ -442,6 +442,13 @@ divert_pkdecrypt (ctrl_t ctrl,
|
||||
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
|
||||
divert_generic_cmd (ctrl_t ctrl, const char *cmdline, void *assuan_context)
|
||||
|
@ -1075,7 +1075,11 @@ hash_passphrase (const char *passphrase, int hashalgo,
|
||||
unsigned long s2kcount,
|
||||
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),
|
||||
s2kmode == 3? GCRY_KDF_ITERSALTED_S2K :
|
||||
s2kmode == 1? GCRY_KDF_SALTED_S2K :
|
||||
|
@ -59,6 +59,7 @@ common_sources = \
|
||||
util.h i18n.c i18n.h \
|
||||
estream.c estream.h estream-printf.c estream-printf.h \
|
||||
status.c status.h\
|
||||
shareddefs.h \
|
||||
openpgpdefs.h \
|
||||
gc-opt-flags.h \
|
||||
keyserver.h \
|
||||
@ -92,6 +93,7 @@ common_sources = \
|
||||
userids.c userids.h \
|
||||
openpgp-oid.c \
|
||||
ssh-utils.c ssh-utils.h \
|
||||
agent-opt.c \
|
||||
helpfile.c
|
||||
|
||||
# To make the code easier to read we have split home some code into
|
||||
|
71
common/agent-opt.c
Normal file
71
common/agent-opt.c
Normal 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
48
common/shareddefs.h
Normal 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*/
|
@ -84,8 +84,6 @@ enum
|
||||
STATUS_NOTATION_NAME,
|
||||
STATUS_NOTATION_DATA,
|
||||
STATUS_POLICY_URL,
|
||||
STATUS_BEGIN_STREAM,
|
||||
STATUS_END_STREAM,
|
||||
STATUS_KEY_CREATED,
|
||||
STATUS_USERID_HINT,
|
||||
STATUS_UNEXPECTED,
|
||||
@ -97,7 +95,6 @@ enum
|
||||
STATUS_ALREADY_SIGNED,
|
||||
STATUS_KEYEXPIRED,
|
||||
STATUS_KEYREVOKED,
|
||||
STATUS_SIGEXPIRED,
|
||||
STATUS_EXPSIG,
|
||||
STATUS_EXPKEYSIG,
|
||||
|
||||
@ -125,6 +122,8 @@ enum
|
||||
STATUS_TRUNCATED,
|
||||
STATUS_MOUNTPOINT,
|
||||
|
||||
STATUS_PINENTRY_LAUNCHED,
|
||||
|
||||
STATUS_ERROR,
|
||||
STATUS_SUCCESS
|
||||
};
|
||||
|
@ -1519,7 +1519,7 @@ fi
|
||||
build_scdaemon_extra=""
|
||||
if test "$build_scdaemon" = "yes"; then
|
||||
if test $have_libusb = no; then
|
||||
build_scdaemon_extra="${tmp}without internal CCID driver"
|
||||
build_scdaemon_extra="without internal CCID driver"
|
||||
fi
|
||||
if test -n "$build_scdaemon_extra"; then
|
||||
build_scdaemon_extra="(${build_scdaemon_extra})"
|
||||
|
1808
doc/DETAILS
1808
doc/DETAILS
File diff suppressed because it is too large
Load Diff
20
doc/gpg.texi
20
doc/gpg.texi
@ -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}.
|
||||
@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}
|
||||
@opindex command-fd
|
||||
This is a replacement for the deprecated shared-memory IPC mode.
|
||||
|
423
doc/help.ja.txt
423
doc/help.ja.txt
@ -1,4 +1,4 @@
|
||||
# help..txt - GnuPG online help
|
||||
# help.ja.txt - Japanese GnuPG online help
|
||||
# Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is part of GnuPG.
|
||||
@ -16,268 +16,317 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
.#pinentry.qualitybar.tooltip
|
||||
# [ このエントリは有効にするには、上記のキーの # を削除してください。]
|
||||
# これは例です。
|
||||
このバーは、入力されたパスフレーズの品質を示しています。
|
||||
|
||||
.#gpg.edit_ownertrust.value
|
||||
# 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.
|
||||
バーが赤い色となっている場合、GnuPGはパスフレーズが弱すぎると判断し、受
|
||||
け付けません。管理者にパスフレーズの制限の設定について詳細を問い合わせ
|
||||
てください。
|
||||
.
|
||||
|
||||
.#gpg.edit_ownertrust.set_ultimate.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
To build the Web-of-Trust, GnuPG needs to know which keys are
|
||||
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
|
||||
.gnupg.agent-problem
|
||||
# There was a problem accessing or starting the agent.
|
||||
動作中のGpg-Agentへの接続ができなかったか、通信の問題が発生しました。
|
||||
|
||||
システムは、Gpg-Agentと呼ばれるバックグラウンド・プロセスを利用し、秘密
|
||||
鍵とパスフレーズの問い合わせを処理します。このエージェントは通常、ユー
|
||||
ザがログインするときに開始され、ログインしている間、動いています。もし、
|
||||
エージェントが利用可能でない場合、システムは、その場でエージェントの起
|
||||
動を試しますが、この場合、機能がやや制限され、若干の問題がある場合があ
|
||||
ります。
|
||||
|
||||
もしかしたら、管理者に問い合わせて、この問題をどのように解決したら良い
|
||||
か聞いた方が良いかもしれません。とりあえずの方策としては、一度ログアウ
|
||||
トしてもう一度ログインし、改善が見られるか試してみることがあります。も
|
||||
し、これがうまくいくようであれば管理者に報告してください。それはおそら
|
||||
く、ソフトウェアのバグであることを示していますので。
|
||||
.
|
||||
|
||||
.#gpg.untrusted_key.override
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
If you want to use this untrusted key anyway, answer "yes".
|
||||
|
||||
.gnupg.dirmngr-problem
|
||||
# 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.
|
||||
Enter the user ID of the addressee to whom you want to send the message.
|
||||
|
||||
.gpg.edit_ownertrust.value
|
||||
ここでの値の指定は、あなたに任されています。この値は、第三者に開示され
|
||||
ることは決してありません。ウェブ・オブ・トラストを実装するためにこの値
|
||||
が必要となりますが、(暗黙的に作られる)証明書の網には何も関係しません。
|
||||
.
|
||||
|
||||
.#gpg.keygen.algo
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Select the algorithm to use.
|
||||
|
||||
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.edit_ownertrust.set_ultimate.okay
|
||||
ウェブ・オブ・トラストを構築するためにGnuPGは、どの鍵が究極的に信頼でき
|
||||
るかを知る必要があります。その鍵は通常は、あなたが秘密鍵へアクセスでき
|
||||
るものです。この鍵が究極的に信頼できる場合、"yes" と答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.algo.rsa_se
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
In general it is not a good idea to use the same key for signing and
|
||||
encryption. This algorithm should only be used in certain domains.
|
||||
Please consult your security expert first.
|
||||
|
||||
.gpg.untrusted_key.override
|
||||
この信頼されてない鍵をどちらにせよ使いたい場合、"yes" と答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.size
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Enter the size of the key
|
||||
.gpg.pklist.user_id.enter
|
||||
このメッセージを送りたい宛先のユーザIDを入力してください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.size.huge.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
.gpg.keygen.algo
|
||||
使用するアルゴリズムを選択してください。
|
||||
|
||||
DSA (別名 DSS)は電子署名アルゴリズムであり、署名にのみ使えます。
|
||||
|
||||
Elgamal は暗号化のみのアルゴリズムです。
|
||||
|
||||
RSA は署名と暗号化のどちらにも使えます。
|
||||
|
||||
主鍵は常に、署名が可能の鍵である必要があります。
|
||||
.
|
||||
|
||||
.#gpg.keygen.size.large.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
|
||||
.gpg.keygen.algo.rsa_se
|
||||
一般的に、署名と暗号化に同一の鍵を用いることは良いことではありません。
|
||||
このアルゴリズムはある特定の領域だけに使うべきです。まず、セキュリティ
|
||||
の専門家に相談してください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.valid
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
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.
|
||||
|
||||
.gpg.keygen.size
|
||||
鍵の長さを入力してください。
|
||||
|
||||
提案されたデフォルトが通常良い選択です。
|
||||
|
||||
大きな鍵長を使いたい場合、たとえば4096ビットなど、本当に意味があるか再
|
||||
検討してください。こちらのウェブページを見るのも良いと思います:
|
||||
http://www.xkcd.com/538/
|
||||
.
|
||||
|
||||
.#gpg.keygen.valid.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
.gpg.keygen.size.huge.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.name
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Enter the name of the key holder
|
||||
|
||||
.gpg.keygen.size.large.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.email
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
please enter an optional but highly suggested email address
|
||||
|
||||
.gpg.keygen.valid
|
||||
プロンプトで示された必要な値を入力してください。ISO形式の日付
|
||||
(YYYY-MM-DD)の入力が可能ですが、良いエラー対応が得られないかもしれませ
|
||||
ん。システムが与えられた値を期間と解釈することがあります。.
|
||||
.
|
||||
|
||||
.#gpg.keygen.comment
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Please enter an optional comment
|
||||
.gpg.keygen.valid.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keygen.userid.cmd
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
N to change the name.
|
||||
C to change the comment.
|
||||
E to change the email address.
|
||||
O to continue with key generation.
|
||||
Q to to quit the key generation.
|
||||
|
||||
.gpg.keygen.name
|
||||
鍵の持ち主の名前を入力してください。
|
||||
文字 "<" と ">" は許されていません。
|
||||
例: Heinrich Heine
|
||||
.
|
||||
|
||||
.#gpg.keygen.sub.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" (or just "y") if it is okay to generate the sub key.
|
||||
|
||||
.gpg.keygen.email
|
||||
オプションですが推奨される電子メールアドレスを入力してください。
|
||||
例: heinrichh@duesseldorf.de
|
||||
.
|
||||
|
||||
.#gpg.sign_uid.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
.gpg.keygen.comment
|
||||
オプションのコメントを入力してください。
|
||||
文字 "(" と ")" は許されていません。
|
||||
一般的にコメントは必要ではありません。
|
||||
.
|
||||
|
||||
.#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
|
||||
key.
|
||||
.gpg.keygen.userid.cmd
|
||||
# (Keep a leading empty line)
|
||||
|
||||
"1" means you believe the key is owned by the person who claims to own it
|
||||
but you could not, or did not verify the key at all. This is useful for
|
||||
a "persona" verification, where you sign the key of a pseudonymous user.
|
||||
|
||||
"2" means you did casual verification of the key. For example, this could
|
||||
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".
|
||||
N 名前の変更。
|
||||
C コメントの変更。
|
||||
E 電子メールアドレスの変更。
|
||||
O 鍵生成に進む。
|
||||
Q 鍵生成を止める。
|
||||
.
|
||||
|
||||
.#gpg.change_passwd.empty.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
.gpg.keygen.sub.okay
|
||||
副鍵を生成してよければ、"yes" (あるいは単に "y") と答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.save.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
.gpg.sign_uid.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.cancel.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" or "no"
|
||||
.gpg.sign_uid.class
|
||||
ある鍵のユーザIDに署名するとき、あなたは、まず、その鍵がそのユーザIDの
|
||||
人に属するかどうかを確認しなければなりません。あなたがどれくらいこれを
|
||||
慎重に確認したかについて、ほかの人が知ることは有用です。
|
||||
|
||||
"0" は、どれくらい慎重に確認したかについて特になにも主張しないことを意味します。
|
||||
|
||||
"1" は、あなたは、主張するその人が所有する鍵であると考えるが、その鍵について、
|
||||
確認できなかった、あるいはしなかったことを意味します。これは、ペンネームの
|
||||
ユーザの鍵に署名するような "persona" 確認に有用です。
|
||||
|
||||
"2" は、その鍵に対し、通常の検証を行ったことを意味します。たとえば、鍵
|
||||
のフィンガープリントを確認し、写真付きIDでユーザIDを確認したことを
|
||||
意味します。
|
||||
|
||||
"3" は、その鍵に対し、広範な検証を行ったことを意味します。たとえば、鍵
|
||||
のフィンガープリントを対面で確認し、パスポートなど偽造することが難
|
||||
しい写真付きIDでユーザIDを確認し、所有者の名前が鍵のユーザIDに適合
|
||||
し、メールの交換で、メールアドレスが所有者に属することを確認したこ
|
||||
とを意味します。
|
||||
|
||||
上記のレベル2とレベル3で示した例は、単に例であることに注意してください。
|
||||
結局は、ほかの鍵に署名するとき、なにがあなたにとって「通常」で、なにが
|
||||
「広範」かをを決めるのは、あなた自身に任されています。
|
||||
|
||||
正しい答えがなにかわからないときは "0" と答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.sign_all.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" if you want to sign ALL the user IDs
|
||||
.gpg.change_passwd.empty.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.remove.uid.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" if you really want to delete this user ID.
|
||||
All certificates are then also lost!
|
||||
|
||||
.gpg.keyedit.save.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.remove.subkey.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" if it is okay to delete the subkey
|
||||
|
||||
.gpg.keyedit.cancel.okay
|
||||
"yes" か "no" で答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.delsig.valid
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
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.sign_all.okay
|
||||
すべてのユーザIDに対して署名したい場合、"yes"と答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.delsig.unknown
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
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.remove.uid.okay
|
||||
このユーザIDを本当に削除したい場合、"yes"と答えてください。
|
||||
そうすると全部の証明書が失われます!
|
||||
.
|
||||
|
||||
.#gpg.keyedit.delsig.invalid
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
The signature is not valid. It does make sense to remove it from
|
||||
your keyring.
|
||||
.gpg.keyedit.remove.subkey.okay
|
||||
副鍵を削除してよい場合、"yes"と答えてください。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.delsig.selfsig
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
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.delsig.valid
|
||||
これは、この鍵の有効な署名です。通常、この署名を削除することは望まない
|
||||
でしょう。この鍵(または、この鍵で証明された別の鍵)への信頼のコネクショ
|
||||
ンが成立することが重要となる場合があるからです。
|
||||
.
|
||||
|
||||
.#gpg.keyedit.updpref.okay
|
||||
# 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.keyedit.delsig.unknown
|
||||
この署名は検証できませんでした。対応する鍵を持っていないからです。どの
|
||||
鍵が使われたかわかるまでこの削除を延期すべきです。この署名の鍵は、別の
|
||||
すでに証明された鍵を通じて信頼のコネクションを成立することがあるからで
|
||||
す。
|
||||
.
|
||||
|
||||
.#gpg.passphrase.enter
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Please enter the passhrase; this is a secret sentence
|
||||
|
||||
.gpg.keyedit.delsig.invalid
|
||||
この署名は有効ではありません。鍵リングから削除することに意味があります。
|
||||
.
|
||||
|
||||
.#gpg.passphrase.repeat
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Please repeat the last passphrase, so you are sure what you typed in.
|
||||
.gpg.keyedit.delsig.selfsig
|
||||
これはこのユーザIDとこの鍵とを結ぶ署名です。通常、このような署名を削除
|
||||
することは良いことではありません。実際、GnuPGはこの鍵を使うことができな
|
||||
くなってしまうかもしれません。ですから、この自己署名がなんらかの理由に
|
||||
よって無効であり、第二のものが利用可能である場合にだけ、実行してくださ
|
||||
い。
|
||||
.
|
||||
|
||||
.#gpg.detached_signature.filename
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Give the name of the file to which the signature applies
|
||||
.gpg.keyedit.updpref.okay
|
||||
すべてのユーザID(もしくは単に選択された一つ)の優先指定を現行の優先指定
|
||||
に変更します。すべての関係する自己署名のタイムスタンプは、一秒進んだも
|
||||
のとなります。
|
||||
.
|
||||
|
||||
.#gpg.openfile.overwrite.okay
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Answer "yes" if it is okay to overwrite the file
|
||||
.gpg.passphrase.enter
|
||||
# (keep a leading empty line)
|
||||
|
||||
パスフレーズを入力してください。秘密の文です。
|
||||
.
|
||||
|
||||
.#gpg.openfile.askoutname
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
Please enter a new filename. If you just hit RETURN the default
|
||||
file (which is shown in brackets) will be used.
|
||||
|
||||
.gpg.passphrase.repeat
|
||||
もう一度パスフレーズを入力し、間違いなく入力されたことを確認してください。
|
||||
.
|
||||
|
||||
.#gpg.ask_revocation_reason.code
|
||||
# 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.detached_signature.filename
|
||||
署名が適用されるファイルの名前を与えてください。
|
||||
.
|
||||
|
||||
.#gpg.ask_revocation_reason.text
|
||||
# fixme: Please translate and remove the hash mark from the key line.
|
||||
If you like, you can enter a text describing why you issue this
|
||||
revocation certificate. Please keep this text concise.
|
||||
An empty line ends the text.
|
||||
|
||||
.gpg.openfile.overwrite.okay
|
||||
# openfile.c (overwrite_filep)
|
||||
ファイルを上書きしてよければ、"yes"と答えてください。
|
||||
.
|
||||
|
||||
.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:
|
||||
|
@ -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
|
||||
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
|
||||
Even if a card reader features a keypad, do not try to use it.
|
||||
|
||||
@item --disable-pinpad
|
||||
@opindex disable-pinpad
|
||||
Even if a card reader features a pinpad, do not try to use it.
|
||||
|
||||
|
||||
@item --deny-admin
|
||||
|
294
g10/call-agent.c
294
g10/call-agent.c
@ -1,6 +1,6 @@
|
||||
/* call-agent.c - Divert GPG operations to the agent.
|
||||
* 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.
|
||||
*
|
||||
@ -40,47 +40,60 @@
|
||||
#include "sysutils.h"
|
||||
#include "call-agent.h"
|
||||
#include "status.h"
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
#ifndef DBG_ASSUAN
|
||||
# define DBG_ASSUAN 1
|
||||
#endif
|
||||
|
||||
#define CONTROL_D ('D' - 'A' + 1)
|
||||
|
||||
|
||||
static assuan_context_t agent_ctx = NULL;
|
||||
static int did_early_card_test;
|
||||
|
||||
struct cipher_parm_s
|
||||
struct default_inq_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
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;
|
||||
size_t ciphertextlen;
|
||||
};
|
||||
|
||||
struct writecert_parm_s
|
||||
{
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const unsigned char *certdata;
|
||||
size_t certdatalen;
|
||||
};
|
||||
|
||||
struct writekey_parm_s
|
||||
{
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const unsigned char *keydata;
|
||||
size_t keydatalen;
|
||||
};
|
||||
|
||||
struct genkey_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const char *keyparms;
|
||||
};
|
||||
|
||||
struct import_key_parm_s
|
||||
{
|
||||
ctrl_t ctrl;
|
||||
assuan_context_t ctx;
|
||||
struct default_inq_parm_s *dflt;
|
||||
const void *key;
|
||||
size_t keylen;
|
||||
};
|
||||
@ -161,6 +174,19 @@ start_agent (ctrl_t ctrl, int for_card)
|
||||
here used to indirectly enable GPG_ERR_FULLY_CANCELED. */
|
||||
assuan_transact (agent_ctx, "OPTION agent-awareness=2.1.0",
|
||||
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
|
||||
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]))
|
||||
{
|
||||
/* There is no working server mode yet thus we use
|
||||
AllowSetForegroundWindow window right here. We might want to
|
||||
do this anyway in case gpg is called on the console. */
|
||||
gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
|
||||
err = gpg_proxy_pinentry_notify (parm->ctrl, line);
|
||||
if (err)
|
||||
log_error (_("failed to proxy %s inquiry to client\n"),
|
||||
"PINENTRY_LAUNCHED");
|
||||
/* 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
|
||||
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)
|
||||
{
|
||||
int rc;
|
||||
struct default_inq_parm_s parm;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
@ -532,10 +587,10 @@ agent_learn (struct agent_card_info_s *info)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
||||
parm.ctx = agent_ctx;
|
||||
memset (info, 0, sizeof *info);
|
||||
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);
|
||||
/* Also try to get the key attributes. */
|
||||
if (!rc)
|
||||
@ -544,6 +599,30 @@ agent_learn (struct agent_card_info_s *info)
|
||||
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
|
||||
the data in the same structure as used by the learn command. It is
|
||||
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;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s parm;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
if (!*name)
|
||||
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)
|
||||
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);
|
||||
|
||||
return rc;
|
||||
@ -583,6 +666,9 @@ agent_scd_setattr (const char *name,
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
char *p;
|
||||
struct default_inq_parm_s parm;
|
||||
|
||||
memset (&parm, 0, sizeof parm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
@ -614,8 +700,9 @@ agent_scd_setattr (const char *name,
|
||||
rc = start_agent (NULL, 1);
|
||||
if (!rc)
|
||||
{
|
||||
parm.ctx = agent_ctx;
|
||||
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);
|
||||
@ -635,10 +722,11 @@ inq_writecert_parms (void *opaque, const char *line)
|
||||
|
||||
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
|
||||
rc = default_inq_cb (opaque, line);
|
||||
rc = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -652,6 +740,9 @@ agent_scd_writecert (const char *certidstr,
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct writecert_parm_s parms;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
@ -661,7 +752,8 @@ agent_scd_writecert (const char *certidstr,
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
|
||||
line[DIM(line)-1] = 0;
|
||||
parms.ctx = agent_ctx;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
parms.dflt = &dfltparm;
|
||||
parms.certdata = certdata;
|
||||
parms.certdatalen = certdatalen;
|
||||
|
||||
@ -683,10 +775,10 @@ inq_writekey_parms (void *opaque, const char *line)
|
||||
|
||||
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
|
||||
rc = default_inq_cb (opaque, line);
|
||||
rc = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -700,6 +792,9 @@ agent_scd_writekey (int keyno, const char *serialno,
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct writekey_parm_s parms;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
(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);
|
||||
line[DIM(line)-1] = 0;
|
||||
parms.ctx = agent_ctx;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
parms.dflt = &dfltparm;
|
||||
parms.keydata = keydata;
|
||||
parms.keydatalen = keydatalen;
|
||||
|
||||
@ -836,6 +932,9 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
gnupg_isotime_t tbuf;
|
||||
struct scd_genkey_parm_s parms;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
@ -857,9 +956,10 @@ agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
|
||||
keyno);
|
||||
line[DIM(line)-1] = 0;
|
||||
|
||||
dfltparm.ctx = agent_ctx;
|
||||
memset (info, 0, sizeof *info);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL, default_inq_cb, NULL,
|
||||
NULL, NULL, default_inq_cb, &dfltparm,
|
||||
scd_genkey_cb, &parms);
|
||||
|
||||
xfree (parms.savedbytes);
|
||||
@ -985,19 +1085,25 @@ agent_scd_readcert (const char *certidstr,
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
membuf_t data;
|
||||
size_t len;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
*r_buf = NULL;
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
init_membuf (&data, 2048);
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (rc)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
@ -1028,6 +1134,9 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
const char *reset = "";
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
(void)serialno;
|
||||
|
||||
@ -1038,11 +1147,14 @@ agent_scd_change_pin (int chvno, const char *serialno)
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD PASSWD %s %d", reset, chvno);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
status_sc_op_failure (rc);
|
||||
return rc;
|
||||
}
|
||||
@ -1056,16 +1168,21 @@ agent_scd_checkpin (const char *serialno)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
rc = start_agent (NULL, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD CHECKPIN %s", serialno);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
status_sc_op_failure (rc);
|
||||
return rc;
|
||||
}
|
||||
@ -1101,12 +1218,16 @@ agent_get_passphrase (const char *cache_id,
|
||||
char *arg3 = NULL;
|
||||
char *arg4 = NULL;
|
||||
membuf_t data;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
*r_passphrase = NULL;
|
||||
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
/* Check that the gpg-agent understands the repeat option. */
|
||||
if (assuan_transact (agent_ctx,
|
||||
@ -1144,7 +1265,8 @@ agent_get_passphrase (const char *cache_id,
|
||||
init_membuf_secure (&data, 64);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
|
||||
if (rc)
|
||||
xfree (get_membuf (&data, NULL));
|
||||
@ -1171,6 +1293,9 @@ agent_clear_passphrase (const char *cache_id)
|
||||
{
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
if (!cache_id || !*cache_id)
|
||||
return 0;
|
||||
@ -1178,11 +1303,14 @@ agent_clear_passphrase (const char *cache_id)
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "CLEAR_PASSPHRASE %s", cache_id);
|
||||
line[DIM(line)-1] = 0;
|
||||
return assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
return assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -1194,10 +1322,14 @@ gpg_agent_get_confirmation (const char *desc)
|
||||
int rc;
|
||||
char *tmp;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
|
||||
rc = start_agent (NULL, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
tmp = percent_plus_escape (desc);
|
||||
if (!tmp)
|
||||
@ -1206,8 +1338,10 @@ gpg_agent_get_confirmation (const char *desc)
|
||||
line[DIM(line)-1] = 0;
|
||||
xfree (tmp);
|
||||
|
||||
rc = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
rc = assuan_transact (agent_ctx, line,
|
||||
NULL, NULL,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1438,11 +1572,11 @@ inq_genkey_parms (void *opaque, const char *line)
|
||||
|
||||
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));
|
||||
}
|
||||
else
|
||||
err = default_inq_cb (parm->ctrl, line);
|
||||
err = default_inq_cb (parm->dflt, line);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -1459,15 +1593,20 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
|
||||
gpg_error_t err;
|
||||
struct genkey_parm_s gk_parm;
|
||||
struct cache_nonce_parm_s cn_parm;
|
||||
struct default_inq_parm_s dfltparm;
|
||||
membuf_t data;
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_pubkey = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
err = assuan_transact (agent_ctx, "RESET",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
@ -1475,8 +1614,7 @@ agent_genkey (ctrl_t ctrl, char **cache_nonce_addr,
|
||||
return err;
|
||||
|
||||
init_membuf (&data, 1024);
|
||||
gk_parm.ctrl = ctrl;
|
||||
gk_parm.ctx = agent_ctx;
|
||||
gk_parm.dflt = &dfltparm;
|
||||
gk_parm.keyparms = keyparms;
|
||||
snprintf (line, sizeof line, "GENKEY%s%s%s",
|
||||
no_protection? " --no-protection":"",
|
||||
@ -1520,11 +1658,16 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_pubkey = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
err = assuan_transact (agent_ctx, "RESET",NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if (err)
|
||||
@ -1535,7 +1678,8 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||
init_membuf (&data, 1024);
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, NULL, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
xfree (get_membuf (&data, &len));
|
||||
@ -1564,17 +1708,26 @@ agent_readkey (ctrl_t ctrl, int fromcard, const char *hexkeygrip,
|
||||
gpg_error_t
|
||||
agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
||||
const char *keygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
unsigned char *digest, size_t digestlen, int digestalgo,
|
||||
gcry_sexp_t *r_sigval)
|
||||
{
|
||||
gpg_error_t err;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
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;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (digestlen*2 + 50 > DIM(line))
|
||||
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:"");
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data, default_inq_cb, ctrl,
|
||||
NULL, NULL);
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
xfree (get_membuf (&data, NULL));
|
||||
else
|
||||
@ -1646,11 +1800,12 @@ inq_ciphertext_cb (void *opaque, const char *line)
|
||||
if (!strncmp (line, "CIPHERTEXT", 10) && (line[10]==' '||!line[10]))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
rc = default_inq_cb (parm->ctrl, line);
|
||||
rc = default_inq_cb (parm->dflt, line);
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
gcry_sexp_t s_ciphertext,
|
||||
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;
|
||||
size_t n, len;
|
||||
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)
|
||||
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);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
err = assuan_transact (agent_ctx, "RESET",
|
||||
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;
|
||||
|
||||
parm.ctrl = ctrl;
|
||||
parm.dflt = &dfltparm;
|
||||
parm.ctx = agent_ctx;
|
||||
err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen);
|
||||
if (err)
|
||||
@ -1772,11 +1938,16 @@ agent_keywrap_key (ctrl_t ctrl, int forexport, void **r_kek, size_t *r_keklen)
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_kek = NULL;
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
snprintf (line, DIM(line)-1, "KEYWRAP_KEY %s",
|
||||
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);
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, ctrl, NULL, NULL);
|
||||
default_inq_cb, &dfltparm,
|
||||
NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
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]))
|
||||
{
|
||||
err = assuan_send_data (parm->ctx, parm->key, parm->keylen);
|
||||
err = assuan_send_data (parm->dflt->ctx, parm->key, parm->keylen);
|
||||
}
|
||||
else
|
||||
err = default_inq_cb (parm->ctrl, line);
|
||||
err = default_inq_cb (parm->dflt, line);
|
||||
|
||||
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 cache_nonce_parm_s cn_parm;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (desc)
|
||||
{
|
||||
@ -1842,8 +2019,7 @@ agent_import_key (ctrl_t ctrl, const char *desc, char **cache_nonce_addr,
|
||||
return err;
|
||||
}
|
||||
|
||||
parm.ctrl = ctrl;
|
||||
parm.ctx = agent_ctx;
|
||||
parm.dflt = &dfltparm;
|
||||
parm.key = key;
|
||||
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.passwd_nonce_addr = NULL;
|
||||
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);
|
||||
return err;
|
||||
}
|
||||
@ -1875,12 +2052,17 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
*r_result = NULL;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (desc)
|
||||
{
|
||||
@ -1901,7 +2083,7 @@ agent_export_key (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
cn_parm.passwd_nonce_addr = NULL;
|
||||
err = assuan_transact (agent_ctx, line,
|
||||
membuf_data_cb, &data,
|
||||
default_inq_cb, ctrl,
|
||||
default_inq_cb, &dfltparm,
|
||||
cache_nonce_status_cb, &cn_parm);
|
||||
if (err)
|
||||
{
|
||||
@ -1931,14 +2113,20 @@ agent_passwd (ctrl_t ctrl, const char *hexkeygrip, const char *desc,
|
||||
gpg_error_t err;
|
||||
struct cache_nonce_parm_s cn_parm;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
struct default_inq_parm_s dfltparm;
|
||||
|
||||
memset (&dfltparm, 0, sizeof dfltparm);
|
||||
dfltparm.ctrl = ctrl;
|
||||
|
||||
err = start_agent (ctrl, 0);
|
||||
if (err)
|
||||
return err;
|
||||
dfltparm.ctx = agent_ctx;
|
||||
|
||||
if (!hexkeygrip || strlen (hexkeygrip) != 40)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
|
||||
if (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.passwd_nonce_addr = passwd_nonce_addr;
|
||||
err = assuan_transact (agent_ctx, line, NULL, NULL,
|
||||
default_inq_cb, ctrl,
|
||||
default_inq_cb, &dfltparm,
|
||||
cache_nonce_status_cb, &cn_parm);
|
||||
return err;
|
||||
}
|
||||
|
@ -81,6 +81,10 @@ int agent_learn (struct agent_card_info_s *info);
|
||||
/* Update INFO with the attribute NAME. */
|
||||
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. */
|
||||
int agent_scd_setattr (const char *name,
|
||||
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. */
|
||||
gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce,
|
||||
const char *hexkeygrip, const char *desc,
|
||||
u32 *keyid, u32 *mainkeyid, int pubkey_algo,
|
||||
unsigned char *digest, size_t digestlen,
|
||||
int digestalgo,
|
||||
gcry_sexp_t *r_sigval);
|
||||
|
||||
/* Decrypt a ciphertext. */
|
||||
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,
|
||||
unsigned char **r_buf, size_t *r_buflen);
|
||||
|
||||
|
212
g10/card-util.c
212
g10/card-util.c
@ -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",
|
||||
_("Replace existing key? (y/N) ")))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1484,7 +1485,7 @@ card_generate_subkey (KBNODE pub_keyblock)
|
||||
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);
|
||||
goto leave;
|
||||
@ -1531,152 +1532,99 @@ card_generate_subkey (KBNODE pub_keyblock)
|
||||
int
|
||||
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; */
|
||||
/* int okay = 0; */
|
||||
/* int rc; */
|
||||
/* int keyno, i; */
|
||||
/* PKT_secret_key *copied_sk = NULL; */
|
||||
/* PKT_secret_key *sk; */
|
||||
/* size_t n; */
|
||||
/* const char *s; */
|
||||
/* int allow_keyno[3]; */
|
||||
/* unsigned int nbits; */
|
||||
struct agent_card_info_s info;
|
||||
int okay = 0;
|
||||
unsigned int nbits;
|
||||
int allow_keyno[3];
|
||||
int keyno;
|
||||
PKT_public_key *pk;
|
||||
gpg_error_t err;
|
||||
char *hexgrip;
|
||||
int rc;
|
||||
gnupg_isotime_t timebuf;
|
||||
|
||||
assert (node->pkt->pkttype == PKT_PUBLIC_KEY
|
||||
|| node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
|
||||
|
||||
/* assert (node->pkt->pkttype == PKT_SECRET_KEY */
|
||||
/* || node->pkt->pkttype == PKT_SECRET_SUBKEY); */
|
||||
/* sk = node->pkt->pkt.secret_key; */
|
||||
pk = node->pkt->pkt.public_key;
|
||||
|
||||
/* if (get_info_for_key_operation (&info)) */
|
||||
/* return 0; */
|
||||
if (get_info_for_key_operation (&info))
|
||||
return 0;
|
||||
|
||||
/* if (!info.extcap.ki) */
|
||||
/* { */
|
||||
/* tty_printf ("The card does not support the import of keys\n"); */
|
||||
/* tty_printf ("\n"); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
if (!info.extcap.ki)
|
||||
{
|
||||
tty_printf ("The card does not support the import of keys\n");
|
||||
tty_printf ("\n");
|
||||
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) ) */
|
||||
/* { */
|
||||
/* tty_printf ("You may only store a 1024 bit RSA key on the card\n"); */
|
||||
/* tty_printf ("\n"); */
|
||||
/* goto leave; */
|
||||
/* } */
|
||||
allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG)));
|
||||
allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
|
||||
allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
|
||||
|
||||
/* allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG))); */
|
||||
/* 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"));
|
||||
|
||||
/* 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]) */
|
||||
/* 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")); */
|
||||
for (;;)
|
||||
{
|
||||
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"));
|
||||
}
|
||||
|
||||
/* for (;;) */
|
||||
/* { */
|
||||
/* 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 ((rc = replace_existing_key_p (&info, keyno)) < 0)
|
||||
goto leave;
|
||||
|
||||
/* if (replace_existing_key_p (&info, keyno)) */
|
||||
/* goto leave; */
|
||||
err = hexkeygrip_from_pk (pk, &hexgrip);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* /\* Unprotect key. *\/ */
|
||||
/* switch (is_secret_key_protected (sk) ) */
|
||||
/* { */
|
||||
/* 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; */
|
||||
/* } */
|
||||
epoch2isotime (timebuf, (time_t)pk->timestamp);
|
||||
agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
|
||||
|
||||
/* #warning code save_unprotected_key_to_card */
|
||||
/* /\* rc = save_unprotected_key_to_card (sk, keyno); *\/ */
|
||||
/* /\* if (rc) *\/ */
|
||||
/* /\* { *\/ */
|
||||
/* /\* log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); *\/ */
|
||||
/* /\* goto leave; *\/ */
|
||||
/* /\* } *\/ */
|
||||
if (rc)
|
||||
log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
|
||||
else
|
||||
okay = 1;
|
||||
xfree (hexgrip);
|
||||
|
||||
/* /\* Get back to the maybe protected original secret key. *\/ */
|
||||
/* if (copied_sk) */
|
||||
/* { */
|
||||
/* 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;
|
||||
leave:
|
||||
agent_release_card_info (&info);
|
||||
return okay;
|
||||
}
|
||||
|
||||
|
||||
|
14
g10/gpg.c
14
g10/gpg.c
@ -56,6 +56,7 @@
|
||||
#include "asshelp.h"
|
||||
#include "call-dirmngr.h"
|
||||
#include "../common/init.h"
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
|
||||
#define MY_O_BINARY O_BINARY
|
||||
@ -217,6 +218,7 @@ enum cmd_and_opt_values
|
||||
oPassphraseFD,
|
||||
oPassphraseFile,
|
||||
oPassphraseRepeat,
|
||||
oPinentryMode,
|
||||
oCommandFD,
|
||||
oCommandFile,
|
||||
oQuickRandom,
|
||||
@ -611,6 +613,7 @@ static ARGPARSE_OPTS opts[] = {
|
||||
ARGPARSE_s_i (oPassphraseFD, "passphrase-fd", "@"),
|
||||
ARGPARSE_s_s (oPassphraseFile, "passphrase-file", "@"),
|
||||
ARGPARSE_s_i (oPassphraseRepeat,"passphrase-repeat", "@"),
|
||||
ARGPARSE_s_s (oPinentryMode, "pinentry-mode", "@"),
|
||||
ARGPARSE_s_i (oCommandFD, "command-fd", "@"),
|
||||
ARGPARSE_s_s (oCommandFile, "command-file", "@"),
|
||||
ARGPARSE_s_n (oQuickRandom, "debug-quick-random", "@"),
|
||||
@ -2594,7 +2597,16 @@ main (int argc, char **argv)
|
||||
case oPassphraseFile:
|
||||
pwfd = open_info_file (pargs.r.ret_str, 0, 1);
|
||||
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:
|
||||
opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
|
||||
break;
|
||||
|
@ -181,6 +181,7 @@ unsigned char encode_s2k_iterations (int iterations);
|
||||
assuan_context_t agent_open (int try, const char *orig_codeset);
|
||||
void agent_close (assuan_context_t ctx);
|
||||
int have_static_passphrase(void);
|
||||
const char *get_static_passphrase (void);
|
||||
void set_passphrase_from_string(const char *pass);
|
||||
void read_passphrase_from_fd( int fd );
|
||||
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);
|
||||
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);
|
||||
|
||||
|
||||
|
@ -353,6 +353,8 @@ void unblock_all_signals(void);
|
||||
|
||||
/*-- server.c --*/
|
||||
int gpg_server (ctrl_t);
|
||||
gpg_error_t gpg_proxy_pinentry_notify (ctrl_t ctrl,
|
||||
const unsigned char *line);
|
||||
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
/*-- card-util.c --*/
|
||||
|
@ -242,6 +242,7 @@ struct
|
||||
} *auto_key_locate;
|
||||
|
||||
int passphrase_repeat;
|
||||
int pinentry_mode;
|
||||
} opt;
|
||||
|
||||
/* CTRL is used to keep some global variables we currently can't
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include "i18n.h"
|
||||
#include "status.h"
|
||||
#include "call-agent.h"
|
||||
|
||||
#include "../common/shareddefs.h"
|
||||
|
||||
static char *fd_passwd = NULL;
|
||||
static char *next_pw = NULL;
|
||||
@ -104,9 +104,21 @@ encode_s2k_iterations (int iterations)
|
||||
int
|
||||
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
|
||||
* one.
|
||||
@ -156,7 +168,7 @@ read_passphrase_from_fd( int fd )
|
||||
int i, len;
|
||||
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
|
||||
up at the begin of the message if the quite usual trick to
|
||||
prepend the passphtrase to the message is used. */
|
||||
@ -187,7 +199,7 @@ read_passphrase_from_fd( int fd )
|
||||
break;
|
||||
}
|
||||
pw[i] = 0;
|
||||
if (!opt.batch)
|
||||
if (!opt.batch && opt.pinentry_mode != PINENTRY_MODE_LOOPBACK)
|
||||
tty_printf("\b\b\b \n" );
|
||||
|
||||
xfree ( fd_passwd );
|
||||
@ -458,30 +470,9 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo,
|
||||
|
||||
if ( keyid )
|
||||
{
|
||||
u32 used_kid[2];
|
||||
char *us;
|
||||
|
||||
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 );
|
||||
emit_status_need_passphrase (keyid,
|
||||
keyid[2] && keyid[3]? keyid+2:NULL,
|
||||
pubkey_algo);
|
||||
}
|
||||
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
|
||||
is true spaces and control characters are percent or plus escaped.
|
||||
MODE 0 is for the common prompt, MODE 1 for the import prompt. */
|
||||
|
@ -201,7 +201,9 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
|
||||
|
||||
/* Decrypt. */
|
||||
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);
|
||||
gcry_sexp_release (s_data);
|
||||
if (err)
|
||||
|
36
g10/server.c
36
g10/server.c
@ -50,6 +50,9 @@ struct server_local_s
|
||||
/* List of prepared recipients. */
|
||||
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
|
||||
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;
|
||||
|
||||
/* 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. */
|
||||
}
|
||||
else if (!strcmp (key, "allow-pinentry-notify"))
|
||||
{
|
||||
ctrl->server_local->allow_pinentry_notify = 1;
|
||||
}
|
||||
else
|
||||
return gpg_error (GPG_ERR_UNKNOWN_OPTION);
|
||||
|
||||
@ -768,3 +774,29 @@ gpg_server (ctrl_t ctrl)
|
||||
assuan_release (ctx);
|
||||
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);
|
||||
}
|
||||
|
@ -272,6 +272,7 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig,
|
||||
|
||||
desc = gpg_format_keydesc (pksk, 0, 1);
|
||||
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,
|
||||
&s_sigval);
|
||||
xfree (desc);
|
||||
@ -1604,6 +1605,8 @@ update_keysig_packet( PKT_signature **ret_sig,
|
||||
/* create a new signature packet */
|
||||
sig = copy_signature (NULL, orig_sig);
|
||||
|
||||
sig->digest_algo=digest_algo;
|
||||
|
||||
/* We need to create a new timestamp so that new sig expiration
|
||||
calculations are done correctly... */
|
||||
sig->timestamp=make_timestamp();
|
||||
|
230
scd/apdu.c
230
scd/apdu.c
@ -60,10 +60,9 @@
|
||||
#include "exechelp.h"
|
||||
#endif /* GNUPG_MAJOR_VERSION != 1 */
|
||||
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h"
|
||||
#include "ccid-driver.h"
|
||||
#include "iso7816.h"
|
||||
|
||||
|
||||
/* Due to conflicting use of threading libraries we usually can't link
|
||||
against libpcsclite. Instead we use a wrapper program. */
|
||||
@ -83,16 +82,6 @@
|
||||
#define DLSTDCALL
|
||||
#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
|
||||
slot. */
|
||||
struct reader_table_s {
|
||||
@ -107,12 +96,12 @@ struct reader_table_s {
|
||||
int (*reset_reader)(int);
|
||||
int (*get_status_reader)(int, unsigned int *);
|
||||
int (*send_apdu_reader)(int,unsigned char *,size_t,
|
||||
unsigned char *, size_t *, struct pininfo_s *);
|
||||
int (*check_keypad)(int, int, int, int, int, int);
|
||||
unsigned char *, size_t *, pininfo_t *);
|
||||
int (*check_pinpad)(int, int, pininfo_t *);
|
||||
void (*dump_status_reader)(int);
|
||||
int (*set_progress_cb)(int, gcry_handler_progress_t, void*);
|
||||
int (*keypad_verify)(int, int, int, int, int, struct pininfo_s *);
|
||||
int (*keypad_modify)(int, int, int, int, int, struct pininfo_s *);
|
||||
int (*pinpad_verify)(int, int, int, int, int, pininfo_t *);
|
||||
int (*pinpad_modify)(int, int, int, int, int, pininfo_t *);
|
||||
|
||||
struct {
|
||||
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,
|
||||
unsigned int *status,
|
||||
unsigned int *changed);
|
||||
static int check_pcsc_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen);
|
||||
static int pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
struct pininfo_s *pininfo);
|
||||
static int pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
|
||||
struct pininfo_s *pininfo);
|
||||
static int check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo);
|
||||
static int pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo);
|
||||
static int pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo);
|
||||
|
||||
|
||||
|
||||
@ -381,11 +369,11 @@ new_reader_slot (void)
|
||||
reader_table[reader].reset_reader = NULL;
|
||||
reader_table[reader].get_status_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].set_progress_cb = NULL;
|
||||
reader_table[reader].keypad_verify = pcsc_keypad_verify;
|
||||
reader_table[reader].keypad_modify = pcsc_keypad_modify;
|
||||
reader_table[reader].pinpad_verify = pcsc_pinpad_verify;
|
||||
reader_table[reader].pinpad_modify = pcsc_pinpad_modify;
|
||||
|
||||
reader_table[reader].used = 1;
|
||||
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_NO_READER: return "no reader";
|
||||
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";
|
||||
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. */
|
||||
static int
|
||||
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;
|
||||
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].get_status_reader = ct_get_status;
|
||||
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].keypad_verify = NULL;
|
||||
reader_table[reader].keypad_modify = NULL;
|
||||
reader_table[reader].pinpad_verify = NULL;
|
||||
reader_table[reader].pinpad_modify = NULL;
|
||||
|
||||
dump_reader_status (reader);
|
||||
return reader;
|
||||
@ -1039,7 +1027,7 @@ pcsc_get_status (int slot, unsigned int *status)
|
||||
static int
|
||||
pcsc_send_apdu_direct (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
long err;
|
||||
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
|
||||
pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
long err;
|
||||
reader_table_t slotp;
|
||||
@ -1195,7 +1183,7 @@ pcsc_send_apdu_wrapped (int slot, unsigned char *apdu, size_t apdulen,
|
||||
static int
|
||||
pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
#ifdef NEED_PCSC_WRAPPER
|
||||
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
|
||||
on the keypad. Return 0 on success. */
|
||||
on the pinpad. Return 0 on success. */
|
||||
static int
|
||||
check_pcsc_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
check_pcsc_pinpad (int slot, int command, pininfo_t *pininfo)
|
||||
{
|
||||
unsigned char buf[256];
|
||||
size_t len = 256;
|
||||
int sw;
|
||||
|
||||
(void)pin_mode;
|
||||
(void)pinlen_min;
|
||||
(void)pinlen_max;
|
||||
(void)pin_padlen;
|
||||
(void)pininfo; /* XXX: Identify reader and set pininfo->fixedlen. */
|
||||
|
||||
check_again:
|
||||
if (command == ISO7816_VERIFY)
|
||||
@ -2053,12 +2037,12 @@ check_pcsc_keypad (int slot, int command, int pin_mode,
|
||||
|
||||
#define PIN_VERIFY_STRUCTURE_SIZE 24
|
||||
static int
|
||||
pcsc_keypad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
struct pininfo_s *pininfo)
|
||||
pcsc_pinpad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
unsigned char *pin_verify;
|
||||
int len = PIN_VERIFY_STRUCTURE_SIZE;
|
||||
int len = PIN_VERIFY_STRUCTURE_SIZE + pininfo->fixedlen;
|
||||
unsigned char result[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)))
|
||||
return sw;
|
||||
|
||||
if (pininfo->mode != 1)
|
||||
return SW_NOT_SUPPORTED;
|
||||
|
||||
if (pininfo->padlen != 0)
|
||||
if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
|
||||
return SW_NOT_SUPPORTED;
|
||||
|
||||
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[1] = 0x00; /* bTimerOut2 */
|
||||
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[5] = pininfo->maxlen; /* 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[12] = 0x00; /* bTeoPrologue[0] */
|
||||
pin_verify[13] = 0x00; /* bTeoPrologue[1] */
|
||||
pin_verify[14] = 0x00; /* bTeoPrologue[2] */
|
||||
pin_verify[15] = 0x05; /* ulDataLength */
|
||||
pin_verify[14] = pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
|
||||
pin_verify[15] = pininfo->fixedlen + 0x05; /* ulDataLength */
|
||||
pin_verify[16] = 0x00; /* ulDataLength */
|
||||
pin_verify[17] = 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[21] = p0; /* abData[2] */
|
||||
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)
|
||||
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
|
||||
static int
|
||||
pcsc_keypad_modify (int slot, int class, int ins, int p0, int p1,
|
||||
struct pininfo_s *pininfo)
|
||||
pcsc_pinpad_modify (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
unsigned char *pin_modify;
|
||||
int len = PIN_MODIFY_STRUCTURE_SIZE;
|
||||
int len = PIN_MODIFY_STRUCTURE_SIZE + 2 * pininfo->fixedlen;
|
||||
unsigned char result[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)))
|
||||
return sw;
|
||||
|
||||
if (pininfo->mode != 1)
|
||||
return SW_NOT_SUPPORTED;
|
||||
|
||||
if (pininfo->padlen != 0)
|
||||
if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
|
||||
return SW_NOT_SUPPORTED;
|
||||
|
||||
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[1] = 0x00; /* bTimerOut2 */
|
||||
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[5] = 0x00; /* bInsertionOffsetOld */
|
||||
pin_modify[6] = 0x00; /* bInsertionOffsetNew */
|
||||
pin_modify[6] = pininfo->fixedlen; /* bInsertionOffsetNew */
|
||||
pin_modify[7] = pininfo->maxlen; /* wPINMaxExtraDigit */
|
||||
pin_modify[8] = pininfo->minlen; /* wPINMaxExtraDigit */
|
||||
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[17] = 0x00; /* bTeoPrologue[0] */
|
||||
pin_modify[18] = 0x00; /* bTeoPrologue[1] */
|
||||
pin_modify[19] = 0x00; /* bTeoPrologue[2] */
|
||||
pin_modify[20] = 0x05; /* ulDataLength */
|
||||
pin_modify[19] = 2 * pininfo->fixedlen + 0x05; /* bTeoPrologue[2] */
|
||||
pin_modify[20] = 2 * pininfo->fixedlen + 0x05; /* ulDataLength */
|
||||
pin_modify[21] = 0x00; /* ulDataLength */
|
||||
pin_modify[22] = 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[26] = p0; /* abData[2] */
|
||||
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)
|
||||
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
|
||||
send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
long err;
|
||||
size_t maxbuflen;
|
||||
@ -2328,11 +2310,7 @@ send_apdu_ccid (int slot, unsigned char *apdu, size_t apdulen,
|
||||
maxbuflen = *buflen;
|
||||
if (pininfo)
|
||||
err = ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, apdulen,
|
||||
pininfo->mode,
|
||||
pininfo->minlen,
|
||||
pininfo->maxlen,
|
||||
pininfo->padlen,
|
||||
apdu, apdulen, pininfo,
|
||||
buffer, maxbuflen, buflen);
|
||||
else
|
||||
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
|
||||
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 */
|
||||
static int
|
||||
check_ccid_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
check_ccid_pinpad (int slot, int command, pininfo_t *pininfo)
|
||||
{
|
||||
unsigned char apdu[] = { 0, 0, 0, 0x81 };
|
||||
|
||||
apdu[1] = command;
|
||||
return ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, sizeof apdu,
|
||||
pin_mode, pinlen_min, pinlen_max, pin_padlen,
|
||||
NULL, 0, NULL);
|
||||
return ccid_transceive_secure (reader_table[slot].ccid.handle, apdu,
|
||||
sizeof apdu, pininfo, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
|
||||
struct pininfo_s *pininfo)
|
||||
ccid_pinpad_operation (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
unsigned char apdu[4];
|
||||
int err, sw;
|
||||
@ -2377,9 +2352,7 @@ ccid_keypad_operation (int slot, int class, int ins, int p0, int p1,
|
||||
apdu[2] = p0;
|
||||
apdu[3] = p1;
|
||||
err = ccid_transceive_secure (reader_table[slot].ccid.handle,
|
||||
apdu, sizeof apdu,
|
||||
pininfo->mode, pininfo->minlen, pininfo->maxlen,
|
||||
pininfo->padlen,
|
||||
apdu, sizeof apdu, pininfo,
|
||||
result, 2, &resultlen);
|
||||
if (err)
|
||||
return err;
|
||||
@ -2433,11 +2406,11 @@ open_ccid_reader (const char *portstr)
|
||||
reader_table[slot].reset_reader = reset_ccid_reader;
|
||||
reader_table[slot].get_status_reader = get_status_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].set_progress_cb = set_progress_cb_ccid_reader;
|
||||
reader_table[slot].keypad_verify = ccid_keypad_operation;
|
||||
reader_table[slot].keypad_modify = ccid_keypad_operation;
|
||||
reader_table[slot].pinpad_verify = ccid_pinpad_operation;
|
||||
reader_table[slot].pinpad_modify = ccid_pinpad_operation;
|
||||
/* Our CCID reader code does not support T=0 at all, thus reset the
|
||||
flag. */
|
||||
reader_table[slot].is_t0 = 0;
|
||||
@ -2597,7 +2570,7 @@ my_rapdu_get_status (int slot, unsigned int *status)
|
||||
static int
|
||||
my_rapdu_send_apdu (int slot, unsigned char *apdu, size_t apdulen,
|
||||
unsigned char *buffer, size_t *buflen,
|
||||
struct pininfo_s *pininfo)
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
int err;
|
||||
reader_table_t slotp;
|
||||
@ -2728,10 +2701,10 @@ open_rapdu_reader (int portno,
|
||||
reader_table[slot].reset_reader = reset_rapdu_reader;
|
||||
reader_table[slot].get_status_reader = my_rapdu_get_status;
|
||||
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].keypad_verify = NULL;
|
||||
reader_table[slot].keypad_modify = NULL;
|
||||
reader_table[slot].pinpad_verify = NULL;
|
||||
reader_table[slot].pinpad_modify = NULL;
|
||||
|
||||
dump_reader_status (slot);
|
||||
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
|
||||
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 */
|
||||
int
|
||||
apdu_check_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
apdu_check_pinpad (int slot, int command, pininfo_t *pininfo)
|
||||
{
|
||||
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
|
||||
if (reader_table[slot].check_keypad)
|
||||
return reader_table[slot].check_keypad (slot, command,
|
||||
pin_mode, pinlen_min, pinlen_max,
|
||||
pin_padlen);
|
||||
if (opt.enable_pinpad_varlen)
|
||||
pininfo->fixedlen = 0;
|
||||
|
||||
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
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
apdu_keypad_verify (int slot, int class, int ins, int p0, int p1, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen)
|
||||
apdu_pinpad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
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 )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
|
||||
if (reader_table[slot].keypad_verify)
|
||||
return reader_table[slot].keypad_verify (slot, class, ins, p0, p1,
|
||||
&pininfo);
|
||||
if (reader_table[slot].pinpad_verify)
|
||||
{
|
||||
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
|
||||
return SW_HOST_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
apdu_pinpad_modify (int slot, int class, int ins, int p0, int p1,
|
||||
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 )
|
||||
return SW_HOST_NO_DRIVER;
|
||||
|
||||
if (reader_table[slot].keypad_modify)
|
||||
return reader_table[slot].keypad_modify (slot, class, ins, p0, p1,
|
||||
&pininfo);
|
||||
if (reader_table[slot].pinpad_modify)
|
||||
{
|
||||
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
|
||||
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. */
|
||||
static int
|
||||
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 )
|
||||
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
|
||||
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
|
||||
command chaining or extended length will be used according to these
|
||||
values:
|
||||
@ -3517,7 +3503,7 @@ static int
|
||||
send_le (int slot, int class, int ins, int p0, int p1,
|
||||
int lc, const char *data, int le,
|
||||
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
|
||||
/* We allocate 8 extra bytes as a safety margin towards a driver bug. */
|
||||
|
15
scd/apdu.h
15
scd/apdu.h
@ -69,7 +69,7 @@ enum {
|
||||
SW_HOST_GENERAL_ERROR = 0x1000b,
|
||||
SW_HOST_NO_READER = 0x1000c,
|
||||
SW_HOST_ABORTED = 0x1000d,
|
||||
SW_HOST_NO_KEYPAD = 0x1000e,
|
||||
SW_HOST_NO_PINPAD = 0x1000e,
|
||||
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_get_status (int slot, int hang,
|
||||
unsigned int *status, unsigned int *changed);
|
||||
int apdu_check_keypad (int slot, int command, int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen);
|
||||
int apdu_keypad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
int pin_mode, int pinlen_min, int pinlen_max,
|
||||
int pin_padlen);
|
||||
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_check_pinpad (int slot, int command, pininfo_t *pininfo);
|
||||
int apdu_pinpad_verify (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo);
|
||||
int apdu_pinpad_modify (int slot, int class, int ins, int p0, int p1,
|
||||
pininfo_t *pininfo);
|
||||
int apdu_send_simple (int slot, int extended_mode,
|
||||
int class, int ins, int p0, int p1,
|
||||
int lc, const char *data);
|
||||
|
@ -282,21 +282,21 @@ verify_pin (app_t app,
|
||||
{
|
||||
const char *s;
|
||||
int rc;
|
||||
iso7816_pininfo_t pininfo;
|
||||
pininfo_t pininfo;
|
||||
|
||||
if ( app->did_chv1 && !app->force_chv1 )
|
||||
return 0; /* No need to verify it again. */
|
||||
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.fixedlen = -1;
|
||||
pininfo.minlen = 6;
|
||||
pininfo.maxlen = 8;
|
||||
|
||||
if (!opt.disable_keypad
|
||||
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
|
||||
if (!opt.disable_pinpad
|
||||
&& !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
|
||||
{
|
||||
rc = pincb (pincb_arg,
|
||||
_("||Please enter your PIN at the reader's keypad"),
|
||||
_("||Please enter your PIN at the reader's pinpad"),
|
||||
NULL);
|
||||
if (rc)
|
||||
{
|
||||
@ -308,7 +308,7 @@ verify_pin (app_t app,
|
||||
/* Dismiss the prompt. */
|
||||
pincb (pincb_arg, NULL, NULL);
|
||||
}
|
||||
else /* No Keypad. */
|
||||
else /* No Pinpad. */
|
||||
{
|
||||
char *pinvalue;
|
||||
|
||||
|
@ -781,19 +781,19 @@ verify_pin (app_t app, int pwid, const char *desc,
|
||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||
void *pincb_arg)
|
||||
{
|
||||
iso7816_pininfo_t pininfo;
|
||||
pininfo_t pininfo;
|
||||
int rc;
|
||||
|
||||
if (!desc)
|
||||
desc = "PIN";
|
||||
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.fixedlen = -1;
|
||||
pininfo.minlen = 6;
|
||||
pininfo.maxlen = 16;
|
||||
|
||||
if (!opt.disable_keypad
|
||||
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
|
||||
if (!opt.disable_pinpad
|
||||
&& !iso7816_check_pinpad (app->slot, ISO7816_VERIFY, &pininfo) )
|
||||
{
|
||||
rc = pincb (pincb_arg, desc, NULL);
|
||||
if (rc)
|
||||
@ -1144,7 +1144,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
|
||||
int is_sigg;
|
||||
const char *newdesc;
|
||||
int pwid;
|
||||
iso7816_pininfo_t pininfo;
|
||||
pininfo_t pininfo;
|
||||
|
||||
(void)ctrl;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* app-openpgp.c - The OpenPGP card application.
|
||||
* Copyright (C) 2003, 2004, 2005, 2007, 2008,
|
||||
* 2009 Free Software Foundation, Inc.
|
||||
* 2009, 2013 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -191,6 +191,14 @@ struct app_local_s {
|
||||
unsigned int def_chv2:1; /* Use 123456 for CHV2. */
|
||||
} flags;
|
||||
|
||||
/* Pinpad request specified on card. */
|
||||
struct
|
||||
{
|
||||
unsigned int specified:1;
|
||||
int fixedlen_user;
|
||||
int fixedlen_admin;
|
||||
} pinpad;
|
||||
|
||||
struct
|
||||
{
|
||||
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
|
||||
the first LF is followed by DC4 (0x14) control sequence are
|
||||
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>
|
||||
|
||||
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:
|
||||
|
||||
Bit 0 = CHV1 and CHV2 are not syncronized
|
||||
Bit 1 = CHV2 has been been set to the default PIN of "123456"
|
||||
(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
|
||||
parse_login_data (app_t app)
|
||||
@ -603,6 +617,9 @@ parse_login_data (app_t app)
|
||||
/* Set defaults. */
|
||||
app->app_local->flags.no_sync = 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. */
|
||||
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. */
|
||||
for (p=buffer+2, len = buflen-2; len && hexdigitp (p); p++, len--)
|
||||
lastdig = xtoi_1 (p);
|
||||
buffer = p;
|
||||
buflen = len;
|
||||
if (len && !(*p == '\n' || *p == '\x18'))
|
||||
goto next; /* Invalid characters in field. */
|
||||
app->app_local->flags.no_sync = !!(lastdig & 1);
|
||||
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:
|
||||
for (; buflen && *buffer != '\x18'; buflen--, buffer++)
|
||||
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
|
||||
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
|
||||
used with CHV1. PINVALUE is the address of a pointer which will
|
||||
receive a newly allocated block with the actual PIN (this is useful
|
||||
in case that PIN shall be used for another verify operation). The
|
||||
caller needs to free this value. If the function returns with
|
||||
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
|
||||
verify_a_chv (app_t app,
|
||||
@ -1489,7 +1584,7 @@ verify_a_chv (app_t app,
|
||||
int rc = 0;
|
||||
char *prompt_buffer = NULL;
|
||||
const char *prompt;
|
||||
iso7816_pininfo_t pininfo;
|
||||
pininfo_t pininfo;
|
||||
int minlen = 6;
|
||||
|
||||
assert (chvno == 1 || chvno == 2);
|
||||
@ -1516,7 +1611,7 @@ verify_a_chv (app_t app,
|
||||
}
|
||||
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.fixedlen = -1;
|
||||
pininfo.minlen = minlen;
|
||||
|
||||
|
||||
@ -1536,12 +1631,13 @@ verify_a_chv (app_t app,
|
||||
prompt = _("||Please enter the PIN");
|
||||
|
||||
|
||||
if (!opt.disable_keypad
|
||||
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
|
||||
if (!opt.disable_pinpad
|
||||
&& !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
|
||||
user to use the keypad. */
|
||||
user to use the pinpad. */
|
||||
rc = pincb (pincb_arg, prompt, NULL);
|
||||
prompt = NULL;
|
||||
xfree (prompt_buffer);
|
||||
@ -1560,7 +1656,7 @@ verify_a_chv (app_t app,
|
||||
}
|
||||
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);
|
||||
prompt = NULL;
|
||||
xfree (prompt_buffer);
|
||||
@ -1620,7 +1716,7 @@ verify_chv2 (app_t app,
|
||||
/* For convenience we verify CHV1 here too. We do this only if
|
||||
the card is not configured to require a verification before
|
||||
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));
|
||||
if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
|
||||
rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
|
||||
@ -1707,22 +1803,23 @@ verify_chv3 (app_t app,
|
||||
|
||||
if (!app->did_chv3)
|
||||
{
|
||||
iso7816_pininfo_t pininfo;
|
||||
pininfo_t pininfo;
|
||||
int minlen = 8;
|
||||
char *prompt;
|
||||
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.fixedlen = -1;
|
||||
pininfo.minlen = minlen;
|
||||
|
||||
rc = build_enter_admin_pin_prompt (app, &prompt);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (!opt.disable_keypad
|
||||
&& !iso7816_check_keypad (app->slot, ISO7816_VERIFY, &pininfo) )
|
||||
if (!opt.disable_pinpad
|
||||
&& !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);
|
||||
xfree (prompt);
|
||||
prompt = NULL;
|
||||
@ -1917,13 +2014,13 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
||||
char *pinvalue = NULL;
|
||||
int reset_mode = !!(flags & APP_CHANGE_FLAG_RESET);
|
||||
int set_resetcode = 0;
|
||||
iso7816_pininfo_t pininfo;
|
||||
int use_keypad = 0;
|
||||
pininfo_t pininfo;
|
||||
int use_pinpad = 0;
|
||||
int minlen = 6;
|
||||
|
||||
(void)ctrl;
|
||||
memset (&pininfo, 0, sizeof pininfo);
|
||||
pininfo.mode = 1;
|
||||
pininfo.fixedlen = -1;
|
||||
pininfo.minlen = minlen;
|
||||
|
||||
if (reset_mode && chvno == 3)
|
||||
@ -1968,15 +2065,16 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
||||
{
|
||||
/* Version 2 cards. */
|
||||
|
||||
if (!opt.disable_keypad
|
||||
&& !iso7816_check_keypad (app->slot,
|
||||
ISO7816_CHANGE_REFERENCE_DATA, &pininfo))
|
||||
use_keypad = 1;
|
||||
if (!opt.disable_pinpad
|
||||
&& !iso7816_check_pinpad (app->slot,
|
||||
ISO7816_CHANGE_REFERENCE_DATA, &pininfo)
|
||||
&& !check_pinpad_request (app, &pininfo, chvno == 3))
|
||||
use_pinpad = 1;
|
||||
|
||||
if (reset_mode)
|
||||
{
|
||||
/* To reset a PIN the Admin PIN is required. */
|
||||
use_keypad = 0;
|
||||
use_pinpad = 0;
|
||||
app->did_chv3 = 0;
|
||||
rc = verify_chv3 (app, pincb, pincb_arg);
|
||||
if (rc)
|
||||
@ -1987,7 +2085,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
||||
}
|
||||
else if (chvno == 1 || chvno == 3)
|
||||
{
|
||||
if (!use_keypad)
|
||||
if (!use_pinpad)
|
||||
{
|
||||
char *promptbuf = NULL;
|
||||
const char *prompt;
|
||||
@ -2030,7 +2128,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
||||
size_t valuelen;
|
||||
int remaining;
|
||||
|
||||
use_keypad = 0;
|
||||
use_pinpad = 0;
|
||||
minlen = 8;
|
||||
relptr = get_one_do (app, 0x00C4, &value, &valuelen, NULL);
|
||||
if (!relptr || valuelen < 7)
|
||||
@ -2078,7 +2176,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
|
||||
else
|
||||
app->did_chv1 = app->did_chv2 = 0;
|
||||
|
||||
if (!use_keypad)
|
||||
if (!use_pinpad)
|
||||
{
|
||||
/* TRANSLATORS: Do not translate the "|*|" prefixes but
|
||||
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. */
|
||||
assert (chvno == 1 || chvno == 3);
|
||||
|
||||
if (use_keypad)
|
||||
if (use_pinpad)
|
||||
{
|
||||
rc = pincb (pincb_arg,
|
||||
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
|
||||
with version2 to not have the need for a separate CHV2 and
|
||||
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)
|
||||
{
|
||||
rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
|
||||
|
@ -26,8 +26,8 @@
|
||||
|
||||
#include "scdaemon.h"
|
||||
#include "app-common.h"
|
||||
#include "apdu.h"
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h"
|
||||
#include "tlv.h"
|
||||
|
||||
/* This table is used to keep track of locks on a per reader base.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ccid-driver.c - USB ChipCardInterfaceDevices driver
|
||||
* Copyright (C) 2003, 2004, 2005, 2006, 2007
|
||||
* 2008, 2009 Free Software Foundation, Inc.
|
||||
* 2008, 2009, 2013 Free Software Foundation, Inc.
|
||||
* Written by Werner Koch.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
@ -89,6 +89,8 @@
|
||||
|
||||
#include <usb.h>
|
||||
|
||||
#include "scdaemon.h"
|
||||
#include "iso7816.h"
|
||||
#include "ccid-driver.h"
|
||||
|
||||
#define DRVNAME "ccid-driver: "
|
||||
@ -207,6 +209,7 @@ enum {
|
||||
VENDOR_SCM = 0x04e6,
|
||||
VENDOR_OMNIKEY= 0x076b,
|
||||
VENDOR_GEMPC = 0x08e6,
|
||||
VENDOR_VEGA = 0x0982,
|
||||
VENDOR_KAAN = 0x0d46,
|
||||
VENDOR_FSIJ = 0x234b,
|
||||
VENDOR_VASCO = 0x1a44
|
||||
@ -220,6 +223,8 @@ enum {
|
||||
#define SCM_SPR532 0xe003
|
||||
#define CHERRY_ST2000 0x003e
|
||||
#define VASCO_920 0x0920
|
||||
#define GEMPC_PINPAD 0x3478
|
||||
#define VEGA_ALPHA 0x0008
|
||||
|
||||
/* A list and a table with special transport descriptions. */
|
||||
enum {
|
||||
@ -264,6 +269,9 @@ struct ccid_driver_s
|
||||
unsigned char apdu_level:2; /* Reader supports short APDU level
|
||||
exchange. With a value of 2 short
|
||||
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 powered_off:1;
|
||||
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,
|
||||
int no_debug);
|
||||
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
|
||||
integer. */
|
||||
@ -758,7 +769,7 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
||||
{
|
||||
unsigned int i;
|
||||
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;
|
||||
@ -767,6 +778,9 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
||||
handle->ifsd = 0;
|
||||
handle->has_pinpad = 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",
|
||||
handle->id_vendor, handle->id_product, handle->bcd_device);
|
||||
if (buflen < 54 || buf[0] < 54)
|
||||
@ -842,22 +856,31 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
||||
DEBUGOUT_1 (" dwFeatures %08X\n", us);
|
||||
if ((us & 0x0002))
|
||||
{
|
||||
DEBUGOUT (" Auto configuration based on ATR\n");
|
||||
have_auto_conf = 1;
|
||||
DEBUGOUT (" Auto configuration based on ATR (assumes auto voltage)\n");
|
||||
handle->auto_voltage = 1;
|
||||
}
|
||||
if ((us & 0x0004))
|
||||
DEBUGOUT (" Auto activation on insert\n");
|
||||
if ((us & 0x0008))
|
||||
DEBUGOUT (" Auto voltage selection\n");
|
||||
{
|
||||
DEBUGOUT (" Auto voltage selection\n");
|
||||
handle->auto_voltage = 1;
|
||||
}
|
||||
if ((us & 0x0010))
|
||||
DEBUGOUT (" Auto clock change\n");
|
||||
if ((us & 0x0020))
|
||||
DEBUGOUT (" Auto baud rate change\n");
|
||||
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))
|
||||
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");
|
||||
|
||||
if ((us & 0x0100))
|
||||
@ -935,11 +958,10 @@ parse_ccid_descriptor (ccid_driver_t handle,
|
||||
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, "
|
||||
"TPDU or APDU level exchange and auto configuration - "
|
||||
"this is not available\n");
|
||||
"TPDU or APDU level exchange - this is not available\n");
|
||||
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
|
||||
pointer to be used as handle in HANDLE. Returns 0 on success. */
|
||||
int
|
||||
@ -1614,6 +1659,8 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
|
||||
}
|
||||
}
|
||||
|
||||
rc = ccid_vendor_specific_init (*handle);
|
||||
|
||||
leave:
|
||||
free (ifcdesc_extra);
|
||||
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
|
||||
actual reset is done. */
|
||||
int
|
||||
@ -2354,6 +2546,15 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
unsigned int edc;
|
||||
int tried_iso = 0;
|
||||
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. */
|
||||
rc = ccid_slot_status (handle, &statusbits);
|
||||
@ -2368,7 +2569,8 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
msg[0] = PC_to_RDR_IccPowerOn;
|
||||
msg[5] = 0; /* slot */
|
||||
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[9] = 0; /* RFU */
|
||||
set_msg_len (msg, 0);
|
||||
@ -2410,23 +2612,73 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
*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;
|
||||
msg[0] = PC_to_RDR_GetParameters;
|
||||
msg[5] = 0; /* slot */
|
||||
msg[6] = seqno = handle->seqno++;
|
||||
msg[7] = 0; /* RFU */
|
||||
msg[8] = 0; /* RFU */
|
||||
msg[9] = 0; /* RFU */
|
||||
set_msg_len (msg, 0);
|
||||
msglen = 10;
|
||||
rc = bulk_out (handle, msg, msglen, 0);
|
||||
if (!rc)
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
|
||||
seqno, 2000, 0);
|
||||
if (rc)
|
||||
DEBUGOUT ("GetParameters failed\n");
|
||||
else if (msglen == 17 && msg[9] == 1)
|
||||
got_param = 1;
|
||||
|
||||
if (handle->auto_param)
|
||||
{
|
||||
msg[0] = PC_to_RDR_GetParameters;
|
||||
msg[5] = 0; /* slot */
|
||||
msg[6] = seqno = handle->seqno++;
|
||||
msg[7] = 0; /* RFU */
|
||||
msg[8] = 0; /* RFU */
|
||||
msg[9] = 0; /* RFU */
|
||||
set_msg_len (msg, 0);
|
||||
msglen = 10;
|
||||
rc = bulk_out (handle, msg, msglen, 0);
|
||||
if (!rc)
|
||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_Parameters,
|
||||
seqno, 2000, 0);
|
||||
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. */
|
||||
msg[0] = PC_to_RDR_SetParameters;
|
||||
@ -2437,16 +2689,7 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
msg[9] = 0; /* RFU */
|
||||
|
||||
if (!got_param)
|
||||
{
|
||||
/* 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. */
|
||||
}
|
||||
memcpy (&msg[10], param, 7);
|
||||
set_msg_len (msg, 7);
|
||||
msglen = 10 + 7;
|
||||
|
||||
@ -2463,6 +2706,12 @@ ccid_get_atr (ccid_driver_t handle,
|
||||
else
|
||||
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_nr = 0;
|
||||
|
||||
@ -3071,7 +3320,7 @@ ccid_transceive (ccid_driver_t handle,
|
||||
The APDU should me made up of 4 bytes without Lc.
|
||||
|
||||
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
|
||||
merely check whether the reader supports the secure command for the
|
||||
@ -3079,8 +3328,7 @@ ccid_transceive (ccid_driver_t handle,
|
||||
int
|
||||
ccid_transceive_secure (ccid_driver_t handle,
|
||||
const unsigned char *apdu_buf, size_t apdu_buflen,
|
||||
int pin_mode, int pinlen_min, int pinlen_max,
|
||||
int pin_padlen,
|
||||
pininfo_t *pininfo,
|
||||
unsigned char *resp, size_t maxresplen, size_t *nresp)
|
||||
{
|
||||
int rc;
|
||||
@ -3091,6 +3339,7 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
size_t dummy_nresp;
|
||||
int testmode;
|
||||
int cherry_mode = 0;
|
||||
int enable_varlen = 0;
|
||||
|
||||
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
|
||||
return CCID_DRIVER_ERR_NO_KEYPAD;
|
||||
return CCID_DRIVER_ERR_NO_PINPAD;
|
||||
|
||||
if (pin_mode != 1)
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
|
||||
if (pin_padlen != 0)
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
|
||||
if (!pinlen_min)
|
||||
pinlen_min = 1;
|
||||
if (!pinlen_max)
|
||||
pinlen_max = 25;
|
||||
if (!pininfo->minlen)
|
||||
pininfo->minlen = 1;
|
||||
if (!pininfo->maxlen)
|
||||
pininfo->maxlen = 25;
|
||||
|
||||
/* Note that the 25 is the maximum value the SPR532 allows. */
|
||||
if (pinlen_min < 1 || pinlen_min > 25
|
||||
|| pinlen_max < 1 || pinlen_max > 25
|
||||
|| pinlen_min > pinlen_max)
|
||||
if (pininfo->minlen < 1 || pininfo->minlen > 25
|
||||
|| pininfo->maxlen < 1 || pininfo->maxlen > 25
|
||||
|| pininfo->minlen > pininfo->maxlen)
|
||||
return CCID_DRIVER_ERR_INV_VALUE;
|
||||
|
||||
/* 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_KAAN: /* Tested with KAAN Advanced (1.02). */
|
||||
case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05). */
|
||||
enable_varlen = 1;
|
||||
break;
|
||||
case VENDOR_VASCO: /* Tested with DIGIPASS 920 */
|
||||
pinlen_max = 15;
|
||||
enable_varlen = 1;
|
||||
pininfo->maxlen = 15;
|
||||
break;
|
||||
case VENDOR_CHERRY:
|
||||
enable_varlen = 1;
|
||||
/* The CHERRY XX44 keyboard echos an asterisk for each entered
|
||||
character on the keyboard channel. We use a special variant
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
if (enable_varlen)
|
||||
pininfo->fixedlen = 0;
|
||||
|
||||
if (testmode)
|
||||
return 0; /* Success */
|
||||
|
||||
if (pininfo->fixedlen < 0 || pininfo->fixedlen >= 16)
|
||||
return CCID_DRIVER_ERR_NOT_SUPPORTED;
|
||||
|
||||
msg = send_buffer;
|
||||
if (handle->id_vendor == VENDOR_SCM)
|
||||
{
|
||||
@ -3180,9 +3442,9 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
}
|
||||
else
|
||||
{
|
||||
msg[13] = 0x00; /* bmPINBlockString:
|
||||
0 bits of pin length to insert.
|
||||
0 bytes of PIN block size. */
|
||||
msg[13] = pininfo->fixedlen; /* bmPINBlockString:
|
||||
0 bits of pin length to insert.
|
||||
PIN block size by fixedlen. */
|
||||
msg[14] = 0x00; /* bmPINLengthFormat:
|
||||
Units are bytes, position is 0. */
|
||||
}
|
||||
@ -3191,12 +3453,12 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
if (apdu_buf[1] == 0x24)
|
||||
{
|
||||
msg[msglen++] = 0; /* bInsertionOffsetOld */
|
||||
msg[msglen++] = 0; /* bInsertionOffsetNew */
|
||||
msg[msglen++] = pininfo->fixedlen; /* bInsertionOffsetNew */
|
||||
}
|
||||
|
||||
/* The following is a little endian word. */
|
||||
msg[msglen++] = pinlen_max; /* wPINMaxExtraDigit-Maximum. */
|
||||
msg[msglen++] = pinlen_min; /* wPINMaxExtraDigit-Minimum. */
|
||||
msg[msglen++] = pininfo->maxlen; /* wPINMaxExtraDigit-Maximum. */
|
||||
msg[msglen++] = pininfo->minlen; /* wPINMaxExtraDigit-Minimum. */
|
||||
|
||||
if (apdu_buf[1] == 0x24)
|
||||
msg[msglen++] = apdu_buf[2] == 0 ? 0x03 : 0x01;
|
||||
@ -3209,12 +3471,12 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
|
||||
msg[msglen] = 0x02; /* bEntryValidationCondition:
|
||||
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. */
|
||||
msglen++;
|
||||
|
||||
if (apdu_buf[1] == 0x20)
|
||||
msg[msglen++] = 0xff; /* bNumberMessage: Default. */
|
||||
msg[msglen++] = 0x01; /* bNumberMessage. */
|
||||
else
|
||||
msg[msglen++] = 0x03; /* bNumberMessage. */
|
||||
|
||||
@ -3230,10 +3492,18 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
msg[msglen++] = 2; /* bMsgIndex3. */
|
||||
}
|
||||
|
||||
/* Calculate Lc. */
|
||||
n = pininfo->fixedlen;
|
||||
if (apdu_buf[1] == 0x24)
|
||||
n += pininfo->fixedlen;
|
||||
|
||||
/* bTeoProlog follows: */
|
||||
msg[msglen++] = handle->nonnull_nad? ((1 << 4) | 0): 0;
|
||||
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: */
|
||||
msg[msglen++] = apdu_buf[0]; /* CLA */
|
||||
msg[msglen++] = apdu_buf[1]; /* INS */
|
||||
@ -3241,6 +3511,12 @@ ccid_transceive_secure (ccid_driver_t handle,
|
||||
msg[msglen++] = apdu_buf[3]; /* P2 */
|
||||
if (cherry_mode)
|
||||
msg[msglen++] = 0;
|
||||
else if (pininfo->fixedlen != 0)
|
||||
{
|
||||
msg[msglen++] = n;
|
||||
memset (&msg[msglen], 0xff, n);
|
||||
msglen += n;
|
||||
}
|
||||
/* An EDC is not required. */
|
||||
set_msg_len (msg, msglen - 10);
|
||||
|
||||
|
@ -72,7 +72,7 @@
|
||||
#define CCID_DRIVER_ERR_GENERAL_ERROR 0x1000b
|
||||
#define CCID_DRIVER_ERR_NO_READER 0x1000c
|
||||
#define CCID_DRIVER_ERR_ABORTED 0x1000d
|
||||
#define CCID_DRIVER_ERR_NO_KEYPAD 0x1000e
|
||||
#define CCID_DRIVER_ERR_NO_PINPAD 0x1000e
|
||||
|
||||
struct ccid_driver_s;
|
||||
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);
|
||||
int ccid_transceive_secure (ccid_driver_t handle,
|
||||
const unsigned char *apdu, size_t apdulen,
|
||||
int pin_mode,
|
||||
int pinlen_min, int pinlen_max, int pin_padlen,
|
||||
pininfo_t *pininfo,
|
||||
unsigned char *resp, size_t maxresplen, size_t *nresp);
|
||||
int ccid_transceive_escape (ccid_driver_t handle,
|
||||
const unsigned char *data, size_t datalen,
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <assuan.h>
|
||||
#include <ksba.h>
|
||||
#include "app-common.h"
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h" /* Required for apdu_*_reader (). */
|
||||
#include "atr.h"
|
||||
#include "exechelp.h"
|
||||
@ -908,13 +909,13 @@ pin_cb (void *opaque, const char *info, char **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.
|
||||
We ignore any value returned. */
|
||||
if (info)
|
||||
{
|
||||
log_debug ("prompting for keypad entry '%s'\n", info);
|
||||
rc = estream_asprintf (&command, "POPUPKEYPADPROMPT %s", info);
|
||||
log_debug ("prompting for pinpad entry '%s'\n", info);
|
||||
rc = estream_asprintf (&command, "POPUPPINPADPROMPT %s", info);
|
||||
if (rc < 0)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
|
||||
@ -922,8 +923,8 @@ pin_cb (void *opaque, const char *info, char **retstr)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_debug ("dismiss keypad entry prompt\n");
|
||||
rc = assuan_inquire (ctx, "DISMISSKEYPADPROMPT",
|
||||
log_debug ("dismiss pinpad entry prompt\n");
|
||||
rc = assuan_inquire (ctx, "DISMISSPINPADPROMPT",
|
||||
&value, &valuelen, MAXLEN_PIN);
|
||||
}
|
||||
if (!rc)
|
||||
|
@ -94,7 +94,7 @@ map_sw (int sw)
|
||||
case SW_HOST_GENERAL_ERROR: ec = GPG_ERR_GENERAL; break;
|
||||
case SW_HOST_NO_READER: ec = GPG_ERR_ENODEV; 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:
|
||||
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
|
||||
the keypad. Returns 0 on success. */
|
||||
the pinpad. Returns 0 on success. */
|
||||
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;
|
||||
|
||||
sw = apdu_check_keypad (slot, command,
|
||||
pininfo->mode, pininfo->minlen, pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
sw = apdu_check_pinpad (slot, command, pininfo);
|
||||
return iso7816_map_sw (sw);
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
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;
|
||||
|
||||
sw = apdu_keypad_verify (slot, 0x00, CMD_VERIFY, 0, chvno,
|
||||
pininfo->mode, pininfo->minlen, pininfo->maxlen,
|
||||
pininfo->padlen);
|
||||
sw = apdu_pinpad_verify (slot, 0x00, CMD_VERIFY, 0, chvno, pininfo);
|
||||
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
|
||||
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
|
||||
data" is done, otherwise an "exchange reference data". */
|
||||
gpg_error_t
|
||||
iso7816_change_reference_data_kp (int slot, int chvno, int is_exchange,
|
||||
iso7816_pininfo_t *pininfo)
|
||||
pininfo_t *pininfo)
|
||||
{
|
||||
int sw;
|
||||
|
||||
sw = apdu_keypad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
is_exchange ? 1 : 0,
|
||||
chvno, pininfo->mode, pininfo->minlen,
|
||||
pininfo->maxlen, pininfo->padlen);
|
||||
sw = apdu_pinpad_modify (slot, 0x00, CMD_CHANGE_REFERENCE_DATA,
|
||||
is_exchange ? 1 : 0, chvno, pininfo);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
|
@ -24,23 +24,26 @@
|
||||
#include "cardglue.h"
|
||||
#endif
|
||||
|
||||
/* Command codes used by iso7816_check_keypad. */
|
||||
/* Command codes used by iso7816_check_pinpad. */
|
||||
#define ISO7816_VERIFY 0x20
|
||||
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
|
||||
#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. */
|
||||
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 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);
|
||||
@ -59,17 +62,17 @@ gpg_error_t iso7816_apdu_direct (int slot,
|
||||
const void *apdudata, size_t apdudatalen,
|
||||
int handle_more,
|
||||
unsigned char **result, size_t *resultlen);
|
||||
gpg_error_t iso7816_check_keypad (int slot, int command,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_check_pinpad (int slot, int command,
|
||||
pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_verify (int slot,
|
||||
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,
|
||||
const char *oldchv, size_t oldchvlen,
|
||||
const char *newchv, size_t newchvlen);
|
||||
gpg_error_t iso7816_change_reference_data_kp (int slot, int chvno,
|
||||
int is_exchange,
|
||||
iso7816_pininfo_t *pininfo);
|
||||
pininfo_t *pininfo);
|
||||
gpg_error_t iso7816_reset_retry_counter (int slot, int chvno,
|
||||
const char *newchv, size_t newchvlen);
|
||||
gpg_error_t iso7816_reset_retry_counter_with_rc (int slot, int chvno,
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "../common/ttyio.h"
|
||||
#include "../common/simple-pwquery.h"
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h" /* for open_reader */
|
||||
#include "atr.h"
|
||||
#include "app-common.h"
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "i18n.h"
|
||||
#include "sysutils.h"
|
||||
#include "app-common.h"
|
||||
#include "iso7816.h"
|
||||
#include "apdu.h"
|
||||
#include "ccid-driver.h"
|
||||
#include "mkdtemp.h"
|
||||
@ -91,10 +92,11 @@ enum cmd_and_opt_values
|
||||
opcscDriver,
|
||||
oDisableCCID,
|
||||
oDisableOpenSC,
|
||||
oDisableKeypad,
|
||||
oDisablePinpad,
|
||||
oAllowAdmin,
|
||||
oDenyAdmin,
|
||||
oDisableApplication,
|
||||
oEnablePinpadVarlen,
|
||||
oDebugDisableTicker
|
||||
};
|
||||
|
||||
@ -142,12 +144,14 @@ static ARGPARSE_OPTS opts[] = {
|
||||
/* end --disable-ccid */),
|
||||
ARGPARSE_s_u (oCardTimeout, "card-timeout",
|
||||
N_("|N|disconnect the card after N seconds of inactivity")),
|
||||
ARGPARSE_s_n (oDisableKeypad, "disable-keypad",
|
||||
N_("do not use a reader's keypad")),
|
||||
ARGPARSE_s_n (oDisablePinpad, "disable-pinpad",
|
||||
N_("do not use a reader's pinpad")),
|
||||
ARGPARSE_s_n (oAllowAdmin, "allow-admin", "@"),
|
||||
ARGPARSE_s_n (oDenyAdmin, "deny-admin",
|
||||
N_("deny the use of admin card commands")),
|
||||
ARGPARSE_s_s (oDisableApplication, "disable-application", "@"),
|
||||
ARGPARSE_s_n (oEnablePinpadVarlen, "enable-pinpad-varlen",
|
||||
N_("use variable length input for pinpad")),
|
||||
|
||||
ARGPARSE_end ()
|
||||
};
|
||||
@ -575,7 +579,7 @@ main (int argc, char **argv )
|
||||
case oDisableCCID: opt.disable_ccid = 1; 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. */
|
||||
break;
|
||||
@ -587,6 +591,8 @@ main (int argc, char **argv )
|
||||
add_to_strlist (&opt.disabled_applications, pargs.r.ret_str);
|
||||
break;
|
||||
|
||||
case oEnablePinpadVarlen: opt.enable_pinpad_varlen = 1; break;
|
||||
|
||||
default:
|
||||
pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
|
||||
break;
|
||||
@ -675,8 +681,9 @@ main (int argc, char **argv )
|
||||
es_printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE );
|
||||
#endif
|
||||
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 ("enable-pinpad-varlen:%lu:\n", GC_OPT_FLAG_NONE );
|
||||
|
||||
scd_exit (0);
|
||||
}
|
||||
|
@ -56,7 +56,8 @@ struct
|
||||
const char *pcsc_driver; /* Library to access the PC/SC system. */
|
||||
const char *reader_port; /* NULL or reder port to use. */
|
||||
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
|
||||
cards. */
|
||||
strlist_t disabled_applications; /* Card applications we do not
|
||||
|
@ -617,8 +617,8 @@ static gc_option_t gc_options_scdaemon[] =
|
||||
{ "disable-ccid", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_EXPERT,
|
||||
"gnupg", "do not use the internal CCID driver",
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
|
||||
{ "disable-keypad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
|
||||
"gnupg", "do not use a reader's keypad",
|
||||
{ "disable-pinpad", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
|
||||
"gnupg", "do not use a reader's pinpad",
|
||||
GC_ARG_TYPE_NONE, GC_BACKEND_SCDAEMON },
|
||||
{ "card-timeout", GC_OPT_FLAG_NONE|GC_OPT_FLAG_RUNTIME, GC_LEVEL_BASIC,
|
||||
"gnupg", "|N|disconnect the card after N seconds of inactivity",
|
||||
|
Loading…
x
Reference in New Issue
Block a user