1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

Changes needed to support smartcards. Well, only _support_. There is

no real code yet.
This commit is contained in:
Werner Koch 2002-02-28 11:07:59 +00:00
parent f8c8ca26d4
commit 56341c289c
23 changed files with 808 additions and 104 deletions

View file

@ -1,3 +1,22 @@
2002-02-28 Werner Koch <wk@gnupg.org>
* pksign.c (agent_pksign): Detect whether a Smartcard is to be
used and divert the operation in this case.
* pkdecrypt.c (agent_pkdecrypt): Likewise
* findkey.c (agent_key_from_file): Add optional arg shadow_info
and have it return information about a shadowed key.
* protect.c (agent_get_shadow_info): New.
* divert-scd.c: New.
2002-02-27 Werner Koch <wk@gnupg.org>
* protect.c (agent_shadow_key): New.
* command.c (cmd_learn): New command LEARN.
* gpg-agent.c: New option --scdaemon-program.
* call-scd.c (start_scd): New. Based on query.c
* query.c: Add 2 more arguments to all uses of assuan_transact.
2002-02-18 Werner Koch <wk@gnupg.org>
* findkey.c (unprotect): Show an error message for a bad passphrase.

View file

@ -35,7 +35,9 @@ gpg_agent_SOURCES = \
pkdecrypt.c \
genkey.c \
protect.c \
trustlist.c
trustlist.c \
divert-scd.c \
call-scd.c
gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \
../common/libcommon.a $(LIBGCRYPT_LIBS)

View file

@ -36,6 +36,7 @@ struct {
int batch; /* batch mode */
const char *homedir; /* configuration directory name */
const char *pinentry_program;
const char *scdaemon_program;
int no_grab; /* don't let the pinentry grab the keyboard */
unsigned long def_cache_ttl;
@ -101,7 +102,8 @@ const char *trans (const char *text);
void start_command_handler (int);
/*-- findkey.c --*/
GCRY_SEXP agent_key_from_file (const unsigned char *grip);
GCRY_SEXP agent_key_from_file (const unsigned char *grip,
unsigned char **shadow_info);
int agent_key_available (const unsigned char *grip);
/*-- query.c --*/
@ -135,6 +137,11 @@ int agent_protect (const unsigned char *plainkey, const char *passphrase,
int agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
unsigned char **result, size_t *resultlen);
int agent_private_key_type (const unsigned char *privatekey);
int agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info,
unsigned char **result);
int agent_get_shadow_info (const unsigned char *shadowkey,
unsigned char const **shadow_info);
/*-- trustlist.c --*/
@ -143,4 +150,14 @@ int agent_listtrusted (void *assuan_context);
int agent_marktrusted (const char *name, const char *fpr, int flag);
/*-- divert-scd.c --*/
int divert_pksign (GCRY_SEXP *s_sig, GCRY_SEXP s_hash,
const char *shadow_info);
int divert_pkdecrypt (GCRY_SEXP *s_plain, GCRY_SEXP s_cipher,
const char *shadow_info);
/*-- call-scd.c --*/
int agent_learn_card (void);
#endif /*AGENT_H*/

View file

@ -462,6 +462,22 @@ cmd_clear_passphrase (ASSUAN_CONTEXT ctx, char *line)
return 0;
}
/* LEARN
Learn something about the currently inserted smartcard
*/
static int
cmd_learn (ASSUAN_CONTEXT ctx, char *line)
{
int rc;
rc = agent_learn_card ();
if (rc)
log_error ("agent_learn_card failed: %s\n", gnupg_strerror (rc));
return map_to_assuan_status (rc);
}
/* Tell the assuan library about our commands */
@ -485,6 +501,7 @@ register_commands (ASSUAN_CONTEXT ctx)
{ "CLEAR_PASSPHRASE",0, cmd_clear_passphrase },
{ "LISTTRUSTED", 0, cmd_listtrusted },
{ "MARKTRUSTED", 0, cmd_marktrusted },
{ "LEARN", 0, cmd_learn },
{ "", ASSUAN_CMD_INPUT, NULL },
{ "", ASSUAN_CMD_OUTPUT, NULL },
{ NULL }

