mirror of
git://git.gnupg.org/gnupg.git
synced 2025-03-05 21:41:06 +01:00
* gpg.sgml: Add bkuptocard command for --edit-key.
* passphrase.c (agent_get_passphrase): Don't call free_public_key if PK is NULL. (passphrase_clear_cache): Ditto. Removed debug output. (passphrase_to_dek): Ditto.
This commit is contained in:
parent
2833a0eadc
commit
bb71180d07
3
NEWS
3
NEWS
@ -47,6 +47,9 @@ Noteworthy changes in version 1.4.1
|
||||
that directory must be stored in the registry at the same key as
|
||||
above with the name "Install Directory".
|
||||
|
||||
* Add new --edit-key command "bkuptocard" to allow restoring a
|
||||
card key from a backup.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.4.0 (2004-12-16)
|
||||
------------------------------------------------
|
||||
|
@ -1,3 +1,7 @@
|
||||
2005-02-15 Werner Koch <wk@g10code.com>
|
||||
|
||||
* gpg.sgml: Add bkuptocard command for --edit-key.
|
||||
|
||||
2005-02-05 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* gpg.sgml: Note that level 0 signatures are always accepted
|
||||
|
14
doc/gpg.sgml
14
doc/gpg.sgml
@ -1,6 +1,6 @@
|
||||
<!-- gpg.sgml - the man page for GnuPG
|
||||
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
2004 Free Software Foundation, Inc.
|
||||
2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GnuPG.
|
||||
|
||||
@ -426,6 +426,18 @@ transferred to the card. A sub menu allows you to select on what card
|
||||
to store the key. Note that it is not possible to get that key back
|
||||
from the card - if the card gets broken your secret key will be lost
|
||||
unless you have a backup somewhere.</para></listitem></varlistentry>
|
||||
<varlistentry>
|
||||
<term>bkuptocard &ParmFile;</term>
|
||||
<listitem><para>
|
||||
Restore the given file to a card. This command
|
||||
may be used to restore a backup key (as generated during card
|
||||
initialization) to a new card. In almost all cases this will be the
|
||||
encryption key. You should use this command only
|
||||
with the corresponding public key and make sure that the file
|
||||
given as argument is indeed the backup to restore. You should
|
||||
then select 2 to restore as encryption key.
|
||||
You will first be asked to enter the passphrase of the backup key and
|
||||
then for the Admin PIN of the card.</para></listitem></varlistentry>
|
||||
<varlistentry>
|
||||
<term>delkey</term>
|
||||
<listitem><para>
|
||||
|
@ -1,3 +1,15 @@
|
||||
2005-02-15 Werner Koch <wk@g10code.com>
|
||||
|
||||
* passphrase.c (agent_get_passphrase): Don't call free_public_key
|
||||
if PK is NULL.
|
||||
(passphrase_clear_cache): Ditto. Removed debug output.
|
||||
(passphrase_to_dek): Ditto.
|
||||
|
||||
2005-02-13 Werner Koch <wk@g10code.com>
|
||||
|
||||
* keyedit.c (cmds): Limit code to 80 columns. Add command
|
||||
BKUPTOCARD.
|
||||
|
||||
2005-02-09 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* encr-data.c (decrypt_data): Use it here to turn off the "quick
|
||||
@ -7,6 +19,11 @@
|
||||
* mainproc.c (proc_symkey_enc): Set a flag to indicate that a
|
||||
particular session key came from a passphrase and not a PK.
|
||||
|
||||
2005-02-08 Werner Koch <wk@g10code.com>
|
||||
|
||||
* misc.c (w32_shgetfolderpath): New.
|
||||
(default_homedir): Use it to avoid problems under Windows95.
|
||||
|
||||
2005-02-06 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* trustdb.h, trustdb.c (trustdb_check_or_update): New. If the
|
||||
|
@ -1122,9 +1122,10 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
|
||||
}
|
||||
|
||||
|
||||
/* Store the subkey at NODE into the smartcard and modify NODE to
|
||||
carry the serrialno stuff instead of the actual secret key
|
||||
parameters. */
|
||||
/* Store the key at NODE into the smartcard and modify NODE to
|
||||
carry the serialno stuff instead of the actual secret key
|
||||
parameters. USE is the usage for that key; 0 means any
|
||||
usage. */
|
||||
int
|
||||
card_store_subkey (KBNODE node, int use)
|
||||
{
|
||||
|
146
g10/keyedit.c
146
g10/keyedit.c
@ -1303,7 +1303,7 @@ enum cmdids
|
||||
cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
|
||||
cmdEXPIRE, cmdENABLEKEY, cmdDISABLEKEY, cmdSHOWPREF, cmdSETPREF,
|
||||
cmdPREFKS, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST, cmdCHKTRUST,
|
||||
cmdADDCARDKEY, cmdKEYTOCARD, cmdNOP
|
||||
cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdNOP
|
||||
};
|
||||
|
||||
static struct
|
||||
@ -1326,47 +1326,79 @@ static struct
|
||||
{ "key" , cmdSELKEY , 0, N_("select subkey N") },
|
||||
{ "check" , cmdCHECK , 0, N_("check signatures") },
|
||||
{ "c" , cmdCHECK , 0, NULL },
|
||||
{ "sign" , cmdSIGN , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH, N_("sign selected user IDs [* see below for related commands]") },
|
||||
{ "sign" , cmdSIGN , KEYEDIT_NOT_SK|KEYEDIT_TAIL_MATCH,
|
||||
N_("sign selected user IDs [* see below for related commands]") },
|
||||
{ "s" , cmdSIGN , KEYEDIT_NOT_SK, NULL },
|
||||
/* "lsign" and friends will never match since "sign" comes first
|
||||
and it is a tail match. They are just here so they show up in
|
||||
the help menu. */
|
||||
{ "lsign" , cmdNOP , 0, N_("sign selected user IDs locally") },
|
||||
{ "tsign" , cmdNOP , 0, N_("sign selected user IDs with a trust signature") },
|
||||
{ "nrsign" , cmdNOP , 0, N_("sign selected user IDs with a non-revocable signature") },
|
||||
{ "tsign" , cmdNOP , 0,
|
||||
N_("sign selected user IDs with a trust signature") },
|
||||
{ "nrsign" , cmdNOP , 0,
|
||||
N_("sign selected user IDs with a non-revocable signature") },
|
||||
|
||||
{ "debug" , cmdDEBUG , 0, NULL },
|
||||
{ "adduid" , cmdADDUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a user ID") },
|
||||
{ "addphoto", cmdADDPHOTO , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a photo ID") },
|
||||
{ "deluid" , cmdDELUID , KEYEDIT_NOT_SK, N_("delete selected user IDs") },
|
||||
{ "adduid" , cmdADDUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("add a user ID") },
|
||||
{ "addphoto", cmdADDPHOTO , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("add a photo ID") },
|
||||
{ "deluid" , cmdDELUID , KEYEDIT_NOT_SK,
|
||||
N_("delete selected user IDs") },
|
||||
/* delphoto is really deluid in disguise */
|
||||
{ "delphoto", cmdDELUID , KEYEDIT_NOT_SK, NULL },
|
||||
{ "addkey" , cmdADDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a subkey") },
|
||||
|
||||
{ "addkey" , cmdADDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("add a subkey") },
|
||||
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
{ "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a key to a smartcard") },
|
||||
{ "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK, N_("move a key to a smartcard")},
|
||||
{ "addcardkey", cmdADDCARDKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("add a key to a smartcard") },
|
||||
{ "keytocard", cmdKEYTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK,
|
||||
N_("move a key to a smartcard")},
|
||||
{ "bkuptocard", cmdBKUPTOCARD , KEYEDIT_NEED_SK|KEYEDIT_ONLY_SK,
|
||||
N_("move a backup key to a smartcard")},
|
||||
#endif /*ENABLE_CARD_SUPPORT*/
|
||||
{ "delkey" , cmdDELKEY , KEYEDIT_NOT_SK, N_("delete selected subkeys") },
|
||||
{ "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("add a revocation key") },
|
||||
{ "delsig" , cmdDELSIG , KEYEDIT_NOT_SK, N_("delete signatures from the selected user IDs") },
|
||||
{ "expire" , cmdEXPIRE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the expiration date for the key or selected subkeys") },
|
||||
{ "primary" , cmdPRIMARY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("flag the selected user ID as primary")},
|
||||
{ "toggle" , cmdTOGGLE , KEYEDIT_NEED_SK, N_("toggle between the secret and public key listings") },
|
||||
|
||||
{ "delkey" , cmdDELKEY , KEYEDIT_NOT_SK,
|
||||
N_("delete selected subkeys") },
|
||||
{ "addrevoker",cmdADDREVOKER,KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("add a revocation key") },
|
||||
{ "delsig" , cmdDELSIG , KEYEDIT_NOT_SK,
|
||||
N_("delete signatures from the selected user IDs") },
|
||||
{ "expire" , cmdEXPIRE , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("change the expiration date for the key or selected subkeys") },
|
||||
{ "primary" , cmdPRIMARY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("flag the selected user ID as primary")},
|
||||
{ "toggle" , cmdTOGGLE , KEYEDIT_NEED_SK,
|
||||
N_("toggle between the secret and public key listings") },
|
||||
{ "t" , cmdTOGGLE , KEYEDIT_NEED_SK, NULL },
|
||||
{ "pref" , cmdPREF , KEYEDIT_NOT_SK, N_("list preferences (expert)")},
|
||||
{ "showpref", cmdSHOWPREF , KEYEDIT_NOT_SK, N_("list preferences (verbose)") },
|
||||
{ "setpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preference list for the selected user IDs") },
|
||||
{ "pref" , cmdPREF , KEYEDIT_NOT_SK,
|
||||
N_("list preferences (expert)")},
|
||||
{ "showpref", cmdSHOWPREF , KEYEDIT_NOT_SK,
|
||||
N_("list preferences (verbose)") },
|
||||
{ "setpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("set preference list for the selected user IDs") },
|
||||
/* Alias */
|
||||
{ "updpref" , cmdSETPREF , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
|
||||
{ "keyserver",cmdPREFKS , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("set preferred keyserver URL for the selected user IDs")},
|
||||
{ "passwd" , cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("change the passphrase") },
|
||||
|
||||
{ "keyserver",cmdPREFKS , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("set preferred keyserver URL for the selected user IDs")},
|
||||
{ "passwd" , cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("change the passphrase") },
|
||||
/* Alias */
|
||||
{ "password", cmdPASSWD , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
|
||||
|
||||
{ "trust" , cmdTRUST , KEYEDIT_NOT_SK, N_("change the ownertrust") },
|
||||
{ "revsig" , cmdREVSIG , KEYEDIT_NOT_SK, N_("revoke signatures on the selected user IDs") },
|
||||
{ "revuid" , cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke selected user IDs") },
|
||||
{ "revsig" , cmdREVSIG , KEYEDIT_NOT_SK,
|
||||
N_("revoke signatures on the selected user IDs") },
|
||||
{ "revuid" , cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("revoke selected user IDs") },
|
||||
/* Alias */
|
||||
{ "revphoto", cmdREVUID , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, NULL },
|
||||
{ "revkey" , cmdREVKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK, N_("revoke key or selected subkeys") },
|
||||
|
||||
{ "revkey" , cmdREVKEY , KEYEDIT_NOT_SK|KEYEDIT_NEED_SK,
|
||||
N_("revoke key or selected subkeys") },
|
||||
{ "enable" , cmdENABLEKEY , KEYEDIT_NOT_SK, N_("enable key") },
|
||||
{ "disable" , cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key") },
|
||||
{ "showphoto",cmdSHOWPHOTO , 0, N_("show selected photo IDs") },
|
||||
@ -1550,7 +1582,8 @@ keyedit_menu( const char *username, STRLIST locusr,
|
||||
|
||||
tty_printf("\n");
|
||||
tty_printf(_(
|
||||
"* The `sign' command may be prefixed with an `l' for local signatures (lsign),\n"
|
||||
"* The `sign' command may be prefixed with an `l' for local "
|
||||
"signatures (lsign),\n"
|
||||
" a `t' for trust signatures (tsign), an `nr' for non-revocable signatures\n"
|
||||
" (nrsign), or any combination thereof (ltsign, tnrsign, etc.).\n"));
|
||||
|
||||
@ -1744,6 +1777,69 @@ keyedit_menu( const char *username, STRLIST locusr,
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case cmdBKUPTOCARD:
|
||||
{
|
||||
/* Ask for a filename, check whether this is really a
|
||||
backup key as generated by the card generation, parse
|
||||
that key and store it on card. */
|
||||
KBNODE node;
|
||||
const char *fname;
|
||||
PACKET *pkt;
|
||||
IOBUF a;
|
||||
|
||||
fname = arg_string;
|
||||
if (!*fname)
|
||||
{
|
||||
tty_printf (_("Command expects a filename argument\n"));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Open that file. */
|
||||
a = iobuf_open (fname);
|
||||
if (a && is_secured_file (iobuf_get_fd (a)))
|
||||
{
|
||||
iobuf_close (a);
|
||||
a = NULL;
|
||||
errno = EPERM;
|
||||
}
|
||||
if (!a)
|
||||
{
|
||||
tty_printf (_("Can't open `%s': %s\n"),
|
||||
fname, strerror(errno));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Parse and check that file. */
|
||||
pkt = xmalloc (sizeof *pkt);
|
||||
init_packet (pkt);
|
||||
rc = parse_packet (a, pkt);
|
||||
iobuf_close (a);
|
||||
iobuf_ioctl (NULL, 2, 0, (char*)fname); /* (invalidate cache). */
|
||||
if (!rc
|
||||
&& pkt->pkttype != PKT_SECRET_KEY
|
||||
&& pkt->pkttype != PKT_SECRET_SUBKEY)
|
||||
rc = G10ERR_NO_SECKEY;
|
||||
if (rc)
|
||||
{
|
||||
tty_printf(_("Error reading backup key from `%s': %s\n"),
|
||||
fname, g10_errstr (rc));
|
||||
free_packet (pkt);
|
||||
xfree (pkt);
|
||||
break;
|
||||
}
|
||||
node = new_kbnode (pkt);
|
||||
|
||||
/* Store it. */
|
||||
if (card_store_subkey (node, 0))
|
||||
{
|
||||
redisplay = 1;
|
||||
sec_modified = 1;
|
||||
}
|
||||
release_kbnode (node);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /* ENABLE_CARD_SUPPORT */
|
||||
|
||||
case cmdDELKEY: {
|
||||
|
@ -1636,7 +1636,8 @@ ask_user_id( int mode )
|
||||
|
||||
if( !mode )
|
||||
tty_printf( _("\n"
|
||||
"You need a user ID to identify your key; the software constructs the user ID\n"
|
||||
"You need a user ID to identify your key; "
|
||||
"the software constructs the user ID\n"
|
||||
"from the Real Name, Comment and Email Address in this form:\n"
|
||||
" \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n") );
|
||||
uid = aname = acomment = amail = NULL;
|
||||
@ -1731,7 +1732,7 @@ ask_user_id( int mode )
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
/* Note to translators: These are the allowed answers in
|
||||
/* TRANSLATORS: These are the allowed answers in
|
||||
lower and uppercase. Below you will find the matching
|
||||
string which should be translated accordingly and the
|
||||
letter changed to match the one in the answer string.
|
||||
|
44
g10/misc.c
44
g10/misc.c
@ -51,6 +51,8 @@
|
||||
#ifndef CSIDL_FLAG_CREATE
|
||||
#define CSIDL_FLAG_CREATE 0x8000
|
||||
#endif
|
||||
#include "errors.h"
|
||||
#include "dynload.h"
|
||||
#endif /*_WIN32*/
|
||||
|
||||
#include "util.h"
|
||||
@ -1018,6 +1020,46 @@ parse_options(char *str,unsigned int *options,
|
||||
}
|
||||
|
||||
|
||||
/* This is a helper function to load a Windows function from either of
|
||||
one DLLs. */
|
||||
#ifdef HAVE_W32_SYSTEM
|
||||
static HRESULT
|
||||
w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e)
|
||||
{
|
||||
static int initialized;
|
||||
static HRESULT (* WINAPI func)(HWND,int,HANDLE,DWORD,LPSTR);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
static char *dllnames[] = { "shell32.dll", "shfolder.dll", NULL };
|
||||
void *handle;
|
||||
int i;
|
||||
|
||||
initialized = 1;
|
||||
|
||||
for (i=0, handle = NULL; !handle && dllnames[i]; i++)
|
||||
{
|
||||
handle = dlopen (dllnames[i], RTLD_LAZY);
|
||||
if (handle)
|
||||
{
|
||||
func = dlsym (handle, "SHGetFolderPathA");
|
||||
if (!func)
|
||||
{
|
||||
dlclose (handle);
|
||||
handle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (func)
|
||||
return func (a,b,c,d,e);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
#endif /*HAVE_W32_SYSTEM*/
|
||||
|
||||
|
||||
/* Set up the default home directory. The usual --homedir option
|
||||
should be parsed later. */
|
||||
char *
|
||||
@ -1040,7 +1082,7 @@ default_homedir (void)
|
||||
using a system roaming serives might be better than to let
|
||||
them do it manually. A security conscious user will anyway
|
||||
use the registry entry to have better control. */
|
||||
if (SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
|
||||
if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE,
|
||||
NULL, 0, path) >= 0)
|
||||
{
|
||||
char *tmp = xmalloc (strlen (path) + 6 +1);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* passphrase.c - Get a passphrase
|
||||
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
|
||||
* 2004 Free Software Foundation, Inc.
|
||||
* 2004, 2005 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -661,6 +661,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
memset (fpr, 0, MAX_FINGERPRINT_LEN );
|
||||
if( keyid && get_pubkey( pk, keyid ) )
|
||||
{
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
pk = NULL; /* oops: no key for some reason */
|
||||
}
|
||||
@ -795,6 +796,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
}
|
||||
pw[pwlen] = 0; /* make a C String */
|
||||
agent_close (fd);
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
#ifdef ENABLE_NLS
|
||||
if (orig_codeset)
|
||||
@ -912,6 +914,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
pw[pwlen++] = xtoi_2 (pw+i);
|
||||
pw[pwlen] = 0; /* make a C String */
|
||||
agent_close (fd);
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
#ifdef ENABLE_NLS
|
||||
if (orig_codeset)
|
||||
@ -946,6 +949,7 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
|
||||
if ( fd != -1 )
|
||||
agent_close (fd);
|
||||
m_free (pw );
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
|
||||
return NULL;
|
||||
@ -981,7 +985,6 @@ passphrase_clear_cache ( u32 *keyid, int algo )
|
||||
memset (fpr, 0, MAX_FINGERPRINT_LEN );
|
||||
if( !keyid || get_pubkey( pk, keyid ) )
|
||||
{
|
||||
log_debug ("oops, no key in passphrase_clear_cache\n");
|
||||
goto failure; /* oops: no key for some reason */
|
||||
}
|
||||
|
||||
@ -1051,6 +1054,7 @@ passphrase_clear_cache ( u32 *keyid, int algo )
|
||||
failure:
|
||||
if (fd != -1)
|
||||
agent_close (fd);
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
#endif /* Posix or W32 */
|
||||
}
|
||||
@ -1208,6 +1212,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
|
||||
}
|
||||
|
||||
tty_printf("\n");
|
||||
if (pk)
|
||||
free_public_key( pk );
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user