View file

@ -95,9 +95,12 @@ unprotect (unsigned char **keybuf, const unsigned char *grip)
/* Return the secret key as an S-Exp after locating it using the grip.
Returns NULL if key is not available. */
Returns NULL if key is not available or the operation should be
diverted to a token. In the latter case shadow_info will point to
an allocated S-Expression with the shadow_info part from the
file. */
GCRY_SEXP
agent_key_from_file (const unsigned char *grip)
agent_key_from_file (const unsigned char *grip, unsigned char **shadow_info)
{
int i, rc;
char *fname;
@ -108,6 +111,9 @@ agent_key_from_file (const unsigned char *grip)
GCRY_SEXP s_skey;
char hexgrip[40+4+1];
if (shadow_info)
*shadow_info = NULL;
for (i=0; i < 20; i++)
sprintf (hexgrip+2*i, "%02X", grip[i]);
strcpy (hexgrip+40, ".key");
@ -173,8 +179,30 @@ agent_key_from_file (const unsigned char *grip)
gnupg_strerror (rc));
break;
case PRIVATE_KEY_SHADOWED:
log_error ("shadowed private keys are not yet supported\n");
rc = GNUPG_Not_Implemented;
if (shadow_info)
{
const unsigned char *s;
size_t n;
rc = agent_get_shadow_info (buf, &s);
if (!rc)
{
n = gcry_sexp_canon_len (s, 0, NULL,NULL);
assert (n);
*shadow_info = xtrymalloc (n);
if (!*shadow_info)
rc = GNUPG_Out_Of_Core;
else
{
memcpy (*shadow_info, s, n);
rc = 0;
}
}
if (rc)
log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc));
}
rc = -1; /* ugly interface: we return an error but keep a value
in shadow_info. */
break;
default:
log_error ("invalid private key format\n");

View file

@ -69,6 +69,7 @@ enum cmd_and_opt_values
oBatch,
oPinentryProgram,
oScdaemonProgram,
oDefCacheTTL,
aTest };
@ -92,7 +93,8 @@ static ARGPARSE_OPTS opts[] = {
{ oNoGrab, "no-grab" ,0, N_("do not grab keyboard and mouse")},
{ oLogFile, "log-file" ,2, N_("use a log file for the server")},
{ oPinentryProgram, "pinentry-program", 2 , "path of PIN Entry program" },
{ oPinentryProgram, "pinentry-program", 2 , "path to PIN Entry program" },
{ oScdaemonProgram, "scdaemon-program", 2 , "path to SCdaemon program" },
{ oDefCacheTTL, "default-cache-ttl", 4,
"|N|expire cached PINs after N seconds"},
@ -372,6 +374,7 @@ main (int argc, char **argv )
case oServer: pipe_server = 1; break;
case oPinentryProgram: opt.pinentry_program = pargs.r.ret_str; break;
case oScdaemonProgram: opt.scdaemon_program = pargs.r.ret_str; break;
case oDefCacheTTL: opt.def_cache_ttl = pargs.r.ret_ulong; break;
default : pargs.err = configfp? 1:2; break;

View file

@ -4,7 +4,8 @@ keyformat.txt (wk 2001-12-18)
Some notes on the format of the secret keys used with gpg-agent.
Location of keys
================
The secret keys[1] are stored on a per file basis in a directory below
the ~/.gnupg home directory. This directory is named
@ -13,9 +14,12 @@ the ~/.gnupg home directory. This directory is named
and should have permissions 700.
The secret keys are stored in files with a name matching the
hexadecimal representation of the keygrip[2]. The content of the file
is an S-Expression like the ones used with Libgcrypt. Here is an
example of an unprotected file:
hexadecimal representation of the keygrip[2].
Unprotected Private Key Format
==============================
The content of the file is an S-Expression like the ones used with
Libgcrypt. Here is an example of an unprotected file:
(private-key
(rsa
@ -47,8 +51,9 @@ keys is in canonical representation[3]:
)
This describes an unprotected key; a protected key is like this:
Protected Private Key Format
==============================
A protected key is like this:
(protected-private-key
(rsa
@ -116,12 +121,35 @@ the stored one - If they don't match the integrity of the key is not
given.
Shadowed Private Key Format
============================
To keep track of keys stored on IC cards we use a third format for
private kyes which are called shadow keys as they are only a reference
to keys stored on a token:
(shadowed-private-key
(rsa
(n #00e0ce9..[some bytes not shown]..51#)
(e #010001#)
(shadowed protocol (info))
)
(uri http://foo.bar x-foo:whatever_you_want)
)
The currently used protocol is "ti-v1" (token info version 1). The
second list with the information has this layout:
(card_serial_number id_string_of_key)
More items may be added to the list.
Notes:
======
[1] I usually use the terms private and secret key exchangeable but prefer the
term secret key because it can be visually be better distinguished
from the term public key.

View file

@ -39,6 +39,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
FILE *outfp)
{
GCRY_SEXP s_skey = NULL, s_cipher = NULL, s_plain = NULL;
unsigned char *shadow_info = NULL;
int rc;
char *buf = NULL;
size_t len;
@ -63,27 +64,38 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
log_printhex ("keygrip:", ctrl->keygrip, 20);
log_printhex ("cipher: ", ciphertext, ciphertextlen);
}
s_skey = agent_key_from_file (ctrl->keygrip);
if (!s_skey)
s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info);
if (!s_skey && !shadow_info)
{
log_error ("failed to read the secret key\n");
rc = seterr (No_Secret_Key);
goto leave;
}
if (DBG_CRYPTO)
{
log_debug ("skey: ");
gcry_sexp_dump (s_skey);
if (!s_skey)
{ /* divert operation to the smartcard */
rc = divert_pkdecrypt (&s_plain, s_cipher, shadow_info);
if (rc)
{
log_error ("smartcard decryption failed: %s\n", gnupg_strerror (rc));
goto leave;
}
}
else
{ /* no smartcard, but a private key */
if (DBG_CRYPTO)
{
log_debug ("skey: ");
gcry_sexp_dump (s_skey);
}
rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey);
if (rc)
{
log_error ("decryption failed: %s\n", gcry_strerror (rc));
rc = map_gcry_err (rc);
goto leave;
}
rc = gcry_pk_decrypt (&s_plain, s_cipher, s_skey);
if (rc)
{
log_error ("decryption failed: %s\n", gcry_strerror (rc));
rc = map_gcry_err (rc);
goto leave;
}
}
if (DBG_CRYPTO)
{
@ -106,6 +118,7 @@ agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
gcry_sexp_release (s_plain);
gcry_sexp_release (s_cipher);
xfree (buf);
xfree (shadow_info);
return rc;
}

View file

@ -90,6 +90,7 @@ agent_pksign (CTRL ctrl, FILE *outfp)
{
GCRY_SEXP s_skey = NULL, s_hash = NULL, s_sig = NULL;
GCRY_MPI frame = NULL;
unsigned char *shadow_info = NULL;
int rc;
char *buf = NULL;
size_t len;
@ -97,39 +98,50 @@ agent_pksign (CTRL ctrl, FILE *outfp)
if (!ctrl->have_keygrip)
return seterr (No_Secret_Key);
s_skey = agent_key_from_file (ctrl->keygrip);
if (!s_skey)
s_skey = agent_key_from_file (ctrl->keygrip, &shadow_info);
if (!s_skey && !shadow_info)
{
log_error ("failed to read the secret key\n");
rc = seterr (No_Secret_Key);
goto leave;
}
/* put the hash into a sexp */
/* put the hash into a sexp FIXME: this belongs into libgcrypt/divert-scd.c*/
rc = do_encode_md (ctrl->digest.value,
ctrl->digest.valuelen,
ctrl->digest.algo,
gcry_pk_get_nbits (s_skey),
&frame);
if (rc)
goto leave;
goto leave;
if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) )
BUG ();
if (DBG_CRYPTO)
{
log_debug ("skey: ");
gcry_sexp_dump (s_skey);
if (!s_skey)
{ /* divert operation to the smartcard */
rc = divert_pksign (&s_sig, s_hash, shadow_info);
if (rc)
{
log_error ("smartcard signing failed: %s\n", gnupg_strerror (rc));
goto leave;
}
}
else
{ /* no smartcard, but a private key */
if (DBG_CRYPTO)
{
log_debug ("skey: ");
gcry_sexp_dump (s_skey);
}
/* sign */
rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
if (rc)
{
log_error ("signing failed: %s\n", gcry_strerror (rc));
rc = map_gcry_err (rc);
goto leave;
/* sign */
rc = gcry_pk_sign (&s_sig, s_hash, s_skey);
if (rc)
{
log_error ("signing failed: %s\n", gcry_strerror (rc));
rc = map_gcry_err (rc);
goto leave;
}
}
if (DBG_CRYPTO)
@ -138,7 +150,6 @@ agent_pksign (CTRL ctrl, FILE *outfp)
gcry_sexp_dump (s_sig);
}
len = gcry_sexp_sprint (s_sig, GCRYSEXP_FMT_CANON, NULL, 0);
assert (len);
buf = xmalloc (len);
@ -156,6 +167,7 @@ agent_pksign (CTRL ctrl, FILE *outfp)
gcry_sexp_release (s_sig);
gcry_mpi_release (frame);
xfree (buf);
xfree (shadow_info);
return rc;
}

View file

@ -49,6 +49,8 @@ enum cmd_and_opt_values
oUnprotect = 'u',
oNoVerbose = 500,
oShadow,
oShowShadowInfo,
aTest };
@ -65,6 +67,8 @@ static ARGPARSE_OPTS opts[] = {
{ oPassphrase, "passphrase", 2, "|STRING| Use passphrase STRING" },
{ oProtect, "protect", 256, "protect a private key"},
{ oUnprotect, "unprotect", 256, "unprotect a private key"},
{ oShadow, "shadow", 256, "create a shadow entry for a priblic key"},
{ oShowShadowInfo, "show-shadow-info", 256, "return the shadow info"},
{0}
};
@ -125,8 +129,7 @@ my_gcry_logger (void *dummy, int level, const char *fmt, va_list arg_ptr)
case GCRY_LOG_FATAL:level = JNLIB_LOG_FATAL; break;
case GCRY_LOG_BUG: level = JNLIB_LOG_BUG; break;
case GCRY_LOG_DEBUG:level = JNLIB_LOG_DEBUG; break;
default: level = JNLIB_LOG_ERROR; break;
}
default: level = JNLIB_LOG_ERROR; break; }
log_logv (level, fmt, arg_ptr);
}
@ -291,6 +294,79 @@ read_and_unprotect (const char *fname)
}
static void
read_and_shadow (const char *fname)
{
int rc;
unsigned char *key;
unsigned char *result;
size_t resultlen;
key = read_key (fname);
if (!key)
return;
rc = agent_shadow_key (key, "(8:313233342:43)", &result);
xfree (key);
if (rc)
{
log_error ("shadowing the key failed: %s\n", gnupg_strerror (rc));
return;
}
resultlen = gcry_sexp_canon_len (result, 0, NULL,NULL);
assert (resultlen);
if (opt_armor)
{
char *p = make_advanced (result, resultlen);
xfree (result);
if (!p)
return;
result = p;
resultlen = strlen (p);
}
fwrite (result, resultlen, 1, stdout);
xfree (result);
}
static void
show_shadow_info (const char *fname)
{
int rc;
unsigned char *key;
const unsigned char *info;
size_t infolen;
key = read_key (fname);
if (!key)
return;
rc = agent_get_shadow_info (key, &info);
xfree (key);
if (rc)
{
log_error ("get_shadow_info failed: %s\n", gnupg_strerror (rc));
return;
}
infolen = gcry_sexp_canon_len (info, 0, NULL,NULL);
assert (infolen);
if (opt_armor)
{
char *p = make_advanced (info, infolen);
if (!p)
return;
fwrite (p, strlen (p), 1, stdout);
xfree (p);
}
else
fwrite (info, infolen, 1, stdout);
}
int
main (int argc, char **argv )
@ -325,6 +401,8 @@ main (int argc, char **argv )
case oProtect: cmd = oProtect; break;
case oUnprotect: cmd = oUnprotect; break;
case oShadow: cmd = oShadow; break;
case oShowShadowInfo: cmd = oShowShadowInfo; break;
case oPassphrase: passphrase = pargs.r.ret_str; break;
@ -341,6 +419,10 @@ main (int argc, char **argv )
read_and_protect (*argv);
else if (cmd == oUnprotect)
read_and_unprotect (*argv);
else if (cmd == oShadow)
read_and_shadow (*argv);
else if (cmd == oShowShadowInfo)
show_shadow_info (*argv);
else
log_info ("no action requested\n");

View file

@ -780,7 +780,7 @@ agent_unprotect (const unsigned char *protectedkey, const char *passphrase,
PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
PRIVATE_KEY_PROTECTED for an protected private key or
PRIVATE_KEY_SHADOWED for a sub key where the secret parts are store
PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
elsewhere. */
int
agent_private_key_type (const unsigned char *privatekey)
@ -886,3 +886,154 @@ hash_passphrase (const char *passphrase, int hashalgo,
}
/* Create a shadow key from a public key. We use the shadow protocol
"ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
S-expression is returned in an allocated buffer RESULT will point
to. The input parameters are expected to be valid canonilized
S-expressions */
int
agent_shadow_key (const unsigned char *pubkey,
const unsigned char *shadow_info,
unsigned char **result)
{
const unsigned char *s;
const unsigned char *point;
size_t n;
int depth = 0;
unsigned char *p;
size_t pubkey_len = gcry_sexp_canon_len (pubkey, 0, NULL,NULL);
size_t shadow_info_len = gcry_sexp_canon_len (shadow_info, 0, NULL,NULL);
if (!pubkey_len || !shadow_info_len)
return GNUPG_Invalid_Value;
s = pubkey;
if (*s != '(')
return GNUPG_Invalid_Sexp;
depth++;
s++;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
if (!smatch (&s, n, "public-key"))
return GNUPG_Unknown_Sexp;
if (*s != '(')
return GNUPG_Unknown_Sexp;
depth++;
s++;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
s += n; /* skip over the algorithm name */
while (*s != ')')
{
if (*s != '(')
return GNUPG_Invalid_Sexp;
depth++;
s++;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
s += n;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
s +=n; /* skip value */
if (*s != ')')
return GNUPG_Invalid_Sexp;
depth--;
s++;
}
point = s; /* insert right before the point */
depth--;
s++;
assert (depth == 1);
/* calculate required length by taking in account: the "shadowed-"
prefix, the "shadowed", "t1-v1" as well as some parenthesis */
n = 12 + pubkey_len + 1 + 3+8 + 2+5 + shadow_info_len + 1;
*result = p = xtrymalloc (n);
if (!p)
return GNUPG_Out_Of_Core;
p = stpcpy (p, "(20:shadowed-private-key");
/* (10:public-key ...)*/
memcpy (p, pubkey+14, point - (pubkey+14));
p += point - (pubkey+14);
p = stpcpy (p, "(8:shadowed5:t1-v1");
memcpy (p, shadow_info, shadow_info_len);
p += shadow_info_len;
*p++ = ')';
memcpy (p, point, pubkey_len - (point - pubkey));
p += pubkey_len - (point - pubkey);
return 0;
}
/* Parse a canonical encoded shadowed key and return a pointer to the
inner list with the shadow_info */
int
agent_get_shadow_info (const unsigned char *shadowkey,
unsigned char const **shadow_info)
{
const unsigned char *s;
size_t n;
int depth = 0;
s = shadowkey;
if (*s != '(')
return GNUPG_Invalid_Sexp;
depth++;
s++;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
if (!smatch (&s, n, "shadowed-private-key"))
return GNUPG_Unknown_Sexp;
if (*s != '(')
return GNUPG_Unknown_Sexp;
depth++;
s++;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
s += n; /* skip over the algorithm name */
for (;;)
{
if (*s == ')')
return GNUPG_Unknown_Sexp;
if (*s != '(')
return GNUPG_Invalid_Sexp;
depth++;
s++;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
if (smatch (&s, n, "shadowed"))
break;
s += n;
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
s +=n; /* skip value */
if (*s != ')')
return GNUPG_Invalid_Sexp;
depth--;
s++;
}
/* found the shadowed list, s points to the protocol */
n = snext (&s);
if (!n)
return GNUPG_Invalid_Sexp;
if (smatch (&s, n, "t1-v1"))
{
if (*s != '(')
return GNUPG_Invalid_Sexp;
*shadow_info = s;
}
else
return GNUPG_Unsupported_Protocol;
return 0;
}

View file

@ -97,7 +97,7 @@ start_pinentry (void)
rc = assuan_transact (entry_ctx,
opt.no_grab? "OPTION no-grab":"OPTION grab",
NULL, NULL, NULL, NULL);
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
@ -160,14 +160,14 @@ agent_askpin (const char *desc_text, const char *start_err_text,
snprintf (line, DIM(line)-1, "SETDESC %s", desc_text);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
rc = assuan_transact (entry_ctx,
pininfo->min_digits? "SETPROMPT PIN:"
: "SETPROMPT Passphrase:",
NULL, NULL, NULL, NULL);
NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
@ -189,13 +189,13 @@ agent_askpin (const char *desc_text, const char *start_err_text,
snprintf (line, DIM(line)-1, "SETERROR %s (try %d of %d)",
errtext, pininfo->failed_tries+1, pininfo->max_tries);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
errtext = NULL;
}
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL);
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
if (rc == ASSUAN_Too_Much_Data)
errtext = pininfo->min_digits? trans ("PIN too long")
: trans ("Passphrase too long");
@ -248,13 +248,13 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
else
snprintf (line, DIM(line)-1, "RESET");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt? prompt : "Passphrase");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
@ -262,7 +262,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
{
snprintf (line, DIM(line)-1, "SETERROR %s", errtext);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
}
@ -274,7 +274,7 @@ agent_get_passphrase (char **retpass, const char *desc, const char *prompt,
return seterr (Out_Of_Core);
assuan_begin_confidential (entry_ctx);
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL);
rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL);
if (rc)
{
xfree (parm.buffer);
@ -317,7 +317,7 @@ agent_get_confirmation (const char *desc, const char *prompt)
else
snprintf (line, DIM(line)-1, "RESET");
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
@ -325,12 +325,12 @@ agent_get_confirmation (const char *desc, const char *prompt)
{
snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
line[DIM(line)-1] = 0;
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
if (rc)
return map_assuan_err (rc);
}
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL);
rc = assuan_transact (entry_ctx, "CONFIRM", NULL, NULL, NULL, NULL, NULL, NULL);
return map_assuan_err (rc);
}